summaryrefslogtreecommitdiff
path: root/browser/devtools/webconsole/test
diff options
context:
space:
mode:
Diffstat (limited to 'browser/devtools/webconsole/test')
-rw-r--r--browser/devtools/webconsole/test/Makefile.in245
-rw-r--r--browser/devtools/webconsole/test/browser_bug664688_sandbox_update_after_navigation.js113
-rw-r--r--browser/devtools/webconsole/test/browser_bug_638949_copy_link_location.js107
-rw-r--r--browser/devtools/webconsole/test/browser_bug_862916_console_dir_and_filter_off.js34
-rw-r--r--browser/devtools/webconsole/test/browser_bug_865288_repeat_different_objects.js82
-rw-r--r--browser/devtools/webconsole/test/browser_bug_865871_variables_view_close_on_esc_key.js98
-rw-r--r--browser/devtools/webconsole/test/browser_bug_869003_inspect_cross_domain_object.js94
-rw-r--r--browser/devtools/webconsole/test/browser_bug_871156_ctrlw_close_tab.js66
-rw-r--r--browser/devtools/webconsole/test/browser_cached_messages.js76
-rw-r--r--browser/devtools/webconsole/test/browser_console.js102
-rw-r--r--browser/devtools/webconsole/test/browser_console_addonsdk_loader_exception.js93
-rw-r--r--browser/devtools/webconsole/test/browser_console_clear_on_reload.js73
-rw-r--r--browser/devtools/webconsole/test/browser_console_consolejsm_output.js135
-rw-r--r--browser/devtools/webconsole/test/browser_console_dead_objects.js79
-rw-r--r--browser/devtools/webconsole/test/browser_console_error_source_click.js75
-rw-r--r--browser/devtools/webconsole/test/browser_console_filters.js71
-rw-r--r--browser/devtools/webconsole/test/browser_console_keyboard_accessibility.js69
-rw-r--r--browser/devtools/webconsole/test/browser_console_log_inspectable_object.js58
-rw-r--r--browser/devtools/webconsole/test/browser_console_native_getters.js121
-rw-r--r--browser/devtools/webconsole/test/browser_console_nsiconsolemessage.js95
-rw-r--r--browser/devtools/webconsole/test/browser_console_private_browsing.js199
-rw-r--r--browser/devtools/webconsole/test/browser_console_variables_view.js177
-rw-r--r--browser/devtools/webconsole/test/browser_console_variables_view_while_debugging.js132
-rw-r--r--browser/devtools/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js127
-rw-r--r--browser/devtools/webconsole/test/browser_eval_in_debugger_stackframe.js150
-rw-r--r--browser/devtools/webconsole/test/browser_jsterm_inspect.js35
-rw-r--r--browser/devtools/webconsole/test/browser_longstring_hang.js73
-rw-r--r--browser/devtools/webconsole/test/browser_netpanel_longstring_expand.js309
-rw-r--r--browser/devtools/webconsole/test/browser_output_breaks_after_console_dir_uninspectable.js56
-rw-r--r--browser/devtools/webconsole/test/browser_output_longstring_expand.js153
-rw-r--r--browser/devtools/webconsole/test/browser_repeated_messages_accuracy.js120
-rw-r--r--browser/devtools/webconsole/test/browser_result_format_as_string.js49
-rw-r--r--browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js79
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_abbreviate_source_url.js21
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_basic_net_logging.js45
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_578437_page_reload.js38
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_579412_input_focus.js25
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_580001_closing_after_completion.js44
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js67
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js78
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_580454_timestamp_l10n.js36
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js68
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js35
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js109
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js50
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js283
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js95
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js81
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js91
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_588342_document_focus.js39
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js49
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_588967_input_expansion.js44
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_589162_css_filter.js62
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_592442_closing_brackets.js41
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js75
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_594477_clickable_output.js132
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_594497_history_arrow_keys.js157
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_595223_file_uri.js54
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js101
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js209
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js106
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js43
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_597136_network_requests_from_chrome.js47
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js81
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js63
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js275
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js76
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js53
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_601177_log_levels.js82
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js75
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_601667_filter_buttons.js146
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js182
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js39
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_611795.js93
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_613013_console_api_iframe.js52
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_613280_jsterm_copy.js85
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js104
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js101
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js68
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_618078_network_exceptions.js70
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_618311_close_panels.js89
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_621644_jsterm_dollar.js68
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_622303_persistent_filters.js123
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_623749_ctrl_a_select_all_winnt.js32
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_626484_output_copy_order.js70
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js129
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_632275_getters_document_width.js44
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js88
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_632817.js196
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_642108_pruneTest.js89
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js102
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js217
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_646025_console_file_location.js56
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js106
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js144
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_658368_time_methods.js103
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_659907_console_dir.js29
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_660806_history_nav.js48
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_664131_console_group.js133
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_704295.js42
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_734061_No_input_change_and_Tab_key_pressed.js39
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js96
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_764572_output_open_url.js119
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js113
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_770099_bad_policyuri.js55
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js46
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js150
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_804845_ctrl_key_nav.js214
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_817834_add_edited_input_to_history.js61
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_821877_csp_errors.js28
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_bug_837351_securityerrors.js34
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_change_font_size.js44
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_chrome.js35
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_completion.js120
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_console_extras.js39
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_console_logging_api.js146
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_copying_multiple_messages_inserts_newlines_in_between.js67
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_execution_scope.js45
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_for_of.js35
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_history.js66
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_js_input_and_output_styling.js48
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_js_input_expansion.js60
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_jsterm.js194
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_live_filtering_of_message_types.js66
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_live_filtering_on_search_strings.js106
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_log_node_classes.js71
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_message_node_id.js29
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_netlogging.js211
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_network_panel.js543
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_notifications.js70
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_null_and_undefined_output.js62
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_output_order.js44
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_property_provider.js42
-rw-r--r--browser/devtools/webconsole/test/browser_webconsole_view_source.js66
-rw-r--r--browser/devtools/webconsole/test/head.js1247
-rw-r--r--browser/devtools/webconsole/test/moz.build6
-rw-r--r--browser/devtools/webconsole/test/test-bug-585956-console-trace.html27
-rw-r--r--browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud-iframe.html13
-rw-r--r--browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud.html14
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-canvas-css.html17
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-canvas-css.js10
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-canvas.html15
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-canvas.js11
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-css-loader.css10
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-css-loader.css^headers^1
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-css-loader.html13
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-css-parser.css10
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-css-parser.html14
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.html16
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.js8
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-html.html16
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-image.html15
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-image.jpgbin0 -> 2532 bytes
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-imagemap.html17
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.html19
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.xml8
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-malformedxml.xhtml10
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-svg.xhtml17
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-workers.html18
-rw-r--r--browser/devtools/webconsole/test/test-bug-595934-workers.js9
-rw-r--r--browser/devtools/webconsole/test/test-bug-597136-external-script-errors.html25
-rw-r--r--browser/devtools/webconsole/test/test-bug-597136-external-script-errors.js14
-rw-r--r--browser/devtools/webconsole/test/test-bug-597756-reopen-closed-tab.html18
-rw-r--r--browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs25
-rw-r--r--browser/devtools/webconsole/test/test-bug-600183-charset.html9
-rw-r--r--browser/devtools/webconsole/test/test-bug-600183-charset.html^headers^1
-rw-r--r--browser/devtools/webconsole/test/test-bug-601177-log-levels.html20
-rw-r--r--browser/devtools/webconsole/test/test-bug-601177-log-levels.js8
-rw-r--r--browser/devtools/webconsole/test/test-bug-603750-websocket.html14
-rw-r--r--browser/devtools/webconsole/test/test-bug-603750-websocket.js18
-rw-r--r--browser/devtools/webconsole/test/test-bug-613013-console-api-iframe.html21
-rw-r--r--browser/devtools/webconsole/test/test-bug-618078-network-exceptions.html24
-rw-r--r--browser/devtools/webconsole/test/test-bug-621644-jsterm-dollar.html23
-rw-r--r--browser/devtools/webconsole/test/test-bug-630733-response-redirect-headers.sjs16
-rw-r--r--browser/devtools/webconsole/test/test-bug-632275-getters.html20
-rw-r--r--browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html54
-rw-r--r--browser/devtools/webconsole/test/test-bug-644419-log-limits.html21
-rw-r--r--browser/devtools/webconsole/test/test-bug-646025-console-file-location.html12
-rw-r--r--browser/devtools/webconsole/test/test-bug-658368-time-methods.html24
-rw-r--r--browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html15
-rw-r--r--browser/devtools/webconsole/test/test-bug-766001-console-log.js8
-rw-r--r--browser/devtools/webconsole/test/test-bug-766001-js-console-links.html14
-rw-r--r--browser/devtools/webconsole/test/test-bug-766001-js-errors.js7
-rw-r--r--browser/devtools/webconsole/test/test-bug-782653-css-errors-1.css10
-rw-r--r--browser/devtools/webconsole/test/test-bug-782653-css-errors-2.css10
-rw-r--r--browser/devtools/webconsole/test/test-bug-782653-css-errors.html14
-rw-r--r--browser/devtools/webconsole/test/test-bug-821877-csperrors.html12
-rw-r--r--browser/devtools/webconsole/test/test-bug-821877-csperrors.html^headers^1
-rw-r--r--browser/devtools/webconsole/test/test-bug-837351-security-errors.html15
-rw-r--r--browser/devtools/webconsole/test/test-bug-859170-longstring-hang.html23
-rw-r--r--browser/devtools/webconsole/test/test-bug-869003-iframe.html20
-rw-r--r--browser/devtools/webconsole/test/test-bug-869003-top-window.html14
-rw-r--r--browser/devtools/webconsole/test/test-console-extras.html25
-rw-r--r--browser/devtools/webconsole/test/test-console-replaced-api.html12
-rw-r--r--browser/devtools/webconsole/test/test-console.html23
-rw-r--r--browser/devtools/webconsole/test/test-data.json1
-rw-r--r--browser/devtools/webconsole/test/test-data.json^headers^1
-rw-r--r--browser/devtools/webconsole/test/test-duplicate-error.html21
-rw-r--r--browser/devtools/webconsole/test/test-encoding-ISO-8859-1.html7
-rw-r--r--browser/devtools/webconsole/test/test-error.html21
-rw-r--r--browser/devtools/webconsole/test/test-eval-in-stackframe.html39
-rw-r--r--browser/devtools/webconsole/test/test-file-location.js9
-rw-r--r--browser/devtools/webconsole/test/test-filter.html11
-rw-r--r--browser/devtools/webconsole/test/test-for-of.html8
-rw-r--r--browser/devtools/webconsole/test/test-image.pngbin0 -> 580 bytes
-rw-r--r--browser/devtools/webconsole/test/test-mutation.html16
-rw-r--r--browser/devtools/webconsole/test/test-network-request.html36
-rw-r--r--browser/devtools/webconsole/test/test-network.html11
-rw-r--r--browser/devtools/webconsole/test/test-observe-http-ajax.html17
-rw-r--r--browser/devtools/webconsole/test/test-own-console.html24
-rw-r--r--browser/devtools/webconsole/test/test-property-provider.html14
-rw-r--r--browser/devtools/webconsole/test/test-repeated-messages.html35
-rw-r--r--browser/devtools/webconsole/test/test-result-format-as-string.html24
-rw-r--r--browser/devtools/webconsole/test/test-webconsole-error-observer.html25
-rw-r--r--browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html12
-rw-r--r--browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html^headers^2
-rw-r--r--browser/devtools/webconsole/test/test_bug_770099_violation.html13
-rw-r--r--browser/devtools/webconsole/test/test_bug_770099_violation.html^headers^1
-rw-r--r--browser/devtools/webconsole/test/testscript.js1
219 files changed, 15087 insertions, 0 deletions
diff --git a/browser/devtools/webconsole/test/Makefile.in b/browser/devtools/webconsole/test/Makefile.in
new file mode 100644
index 000000000..f4a8ca682
--- /dev/null
+++ b/browser/devtools/webconsole/test/Makefile.in
@@ -0,0 +1,245 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH = @DEPTH@
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+relativesrcdir = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_BROWSER_FILES = \
+ browser_webconsole_notifications.js \
+ browser_webconsole_message_node_id.js \
+ browser_webconsole_bug_580030_errors_after_page_reload.js \
+ browser_webconsole_basic_net_logging.js \
+ browser_webconsole_bug_579412_input_focus.js \
+ browser_webconsole_bug_580001_closing_after_completion.js \
+ browser_webconsole_bug_580400_groups.js \
+ browser_webconsole_bug_588730_text_node_insertion.js \
+ browser_webconsole_bug_601667_filter_buttons.js \
+ browser_webconsole_bug_597136_external_script_errors.js \
+ browser_webconsole_bug_597136_network_requests_from_chrome.js \
+ browser_webconsole_completion.js \
+ browser_webconsole_console_logging_api.js \
+ browser_webconsole_change_font_size.js \
+ browser_webconsole_chrome.js \
+ browser_webconsole_execution_scope.js \
+ browser_webconsole_for_of.js \
+ browser_webconsole_history.js \
+ browser_webconsole_js_input_and_output_styling.js \
+ browser_webconsole_js_input_expansion.js \
+ browser_webconsole_live_filtering_of_message_types.js \
+ browser_webconsole_live_filtering_on_search_strings.js \
+ browser_warn_user_about_replaced_api.js \
+ browser_webconsole_copying_multiple_messages_inserts_newlines_in_between.js \
+ browser_webconsole_bug_586388_select_all.js \
+ browser_webconsole_bug_588967_input_expansion.js \
+ browser_webconsole_log_node_classes.js \
+ browser_webconsole_network_panel.js \
+ browser_webconsole_jsterm.js \
+ browser_webconsole_null_and_undefined_output.js \
+ browser_webconsole_output_order.js \
+ browser_webconsole_property_provider.js \
+ browser_webconsole_bug_587617_output_copy.js \
+ browser_webconsole_bug_585237_line_limit.js \
+ browser_webconsole_bug_582201_duplicate_errors.js \
+ browser_webconsole_bug_580454_timestamp_l10n.js \
+ browser_webconsole_netlogging.js \
+ browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js \
+ browser_webconsole_bug_734061_No_input_change_and_Tab_key_pressed.js \
+ browser_webconsole_bug_594477_clickable_output.js \
+ browser_webconsole_bug_589162_css_filter.js \
+ browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js \
+ browser_webconsole_bug_595350_multiple_windows_and_tabs.js \
+ browser_webconsole_bug_594497_history_arrow_keys.js \
+ browser_webconsole_bug_588342_document_focus.js \
+ browser_webconsole_bug_595934_message_categories.js \
+ browser_webconsole_bug_601352_scroll.js \
+ browser_webconsole_bug_592442_closing_brackets.js \
+ browser_webconsole_bug_593003_iframe_wrong_hud.js \
+ browser_webconsole_bug_613013_console_api_iframe.js \
+ browser_webconsole_bug_597756_reopen_closed_tab.js \
+ browser_webconsole_bug_600183_charset.js \
+ browser_webconsole_bug_601177_log_levels.js \
+ browser_webconsole_bug_597460_filter_scroll.js \
+ browser_webconsole_console_extras.js \
+ browser_webconsole_bug_598357_jsterm_output.js \
+ browser_webconsole_bug_603750_websocket.js \
+ browser_webconsole_abbreviate_source_url.js \
+ browser_webconsole_view_source.js \
+ browser_webconsole_bug_602572_log_bodies_checkbox.js \
+ browser_webconsole_bug_614793_jsterm_scroll.js \
+ browser_webconsole_bug_599725_response_headers.js \
+ browser_webconsole_bug_613642_maintain_scroll.js \
+ browser_webconsole_bug_613642_prune_scroll.js \
+ browser_webconsole_bug_618078_network_exceptions.js \
+ browser_webconsole_bug_613280_jsterm_copy.js \
+ browser_webconsole_bug_630733_response_redirect_headers.js \
+ browser_webconsole_bug_621644_jsterm_dollar.js \
+ browser_webconsole_bug_632817.js \
+ browser_webconsole_bug_611795.js \
+ browser_webconsole_bug_618311_close_panels.js \
+ browser_webconsole_bug_626484_output_copy_order.js \
+ browser_webconsole_bug_632347_iterators_generators.js \
+ browser_webconsole_bug_642108_pruneTest.js \
+ browser_webconsole_bug_585956_console_trace.js \
+ browser_webconsole_bug_595223_file_uri.js \
+ browser_webconsole_bug_632275_getters_document_width.js \
+ browser_webconsole_bug_644419_log_limits.js \
+ browser_webconsole_bug_646025_console_file_location.js \
+ browser_webconsole_bug_642615_autocomplete.js \
+ browser_webconsole_bug_585991_autocomplete_popup.js \
+ browser_webconsole_bug_585991_autocomplete_keys.js \
+ browser_webconsole_bug_660806_history_nav.js \
+ browser_webconsole_bug_651501_document_body_autocomplete.js \
+ browser_webconsole_bug_653531_highlighter_console_helper.js \
+ browser_webconsole_bug_659907_console_dir.js \
+ browser_webconsole_bug_664131_console_group.js \
+ browser_webconsole_bug_704295.js \
+ browser_webconsole_bug_658368_time_methods.js \
+ browser_webconsole_bug_764572_output_open_url.js \
+ browser_webconsole_bug_622303_persistent_filters.js \
+ browser_webconsole_bug_770099_bad_policyuri.js \
+ browser_webconsole_bug_770099_violation.js \
+ browser_webconsole_bug_766001_JS_Console_in_Debugger.js \
+ browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js \
+ browser_cached_messages.js \
+ browser_bug664688_sandbox_update_after_navigation.js \
+ browser_result_format_as_string.js \
+ browser_webconsole_bug_737873_mixedcontent.js \
+ browser_output_breaks_after_console_dir_uninspectable.js \
+ browser_console_log_inspectable_object.js \
+ browser_bug_638949_copy_link_location.js \
+ browser_output_longstring_expand.js \
+ browser_netpanel_longstring_expand.js \
+ browser_repeated_messages_accuracy.js \
+ browser_webconsole_bug_821877_csp_errors.js \
+ browser_eval_in_debugger_stackframe.js \
+ browser_console_variables_view.js \
+ browser_console_variables_view_while_debugging.js \
+ browser_console.js \
+ browser_longstring_hang.js \
+ browser_console_consolejsm_output.js \
+ browser_webconsole_bug_837351_securityerrors.js \
+ browser_bug_865871_variables_view_close_on_esc_key.js \
+ browser_bug_865288_repeat_different_objects.js \
+ browser_jsterm_inspect.js \
+ browser_bug_869003_inspect_cross_domain_object.js \
+ browser_bug_862916_console_dir_and_filter_off.js \
+ browser_console_native_getters.js \
+ browser_bug_871156_ctrlw_close_tab.js \
+ browser_console_private_browsing.js \
+ browser_console_nsiconsolemessage.js \
+ browser_webconsole_bug_817834_add_edited_input_to_history.js \
+ browser_console_addonsdk_loader_exception.js \
+ browser_console_error_source_click.js \
+ browser_console_clear_on_reload.js \
+ browser_console_keyboard_accessibility.js \
+ browser_console_filters.js \
+ browser_console_dead_objects.js \
+ browser_console_variables_view_while_debugging_and_inspecting.js \
+ head.js \
+ $(NULL)
+
+ifeq ($(OS_ARCH), Darwin)
+MOCHITEST_BROWSER_FILES += \
+ browser_webconsole_bug_804845_ctrl_key_nav.js \
+ $(NULL)
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+MOCHITEST_BROWSER_FILES += \
+ browser_webconsole_bug_623749_ctrl_a_select_all_winnt.js \
+ $(NULL)
+endif
+
+MOCHITEST_BROWSER_FILES += \
+ test-console.html \
+ test-network.html \
+ test-network-request.html \
+ test-mutation.html \
+ testscript.js \
+ test-filter.html \
+ test-observe-http-ajax.html \
+ test-data.json \
+ test-data.json^headers^ \
+ test-property-provider.html \
+ test-error.html \
+ test-duplicate-error.html \
+ test-image.png \
+ test-encoding-ISO-8859-1.html \
+ test-bug-593003-iframe-wrong-hud.html \
+ test-bug-593003-iframe-wrong-hud-iframe.html \
+ test-console-replaced-api.html \
+ test-own-console.html \
+ test-bug-595934-css-loader.html \
+ test-bug-595934-css-loader.css \
+ test-bug-595934-css-loader.css^headers^ \
+ test-bug-595934-imagemap.html \
+ test-bug-595934-html.html \
+ test-bug-595934-malformedxml.xhtml \
+ test-bug-595934-svg.xhtml \
+ test-bug-595934-workers.html \
+ test-bug-595934-workers.js \
+ test-bug-595934-canvas.html \
+ test-bug-595934-canvas.js \
+ test-bug-595934-css-parser.html \
+ test-bug-595934-css-parser.css \
+ test-bug-595934-canvas-css.html \
+ test-bug-595934-canvas-css.js \
+ test-bug-595934-malformedxml-external.html \
+ test-bug-595934-malformedxml-external.xml \
+ test-bug-595934-empty-getelementbyid.html \
+ test-bug-595934-empty-getelementbyid.js \
+ test-bug-595934-image.html \
+ test-bug-595934-image.jpg \
+ test-bug-597136-external-script-errors.html \
+ test-bug-597136-external-script-errors.js \
+ test-bug-613013-console-api-iframe.html \
+ test-bug-597756-reopen-closed-tab.html \
+ test-bug-600183-charset.html \
+ test-bug-600183-charset.html^headers^ \
+ test-bug-601177-log-levels.html \
+ test-bug-601177-log-levels.js \
+ test-console-extras.html \
+ test-bug-603750-websocket.html \
+ test-bug-603750-websocket.js \
+ test-bug-599725-response-headers.sjs \
+ test-bug-618078-network-exceptions.html \
+ test-bug-630733-response-redirect-headers.sjs \
+ test-bug-621644-jsterm-dollar.html \
+ test-bug-632347-iterators-generators.html \
+ test-bug-585956-console-trace.html \
+ test-bug-644419-log-limits.html \
+ test-bug-632275-getters.html \
+ test-bug-646025-console-file-location.html \
+ test-bug-782653-css-errors.html \
+ test-bug-782653-css-errors-1.css \
+ test-bug-782653-css-errors-2.css \
+ test-file-location.js \
+ test-bug-658368-time-methods.html \
+ test-webconsole-error-observer.html \
+ test-for-of.html \
+ test_bug_770099_violation.html \
+ test_bug_770099_violation.html^headers^ \
+ test_bug_770099_bad_policy_uri.html \
+ test_bug_770099_bad_policy_uri.html^headers^ \
+ test-result-format-as-string.html \
+ test-bug-737873-mixedcontent.html \
+ test-repeated-messages.html \
+ test-bug-766001-console-log.js \
+ test-bug-766001-js-console-links.html \
+ test-bug-766001-js-errors.js \
+ test-bug-821877-csperrors.html \
+ test-bug-821877-csperrors.html^headers^ \
+ test-eval-in-stackframe.html \
+ test-bug-859170-longstring-hang.html \
+ test-bug-837351-security-errors.html \
+ test-bug-869003-top-window.html \
+ test-bug-869003-iframe.html \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/browser/devtools/webconsole/test/browser_bug664688_sandbox_update_after_navigation.js b/browser/devtools/webconsole/test/browser_bug664688_sandbox_update_after_navigation.js
new file mode 100644
index 000000000..7a9947103
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_bug664688_sandbox_update_after_navigation.js
@@ -0,0 +1,113 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests if the JSTerm sandbox is updated when the user navigates from one
+// domain to another, in order to avoid permission denied errors with a sandbox
+// created for a different origin.
+
+function test()
+{
+ const TEST_URI1 = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+ const TEST_URI2 = "http://example.org/browser/browser/devtools/webconsole/test/test-console.html";
+
+ let hud;
+ let msgForLocation1;
+
+ waitForExplicitFinish();
+
+ gBrowser.selectedTab = gBrowser.addTab(TEST_URI1);
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ openConsole(gBrowser.selectedTab, pageLoad1);
+ }, true);
+
+ function pageLoad1(aHud)
+ {
+ hud = aHud;
+
+ hud.jsterm.clearOutput();
+ hud.jsterm.execute("window.location.href");
+
+ info("wait for window.location.href");
+
+ msgForLocation1 = {
+ webconsole: hud,
+ messages: [
+ {
+ name: "window.location.href jsterm input",
+ text: "window.location.href",
+ category: CATEGORY_INPUT,
+ },
+ {
+ name: "window.location.href result is displayed",
+ text: TEST_URI1,
+ category: CATEGORY_OUTPUT,
+ },
+ ]
+ };
+
+ waitForMessages(msgForLocation1).then(() => {
+ gBrowser.selectedBrowser.addEventListener("load", onPageLoad2, true);
+ content.location = TEST_URI2;
+ });
+ }
+
+ function onPageLoad2() {
+ gBrowser.selectedBrowser.removeEventListener("load", onPageLoad2, true);
+
+ is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
+ "no permission denied errors");
+
+ hud.jsterm.clearOutput();
+ hud.jsterm.execute("window.location.href");
+
+ info("wait for window.location.href after page navigation");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "window.location.href jsterm input",
+ text: "window.location.href",
+ category: CATEGORY_INPUT,
+ },
+ {
+ name: "window.location.href result is displayed",
+ text: TEST_URI2,
+ category: CATEGORY_OUTPUT,
+ },
+ ]
+ }).then(() => {
+ is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
+ "no permission denied errors");
+
+ gBrowser.goBack();
+ waitForSuccess(waitForBack);
+ });
+ }
+
+ let waitForBack = {
+ name: "go back",
+ validatorFn: function()
+ {
+ return content.location.href == TEST_URI1;
+ },
+ successFn: function()
+ {
+ hud.jsterm.clearOutput();
+ executeSoon(() => {
+ hud.jsterm.execute("window.location.href");
+ });
+
+ info("wait for window.location.href after goBack()");
+ waitForMessages(msgForLocation1).then(() => executeSoon(() => {
+ is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
+ "no permission denied errors");
+ finishTest();
+ }));
+ },
+ failureFn: finishTest,
+ };
+}
diff --git a/browser/devtools/webconsole/test/browser_bug_638949_copy_link_location.js b/browser/devtools/webconsole/test/browser_bug_638949_copy_link_location.js
new file mode 100644
index 000000000..3853d531b
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_bug_638949_copy_link_location.js
@@ -0,0 +1,107 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/" +
+ "test/test-console.html?_date=" + Date.now();
+const COMMAND_NAME = "consoleCmd_copyURL";
+const CONTEXT_MENU_ID = "#menu_copyURL";
+
+let HUD = null;
+let output = null;
+let menu = null;
+
+function test() {
+ registerCleanupFunction(() => {
+ HUD = output = menu = null;
+ });
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function (aHud) {
+ HUD = aHud;
+ output = aHud.outputNode;
+ menu = HUD.iframeWindow.document.getElementById("output-contextmenu");
+
+ executeSoon(testWithoutNetActivity);
+ });
+ }, true);
+}
+
+// Return whether "Copy Link Location" command is enabled or not.
+function isEnabled() {
+ let controller = top.document.commandDispatcher
+ .getControllerForCommand(COMMAND_NAME);
+ return controller && controller.isCommandEnabled(COMMAND_NAME);
+}
+
+function testWithoutNetActivity() {
+ HUD.jsterm.clearOutput();
+ content.console.log("bug 638949");
+
+ // Test that the "Copy Link Location" command is disabled for non-network
+ // messages.
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ text: "bug 638949",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onConsoleMessage);
+}
+
+function onConsoleMessage(aResults) {
+ output.focus();
+ output.selectedItem = [...aResults[0].matched][0];
+
+ goUpdateCommand(COMMAND_NAME);
+ ok(!isEnabled(), COMMAND_NAME + "is disabled");
+
+ // Test that the "Copy Link Location" menu item is hidden for non-network
+ // messages.
+ waitForContextMenu(menu, output.selectedItem, () => {
+ let isHidden = menu.querySelector(CONTEXT_MENU_ID).hidden;
+ ok(isHidden, CONTEXT_MENU_ID + " is hidden");
+ }, testWithNetActivity);
+}
+
+function testWithNetActivity() {
+ HUD.jsterm.clearOutput();
+ content.location.reload(); // Reloading will produce network logging
+
+ // Test that the "Copy Link Location" command is enabled and works
+ // as expected for any network-related message.
+ // This command should copy only the URL.
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ text: "test-console.html",
+ category: CATEGORY_NETWORK,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onNetworkMessage);
+}
+
+function onNetworkMessage(aResults) {
+ output.focus();
+ output.selectedItem = [...aResults[0].matched][0];
+
+ goUpdateCommand(COMMAND_NAME);
+ ok(isEnabled(), COMMAND_NAME + " is enabled");
+
+ waitForClipboard(output.selectedItem.url, () => goDoCommand(COMMAND_NAME),
+ testMenuWithNetActivity, testMenuWithNetActivity);
+}
+
+function testMenuWithNetActivity() {
+ // Test that the "Copy Link Location" menu item is visible for network-related
+ // messages.
+ waitForContextMenu(menu, output.selectedItem, () => {
+ let isVisible = !menu.querySelector(CONTEXT_MENU_ID).hidden;
+ ok(isVisible, CONTEXT_MENU_ID + " is visible");
+ }, finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_bug_862916_console_dir_and_filter_off.js b/browser/devtools/webconsole/test/browser_bug_862916_console_dir_and_filter_off.js
new file mode 100644
index 000000000..6dfc00b8a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_bug_862916_console_dir_and_filter_off.js
@@ -0,0 +1,34 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that the output for console.dir() works even if Logging filter is off.
+
+const TEST_URI = "data:text/html;charset=utf8,<p>test for bug 862916";
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ ok(hud, "web console opened");
+
+ hud.setFilterState("log", false);
+ registerCleanupFunction(() => hud.setFilterState("log", true));
+
+ content.wrappedJSObject.fooBarz = "bug862916";
+ hud.jsterm.execute("console.dir(window)");
+ hud.jsterm.once("variablesview-fetched", (aEvent, aVar) => {
+ ok(aVar, "variables view object");
+ findVariableViewProperties(aVar, [
+ { name: "fooBarz", value: "bug862916" },
+ ], { webconsole: hud }).then(finishTest);
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_bug_865288_repeat_different_objects.js b/browser/devtools/webconsole/test/browser_bug_865288_repeat_different_objects.js
new file mode 100644
index 000000000..df3335082
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_bug_865288_repeat_different_objects.js
@@ -0,0 +1,82 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that makes sure messages are not considered repeated when console.log()
+// is invoked with different objects, see bug 865288.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-repeated-messages.html";
+
+let hud = null;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(aHud) {
+ hud = aHud;
+
+ // Check that css warnings are not coalesced if they come from different lines.
+ info("waiting for 3 console.log objects");
+
+ hud.jsterm.clearOutput(true);
+ content.wrappedJSObject.testConsoleObjects();
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ name: "3 console.log messages",
+ text: "abba",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ count: 3,
+ repeats: 1,
+ objects: true,
+ }],
+ }).then(checkMessages);
+}
+
+function checkMessages(aResults)
+{
+ let result = aResults[0];
+ let msgs = [...result.matched];
+ is(msgs.length, 3, "3 message elements");
+ let m = -1;
+
+ function nextMessage()
+ {
+ let msg = msgs[++m];
+ if (msg) {
+ ok(msg, "message element #" + m);
+
+ let clickable = msg.querySelector(".hud-clickable");
+ ok(clickable, "clickable object #" + m);
+
+ scrollOutputToNode(msg);
+ clickObject(clickable);
+ }
+ else {
+ finishTest();
+ }
+ }
+
+ nextMessage();
+
+ function clickObject(aObject)
+ {
+ hud.jsterm.once("variablesview-fetched", onObjectFetch);
+ EventUtils.synthesizeMouse(aObject, 2, 2, {}, hud.iframeWindow);
+ }
+
+ function onObjectFetch(aEvent, aVar)
+ {
+ findVariableViewProperties(aVar, [
+ { name: "id", value: "abba" + m },
+ ], { webconsole: hud }).then(nextMessage);
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_bug_865871_variables_view_close_on_esc_key.js b/browser/devtools/webconsole/test/browser_bug_865871_variables_view_close_on_esc_key.js
new file mode 100644
index 000000000..7e47d38c3
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_bug_865871_variables_view_close_on_esc_key.js
@@ -0,0 +1,98 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that the variables view sidebar can be closed by pressing Escape in the
+// web console.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
+
+let gWebConsole, gJSTerm, gVariablesView;
+
+function test()
+{
+ registerCleanupFunction(() => {
+ gWebConsole = gJSTerm = gVariablesView = null;
+ });
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ gWebConsole = hud;
+ gJSTerm = hud.jsterm;
+ gJSTerm.execute("fooObj", onExecuteFooObj);
+}
+
+function onExecuteFooObj()
+{
+ let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
+ ok(msg, "output message found");
+ isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
+
+ gJSTerm.once("variablesview-fetched", onFooObjFetch);
+ EventUtils.synthesizeMouse(msg, 2, 2, {}, gWebConsole.iframeWindow)
+}
+
+function onFooObjFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp", value: "testValue" },
+ ], { webconsole: gWebConsole }).then(onTestPropFound);
+}
+
+function onTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the |testProp| property in the variables view");
+
+ is(content.wrappedJSObject.fooObj.testProp, aResults[0].value,
+ "|fooObj.testProp| value is correct");
+
+ gVariablesView.window.focus();
+ gJSTerm.once("sidebar-closed", onSidebarClosed);
+ EventUtils.synthesizeKey("VK_ESCAPE", {}, gVariablesView.window);
+}
+
+function onSidebarClosed()
+{
+ gJSTerm.clearOutput();
+ gJSTerm.execute("window", onExecuteWindow);
+}
+
+function onExecuteWindow()
+{
+ let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
+ ok(msg, "output message found");
+ isnot(msg.textContent.indexOf("[object Window]"), -1, "message text check");
+
+ gJSTerm.once("variablesview-fetched", onWindowFetch);
+ EventUtils.synthesizeMouse(msg, 2, 2, {}, gWebConsole.iframeWindow)
+}
+
+function onWindowFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "foo", value: "globalFooBug783499" },
+ ], { webconsole: gWebConsole }).then(onFooFound);
+}
+
+function onFooFound(aResults)
+{
+ gVariablesView.window.focus();
+ gJSTerm.once("sidebar-closed", finishTest);
+ EventUtils.synthesizeKey("VK_ESCAPE", {}, gVariablesView.window);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_bug_869003_inspect_cross_domain_object.js b/browser/devtools/webconsole/test/browser_bug_869003_inspect_cross_domain_object.js
new file mode 100644
index 000000000..0f8778e81
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_bug_869003_inspect_cross_domain_object.js
@@ -0,0 +1,94 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that users can inspect objects logged from cross-domain iframes -
+// bug 869003.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-869003-top-window.html";
+
+let gWebConsole, gJSTerm, gVariablesView;
+
+function test()
+{
+ // This test is slightly more involved: it opens the web console, then the
+ // variables view for a given object, it updates a property in the view and
+ // checks the result. We can get a timeout with debug builds on slower machines.
+ requestLongerTimeout(2);
+
+ addTab("data:text/html;charset=utf8,<p>hello");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ gWebConsole = hud;
+ gJSTerm = hud.jsterm;
+ content.location = TEST_URI;
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ name: "console.log message",
+ text: "foobar",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ objects: true,
+ }],
+ }).then(onConsoleMessage);
+}
+
+function onConsoleMessage(aResults)
+{
+ let clickable = aResults[0].clickableElements[0];
+ ok(clickable, "clickable object found");
+ isnot(clickable.textContent.indexOf("[object Object]"), -1,
+ "message text check");
+
+ gJSTerm.once("variablesview-fetched", onObjFetch);
+
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, gWebConsole.iframeWindow)
+}
+
+function onObjFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "hello", value: "world!" },
+ { name: "bug", value: 869003 },
+ ], { webconsole: gWebConsole }).then(onPropFound);
+}
+
+function onPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the |hello| property in the variables view");
+
+ // Check that property value updates work.
+ updateVariablesViewProperty({
+ property: prop,
+ field: "value",
+ string: "'omgtest'",
+ webconsole: gWebConsole,
+ callback: onFetchAfterUpdate,
+ });
+}
+
+function onFetchAfterUpdate(aEvent, aVar)
+{
+ info("onFetchAfterUpdate");
+
+ findVariableViewProperties(aVar, [
+ { name: "hello", value: "omgtest" },
+ { name: "bug", value: 869003 },
+ ], { webconsole: gWebConsole }).then(() => {
+ gWebConsole = gJSTerm = gVariablesView = null;
+ finishTest();
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_bug_871156_ctrlw_close_tab.js b/browser/devtools/webconsole/test/browser_bug_871156_ctrlw_close_tab.js
new file mode 100644
index 000000000..a76bf2bfe
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_bug_871156_ctrlw_close_tab.js
@@ -0,0 +1,66 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that Ctrl-W closes the Browser Console and that Ctrl-W closes the
+// current tab when using the Web Console - bug 871156.
+
+function test()
+{
+ const TEST_URI = "data:text/html;charset=utf8,<title>bug871156</title>\n" +
+ "<p>hello world";
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+
+ function consoleOpened(hud)
+ {
+ ok(hud, "Web Console opened");
+
+ let tabClosed = false, toolboxDestroyed = false;
+
+ gBrowser.tabContainer.addEventListener("TabClose", function onTabClose() {
+ gBrowser.tabContainer.removeEventListener("TabClose", onTabClose);
+
+ ok(true, "tab closed");
+
+ tabClosed = true;
+ if (toolboxDestroyed) {
+ testBrowserConsole();
+ }
+ });
+
+ let toolbox = gDevTools.getToolbox(hud.target);
+ toolbox.once("destroyed", () => {
+ ok(true, "toolbox destroyed");
+
+ toolboxDestroyed = true;
+ if (tabClosed) {
+ testBrowserConsole();
+ }
+ });
+
+ EventUtils.synthesizeKey("w", { accelKey: true }, hud.iframeWindow);
+ }
+
+ function testBrowserConsole()
+ {
+ info("test the Browser Console");
+
+ HUDConsoleUI.toggleBrowserConsole().then((hud) => {
+ ok(hud, "Browser Console opened");
+
+ Services.obs.addObserver(function onDestroy() {
+ Services.obs.removeObserver(onDestroy, "web-console-destroyed");
+ ok(true, "the Browser Console closed");
+
+ executeSoon(finishTest);
+ }, "web-console-destroyed", false);
+
+ EventUtils.synthesizeKey("w", { accelKey: true }, hud.iframeWindow);
+ });
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_cached_messages.js b/browser/devtools/webconsole/test/browser_cached_messages.js
new file mode 100644
index 000000000..aa28daaef
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_cached_messages.js
@@ -0,0 +1,76 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-webconsole-error-observer.html";
+
+function test()
+{
+ waitForExplicitFinish();
+
+ expectUncaughtException();
+
+ addTab(TEST_URI);
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ testOpenUI(true);
+ }, true);
+}
+
+function testOpenUI(aTestReopen)
+{
+ // test to see if the messages are
+ // displayed when the console UI is opened
+
+ let messages = {
+ "log Bazzle" : false,
+ "error Bazzle" : false,
+ "bazBug611032" : false,
+ "cssColorBug611032" : false,
+ };
+
+ openConsole(null, function(hud) {
+ waitForSuccess({
+ name: "cached messages displayed",
+ validatorFn: function()
+ {
+ let foundAll = true;
+ for (let msg in messages) {
+ let found = messages[msg];
+ if (!found) {
+ found = hud.outputNode.textContent.indexOf(msg) > -1;
+ if (found) {
+ info("found message '" + msg + "'");
+ messages[msg] = found;
+ }
+ }
+ foundAll = foundAll && found;
+ }
+ return foundAll;
+ },
+ successFn: function()
+ {
+ // Make sure the CSS warning is given the correct category - bug 768019.
+ let cssNode = hud.outputNode.querySelector(".webconsole-msg-cssparser");
+ ok(cssNode, "CSS warning message element");
+ isnot(cssNode.textContent.indexOf("cssColorBug611032"), -1,
+ "CSS warning message element content is correct");
+
+ closeConsole(gBrowser.selectedTab, function() {
+ aTestReopen && info("will reopen the Web Console");
+ executeSoon(aTestReopen ? testOpenUI : finishTest);
+ });
+ },
+ failureFn: function()
+ {
+ for (let msg in messages) {
+ if (!messages[msg]) {
+ ok(false, "failed to find '" + msg + "'");
+ }
+ }
+ finishTest();
+ },
+ });
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_console.js b/browser/devtools/webconsole/test/browser_console.js
new file mode 100644
index 000000000..d204c1b2b
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console.js
@@ -0,0 +1,102 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test the basic features of the Browser Console, bug 587757.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html?" + Date.now();
+
+function test()
+{
+ let oldFunction = HUDConsoleUI.toggleBrowserConsole;
+ let functionExecuted = false;
+ HUDConsoleUI.toggleBrowserConsole = () => functionExecuted = true;
+ EventUtils.synthesizeKey("j", { accelKey: true, shiftKey: true }, content);
+
+ ok(functionExecuted,
+ "toggleBrowserConsole() was executed by the Ctrl-Shift-J key shortcut");
+
+ HUDConsoleUI.toggleBrowserConsole = oldFunction;
+ HUDConsoleUI.toggleBrowserConsole().then(consoleOpened);
+}
+
+function consoleOpened(hud)
+{
+ hud.jsterm.clearOutput(true);
+
+ expectUncaughtException();
+ executeSoon(() => {
+ foobarExceptionBug587757();
+ });
+
+ // Add a message from a chrome window.
+ hud.iframeWindow.console.log("bug587757a");
+
+ // Add a message from a content window.
+ content.console.log("bug587757b");
+
+ // Test eval.
+ hud.jsterm.execute("document.location.href");
+
+ // Check for network requests.
+ let xhr = new XMLHttpRequest();
+ xhr.onload = () => console.log("xhr loaded, status is: " + xhr.status);
+ xhr.open("get", TEST_URI, true);
+ xhr.send();
+
+ let chromeConsole = -1;
+ let contentConsole = -1;
+ let execValue = -1;
+ let exception = -1;
+ let xhrRequest = false;
+
+ let output = hud.outputNode;
+ function performChecks()
+ {
+ let text = output.textContent;
+ chromeConsole = text.indexOf("bug587757a");
+ contentConsole = text.indexOf("bug587757b");
+ execValue = text.indexOf("browser.xul");
+ exception = text.indexOf("foobarExceptionBug587757");
+
+ xhrRequest = false;
+ let urls = output.querySelectorAll(".webconsole-msg-url");
+ for (let url of urls) {
+ if (url.value.indexOf(TEST_URI) > -1) {
+ xhrRequest = true;
+ break;
+ }
+ }
+ }
+
+ function showResults()
+ {
+ isnot(chromeConsole, -1, "chrome window console.log() is displayed");
+ isnot(contentConsole, -1, "content window console.log() is displayed");
+ isnot(execValue, -1, "jsterm eval result is displayed");
+ isnot(exception, -1, "exception is displayed");
+ ok(xhrRequest, "xhr request is displayed");
+ }
+
+ waitForSuccess({
+ name: "messages displayed",
+ validatorFn: () => {
+ performChecks();
+ return chromeConsole > -1 &&
+ contentConsole > -1 &&
+ execValue > -1 &&
+ exception > -1 &&
+ xhrRequest;
+ },
+ successFn: () => {
+ showResults();
+ executeSoon(finishTest);
+ },
+ failureFn: () => {
+ showResults();
+ info("output: " + output.textContent);
+ executeSoon(finishTest);
+ },
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_console_addonsdk_loader_exception.js b/browser/devtools/webconsole/test/browser_console_addonsdk_loader_exception.js
new file mode 100644
index 000000000..7a4186761
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_addonsdk_loader_exception.js
@@ -0,0 +1,93 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that exceptions from scripts loaded with the addon-sdk loader are
+// opened correctly in View Source from the Browser Console.
+// See bug 866950.
+
+const TEST_URI = "data:text/html;charset=utf8,<p>hello world from bug 866950";
+
+function test()
+{
+ let webconsole, browserconsole;
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, consoleOpened);
+ }, true);
+
+ function consoleOpened(hud)
+ {
+ ok(hud, "web console opened");
+ webconsole = hud;
+ HUDConsoleUI.toggleBrowserConsole().then(browserConsoleOpened);
+ }
+
+ function browserConsoleOpened(hud)
+ {
+ ok(hud, "browser console opened");
+ browserconsole = hud;
+
+ // Cause an exception in a script loaded with the addon-sdk loader.
+ let toolbox = gDevTools.getToolbox(webconsole.target);
+ let oldPanels = toolbox._toolPanels;
+ toolbox._toolPanels = null;
+ function fixToolbox()
+ {
+ toolbox._toolPanels = oldPanels;
+ }
+
+ info("generate exception and wait for message");
+
+ executeSoon(() => {
+ executeSoon(fixToolbox);
+ expectUncaughtException();
+ toolbox.getToolPanels();
+ });
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ text: "TypeError: this._toolPanels is null",
+ category: CATEGORY_JS,
+ severity: SEVERITY_ERROR,
+ },
+ ],
+ }).then((results) => {
+ fixToolbox();
+ onMessageFound(results);
+ });
+ }
+
+ function onMessageFound(results)
+ {
+ let msg = [...results[0].matched][0];
+ ok(msg, "message element found");
+ let locationNode = msg.querySelector(".webconsole-location");
+ ok(locationNode, "message location element found");
+
+ let title = locationNode.getAttribute("title");
+ info("location node title: " + title);
+ isnot(title.indexOf(" -> "), -1, "error comes from a subscript");
+
+ let viewSource = browserconsole.viewSource;
+ let URL = null;
+ browserconsole.viewSource = (aURL) => URL = aURL;
+
+ EventUtils.synthesizeMouse(locationNode, 2, 2, {},
+ browserconsole.iframeWindow);
+
+ info("view-source url: " + URL);
+ isnot(URL.indexOf("toolbox.js"), -1, "expected view source URL");
+ is(URL.indexOf("->"), -1, "no -> in the URL given to view-source");
+
+ browserconsole.viewSource = viewSource;
+
+ finishTest();
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_clear_on_reload.js b/browser/devtools/webconsole/test/browser_console_clear_on_reload.js
new file mode 100644
index 000000000..63103c368
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_clear_on_reload.js
@@ -0,0 +1,73 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that clear output on page reload works - bug 705921.
+
+function test()
+{
+ const PREF = "devtools.webconsole.persistlog";
+ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+ let hud = null;
+
+ Services.prefs.setBoolPref(PREF, false);
+ registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
+
+ addTab(TEST_URI);
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+
+ function consoleOpened(aHud)
+ {
+ hud = aHud;
+ ok(hud, "Web Console opened");
+
+ hud.jsterm.clearOutput();
+ content.console.log("foobarz1");
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "foobarz1",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onConsoleMessage);
+ }
+
+ function onConsoleMessage()
+ {
+ browser.addEventListener("load", onReload, true);
+ content.location.reload();
+ }
+
+ function onReload()
+ {
+ browser.removeEventListener("load", onReload, true);
+
+ content.console.log("foobarz2");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "test-console.html",
+ category: CATEGORY_NETWORK,
+ },
+ {
+ text: "foobarz2",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onConsoleMessageAfterReload);
+ }
+
+ function onConsoleMessageAfterReload()
+ {
+ is(hud.outputNode.textContent.indexOf("foobarz1"), -1,
+ "foobarz1 has been removed from output");
+ finishTest();
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_consolejsm_output.js b/browser/devtools/webconsole/test/browser_console_consolejsm_output.js
new file mode 100644
index 000000000..96b8ff42e
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_consolejsm_output.js
@@ -0,0 +1,135 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test that Console.jsm outputs messages to the Browser Console, bug 851231.
+
+function test()
+{
+ let storage = Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", {}).ConsoleAPIStorage;
+ storage.clearEvents();
+
+ let console = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).console;
+ console.log("bug861338-log-cached");
+
+ HUDConsoleUI.toggleBrowserConsole().then(consoleOpened);
+ let hud = null;
+
+ function consoleOpened(aHud)
+ {
+ hud = aHud;
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ name: "cached console.log message",
+ text: "bug861338-log-cached",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onCachedMessage);
+ }
+
+ function onCachedMessage()
+ {
+ hud.jsterm.clearOutput(true);
+
+ console.time("foobarTimer");
+ let foobar = { bug851231prop: "bug851231value" };
+
+ console.log("bug851231-log");
+ console.info("bug851231-info");
+ console.warn("bug851231-warn");
+ console.error("bug851231-error", foobar);
+ console.debug("bug851231-debug");
+ console.trace();
+ console.dir(document);
+ console.timeEnd("foobarTimer");
+
+ info("wait for the Console.jsm messages");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "console.log output",
+ text: "bug851231-log",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ },
+ {
+ name: "console.info output",
+ text: "bug851231-info",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_INFO,
+ },
+ {
+ name: "console.warn output",
+ text: "bug851231-warn",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_WARNING,
+ },
+ {
+ name: "console.error output",
+ text: /\bbug851231-error\b.+\[object Object\]/,
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_ERROR,
+ objects: true,
+ },
+ {
+ name: "console.debug output",
+ text: "bug851231-debug",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ },
+ {
+ name: "console.trace output",
+ consoleTrace: {
+ file: "browser_console_consolejsm_output.js",
+ fn: "onCachedMessage",
+ },
+ },
+ {
+ name: "console.dir output",
+ consoleDir: "[object XULDocument]",
+ },
+ {
+ name: "console.time output",
+ consoleTime: "foobarTimer",
+ },
+ {
+ name: "console.timeEnd output",
+ consoleTimeEnd: "foobarTimer",
+ },
+ ],
+ }).then((aResults) => {
+ let consoleErrorMsg = aResults[3];
+ ok(consoleErrorMsg, "console.error message element found");
+ let clickable = consoleErrorMsg.clickableElements[0];
+ ok(clickable, "clickable object found for console.error");
+
+ let onFetch = (aEvent, aVar) => {
+ // Skip the notification from console.dir variablesview-fetched.
+ if (aVar._variablesView != hud.jsterm._variablesView) {
+ return;
+ }
+ hud.jsterm.off("variablesview-fetched", onFetch);
+
+ ok(aVar, "object inspector opened on click");
+
+ findVariableViewProperties(aVar, [{
+ name: "bug851231prop",
+ value: "bug851231value",
+ }], { webconsole: hud }).then(finishTest);
+ };
+
+ hud.jsterm.on("variablesview-fetched", onFetch);
+
+ scrollOutputToNode(clickable);
+
+ info("wait for variablesview-fetched");
+ executeSoon(() =>
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow));
+ });
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_dead_objects.js b/browser/devtools/webconsole/test/browser_console_dead_objects.js
new file mode 100644
index 000000000..1d68df857
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_dead_objects.js
@@ -0,0 +1,79 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that Dead Objects do not break the Web/Browser Consoles. See bug 883649.
+
+const TEST_URI = "data:text/html;charset=utf8,<p>dead objects!";
+
+function test()
+{
+ let hud = null;
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ info("open the browser console");
+ HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
+ }, true);
+
+ function onBrowserConsoleOpen(aHud)
+ {
+ hud = aHud;
+ ok(hud, "browser console opened");
+
+ hud.jsterm.clearOutput();
+ hud.jsterm.execute("foobarzTezt = content.document", onAddVariable);
+ }
+
+ function onAddVariable()
+ {
+ gBrowser.removeCurrentTab();
+
+ hud.jsterm.execute("foobarzTezt", onReadVariable);
+ }
+
+ function onReadVariable()
+ {
+ isnot(hud.outputNode.textContent.indexOf("[object DeadObject]"), -1,
+ "dead object found");
+
+ hud.jsterm.setInputValue("foobarzTezt");
+
+ for (let c of ".hello") {
+ EventUtils.synthesizeKey(c, {}, hud.iframeWindow);
+ }
+
+ hud.jsterm.execute(null, onReadProperty);
+ }
+
+ function onReadProperty()
+ {
+ isnot(hud.outputNode.textContent.indexOf("can't access dead object"), -1,
+ "'cannot access dead object' message found");
+
+ // Click the second execute output.
+ let clickable = hud.outputNode.querySelectorAll(".webconsole-msg-output")[1]
+ .querySelector(".hud-clickable");
+ ok(clickable, "clickable object found");
+ isnot(clickable.textContent.indexOf("[object DeadObject]"), -1,
+ "message text check");
+
+ hud.jsterm.once("variablesview-fetched", onFetched);
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
+ }
+
+ function onFetched()
+ {
+ hud.jsterm.execute("delete window.foobarzTezt; 2013-26", onCalcResult);
+ }
+
+ function onCalcResult()
+ {
+ isnot(hud.outputNode.textContent.indexOf("1987"), -1, "result message found");
+
+ // executeSoon() is needed to get out of the execute() event loop.
+ executeSoon(finishTest);
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_error_source_click.js b/browser/devtools/webconsole/test/browser_console_error_source_click.js
new file mode 100644
index 000000000..98fe93dbc
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_error_source_click.js
@@ -0,0 +1,75 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that JS errors and CSS warnings open view source when their source link
+// is clicked in the Browser Console. See bug 877778.
+
+const TEST_URI = "data:text/html;charset=utf8,<p>hello world from bug 877778 " +
+ "<button onclick='foobar.explode()' " +
+ "style='test-color: green-please'>click!</button>";
+function test()
+{
+ let hud;
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ HUDConsoleUI.toggleBrowserConsole().then(browserConsoleOpened);
+ }, true);
+
+ function browserConsoleOpened(aHud)
+ {
+ hud = aHud;
+ ok(hud, "browser console opened");
+
+ let button = content.document.querySelector("button");
+ ok(button, "button element found");
+
+ info("generate exception and wait for the message");
+ executeSoon(() => {
+ expectUncaughtException();
+ button.click();
+ });
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ text: "ReferenceError: foobar is not defined",
+ category: CATEGORY_JS,
+ severity: SEVERITY_ERROR,
+ },
+ {
+ text: "Unknown property 'test-color'",
+ category: CATEGORY_CSS,
+ severity: SEVERITY_WARNING,
+ },
+ ],
+ }).then(onMessageFound);
+ }
+
+ function onMessageFound(results)
+ {
+ let viewSource = hud.viewSource;
+ let viewSourceCalled = false;
+ hud.viewSource = () => viewSourceCalled = true;
+
+ for (let result of results) {
+ viewSourceCalled = false;
+
+ let msg = [...results[0].matched][0];
+ ok(msg, "message element found for: " + result.text);
+ let locationNode = msg.querySelector(".webconsole-location");
+ ok(locationNode, "message location element found");
+
+ EventUtils.synthesizeMouse(locationNode, 2, 2, {}, hud.iframeWindow);
+
+ ok(viewSourceCalled, "view source opened");
+ }
+
+ hud.viewSource = viewSource;
+ finishTest();
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_filters.js b/browser/devtools/webconsole/test/browser_console_filters.js
new file mode 100644
index 000000000..d9aa35c81
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_filters.js
@@ -0,0 +1,71 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that the Browser Console does not use the same filter prefs as the Web
+// Console. See bug 878186.
+
+const TEST_URI = "data:text/html;charset=utf8,<p>browser console filters";
+const WEB_CONSOLE_PREFIX = "devtools.webconsole.filter.";
+const BROWSER_CONSOLE_PREFIX = "devtools.browserconsole.filter.";
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ info("open the web console");
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ ok(hud, "web console opened");
+
+ is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), true,
+ "'exception' filter is enabled (browser console)");
+ is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), true,
+ "'exception' filter is enabled (web console)");
+
+ info("toggle 'exception' filter");
+ hud.setFilterState("exception", false);
+
+ is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), true,
+ "'exception' filter is enabled (browser console)");
+ is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), false,
+ "'exception' filter is disabled (web console)");
+
+ hud.setFilterState("exception", true);
+
+ executeSoon(() => closeConsole(null, onWebConsoleClose));
+}
+
+function onWebConsoleClose()
+{
+ info("web console closed");
+ HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
+}
+
+function onBrowserConsoleOpen(hud)
+{
+ ok(hud, "browser console opened");
+
+ is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), true,
+ "'exception' filter is enabled (browser console)");
+ is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), true,
+ "'exception' filter is enabled (web console)");
+
+ info("toggle 'exception' filter");
+ hud.setFilterState("exception", false);
+
+ is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), false,
+ "'exception' filter is disabled (browser console)");
+ is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), true,
+ "'exception' filter is enabled (web console)");
+
+ hud.setFilterState("exception", true);
+
+ executeSoon(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_console_keyboard_accessibility.js b/browser/devtools/webconsole/test/browser_console_keyboard_accessibility.js
new file mode 100644
index 000000000..aca00bd5a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_keyboard_accessibility.js
@@ -0,0 +1,69 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that basic keyboard shortcuts work in the web console.
+
+function test()
+{
+ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+ let hud = null;
+
+ addTab(TEST_URI);
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+
+ function consoleOpened(aHud)
+ {
+ hud = aHud;
+ ok(hud, "Web Console opened");
+
+ content.console.log("foobarz1");
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "foobarz1",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onConsoleMessage);
+ }
+
+ function onConsoleMessage()
+ {
+ hud.jsterm.once("messages-cleared", onClear);
+ info("try ctrl-k to clear output");
+ EventUtils.synthesizeKey("K", { accelKey: true });
+ }
+
+ function onClear()
+ {
+ is(hud.outputNode.textContent.indexOf("foobarz1"), -1, "output cleared");
+ is(hud.jsterm.inputNode.getAttribute("focused"), "true",
+ "jsterm input is focused");
+
+ info("try ctrl-f to focus filter");
+ EventUtils.synthesizeKey("F", { accelKey: true });
+ ok(!hud.jsterm.inputNode.getAttribute("focused"),
+ "jsterm input is not focused");
+ is(hud.ui.filterBox.getAttribute("focused"), "true",
+ "filter input is focused");
+
+ if (Services.appinfo.OS == "Darwin") {
+ EventUtils.synthesizeKey("t", { ctrlKey: true });
+ }
+ else {
+ EventUtils.synthesizeKey("N", { altKey: true });
+ }
+
+ let net = hud.ui.document.querySelector("toolbarbutton[category=net]");
+ is(hud.ui.document.activeElement, net,
+ "accesskey for Network category focuses the Net button");
+
+ finishTest();
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_log_inspectable_object.js b/browser/devtools/webconsole/test/browser_console_log_inspectable_object.js
new file mode 100644
index 000000000..230805401
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_log_inspectable_object.js
@@ -0,0 +1,58 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that objects given to console.log() are inspectable.
+
+function test()
+{
+ waitForExplicitFinish();
+
+ addTab("data:text/html;charset=utf8,test for bug 676722 - inspectable objects for window.console");
+
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ openConsole(null, performTest);
+ }, true);
+}
+
+function performTest(hud)
+{
+ hud.jsterm.clearOutput(true);
+
+ hud.jsterm.execute("myObj = {abba: 'omgBug676722'}");
+ hud.jsterm.execute("console.log('fooBug676722', myObj)");
+ waitForSuccess({
+ name: "eval results are shown",
+ validatorFn: function()
+ {
+ return hud.outputNode.textContent.indexOf("fooBug676722") > -1 &&
+ hud.outputNode.querySelector(".hud-clickable");
+ },
+ successFn: function()
+ {
+ isnot(hud.outputNode.textContent.indexOf("myObj = {"), -1,
+ "myObj = ... is shown");
+
+ let clickable = hud.outputNode.querySelector(".hud-clickable");
+ ok(clickable, "the console.log() object .hud-clickable was found");
+ isnot(clickable.textContent.indexOf("Object"), -1,
+ "clickable node content is correct");
+
+ hud.jsterm.once("variablesview-fetched",
+ (aEvent, aVar) => {
+ ok(aVar, "object inspector opened on click");
+
+ findVariableViewProperties(aVar, [{
+ name: "abba",
+ value: "omgBug676722",
+ }], { webconsole: hud }).then(finishTest);
+ });
+
+ executeSoon(function() {
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
+ });
+ },
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_console_native_getters.js b/browser/devtools/webconsole/test/browser_console_native_getters.js
new file mode 100644
index 000000000..3dd89d298
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_native_getters.js
@@ -0,0 +1,121 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that native getters and setters for DOM elements work as expected in
+// variables view - bug 870220.
+
+const TEST_URI = "data:text/html;charset=utf8,<title>bug870220</title>\n" +
+ "<p>hello world\n<p>native getters!";
+
+let gWebConsole, gJSTerm, gVariablesView;
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ gWebConsole = hud;
+ gJSTerm = hud.jsterm;
+
+ gJSTerm.execute("document");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "[object HTMLDocument]",
+ category: CATEGORY_OUTPUT,
+ objects: true,
+ }],
+ }).then(onEvalResult);
+}
+
+function onEvalResult(aResults)
+{
+ let clickable = aResults[0].clickableElements[0];
+ ok(clickable, "clickable object found");
+
+ gJSTerm.once("variablesview-fetched", onDocumentFetch);
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, gWebConsole.iframeWindow)
+}
+
+function onDocumentFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "title", value: "bug870220" },
+ { name: "bgColor" },
+ ], { webconsole: gWebConsole }).then(onDocumentPropsFound);
+}
+
+function onDocumentPropsFound(aResults)
+{
+ let prop = aResults[1].matchedProp;
+ ok(prop, "matched the |bgColor| property in the variables view");
+
+ // Check that property value updates work.
+ updateVariablesViewProperty({
+ property: prop,
+ field: "value",
+ string: "'red'",
+ webconsole: gWebConsole,
+ callback: onFetchAfterBackgroundUpdate,
+ });
+}
+
+function onFetchAfterBackgroundUpdate(aEvent, aVar)
+{
+ info("onFetchAfterBackgroundUpdate");
+
+ is(content.document.bgColor, "red", "document background color changed");
+
+ findVariableViewProperties(aVar, [
+ { name: "bgColor", value: "red" },
+ ], { webconsole: gWebConsole }).then(testParagraphs);
+}
+
+function testParagraphs()
+{
+ gJSTerm.execute("$$('p')");
+
+ waitForMessages({
+ webconsole: gWebConsole,
+ messages: [{
+ text: "[object NodeList]",
+ category: CATEGORY_OUTPUT,
+ objects: true,
+ }],
+ }).then(onEvalNodeList);
+}
+
+function onEvalNodeList(aResults)
+{
+ let clickable = aResults[0].clickableElements[0];
+ ok(clickable, "clickable object found");
+
+ gJSTerm.once("variablesview-fetched", onNodeListFetch);
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, gWebConsole.iframeWindow)
+}
+
+function onNodeListFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "0.textContent", value: /hello world/ },
+ { name: "1.textContent", value: /native getters/ },
+ ], { webconsole: gWebConsole }).then(() => {
+ gWebConsole = gJSTerm = gVariablesView = null;
+ finishTest();
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_console_nsiconsolemessage.js b/browser/devtools/webconsole/test/browser_console_nsiconsolemessage.js
new file mode 100644
index 000000000..dcfc19fee
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_nsiconsolemessage.js
@@ -0,0 +1,95 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that nsIConsoleMessages are displayed in the Browser Console.
+// See bug 859756.
+
+const TEST_URI = "data:text/html;charset=utf8,<title>bug859756</title>\n" +
+ "<p>hello world\n<p>nsIConsoleMessages ftw!";
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ // Test for cached nsIConsoleMessages.
+ Services.console.logStringMessage("test1 for bug859756");
+
+ info("open web console");
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ ok(hud, "web console opened");
+ Services.console.logStringMessage("do-not-show-me");
+ content.console.log("foobarz");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ text: "foobarz",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ },
+ ],
+ }).then(() => {
+ let text = hud.outputNode.textContent;
+ is(text.indexOf("do-not-show-me"), -1,
+ "nsIConsoleMessages are not displayed");
+ is(text.indexOf("test1 for bug859756"), -1,
+ "nsIConsoleMessages are not displayed (confirmed)");
+ closeConsole(null, onWebConsoleClose);
+ });
+}
+
+function onWebConsoleClose()
+{
+ info("web console closed");
+ HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
+}
+
+function onBrowserConsoleOpen(hud)
+{
+ ok(hud, "browser console opened");
+ Services.console.logStringMessage("test2 for bug859756");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ text: "test1 for bug859756",
+ category: CATEGORY_JS,
+ },
+ {
+ text: "test2 for bug859756",
+ category: CATEGORY_JS,
+ },
+ {
+ text: "do-not-show-me",
+ category: CATEGORY_JS,
+ },
+ ],
+ }).then(testFiltering);
+
+ function testFiltering(results)
+ {
+ let msg = [...results[2].matched][0];
+ ok(msg, "message element for do-not-show-me (nsIConsoleMessage)");
+ isnot(msg.textContent.indexOf("do-not-show"), -1, "element content is correct");
+ ok(!msg.classList.contains("hud-filtered-by-type"), "element is not filtered");
+
+ hud.setFilterState("jslog", false);
+
+ ok(msg.classList.contains("hud-filtered-by-type"), "element is filtered");
+
+ hud.setFilterState("jslog", true);
+
+ finishTest();
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_private_browsing.js b/browser/devtools/webconsole/test/browser_console_private_browsing.js
new file mode 100644
index 000000000..b2932e07b
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_private_browsing.js
@@ -0,0 +1,199 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Bug 874061: test for how the browser and web consoles display messages coming
+// from private windows. See bug for description of expected behavior.
+
+function test()
+{
+ const TEST_URI = "data:text/html;charset=utf8,<p>hello world! bug 874061" +
+ "<button onclick='console.log(\"foobar bug 874061\");" +
+ "fooBazBaz.yummy()'>click</button>";
+ let ConsoleAPIStorage = Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", {}).ConsoleAPIStorage;
+ let privateWindow, privateBrowser, privateTab, privateContent;
+ let hud, expectedMessages, nonPrivateMessage;
+
+ // This test is slightly more involved: it opens the web console twice,
+ // a new private window once, and the browser console twice. We can get
+ // a timeout with debug builds on slower machines.
+ requestLongerTimeout(2);
+ start();
+
+ function start()
+ {
+ gBrowser.selectedTab = gBrowser.addTab("data:text/html;charset=utf8," +
+ "<p>hello world! I am not private!");
+ gBrowser.selectedBrowser.addEventListener("load", onLoadTab, true);
+ }
+
+ function onLoadTab()
+ {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoadTab, true);
+ info("onLoadTab()");
+
+ // Make sure we have a clean state to start with.
+ Services.console.reset();
+ ConsoleAPIStorage.clearEvents();
+
+ // Add a non-private message to the browser console.
+ content.console.log("bug874061-not-private");
+
+ nonPrivateMessage = {
+ name: "console message from a non-private window",
+ text: "bug874061-not-private",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ };
+
+ privateWindow = OpenBrowserWindow({ private: true });
+ ok(privateWindow, "new private window");
+ ok(PrivateBrowsingUtils.isWindowPrivate(privateWindow), "window is private");
+
+ whenDelayedStartupFinished(privateWindow, onPrivateWindowReady);
+ }
+
+ function onPrivateWindowReady()
+ {
+ info("private browser window opened");
+ privateBrowser = privateWindow.gBrowser;
+
+ privateTab = privateBrowser.selectedTab = privateBrowser.addTab(TEST_URI);
+ privateBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ info("private tab opened");
+ privateBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ privateContent = privateBrowser.selectedBrowser.contentWindow;
+ ok(PrivateBrowsingUtils.isWindowPrivate(privateContent), "tab window is private");
+ openConsole(privateTab, consoleOpened);
+ }, true);
+ }
+
+ function addMessages()
+ {
+ let button = privateContent.document.querySelector("button");
+ ok(button, "button in page");
+ EventUtils.synthesizeMouse(button, 2, 2, {}, privateContent);
+ }
+
+ function consoleOpened(aHud)
+ {
+ hud = aHud;
+ ok(hud, "web console opened");
+
+ addMessages();
+ expectedMessages = [
+ {
+ name: "script error",
+ text: "fooBazBaz is not defined",
+ category: CATEGORY_JS,
+ severity: SEVERITY_ERROR,
+ },
+ {
+ name: "console message",
+ text: "foobar bug 874061",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ },
+ ];
+
+ // Make sure messages are displayed in the web console as they happen, even
+ // if this is a private tab.
+ waitForMessages({
+ webconsole: hud,
+ messages: expectedMessages,
+ }).then(testCachedMessages);
+ }
+
+ function testCachedMessages()
+ {
+ info("testCachedMessages()");
+ closeConsole(privateTab, () => {
+ info("web console closed");
+ openConsole(privateTab, consoleReopened);
+ });
+ }
+
+ function consoleReopened(aHud)
+ {
+ hud = aHud;
+ ok(hud, "web console reopened");
+
+ // Make sure that cached messages are displayed in the web console, even
+ // if this is a private tab.
+ waitForMessages({
+ webconsole: hud,
+ messages: expectedMessages,
+ }).then(testBrowserConsole);
+ }
+
+ function testBrowserConsole()
+ {
+ info("testBrowserConsole()");
+ closeConsole(privateTab, () => {
+ info("web console closed");
+ privateWindow.HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
+ });
+ }
+
+ // Make sure that the cached messages from private tabs are not displayed in
+ // the browser console.
+ function checkNoPrivateMessages()
+ {
+ let text = hud.outputNode.textContent;
+ is(text.indexOf("fooBazBaz"), -1, "no exception displayed");
+ is(text.indexOf("bug 874061"), -1, "no console message displayed");
+ }
+
+ function onBrowserConsoleOpen(aHud)
+ {
+ hud = aHud;
+ ok(hud, "browser console opened");
+
+ checkNoPrivateMessages();
+ addMessages();
+ expectedMessages.push(nonPrivateMessage);
+
+ // Make sure that live messages are displayed in the browser console, even
+ // from private tabs.
+ waitForMessages({
+ webconsole: hud,
+ messages: expectedMessages,
+ }).then(testPrivateWindowClose);
+ }
+
+ function testPrivateWindowClose()
+ {
+ info("close the private window and check if the private messages are removed");
+ hud.jsterm.once("private-messages-cleared", () => {
+ isnot(hud.outputNode.textContent.indexOf("bug874061-not-private"), -1,
+ "non-private messages are still shown after private window closed");
+ checkNoPrivateMessages();
+
+ info("close the browser console");
+ privateWindow.HUDConsoleUI.toggleBrowserConsole().then(() => {
+ info("reopen the browser console");
+ executeSoon(() =>
+ HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleReopen));
+ });
+ });
+ privateWindow.BrowserTryToCloseWindow();
+ }
+
+ function onBrowserConsoleReopen(aHud)
+ {
+ hud = aHud;
+ ok(hud, "browser console reopened");
+
+ // Make sure that the non-private message is still shown after reopen.
+ waitForMessages({
+ webconsole: hud,
+ messages: [nonPrivateMessage],
+ }).then(() => {
+ // Make sure that no private message is displayed after closing the private
+ // window and reopening the Browser Console.
+ checkNoPrivateMessages();
+ executeSoon(finishTest);
+ });
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_console_variables_view.js b/browser/devtools/webconsole/test/browser_console_variables_view.js
new file mode 100644
index 000000000..c1d08f653
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_variables_view.js
@@ -0,0 +1,177 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that variables view works as expected in the web console.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
+
+let gWebConsole, gJSTerm, gVariablesView;
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ gWebConsole = hud;
+ gJSTerm = hud.jsterm;
+ gJSTerm.execute("fooObj", onExecuteFooObj);
+}
+
+function onExecuteFooObj()
+{
+ let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
+ ok(msg, "output message found");
+ isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
+
+ gJSTerm.once("variablesview-fetched", onFooObjFetch);
+
+ executeSoon(() =>
+ EventUtils.synthesizeMouse(msg, 2, 2, {}, gWebConsole.iframeWindow)
+ );
+}
+
+function onFooObjFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp", value: "testValue" },
+ ], { webconsole: gWebConsole }).then(onTestPropFound);
+}
+
+function onTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the |testProp| property in the variables view");
+
+ is(content.wrappedJSObject.fooObj.testProp, aResults[0].value,
+ "|fooObj.testProp| value is correct");
+
+ // Check that property value updates work and that jsterm functions can be
+ // used.
+ updateVariablesViewProperty({
+ property: prop,
+ field: "value",
+ string: "document.title + window.location + $('p')",
+ webconsole: gWebConsole,
+ callback: onFooObjFetchAfterUpdate,
+ });
+}
+
+function onFooObjFetchAfterUpdate(aEvent, aVar)
+{
+ info("onFooObjFetchAfterUpdate");
+ let para = content.wrappedJSObject.document.querySelector("p");
+ let expectedValue = content.document.title + content.location + para;
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp", value: expectedValue },
+ ], { webconsole: gWebConsole }).then(onUpdatedTestPropFound);
+}
+
+function onUpdatedTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the updated |testProp| property value");
+
+ is(content.wrappedJSObject.fooObj.testProp, aResults[0].value,
+ "|fooObj.testProp| value has been updated");
+
+ // Check that property name updates work.
+ updateVariablesViewProperty({
+ property: prop,
+ field: "name",
+ string: "testUpdatedProp",
+ webconsole: gWebConsole,
+ callback: onFooObjFetchAfterPropRename,
+ });
+}
+
+function onFooObjFetchAfterPropRename(aEvent, aVar)
+{
+ info("onFooObjFetchAfterPropRename");
+
+ let para = content.wrappedJSObject.document.querySelector("p");
+ let expectedValue = content.document.title + content.location + para;
+
+ // Check that the new value is in the variables view.
+ findVariableViewProperties(aVar, [
+ { name: "testUpdatedProp", value: expectedValue },
+ ], { webconsole: gWebConsole }).then(onRenamedTestPropFound);
+}
+
+function onRenamedTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the renamed |testProp| property");
+
+ ok(!content.wrappedJSObject.fooObj.testProp,
+ "|fooObj.testProp| has been deleted");
+ is(content.wrappedJSObject.fooObj.testUpdatedProp, aResults[0].value,
+ "|fooObj.testUpdatedProp| is correct");
+
+ // Check that property value updates that cause exceptions are reported in
+ // the web console output.
+ updateVariablesViewProperty({
+ property: prop,
+ field: "value",
+ string: "foobarzFailure()",
+ webconsole: gWebConsole,
+ callback: onPropUpdateError,
+ });
+}
+
+function onPropUpdateError(aEvent, aVar)
+{
+ info("onPropUpdateError");
+
+ let para = content.wrappedJSObject.document.querySelector("p");
+ let expectedValue = content.document.title + content.location + para;
+
+ // Make sure the property did not change.
+ findVariableViewProperties(aVar, [
+ { name: "testUpdatedProp", value: expectedValue },
+ ], { webconsole: gWebConsole }).then(onRenamedTestPropFoundAgain);
+}
+
+function onRenamedTestPropFoundAgain(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the renamed |testProp| property again");
+
+ let outputNode = gWebConsole.outputNode;
+
+ waitForSuccess({
+ name: "exception in property update reported in the web console output",
+ validatorFn: () => outputNode.textContent.indexOf("foobarzFailure") != -1,
+ successFn: testPropDelete.bind(null, prop),
+ failureFn: testPropDelete.bind(null, prop),
+ });
+}
+
+function testPropDelete(aProp)
+{
+ gVariablesView.window.focus();
+ aProp.focus();
+
+ executeSoon(() => {
+ EventUtils.synthesizeKey("VK_DELETE", {}, gVariablesView.window);
+ gWebConsole = gJSTerm = gVariablesView = null;
+ });
+
+ waitForSuccess({
+ name: "property deleted",
+ validatorFn: () => !("testUpdatedProp" in content.wrappedJSObject.fooObj),
+ successFn: finishTest,
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging.js b/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging.js
new file mode 100644
index 000000000..1ff987c68
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging.js
@@ -0,0 +1,132 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test that makes sure web console eval happens in the user-selected stackframe
+// from the js debugger, when changing the value of a property in the variables
+// view.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
+
+let gWebConsole, gJSTerm, gDebuggerWin, gThread, gDebuggerController,
+ gStackframes, gVariablesView;
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ gWebConsole = hud;
+ gJSTerm = hud.jsterm;
+
+ executeSoon(() => {
+ info("openDebugger");
+ openDebugger().then(debuggerOpened);
+ });
+}
+
+function debuggerOpened(aResult)
+{
+ gDebuggerWin = aResult.panelWin;
+ gDebuggerController = gDebuggerWin.DebuggerController;
+ gThread = gDebuggerController.activeThread;
+ gStackframes = gDebuggerController.StackFrames;
+
+ executeSoon(() => {
+ gThread.addOneTimeListener("framesadded", onFramesAdded);
+
+ info("firstCall()");
+ content.wrappedJSObject.firstCall();
+ });
+}
+
+function onFramesAdded()
+{
+ info("onFramesAdded");
+
+ executeSoon(() =>
+ openConsole(null, () =>
+ gJSTerm.execute("fooObj", onExecuteFooObj)
+ )
+ );
+}
+
+
+function onExecuteFooObj()
+{
+ let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
+ ok(msg, "output message found");
+ isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
+
+ gJSTerm.once("variablesview-fetched", onFooObjFetch);
+
+ executeSoon(() => EventUtils.synthesizeMouse(msg, 2, 2, {},
+ gWebConsole.iframeWindow));
+}
+
+function onFooObjFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp2", value: "testValue2" },
+ { name: "testProp", value: "testValue", dontMatch: true },
+ ], { webconsole: gWebConsole }).then(onTestPropFound);
+}
+
+function onTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the |testProp2| property in the variables view");
+
+ // Check that property value updates work and that jsterm functions can be
+ // used.
+ updateVariablesViewProperty({
+ property: prop,
+ field: "value",
+ string: "document.title + foo2 + $('p')",
+ webconsole: gWebConsole,
+ callback: onFooObjFetchAfterUpdate,
+ });
+}
+
+function onFooObjFetchAfterUpdate(aEvent, aVar)
+{
+ info("onFooObjFetchAfterUpdate");
+ let para = content.wrappedJSObject.document.querySelector("p");
+ let expectedValue = content.document.title + "foo2SecondCall" + para;
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp2", value: expectedValue },
+ ], { webconsole: gWebConsole }).then(onUpdatedTestPropFound);
+}
+
+function onUpdatedTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the updated |testProp2| property value");
+
+ // Check that testProp2 was updated.
+ executeSoon(() => gJSTerm.execute("fooObj.testProp2", onExecuteFooObjTestProp2));
+}
+
+function onExecuteFooObjTestProp2()
+{
+ let para = content.wrappedJSObject.document.querySelector("p");
+ let expected = content.document.title + "foo2SecondCall" + para;
+
+ isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
+ "fooObj.testProp2 is correct");
+
+ gWebConsole = gJSTerm = gDebuggerWin = gThread = gDebuggerController =
+ gStackframes = gVariablesView = null;
+ executeSoon(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js b/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js
new file mode 100644
index 000000000..cecc24b72
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js
@@ -0,0 +1,127 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test that makes sure web console eval works while the js debugger paused the
+// page, and while the inspector is active. See bug 886137.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
+
+let gWebConsole, gJSTerm, gDebuggerWin, gThread, gDebuggerController,
+ gStackframes, gVariablesView;
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ gWebConsole = hud;
+ gJSTerm = hud.jsterm;
+
+ info("openDebugger");
+ openDebugger().then(debuggerOpened);
+}
+
+function debuggerOpened(aResult)
+{
+ gDebuggerWin = aResult.panelWin;
+ gDebuggerController = gDebuggerWin.DebuggerController;
+ gThread = gDebuggerController.activeThread;
+ gStackframes = gDebuggerController.StackFrames;
+
+ openInspector(inspectorOpened);
+}
+
+function inspectorOpened(aPanel)
+{
+ gThread.addOneTimeListener("framesadded", onFramesAdded);
+
+ info("firstCall()");
+ content.wrappedJSObject.firstCall();
+}
+
+function onFramesAdded()
+{
+ info("onFramesAdded");
+
+ openConsole(null, () => gJSTerm.execute("fooObj", onExecuteFooObj));
+}
+
+function onExecuteFooObj()
+{
+ let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
+ ok(msg, "output message found");
+ isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
+
+ gJSTerm.once("variablesview-fetched", onFooObjFetch);
+
+ EventUtils.synthesizeMouse(msg, 2, 2, {}, gWebConsole.iframeWindow);
+}
+
+function onFooObjFetch(aEvent, aVar)
+{
+ gVariablesView = aVar._variablesView;
+ ok(gVariablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp2", value: "testValue2" },
+ { name: "testProp", value: "testValue", dontMatch: true },
+ ], { webconsole: gWebConsole }).then(onTestPropFound);
+}
+
+function onTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the |testProp2| property in the variables view");
+
+ // Check that property value updates work and that jsterm functions can be
+ // used.
+ updateVariablesViewProperty({
+ property: prop,
+ field: "value",
+ string: "document.title + foo2 + $('p')",
+ webconsole: gWebConsole,
+ callback: onFooObjFetchAfterUpdate,
+ });
+}
+
+function onFooObjFetchAfterUpdate(aEvent, aVar)
+{
+ info("onFooObjFetchAfterUpdate");
+ let para = content.wrappedJSObject.document.querySelector("p");
+ let expectedValue = content.document.title + "foo2SecondCall" + para;
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp2", value: expectedValue },
+ ], { webconsole: gWebConsole }).then(onUpdatedTestPropFound);
+}
+
+function onUpdatedTestPropFound(aResults)
+{
+ let prop = aResults[0].matchedProp;
+ ok(prop, "matched the updated |testProp2| property value");
+
+ // Check that testProp2 was updated.
+ gJSTerm.execute("fooObj.testProp2", onExecuteFooObjTestProp2);
+}
+
+function onExecuteFooObjTestProp2()
+{
+ let para = content.wrappedJSObject.document.querySelector("p");
+ let expected = content.document.title + "foo2SecondCall" + para;
+
+ isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
+ "fooObj.testProp2 is correct");
+
+ gWebConsole = gJSTerm = gDebuggerWin = gThread = gDebuggerController =
+ gStackframes = gVariablesView = null;
+
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_eval_in_debugger_stackframe.js b/browser/devtools/webconsole/test/browser_eval_in_debugger_stackframe.js
new file mode 100644
index 000000000..4dd3d6c76
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_eval_in_debugger_stackframe.js
@@ -0,0 +1,150 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test that makes sure web console eval happens in the user-selected stackframe
+// from the js debugger.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
+
+let gWebConsole, gJSTerm, gDebuggerWin, gThread, gDebuggerController, gStackframes;
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud)
+{
+ gWebConsole = hud;
+ gJSTerm = hud.jsterm;
+ gJSTerm.execute("foo", onExecuteFoo);
+}
+
+function onExecuteFoo()
+{
+ isnot(gWebConsole.outputNode.textContent.indexOf("globalFooBug783499"), -1,
+ "|foo| value is correct");
+
+ gJSTerm.clearOutput();
+
+ // Test for Bug 690529 - Web Console and Scratchpad should evaluate
+ // expressions in the scope of the content window, not in a sandbox.
+ executeSoon(() => gJSTerm.execute("foo2 = 'newFoo'; window.foo2", onNewFoo2));
+}
+
+function onNewFoo2()
+{
+ is(gWebConsole.outputNode.textContent.indexOf("undefined"), -1,
+ "|undefined| is not displayed after adding |foo2|");
+
+ let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
+ ok(msg, "output result found");
+
+ isnot(msg.textContent.indexOf("newFoo"), -1,
+ "'newFoo' is displayed after adding |foo2|");
+
+ gJSTerm.clearOutput();
+
+ info("openDebugger");
+ executeSoon(() => openDebugger().then(debuggerOpened));
+}
+
+function debuggerOpened(aResult)
+{
+ gDebuggerWin = aResult.panelWin;
+ gDebuggerController = gDebuggerWin.DebuggerController;
+ gThread = gDebuggerController.activeThread;
+ gStackframes = gDebuggerController.StackFrames;
+
+ info("openConsole");
+ executeSoon(() =>
+ openConsole(null, () =>
+ gJSTerm.execute("foo + foo2", onExecuteFooAndFoo2)
+ )
+ );
+}
+
+function onExecuteFooAndFoo2()
+{
+ let expected = "globalFooBug783499newFoo";
+ isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
+ "|foo + foo2| is displayed after starting the debugger");
+
+ executeSoon(() => {
+ gJSTerm.clearOutput();
+
+ info("openDebugger");
+ openDebugger().then(() => {
+ gThread.addOneTimeListener("framesadded", onFramesAdded);
+
+ info("firstCall()");
+ content.wrappedJSObject.firstCall();
+ });
+ });
+}
+
+function onFramesAdded()
+{
+ info("onFramesAdded, openConsole() now");
+ executeSoon(() =>
+ openConsole(null, () =>
+ gJSTerm.execute("foo + foo2", onExecuteFooAndFoo2InSecondCall)
+ )
+ );
+}
+
+function onExecuteFooAndFoo2InSecondCall()
+{
+ let expected = "globalFooBug783499foo2SecondCall";
+ isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
+ "|foo + foo2| from |secondCall()|");
+
+ executeSoon(() => {
+ gJSTerm.clearOutput();
+
+ info("openDebugger and selectFrame(1)");
+
+ openDebugger().then(() => {
+ gStackframes.selectFrame(1);
+
+ info("openConsole");
+ executeSoon(() =>
+ openConsole(null, () =>
+ gJSTerm.execute("foo + foo2 + foo3", onExecuteFoo23InFirstCall)
+ )
+ );
+ });
+ });
+}
+
+function onExecuteFoo23InFirstCall()
+{
+ let expected = "fooFirstCallnewFoofoo3FirstCall";
+ isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
+ "|foo + foo2 + foo3| from |firstCall()|");
+
+ executeSoon(() =>
+ gJSTerm.execute("foo = 'abba'; foo3 = 'bug783499'; foo + foo3",
+ onExecuteFooAndFoo3ChangesInFirstCall));
+}
+
+function onExecuteFooAndFoo3ChangesInFirstCall()
+{
+ let expected = "abbabug783499";
+ isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
+ "|foo + foo3| updated in |firstCall()|");
+
+ is(content.wrappedJSObject.foo, "globalFooBug783499", "|foo| in content window");
+ is(content.wrappedJSObject.foo2, "newFoo", "|foo2| in content window");
+ ok(!content.wrappedJSObject.foo3, "|foo3| was not added to the content window");
+
+ gWebConsole = gJSTerm = gDebuggerWin = gThread = gDebuggerController =
+ gStackframes = null;
+ executeSoon(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_jsterm_inspect.js b/browser/devtools/webconsole/test/browser_jsterm_inspect.js
new file mode 100644
index 000000000..4dac58b34
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_jsterm_inspect.js
@@ -0,0 +1,35 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Check that the inspect() jsterm helper function works.
+
+function test()
+{
+ const TEST_URI = "data:text/html;charset=utf8,<p>hello bug 869981";
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+
+ function consoleOpened(hud)
+ {
+ content.wrappedJSObject.testProp = "testValue";
+
+ hud.jsterm.once("variablesview-fetched", onObjFetch);
+ hud.jsterm.execute("inspect(window)");
+ }
+
+ function onObjFetch(aEvent, aVar)
+ {
+ ok(aVar._variablesView, "variables view object");
+
+ findVariableViewProperties(aVar, [
+ { name: "testProp", value: "testValue" },
+ { name: "document", value: "[object HTMLDocument]" },
+ ], { webconsole: hud }).then(finishTest);
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_longstring_hang.js b/browser/devtools/webconsole/test/browser_longstring_hang.js
new file mode 100644
index 000000000..0a3600680
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_longstring_hang.js
@@ -0,0 +1,73 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that very long strings do not hang the browser.
+
+function test()
+{
+ waitForExplicitFinish();
+
+ let DebuggerServer = Cu.import("resource://gre/modules/devtools/dbg-server.jsm",
+ {}).DebuggerServer;
+
+ addTab("http://example.com/browser/browser/devtools/webconsole/test/test-bug-859170-longstring-hang.html");
+
+ let hud = null;
+
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ openConsole(null, performTest);
+ }, true);
+
+ function performTest(aHud)
+ {
+ hud = aHud;
+
+ info("wait for the initial long string");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "find 'foobar', no 'foobaz', in long string output",
+ text: "foobar",
+ noText: "foobaz",
+ category: CATEGORY_WEBDEV,
+ longString: true,
+ },
+ ],
+ }).then(onInitialString);
+ }
+
+ function onInitialString(aResults)
+ {
+ let clickable = aResults[0].longStrings[0];
+ ok(clickable, "long string ellipsis is shown");
+
+ scrollOutputToNode(clickable);
+
+ executeSoon(() => {
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
+
+ info("wait for long string expansion");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "find 'foobaz' after expand, but no 'boom!' at the end",
+ text: "foobaz",
+ noText: "boom!",
+ category: CATEGORY_WEBDEV,
+ longString: false,
+ },
+ {
+ text: "too long to be displayed",
+ longString: false,
+ },
+ ],
+ }).then(finishTest);
+ });
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_netpanel_longstring_expand.js b/browser/devtools/webconsole/test/browser_netpanel_longstring_expand.js
new file mode 100644
index 000000000..8488ad37e
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_netpanel_longstring_expand.js
@@ -0,0 +1,309 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the network panel works with LongStringActors.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+const TEST_IMG = "http://example.com/browser/browser/devtools/webconsole/test/test-image.png";
+
+const TEST_IMG_BASE64 =
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAVRJREFU" +
+ "OI2lk7FLw0AUxr+YpC1CBqcMWfsvCCLdXFzqEJCgDl1EQRGxg9AhSBEJONhFhG52UCuFDjq5dxD8" +
+ "FwoO0qGDOBQkl7vLOeWa2EQDffDBvTu+373Hu1OEEJgntGgxGD6J+7fLXKbt5VNUyhsKAChRBQcP" +
+ "FVFeWskFGH694mZroCQqCLlAwPxcgJBP254CmAD5B7C7dgHLMLF3uzoL4DQEod+Z5sP1FizDxGgy" +
+ "BqfhLID9AahX29J89bwPFgMsSEAQglAf9WobhPpScbPXr4FQHyzIADTsDizDRMPuIOC+zEeTMZo9" +
+ "BwH3EfAMACccbtfGaDKGZZg423yUZrdrg3EqxQlPr0BTdTR7joREN2uqnlBmCwW1hIJagtev4f3z" +
+ "A16/JvfiigMSYyzqJXlw/XKUyOORMUaBor6YavgdjKa8xGOnidadmwtwsnMu18q83/kHSou+bFND" +
+ "Dr4AAAAASUVORK5CYII=";
+
+let testDriver;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testNetworkPanel);
+ }, true);
+}
+
+function testNetworkPanel() {
+ testDriver = testGen();
+ testDriver.next();
+}
+
+function checkIsVisible(aPanel, aList) {
+ for (let id in aList) {
+ let node = aPanel.document.getElementById(id);
+ let isVisible = aList[id];
+ is(node.style.display, (isVisible ? "block" : "none"), id + " isVisible=" + isVisible);
+ }
+}
+
+function checkNodeContent(aPanel, aId, aContent) {
+ let node = aPanel.document.getElementById(aId);
+ if (node == null) {
+ ok(false, "Tried to access node " + aId + " that doesn't exist!");
+ }
+ else if (node.textContent.indexOf(aContent) != -1) {
+ ok(true, "checking content of " + aId);
+ }
+ else {
+ ok(false, "Got false value for " + aId + ": " + node.textContent + " doesn't have " + aContent);
+ }
+}
+
+function checkNodeKeyValue(aPanel, aId, aKey, aValue) {
+ let node = aPanel.document.getElementById(aId);
+
+ let headers = node.querySelectorAll("th");
+ for (let i = 0; i < headers.length; i++) {
+ if (headers[i].textContent == (aKey + ":")) {
+ is(headers[i].nextElementSibling.textContent, aValue,
+ "checking content of " + aId + " for key " + aKey);
+ return;
+ }
+ }
+
+ ok(false, "content check failed for " + aId + ", key " + aKey);
+}
+
+function testGen() {
+ let hud = HUDService.getHudByWindow(content);
+ let filterBox = hud.ui.filterBox;
+
+ let headerValue = (new Array(456)).join("fooz bar");
+ let headerValueGrip = {
+ type: "longString",
+ initial: headerValue.substr(0, 123),
+ length: headerValue.length,
+ actor: "faktor",
+ _fullString: headerValue,
+ };
+
+ let imageContentGrip = {
+ type: "longString",
+ initial: TEST_IMG_BASE64.substr(0, 143),
+ length: TEST_IMG_BASE64.length,
+ actor: "faktor2",
+ _fullString: TEST_IMG_BASE64,
+ };
+
+ let postDataValue = (new Array(123)).join("post me");
+ let postDataGrip = {
+ type: "longString",
+ initial: postDataValue.substr(0, 172),
+ length: postDataValue.length,
+ actor: "faktor3",
+ _fullString: postDataValue,
+ };
+
+ let httpActivity = {
+ updates: ["responseContent", "eventTimings"],
+ discardRequestBody: false,
+ discardResponseBody: false,
+ startedDateTime: (new Date()).toISOString(),
+ request: {
+ url: TEST_IMG,
+ method: "GET",
+ cookies: [],
+ headers: [
+ { name: "foo", value: "bar" },
+ { name: "loongstring", value: headerValueGrip },
+ ],
+ postData: { text: postDataGrip },
+ },
+ response: {
+ httpVersion: "HTTP/3.14",
+ status: 2012,
+ statusText: "ddahl likes tacos :)",
+ headers: [
+ { name: "Content-Type", value: "image/png" },
+ ],
+ content: { mimeType: "image/png", text: imageContentGrip },
+ cookies: [],
+ },
+ timings: { wait: 15, receive: 23 },
+ };
+
+ let networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+
+ is(filterBox._netPanel, networkPanel,
+ "Network panel stored on the anchor object");
+
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ info("test 1: check if a header value is expandable");
+
+ checkIsVisible(networkPanel, {
+ requestCookie: false,
+ requestFormData: false,
+ requestBody: false,
+ requestBodyFetchLink: true,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: true,
+ responseImageCached: false,
+ responseBodyFetchLink: true,
+ });
+
+ checkNodeKeyValue(networkPanel, "requestHeadersContent", "foo", "bar");
+ checkNodeKeyValue(networkPanel, "requestHeadersContent", "loongstring",
+ headerValueGrip.initial + "[\u2026]");
+
+ let webConsoleClient = networkPanel.webconsole.webConsoleClient;
+ let longStringFn = webConsoleClient.longString;
+
+ let expectedGrip = headerValueGrip;
+
+ function longStringClientProvider(aLongString)
+ {
+ is(aLongString, expectedGrip,
+ "longString grip is correct");
+
+ return {
+ initial: expectedGrip.initial,
+ length: expectedGrip.length,
+ substring: function(aStart, aEnd, aCallback) {
+ is(aStart, expectedGrip.initial.length,
+ "substring start is correct");
+ is(aEnd, expectedGrip.length,
+ "substring end is correct");
+
+ executeSoon(function() {
+ aCallback({
+ substring: expectedGrip._fullString.substring(aStart, aEnd),
+ });
+
+ executeSoon(function() {
+ testDriver.next();
+ });
+ });
+ },
+ };
+ }
+
+ webConsoleClient.longString = longStringClientProvider;
+
+ let clickable = networkPanel.document
+ .querySelector("#requestHeadersContent .longStringEllipsis");
+ ok(clickable, "long string ellipsis is shown");
+
+ EventUtils.sendMouseEvent({ type: "mousedown"}, clickable,
+ networkPanel.document.defaultView);
+
+ yield;
+
+ clickable = networkPanel.document
+ .querySelector("#requestHeadersContent .longStringEllipsis");
+ ok(!clickable, "long string ellipsis is not shown");
+
+ checkNodeKeyValue(networkPanel, "requestHeadersContent", "loongstring",
+ expectedGrip._fullString);
+
+ info("test 2: check that response body image fetching works");
+ expectedGrip = imageContentGrip;
+
+ let imgNode = networkPanel.document.getElementById("responseImageNode");
+ ok(!imgNode.getAttribute("src"), "no image is displayed");
+
+ clickable = networkPanel.document.querySelector("#responseBodyFetchLink");
+ EventUtils.sendMouseEvent({ type: "mousedown"}, clickable,
+ networkPanel.document.defaultView);
+
+ yield;
+
+ imgNode = networkPanel.document.getElementById("responseImageNode");
+ is(imgNode.getAttribute("src"), "data:image/png;base64," + TEST_IMG_BASE64,
+ "displayed image is correct");
+ is(clickable.style.display, "none", "#responseBodyFetchLink is not visible");
+
+ info("test 3: expand the request body");
+
+ expectedGrip = postDataGrip;
+
+ clickable = networkPanel.document.querySelector("#requestBodyFetchLink");
+ EventUtils.sendMouseEvent({ type: "mousedown"}, clickable,
+ networkPanel.document.defaultView);
+ yield;
+
+ is(clickable.style.display, "none", "#requestBodyFetchLink is not visible");
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestBodyFetchLink: false,
+ });
+
+ checkNodeContent(networkPanel, "requestBodyContent", expectedGrip._fullString);
+
+ webConsoleClient.longString = longStringFn;
+
+ networkPanel.panel.hidePopup();
+
+ info("test 4: reponse body long text");
+
+ httpActivity.response.content.mimeType = "text/plain";
+ httpActivity.response.headers[0].value = "text/plain";
+
+ expectedGrip = imageContentGrip;
+
+ // Reset response.content.text to avoid caching of the full string.
+ httpActivity.response.content.text = expectedGrip;
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ is(filterBox._netPanel, networkPanel,
+ "Network panel stored on httpActivity object");
+
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestCookie: false,
+ requestFormData: false,
+ requestBody: true,
+ requestBodyFetchLink: false,
+ responseContainer: true,
+ responseBody: true,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false,
+ responseBodyFetchLink: true,
+ });
+
+ checkNodeContent(networkPanel, "responseBodyContent", expectedGrip.initial);
+
+ webConsoleClient.longString = longStringClientProvider;
+
+ clickable = networkPanel.document.querySelector("#responseBodyFetchLink");
+ EventUtils.sendMouseEvent({ type: "mousedown"}, clickable,
+ networkPanel.document.defaultView);
+
+ yield;
+
+ webConsoleClient.longString = longStringFn;
+ is(clickable.style.display, "none", "#responseBodyFetchLink is not visible");
+ checkNodeContent(networkPanel, "responseBodyContent", expectedGrip._fullString);
+
+ networkPanel.panel.hidePopup();
+
+ // All done!
+ testDriver = null;
+ executeSoon(finishTest);
+
+ yield;
+}
diff --git a/browser/devtools/webconsole/test/browser_output_breaks_after_console_dir_uninspectable.js b/browser/devtools/webconsole/test/browser_output_breaks_after_console_dir_uninspectable.js
new file mode 100644
index 000000000..935a13932
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_output_breaks_after_console_dir_uninspectable.js
@@ -0,0 +1,56 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Make sure that the Web Console output does not break after we try to call
+// console.dir() for objects that are not inspectable.
+
+function test()
+{
+ waitForExplicitFinish();
+
+ addTab("data:text/html;charset=utf8,test for bug 773466");
+
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ openConsole(null, performTest);
+ }, true);
+}
+
+function performTest(hud)
+{
+ hud.jsterm.clearOutput(true);
+
+ hud.jsterm.execute("console.log('fooBug773466a')");
+ hud.jsterm.execute("myObj = Object.create(null)");
+ hud.jsterm.execute("console.dir(myObj)");
+ waitForSuccess({
+ name: "eval results are shown",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(".webconsole-msg-inspector");
+ },
+ successFn: function()
+ {
+ isnot(hud.outputNode.textContent.indexOf("fooBug773466a"), -1,
+ "fooBug773466a shows");
+ ok(hud.outputNode.querySelector(".webconsole-msg-inspector"),
+ "the console.dir() tree shows");
+
+ content.console.log("fooBug773466b");
+
+ waitForSuccess(waitForAnotherConsoleLogCall);
+ },
+ failureFn: finishTest,
+ });
+
+ let waitForAnotherConsoleLogCall = {
+ name: "eval result after console.dir()",
+ validatorFn: function()
+ {
+ return hud.outputNode.textContent.indexOf("fooBug773466b") > -1;
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ };
+}
diff --git a/browser/devtools/webconsole/test/browser_output_longstring_expand.js b/browser/devtools/webconsole/test/browser_output_longstring_expand.js
new file mode 100644
index 000000000..014c6d2bd
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_output_longstring_expand.js
@@ -0,0 +1,153 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that long strings can be expanded in the console output.
+
+function test()
+{
+ waitForExplicitFinish();
+
+ let tempScope = {};
+ Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
+ let DebuggerServer = tempScope.DebuggerServer;
+
+ let longString = (new Array(DebuggerServer.LONG_STRING_LENGTH + 4)).join("a") +
+ "foobar";
+ let initialString =
+ longString.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH);
+
+ addTab("data:text/html;charset=utf8,test for bug 787981 - check that long strings can be expanded in the output.");
+
+ let hud = null;
+
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ openConsole(null, performTest);
+ }, true);
+
+ function performTest(aHud)
+ {
+ hud = aHud;
+
+ hud.jsterm.clearOutput(true);
+ hud.jsterm.execute("console.log('bazbaz', '" + longString +"', 'boom')");
+
+ waitForSuccess(waitForConsoleLog);
+ }
+
+ let waitForConsoleLog = {
+ name: "console.log output shown",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(".webconsole-msg-console");
+ },
+ successFn: function()
+ {
+ let msg = hud.outputNode.querySelector(".webconsole-msg-console");
+ is(msg.textContent.indexOf("foobar"), -1,
+ "foobar is not shown");
+ isnot(msg.textContent.indexOf("bazbaz"), -1,
+ "bazbaz is shown");
+ isnot(msg.textContent.indexOf("boom"), -1,
+ "boom is shown");
+ isnot(msg.textContent.indexOf(initialString), -1,
+ "initial string is shown");
+
+ let clickable = msg.querySelector(".longStringEllipsis");
+ ok(clickable, "long string ellipsis is shown");
+
+ scrollToVisible(clickable);
+
+ executeSoon(function() {
+ EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
+ waitForSuccess(waitForFullString);
+ });
+ },
+ failureFn: finishTest,
+ };
+
+ let waitForFullString = {
+ name: "full string shown",
+ validatorFn: function()
+ {
+ let msg = hud.outputNode.querySelector(".webconsole-msg-log");
+ return msg.textContent.indexOf(longString) > -1;
+ },
+ successFn: function()
+ {
+ let msg = hud.outputNode.querySelector(".webconsole-msg-log");
+ isnot(msg.textContent.indexOf("bazbaz"), -1,
+ "bazbaz is shown");
+ isnot(msg.textContent.indexOf("boom"), -1,
+ "boom is shown");
+
+ let clickable = msg.querySelector(".longStringEllipsis");
+ ok(!clickable, "long string ellipsis is not shown");
+
+ executeSoon(function() {
+ hud.jsterm.clearOutput(true);
+ hud.jsterm.execute("'" + longString +"'");
+ waitForSuccess(waitForExecute);
+ });
+ },
+ failureFn: finishTest,
+ };
+
+ let waitForExecute = {
+ name: "execute() output shown",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ let msg = hud.outputNode.querySelector(".webconsole-msg-output");
+ isnot(msg.textContent.indexOf(initialString), -1,
+ "initial string is shown");
+ is(msg.textContent.indexOf(longString), -1,
+ "full string is not shown");
+
+ let clickable = msg.querySelector(".longStringEllipsis");
+ ok(clickable, "long string ellipsis is shown");
+
+ scrollToVisible(clickable);
+
+ executeSoon(function() {
+ EventUtils.synthesizeMouse(clickable, 3, 4, {}, hud.iframeWindow);
+ waitForSuccess(waitForFullStringAfterExecute);
+ });
+ },
+ failureFn: finishTest,
+ };
+
+ let waitForFullStringAfterExecute = {
+ name: "full string shown again",
+ validatorFn: function()
+ {
+ let msg = hud.outputNode.querySelector(".webconsole-msg-output");
+ return msg.textContent.indexOf(longString) > -1;
+ },
+ successFn: function()
+ {
+ let msg = hud.outputNode.querySelector(".webconsole-msg-output");
+ let clickable = msg.querySelector(".longStringEllipsis");
+ ok(!clickable, "long string ellipsis is not shown");
+
+ executeSoon(finishTest);
+ },
+ failureFn: finishTest,
+ };
+
+ function scrollToVisible(aNode)
+ {
+ let richListBoxNode = aNode.parentNode;
+ while (richListBoxNode.tagName != "richlistbox") {
+ richListBoxNode = richListBoxNode.parentNode;
+ }
+
+ let boxObject = richListBoxNode.scrollBoxObject;
+ let nsIScrollBoxObject = boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+ nsIScrollBoxObject.ensureElementIsVisible(aNode);
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_repeated_messages_accuracy.js b/browser/devtools/webconsole/test/browser_repeated_messages_accuracy.js
new file mode 100644
index 000000000..753257c19
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_repeated_messages_accuracy.js
@@ -0,0 +1,120 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that makes sure messages are not considered repeated when coming from
+// different lines of code, or from different severities, etc.
+// See bugs 720180 and 800510.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-repeated-messages.html";
+
+function test() {
+ const PREF = "devtools.webconsole.persistlog";
+ Services.prefs.setBoolPref(PREF, true);
+ registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud) {
+ // Check that css warnings are not coalesced if they come from different lines.
+ info("waiting for 2 css warnings");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ name: "two css warnings",
+ category: CATEGORY_CSS,
+ count: 2,
+ repeats: 1,
+ }],
+ }).then(testCSSRepeats.bind(null, hud));
+}
+
+function testCSSRepeats(hud) {
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ info("wait for repeats after page reload");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ name: "two css warnings, repeated twice",
+ category: CATEGORY_CSS,
+ repeats: 2,
+ count: 2,
+ }],
+ }).then(testCSSRepeatsAfterReload.bind(null, hud));
+ }, true);
+ content.location.reload();
+}
+
+function testCSSRepeatsAfterReload(hud) {
+ hud.jsterm.clearOutput(true);
+ content.wrappedJSObject.testConsole();
+
+ info("wait for repeats with the console API");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "console.log 'foo repeat' repeated twice",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ repeats: 2,
+ },
+ {
+ name: "console.log 'foo repeat' repeated once",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ repeats: 1,
+ },
+ {
+ name: "console.error 'foo repeat' repeated once",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_ERROR,
+ repeats: 1,
+ },
+ ],
+ }).then(testConsoleRepeats.bind(null, hud));
+}
+
+function testConsoleRepeats(hud) {
+ hud.jsterm.clearOutput(true);
+ hud.jsterm.execute("undefined");
+ content.console.log("undefined");
+
+ info("make sure console API messages are not coalesced with jsterm output");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "'undefined' jsterm input message",
+ text: "undefined",
+ category: CATEGORY_INPUT,
+ repeats: 1,
+ },
+ {
+ name: "'undefined' jsterm output message",
+ text: "undefined",
+ category: CATEGORY_OUTPUT,
+ repeats: 1,
+ },
+ {
+ name: "'undefined' console.log message",
+ text: "undefined",
+ category: CATEGORY_WEBDEV,
+ repeats: 1,
+ },
+ ],
+ }).then(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_result_format_as_string.js b/browser/devtools/webconsole/test/browser_result_format_as_string.js
new file mode 100644
index 000000000..c887fb309
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_result_format_as_string.js
@@ -0,0 +1,49 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Make sure that JS eval result are properly formatted as strings.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-result-format-as-string.html";
+
+function test()
+{
+ waitForExplicitFinish();
+
+ addTab(TEST_URI);
+
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ openConsole(null, performTest);
+ }, true);
+}
+
+function performTest(hud)
+{
+ hud.jsterm.clearOutput(true);
+
+ hud.jsterm.execute("document.querySelector('p')");
+ waitForSuccess({
+ name: "eval result shown",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ is(hud.outputNode.textContent.indexOf("bug772506_content"), -1,
+ "no content element found");
+ ok(!hud.outputNode.querySelector("div"), "no div element found");
+
+ let msg = hud.outputNode.querySelector(".webconsole-msg-output");
+ ok(msg, "eval output node found");
+ is(msg.textContent.indexOf("HTMLDivElement"), -1,
+ "HTMLDivElement string not displayed");
+ EventUtils.synthesizeMouseAtCenter(msg, {type: "mousemove"});
+ ok(!gBrowser._bug772506, "no content variable");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js b/browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js
new file mode 100644
index 000000000..42e011339
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_warn_user_about_replaced_api.js
@@ -0,0 +1,79 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_REPLACED_API_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-replaced-api.html";
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/testscript.js";
+
+function test() {
+ waitForExplicitFinish();
+
+ const PREF = "devtools.webconsole.persistlog";
+ Services.prefs.setBoolPref(PREF, true);
+ registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
+
+ // First test that the warning does not appear on a page that doesn't override
+ // the window.console object.
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testWarningNotPresent);
+ }, true);
+
+ function testWarningNotPresent(hud)
+ {
+ is(hud.outputNode.textContent.indexOf("logging API"), -1,
+ "no warning displayed");
+
+ // Bug 862024: make sure the warning doesn't show after page reload.
+ info("reload " + TEST_URI);
+ executeSoon(() => content.location.reload());
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "testscript.js",
+ category: CATEGORY_NETWORK,
+ }],
+ }).then(() => executeSoon(() => {
+ is(hud.outputNode.textContent.indexOf("logging API"), -1,
+ "no warning displayed");
+
+ closeConsole(null, loadTestPage);
+ }));
+ }
+
+ function loadTestPage()
+ {
+ info("load test " + TEST_REPLACED_API_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testWarningPresent);
+ }, true);
+ content.location = TEST_REPLACED_API_URI;
+ }
+
+ function testWarningPresent(hud)
+ {
+ info("wait for the warning to show");
+ let warning = {
+ webconsole: hud,
+ messages: [{
+ text: /logging API .+ disabled by a script/,
+ category: CATEGORY_JS,
+ severity: SEVERITY_WARNING,
+ }],
+ };
+
+ waitForMessages(warning).then(() => {
+ hud.jsterm.clearOutput();
+
+ executeSoon(() => {
+ info("reload the test page and wait for the warning to show");
+ waitForMessages(warning).then(finishTest);
+ content.location.reload();
+ });
+ });
+ }
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_abbreviate_source_url.js b/browser/devtools/webconsole/test/browser_webconsole_abbreviate_source_url.js
new file mode 100644
index 000000000..1bc94b5d3
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_abbreviate_source_url.js
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that source URLs are abbreviated properly for display on the right-
+// hand side of the Web Console.
+
+function test() {
+ testAbbreviation("http://example.com/x.js", "x.js");
+ testAbbreviation("http://example.com/foo/bar/baz/boo.js", "boo.js");
+ testAbbreviation("http://example.com/foo/bar/", "bar");
+ testAbbreviation("http://example.com/foo.js?bar=1&baz=2", "foo.js");
+ testAbbreviation("http://example.com/foo/?bar=1&baz=2", "foo");
+
+ finishTest();
+}
+
+function testAbbreviation(aFullURL, aAbbreviatedURL) {
+ is(WebConsoleUtils.abbreviateSourceURL(aFullURL), aAbbreviatedURL, aFullURL +
+ " is abbreviated to " + aAbbreviatedURL);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_basic_net_logging.js b/browser/devtools/webconsole/test/browser_webconsole_basic_net_logging.js
new file mode 100644
index 000000000..c35cbd7d5
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_basic_net_logging.js
@@ -0,0 +1,45 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the page's resources are displayed in the console as they're
+// loaded
+
+const TEST_NETWORK_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-network.html" + "?_date=" + Date.now();
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console basic network logging test");
+ browser.addEventListener("load", onLoad, true);
+}
+
+function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, function() {
+ browser.addEventListener("load", testBasicNetLogging, true);
+ content.location = TEST_NETWORK_URI;
+ });
+}
+
+function testBasicNetLogging(aEvent) {
+ browser.removeEventListener(aEvent.type, testBasicNetLogging, true);
+
+ outputNode = HUDService.getHudByWindow(content).outputNode;
+
+ waitForSuccess({
+ name: "network console message",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("running network console") > -1;
+ },
+ successFn: function()
+ {
+ findLogEntry("test-network.html");
+ findLogEntry("testscript.js");
+ findLogEntry("test-image.png");
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_578437_page_reload.js b/browser/devtools/webconsole/test/browser_webconsole_bug_578437_page_reload.js
new file mode 100644
index 000000000..2c6e294fd
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_578437_page_reload.js
@@ -0,0 +1,38 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the console object still exists after a page reload.
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("DOMContentLoaded", onLoad, false);
+}
+
+function onLoad() {
+ browser.removeEventListener("DOMContentLoaded", onLoad, false);
+
+ openConsole();
+
+ browser.addEventListener("DOMContentLoaded", testPageReload, false);
+ content.location.reload();
+}
+
+function testPageReload() {
+
+ browser.removeEventListener("DOMContentLoaded", testPageReload, false);
+
+ let console = browser.contentWindow.wrappedJSObject.console;
+
+ is(typeof console, "object", "window.console is an object, after page reload");
+ is(typeof console.log, "function", "console.log is a function");
+ is(typeof console.info, "function", "console.info is a function");
+ is(typeof console.warn, "function", "console.warn is a function");
+ is(typeof console.error, "function", "console.error is a function");
+ is(typeof console.exception, "function", "console.exception is a function");
+
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_579412_input_focus.js b/browser/devtools/webconsole/test/browser_webconsole_bug_579412_input_focus.js
new file mode 100644
index 000000000..d13a97fe0
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_579412_input_focus.js
@@ -0,0 +1,25 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the input field is focused when the console is opened.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("DOMContentLoaded", testInputFocus, false);
+}
+
+function testInputFocus() {
+ browser.removeEventListener("DOMContentLoaded", testInputFocus, false);
+
+ openConsole(null, function(hud) {
+ let inputNode = hud.jsterm.inputNode;
+ ok(inputNode.getAttribute("focused"), "input node is focused");
+
+ finishTest();
+ });
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_580001_closing_after_completion.js b/browser/devtools/webconsole/test/browser_webconsole_bug_580001_closing_after_completion.js
new file mode 100644
index 000000000..86a9d8ff8
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580001_closing_after_completion.js
@@ -0,0 +1,44 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests to ensure that errors don't appear when the console is closed while a
+// completion is being performed.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testClosingAfterCompletion);
+ }, true);
+}
+
+function testClosingAfterCompletion(hud) {
+ let inputNode = hud.jsterm.inputNode;
+
+ let errorWhileClosing = false;
+ function errorListener(evt) {
+ errorWhileClosing = true;
+ }
+
+ browser.addEventListener("error", errorListener, false);
+
+ // Focus the inputNode and perform the keycombo to close the WebConsole.
+ inputNode.focus();
+
+ gDevTools.once("toolbox-destroyed", function() {
+ browser.removeEventListener("error", errorListener, false);
+ is(errorWhileClosing, false, "no error while closing the WebConsole");
+ finishTest();
+ });
+
+ if (Services.appinfo.OS == "Darwin") {
+ EventUtils.synthesizeKey("k", { accelKey: true, altKey: true });
+ } else {
+ EventUtils.synthesizeKey("k", { accelKey: true, shiftKey: true });
+ }
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js b/browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js
new file mode 100644
index 000000000..bc325d9ce
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580030_errors_after_page_reload.js
@@ -0,0 +1,67 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that errors still show up in the Web Console after a page reload.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-error.html";
+
+function test() {
+ expectUncaughtException();
+ addTab(TEST_URI);
+ browser.addEventListener("load", onLoad, true);
+}
+
+// see bug 580030: the error handler fails silently after page reload.
+// https://bugzilla.mozilla.org/show_bug.cgi?id=580030
+function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+
+ openConsole(null, function(hud) {
+ hud.jsterm.clearOutput();
+ browser.addEventListener("load", testErrorsAfterPageReload, true);
+ content.location.reload();
+ });
+}
+
+function testErrorsAfterPageReload(aEvent) {
+ browser.removeEventListener(aEvent.type, testErrorsAfterPageReload, true);
+
+ // dispatch a click event to the button in the test page and listen for
+ // errors.
+
+ Services.console.registerListener(consoleObserver);
+
+ let button = content.document.querySelector("button").wrappedJSObject;
+ ok(button, "button found");
+ EventUtils.sendMouseEvent({type: "click"}, button, content.wrappedJSObject);
+}
+
+var consoleObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function test_observe(aMessage)
+ {
+ // Ignore errors we don't care about.
+ if (!(aMessage instanceof Ci.nsIScriptError) ||
+ aMessage.category != "content javascript") {
+ return;
+ }
+
+ Services.console.unregisterListener(this);
+
+ let outputNode = HUDService.getHudByWindow(content).outputNode;
+
+ waitForSuccess({
+ name: "error message after page reload",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("fooBazBaz") > -1;
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ });
+ }
+};
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js b/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js
new file mode 100644
index 000000000..33fdc6e9e
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js
@@ -0,0 +1,78 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that console groups behave properly.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testGroups);
+ }, true);
+}
+
+function testGroups(HUD) {
+ let jsterm = HUD.jsterm;
+ let outputNode = HUD.outputNode;
+ jsterm.clearOutput();
+
+ // We test for one group by testing for zero "new" groups. The
+ // "webconsole-new-group" class creates a divider. Thus one group is
+ // indicated by zero new groups, two groups are indicated by one new group,
+ // and so on.
+
+ let waitForSecondMessage = {
+ name: "second console message",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".webconsole-msg-output").length == 2;
+ },
+ successFn: function()
+ {
+ let timestamp1 = Date.now();
+ if (timestamp1 - timestamp0 < 5000) {
+ is(outputNode.querySelectorAll(".webconsole-new-group").length, 0,
+ "no group dividers exist after the second console message");
+ }
+
+ for (let i = 0; i < outputNode.itemCount; i++) {
+ outputNode.getItemAtIndex(i).timestamp = 0; // a "far past" value
+ }
+
+ jsterm.execute("2");
+ waitForSuccess(waitForThirdMessage);
+ },
+ failureFn: finishTest,
+ };
+
+ let waitForThirdMessage = {
+ name: "one group divider exists after the third console message",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".webconsole-new-group").length == 1;
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ };
+
+ let timestamp0 = Date.now();
+ jsterm.execute("0");
+
+ waitForSuccess({
+ name: "no group dividers exist after the first console message",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".webconsole-new-group").length == 0;
+ },
+ successFn: function()
+ {
+ jsterm.execute("1");
+ waitForSuccess(waitForSecondMessage);
+ },
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_580454_timestamp_l10n.js b/browser/devtools/webconsole/test/browser_webconsole_bug_580454_timestamp_l10n.js
new file mode 100644
index 000000000..d1c9487c3
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580454_timestamp_l10n.js
@@ -0,0 +1,36 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that appropriately-localized timestamps are printed.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("DOMContentLoaded", testTimestamp, false);
+
+ function testTimestamp()
+ {
+ browser.removeEventListener("DOMContentLoaded", testTimestamp, false);
+ const TEST_TIMESTAMP = 12345678;
+ let date = new Date(TEST_TIMESTAMP);
+ let localizedString = WCU_l10n.timestampString(TEST_TIMESTAMP);
+ isnot(localizedString.indexOf(date.getHours()), -1, "the localized " +
+ "timestamp contains the hours");
+ isnot(localizedString.indexOf(date.getMinutes()), -1, "the localized " +
+ "timestamp contains the minutes");
+ isnot(localizedString.indexOf(date.getSeconds()), -1, "the localized " +
+ "timestamp contains the seconds");
+ isnot(localizedString.indexOf(date.getMilliseconds()), -1, "the localized " +
+ "timestamp contains the milliseconds");
+ finishTest();
+ }
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js b/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js
new file mode 100644
index 000000000..154799370
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js
@@ -0,0 +1,68 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that exceptions thrown by content don't show up twice in the Web
+// Console.
+
+const TEST_DUPLICATE_ERROR_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-duplicate-error.html";
+
+function test() {
+ expectUncaughtException();
+ addTab(TEST_DUPLICATE_ERROR_URI);
+ browser.addEventListener("DOMContentLoaded", testDuplicateErrors, false);
+}
+
+function testDuplicateErrors() {
+ browser.removeEventListener("DOMContentLoaded", testDuplicateErrors,
+ false);
+ openConsole(null, function(hud) {
+ hud.jsterm.clearOutput();
+
+ Services.console.registerListener(consoleObserver);
+
+ expectUncaughtException();
+ content.location.reload();
+ });
+}
+
+var consoleObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function (aMessage)
+ {
+ // we ignore errors we don't care about
+ if (!(aMessage instanceof Ci.nsIScriptError) ||
+ aMessage.category != "content javascript") {
+ return;
+ }
+
+ Services.console.unregisterListener(this);
+
+ outputNode = HUDService.getHudByWindow(content).outputNode;
+
+ waitForSuccess({
+ name: "fooDuplicateError1 error displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("fooDuplicateError1") > -1;
+ },
+ successFn: function()
+ {
+ let text = outputNode.textContent;
+ let error1pos = text.indexOf("fooDuplicateError1");
+ ok(error1pos > -1, "found fooDuplicateError1");
+ if (error1pos > -1) {
+ ok(text.indexOf("fooDuplicateError1", error1pos + 1) == -1,
+ "no duplicate for fooDuplicateError1");
+ }
+
+ findLogEntry("test-duplicate-error.html");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+ }
+};
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js b/browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js
new file mode 100644
index 000000000..ceeac816d
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js
@@ -0,0 +1,35 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testCompletion);
+ }, true);
+}
+
+function testCompletion(hud) {
+ var jsterm = hud.jsterm;
+ var input = jsterm.inputNode;
+
+ jsterm.setInputValue("");
+ EventUtils.synthesizeKey("VK_TAB", {});
+ is(jsterm.completeNode.value, "<- no result", "<- no result - matched");
+ is(input.value, "", "inputnode is empty - matched")
+ is(input.getAttribute("focused"), "true", "input is still focused");
+
+ //Any thing which is not in property autocompleter
+ jsterm.setInputValue("window.Bug583816");
+ EventUtils.synthesizeKey("VK_TAB", {});
+ is(jsterm.completeNode.value, " <- no result", "completenode content - matched");
+ is(input.value, "window.Bug583816", "inputnode content - matched");
+ is(input.getAttribute("focused"), "true", "input is still focused");
+
+ jsterm = input = null;
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js b/browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js
new file mode 100644
index 000000000..1f142ce74
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585237_line_limit.js
@@ -0,0 +1,109 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that the Web Console limits the number of lines displayed according to
+// the user's preferences.
+
+const TEST_URI = "data:text/html;charset=utf8,test for bug 585237";
+let hud, testDriver;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ testDriver = testGen();
+ testNext();
+ });
+ }, true);
+}
+
+function testNext() {
+ testDriver.next();
+}
+
+function testGen() {
+ let console = content.console;
+ outputNode = hud.outputNode;
+
+ hud.jsterm.clearOutput();
+
+ let prefBranch = Services.prefs.getBranch("devtools.hud.loglimit.");
+ prefBranch.setIntPref("console", 20);
+
+ for (let i = 0; i < 30; i++) {
+ console.log("foo #" + i); // must change message to prevent repeats
+ }
+
+ waitForSuccess({
+ name: "20 console.log messages displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("foo #29") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ is(countMessageNodes(), 20, "there are 20 message nodes in the output " +
+ "when the log limit is set to 20");
+
+ console.log("bar bug585237");
+
+ waitForSuccess({
+ name: "another console.log message displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bar bug585237") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ is(countMessageNodes(), 20, "there are still 20 message nodes in the " +
+ "output when adding one more");
+
+ prefBranch.setIntPref("console", 30);
+ for (let i = 0; i < 20; i++) {
+ console.log("boo #" + i); // must change message to prevent repeats
+ }
+
+ waitForSuccess({
+ name: "another 20 console.log message displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("boo #19") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ is(countMessageNodes(), 30, "there are 30 message nodes in the output " +
+ "when the log limit is set to 30");
+
+ prefBranch.clearUserPref("console");
+ hud = testDriver = prefBranch = console = outputNode = null;
+ finishTest();
+
+ yield;
+}
+
+function countMessageNodes() {
+ return outputNode.querySelectorAll(".hud-msg-node").length;
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js b/browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js
new file mode 100644
index 000000000..a062ebd99
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585956_console_trace.js
@@ -0,0 +1,50 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-585956-console-trace.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", tabLoaded, true);
+}
+
+function tabLoaded() {
+ browser.removeEventListener("load", tabLoaded, true);
+
+ openConsole(null, function(hud) {
+ content.location.reload();
+
+ waitForSuccess({
+ name: "stacktrace message",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(".hud-log");
+ },
+ successFn: performChecks,
+ failureFn: finishTest,
+ });
+ });
+}
+
+function performChecks() {
+ // The expected stack trace object.
+ let stacktrace = [
+ { filename: TEST_URI, lineNumber: 9, functionName: "window.foobar585956c", language: 2 },
+ { filename: TEST_URI, lineNumber: 14, functionName: "foobar585956b", language: 2 },
+ { filename: TEST_URI, lineNumber: 18, functionName: "foobar585956a", language: 2 },
+ { filename: TEST_URI, lineNumber: 21, functionName: null, language: 2 }
+ ];
+
+ let hudId = HUDService.getHudIdByWindow(content);
+ let HUD = HUDService.hudReferences[hudId];
+
+ let node = HUD.outputNode.querySelector(".hud-log");
+ ok(node, "found trace log node");
+ ok(node._stacktrace, "found stacktrace object");
+ is(node._stacktrace.toSource(), stacktrace.toSource(), "stacktrace is correct");
+ isnot(node.textContent.indexOf("bug-585956"), -1, "found file name");
+
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js b/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
new file mode 100644
index 000000000..21dcc603b
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
@@ -0,0 +1,283 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>bug 585991 - autocomplete popup keyboard usage test";
+let HUD, popup, jsterm, inputNode, completeNode;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(aHud) {
+ HUD = aHud;
+ info("web console opened");
+
+ content.wrappedJSObject.foobarBug585991 = {
+ "item0": "value0",
+ "item1": "value1",
+ "item2": "value2",
+ "item3": "value3",
+ };
+
+ jsterm = HUD.jsterm;
+ popup = jsterm.autocompletePopup;
+ completeNode = jsterm.completeNode;
+ inputNode = jsterm.inputNode;
+
+ ok(!popup.isOpen, "popup is not open");
+
+ popup._panel.addEventListener("popupshown", function onShown() {
+ popup._panel.removeEventListener("popupshown", onShown, false);
+
+ ok(popup.isOpen, "popup is open");
+
+ // 4 values, and the following properties:
+ // __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__
+ // hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString
+ // toSource unwatch valueOf watch constructor.
+ is(popup.itemCount, 18, "popup.itemCount is correct");
+
+ let sameItems = popup.getItems().reverse().map(function(e) {return e.label;});
+ ok(sameItems.every(function(prop, index) {
+ return [
+ "__defineGetter__",
+ "__defineSetter__",
+ "__lookupGetter__",
+ "__lookupSetter__",
+ "constructor",
+ "hasOwnProperty",
+ "isPrototypeOf",
+ "item0",
+ "item1",
+ "item2",
+ "item3",
+ "propertyIsEnumerable",
+ "toLocaleString",
+ "toSource",
+ "toString",
+ "unwatch",
+ "valueOf",
+ "watch",
+ ][index] === prop}), "getItems returns the items we expect");
+
+ is(popup.selectedIndex, 17,
+ "Index of the first item from bottom is selected.");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ let prefix = jsterm.inputNode.value.replace(/[\S]/g, " ");
+
+ is(popup.selectedIndex, 0, "index 0 is selected");
+ is(popup.selectedItem.label, "watch", "watch is selected");
+ is(completeNode.value, prefix + "watch",
+ "completeNode.value holds watch");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(popup.selectedIndex, 1, "index 1 is selected");
+ is(popup.selectedItem.label, "valueOf", "valueOf is selected");
+ is(completeNode.value, prefix + "valueOf",
+ "completeNode.value holds valueOf");
+
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(popup.selectedIndex, 0, "index 0 is selected");
+ is(popup.selectedItem.label, "watch", "watch is selected");
+ is(completeNode.value, prefix + "watch",
+ "completeNode.value holds watch");
+
+ info("press Tab and wait for popup to hide");
+ popup._panel.addEventListener("popuphidden", popupHideAfterTab, false);
+ EventUtils.synthesizeKey("VK_TAB", {});
+ }, false);
+
+ info("wait for completion: window.foobarBug585991.");
+ jsterm.setInputValue("window.foobarBug585991");
+ EventUtils.synthesizeKey(".", {});
+}
+
+function popupHideAfterTab()
+{
+ // At this point the completion suggestion should be accepted.
+ popup._panel.removeEventListener("popuphidden", popupHideAfterTab, false);
+
+ ok(!popup.isOpen, "popup is not open");
+
+ is(inputNode.value, "window.foobarBug585991.watch",
+ "completion was successful after VK_TAB");
+
+ ok(!completeNode.value, "completeNode is empty");
+
+ popup._panel.addEventListener("popupshown", function onShown() {
+ popup._panel.removeEventListener("popupshown", onShown, false);
+
+ ok(popup.isOpen, "popup is open");
+
+ is(popup.itemCount, 18, "popup.itemCount is correct");
+
+ is(popup.selectedIndex, 17, "First index from bottom is selected");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ let prefix = jsterm.inputNode.value.replace(/[\S]/g, " ");
+
+ is(popup.selectedIndex, 0, "index 0 is selected");
+ is(popup.selectedItem.label, "watch", "watch is selected");
+ is(completeNode.value, prefix + "watch",
+ "completeNode.value holds watch");
+
+ popup._panel.addEventListener("popuphidden", function onHidden() {
+ popup._panel.removeEventListener("popuphidden", onHidden, false);
+
+ ok(!popup.isOpen, "popup is not open after VK_ESCAPE");
+
+ is(inputNode.value, "window.foobarBug585991.",
+ "completion was cancelled");
+
+ ok(!completeNode.value, "completeNode is empty");
+
+ executeSoon(testReturnKey);
+ }, false);
+
+ info("press Escape to close the popup");
+ executeSoon(function() {
+ EventUtils.synthesizeKey("VK_ESCAPE", {});
+ });
+ }, false);
+
+ info("wait for completion: window.foobarBug585991.");
+ executeSoon(function() {
+ jsterm.setInputValue("window.foobarBug585991");
+ EventUtils.synthesizeKey(".", {});
+ });
+}
+
+function testReturnKey()
+{
+ popup._panel.addEventListener("popupshown", function onShown() {
+ popup._panel.removeEventListener("popupshown", onShown, false);
+
+ ok(popup.isOpen, "popup is open");
+
+ is(popup.itemCount, 18, "popup.itemCount is correct");
+
+ is(popup.selectedIndex, 17, "First index from bottom is selected");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ let prefix = jsterm.inputNode.value.replace(/[\S]/g, " ");
+
+ is(popup.selectedIndex, 0, "index 0 is selected");
+ is(popup.selectedItem.label, "watch", "watch is selected");
+ is(completeNode.value, prefix + "watch",
+ "completeNode.value holds watch");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(popup.selectedIndex, 1, "index 1 is selected");
+ is(popup.selectedItem.label, "valueOf", "valueOf is selected");
+ is(completeNode.value, prefix + "valueOf",
+ "completeNode.value holds valueOf");
+
+ popup._panel.addEventListener("popuphidden", function onHidden() {
+ popup._panel.removeEventListener("popuphidden", onHidden, false);
+
+ ok(!popup.isOpen, "popup is not open after VK_RETURN");
+
+ is(inputNode.value, "window.foobarBug585991.valueOf",
+ "completion was successful after VK_RETURN");
+
+ ok(!completeNode.value, "completeNode is empty");
+
+ dontShowArrayNumbers();
+ }, false);
+
+ info("press Return to accept suggestion. wait for popup to hide");
+
+ executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {}));
+ }, false);
+
+ info("wait for completion suggestions: window.foobarBug585991.");
+
+ executeSoon(function() {
+ jsterm.setInputValue("window.foobarBug58599");
+ EventUtils.synthesizeKey("1", {});
+ EventUtils.synthesizeKey(".", {});
+ });
+}
+
+function dontShowArrayNumbers()
+{
+ info("dontShowArrayNumbers");
+ content.wrappedJSObject.foobarBug585991 = ["Sherlock Holmes"];
+
+ let jsterm = HUD.jsterm;
+ let popup = jsterm.autocompletePopup;
+ let completeNode = jsterm.completeNode;
+
+ popup._panel.addEventListener("popupshown", function onShown() {
+ popup._panel.removeEventListener("popupshown", onShown, false);
+
+ let sameItems = popup.getItems().map(function(e) {return e.label;});
+ ok(!sameItems.some(function(prop, index) { prop === "0"; }),
+ "Completing on an array doesn't show numbers.");
+
+ popup._panel.addEventListener("popuphidden", testReturnWithNoSelection, false);
+
+ info("wait for popup to hide");
+ executeSoon(() => EventUtils.synthesizeKey("VK_ESCAPE", {}));
+ }, false);
+
+ info("wait for popup to show");
+ executeSoon(() => {
+ jsterm.setInputValue("window.foobarBug585991");
+ EventUtils.synthesizeKey(".", {});
+ });
+}
+
+function testReturnWithNoSelection()
+{
+ popup._panel.removeEventListener("popuphidden", testReturnWithNoSelection, false);
+
+ info("test pressing return with open popup, but no selection, see bug 873250");
+ content.wrappedJSObject.testBug873250a = "hello world";
+ content.wrappedJSObject.testBug873250b = "hello world 2";
+
+ popup._panel.addEventListener("popupshown", function onShown() {
+ popup._panel.removeEventListener("popupshown", onShown);
+
+ ok(popup.isOpen, "popup is open");
+ is(popup.itemCount, 2, "popup.itemCount is correct");
+ isnot(popup.selectedIndex, -1, "popup.selectedIndex is correct");
+
+ info("press Return and wait for popup to hide");
+ popup._panel.addEventListener("popuphidden", popupHideAfterReturnWithNoSelection);
+ executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {}));
+ });
+
+ executeSoon(() => {
+ info("wait for popup to show");
+ jsterm.setInputValue("window.testBu");
+ EventUtils.synthesizeKey("g", {});
+ });
+}
+
+function popupHideAfterReturnWithNoSelection()
+{
+ popup._panel.removeEventListener("popuphidden", popupHideAfterReturnWithNoSelection);
+
+ ok(!popup.isOpen, "popup is not open after VK_RETURN");
+
+ is(inputNode.value, "", "inputNode is empty after VK_RETURN");
+ is(completeNode.value, "", "completeNode is empty");
+ is(jsterm.history[jsterm.history.length-1], "window.testBug",
+ "jsterm history is correct");
+
+ executeSoon(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js b/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js
new file mode 100644
index 000000000..eb9134b4a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js
@@ -0,0 +1,95 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>bug 585991 - autocomplete popup test";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(HUD) {
+ let items = [
+ {label: "item0", value: "value0"},
+ {label: "item1", value: "value1"},
+ {label: "item2", value: "value2"},
+ ];
+
+ let popup = HUD.jsterm.autocompletePopup;
+
+ ok(!popup.isOpen, "popup is not open");
+
+ popup._panel.addEventListener("popupshown", function() {
+ popup._panel.removeEventListener("popupshown", arguments.callee, false);
+
+ ok(popup.isOpen, "popup is open");
+
+ is(popup.itemCount, 0, "no items");
+
+ popup.setItems(items);
+
+ is(popup.itemCount, items.length, "items added");
+
+ let sameItems = popup.getItems();
+ is(sameItems.every(function(aItem, aIndex) {
+ return aItem === items[aIndex];
+ }), true, "getItems returns back the same items");
+
+ is(popup.selectedIndex, 2,
+ "Index of the first item from bottom is selected.");
+ is(popup.selectedItem, items[2], "First item from bottom is selected");
+
+ popup.selectedIndex = 1;
+
+ is(popup.selectedIndex, 1, "index 1 is selected");
+ is(popup.selectedItem, items[1], "item1 is selected");
+
+ popup.selectedItem = items[2];
+
+ is(popup.selectedIndex, 2, "index 2 is selected");
+ is(popup.selectedItem, items[2], "item2 is selected");
+
+ is(popup.selectPreviousItem(), items[1], "selectPreviousItem() works");
+
+ is(popup.selectedIndex, 1, "index 1 is selected");
+ is(popup.selectedItem, items[1], "item1 is selected");
+
+ is(popup.selectNextItem(), items[2], "selectPreviousItem() works");
+
+ is(popup.selectedIndex, 2, "index 2 is selected");
+ is(popup.selectedItem, items[2], "item2 is selected");
+
+ ok(!popup.selectNextItem(), "selectPreviousItem() works");
+
+ is(popup.selectedIndex, -1, "no index is selected");
+ ok(!popup.selectedItem, "no item is selected");
+
+ items.push({label: "label3", value: "value3"});
+ popup.appendItem(items[3]);
+
+ is(popup.itemCount, items.length, "item3 appended");
+
+ popup.selectedIndex = 3;
+ is(popup.selectedItem, items[3], "item3 is selected");
+
+ popup.removeItem(items[2]);
+
+ is(popup.selectedIndex, 2, "index2 is selected");
+ is(popup.selectedItem, items[3], "item3 is still selected");
+ is(popup.itemCount, items.length - 1, "item2 removed");
+
+ popup.clearItems();
+ is(popup.itemCount, 0, "items cleared");
+
+ popup.hidePopup();
+ finishTest();
+ }, false);
+
+ popup.openPopup();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js b/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js
new file mode 100644
index 000000000..b5bba5003
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js
@@ -0,0 +1,81 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testSelectionWhenMovingBetweenBoxes);
+ }, true);
+}
+
+function testSelectionWhenMovingBetweenBoxes(hud) {
+ let jsterm = hud.jsterm;
+
+ // Fill the console with some output.
+ jsterm.clearOutput();
+ jsterm.execute("1 + 2");
+ jsterm.execute("3 + 4");
+ jsterm.execute("5 + 6");
+
+ waitForSuccess({
+ name: "execution results displayed",
+ validatorFn: function()
+ {
+ return hud.outputNode.textContent.indexOf("5 + 6") > -1 &&
+ hud.outputNode.textContent.indexOf("11") > -1;
+ },
+ successFn: performTestsAfterOutput.bind(null, hud),
+ failureFn: finishTest,
+ });
+}
+
+function performTestsAfterOutput(hud) {
+ let outputNode = hud.outputNode;
+
+ ok(outputNode.childNodes.length >= 3, "the output node has children after " +
+ "executing some JavaScript");
+
+ // Test that the global Firefox "Select All" functionality (e.g. Edit >
+ // Select All) works properly in the Web Console.
+ let commandController = hud.ui._commandController;
+ ok(commandController != null, "the window has a command controller object");
+
+ commandController.selectAll(outputNode);
+ is(outputNode.selectedCount, outputNode.childNodes.length, "all console " +
+ "messages are selected after performing a regular browser select-all " +
+ "operation");
+
+ outputNode.selectedIndex = -1;
+
+ // Test the context menu "Select All" (which has a different code path) works
+ // properly as well.
+ let contextMenuId = outputNode.getAttribute("context");
+ let contextMenu = hud.ui.document.getElementById(contextMenuId);
+ ok(contextMenu != null, "the output node has a context menu");
+
+ let selectAllItem = contextMenu.querySelector("*[command='cmd_selectAll']");
+ ok(selectAllItem != null,
+ "the context menu on the output node has a \"Select All\" item");
+
+ outputNode.focus();
+
+ selectAllItem.doCommand();
+
+ is(outputNode.selectedCount, outputNode.childNodes.length, "all console " +
+ "messages are selected after performing a select-all operation from " +
+ "the context menu");
+
+ outputNode.selectedIndex = -1;
+
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js b/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js
new file mode 100644
index 000000000..8ad4a4b70
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js
@@ -0,0 +1,91 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let HUD, outputNode;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(aHud) {
+ HUD = aHud;
+
+ // See bugs 574036, 586386 and 587617.
+ outputNode = HUD.outputNode;
+ let selection = getSelection();
+ let jstermInput = HUD.jsterm.inputNode;
+ let console = content.wrappedJSObject.console;
+ let contentSelection = content.wrappedJSObject.getSelection();
+
+ HUD.jsterm.clearOutput();
+
+ let controller = top.document.commandDispatcher.
+ getControllerForCommand("cmd_copy");
+ is(controller.isCommandEnabled("cmd_copy"), false, "cmd_copy is disabled");
+
+ console.log("Hello world! bug587617");
+
+ waitForSuccess({
+ name: "console log 'Hello world!' message",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bug587617") > -1;
+ },
+ successFn: function()
+ {
+ outputNode.selectedIndex = 0;
+ outputNode.focus();
+
+ goUpdateCommand("cmd_copy");
+ controller = top.document.commandDispatcher.
+ getControllerForCommand("cmd_copy");
+ is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
+ let selectedNode = outputNode.getItemAtIndex(0);
+ waitForClipboard(getExpectedClipboardText(selectedNode), clipboardSetup,
+ testContextMenuCopy, testContextMenuCopy);
+ },
+ failureFn: finishTest,
+ });
+}
+
+// Test that the context menu "Copy" (which has a different code path) works
+// properly as well.
+function testContextMenuCopy() {
+ let contextMenuId = outputNode.getAttribute("context");
+ let contextMenu = HUD.ui.document.getElementById(contextMenuId);
+ ok(contextMenu, "the output node has a context menu");
+
+ let copyItem = contextMenu.querySelector("*[command='cmd_copy']");
+ ok(copyItem, "the context menu on the output node has a \"Copy\" item");
+
+ copyItem.doCommand();
+
+ let selectedNode = outputNode.getItemAtIndex(0);
+
+ HUD = outputNode = null;
+ waitForClipboard(getExpectedClipboardText(selectedNode), clipboardSetup,
+ finishTest, finishTest);
+}
+
+function getExpectedClipboardText(aItem) {
+ return "[" + WCU_l10n.timestampString(aItem.timestamp) + "] " +
+ aItem.clipboardText;
+}
+
+function clipboardSetup() {
+ goDoCommand("cmd_copy");
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_588342_document_focus.js b/browser/devtools/webconsole/test/browser_webconsole_bug_588342_document_focus.js
new file mode 100644
index 000000000..a27c64b02
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_588342_document_focus.js
@@ -0,0 +1,39 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 588342";
+let fm;
+
+function test() {
+ fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud) {
+ waitForFocus(function() {
+ is(hud.jsterm.inputNode.getAttribute("focused"), "true",
+ "jsterm input is focused on web console open");
+ isnot(fm.focusedWindow, content, "content document has no focus");
+ closeConsole(null, consoleClosed);
+ }, hud.iframeWindow);
+}
+
+function consoleClosed() {
+ is(fm.focusedWindow, browser.contentWindow,
+ "content document has focus");
+
+ fm = null;
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js b/browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js
new file mode 100644
index 000000000..74f56aa77
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_588730_text_node_insertion.js
@@ -0,0 +1,49 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that adding text to one of the output labels doesn't cause errors.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testTextNodeInsertion);
+ }, true);
+}
+
+// Test for bug 588730: Adding a text node to an existing label element causes
+// warnings
+function testTextNodeInsertion(hud) {
+ let outputNode = hud.outputNode;
+
+ let label = document.createElementNS(
+ "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "label");
+ outputNode.appendChild(label);
+
+ let error = false;
+ let listener = {
+ observe: function(aMessage) {
+ let messageText = aMessage.message;
+ if (messageText.indexOf("JavaScript Warning") !== -1) {
+ error = true;
+ }
+ }
+ };
+
+ Services.console.registerListener(listener);
+
+ // This shouldn't fail.
+ label.appendChild(document.createTextNode("foo"));
+
+ executeSoon(function() {
+ Services.console.unregisterListener(listener);
+ ok(!error, "no error when adding text nodes as children of labels");
+
+ finishTest();
+ });
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_588967_input_expansion.js b/browser/devtools/webconsole/test/browser_webconsole_bug_588967_input_expansion.js
new file mode 100644
index 000000000..c22894924
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_588967_input_expansion.js
@@ -0,0 +1,44 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testInputExpansion);
+ }, true);
+}
+
+function testInputExpansion(hud) {
+ let input = hud.jsterm.inputNode;
+
+ input.focus();
+
+ is(input.getAttribute("multiline"), "true", "multiline is enabled");
+
+ let ordinaryHeight = input.clientHeight;
+
+ // Tests if the inputNode expands.
+ input.value = "hello\nworld\n";
+ let length = input.value.length;
+ input.selectionEnd = length;
+ input.selectionStart = length;
+ // Performs an "d". This will trigger/test for the input event that should
+ // change the height of the inputNode.
+ EventUtils.synthesizeKey("d", {});
+ ok(input.clientHeight > ordinaryHeight, "the input expanded");
+
+ // Test if the inputNode shrinks again.
+ input.value = "";
+ EventUtils.synthesizeKey("d", {});
+ is(input.clientHeight, ordinaryHeight, "the input's height is normal again");
+
+ input = length = null;
+
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_589162_css_filter.js b/browser/devtools/webconsole/test/browser_webconsole_bug_589162_css_filter.js
new file mode 100644
index 000000000..95e032f99
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_589162_css_filter.js
@@ -0,0 +1,62 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "data:text/html;charset=utf-8,<div style='font-size:3em;" +
+ "foobarCssParser:baz'>test CSS parser filter</div>";
+
+function onContentLoaded()
+{
+ browser.removeEventListener("load", onContentLoaded, true);
+
+ let HUD = HUDService.getHudByWindow(content);
+ let hudId = HUD.hudId;
+ let outputNode = HUD.outputNode;
+
+ HUD.jsterm.clearOutput();
+
+ waitForSuccess({
+ name: "css error displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("foobarCssParser") > -1;
+ },
+ successFn: function()
+ {
+ HUD.setFilterState("cssparser", false);
+
+ let msg = "the unknown CSS property warning is not displayed, " +
+ "after filtering";
+ testLogEntry(outputNode, "foobarCssParser", msg, true, true);
+
+ HUD.setFilterState("cssparser", true);
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+}
+
+/**
+ * Unit test for bug 589162:
+ * CSS filtering on the console does not work
+ */
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function() {
+ browser.addEventListener("load", onContentLoaded, true);
+ content.location.reload();
+ });
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_592442_closing_brackets.js b/browser/devtools/webconsole/test/browser_webconsole_bug_592442_closing_brackets.js
new file mode 100644
index 000000000..fbea54e9d
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_592442_closing_brackets.js
@@ -0,0 +1,41 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Julian Viereck <jviereck@mozilla.com>
+ * Patrick Walton <pcwalton@mozilla.com>
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that, when the user types an extraneous closing bracket, no error
+// appears.
+
+function test() {
+ addTab("data:text/html;charset=utf-8,test for bug 592442");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testExtraneousClosingBrackets);
+ }, true);
+}
+
+function testExtraneousClosingBrackets(hud) {
+ let jsterm = hud.jsterm;
+
+ jsterm.setInputValue("document.getElementById)");
+
+ let error = false;
+ try {
+ jsterm.complete(jsterm.COMPLETE_HINT_ONLY);
+ }
+ catch (ex) {
+ error = true;
+ }
+
+ ok(!error, "no error was thrown when an extraneous bracket was inserted");
+
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js b/browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js
new file mode 100644
index 000000000..9fe88e128
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_593003_iframe_wrong_hud.js
@@ -0,0 +1,75 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud.html";
+
+const TEST_IFRAME_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud-iframe.html";
+
+const TEST_DUMMY_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let tab1, tab2;
+
+function test() {
+ addTab(TEST_URI);
+ tab1 = tab;
+ browser.addEventListener("load", tab1Loaded, true);
+}
+
+function tab1Loaded(aEvent) {
+ browser.removeEventListener(aEvent.type, tab1Loaded, true);
+ content.console.log("FOO");
+ openConsole(null, function() {
+ tab2 = gBrowser.addTab(TEST_DUMMY_URI);
+ gBrowser.selectedTab = tab2;
+ gBrowser.selectedBrowser.addEventListener("load", tab2Loaded, true);
+ });
+}
+
+function tab2Loaded(aEvent) {
+ tab2.linkedBrowser.removeEventListener(aEvent.type, tab2Loaded, true);
+
+ openConsole(gBrowser.selectedTab, function() {
+ tab1.linkedBrowser.addEventListener("load", tab1Reloaded, true);
+ tab1.linkedBrowser.contentWindow.location.reload();
+ });
+}
+
+function tab1Reloaded(aEvent) {
+ tab1.linkedBrowser.removeEventListener(aEvent.type, tab1Reloaded, true);
+
+ let hud1 = HUDService.getHudByWindow(tab1.linkedBrowser.contentWindow);
+ let outputNode1 = hud1.outputNode;
+
+ waitForSuccess({
+ name: "iframe network request displayed in tab1",
+ validatorFn: function()
+ {
+ let selector = ".webconsole-msg-url[value='" + TEST_IFRAME_URI +"']";
+ return outputNode1.querySelector(selector);
+ },
+ successFn: function()
+ {
+ let hud2 = HUDService.getHudByWindow(tab2.linkedBrowser.contentWindow);
+ let outputNode2 = hud2.outputNode;
+
+ isnot(outputNode1, outputNode2,
+ "the two HUD outputNodes must be different");
+
+ let msg = "Didn't find the iframe network request in tab2";
+ testLogEntry(outputNode2, TEST_IFRAME_URI, msg, true, true);
+
+ testEnd();
+ },
+ failureFn: testEnd,
+ });
+}
+
+function testEnd() {
+ closeConsole(tab2, function() {
+ gBrowser.removeTab(tab2);
+ tab1 = tab2 = null;
+ executeSoon(finishTest);
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_594477_clickable_output.js b/browser/devtools/webconsole/test/browser_webconsole_bug_594477_clickable_output.js
new file mode 100644
index 000000000..c2dc7f753
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_594477_clickable_output.js
@@ -0,0 +1,132 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+let HUD;
+
+let outputItem;
+
+function consoleOpened(aHud) {
+ HUD = aHud;
+
+ outputNode = HUD.outputNode;
+
+ browser.addEventListener("load", tabLoad2, true);
+
+ // Reload so we get some output in the console.
+ browser.contentWindow.location.reload();
+}
+
+function tabLoad2(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoad2, true);
+
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ text: "test-console.html",
+ category: CATEGORY_NETWORK,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(([result]) => {
+ let msg = [...result.matched][0];
+ outputItem = msg.querySelector(".hud-clickable");
+ ok(outputItem, "found a network message");
+ document.addEventListener("popupshown", networkPanelShown, false);
+
+ // Send the mousedown and click events such that the network panel opens.
+ EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
+ EventUtils.sendMouseEvent({type: "click"}, outputItem);
+ });
+}
+
+function networkPanelShown(aEvent) {
+ document.removeEventListener(aEvent.type, networkPanelShown, false);
+
+ info("networkPanelShown");
+
+ document.addEventListener("popupshown", networkPanelShowFailure, false);
+
+ // The network panel should not open for the second time.
+ EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
+ EventUtils.sendMouseEvent({type: "click"}, outputItem);
+
+ executeSoon(function() {
+ aEvent.target.addEventListener("popuphidden", networkPanelHidden, false);
+ aEvent.target.hidePopup();
+ });
+}
+
+function networkPanelShowFailure(aEvent) {
+ document.removeEventListener(aEvent.type, networkPanelShowFailure, false);
+
+ ok(false, "the network panel should not show");
+}
+
+function networkPanelHidden(aEvent) {
+ this.removeEventListener(aEvent.type, networkPanelHidden, false);
+
+ info("networkPanelHidden");
+
+ // The network panel should not show because this is a mouse event that starts
+ // in a position and ends in another.
+ EventUtils.sendMouseEvent({type: "mousedown", clientX: 3, clientY: 4},
+ outputItem);
+ EventUtils.sendMouseEvent({type: "click", clientX: 5, clientY: 6},
+ outputItem);
+
+ // The network panel should not show because this is a middle-click.
+ EventUtils.sendMouseEvent({type: "mousedown", button: 1},
+ outputItem);
+ EventUtils.sendMouseEvent({type: "click", button: 1},
+ outputItem);
+
+ // The network panel should not show because this is a right-click.
+ EventUtils.sendMouseEvent({type: "mousedown", button: 2},
+ outputItem);
+ EventUtils.sendMouseEvent({type: "click", button: 2},
+ outputItem);
+
+ executeSoon(function() {
+ document.removeEventListener("popupshown", networkPanelShowFailure, false);
+
+ // Done with the network output. Now test the jsterm output and the property
+ // panel.
+ HUD.jsterm.execute("document", () => {
+ info("jsterm execute 'document' callback");
+
+ HUD.jsterm.once("variablesview-open", onVariablesViewOpen);
+ let outputItem = outputNode
+ .querySelector(".webconsole-msg-output .hud-clickable");
+ ok(outputItem, "jsterm output message found");
+
+ // Send the mousedown and click events such that the property panel opens.
+ EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
+ EventUtils.sendMouseEvent({type: "click"}, outputItem);
+ });
+ });
+}
+
+function onVariablesViewOpen() {
+ info("onVariablesViewOpen");
+
+ executeSoon(function() {
+ HUD = outputItem = null;
+ executeSoon(finishTest);
+ });
+}
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_594497_history_arrow_keys.js b/browser/devtools/webconsole/test/browser_webconsole_bug_594497_history_arrow_keys.js
new file mode 100644
index 000000000..2cdf52bc9
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_594497_history_arrow_keys.js
@@ -0,0 +1,157 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let inputNode, values;
+
+function tabLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoad, true);
+
+ openConsole(null, function(HUD) {
+ inputNode = HUD.jsterm.inputNode;
+
+ inputNode.focus();
+
+ ok(!inputNode.value, "inputNode.value is empty");
+
+ values = ["document", "window", "document.body"];
+ values.push(values.join(";\n"), "document.location");
+
+ // Execute each of the values;
+ for (let i = 0; i < values.length; i++) {
+ HUD.jsterm.setInputValue(values[i]);
+ HUD.jsterm.execute();
+ }
+
+ performTests();
+ });
+}
+
+function performTests() {
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(inputNode.value, values[4],
+ "VK_UP: inputNode.value #4 is correct");
+
+ ok(inputNode.selectionStart == values[4].length &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(inputNode.value, values[3],
+ "VK_UP: inputNode.value #3 is correct");
+
+ ok(inputNode.selectionStart == values[3].length &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ inputNode.setSelectionRange(values[3].length - 2, values[3].length - 2);
+
+ EventUtils.synthesizeKey("VK_UP", {});
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(inputNode.value, values[3],
+ "VK_UP two times: inputNode.value #3 is correct");
+
+ ok(inputNode.selectionStart == inputNode.value.indexOf("\n") &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(inputNode.value, values[3],
+ "VK_UP again: inputNode.value #3 is correct");
+
+ ok(inputNode.selectionStart == 0 &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(inputNode.value, values[2],
+ "VK_UP: inputNode.value #2 is correct");
+
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(inputNode.value, values[1],
+ "VK_UP: inputNode.value #1 is correct");
+
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(inputNode.value, values[0],
+ "VK_UP: inputNode.value #0 is correct");
+
+ ok(inputNode.selectionStart == values[0].length &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(inputNode.value, values[1],
+ "VK_DOWN: inputNode.value #1 is correct");
+
+ ok(inputNode.selectionStart == values[1].length &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(inputNode.value, values[2],
+ "VK_DOWN: inputNode.value #2 is correct");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(inputNode.value, values[3],
+ "VK_DOWN: inputNode.value #3 is correct");
+
+ ok(inputNode.selectionStart == values[3].length &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ inputNode.setSelectionRange(2, 2);
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(inputNode.value, values[3],
+ "VK_DOWN two times: inputNode.value #3 is correct");
+
+ ok(inputNode.selectionStart > inputNode.value.lastIndexOf("\n") &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(inputNode.value, values[3],
+ "VK_DOWN again: inputNode.value #3 is correct");
+
+ ok(inputNode.selectionStart == values[3].length &&
+ inputNode.selectionStart == inputNode.selectionEnd,
+ "caret location is correct");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ is(inputNode.value, values[4],
+ "VK_DOWN: inputNode.value #4 is correct");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+
+ ok(!inputNode.value,
+ "VK_DOWN: inputNode.value is empty");
+
+ inputNode = values = null;
+ executeSoon(finishTest);
+}
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 594497 and bug 619598");
+ browser.addEventListener("load", tabLoad, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_595223_file_uri.js b/browser/devtools/webconsole/test/browser_webconsole_bug_595223_file_uri.js
new file mode 100644
index 000000000..7fe96922e
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595223_file_uri.js
@@ -0,0 +1,54 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_FILE = "test-network.html";
+
+function tabReload(aEvent) {
+ browser.removeEventListener(aEvent.type, tabReload, true);
+
+ outputNode = hud.outputNode;
+
+ waitForSuccess({
+ name: "console.log() message displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent
+ .indexOf("running network console logging tests") > -1;
+ },
+ successFn: function()
+ {
+ findLogEntry("test-network.html");
+ findLogEntry("test-image.png");
+ findLogEntry("testscript.js");
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+}
+
+function test() {
+ let jar = getJar(getRootDirectory(gTestPath));
+ let dir = jar ?
+ extractJarToTmp(jar) :
+ getChromeDir(getResolvedURI(gTestPath));
+ dir.append(TEST_FILE);
+
+ let uri = Services.io.newFileURI(dir);
+
+ const PREF = "devtools.webconsole.persistlog";
+ Services.prefs.setBoolPref(PREF, true);
+ registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
+
+ addTab("data:text/html;charset=utf8,<p>test file URI");
+ browser.addEventListener("load", function tabLoad() {
+ browser.removeEventListener("load", tabLoad, true);
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ hud.jsterm.clearOutput();
+ browser.addEventListener("load", tabReload, true);
+ content.location = uri.spec;
+ });
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js b/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js
new file mode 100644
index 000000000..a1c96b9c1
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js
@@ -0,0 +1,101 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that the Web Console doesn't leak when multiple tabs and windows are
+// opened and then closed.
+
+const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 595350";
+
+let win1 = window, win2;
+let openTabs = [];
+let loadedTabCount = 0;
+
+function test() {
+ requestLongerTimeout(3);
+
+ // Add two tabs in the main window.
+ addTabs(win1);
+
+ // Open a new window.
+ win2 = OpenBrowserWindow();
+ win2.addEventListener("load", onWindowLoad, true);
+}
+
+function onWindowLoad(aEvent) {
+ win2.removeEventListener(aEvent.type, onWindowLoad, true);
+
+ // Add two tabs in the new window.
+ addTabs(win2);
+}
+
+function addTabs(aWindow) {
+ for (let i = 0; i < 2; i++) {
+ let tab = aWindow.gBrowser.addTab(TEST_URI);
+ openTabs.push(tab);
+
+ tab.linkedBrowser.addEventListener("load", function onLoad(aEvent) {
+ tab.linkedBrowser.removeEventListener(aEvent.type, onLoad, true);
+
+ loadedTabCount++;
+ info("tabs loaded: " + loadedTabCount);
+ if (loadedTabCount >= 4) {
+ executeSoon(openConsoles);
+ }
+ }, true);
+ }
+}
+
+function openConsoles() {
+ // open the Web Console for each of the four tabs and log a message.
+ let consolesOpen = 0;
+ for (let i = 0; i < openTabs.length; i++) {
+ let tab = openTabs[i];
+ openConsole(tab, function(index, hud) {
+ ok(hud, "HUD is open for tab " + index);
+ let window = hud.target.tab.linkedBrowser.contentWindow;
+ window.console.log("message for tab " + index);
+ consolesOpen++;
+ if (consolesOpen == 4) {
+ // Use executeSoon() to allow the promise to resolve.
+ executeSoon(closeConsoles);
+ }
+ }.bind(null, i));
+ }
+}
+
+function closeConsoles() {
+ let consolesClosed = 0;
+
+ function onWebConsoleClose(aSubject, aTopic) {
+ if (aTopic == "web-console-destroyed") {
+ consolesClosed++;
+ info("consoles destroyed: " + consolesClosed);
+ if (consolesClosed == 4) {
+ // Use executeSoon() to allow all the observers to execute.
+ executeSoon(finishTest);
+ }
+ }
+ }
+
+ Services.obs.addObserver(onWebConsoleClose, "web-console-destroyed", false);
+
+ registerCleanupFunction(() => {
+ Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed");
+ });
+
+ win2.close();
+
+ win1.gBrowser.removeTab(openTabs[0]);
+ win1.gBrowser.removeTab(openTabs[1]);
+
+ openTabs = win1 = win2 = null;
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
new file mode 100644
index 000000000..8e00c27ed
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
@@ -0,0 +1,209 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TESTS_PATH = "http://example.com/browser/browser/devtools/webconsole/test/";
+const TESTS = [
+ { // #0
+ file: "test-bug-595934-css-loader.html",
+ category: "CSS Loader",
+ matchString: "text/css",
+ },
+ { // #1
+ file: "test-bug-595934-imagemap.html",
+ category: "ImageMap",
+ matchString: "shape=\"rect\"",
+ },
+ { // #2
+ file: "test-bug-595934-html.html",
+ category: "HTML",
+ matchString: "multipart/form-data",
+ onload: function() {
+ let form = content.document.querySelector("form");
+ form.submit();
+ },
+ },
+ { // #3
+ file: "test-bug-595934-workers.html",
+ category: "Web Worker",
+ matchString: "fooBarWorker",
+ expectError: true,
+ },
+ { // #4
+ file: "test-bug-595934-malformedxml.xhtml",
+ category: "malformed-xml",
+ matchString: "no element found",
+ },
+ { // #5
+ file: "test-bug-595934-svg.xhtml",
+ category: "SVG",
+ matchString: "fooBarSVG",
+ },
+ { // #6
+ file: "test-bug-595934-canvas.html",
+ category: "Canvas",
+ matchString: "strokeStyle",
+ },
+ { // #7
+ file: "test-bug-595934-css-parser.html",
+ category: "CSS Parser",
+ matchString: "foobarCssParser",
+ },
+ { // #8
+ file: "test-bug-595934-malformedxml-external.html",
+ category: "malformed-xml",
+ matchString: "</html>",
+ },
+ { // #9
+ file: "test-bug-595934-empty-getelementbyid.html",
+ category: "DOM",
+ matchString: "getElementById",
+ },
+ { // #10
+ file: "test-bug-595934-canvas-css.html",
+ category: "CSS Parser",
+ matchString: "foobarCanvasCssParser",
+ },
+ { // #11
+ file: "test-bug-595934-image.html",
+ category: "Image",
+ matchString: "corrupt",
+ },
+];
+
+let pos = -1;
+
+let foundCategory = false;
+let foundText = false;
+let pageLoaded = false;
+let pageError = false;
+let output = null;
+let jsterm = null;
+let hud = null;
+let testEnded = false;
+
+let TestObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function test_observe(aSubject)
+ {
+ if (testEnded || !(aSubject instanceof Ci.nsIScriptError)) {
+ return;
+ }
+
+ var expectedCategory = TESTS[pos].category;
+
+ info("test #" + pos + " console observer got " + aSubject.category +
+ ", is expecting " + expectedCategory);
+
+ if (aSubject.category == expectedCategory) {
+ foundCategory = true;
+ startNextTest();
+ }
+ else {
+ info("unexpected message was: " + aSubject.sourceName + ":" +
+ aSubject.lineNumber + "; " + aSubject.errorMessage);
+ }
+ }
+};
+
+function consoleOpened(aHud) {
+ hud = aHud;
+ output = hud.outputNode;
+ jsterm = hud.jsterm;
+
+ Services.console.registerListener(TestObserver);
+
+ registerCleanupFunction(testEnd);
+
+ testNext();
+}
+
+function testNext() {
+ jsterm.clearOutput();
+ foundCategory = false;
+ foundText = false;
+ pageLoaded = false;
+ pageError = false;
+
+ pos++;
+ info("testNext: #" + pos);
+ if (pos < TESTS.length) {
+ let test = TESTS[pos];
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ name: "message for test #" + pos + ": '" + test.matchString +"'",
+ text: test.matchString,
+ }],
+ }).then(() => {
+ foundText = true;
+ startNextTest();
+ });
+
+ let testLocation = TESTS_PATH + test.file;
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad(aEvent) {
+ if (content.location.href != testLocation) {
+ return;
+ }
+ gBrowser.selectedBrowser.removeEventListener(aEvent.type, onLoad, true);
+
+ pageLoaded = true;
+ test.onload && test.onload(aEvent);
+
+ if (test.expectError) {
+ content.addEventListener("error", function _onError() {
+ content.removeEventListener("error", _onError);
+ pageError = true;
+ startNextTest();
+ });
+ expectUncaughtException();
+ }
+ else {
+ pageError = true;
+ }
+
+ startNextTest();
+ }, true);
+
+ content.location = testLocation;
+ }
+ else {
+ testEnded = true;
+ finishTest();
+ }
+}
+
+function testEnd() {
+ if (!testEnded) {
+ info("foundCategory " + foundCategory + " foundText " + foundText +
+ " pageLoaded " + pageLoaded + " pageError " + pageError);
+ }
+
+ Services.console.unregisterListener(TestObserver);
+ hud = TestObserver = output = jsterm = null;
+}
+
+function startNextTest() {
+ if (!testEnded && foundCategory && foundText && pageLoaded && pageError) {
+ testNext();
+ }
+}
+
+function test() {
+ requestLongerTimeout(2);
+
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 595934 - message categories coverage.");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js
new file mode 100644
index 000000000..aab5058c9
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js
@@ -0,0 +1,106 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let tab1, tab2, win1, win2;
+let noErrors = true;
+
+function tab1Loaded(aEvent) {
+ browser.removeEventListener(aEvent.type, tab1Loaded, true);
+
+ win2 = OpenBrowserWindow();
+ whenDelayedStartupFinished(win2, win2Loaded);
+}
+
+function win2Loaded() {
+ tab2 = win2.gBrowser.addTab(TEST_URI);
+ win2.gBrowser.selectedTab = tab2;
+ tab2.linkedBrowser.addEventListener("load", tab2Loaded, true);
+}
+
+function tab2Loaded(aEvent) {
+ tab2.linkedBrowser.removeEventListener(aEvent.type, tab2Loaded, true);
+
+ let consolesOpened = 0;
+ function onWebConsoleOpen() {
+ consolesOpened++;
+ if (consolesOpened == 2) {
+ executeSoon(closeConsoles);
+ }
+ }
+
+ function openConsoles() {
+ try {
+ let target1 = TargetFactory.forTab(tab1);
+ gDevTools.showToolbox(target1, "webconsole").then(onWebConsoleOpen);
+ }
+ catch (ex) {
+ ok(false, "gDevTools.showToolbox(target1) exception: " + ex);
+ noErrors = false;
+ }
+
+ try {
+ let target2 = TargetFactory.forTab(tab2);
+ gDevTools.showToolbox(target2, "webconsole").then(onWebConsoleOpen);
+ }
+ catch (ex) {
+ ok(false, "gDevTools.showToolbox(target2) exception: " + ex);
+ noErrors = false;
+ }
+ }
+
+ function closeConsoles() {
+ try {
+ let target1 = TargetFactory.forTab(tab1);
+ gDevTools.closeToolbox(target1).then(function() {
+ try {
+ let target2 = TargetFactory.forTab(tab2);
+ gDevTools.closeToolbox(target2).then(testEnd);
+ }
+ catch (ex) {
+ ok(false, "gDevTools.closeToolbox(target2) exception: " + ex);
+ noErrors = false;
+ }
+ });
+ }
+ catch (ex) {
+ ok(false, "gDevTools.closeToolbox(target1) exception: " + ex);
+ noErrors = false;
+ }
+ }
+
+ function testEnd() {
+ ok(noErrors, "there were no errors");
+
+ Array.forEach(win1.gBrowser.tabs, function(aTab) {
+ win1.gBrowser.removeTab(aTab);
+ });
+ Array.forEach(win2.gBrowser.tabs, function(aTab) {
+ win2.gBrowser.removeTab(aTab);
+ });
+
+ executeSoon(function() {
+ win2.close();
+ tab1 = tab2 = win1 = win2 = null;
+ finishTest();
+ });
+ }
+
+ waitForFocus(openConsoles, tab2.linkedBrowser.contentWindow);
+}
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", tab1Loaded, true);
+ tab1 = gBrowser.selectedTab;
+ win1 = window;
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js
new file mode 100644
index 000000000..c634b11bd
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597136_external_script_errors.js
@@ -0,0 +1,43 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/" +
+ "webconsole/test/test-bug-597136-external-script-" +
+ "errors.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, function(hud) {
+ executeSoon(function() {
+ consoleOpened(hud);
+ });
+ });
+ }, true);
+}
+
+function consoleOpened(hud) {
+ let button = content.document.querySelector("button");
+ let outputNode = hud.outputNode;
+
+ expectUncaughtException();
+ EventUtils.sendMouseEvent({ type: "click" }, button, content);
+
+ waitForSuccess({
+ name: "external script error message",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bogus is not defined") > -1;
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597136_network_requests_from_chrome.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597136_network_requests_from_chrome.js
new file mode 100644
index 000000000..3aa0f5399
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597136_network_requests_from_chrome.js
@@ -0,0 +1,47 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that network requests from chrome don't cause the Web Console to
+// throw exceptions.
+
+const TEST_URI = "http://example.com/";
+
+let good = true;
+let listener = {
+ QueryInterface: XPCOMUtils.generateQI([ Ci.nsIObserver ]),
+ observe: function(aSubject, aTopic, aData) {
+ if (aSubject instanceof Ci.nsIScriptError &&
+ aSubject.category === "XPConnect JavaScript") {
+ good = false;
+ }
+ }
+};
+
+let xhr;
+
+function test() {
+ Services.console.registerListener(listener);
+
+ HUDService; // trigger a lazy-load of the HUD Service
+
+ xhr = new XMLHttpRequest();
+ xhr.addEventListener("load", xhrComplete, false);
+ xhr.open("GET", TEST_URI, true);
+ xhr.send(null);
+}
+
+function xhrComplete() {
+ xhr.removeEventListener("load", xhrComplete, false);
+ window.setTimeout(checkForException, 0);
+}
+
+function checkForException() {
+ ok(good, "no exception was thrown when sending a network request from a " +
+ "chrome window");
+
+ Services.console.unregisterListener(listener);
+ listener = null;
+
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js
new file mode 100644
index 000000000..7f55cb0fc
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597460_filter_scroll.js
@@ -0,0 +1,81 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-network.html";
+
+function consoleOpened(aHud) {
+ hud = aHud;
+
+ for (let i = 0; i < 200; i++) {
+ content.console.log("test message " + i);
+ }
+
+ hud.setFilterState("network", false);
+ hud.setFilterState("networkinfo", false);
+
+ hud.ui.filterBox.value = "test message";
+ hud.ui.adjustVisibilityOnSearchStringChange();
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ name: "console messages displayed",
+ text: "test message 199",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(() => {
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "test-network.html",
+ category: CATEGORY_NETWORK,
+ severity: SEVERITY_LOG,
+ successFn: testScroll,
+ failureFn: finishTest,
+ }],
+ }).then(testScroll);
+ content.location.reload();
+ });
+}
+
+function testScroll() {
+ let msgNode = hud.outputNode.querySelector(".webconsole-msg-network");
+ ok(msgNode.classList.contains("hud-filtered-by-type"),
+ "network message is filtered by type");
+ ok(msgNode.classList.contains("hud-filtered-by-string"),
+ "network message is filtered by string");
+
+ let scrollBox = hud.outputNode.scrollBoxObject.element;
+ ok(scrollBox.scrollTop > 0, "scroll location is not at the top");
+
+ // Make sure the Web Console output is scrolled as near as possible to the
+ // bottom.
+ let nodeHeight = hud.outputNode.querySelector(".hud-log").clientHeight;
+ ok(scrollBox.scrollTop >= scrollBox.scrollHeight - scrollBox.clientHeight -
+ nodeHeight * 2, "scroll location is correct");
+
+ hud.setFilterState("network", true);
+ hud.setFilterState("networkinfo", true);
+
+ executeSoon(finishTest);
+}
+
+function test() {
+ const PREF = "devtools.webconsole.persistlog";
+ Services.prefs.setBoolPref(PREF, true);
+ registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
+
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js b/browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js
new file mode 100644
index 000000000..b6636a079
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_597756_reopen_closed_tab.js
@@ -0,0 +1,63 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-597756-reopen-closed-tab.html";
+
+let newTabIsOpen = false;
+
+function tabLoaded(aEvent) {
+ gBrowser.selectedBrowser.removeEventListener(aEvent.type, tabLoaded, true);
+
+ openConsole(gBrowser.selectedTab, function() {
+ gBrowser.selectedBrowser.addEventListener("load", tabReloaded, true);
+ expectUncaughtException();
+ content.location.reload();
+ });
+}
+
+function tabReloaded(aEvent) {
+ gBrowser.selectedBrowser.removeEventListener(aEvent.type, tabReloaded, true);
+
+ let hudId = HUDService.getHudIdByWindow(content);
+ let HUD = HUDService.hudReferences[hudId];
+ ok(HUD, "Web Console is open");
+
+ waitForSuccess({
+ name: "error message displayed",
+ validatorFn: function() {
+ return HUD.outputNode.textContent.indexOf("fooBug597756_error") > -1;
+ },
+ successFn: function() {
+ if (newTabIsOpen) {
+ finishTest();
+ return;
+ }
+ closeConsole(gBrowser.selectedTab, function() {
+ gBrowser.removeCurrentTab();
+
+ let newTab = gBrowser.addTab();
+ gBrowser.selectedTab = newTab;
+
+ newTabIsOpen = true;
+ gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
+ expectUncaughtException();
+ content.location = TEST_URI;
+ });
+ },
+ failureFn: finishTest,
+ });
+}
+
+function test() {
+ expectUncaughtException();
+ addTab(TEST_URI);
+ browser.addEventListener("load", tabLoaded, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js b/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js
new file mode 100644
index 000000000..1737b2275
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js
@@ -0,0 +1,275 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let testEnded = false;
+let pos = -1;
+
+let dateNow = Date.now();
+
+let tempScope = {};
+Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
+
+let longString = (new Array(tempScope.DebuggerServer.LONG_STRING_LENGTH + 4)).join("a");
+let initialString = longString.substring(0,
+ tempScope.DebuggerServer.LONG_STRING_INITIAL_LENGTH);
+
+let inputValues = [
+ // [showsVariablesView?, input value, expected output format,
+ // print() output, console API output, optional console API test]
+
+ // 0
+ [false, "'hello \\nfrom \\rthe \\\"string world!'",
+ '"hello \nfrom \rthe "string world!"',
+ "hello \nfrom \rthe \"string world!"],
+
+ // 1
+ [false, "'\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165'",
+ "\"\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165\"",
+ "\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165"],
+
+ // 2
+ [false, "window.location.href", '"' + TEST_URI + '"', TEST_URI],
+
+ // 3
+ [false, "0", "0"],
+
+ // 4
+ [false, "'0'", '"0"', "0"],
+
+ // 5
+ [false, "42", "42"],
+
+ // 6
+ [false, "'42'", '"42"', "42"],
+
+ // 7
+ [true, "/foobar/", "[object RegExp]", '"/foobar/"', "[object RegExp]"],
+
+ // 8
+ [false, "null", "null"],
+
+ // 9
+ [false, "undefined", "undefined"],
+
+ // 10
+ [false, "true", "true"],
+
+ // 11
+ [true, "document.getElementById", "[object Function]",
+ "function getElementById() {\n [native code]\n}",
+ "[object Function]"],
+
+ // 12
+ [true, "(function() { return 42; })", "[object Function]",
+ "function () { return 42; }", "[object Function]"],
+
+ // 13
+ [true, "new Date(" + dateNow + ")", "[object Date]", (new Date(dateNow)).toString(), "[object Date]"],
+
+ // 14
+ [true, "document.body", "[object HTMLBodyElement]"],
+
+ // 15
+ [true, "window.location", "[object Location]", TEST_URI, "[object Location]"],
+
+ // 16
+ [true, "[1,2,3,'a','b','c','4','5']", '[object Array]',
+ '1,2,3,a,b,c,4,5',
+ "[object Array]"],
+
+ // 17
+ [true, "({a:'b', c:'d', e:1, f:'2'})", "[object Object]"],
+
+ // 18
+ [false, "'" + longString + "'",
+ '"' + initialString + "\"[\u2026]", initialString],
+];
+
+longString = null;
+initialString = null;
+tempScope = null;
+
+let eventHandlers = [];
+let popupShown = [];
+let HUD;
+let testDriver;
+
+function tabLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoad, true);
+
+ waitForFocus(function () {
+ openConsole(null, function(aHud) {
+ HUD = aHud;
+ testNext();
+ });
+ }, content);
+}
+
+function subtestNext() {
+ testDriver.next();
+}
+
+function testNext() {
+ pos++;
+ if (pos == inputValues.length) {
+ testEnd();
+ return;
+ }
+
+ testDriver = testGen();
+ testDriver.next();
+}
+
+function testGen() {
+ let cpos = pos;
+
+ let showsVariablesView = inputValues[cpos][0];
+ let inputValue = inputValues[cpos][1];
+ let expectedOutput = inputValues[cpos][2];
+
+ let printOutput = inputValues[cpos].length >= 4 ?
+ inputValues[cpos][3] : expectedOutput;
+
+ let consoleOutput = inputValues[cpos].length >= 5 ?
+ inputValues[cpos][4] : printOutput;
+
+ let consoleTest = inputValues[cpos][5] || inputValue;
+
+ HUD.jsterm.clearOutput();
+
+ // Test the console.log() output.
+
+ HUD.jsterm.execute("console.log(" + consoleTest + ")");
+
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ name: "console API output is correct for inputValues[" + cpos + "]",
+ text: consoleOutput,
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(subtestNext);
+
+ yield undefined;
+
+ HUD.jsterm.clearOutput();
+
+ // Test jsterm print() output.
+
+ HUD.jsterm.setInputValue("print(" + inputValue + ")");
+ HUD.jsterm.execute();
+
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ name: "jsterm print() output is correct for inputValues[" + cpos + "]",
+ text: printOutput,
+ category: CATEGORY_OUTPUT,
+ }],
+ }).then(subtestNext);
+
+ yield undefined;
+
+ // Test jsterm execution output.
+
+ HUD.jsterm.clearOutput();
+ HUD.jsterm.setInputValue(inputValue);
+ HUD.jsterm.execute();
+
+ let outputItem;
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ name: "jsterm output is correct for inputValues[" + cpos + "]",
+ text: expectedOutput,
+ category: CATEGORY_OUTPUT,
+ }],
+ }).then(([result]) => {
+ outputItem = [...result.matched][0];
+ ok(outputItem, "found message element");
+ subtestNext();
+ });
+
+ yield undefined;
+
+ let messageBody = outputItem.querySelector(".webconsole-msg-body");
+ ok(messageBody, "we have the message body for inputValues[" + cpos + "]");
+
+ // Test click on output.
+ let eventHandlerID = eventHandlers.length + 1;
+
+ let variablesViewShown = function(aEvent, aView, aOptions) {
+ if (aOptions.label.indexOf(expectedOutput) == -1) {
+ return;
+ }
+
+ HUD.jsterm.off("variablesview-open", variablesViewShown);
+
+ eventHandlers[eventHandlerID] = null;
+
+ ok(showsVariablesView,
+ "the variables view shown for inputValues[" + cpos + "]");
+
+ popupShown[cpos] = true;
+
+ if (showsVariablesView) {
+ executeSoon(subtestNext);
+ }
+ };
+
+ HUD.jsterm.on("variablesview-open", variablesViewShown);
+
+ eventHandlers.push(variablesViewShown);
+
+ // Send the mousedown, mouseup and click events to check if the variables
+ // view opens.
+ EventUtils.sendMouseEvent({ type: "mousedown" }, messageBody, window);
+ EventUtils.sendMouseEvent({ type: "click" }, messageBody, window);
+
+ if (showsVariablesView) {
+ yield undefined; // wait for the panel to open if we need to.
+ }
+
+ testNext();
+
+ yield undefined;
+}
+
+function testEnd() {
+ if (testEnded) {
+ return;
+ }
+
+ testEnded = true;
+
+ for (let i = 0; i < eventHandlers.length; i++) {
+ if (eventHandlers[i]) {
+ HUD.jsterm.off("variablesview-open", eventHandlers[i]);
+ }
+ }
+
+ for (let i = 0; i < inputValues.length; i++) {
+ if (inputValues[i][0] && !popupShown[i]) {
+ ok(false, "the variables view failed to show for inputValues[" + i + "]");
+ }
+ }
+
+ HUD = inputValues = testDriver = null;
+ executeSoon(finishTest);
+}
+
+function test() {
+ requestLongerTimeout(2);
+ addTab(TEST_URI);
+ browser.addEventListener("load", tabLoad, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js b/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js
new file mode 100644
index 000000000..a913f5e0c
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js
@@ -0,0 +1,76 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs";
+
+let loads = 0;
+function performTest(aRequest, aConsole)
+{
+ loads++;
+ ok(aRequest, "page load was logged");
+ if (loads != 2) {
+ return;
+ }
+
+ let headers = null;
+
+ function readHeader(aName)
+ {
+ for (let header of headers) {
+ if (header.name == aName) {
+ return header.value;
+ }
+ }
+ return null;
+ }
+
+ aConsole.webConsoleClient.getResponseHeaders(aRequest.actor,
+ function (aResponse) {
+ headers = aResponse.headers;
+ ok(headers, "we have the response headers for reload");
+
+ let contentType = readHeader("Content-Type");
+ let contentLength = readHeader("Content-Length");
+
+ ok(!contentType, "we do not have the Content-Type header");
+ isnot(contentLength, 60, "Content-Length != 60");
+
+ if (contentType || contentLength == 60) {
+ console.debug("lastFinishedRequest", lastFinishedRequest,
+ "request", lastFinishedRequest.request,
+ "response", lastFinishedRequest.response,
+ "updates", lastFinishedRequest.updates,
+ "response headers", headers);
+ }
+
+ executeSoon(finishTest);
+ });
+
+ HUDService.lastFinishedRequestCallback = null;
+}
+
+function test()
+{
+ addTab("data:text/plain;charset=utf8,hello world");
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, () => {
+ HUDService.lastFinishedRequestCallback = performTest;
+
+ browser.addEventListener("load", function onReload() {
+ browser.removeEventListener("load", onReload, true);
+ executeSoon(() => content.location.reload());
+ }, true);
+
+ executeSoon(() => content.location = TEST_URI);
+ });
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js b/browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js
new file mode 100644
index 000000000..3dd67379d
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js
@@ -0,0 +1,53 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-600183-charset.html";
+
+function performTest(lastFinishedRequest, aConsole)
+{
+ ok(lastFinishedRequest, "charset test page was loaded and logged");
+ HUDService.lastFinishedRequestCallback = null;
+
+ executeSoon(() => {
+ aConsole.webConsoleClient.getResponseContent(lastFinishedRequest.actor,
+ (aResponse) => {
+ ok(!aResponse.contentDiscarded, "response body was not discarded");
+
+ let body = aResponse.content.text;
+ ok(body, "we have the response body");
+
+ let chars = "\u7684\u95ee\u5019!"; // 的问候!
+ isnot(body.indexOf("<p>" + chars + "</p>"), -1,
+ "found the chinese simplified string");
+
+ HUDService.lastFinishedRequestCallback = null;
+ executeSoon(finishTest);
+ });
+ });
+}
+
+function test()
+{
+ addTab("data:text/html;charset=utf-8,Web Console - bug 600183 test");
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function(hud) {
+ hud.ui.setSaveRequestAndResponseBodies(true).then(() => {
+ ok(hud.ui._saveRequestAndResponseBodies,
+ "The saveRequestAndResponseBodies property was successfully set.");
+
+ HUDService.lastFinishedRequestCallback = performTest;
+ content.location = TEST_URI;
+ });
+ });
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_601177_log_levels.js b/browser/devtools/webconsole/test/browser_webconsole_bug_601177_log_levels.js
new file mode 100644
index 000000000..5a3566a3e
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_601177_log_levels.js
@@ -0,0 +1,82 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-601177-log-levels.html";
+
+function performTest()
+{
+ let hudId = HUDService.getHudIdByWindow(content);
+ let HUD = HUDService.hudReferences[hudId];
+
+ findEntry(HUD, "hud-networkinfo", "test-bug-601177-log-levels.html",
+ "found test-bug-601177-log-levels.html");
+
+ findEntry(HUD, "hud-networkinfo", "test-bug-601177-log-levels.js",
+ "found test-bug-601177-log-levels.js");
+
+ findEntry(HUD, "hud-networkinfo", "test-image.png", "found test-image.png");
+
+ findEntry(HUD, "hud-network", "foobar-known-to-fail.png",
+ "found foobar-known-to-fail.png");
+
+ findEntry(HUD, "hud-exception", "foobarBug601177exception",
+ "found exception");
+
+ findEntry(HUD, "hud-jswarn", "undefinedPropertyBug601177",
+ "found strict warning");
+
+ findEntry(HUD, "hud-jswarn", "foobarBug601177strictError",
+ "found strict error");
+
+ executeSoon(finishTest);
+}
+
+function findEntry(aHUD, aClass, aString, aMessage)
+{
+ return testLogEntry(aHUD.outputNode, aString, aMessage, false, false,
+ aClass);
+}
+
+function test()
+{
+ Services.prefs.setBoolPref("javascript.options.strict", true);
+
+ registerCleanupFunction(function() {
+ Services.prefs.clearUserPref("javascript.options.strict");
+ });
+
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 601177: log levels");
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function(hud) {
+ browser.addEventListener("load", function onLoad2() {
+ browser.removeEventListener("load", onLoad2, true);
+ waitForSuccess({
+ name: "all messages displayed",
+ validatorFn: function()
+ {
+ return hud.outputNode.itemCount >= 7;
+ },
+ successFn: performTest,
+ failureFn: function() {
+ info("itemCount: " + hud.outputNode.itemCount);
+ finishTest();
+ },
+ });
+ }, true);
+
+ expectUncaughtException();
+ content.location = TEST_URI;
+ });
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js
new file mode 100644
index 000000000..2ff469db2
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js
@@ -0,0 +1,75 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function consoleOpened(HUD) {
+ HUD.jsterm.clearOutput();
+
+ let longMessage = "";
+ for (let i = 0; i < 50; i++) {
+ longMessage += "LongNonwrappingMessage";
+ }
+
+ for (let i = 0; i < 50; i++) {
+ content.console.log("test message " + i);
+ }
+
+ content.console.log(longMessage);
+
+ for (let i = 0; i < 50; i++) {
+ content.console.log("test message " + i);
+ }
+
+ HUD.jsterm.execute("1+1");
+
+ function performTest() {
+ let scrollBox = HUD.outputNode.scrollBoxObject.element;
+ isnot(scrollBox.scrollTop, 0, "scroll location is not at the top");
+
+ let node = HUD.outputNode.getItemAtIndex(HUD.outputNode.itemCount - 1);
+ let rectNode = node.getBoundingClientRect();
+ let rectOutput = HUD.outputNode.getBoundingClientRect();
+
+ // Visible scroll viewport.
+ let height = scrollBox.scrollHeight - scrollBox.scrollTop;
+
+ // Top position of the last message node, relative to the outputNode.
+ let top = rectNode.top - rectOutput.top;
+
+ // Bottom position of the last message node, relative to the outputNode.
+ let bottom = rectNode.bottom - rectOutput.top;
+
+ ok(top >= 0 && Math.floor(bottom) <= height + 1,
+ "last message is visible");
+
+ finishTest();
+ };
+
+ waitForSuccess({
+ name: "console output displayed",
+ validatorFn: function()
+ {
+ return HUD.outputNode.itemCount >= 103;
+ },
+ successFn: performTest,
+ failureFn: function() {
+ info("itemCount: " + HUD.outputNode.itemCount);
+ finishTest();
+ },
+ });
+}
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 601352");
+ browser.addEventListener("load", function tabLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_601667_filter_buttons.js b/browser/devtools/webconsole/test/browser_webconsole_bug_601667_filter_buttons.js
new file mode 100644
index 000000000..6872ffc0d
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_601667_filter_buttons.js
@@ -0,0 +1,146 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that the filter button UI logic works correctly.
+
+const TEST_URI = "http://example.com/";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testFilterButtons);
+ }, true);
+}
+
+function testFilterButtons(aHud) {
+ hud = aHud;
+ hudId = hud.hudId;
+ hudBox = hud.ui.rootElement;
+
+ testMenuFilterButton("net");
+ testMenuFilterButton("css");
+ testMenuFilterButton("js");
+ testMenuFilterButton("logging");
+
+ finishTest();
+}
+
+function testMenuFilterButton(aCategory) {
+ let selector = ".webconsole-filter-button[category=\"" + aCategory + "\"]";
+ let button = hudBox.querySelector(selector);
+ ok(button, "we have the \"" + aCategory + "\" button");
+
+ let firstMenuItem = button.querySelector("menuitem");
+ ok(firstMenuItem, "we have the first menu item for the \"" + aCategory +
+ "\" button");
+
+ // Turn all the filters off, if they were on.
+ let menuItem = firstMenuItem;
+ while (menuItem != null) {
+ if (isChecked(menuItem)) {
+ chooseMenuItem(menuItem);
+ }
+ menuItem = menuItem.nextSibling;
+ }
+
+ // Turn all the filters on; make sure the button gets checked.
+ menuItem = firstMenuItem;
+ let prefKey;
+ while (menuItem) {
+ if (menuItem.hasAttribute("prefKey")) {
+ prefKey = menuItem.getAttribute("prefKey");
+ chooseMenuItem(menuItem);
+ ok(isChecked(menuItem), "menu item " + prefKey + " for category " +
+ aCategory + " is checked after clicking it");
+ ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
+ "on after clicking the appropriate menu item");
+ }
+ menuItem = menuItem.nextSibling;
+ }
+ ok(isChecked(button), "the button for category " + aCategory + " is " +
+ "checked after turning on all its menu items");
+
+ // Turn one filter off; make sure the button is still checked.
+ prefKey = firstMenuItem.getAttribute("prefKey");
+ chooseMenuItem(firstMenuItem);
+ ok(!isChecked(firstMenuItem), "the first menu item for category " +
+ aCategory + " is no longer checked after clicking it");
+ ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
+ "turned off after clicking the appropriate menu item");
+ ok(isChecked(button), "the button for category " + aCategory + " is still " +
+ "checked after turning off its first menu item");
+
+ // Turn all the filters off by clicking the main part of the button.
+ let anonymousNodes = hud.ui.document.getAnonymousNodes(button);
+ let subbutton;
+ for (let i = 0; i < anonymousNodes.length; i++) {
+ let node = anonymousNodes[i];
+ if (node.classList.contains("toolbarbutton-menubutton-button")) {
+ subbutton = node;
+ break;
+ }
+ }
+ ok(subbutton, "we have the subbutton for category " + aCategory);
+
+ clickButton(subbutton);
+ ok(!isChecked(button), "the button for category " + aCategory + " is " +
+ "no longer checked after clicking its main part");
+
+ menuItem = firstMenuItem;
+ while (menuItem) {
+ let prefKey = menuItem.getAttribute("prefKey");
+ ok(!isChecked(menuItem), "menu item " + prefKey + " for category " +
+ aCategory + " is no longer checked after clicking the button");
+ ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
+ "off after clicking the button");
+ menuItem = menuItem.nextSibling;
+ }
+
+ // Turn all the filters on by clicking the main part of the button.
+ clickButton(subbutton);
+
+ ok(isChecked(button), "the button for category " + aCategory + " is " +
+ "checked after clicking its main part");
+
+ menuItem = firstMenuItem;
+ while (menuItem) {
+ if (menuItem.hasAttribute("prefKey")) {
+ let prefKey = menuItem.getAttribute("prefKey");
+ ok(isChecked(menuItem), "menu item " + prefKey + " for category " +
+ aCategory + " is checked after clicking the button");
+ ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
+ "on after clicking the button");
+ }
+ menuItem = menuItem.nextSibling;
+ }
+
+ // Uncheck the main button by unchecking all the filters
+ menuItem = firstMenuItem;
+ while (menuItem) {
+ chooseMenuItem(menuItem);
+ menuItem = menuItem.nextSibling;
+ }
+
+ ok(!isChecked(button), "the button for category " + aCategory + " is " +
+ "unchecked after unchecking all its filters");
+
+ // Turn all the filters on again by clicking the button.
+ clickButton(subbutton);
+}
+
+function clickButton(aNode) {
+ EventUtils.sendMouseEvent({ type: "click" }, aNode);
+}
+
+function chooseMenuItem(aNode) {
+ let event = document.createEvent("XULCommandEvent");
+ event.initCommandEvent("command", true, true, window, 0, false, false, false,
+ false, null);
+ aNode.dispatchEvent(event);
+}
+
+function isChecked(aNode) {
+ return aNode.getAttribute("checked") === "true";
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js b/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js
new file mode 100644
index 000000000..d4ed63916
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js
@@ -0,0 +1,182 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let menuitems = [], menupopups = [], huds = [], tabs = [], runCount = 0;
+
+function test()
+{
+ if (runCount == 0) {
+ requestLongerTimeout(2);
+ }
+
+ // open tab 1
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 1");
+ tabs.push(tab);
+
+ browser.addEventListener("load", function onLoad1(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad1, true);
+
+ openConsole(null, (hud) => hud.iframeWindow.mozRequestAnimationFrame(() => {
+ info("iframe1 root height " + hud.ui.rootElement.clientHeight);
+
+ // open tab 2
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 602572: log bodies checkbox. tab 2");
+ tabs.push(tab);
+
+ browser.addEventListener("load", function onLoad2(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad2, true);
+
+ openConsole(null, (hud) => hud.iframeWindow.mozRequestAnimationFrame(startTest));
+ }, true);
+ }));
+ }, true);
+}
+
+function startTest()
+{
+ // Find the relevant elements in the Web Console of tab 2.
+ let win2 = tabs[runCount*2 + 1].linkedBrowser.contentWindow;
+ let hudId2 = HUDService.getHudIdByWindow(win2);
+ huds[1] = HUDService.hudReferences[hudId2];
+ info("startTest: iframe2 root height " + huds[1].ui.rootElement.clientHeight);
+
+ if (runCount == 0) {
+ menuitems[1] = huds[1].ui.rootElement.querySelector("#saveBodies");
+ }
+ else {
+ menuitems[1] = huds[1].ui.rootElement.querySelector("#saveBodiesContextMenu");
+ }
+ menupopups[1] = menuitems[1].parentNode;
+
+ // Open the context menu from tab 2.
+ menupopups[1].addEventListener("popupshown", onpopupshown2, false);
+ executeSoon(function() {
+ menupopups[1].openPopup();
+ });
+}
+
+function onpopupshown2(aEvent)
+{
+ menupopups[1].removeEventListener(aEvent.type, onpopupshown2, false);
+
+ // By default bodies are not logged.
+ isnot(menuitems[1].getAttribute("checked"), "true",
+ "menuitems[1] is not checked");
+
+ ok(!huds[1].ui._saveRequestAndResponseBodies, "bodies are not logged");
+
+ // Enable body logging.
+ huds[1].ui.setSaveRequestAndResponseBodies(true).then(() => {
+ menupopups[1].hidePopup();
+ });
+
+ menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
+ menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
+
+ info("menupopups[1] hidden");
+
+ // Reopen the context menu.
+ huds[1].ui.once("save-bodies-ui-toggled", () => testpopup2b(aEvent));
+ menupopups[1].openPopup();
+ }, false);
+}
+
+function testpopup2b(aEvent) {
+ is(menuitems[1].getAttribute("checked"), "true", "menuitems[1] is checked");
+
+ menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
+ menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
+
+ info("menupopups[1] hidden");
+
+ // Switch to tab 1 and open the Web Console context menu from there.
+ gBrowser.selectedTab = tabs[runCount*2];
+ waitForFocus(function() {
+ // Find the relevant elements in the Web Console of tab 1.
+ let win1 = tabs[runCount*2].linkedBrowser.contentWindow;
+ let hudId1 = HUDService.getHudIdByWindow(win1);
+ huds[0] = HUDService.hudReferences[hudId1];
+
+ info("iframe1 root height " + huds[0].ui.rootElement.clientHeight);
+
+ menuitems[0] = huds[0].ui.rootElement.querySelector("#saveBodies");
+ menupopups[0] = huds[0].ui.rootElement.querySelector("menupopup");
+
+ menupopups[0].addEventListener("popupshown", onpopupshown1, false);
+ executeSoon(() => menupopups[0].openPopup());
+ }, tabs[runCount*2].linkedBrowser.contentWindow);
+ }, false);
+
+ executeSoon(function() {
+ menupopups[1].hidePopup();
+ });
+}
+
+function onpopupshown1(aEvent)
+{
+ menupopups[0].removeEventListener(aEvent.type, onpopupshown1, false);
+
+ // The menuitem checkbox must not be in sync with the other tabs.
+ isnot(menuitems[0].getAttribute("checked"), "true",
+ "menuitems[0] is not checked");
+
+ // Enable body logging for tab 1 as well.
+ huds[0].ui.setSaveRequestAndResponseBodies(true).then(() => {
+ menupopups[0].hidePopup();
+ });
+
+ // Close the menu, and switch back to tab 2.
+ menupopups[0].addEventListener("popuphidden", function _onhidden(aEvent) {
+ menupopups[0].removeEventListener(aEvent.type, _onhidden, false);
+
+ info("menupopups[0] hidden");
+
+ gBrowser.selectedTab = tabs[runCount*2 + 1];
+ waitForFocus(function() {
+ // Reopen the context menu from tab 2.
+ huds[1].ui.once("save-bodies-ui-toggled", () => testpopup2c(aEvent));
+ menupopups[1].openPopup();
+ }, tabs[runCount*2 + 1].linkedBrowser.contentWindow);
+ }, false);
+}
+
+function testpopup2c(aEvent) {
+ is(menuitems[1].getAttribute("checked"), "true", "menuitems[1] is checked");
+
+ menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
+ menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
+
+ info("menupopups[1] hidden");
+
+ // Done if on second run
+ closeConsole(gBrowser.selectedTab, function() {
+ if (runCount == 0) {
+ runCount++;
+ info("start second run");
+ executeSoon(test);
+ }
+ else {
+ gBrowser.removeCurrentTab();
+ gBrowser.selectedTab = tabs[2];
+ gBrowser.removeCurrentTab();
+ gBrowser.selectedTab = tabs[1];
+ gBrowser.removeCurrentTab();
+ gBrowser.selectedTab = tabs[0];
+ gBrowser.removeCurrentTab();
+ huds = menuitems = menupopups = tabs = null;
+ executeSoon(finishTest);
+ }
+ });
+ }, false);
+
+ executeSoon(function() {
+ menupopups[1].hidePopup();
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js b/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js
new file mode 100644
index 000000000..323340f7a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js
@@ -0,0 +1,39 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-603750-websocket.html";
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 603750: Web Socket errors");
+ browser.addEventListener("load", function tabLoad() {
+ browser.removeEventListener("load", tabLoad, true);
+ openConsole(null, (hud) => {
+ content.location = TEST_URI;
+ info("waiting for websocket errors");
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ text: "ws://0.0.0.0:81",
+ source: { url: "test-bug-603750-websocket.js" },
+ category: CATEGORY_JS,
+ severity: SEVERITY_ERROR,
+ },
+ {
+ text: "ws://0.0.0.0:82",
+ source: { url: "test-bug-603750-websocket.js" },
+ category: CATEGORY_JS,
+ severity: SEVERITY_ERROR,
+ },
+ ]}).then(finishTest);
+ });
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js
new file mode 100644
index 000000000..6eb5177e5
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js
@@ -0,0 +1,93 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = 'data:text/html;charset=utf-8,<div style="-moz-opacity:0;">test repeated' +
+ ' css warnings</div><p style="-moz-opacity:0">hi</p>';
+
+function onContentLoaded()
+{
+ browser.removeEventListener("load", onContentLoaded, true);
+
+ let HUD = HUDService.getHudByWindow(content);
+ let jsterm = HUD.jsterm;
+ let outputNode = HUD.outputNode;
+
+ let cssWarning = "Unknown property '-moz-opacity'. Declaration dropped.";
+ let textFound = false;
+ let repeats = 0;
+
+ function displayResults()
+ {
+ ok(textFound, "css warning was found");
+ is(repeats, 2, "The unknown CSS property warning is displayed only once");
+ }
+
+ waitForSuccess({
+ name: "2 repeated CSS warnings",
+ validatorFn: () => {
+ let node = outputNode.querySelector(".webconsole-msg-cssparser");
+ if (!node) {
+ return false;
+ }
+
+ textFound = node.textContent.indexOf(cssWarning) > -1;
+ repeats = node.querySelector(".webconsole-msg-repeat")
+ .getAttribute("value");
+ return textFound && repeats == 2;
+ },
+ successFn: () => {
+ displayResults();
+ testConsoleLogRepeats();
+ },
+ failureFn: () => {
+ displayResults();
+ finishTest();
+ },
+ });
+}
+
+function testConsoleLogRepeats()
+{
+ let HUD = HUDService.getHudByWindow(content);
+ let jsterm = HUD.jsterm;
+ let outputNode = HUD.outputNode;
+
+ jsterm.clearOutput();
+
+ jsterm.setInputValue("for (let i = 0; i < 10; ++i) console.log('this is a line of reasonably long text that I will use to verify that the repeated text node is of an appropriate size.');");
+ jsterm.execute();
+
+ waitForSuccess({
+ timeout: 10000,
+ name: "10 repeated console.log messages",
+ validatorFn: function()
+ {
+ let node = outputNode.querySelector(".webconsole-msg-console");
+ return node && node.childNodes[3].firstChild.getAttribute("value") == 10;
+ },
+ successFn: finishTest,
+ failureFn: function() {
+ info("output content: " + outputNode.textContent);
+ finishTest();
+ },
+ });
+}
+
+/**
+ * Unit test for bug 611795:
+ * Repeated CSS messages get collapsed into one.
+ */
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, function(aHud) {
+ // Clear cached messages that are shown once the Web Console opens.
+ aHud.jsterm.clearOutput(true);
+ browser.addEventListener("load", onContentLoaded, true);
+ content.location.reload();
+ });
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_613013_console_api_iframe.js b/browser/devtools/webconsole/test/browser_webconsole_bug_613013_console_api_iframe.js
new file mode 100644
index 000000000..7e0fe28e1
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613013_console_api_iframe.js
@@ -0,0 +1,52 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-613013-console-api-iframe.html";
+
+let TestObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function test_observe(aMessage, aTopic, aData)
+ {
+ if (aTopic == "console-api-log-event") {
+ executeSoon(performTest);
+ }
+ }
+};
+
+function tabLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoad, true);
+
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ Services.obs.addObserver(TestObserver, "console-api-log-event", false);
+ content.location.reload();
+ });
+}
+
+function performTest() {
+ Services.obs.removeObserver(TestObserver, "console-api-log-event");
+ TestObserver = null;
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "foobarBug613013",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(finishTest);
+}
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", tabLoad, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_613280_jsterm_copy.js b/browser/devtools/webconsole/test/browser_webconsole_bug_613280_jsterm_copy.js
new file mode 100644
index 000000000..8748b0aa7
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613280_jsterm_copy.js
@@ -0,0 +1,85 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ */
+
+const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 613280";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, function(HUD) {
+ content.console.log("foobarBazBug613280");
+ waitForSuccess({
+ name: "a message is displayed",
+ validatorFn: function()
+ {
+ return HUD.outputNode.itemCount > 0;
+ },
+ successFn: performTest.bind(null, HUD),
+ failureFn: finishTest,
+ });
+ });
+ }, true);
+}
+
+function performTest(HUD) {
+ let input = HUD.jsterm.inputNode;
+ let selection = getSelection();
+ let contentSelection = browser.contentWindow.wrappedJSObject.getSelection();
+
+ let clipboard_setup = function() {
+ goDoCommand("cmd_copy");
+ };
+
+ let clipboard_copy_done = function() {
+ finishTest();
+ };
+
+ // Check if we first need to clear any existing selections.
+ if (selection.rangeCount > 0 || contentSelection.rangeCount > 0 ||
+ input.selectionStart != input.selectionEnd) {
+ if (input.selectionStart != input.selectionEnd) {
+ input.selectionStart = input.selectionEnd = 0;
+ }
+
+ if (selection.rangeCount > 0) {
+ selection.removeAllRanges();
+ }
+
+ if (contentSelection.rangeCount > 0) {
+ contentSelection.removeAllRanges();
+ }
+
+ goUpdateCommand("cmd_copy");
+ }
+
+ let controller = top.document.commandDispatcher.
+ getControllerForCommand("cmd_copy");
+ is(controller.isCommandEnabled("cmd_copy"), false, "cmd_copy is disabled");
+
+ HUD.jsterm.execute("'bug613280: hello world!'");
+
+ HUD.outputNode.selectedIndex = HUD.outputNode.itemCount - 1;
+ HUD.outputNode.focus();
+
+ goUpdateCommand("cmd_copy");
+
+ controller = top.document.commandDispatcher.
+ getControllerForCommand("cmd_copy");
+ is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
+
+ ok(HUD.outputNode.selectedItem, "we have a selected message");
+
+ waitForClipboard(getExpectedClipboardText(HUD.outputNode.selectedItem),
+ clipboard_setup, clipboard_copy_done, clipboard_copy_done);
+}
+
+function getExpectedClipboardText(aItem) {
+ return "[" + WCU_l10n.timestampString(aItem.timestamp) + "] " +
+ aItem.clipboardText;
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js
new file mode 100644
index 000000000..b3317a669
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js
@@ -0,0 +1,104 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ */
+
+let hud, testDriver;
+
+function testNext() {
+ testDriver.next();
+}
+
+function testGen() {
+ hud.jsterm.clearOutput();
+ let outputNode = hud.outputNode;
+ let scrollBox = outputNode.scrollBoxObject.element;
+
+ for (let i = 0; i < 150; i++) {
+ content.console.log("test message " + i);
+ }
+
+ waitForSuccess({
+ name: "150 console.log messages displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-log").length == 150;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ let oldScrollTop = scrollBox.scrollTop;
+ ok(oldScrollTop > 0, "scroll location is not at the top");
+
+ // scroll to the first node
+ outputNode.focus();
+
+ EventUtils.synthesizeKey("VK_HOME", {});
+
+ let topPosition = scrollBox.scrollTop;
+ isnot(topPosition, oldScrollTop, "scroll location updated (moved to top)");
+
+ // add a message and make sure scroll doesn't change
+ content.console.log("test message 150");
+
+ waitForSuccess({
+ name: "console.log message no. 151 displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-log").length == 151;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ is(scrollBox.scrollTop, topPosition, "scroll location is still at the top");
+
+ // scroll back to the bottom
+ outputNode.lastChild.focus();
+ EventUtils.synthesizeKey("VK_END", {});
+
+ oldScrollTop = outputNode.scrollTop;
+
+ content.console.log("test message 151");
+
+ waitForSuccess({
+ name: "console.log message no. 152 displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-log").length == 152;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ isnot(scrollBox.scrollTop, oldScrollTop,
+ "scroll location updated (moved to bottom)");
+
+ hud = testDriver = null;
+ finishTest();
+
+ yield;
+}
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 613642: remember scroll location");
+ browser.addEventListener("load", function tabLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoad, true);
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ testDriver = testGen();
+ testDriver.next();
+ });
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js
new file mode 100644
index 000000000..5bde49602
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_prune_scroll.js
@@ -0,0 +1,101 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ */
+
+let hud, testDriver;
+
+function testNext() {
+ testDriver.next();
+}
+
+function testGen() {
+ hud.jsterm.clearOutput();
+
+ let outputNode = hud.outputNode;
+ let oldPref = Services.prefs.getIntPref("devtools.hud.loglimit.console");
+
+ Services.prefs.setIntPref("devtools.hud.loglimit.console", 140);
+ let scrollBoxElement = outputNode.scrollBoxObject.element;
+ let boxObject = outputNode.scrollBoxObject;
+
+ for (let i = 0; i < 150; i++) {
+ content.console.log("test message " + i);
+ }
+
+ waitForSuccess({
+ name: "150 console.log messages displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-log").length == 140;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ let oldScrollTop = scrollBoxElement.scrollTop;
+ ok(oldScrollTop > 0, "scroll location is not at the top");
+
+ let firstNode = outputNode.firstChild;
+ ok(firstNode, "found the first message");
+
+ let msgNode = outputNode.querySelectorAll("richlistitem")[80];
+ ok(msgNode, "found the 80th message");
+
+ // scroll to the middle message node
+ boxObject.ensureElementIsVisible(msgNode);
+
+ isnot(scrollBoxElement.scrollTop, oldScrollTop,
+ "scroll location updated (scrolled to message)");
+
+ oldScrollTop = scrollBoxElement.scrollTop;
+
+ // add a message
+ content.console.log("hello world");
+
+ waitForSuccess({
+ name: "console.log message #151 displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("hello world") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ // Scroll location needs to change, because one message is also removed, and
+ // we need to scroll a bit towards the top, to keep the current view in sync.
+ isnot(scrollBoxElement.scrollTop, oldScrollTop,
+ "scroll location updated (added a message)");
+
+ isnot(outputNode.firstChild, firstNode,
+ "first message removed");
+
+ Services.prefs.setIntPref("devtools.hud.loglimit.console", oldPref);
+
+ hud = testDriver = null;
+ finishTest();
+
+ yield;
+}
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 613642: maintain scroll with pruning of old messages");
+ browser.addEventListener("load", function tabLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoad, true);
+
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ testDriver = testGen();
+ testDriver.next();
+ });
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js b/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js
new file mode 100644
index 000000000..279fc2967
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js
@@ -0,0 +1,68 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ */
+
+function consoleOpened(hud) {
+ hud.jsterm.clearOutput();
+
+ let outputNode = hud.outputNode;
+ let boxObject = outputNode.scrollBoxObject.element;
+
+ for (let i = 0; i < 150; i++) {
+ content.console.log("test message " + i);
+ }
+
+ let oldScrollTop = -1;
+
+ waitForSuccess({
+ name: "console.log messages displayed",
+ validatorFn: function()
+ {
+ return outputNode.itemCount == 150;
+ },
+ successFn: function()
+ {
+ oldScrollTop = boxObject.scrollTop;
+ ok(oldScrollTop > 0, "scroll location is not at the top");
+
+ hud.jsterm.execute("'hello world'");
+
+ waitForSuccess(waitForExecute);
+ },
+ failureFn: finishTest,
+ });
+
+ let waitForExecute = {
+ name: "jsterm output displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ isnot(boxObject.scrollTop, oldScrollTop, "scroll location updated");
+
+ oldScrollTop = boxObject.scrollTop;
+ outputNode.scrollBoxObject.ensureElementIsVisible(outputNode.lastChild);
+
+ is(boxObject.scrollTop, oldScrollTop, "scroll location is the same");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ };
+}
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 614793: jsterm result scroll");
+ browser.addEventListener("load", function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_618078_network_exceptions.js b/browser/devtools/webconsole/test/browser_webconsole_bug_618078_network_exceptions.js
new file mode 100644
index 000000000..62085dd50
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_618078_network_exceptions.js
@@ -0,0 +1,70 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that network log messages bring up the network panel.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-618078-network-exceptions.html";
+
+let testEnded = false;
+
+let TestObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function test_observe(aSubject)
+ {
+ if (testEnded || !(aSubject instanceof Ci.nsIScriptError)) {
+ return;
+ }
+
+ is(aSubject.category, "content javascript", "error category");
+
+ testEnded = true;
+ if (aSubject.category == "content javascript") {
+ executeSoon(checkOutput);
+ }
+ else {
+ executeSoon(finishTest);
+ }
+ }
+};
+
+function checkOutput()
+{
+ waitForSuccess({
+ name: "exception message",
+ validatorFn: function()
+ {
+ return hud.outputNode.textContent.indexOf("bug618078exception") > -1;
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ });
+}
+
+function testEnd()
+{
+ Services.console.unregisterListener(TestObserver);
+}
+
+function test()
+{
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 618078");
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ Services.console.registerListener(TestObserver);
+ registerCleanupFunction(testEnd);
+
+ executeSoon(function() {
+ expectUncaughtException();
+ content.location = TEST_URI;
+ });
+ });
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_618311_close_panels.js b/browser/devtools/webconsole/test/browser_webconsole_bug_618311_close_panels.js
new file mode 100644
index 000000000..b1bd90ffe
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_618311_close_panels.js
@@ -0,0 +1,89 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function(hud) {
+ content.location.reload();
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "test-console.html",
+ category: CATEGORY_NETWORK,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(performTest);
+ });
+ }, true);
+}
+
+function performTest() {
+ let hudId = HUDService.getHudIdByWindow(content);
+ let HUD = HUDService.hudReferences[hudId];
+
+ let networkMessage = HUD.outputNode.querySelector(".webconsole-msg-network");
+ ok(networkMessage, "found network message");
+
+ let networkLink = networkMessage.querySelector(".webconsole-msg-link");
+ ok(networkLink, "found network message link");
+
+ let popupset = document.getElementById("mainPopupSet");
+ ok(popupset, "found #mainPopupSet");
+
+ let popupsShown = 0;
+ let hiddenPopups = 0;
+
+ let onpopupshown = function() {
+ document.removeEventListener("popupshown", onpopupshown, false);
+ popupsShown++;
+
+ executeSoon(function() {
+ let popups = popupset.querySelectorAll("panel[hudId=" + hudId + "]");
+ is(popups.length, 1, "found one popup");
+
+ document.addEventListener("popuphidden", onpopuphidden, false);
+
+ registerCleanupFunction(function() {
+ is(hiddenPopups, 1, "correct number of popups hidden");
+ if (hiddenPopups != 1) {
+ document.removeEventListener("popuphidden", onpopuphidden, false);
+ }
+ });
+
+ executeSoon(closeConsole);
+ });
+ };
+
+ let onpopuphidden = function() {
+ document.removeEventListener("popuphidden", onpopuphidden, false);
+ hiddenPopups++;
+
+ executeSoon(function() {
+ let popups = popupset.querySelectorAll("panel[hudId=" + hudId + "]");
+ is(popups.length, 0, "no popups found");
+
+ executeSoon(finishTest);
+ });
+ };
+
+ document.addEventListener("popupshown", onpopupshown, false);
+
+ registerCleanupFunction(function() {
+ is(popupsShown, 1, "correct number of popups shown");
+ if (popupsShown != 1) {
+ document.removeEventListener("popupshown", onpopupshown, false);
+ }
+ });
+
+ EventUtils.sendMouseEvent({ type: "mousedown" }, networkLink, HUD.iframeWindow);
+ EventUtils.sendMouseEvent({ type: "mouseup" }, networkLink, HUD.iframeWindow);
+ EventUtils.sendMouseEvent({ type: "click" }, networkLink, HUD.iframeWindow);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_621644_jsterm_dollar.js b/browser/devtools/webconsole/test/browser_webconsole_bug_621644_jsterm_dollar.js
new file mode 100644
index 000000000..03b362057
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_621644_jsterm_dollar.js
@@ -0,0 +1,68 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Sucan <mihai.sucan@gmail.com>
+ */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-621644-jsterm-dollar.html";
+
+function test$(HUD) {
+ HUD.jsterm.clearOutput();
+
+ HUD.jsterm.setInputValue("$(document.body)");
+ HUD.jsterm.execute();
+
+ waitForSuccess({
+ name: "jsterm output for $()",
+ validatorFn: function()
+ {
+ return HUD.outputNode.querySelector(".webconsole-msg-output:last-child");
+ },
+ successFn: function()
+ {
+ let outputItem = HUD.outputNode.
+ querySelector(".webconsole-msg-output:last-child");
+ ok(outputItem.textContent.indexOf("<p>") > -1,
+ "jsterm output is correct for $()");
+
+ test$$(HUD);
+ },
+ failureFn: test$$.bind(null, HUD),
+ });
+}
+
+function test$$(HUD) {
+ HUD.jsterm.clearOutput();
+
+ HUD.jsterm.setInputValue("$$(document)");
+ HUD.jsterm.execute();
+
+ waitForSuccess({
+ name: "jsterm output for $$()",
+ validatorFn: function()
+ {
+ return HUD.outputNode.querySelector(".webconsole-msg-output:last-child");
+ },
+ successFn: function()
+ {
+ let outputItem = HUD.outputNode.
+ querySelector(".webconsole-msg-output:last-child");
+ ok(outputItem.textContent.indexOf("621644") > -1,
+ "jsterm output is correct for $$()");
+
+ executeSoon(finishTest);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, test$);
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_622303_persistent_filters.js b/browser/devtools/webconsole/test/browser_webconsole_bug_622303_persistent_filters.js
new file mode 100644
index 000000000..0aa95af84
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_622303_persistent_filters.js
@@ -0,0 +1,123 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let prefs = {
+ "net": [
+ "network",
+ "networkinfo"
+ ],
+ "css": [
+ "csserror",
+ "cssparser"
+ ],
+ "js": [
+ "exception",
+ "jswarn",
+ "jslog",
+ ],
+ "logging": [
+ "error",
+ "warn",
+ "info",
+ "log"
+ ]
+};
+
+function test() {
+ // Set all prefs to true
+ for (let category in prefs) {
+ prefs[category].forEach(function(pref) {
+ Services.prefs.setBoolPref("devtools.webconsole.filter." + pref, true);
+ });
+ }
+
+ addTab("about:blank");
+ openConsole(null, onConsoleOpen);
+}
+
+function onConsoleOpen(hud) {
+ let hudBox = hud.ui.rootElement;
+
+ // Check if the filters menuitems exists and are checked
+ for (let category in prefs) {
+ let button = hudBox.querySelector(".webconsole-filter-button[category=\""
+ + category + "\"]");
+ ok(isChecked(button), "main button for " + category + " category is checked");
+
+ prefs[category].forEach(function(pref) {
+ let menuitem = hudBox.querySelector("menuitem[prefKey=" + pref + "]");
+ ok(isChecked(menuitem), "menuitem for " + pref + " is checked");
+ });
+ }
+
+ // Set all prefs to false
+ for (let category in prefs) {
+ prefs[category].forEach(function(pref) {
+ hud.setFilterState(pref, false);
+ });
+ }
+
+ //Re-init the console
+ closeConsole(null, function() {
+ openConsole(null, onConsoleReopen1);
+ });
+}
+
+function onConsoleReopen1(hud) {
+ let hudBox = hud.ui.rootElement;
+
+ // Check if the filter button and menuitems are unchecked
+ for (let category in prefs) {
+ let button = hudBox.querySelector(".webconsole-filter-button[category=\""
+ + category + "\"]");
+ ok(isUnchecked(button), "main button for " + category + " category is not checked");
+
+ prefs[category].forEach(function(pref) {
+ let menuitem = hudBox.querySelector("menuitem[prefKey=" + pref + "]");
+ ok(isUnchecked(menuitem), "menuitem for " + pref + " is not checked");
+ });
+ }
+
+ // Set first pref in each category to true
+ for (let category in prefs) {
+ hud.setFilterState(prefs[category][0], true);
+ }
+
+ // Re-init the console
+ closeConsole(null, function() {
+ openConsole(null, onConsoleReopen2);
+ });
+}
+
+function onConsoleReopen2(hud) {
+ let hudBox = hud.ui.rootElement;
+
+ // Check the main category button is checked and first menuitem is checked
+ for (let category in prefs) {
+ let button = hudBox.querySelector(".webconsole-filter-button[category=\""
+ + category + "\"]");
+ ok(isChecked(button), category + " button is checked when first pref is true");
+
+ let pref = prefs[category][0];
+ let menuitem = hudBox.querySelector("menuitem[prefKey=" + pref + "]");
+ ok(isChecked(menuitem), "first " + category + " menuitem is checked");
+ }
+
+ // Clear prefs
+ for (let category in prefs) {
+ prefs[category].forEach(function(pref) {
+ Services.prefs.clearUserPref("devtools.webconsole.filter." + pref);
+ });
+ }
+
+ prefs = null;
+ finishTest();
+}
+
+function isChecked(aNode) {
+ return aNode.getAttribute("checked") === "true";
+}
+
+function isUnchecked(aNode) {
+ return aNode.getAttribute("checked") === "false";
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_623749_ctrl_a_select_all_winnt.js b/browser/devtools/webconsole/test/browser_webconsole_bug_623749_ctrl_a_select_all_winnt.js
new file mode 100644
index 000000000..6e93ce523
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_623749_ctrl_a_select_all_winnt.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=623749
+// Map Control + A to Select All, In the web console input, on Windows
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Test console for bug 623749");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, runTest);
+ }, true);
+}
+
+function runTest(HUD) {
+ let jsterm = HUD.jsterm;
+ jsterm.setInputValue("Ignore These Four Words");
+ let inputNode = jsterm.inputNode;
+
+ // Test select all with Control + A.
+ EventUtils.synthesizeKey("a", { ctrlKey: true });
+ let inputLength = inputNode.selectionEnd - inputNode.selectionStart;
+ is(inputLength, inputNode.value.length, "Select all of input");
+
+ // Test do nothing on Control + E.
+ jsterm.setInputValue("Ignore These Four Words");
+ inputNode.selectionStart = 0;
+ EventUtils.synthesizeKey("e", { ctrlKey: true });
+ is(inputNode.selectionStart, 0, "Control + E does not move to end of input");
+
+ executeSoon(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_626484_output_copy_order.js b/browser/devtools/webconsole/test/browser_webconsole_bug_626484_output_copy_order.js
new file mode 100644
index 000000000..5b5193922
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_626484_output_copy_order.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+let itemsSet, HUD, outputNode;
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 626484");
+ browser.addEventListener("load", function tabLoaded(aEvent) {
+ browser.removeEventListener(aEvent.type, tabLoaded, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+
+function consoleOpened(aHud) {
+ HUD = aHud;
+ outputNode = HUD.outputNode;
+ HUD.jsterm.clearOutput();
+
+ let console = content.wrappedJSObject.console;
+ console.log("The first line.");
+ console.log("The second line.");
+ console.log("The last line.");
+ itemsSet = [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1],
+ [2, 1, 0]];
+
+ waitForSuccess({
+ name: "console.log messages displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-log").length == 3;
+ },
+ successFn: nextTest,
+ failureFn: finishTest,
+ });
+}
+
+function nextTest() {
+ if (itemsSet.length === 0) {
+ outputNode.clearSelection();
+ HUD.jsterm.clearOutput();
+ HUD = outputNode = null;
+ executeSoon(finishTest);
+ }
+ else {
+ outputNode.clearSelection();
+ let items = itemsSet.shift();
+ items.forEach(function (index) {
+ outputNode.addItemToSelection(outputNode.getItemAtIndex(index));
+ });
+ outputNode.focus();
+ waitForClipboard(getExpectedClipboardText(items.length),
+ clipboardSetup, nextTest, nextTest);
+ }
+}
+
+function getExpectedClipboardText(aItemCount) {
+ let expectedClipboardText = [];
+ for (let i = 0; i < aItemCount; i++) {
+ let item = outputNode.getItemAtIndex(i);
+ expectedClipboardText.push("[" +
+ WCU_l10n.timestampString(item.timestamp) + "] " +
+ item.clipboardText);
+ }
+ return expectedClipboardText.join("\n");
+}
+
+function clipboardSetup() {
+ goDoCommand("cmd_copy");
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js b/browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js
new file mode 100644
index 000000000..73870efab
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js
@@ -0,0 +1,129 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Mihai Sucan <mihai.sucan@gmail.com>
+ */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-630733-response-redirect-headers.sjs";
+
+let lastFinishedRequests = {};
+let webConsoleClient;
+
+function requestDoneCallback(aHttpRequest )
+{
+ let status = aHttpRequest.response.status;
+ lastFinishedRequests[status] = aHttpRequest;
+}
+
+function consoleOpened(hud)
+{
+ webConsoleClient = hud.ui.webConsoleClient;
+ hud.ui.setSaveRequestAndResponseBodies(true).then(() => {
+ ok(hud.ui._saveRequestAndResponseBodies,
+ "The saveRequestAndResponseBodies property was successfully set.");
+
+ HUDService.lastFinishedRequestCallback = requestDoneCallback;
+ waitForSuccess(waitForResponses);
+ content.location = TEST_URI;
+ });
+
+ let waitForResponses = {
+ name: "301 and 404 responses",
+ validatorFn: function()
+ {
+ return "301" in lastFinishedRequests &&
+ "404" in lastFinishedRequests;
+ },
+ successFn: getHeaders,
+ failureFn: finishTest,
+ };
+}
+
+function getHeaders()
+{
+ HUDService.lastFinishedRequestCallback = null;
+
+ ok("301" in lastFinishedRequests, "request 1: 301 Moved Permanently");
+ ok("404" in lastFinishedRequests, "request 2: 404 Not found");
+
+ webConsoleClient.getResponseHeaders(lastFinishedRequests["301"].actor,
+ function (aResponse) {
+ lastFinishedRequests["301"].response.headers = aResponse.headers;
+
+ webConsoleClient.getResponseHeaders(lastFinishedRequests["404"].actor,
+ function (aResponse) {
+ lastFinishedRequests["404"].response.headers = aResponse.headers;
+ executeSoon(getContent);
+ });
+ });
+}
+
+function getContent()
+{
+ webConsoleClient.getResponseContent(lastFinishedRequests["301"].actor,
+ function (aResponse) {
+ lastFinishedRequests["301"].response.content = aResponse.content;
+ lastFinishedRequests["301"].discardResponseBody = aResponse.contentDiscarded;
+
+ webConsoleClient.getResponseContent(lastFinishedRequests["404"].actor,
+ function (aResponse) {
+ lastFinishedRequests["404"].response.content = aResponse.content;
+ lastFinishedRequests["404"].discardResponseBody =
+ aResponse.contentDiscarded;
+
+ webConsoleClient = null;
+ executeSoon(performTest);
+ });
+ });
+}
+
+function performTest()
+{
+ function readHeader(aName)
+ {
+ for (let header of headers) {
+ if (header.name == aName) {
+ return header.value;
+ }
+ }
+ return null;
+ }
+
+ let headers = lastFinishedRequests["301"].response.headers;
+ is(readHeader("Content-Type"), "text/html",
+ "we do have the Content-Type header");
+ is(readHeader("Content-Length"), 71, "Content-Length is correct");
+ is(readHeader("Location"), "/redirect-from-bug-630733",
+ "Content-Length is correct");
+ is(readHeader("x-foobar-bug630733"), "bazbaz",
+ "X-Foobar-bug630733 is correct");
+
+ let body = lastFinishedRequests["301"].response.content;
+ ok(!body.text, "body discarded for request 1");
+ ok(lastFinishedRequests["301"].discardResponseBody,
+ "body discarded for request 1 (confirmed)");
+
+ headers = lastFinishedRequests["404"].response.headers;
+ ok(!readHeader("Location"), "no Location header");
+ ok(!readHeader("x-foobar-bug630733"), "no X-Foobar-bug630733 header");
+
+ body = lastFinishedRequests["404"].response.content.text;
+ isnot(body.indexOf("404"), -1,
+ "body is correct for request 2");
+
+ lastFinishedRequests = null;
+ executeSoon(finishTest);
+}
+
+function test()
+{
+ addTab("data:text/html;charset=utf-8,<p>Web Console test for bug 630733");
+
+ browser.addEventListener("load", function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_632275_getters_document_width.js b/browser/devtools/webconsole/test/browser_webconsole_bug_632275_getters_document_width.js
new file mode 100644
index 000000000..322eabd18
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_632275_getters_document_width.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-632275-getters.html";
+
+let getterValue = null;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud) {
+ let doc = content.wrappedJSObject.document;
+ getterValue = doc.foobar._val;
+ hud.jsterm.execute("console.dir(document)");
+
+ let onOpen = onViewOpened.bind(null, hud);
+ hud.jsterm.once("variablesview-fetched", onOpen);
+}
+
+function onViewOpened(hud, event, view)
+{
+ let doc = content.wrappedJSObject.document;
+
+ findVariableViewProperties(view, [
+ { name: /^(width|height)$/, dontMatch: 1 },
+ { name: "foobar._val", value: getterValue },
+ { name: "foobar.val", isGetter: true },
+ ], { webconsole: hud }).then(function() {
+ is(doc.foobar._val, getterValue, "getter did not execute");
+ is(doc.foobar.val, getterValue+1, "getter executed");
+ is(doc.foobar._val, getterValue+1, "getter executed (recheck)");
+
+ let textContent = hud.outputNode.textContent;
+ is(textContent.indexOf("document.body.client"), -1,
+ "no document.width/height warning displayed");
+
+ finishTest();
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js b/browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js
new file mode 100644
index 000000000..b14470aa7
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js
@@ -0,0 +1,88 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(HUD) {
+ let tmp = {};
+ Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
+ let WCU = tmp.WebConsoleUtils;
+ let JSPropertyProvider = tmp.JSPropertyProvider;
+ tmp = null;
+
+ let jsterm = HUD.jsterm;
+ let win = content.wrappedJSObject;
+
+ // Make sure autocomplete does not walk through iterators and generators.
+ let result = win.gen1.next();
+ let completion = JSPropertyProvider(win, "gen1.");
+ is(completion, null, "no matches for gen1");
+
+ is(result+1, win.gen1.next(), "gen1.next() did not execute");
+
+ result = win.gen2.next();
+
+ completion = JSPropertyProvider(win, "gen2.");
+ is(completion, null, "no matches for gen2");
+
+ is((result/2+1)*2, win.gen2.next(),
+ "gen2.next() did not execute");
+
+ result = win.iter1.next();
+ is(result[0], "foo", "iter1.next() [0] is correct");
+ is(result[1], "bar", "iter1.next() [1] is correct");
+
+ completion = JSPropertyProvider(win, "iter1.");
+ is(completion, null, "no matches for iter1");
+
+ result = win.iter1.next();
+ is(result[0], "baz", "iter1.next() [0] is correct");
+ is(result[1], "baaz", "iter1.next() [1] is correct");
+
+ completion = JSPropertyProvider(content, "iter2.");
+ is(completion, null, "no matches for iter2");
+
+ completion = JSPropertyProvider(win, "window.");
+ ok(completion, "matches available for window");
+ ok(completion.matches.length, "matches available for window (length)");
+
+ jsterm.clearOutput();
+
+ jsterm.execute("window");
+
+ waitForSuccess({
+ name: "jsterm window object output",
+ validatorFn: function()
+ {
+ return HUD.outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ jsterm.once("variablesview-fetched", testVariablesView.bind(null, HUD));
+ let node = HUD.outputNode.querySelector(".webconsole-msg-output");
+ EventUtils.synthesizeMouse(node, 2, 2, {}, HUD.iframeWindow);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function testVariablesView(aWebconsole, aEvent, aView) {
+ findVariableViewProperties(aView, [
+ { name: "gen1", isGenerator: true },
+ { name: "gen2", isGenerator: true },
+ { name: "iter1", isIterator: true },
+ { name: "iter2", isIterator: true },
+ ], { webconsole: aWebconsole }).then(function() {
+ executeSoon(finishTest);
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_632817.js b/browser/devtools/webconsole/test/browser_webconsole_bug_632817.js
new file mode 100644
index 000000000..e8b20cde7
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_632817.js
@@ -0,0 +1,196 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that network log messages bring up the network panel.
+
+const TEST_NETWORK_REQUEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-network-request.html";
+
+const TEST_IMG = "http://example.com/browser/browser/devtools/webconsole/test/test-image.png";
+
+const TEST_DATA_JSON_CONTENT =
+ '{ id: "test JSON data", myArray: [ "foo", "bar", "baz", "biff" ] }';
+
+let lastRequest = null;
+let requestCallback = null;
+
+function test()
+{
+ const PREF = "devtools.webconsole.persistlog";
+ Services.prefs.setBoolPref(PREF, true);
+ registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
+
+ addTab("data:text/html;charset=utf-8,Web Console network logging tests");
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function(aHud) {
+ hud = aHud;
+
+ HUDService.lastFinishedRequestCallback = function(aRequest) {
+ lastRequest = aRequest;
+ if (requestCallback) {
+ requestCallback();
+ }
+ };
+
+ executeSoon(testPageLoad);
+ });
+ }, true);
+}
+
+function testPageLoad()
+{
+ requestCallback = function() {
+ // Check if page load was logged correctly.
+ ok(lastRequest, "Page load was logged");
+ is(lastRequest.request.url, TEST_NETWORK_REQUEST_URI,
+ "Logged network entry is page load");
+ is(lastRequest.request.method, "GET", "Method is correct");
+ lastRequest = null;
+ requestCallback = null;
+ executeSoon(testPageLoadBody);
+ };
+
+ content.location = TEST_NETWORK_REQUEST_URI;
+}
+
+function testPageLoadBody()
+{
+ let loaded = false;
+ let requestCallbackInvoked = false;
+
+ // Turn off logging of request bodies and check again.
+ requestCallback = function() {
+ ok(lastRequest, "Page load was logged again");
+ lastRequest = null;
+ requestCallback = null;
+ requestCallbackInvoked = true;
+
+ if (loaded) {
+ executeSoon(testXhrGet);
+ }
+ };
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ loaded = true;
+
+ if (requestCallbackInvoked) {
+ executeSoon(testXhrGet);
+ }
+ }, true);
+
+ content.location.reload();
+}
+
+function testXhrGet()
+{
+ requestCallback = function() {
+ ok(lastRequest, "testXhrGet() was logged");
+ is(lastRequest.request.method, "GET", "Method is correct");
+ lastRequest = null;
+ requestCallback = null;
+ executeSoon(testXhrPost);
+ };
+
+ // Start the XMLHttpRequest() GET test.
+ content.wrappedJSObject.testXhrGet();
+}
+
+function testXhrPost()
+{
+ requestCallback = function() {
+ ok(lastRequest, "testXhrPost() was logged");
+ is(lastRequest.request.method, "POST", "Method is correct");
+ lastRequest = null;
+ requestCallback = null;
+ executeSoon(testFormSubmission);
+ };
+
+ // Start the XMLHttpRequest() POST test.
+ content.wrappedJSObject.testXhrPost();
+}
+
+function testFormSubmission()
+{
+ // Start the form submission test. As the form is submitted, the page is
+ // loaded again. Bind to the load event to catch when this is done.
+ requestCallback = function() {
+ ok(lastRequest, "testFormSubmission() was logged");
+ is(lastRequest.request.method, "POST", "Method is correct");
+
+ // There should be 3 network requests pointing to the HTML file.
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "test-network-request.html",
+ category: CATEGORY_NETWORK,
+ severity: SEVERITY_LOG,
+ count: 3,
+ }],
+ }).then(testLiveFilteringOnSearchStrings);
+ };
+
+ let form = content.document.querySelector("form");
+ ok(form, "we have the HTML form");
+ form.submit();
+}
+
+function testLiveFilteringOnSearchStrings() {
+ setStringFilter("http");
+ isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
+ "search string is set to \"http\"");
+
+ setStringFilter("HTTP");
+ isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
+ "search string is set to \"HTTP\"");
+
+ setStringFilter("hxxp");
+ is(countMessageNodes(), 0, "the log nodes are hidden when the search " +
+ "string is set to \"hxxp\"");
+
+ setStringFilter("ht tp");
+ isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
+ "search string is set to \"ht tp\"");
+
+ setStringFilter("");
+ isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
+ "search string is removed");
+
+ setStringFilter("json");
+ is(countMessageNodes(), 2, "the log nodes show only the nodes with \"json\"");
+
+ setStringFilter("'foo'");
+ is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
+ "the string 'foo'");
+
+ setStringFilter("foo\"bar'baz\"boo'");
+ is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
+ "the string \"foo\"bar'baz\"boo'\"");
+
+ HUDService.lastFinishedRequestCallback = null;
+ lastRequest = null;
+ requestCallback = null;
+ finishTest();
+}
+
+function countMessageNodes() {
+ let messageNodes = hud.outputNode.querySelectorAll(".hud-msg-node");
+ let displayedMessageNodes = 0;
+ let view = hud.iframeWindow;
+ for (let i = 0; i < messageNodes.length; i++) {
+ let computedStyle = view.getComputedStyle(messageNodes[i], null);
+ if (computedStyle.display !== "none")
+ displayedMessageNodes++;
+ }
+
+ return displayedMessageNodes;
+}
+
+function setStringFilter(aValue)
+{
+ hud.ui.filterBox.value = aValue;
+ hud.ui.adjustVisibilityOnSearchStringChange();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_642108_pruneTest.js b/browser/devtools/webconsole/test/browser_webconsole_bug_642108_pruneTest.js
new file mode 100644
index 000000000..af54ee7bf
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_642108_pruneTest.js
@@ -0,0 +1,89 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that the Web Console limits the number of lines displayed according to
+// the user's preferences.
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>test for bug 642108.";
+const LOG_LIMIT = 20;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad(){
+ browser.removeEventListener("load", onLoad, false);
+
+ Services.prefs.setIntPref("devtools.hud.loglimit.cssparser", LOG_LIMIT);
+
+ registerCleanupFunction(function() {
+ Services.prefs.clearUserPref("devtools.hud.loglimit.cssparser");
+ });
+
+ openConsole(null, testCSSPruning);
+ }, true);
+}
+
+function populateConsoleRepeats(aHudRef) {
+ for (let i = 0; i < 5; i++) {
+ let node = aHudRef.ui.createMessageNode(CATEGORY_CSS, SEVERITY_WARNING,
+ "css log x");
+ aHudRef.ui.outputMessage(CATEGORY_CSS, node);
+ }
+}
+
+function populateConsole(aHudRef) {
+ for (let i = 0; i < LOG_LIMIT + 5; i++) {
+ let node = aHudRef.ui.createMessageNode(CATEGORY_CSS, SEVERITY_WARNING,
+ "css log " + i);
+ aHudRef.ui.outputMessage(CATEGORY_CSS, node);
+ }
+}
+
+function testCSSPruning(hudRef) {
+ populateConsoleRepeats(hudRef);
+
+ let waitForNoRepeatedNodes = {
+ name: "number of nodes is LOG_LIMIT",
+ validatorFn: function()
+ {
+ return countMessageNodes() == LOG_LIMIT;
+ },
+ successFn: function()
+ {
+ is(Object.keys(hudRef.ui._repeatNodes).length, LOG_LIMIT,
+ "repeated nodes pruned from repeatNodes");
+
+ let msg = hudRef.outputNode.querySelector(".webconsole-msg-cssparser " +
+ ".webconsole-msg-repeat");
+ is(msg.getAttribute("value"), 1,
+ "repeated nodes pruned from repeatNodes (confirmed)");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ };
+
+ waitForSuccess({
+ name: "repeated nodes in cssNodes",
+ validatorFn: function()
+ {
+ let msg = hudRef.outputNode.querySelector(".webconsole-msg-cssparser " +
+ ".webconsole-msg-repeat");
+ return msg && msg.getAttribute("value") == 5;
+ },
+ successFn: function()
+ {
+ populateConsole(hudRef);
+ waitForSuccess(waitForNoRepeatedNodes);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function countMessageNodes() {
+ let outputNode = HUDService.getHudByWindow(content).outputNode;
+ return outputNode.querySelectorAll(".hud-msg-node").length;
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js b/browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js
new file mode 100644
index 000000000..1db6ab68f
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js
@@ -0,0 +1,102 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>test for bug 642615";
+
+XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
+ "@mozilla.org/widget/clipboardhelper;1",
+ "nsIClipboardHelper");
+
+function consoleOpened(HUD) {
+ let jsterm = HUD.jsterm;
+ let stringToCopy = "foobazbarBug642615";
+
+ jsterm.clearOutput();
+
+ ok(!jsterm.completeNode.value, "no completeNode.value");
+
+ jsterm.setInputValue("doc");
+
+ let completionValue;
+
+ // wait for key "u"
+ function onCompletionValue() {
+ completionValue = jsterm.completeNode.value;
+
+ // Arguments: expected, setup, success, failure.
+ waitForClipboard(
+ stringToCopy,
+ function() {
+ clipboardHelper.copyString(stringToCopy, document);
+ },
+ onClipboardCopy,
+ finishTest);
+ }
+
+ function onClipboardCopy() {
+ updateEditUIVisibility();
+ goDoCommand("cmd_paste");
+
+ waitForSuccess(waitForPaste);
+ }
+
+ let waitForPaste = {
+ name: "no completion value after paste",
+ validatorFn: function()
+ {
+ return !jsterm.completeNode.value;
+ },
+ successFn: onClipboardPaste,
+ failureFn: finishTest,
+ };
+
+ function onClipboardPaste() {
+ goDoCommand("cmd_undo");
+ waitForSuccess({
+ name: "completion value for 'docu' after undo",
+ validatorFn: function()
+ {
+ return !!jsterm.completeNode.value;
+ },
+ successFn: onCompletionValueAfterUndo,
+ failureFn: finishTest,
+ });
+ }
+
+ function onCompletionValueAfterUndo() {
+ is(jsterm.completeNode.value, completionValue,
+ "same completeNode.value after undo");
+
+ EventUtils.synthesizeKey("v", {accelKey: true});
+ waitForSuccess({
+ name: "no completion after ctrl-v (paste)",
+ validatorFn: function()
+ {
+ return !jsterm.completeNode.value;
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ });
+ }
+
+ EventUtils.synthesizeKey("u", {});
+
+ waitForSuccess({
+ name: "completion value for 'docu'",
+ validatorFn: function()
+ {
+ return !!jsterm.completeNode.value;
+ },
+ successFn: onCompletionValue,
+ failureFn: finishTest,
+ });
+}
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js b/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js
new file mode 100644
index 000000000..d72a61611
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js
@@ -0,0 +1,217 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that the Web Console limits the number of lines displayed according to
+// the limit set for each category.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/" +
+ "webconsole/test/test-bug-644419-log-limits.html";
+
+let hud, outputNode;
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 644419: Console should " +
+ "have user-settable log limits for each message category");
+ browser.addEventListener("load", onLoad, true);
+}
+
+function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+
+ openConsole(null, function(aHud) {
+ aHud.jsterm.clearOutput();
+ hud = aHud;
+ outputNode = aHud.outputNode;
+
+ browser.addEventListener("load", testWebDevLimits, true);
+ expectUncaughtException();
+ content.location = TEST_URI;
+ });
+}
+
+function testWebDevLimits(aEvent) {
+ browser.removeEventListener(aEvent.type, testWebDevLimits, true);
+ Services.prefs.setIntPref("devtools.hud.loglimit.console", 10);
+
+ // Find the sentinel entry.
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "bar is not defined",
+ category: CATEGORY_JS,
+ severity: SEVERITY_ERROR,
+ }],
+ }).then(testWebDevLimits2);
+}
+
+function testWebDevLimits2() {
+ // Fill the log with Web Developer errors.
+ for (let i = 0; i < 11; i++) {
+ content.console.log("test message " + i);
+ }
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "test message 10",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(() => {
+ testLogEntry(outputNode, "test message 0", "first message is pruned", false, true);
+ findLogEntry("test message 1");
+ // Check if the sentinel entry is still there.
+ findLogEntry("bar is not defined");
+
+ Services.prefs.clearUserPref("devtools.hud.loglimit.console");
+ testJsLimits();
+ });
+}
+
+function testJsLimits() {
+ Services.prefs.setIntPref("devtools.hud.loglimit.exception", 10);
+
+ hud.jsterm.clearOutput();
+ content.console.log("testing JS limits");
+
+ // Find the sentinel entry.
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "testing JS limits",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(testJsLimits2);
+}
+
+function testJsLimits2() {
+ // Fill the log with JS errors.
+ let head = content.document.getElementsByTagName("head")[0];
+ for (let i = 0; i < 11; i++) {
+ var script = content.document.createElement("script");
+ script.text = "fubar" + i + ".bogus(6);";
+ expectUncaughtException();
+ head.insertBefore(script, head.firstChild);
+ }
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "fubar10 is not defined",
+ category: CATEGORY_JS,
+ severity: SEVERITY_ERROR,
+ }],
+ }).then(() => {
+ testLogEntry(outputNode, "fubar0 is not defined", "first message is pruned", false, true);
+ findLogEntry("fubar1 is not defined");
+ // Check if the sentinel entry is still there.
+ findLogEntry("testing JS limits");
+
+ Services.prefs.clearUserPref("devtools.hud.loglimit.exception");
+ testNetLimits();
+ });
+}
+
+var gCounter, gImage;
+
+function testNetLimits() {
+ Services.prefs.setIntPref("devtools.hud.loglimit.network", 10);
+
+ hud.jsterm.clearOutput();
+ content.console.log("testing Net limits");
+
+ // Find the sentinel entry.
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "testing Net limits",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(() => {
+ // Fill the log with network messages.
+ gCounter = 0;
+ loadImage();
+ });
+}
+
+function loadImage() {
+ if (gCounter < 11) {
+ let body = content.document.getElementsByTagName("body")[0];
+ gImage && gImage.removeEventListener("load", loadImage, true);
+ gImage = content.document.createElement("img");
+ gImage.src = "test-image.png?_fubar=" + gCounter;
+ body.insertBefore(gImage, body.firstChild);
+ gImage.addEventListener("load", loadImage, true);
+ gCounter++;
+ return;
+ }
+
+ is(gCounter, 11, "loaded 11 files");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "test-image.png?_fubar=10",
+ category: CATEGORY_NETWORK,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(() => {
+ testLogEntry(outputNode, "test-image.png?_fubar=0", "first message is pruned", false, true);
+ findLogEntry("test-image.png?_fubar=1");
+ // Check if the sentinel entry is still there.
+ findLogEntry("testing Net limits");
+
+ Services.prefs.clearUserPref("devtools.hud.loglimit.network");
+ testCssLimits();
+ });
+}
+
+function testCssLimits() {
+ Services.prefs.setIntPref("devtools.hud.loglimit.cssparser", 10);
+
+ hud.jsterm.clearOutput();
+ content.console.log("testing CSS limits");
+
+ // Find the sentinel entry.
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "testing CSS limits",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(testCssLimits2);
+}
+
+function testCssLimits2() {
+ // Fill the log with CSS errors.
+ let body = content.document.getElementsByTagName("body")[0];
+ for (let i = 0; i < 11; i++) {
+ var div = content.document.createElement("div");
+ div.setAttribute("style", "-moz-foobar" + i + ": 42;");
+ body.insertBefore(div, body.firstChild);
+ }
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "-moz-foobar10",
+ category: CATEGORY_CSS,
+ severity: SEVERITY_WARNING,
+ }],
+ }).then(() => {
+ testLogEntry(outputNode, "Unknown property '-moz-foobar0'",
+ "first message is pruned", false, true);
+ findLogEntry("Unknown property '-moz-foobar1'");
+ // Check if the sentinel entry is still there.
+ findLogEntry("testing CSS limits");
+
+ Services.prefs.clearUserPref("devtools.hud.loglimit.cssparser");
+ finishTest();
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_646025_console_file_location.js b/browser/devtools/webconsole/test/browser_webconsole_bug_646025_console_file_location.js
new file mode 100644
index 000000000..aeca2751a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_646025_console_file_location.js
@@ -0,0 +1,56 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that console logging methods display the method location along with
+// the output in the console.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/" +
+ "webconsole/test/" +
+ "test-bug-646025-console-file-location.html";
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console file location display test");
+ browser.addEventListener("load", onLoad, true);
+}
+
+function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, function(hud) {
+ content.location = TEST_URI;
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "message for level log",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ source: { url: "test-file-location.js", line: 5 },
+ },
+ {
+ text: "message for level info",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_INFO,
+ source: { url: "test-file-location.js", line: 6 },
+ },
+ {
+ text: "message for level warn",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_WARNING,
+ source: { url: "test-file-location.js", line: 7 },
+ },
+ {
+ text: "message for level error",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_ERROR,
+ source: { url: "test-file-location.js", line: 8 },
+ },
+ {
+ text: "message for level debug",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ source: { url: "test-file-location.js", line: 9 },
+ }],
+ }).then(finishTest);
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js b/browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
new file mode 100644
index 000000000..6b2152637
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
@@ -0,0 +1,106 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that document.body autocompletes in the web console.
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console autocompletion bug in document.body");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+let gHUD;
+
+function consoleOpened(aHud) {
+ gHUD = aHud;
+ let jsterm = gHUD.jsterm;
+ let popup = jsterm.autocompletePopup;
+ let completeNode = jsterm.completeNode;
+
+ let tmp = {};
+ Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
+ let WCU = tmp.WebConsoleUtils;
+ tmp = null;
+
+ ok(!popup.isOpen, "popup is not open");
+
+ popup._panel.addEventListener("popupshown", function onShown() {
+ popup._panel.removeEventListener("popupshown", onShown, false);
+
+ ok(popup.isOpen, "popup is open");
+
+ // expected properties:
+ // __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__
+ // constructor hasOwnProperty isPrototypeOf propertyIsEnumerable
+ // toLocaleString toSource toString unwatch valueOf watch.
+ ok(popup.itemCount >= 14, "popup.itemCount is correct");
+
+ popup._panel.addEventListener("popuphidden", autocompletePopupHidden, false);
+
+ EventUtils.synthesizeKey("VK_ESCAPE", {});
+ }, false);
+
+ jsterm.setInputValue("document.body");
+ EventUtils.synthesizeKey(".", {});
+}
+
+function autocompletePopupHidden()
+{
+ let jsterm = gHUD.jsterm;
+ let popup = jsterm.autocompletePopup;
+ let completeNode = jsterm.completeNode;
+ let inputNode = jsterm.inputNode;
+
+ popup._panel.removeEventListener("popuphidden", autocompletePopupHidden, false);
+
+ ok(!popup.isOpen, "popup is not open");
+ let inputStr = "document.b";
+ jsterm.setInputValue(inputStr);
+ EventUtils.synthesizeKey("o", {});
+ let testStr = inputStr.replace(/./g, " ") + " ";
+
+ waitForSuccess({
+ name: "autocomplete shows document.body",
+ validatorFn: function()
+ {
+ return completeNode.value == testStr + "dy";
+ },
+ successFn: testPropertyPanel,
+ failureFn: finishTest,
+ });
+}
+
+function testPropertyPanel()
+{
+ let jsterm = gHUD.jsterm;
+ jsterm.clearOutput();
+ jsterm.execute("document");
+
+ waitForSuccess({
+ name: "jsterm document object output",
+ validatorFn: function()
+ {
+ return gHUD.outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ jsterm.once("variablesview-fetched", onVariablesViewReady);
+ let node = gHUD.outputNode.querySelector(".webconsole-msg-output");
+ EventUtils.synthesizeMouse(node, 2, 2, {}, gHUD.iframeWindow);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function onVariablesViewReady(aEvent, aView)
+{
+ findVariableViewProperties(aView, [
+ { name: "body", value: "[object HTMLBodyElement]" },
+ ], { webconsole: gHUD }).then(finishTest);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js b/browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js
new file mode 100644
index 000000000..c95163e6b
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js
@@ -0,0 +1,144 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the $0 console helper works as intended.
+
+function createDocument()
+{
+ let doc = content.document;
+ let div = doc.createElement("div");
+ let h1 = doc.createElement("h1");
+ let p1 = doc.createElement("p");
+ let p2 = doc.createElement("p");
+ let div2 = doc.createElement("div");
+ let p3 = doc.createElement("p");
+ doc.title = "Inspector Tree Selection Test";
+ h1.textContent = "Inspector Tree Selection Test";
+ p1.textContent = "This is some example text";
+ p2.textContent = "Lorem ipsum dolor sit amet, consectetur adipisicing " +
+ "elit, sed do eiusmod tempor incididunt ut labore et dolore magna " +
+ "aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
+ "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
+ "dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
+ "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " +
+ "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
+ p3.textContent = "Lorem ipsum dolor sit amet, consectetur adipisicing " +
+ "elit, sed do eiusmod tempor incididunt ut labore et dolore magna " +
+ "aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
+ "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
+ "dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
+ "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " +
+ "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
+ div.appendChild(h1);
+ div.appendChild(p1);
+ div.appendChild(p2);
+ div2.appendChild(p3);
+ doc.body.appendChild(div);
+ doc.body.appendChild(div2);
+ setupHighlighterTests();
+}
+
+function setupHighlighterTests()
+{
+ let h1 = content.document.querySelector("h1");
+ ok(h1, "we have the header node");
+
+ openInspector(runSelectionTests);
+}
+
+function runSelectionTests(aInspector)
+{
+ aInspector.highlighter.unlockAndFocus();
+ aInspector.highlighter.outline.setAttribute("disable-transitions", "true");
+
+ executeSoon(function() {
+ aInspector.selection.once("new-node", performTestComparisons);
+ let h1 = content.document.querySelector("h1");
+ EventUtils.synthesizeMouse(h1, 2, 2, {type: "mousemove"}, content);
+ });
+}
+
+function performTestComparisons()
+{
+ let target = TargetFactory.forTab(gBrowser.selectedTab);
+ let inspector = gDevTools.getToolbox(target).getPanel("inspector");
+ inspector.highlighter.lock();
+
+ let isHighlighting =
+ !(inspector.highlighter.outline.getAttribute("hidden") == "true");
+
+ ok(isHighlighting, "inspector is highlighting");
+
+ let h1 = content.document.querySelector("h1");
+ is(inspector.selection.node, h1, "selection matches node");
+
+ openConsole(gBrowser.selectedTab, performWebConsoleTests);
+}
+
+function performWebConsoleTests(hud)
+{
+ let target = TargetFactory.forTab(gBrowser.selectedTab);
+ let jsterm = hud.jsterm;
+ outputNode = hud.outputNode;
+
+ jsterm.clearOutput();
+ jsterm.execute("$0");
+
+ waitForSuccess({
+ name: "$0 output",
+ validatorFn: function()
+ {
+ return outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ let node = outputNode.querySelector(".webconsole-msg-output");
+ isnot(node.textContent.indexOf("[object HTMLHeadingElement"), -1,
+ "correct output for $0");
+
+ jsterm.clearOutput();
+ jsterm.execute("$0.textContent = 'bug653531'");
+ waitForSuccess(waitForNodeUpdate);
+ },
+ failureFn: finishUp,
+ });
+
+ let waitForNodeUpdate = {
+ name: "$0.textContent update",
+ validatorFn: function()
+ {
+ return outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ let node = outputNode.querySelector(".webconsole-msg-output");
+ isnot(node.textContent.indexOf("bug653531"), -1,
+ "correct output for $0.textContent");
+ let inspector = gDevTools.getToolbox(target).getPanel("inspector");
+ is(inspector.selection.node.textContent, "bug653531",
+ "node successfully updated");
+
+ executeSoon(finishUp);
+ },
+ failureFn: finishUp,
+ };
+}
+
+function finishUp() {
+ finishTest();
+}
+
+function test()
+{
+ waitForExplicitFinish();
+ gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ waitForFocus(createDocument, content);
+ }, true);
+
+ content.location = "data:text/html;charset=utf-8,test for highlighter helper in web console";
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_658368_time_methods.js b/browser/devtools/webconsole/test/browser_webconsole_bug_658368_time_methods.js
new file mode 100644
index 000000000..fac1f3896
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_658368_time_methods.js
@@ -0,0 +1,103 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that the Console API implements the time() and timeEnd() methods.
+
+function test() {
+ addTab("http://example.com/browser/browser/devtools/webconsole/" +
+ "test/test-bug-658368-time-methods.html");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud) {
+ outputNode = hud.outputNode;
+
+ waitForSuccess({
+ name: "aTimer started",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("aTimer: timer started") > -1;
+ },
+ successFn: function()
+ {
+ findLogEntry("ms");
+ // The next test makes sure that timers with the same name but in separate
+ // tabs, do not contain the same value.
+ addTab("data:text/html;charset=utf-8,<script type='text/javascript'>" +
+ "console.timeEnd('bTimer');</script>");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testTimerIndependenceInTabs);
+ }, true);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function testTimerIndependenceInTabs(hud) {
+ outputNode = hud.outputNode;
+
+ executeSoon(function() {
+ testLogEntry(outputNode, "bTimer: timer started", "bTimer was not started",
+ false, true);
+
+ // The next test makes sure that timers with the same name but in separate
+ // pages, do not contain the same value.
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ executeSoon(testTimerIndependenceInSameTab);
+ }, true);
+ content.location = "data:text/html;charset=utf-8,<script type='text/javascript'>" +
+ "console.time('bTimer');</script>";
+ });
+}
+
+function testTimerIndependenceInSameTab() {
+ let hudId = HUDService.getHudIdByWindow(content);
+ let hud = HUDService.hudReferences[hudId];
+ outputNode = hud.outputNode;
+
+ waitForSuccess({
+ name: "bTimer started",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bTimer: timer started") > -1;
+ },
+ successFn: function() {
+ hud.jsterm.clearOutput();
+
+ // Now the following console.timeEnd() call shouldn't display anything,
+ // if the timers in different pages are not related.
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ executeSoon(testTimerIndependenceInSameTabAgain);
+ }, true);
+ content.location = "data:text/html;charset=utf-8," +
+ "<script type='text/javascript'>" +
+ "console.timeEnd('bTimer');</script>";
+ },
+ failureFn: finishTest,
+ });
+}
+
+function testTimerIndependenceInSameTabAgain() {
+ let hudId = HUDService.getHudIdByWindow(content);
+ let hud = HUDService.hudReferences[hudId];
+ outputNode = hud.outputNode;
+
+ executeSoon(function() {
+ testLogEntry(outputNode, "bTimer: timer started", "bTimer was not started",
+ false, true);
+
+ closeConsole(gBrowser.selectedTab, function() {
+ gBrowser.removeCurrentTab();
+ executeSoon(finishTest);
+ });
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_659907_console_dir.js b/browser/devtools/webconsole/test/browser_webconsole_bug_659907_console_dir.js
new file mode 100644
index 000000000..50fc7ce77
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_659907_console_dir.js
@@ -0,0 +1,29 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that console.dir works as intended.
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 659907: Expand console " +
+ "object with a dir method");
+ browser.addEventListener("load", function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud) {
+ hud.jsterm.execute("console.dir(document)");
+ hud.jsterm.once("variablesview-fetched", testConsoleDir.bind(null, hud));
+}
+
+function testConsoleDir(hud, ev, view) {
+ findVariableViewProperties(view, [
+ { name: "__proto__.__proto__.querySelectorAll", value: "[object Function]" },
+ { name: "location", value: "[object Location]" },
+ { name: "__proto__.write", value: "[object Function]" },
+ ], { webconsole: hud }).then(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_660806_history_nav.js b/browser/devtools/webconsole/test/browser_webconsole_bug_660806_history_nav.js
new file mode 100644
index 000000000..ade0c0936
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_660806_history_nav.js
@@ -0,0 +1,48 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>bug 660806 - history navigation must not show the autocomplete popup";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(HUD)
+{
+ content.wrappedJSObject.foobarBug660806 = {
+ "location": "value0",
+ "locationbar": "value1",
+ };
+
+ let jsterm = HUD.jsterm;
+ let popup = jsterm.autocompletePopup;
+ let onShown = function() {
+ ok(false, "popup shown");
+ };
+
+ popup._panel.addEventListener("popupshown", onShown, false);
+
+ ok(!popup.isOpen, "popup is not open");
+
+ ok(!jsterm.lastInputValue, "no lastInputValue");
+ jsterm.setInputValue("window.foobarBug660806.location");
+ is(jsterm.lastInputValue, "window.foobarBug660806.location",
+ "lastInputValue is correct");
+
+ EventUtils.synthesizeKey("VK_RETURN", {});
+ EventUtils.synthesizeKey("VK_UP", {});
+
+ is(jsterm.lastInputValue, "window.foobarBug660806.location",
+ "lastInputValue is correct, again");
+
+ executeSoon(function() {
+ ok(!popup.isOpen, "popup is not open");
+ popup._panel.removeEventListener("popupshown", onShown, false);
+ executeSoon(finishTest);
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_664131_console_group.js b/browser/devtools/webconsole/test/browser_webconsole_bug_664131_console_group.js
new file mode 100644
index 000000000..7f8d568fc
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_664131_console_group.js
@@ -0,0 +1,133 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that console.group/groupEnd works as intended.
+const GROUP_INDENT = 12;
+
+let testDriver, hud;
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 664131: Expand console " +
+ "object with group methods");
+ browser.addEventListener("load", function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ testDriver = testGen();
+ testNext();
+ });
+ }, true);
+}
+
+function testNext() {
+ testDriver.next();
+}
+
+function testGen() {
+ outputNode = hud.outputNode;
+
+ hud.jsterm.clearOutput();
+
+ content.console.group("bug664131a");
+
+ waitForSuccess({
+ name: "console.group displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bug664131a") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
+ is(msg.length, 1, "one message node displayed");
+ is(msg[0].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
+
+ content.console.log("bug664131a-inside");
+
+ waitForSuccess({
+ name: "console.log message displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bug664131a-inside") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
+ is(msg.length, 2, "two message nodes displayed");
+ is(msg[1].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
+
+ content.console.groupEnd("bug664131a");
+ content.console.log("bug664131-outside");
+
+ waitForSuccess({
+ name: "console.log message displayed after groupEnd()",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bug664131-outside") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
+ is(msg.length, 3, "three message nodes displayed");
+ is(msg[2].style.marginLeft, "0px", "correct group indent found");
+
+ content.console.groupCollapsed("bug664131b");
+
+ waitForSuccess({
+ name: "console.groupCollapsed displayed",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bug664131b") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
+ is(msg.length, 4, "four message nodes displayed");
+ is(msg[3].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
+
+
+ // Test that clearing the console removes the indentation.
+ hud.jsterm.clearOutput();
+ content.console.log("bug664131-cleared");
+
+ waitForSuccess({
+ name: "console.log displayed after clearOutput",
+ validatorFn: function()
+ {
+ return outputNode.textContent.indexOf("bug664131-cleared") > -1;
+ },
+ successFn: testNext,
+ failureFn: finishTest,
+ });
+
+ yield;
+
+ msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
+ is(msg.length, 1, "one message node displayed");
+ is(msg[0].style.marginLeft, "0px", "correct group indent found");
+
+ testDriver = hud = null;
+ finishTest();
+
+ yield;
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_704295.js b/browser/devtools/webconsole/test/browser_webconsole_bug_704295.js
new file mode 100644
index 000000000..c85c52d13
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_704295.js
@@ -0,0 +1,42 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests for bug 704295
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testCompletion);
+ }, true);
+}
+
+function testCompletion(hud) {
+ var jsterm = hud.jsterm;
+ var input = jsterm.inputNode;
+
+ // Test typing 'var d = 5;' and press RETURN
+ jsterm.setInputValue("var d = ");
+ EventUtils.synthesizeKey("5", {});
+ EventUtils.synthesizeKey(";", {});
+ is(input.value, "var d = 5;", "var d = 5;");
+ is(jsterm.completeNode.value, "", "no completion");
+ EventUtils.synthesizeKey("VK_ENTER", {});
+ is(jsterm.completeNode.value, "", "clear completion on execute()");
+
+ // Test typing 'var a = d' and press RETURN
+ jsterm.setInputValue("var a = ");
+ EventUtils.synthesizeKey("d", {});
+ is(input.value, "var a = d", "var a = d");
+ is(jsterm.completeNode.value, "", "no completion");
+ EventUtils.synthesizeKey("VK_ENTER", {});
+ is(jsterm.completeNode.value, "", "clear completion on execute()");
+
+ jsterm = input = null;
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_734061_No_input_change_and_Tab_key_pressed.js b/browser/devtools/webconsole/test/browser_webconsole_bug_734061_No_input_change_and_Tab_key_pressed.js
new file mode 100644
index 000000000..6433e0f71
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_734061_No_input_change_and_Tab_key_pressed.js
@@ -0,0 +1,39 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testInputChange);
+ }, true);
+}
+
+function testInputChange(hud) {
+ var jsterm = hud.jsterm;
+ var input = jsterm.inputNode;
+
+ is(input.getAttribute("focused"), "true", "input has focus");
+ EventUtils.synthesizeKey("VK_TAB", {});
+ is(input.getAttribute("focused"), "", "focus moved away");
+
+ // Test user changed something
+ input.focus();
+ EventUtils.synthesizeKey("A", {});
+ EventUtils.synthesizeKey("VK_TAB", {});
+ is(input.getAttribute("focused"), "true", "input is still focused");
+
+ // Test non empty input but not changed since last focus
+ input.blur();
+ input.focus();
+ EventUtils.synthesizeKey("VK_RIGHT", {});
+ EventUtils.synthesizeKey("VK_TAB", {});
+ is(input.getAttribute("focused"), "", "input moved away");
+
+ jsterm = input = null;
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js b/browser/devtools/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js
new file mode 100644
index 000000000..14c9714f3
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js
@@ -0,0 +1,96 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Tanvi Vyas <tanvi@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that the Web Console Mixed Content messages are displayed
+
+const TEST_HTTPS_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html";
+
+var origBlockDisplay;
+var origBlockActive;
+
+function test() {
+ addTab("data:text/html;charset=utf8,Web Console mixed content test");
+ browser.addEventListener("load", onLoad, true);
+}
+
+function onLoad(aEvent) {
+ browser.removeEventListener("load", onLoad, true);
+ origBlockDisplay = Services.prefs.getBoolPref("security.mixed_content.block_display_content");
+ origBlockActive = Services.prefs.getBoolPref("security.mixed_content.block_active_content")
+ Services.prefs.setBoolPref("security.mixed_content.block_display_content", false);
+ Services.prefs.setBoolPref("security.mixed_content.block_active_content", false);
+ openConsole(null, testMixedContent);
+}
+
+function testMixedContent(hud) {
+ content.location = TEST_HTTPS_URI;
+ var aOutputNode = hud.outputNode;
+
+ waitForSuccess(
+ {
+ name: "mixed content warning displayed successfully",
+ timeout: 20000,
+ validatorFn: function() {
+ return ( aOutputNode.querySelector(".webconsole-mixed-content") );
+ },
+
+ successFn: function() {
+
+ //tests on the urlnode
+ let node = aOutputNode.querySelector(".webconsole-mixed-content");
+ ok(testSeverity(node), "Severity type is SEVERITY_WARNING.");
+
+ //tests on the warningNode
+ let warningNode = aOutputNode.querySelector(".webconsole-mixed-content-link");
+ is(warningNode.value, "[Mixed Content]", "Message text is accurate." );
+ testClickOpenNewTab(warningNode);
+
+ endTest();
+ },
+
+ failureFn: endTest,
+ }
+ );
+
+}
+
+function testSeverity(node) {
+ let linkNode = node.parentNode;
+ let msgNode = linkNode.parentNode;
+ let bodyNode = msgNode.parentNode;
+ let finalNode = bodyNode.parentNode;
+
+ return finalNode.classList.contains("webconsole-msg-warn");
+}
+
+function testClickOpenNewTab(warningNode) {
+ /* Invoke the click event and check if a new tab would open to the correct page */
+ let linkOpened = false;
+ let oldOpenUILinkIn = window.openUILinkIn;
+
+ window.openUILinkIn = function(aLink) {
+ if (aLink == "https://developer.mozilla.org/en/Security/MixedContent") {
+ linkOpened = true;
+ }
+ }
+
+ EventUtils.synthesizeMouse(warningNode, 2, 2, {},
+ warningNode.ownerDocument.defaultView);
+
+ ok(linkOpened, "Clicking the Mixed Content Warning node opens the desired page");
+
+ window.openUILinkIn = oldOpenUILinkIn;
+}
+
+function endTest() {
+ Services.prefs.setBoolPref("security.mixed_content.block_display_content", origBlockDisplay);
+ Services.prefs.setBoolPref("security.mixed_content.block_active_content", origBlockActive);
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_764572_output_open_url.js b/browser/devtools/webconsole/test/browser_webconsole_bug_764572_output_open_url.js
new file mode 100644
index 000000000..a87066dd6
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_764572_output_open_url.js
@@ -0,0 +1,119 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This is a test for the Open URL context menu item
+// that is shown for network requests
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html"
+const COMMAND_NAME = "consoleCmd_openURL";
+const CONTEXT_MENU_ID = "#menu_openURL";
+
+let HUD = null, outputNode = null, contextMenu = null;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(aHud) {
+ HUD = aHud;
+ outputNode = aHud.outputNode;
+ contextMenu = HUD.iframeWindow.document.getElementById("output-contextmenu");
+
+ registerCleanupFunction(() => {
+ HUD = outputNode = contextMenu = null;
+ });
+
+ HUD.jsterm.clearOutput();
+
+ content.console.log("bug 764572");
+
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ text: "bug 764572",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onConsoleMessage);
+}
+
+function onConsoleMessage(aResults) {
+ outputNode.focus();
+ outputNode.selectedItem = [...aResults[0].matched][0];
+
+ // Check if the command is disabled non-network messages.
+ goUpdateCommand(COMMAND_NAME);
+ let controller = top.document.commandDispatcher
+ .getControllerForCommand(COMMAND_NAME);
+
+ let isDisabled = !controller || !controller.isCommandEnabled(COMMAND_NAME);
+ ok(isDisabled, COMMAND_NAME + " should be disabled.");
+
+ waitForContextMenu(contextMenu, outputNode.selectedItem, () => {
+ let isHidden = contextMenu.querySelector(CONTEXT_MENU_ID).hidden;
+ ok(isHidden, CONTEXT_MENU_ID + " should be hidden.");
+ }, testOnNetActivity);
+}
+
+function testOnNetActivity() {
+ HUD.jsterm.clearOutput();
+
+ // Reload the url to show net activity in console.
+ content.location.reload();
+
+ waitForMessages({
+ webconsole: HUD,
+ messages: [{
+ text: "test-console.html",
+ category: CATEGORY_NETWORK,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(onNetworkMessage);
+}
+
+function onNetworkMessage(aResults) {
+ outputNode.focus();
+ outputNode.selectedItem = [...aResults[0].matched][0];
+
+ let currentTab = gBrowser.selectedTab;
+ let newTab = null;
+
+ gBrowser.tabContainer.addEventListener("TabOpen", function onOpen(aEvent) {
+ gBrowser.tabContainer.removeEventListener("TabOpen", onOpen, true);
+ newTab = aEvent.target;
+ newTab.linkedBrowser.addEventListener("load", onTabLoaded, true);
+ }, true);
+
+ function onTabLoaded() {
+ newTab.linkedBrowser.removeEventListener("load", onTabLoaded, true);
+ gBrowser.removeTab(newTab);
+ gBrowser.selectedTab = currentTab;
+ executeSoon(testOnNetActivity_contextmenu);
+ }
+
+ // Check if the command is enabled for a network message.
+ goUpdateCommand(COMMAND_NAME);
+ let controller = top.document.commandDispatcher
+ .getControllerForCommand(COMMAND_NAME);
+ ok(controller.isCommandEnabled(COMMAND_NAME),
+ COMMAND_NAME + " should be enabled.");
+
+ // Try to open the URL.
+ goDoCommand(COMMAND_NAME);
+}
+
+function testOnNetActivity_contextmenu() {
+ let target = outputNode.querySelector(".webconsole-msg-network");
+
+ outputNode.focus();
+ outputNode.selectedItem = target;
+
+ waitForContextMenu(contextMenu, target, () => {
+ let isShown = !contextMenu.querySelector(CONTEXT_MENU_ID).hidden;
+ ok(isShown, CONTEXT_MENU_ID + " should be shown.");
+ }, finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js b/browser/devtools/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js
new file mode 100644
index 000000000..b60fb70bf
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js
@@ -0,0 +1,113 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test" +
+ "/test-bug-766001-js-console-links.html";
+
+let nodes, dbg, toolbox, target, index = 0, src, line;
+
+function test()
+{
+ expectUncaughtException();
+ requestLongerTimeout(2);
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testViewSource);
+ }, true);
+}
+
+function testViewSource(aHud)
+{
+ registerCleanupFunction(function() {
+ nodes = dbg = toolbox = target = index = src = line = null;
+ });
+
+ let JSSelector = ".webconsole-msg-exception .webconsole-location";
+ let consoleSelector = ".webconsole-msg-console .webconsole-location";
+
+ waitForSuccess({
+ name: "find the location node",
+ validatorFn: function()
+ {
+ return aHud.outputNode.querySelector(JSSelector) &&
+ aHud.outputNode.querySelector(consoleSelector);
+ },
+ successFn: function()
+ {
+ nodes = [aHud.outputNode.querySelector(JSSelector),
+ aHud.outputNode.querySelector(consoleSelector)];
+
+ target = TargetFactory.forTab(gBrowser.selectedTab);
+ toolbox = gDevTools.getToolbox(target);
+ toolbox.once("jsdebugger-selected", checkLineAndClickNext);
+
+ EventUtils.sendMouseEvent({ type: "click" }, nodes[index%2]);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function checkLineAndClickNext(aEvent, aPanel)
+{
+ if (index == 3) {
+ finishTest();
+ return;
+ }
+ info(aEvent + " event fired for index " + index);
+
+ dbg = aPanel;
+
+ src = nodes[index%2].getAttribute("title");
+ ok(src, "source url found for index " + index);
+ line = nodes[index%2].sourceLine;
+ ok(line, "found source line for index " + index);
+
+ info("Waiting for the correct script to be selected for index " + index);
+ dbg.panelWin.addEventListener("Debugger:SourceShown", onSource, false);
+}
+
+function onSource(aEvent) {
+ if (aEvent.detail.url != src) {
+ return;
+ }
+ dbg.panelWin.removeEventListener("Debugger:SourceShown", onSource, false);
+
+ ok(true, "Correct script is selected for index " + index);
+
+ checkCorrectLine(function() {
+ gDevTools.showToolbox(target, "webconsole").then(function() {
+ index++;
+ info("webconsole selected for index " + index);
+
+ toolbox.once("jsdebugger-selected", checkLineAndClickNext);
+
+ EventUtils.sendMouseEvent({ type: "click" }, nodes[index%2]);
+ });
+ });
+}
+
+function checkCorrectLine(aCallback)
+{
+ waitForSuccess({
+ name: "correct source and line test for debugger for index " + index,
+ validatorFn: function()
+ {
+ let debuggerView = dbg.panelWin.DebuggerView;
+ if (debuggerView.editor &&
+ debuggerView.editor.getCaretPosition().line == line - 1) {
+ return true;
+ }
+ return false;
+ },
+ successFn: function()
+ {
+ aCallback && executeSoon(aCallback);
+ },
+ failureFn: finishTest,
+ timeout: 10000,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_770099_bad_policyuri.js b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_bad_policyuri.js
new file mode 100644
index 000000000..cd9c0fcc8
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_bad_policyuri.js
@@ -0,0 +1,55 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that the Web Console CSP messages are displayed
+
+const TEST_BAD_POLICY_URI = "https://example.com/browser/browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html";
+
+let hud = undefined;
+
+function test() {
+ addTab("data:text/html;charset=utf8,Web Console CSP bad policy URI test");
+ browser.addEventListener("load", function _onLoad() {
+ browser.removeEventListener("load", _onLoad, true);
+ openConsole(null, loadDocument);
+ }, true);
+}
+
+function loadDocument(theHud) {
+ hud = theHud;
+ hud.jsterm.clearOutput();
+ browser.addEventListener("load", onLoad, true);
+ content.location = TEST_BAD_POLICY_URI;
+}
+
+function onLoad(aEvent) {
+ browser.removeEventListener("load", onLoad, true);
+ testPolicyURIMessage();
+}
+
+function testPolicyURIMessage() {
+ let aOutputNode = hud.outputNode;
+
+ waitForSuccess(
+ {
+ name: "CSP policy URI warning displayed successfully",
+ validatorFn: function() {
+ return aOutputNode.querySelector(".webconsole-msg-error");
+ },
+
+ successFn: function() {
+ //tests on the urlnode
+ let node = aOutputNode.querySelector(".webconsole-msg-error");
+ isnot(node.textContent.indexOf("can't fetch policy"), -1,
+ "CSP Policy URI message found");
+ finishTest();
+ },
+
+ failureFn: finishTest,
+ }
+ );
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js
new file mode 100644
index 000000000..893401be6
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js
@@ -0,0 +1,46 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that the Web Console CSP messages are displayed
+
+const TEST_VIOLATION = "https://example.com/browser/browser/devtools/webconsole/test/test_bug_770099_violation.html";
+const CSP_VIOLATION_MSG = "Content Security Policy: Directive default-src https://example.com:443 violated by http://some.example.com/test.png"
+
+let hud = undefined;
+
+function test() {
+ addTab("data:text/html;charset=utf8,Web Console CSP violation test");
+ browser.addEventListener("load", function _onLoad() {
+ browser.removeEventListener("load", _onLoad, true);
+ openConsole(null, loadDocument);
+ }, true);
+}
+
+function loadDocument(theHud){
+ hud = theHud;
+ hud.jsterm.clearOutput()
+ browser.addEventListener("load", onLoad, true);
+ content.location = TEST_VIOLATION;
+}
+
+function onLoad(aEvent) {
+ browser.removeEventListener("load", onLoad, true);
+ testViolationMessage();
+}
+
+function testViolationMessage(){
+ let aOutputNode = hud.outputNode;
+
+ waitForSuccess({
+ name: "CSP policy URI warning displayed successfully",
+ validatorFn: function() {
+ return hud.outputNode.textContent.indexOf(CSP_VIOLATION_MSG) > -1;
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js b/browser/devtools/webconsole/test/browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js
new file mode 100644
index 000000000..a8e7ed87a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js
@@ -0,0 +1,150 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test" +
+ "/test-bug-782653-css-errors.html";
+
+let nodes, hud, StyleEditorUI;
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testViewSource);
+ }, true);
+}
+
+function testViewSource(aHud)
+{
+ hud = aHud;
+
+ registerCleanupFunction(function() {
+ nodes = hud = StyleEditorUI = null;
+ });
+
+ let selector = ".webconsole-msg-cssparser .webconsole-location";
+
+ waitForSuccess({
+ name: "find the location node",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(selector);
+ },
+ successFn: function()
+ {
+ nodes = hud.outputNode.querySelectorAll(selector);
+ is(nodes.length, 2, "correct number of css messages");
+
+ let target = TargetFactory.forTab(gBrowser.selectedTab);
+ let toolbox = gDevTools.getToolbox(target);
+ toolbox.once("styleeditor-selected", (event, panel) => {
+ StyleEditorUI = panel.UI;
+
+ let count = 0;
+ StyleEditorUI.on("editor-added", function() {
+ if (++count == 2) {
+ onStyleEditorReady(panel);
+ }
+ });
+ });
+
+ EventUtils.sendMouseEvent({ type: "click" }, nodes[0]);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function onStyleEditorReady(aPanel)
+{
+ let win = aPanel.panelWindow;
+ ok(win, "Style Editor Window is defined");
+ ok(StyleEditorUI, "Style Editor UI is defined");
+
+ waitForFocus(function() {
+ info("style editor window focused");
+
+ let href = nodes[0].getAttribute("title");
+ let line = nodes[0].sourceLine;
+ ok(line, "found source line");
+
+ checkStyleEditorForSheetAndLine(href, line - 1, function() {
+ info("first check done");
+
+ let target = TargetFactory.forTab(gBrowser.selectedTab);
+ let toolbox = gDevTools.getToolbox(target);
+
+ let href = nodes[1].getAttribute("title");
+ let line = nodes[1].sourceLine;
+ ok(line, "found source line");
+
+ toolbox.selectTool("webconsole").then(function() {
+ info("webconsole selected");
+
+ toolbox.once("styleeditor-selected", function(aEvent) {
+ info(aEvent + " event fired");
+
+ checkStyleEditorForSheetAndLine(href, line - 1, function() {
+ info("second check done");
+ finishTest();
+ });
+ });
+
+ EventUtils.sendMouseEvent({ type: "click" }, nodes[1]);
+ });
+ });
+ }, win);
+}
+
+function checkStyleEditorForSheetAndLine(aHref, aLine, aCallback)
+{
+ let foundEditor = null;
+ waitForSuccess({
+ name: "style editor for stylesheet",
+ validatorFn: function()
+ {
+ for (let editor of StyleEditorUI.editors) {
+ if (editor.styleSheet.href == aHref) {
+ foundEditor = editor;
+ return true;
+ }
+ }
+ return false;
+ },
+ successFn: function()
+ {
+ performLineCheck(foundEditor, aLine, aCallback);
+ },
+ failureFn: finishTest,
+ });
+}
+
+function performLineCheck(aEditor, aLine, aCallback)
+{
+ function checkForCorrectState()
+ {
+ is(aEditor.sourceEditor.getCaretPosition().line, aLine,
+ "correct line is selected");
+ is(StyleEditorUI.selectedStyleSheetIndex, aEditor.styleSheet.styleSheetIndex,
+ "correct stylesheet is selected in the editor");
+
+ aCallback && executeSoon(aCallback);
+ }
+
+ waitForSuccess({
+ name: "source editor load",
+ validatorFn: function()
+ {
+ return aEditor.sourceEditor;
+ },
+ successFn: checkForCorrectState,
+ failureFn: function() {
+ info("selectedStyleSheetIndex " + StyleEditorUI.selectedStyleSheetIndex
+ + " expected " + aEditor.styleSheet.styleSheetIndex);
+ finishTest();
+ },
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_804845_ctrl_key_nav.js b/browser/devtools/webconsole/test/browser_webconsole_bug_804845_ctrl_key_nav.js
new file mode 100644
index 000000000..1efd9c141
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_804845_ctrl_key_nav.js
@@ -0,0 +1,214 @@
+/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * zmgmoz <zmgmoz@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Test navigation of webconsole contents via ctrl-a, ctrl-e, ctrl-p, ctrl-n
+// see https://bugzilla.mozilla.org/show_bug.cgi?id=804845
+
+let jsterm, inputNode;
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 804845 and bug 619598");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, doTests);
+ }, true);
+}
+
+function doTests(HUD) {
+ jsterm = HUD.jsterm;
+ inputNode = jsterm.inputNode;
+ ok(!jsterm.inputNode.value, "inputNode.value is empty");
+ is(jsterm.inputNode.selectionStart, 0);
+ is(jsterm.inputNode.selectionEnd, 0);
+
+ testSingleLineInputNavNoHistory();
+ testMultiLineInputNavNoHistory();
+ testNavWithHistory();
+
+ jsterm = inputNode = null;
+ executeSoon(finishTest);
+}
+
+function testSingleLineInputNavNoHistory() {
+ // Single char input
+ EventUtils.synthesizeKey("1", {});
+ is(inputNode.selectionStart, 1, "caret location after single char input");
+
+ // nav to start/end with ctrl-a and ctrl-e;
+ EventUtils.synthesizeKey("a", { ctrlKey: true });
+ is(inputNode.selectionStart, 0, "caret location after single char input and ctrl-a");
+
+ EventUtils.synthesizeKey("e", { ctrlKey: true });
+ is(inputNode.selectionStart, 1, "caret location after single char input and ctrl-e");
+
+ // Second char input
+ EventUtils.synthesizeKey("2", {});
+ // nav to start/end with up/down keys; verify behaviour using ctrl-p/ctrl-n
+ EventUtils.synthesizeKey("VK_UP", {});
+ is(inputNode.selectionStart, 0, "caret location after two char input and VK_UP");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ is(inputNode.selectionStart, 2, "caret location after two char input and VK_DOWN");
+
+ EventUtils.synthesizeKey("a", { ctrlKey: true });
+ is(inputNode.selectionStart, 0, "move caret to beginning of 2 char input with ctrl-a");
+ EventUtils.synthesizeKey("a", { ctrlKey: true });
+ is(inputNode.selectionStart, 0, "no change of caret location on repeat ctrl-a");
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.selectionStart, 0, "no change of caret location on ctrl-p from beginning of line");
+
+ EventUtils.synthesizeKey("e", { ctrlKey: true });
+ is(inputNode.selectionStart, 2, "move caret to end of 2 char input with ctrl-e");
+ EventUtils.synthesizeKey("e", { ctrlKey: true });
+ is(inputNode.selectionStart, 2, "no change of caret location on repeat ctrl-e");
+ EventUtils.synthesizeKey("n", { ctrlKey: true });
+ is(inputNode.selectionStart, 2, "no change of caret location on ctrl-n from end of line");
+
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.selectionStart, 0, "ctrl-p moves to start of line");
+
+ EventUtils.synthesizeKey("n", { ctrlKey: true });
+ is(inputNode.selectionStart, 2, "ctrl-n moves to end of line");
+}
+
+function testMultiLineInputNavNoHistory() {
+ let lineValues = ["one", "2", "something longer", "", "", "three!"];
+ jsterm.setInputValue("");
+ // simulate shift-return
+ for (let i = 0; i < lineValues.length; i++) {
+ jsterm.setInputValue(inputNode.value + lineValues[i]);
+ EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
+ }
+ let inputValue = inputNode.value;
+ is(inputNode.selectionStart, inputNode.selectionEnd);
+ is(inputNode.selectionStart, inputValue.length, "caret at end of multiline input");
+
+ // possibility newline is represented by one ('\r', '\n') or two ('\r\n') chars
+ let newlineString = inputValue.match(/(\r\n?|\n\r?)$/)[0];
+
+ // Ok, test navigating within the multi-line string!
+ EventUtils.synthesizeKey("VK_UP", {});
+ let expectedStringAfterCarat = lineValues[5]+newlineString;
+ is(inputNode.value.slice(inputNode.selectionStart), expectedStringAfterCarat,
+ "up arrow from end of multiline");
+
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ is(inputNode.value.slice(inputNode.selectionStart), "",
+ "down arrow from within multiline");
+
+ // navigate up through input lines
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.value.slice(inputNode.selectionStart), expectedStringAfterCarat,
+ "ctrl-p from end of multiline");
+
+ for (let i = 4; i >= 0; i--) {
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ expectedStringAfterCarat = lineValues[i] + newlineString + expectedStringAfterCarat;
+ is(inputNode.value.slice(inputNode.selectionStart), expectedStringAfterCarat,
+ "ctrl-p from within line " + i + " of multiline input");
+ }
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.selectionStart, 0, "reached start of input");
+ is(inputNode.value, inputValue,
+ "no change to multiline input on ctrl-p from beginning of multiline");
+
+ // navigate to end of first line
+ EventUtils.synthesizeKey("e", { ctrlKey: true });
+ let caretPos = inputNode.selectionStart;
+ let expectedStringBeforeCarat = lineValues[0];
+ is(inputNode.value.slice(0, caretPos), expectedStringBeforeCarat,
+ "ctrl-e into multiline input");
+ EventUtils.synthesizeKey("e", { ctrlKey: true });
+ is(inputNode.selectionStart, caretPos,
+ "repeat ctrl-e doesn't change caret position in multiline input");
+
+ // navigate down one line; ctrl-a to the beginning; ctrl-e to end
+ for (let i = 1; i < lineValues.length; i++) {
+ EventUtils.synthesizeKey("n", { ctrlKey: true });
+ EventUtils.synthesizeKey("a", { ctrlKey: true });
+ caretPos = inputNode.selectionStart;
+ expectedStringBeforeCarat += newlineString;
+ is(inputNode.value.slice(0, caretPos), expectedStringBeforeCarat,
+ "ctrl-a to beginning of line " + (i+1) + " in multiline input");
+
+ EventUtils.synthesizeKey("e", { ctrlKey: true });
+ caretPos = inputNode.selectionStart;
+ expectedStringBeforeCarat += lineValues[i];
+ is(inputNode.value.slice(0, caretPos), expectedStringBeforeCarat,
+ "ctrl-e to end of line " + (i+1) + "in multiline input");
+ }
+}
+
+function testNavWithHistory() {
+ // NOTE: Tests does NOT currently define behaviour for ctrl-p/ctrl-n with
+ // caret placed _within_ single line input
+ let values = ['"single line input"',
+ '"a longer single-line input to check caret repositioning"',
+ ['"multi-line"', '"input"', '"here!"'].join("\n"),
+ ];
+ // submit to history
+ for (let i = 0; i < values.length; i++) {
+ jsterm.setInputValue(values[i]);
+ jsterm.execute();
+ }
+ is(inputNode.selectionStart, 0, "caret location at start of empty line");
+
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.selectionStart, values[values.length-1].length,
+ "caret location correct at end of last history input");
+
+ // Navigate backwards history with ctrl-p
+ for (let i = values.length-1; i > 0; i--) {
+ let match = values[i].match(/(\n)/g);
+ if (match) {
+ // multi-line inputs won't update from history unless caret at beginning
+ EventUtils.synthesizeKey("a", { ctrlKey: true });
+ for (let i = 0; i < match.length; i++) {
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ }
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ } else {
+ // single-line inputs will update from history from end of line
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ }
+ is(inputNode.value, values[i-1],
+ "ctrl-p updates inputNode from backwards history values[" + i-1 + "]");
+ }
+ let inputValue = inputNode.value;
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.selectionStart, 0,
+ "ctrl-p at beginning of history moves caret location to beginning of line");
+ is(inputNode.value, inputValue,
+ "no change to input value on ctrl-p from beginning of line");
+
+ // Navigate forwards history with ctrl-n
+ for (let i = 1; i<values.length; i++) {
+ EventUtils.synthesizeKey("n", { ctrlKey: true });
+ is(inputNode.value, values[i],
+ "ctrl-n updates inputNode from forwards history values[" + i + "]");
+ is(inputNode.selectionStart, values[i].length,
+ "caret location correct at end of history input for values[" + i + "]");
+ }
+ EventUtils.synthesizeKey("n", { ctrlKey: true });
+ ok(!inputNode.value, "ctrl-n at end of history updates to empty input");
+
+ // Simulate editing multi-line
+ inputValue = "one\nlinebreak";
+ jsterm.setInputValue(inputValue);
+
+ // Attempt nav within input
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.value, inputValue,
+ "ctrl-p from end of multi-line does not trigger history");
+
+ EventUtils.synthesizeKey("a", { ctrlKey: true });
+ EventUtils.synthesizeKey("p", { ctrlKey: true });
+ is(inputNode.value, values[values.length-1],
+ "ctrl-p from start of multi-line triggers history");
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_817834_add_edited_input_to_history.js b/browser/devtools/webconsole/test/browser_webconsole_bug_817834_add_edited_input_to_history.js
new file mode 100644
index 000000000..2f075a3a4
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_817834_add_edited_input_to_history.js
@@ -0,0 +1,61 @@
+/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * zmgmoz <zmgmoz@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Test that user input that is not submitted in the command line input is not
+// lost after navigating in history.
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=817834
+
+function test() {
+ addTab("data:text/html;charset=utf-8,Web Console test for bug 817834");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testEditedInputHistory);
+ }, true);
+}
+
+function testEditedInputHistory(HUD) {
+ let jsterm = HUD.jsterm;
+ let inputNode = jsterm.inputNode;
+ ok(!inputNode.value, "inputNode.value is empty");
+ is(inputNode.selectionStart, 0);
+ is(inputNode.selectionEnd, 0);
+
+ jsterm.setInputValue('"first item"');
+ EventUtils.synthesizeKey("VK_UP", {});
+ is(inputNode.value, '"first item"', "null test history up");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ is(inputNode.value, '"first item"', "null test history down");
+
+ jsterm.execute();
+ is(inputNode.value, "", "cleared input line after submit");
+
+ jsterm.setInputValue('"editing input 1"');
+ EventUtils.synthesizeKey("VK_UP", {});
+ is(inputNode.value, '"first item"', "test history up");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ is(inputNode.value, '"editing input 1"',
+ "test history down restores in-progress input");
+
+ jsterm.setInputValue('"second item"');
+ jsterm.execute();
+ jsterm.setInputValue('"editing input 2"');
+ EventUtils.synthesizeKey("VK_UP", {});
+ is(inputNode.value, '"second item"', "test history up");
+ EventUtils.synthesizeKey("VK_UP", {});
+ is(inputNode.value, '"first item"', "test history up");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ is(inputNode.value, '"second item"', "test history down");
+ EventUtils.synthesizeKey("VK_DOWN", {});
+ is(inputNode.value, '"editing input 2"',
+ "test history down restores new in-progress input again");
+
+ executeSoon(finishTest);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_821877_csp_errors.js b/browser/devtools/webconsole/test/browser_webconsole_bug_821877_csp_errors.js
new file mode 100644
index 000000000..dae8f4d8b
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_821877_csp_errors.js
@@ -0,0 +1,28 @@
+// Tests that CSP errors from nsDocument::InitCSP are logged to the Web Console
+
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-bug-821877-csperrors.html";
+const CSP_DEPRECATED_HEADER_MSG = "The X-Content-Security-Policy and X-Content-Security-Report-Only headers will be deprecated in the future. Please use the Content-Security-Policy and Content-Security-Report-Only headers with CSP spec compliant syntax instead.";
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, function testCSPErrorLogged (hud) {
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "Deprecated CSP header error displayed successfully",
+ text: CSP_DEPRECATED_HEADER_MSG,
+ category: CATEGORY_SECURITY,
+ severity: SEVERITY_WARNING
+ },
+ ],
+ }).then(finishTest);
+ });
+ }, true);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_837351_securityerrors.js b/browser/devtools/webconsole/test/browser_webconsole_bug_837351_securityerrors.js
new file mode 100644
index 000000000..19705326d
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_837351_securityerrors.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-bug-837351-security-errors.html";
+
+function run_test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad(aEvent) {
+ browser.removeEventListener(aEvent.type, onLoad, true);
+ openConsole(null, function testSecurityErrorLogged (hud) {
+ let button = hud.ui.rootElement.querySelector(".webconsole-filter-button[category=\"security\"]");
+ ok(button, "Found security button in the web console");
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [
+ {
+ name: "Logged blocking mixed active content",
+ text: "Blocked loading mixed active content \"http://example.com/\"",
+ category: CATEGORY_SECURITY,
+ severity: SEVERITY_ERROR
+ },
+ ],
+ }).then(finishTest);
+ });
+ }, true);
+}
+
+function test()
+{
+ SpecialPowers.pushPrefEnv({'set': [["security.mixed_content.block_active_content", true]]}, run_test);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_change_font_size.js b/browser/devtools/webconsole/test/browser_webconsole_change_font_size.js
new file mode 100644
index 000000000..babfddabb
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_change_font_size.js
@@ -0,0 +1,44 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Jennifer Fong <jfong@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ Services.prefs.setIntPref("devtools.webconsole.fontSize", 10);
+ openConsole(null, testFontSizeChange);
+ }, true);
+}
+
+function testFontSizeChange(hud) {
+ let inputNode = hud.jsterm.inputNode;
+ let outputNode = hud.jsterm.outputNode;
+ outputNode.focus();
+
+ EventUtils.synthesizeKey("-", { accelKey: true });
+ is(inputNode.style.fontSize, "10px", "input font stays at same size with ctrl+-");
+ is(outputNode.style.fontSize, inputNode.style.fontSize, "output font stays at same size with ctrl+-");
+
+ EventUtils.synthesizeKey("=", { accelKey: true });
+ is(inputNode.style.fontSize, "11px", "input font increased with ctrl+=");
+ is(outputNode.style.fontSize, inputNode.style.fontSize, "output font stays at same size with ctrl+=");
+
+ EventUtils.synthesizeKey("-", { accelKey: true });
+ is(inputNode.style.fontSize, "10px", "font decreased with ctrl+-");
+ is(outputNode.style.fontSize, inputNode.style.fontSize, "output font stays at same size with ctrl+-");
+
+ EventUtils.synthesizeKey("0", { accelKey: true });
+ is(inputNode.style.fontSize, "", "font reset with ctrl+0");
+ is(outputNode.style.fontSize, inputNode.style.fontSize, "output font stays at same size with ctrl+0");
+
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_chrome.js b/browser/devtools/webconsole/test/browser_webconsole_chrome.js
new file mode 100644
index 000000000..a04a011a7
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_chrome.js
@@ -0,0 +1,35 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that code completion works properly.
+
+function test() {
+ addTab("about:config");
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testChrome);
+ }, true);
+}
+
+function testChrome(hud) {
+ ok(hud, "we have a console");
+
+ ok(hud.iframeWindow, "we have the console UI window");
+
+ let jsterm = hud.jsterm;
+ ok(jsterm, "we have a jsterm");
+
+ let input = jsterm.inputNode;
+ ok(hud.outputNode, "we have an output node");
+
+ // Test typing 'docu'.
+ input.value = "docu";
+ input.setSelectionRange(4, 4);
+ jsterm.complete(jsterm.COMPLETE_HINT_ONLY, function() {
+ is(jsterm.completeNode.value, " ment", "'docu' completion");
+ executeSoon(finishTest);
+ });
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_completion.js b/browser/devtools/webconsole/test/browser_webconsole_completion.js
new file mode 100644
index 000000000..fc27c7397
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_completion.js
@@ -0,0 +1,120 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that code completion works properly.
+
+const TEST_URI = "data:text/html;charset=utf8,<p>test code completion";
+
+let testDriver;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, function(hud) {
+ testDriver = testCompletion(hud);
+ testDriver.next();
+ });
+ }, true);
+}
+
+function testNext() {
+ executeSoon(function() {
+ testDriver.next();
+ });
+}
+
+function testCompletion(hud) {
+ let jsterm = hud.jsterm;
+ let input = jsterm.inputNode;
+
+ // Test typing 'docu'.
+ input.value = "docu";
+ input.setSelectionRange(4, 4);
+ jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
+ yield;
+
+ is(input.value, "docu", "'docu' completion (input.value)");
+ is(jsterm.completeNode.value, " ment", "'docu' completion (completeNode)");
+
+ // Test typing 'docu' and press tab.
+ input.value = "docu";
+ input.setSelectionRange(4, 4);
+ jsterm.complete(jsterm.COMPLETE_FORWARD, testNext);
+ yield;
+
+ is(input.value, "document", "'docu' tab completion");
+ is(input.selectionStart, 8, "start selection is alright");
+ is(input.selectionEnd, 8, "end selection is alright");
+ is(jsterm.completeNode.value.replace(/ /g, ""), "", "'docu' completed");
+
+ // Test typing 'window.Ob' and press tab. Just 'window.O' is
+ // ambiguous: could be window.Object, window.Option, etc.
+ input.value = "window.Ob";
+ input.setSelectionRange(9, 9);
+ jsterm.complete(jsterm.COMPLETE_FORWARD, testNext);
+ yield;
+
+ is(input.value, "window.Object", "'window.Ob' tab completion");
+
+ // Test typing 'document.getElem'.
+ input.value = "document.getElem";
+ input.setSelectionRange(16, 16);
+ jsterm.complete(jsterm.COMPLETE_FORWARD, testNext);
+ yield;
+
+ is(input.value, "document.getElem", "'document.getElem' completion");
+ is(jsterm.completeNode.value, "", "'document.getElem' completion");
+
+ // Test pressing tab another time.
+ jsterm.complete(jsterm.COMPLETE_FORWARD, testNext);
+ yield;
+
+ is(input.value, "document.getElem", "'document.getElem' completion");
+ is(jsterm.completeNode.value, " entsByTagNameNS", "'document.getElem' another tab completion");
+
+ // Test pressing shift_tab.
+ jsterm.complete(jsterm.COMPLETE_BACKWARD, testNext);
+ yield;
+
+ is(input.value, "document.getElem", "'document.getElem' untab completion");
+ is(jsterm.completeNode.value, "", "'document.getElem' completion");
+
+ jsterm.clearOutput();
+
+ input.value = "docu";
+ jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
+ yield;
+
+ is(jsterm.completeNode.value, " ment", "'docu' completion");
+ jsterm.execute();
+ is(jsterm.completeNode.value, "", "clear completion on execute()");
+
+ // Test multi-line completion works
+ input.value = "console.log('one');\nconsol";
+ jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
+ yield;
+
+ is(jsterm.completeNode.value, " \n e", "multi-line completion");
+
+ // Test non-object autocompletion.
+ input.value = "Object.name.sl";
+ jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
+ yield;
+
+ is(jsterm.completeNode.value, " ice", "non-object completion");
+
+ // Test string literal autocompletion.
+ input.value = "'Asimov'.sl";
+ jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
+ yield;
+
+ is(jsterm.completeNode.value, " ice", "string literal completion");
+
+ testDriver = jsterm = input = null;
+ executeSoon(finishTest);
+ yield;
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_console_extras.js b/browser/devtools/webconsole/test/browser_webconsole_console_extras.js
new file mode 100644
index 000000000..4e0fa63d8
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_console_extras.js
@@ -0,0 +1,39 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the basic console.log()-style APIs and filtering work.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-extras.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(hud) {
+ waitForSuccess({
+ name: "two nodes displayed",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelectorAll(".hud-msg-node").length == 2;
+ },
+ successFn: function()
+ {
+ let nodes = hud.outputNode.querySelectorAll(".hud-msg-node");
+ ok(/start/.test(nodes[0].textContent), "start found");
+ ok(/end/.test(nodes[1].textContent), "end found - complete!");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+
+ let button = content.document.querySelector("button");
+ ok(button, "we have the button");
+ EventUtils.sendMouseEvent({ type: "click" }, button, content);
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_console_logging_api.js b/browser/devtools/webconsole/test/browser_webconsole_console_logging_api.js
new file mode 100644
index 000000000..4d8a1d492
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_console_logging_api.js
@@ -0,0 +1,146 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the basic console.log()-style APIs and filtering work.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let testDriver = null;
+let subtestDriver = null;
+
+function test() {
+ addTab(TEST_URI);
+
+ browser.addEventListener("DOMContentLoaded", onLoad, false);
+}
+
+function onLoad() {
+ browser.removeEventListener("DOMContentLoaded", onLoad, false);
+
+ openConsole(null, function(aHud) {
+ hud = aHud;
+ hudId = hud.hudId;
+ outputNode = hud.outputNode;
+ testDriver = testGen();
+ testDriver.next();
+ });
+}
+
+function testGen() {
+ subtestGen("log");
+ yield;
+
+ subtestGen("info");
+ yield;
+
+ subtestGen("warn");
+ yield;
+
+ subtestGen("error");
+ yield;
+
+ subtestGen("debug"); // bug 616742
+ yield;
+
+ testDriver = subtestDriver = null;
+ finishTest();
+
+ yield;
+}
+
+function subtestGen(aMethod) {
+ subtestDriver = testConsoleLoggingAPI(aMethod);
+ subtestDriver.next();
+}
+
+function testConsoleLoggingAPI(aMethod) {
+ let console = content.wrappedJSObject.console;
+
+ hud.jsterm.clearOutput();
+
+ setStringFilter("foo");
+ console[aMethod]("foo-bar-baz");
+ console[aMethod]("bar-baz");
+
+ function nextTest() {
+ subtestDriver.next();
+ }
+
+ waitForSuccess({
+ name: "1 hidden " + aMethod + " node via string filtering",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-filtered-by-string").length == 1;
+ },
+ successFn: nextTest,
+ failureFn: nextTest,
+ });
+
+ yield;
+
+ hud.jsterm.clearOutput();
+
+ // now toggle the current method off - make sure no visible message
+
+ // TODO: move all filtering tests into a separate test file: see bug 608135
+ setStringFilter("");
+ hud.setFilterState(aMethod, false);
+ console[aMethod]("foo-bar-baz");
+
+ waitForSuccess({
+ name: "1 message hidden for " + aMethod + " (logging turned off)",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll("description").length == 1;
+ },
+ successFn: nextTest,
+ failureFn: nextTest,
+ });
+
+ yield;
+
+ hud.jsterm.clearOutput();
+ hud.setFilterState(aMethod, true);
+ console[aMethod]("foo-bar-baz");
+
+ waitForSuccess({
+ name: "1 message shown for " + aMethod + " (logging turned on)",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll("description").length == 1;
+ },
+ successFn: nextTest,
+ failureFn: nextTest,
+ });
+
+ yield;
+
+ hud.jsterm.clearOutput();
+ setStringFilter("");
+
+ // test for multiple arguments.
+ console[aMethod]("foo", "bar");
+
+ waitForSuccess({
+ name: "show both console arguments for " + aMethod,
+ validatorFn: function()
+ {
+ let node = outputNode.querySelector(".hud-msg-node");
+ return node && /"foo" "bar"/.test(node.textContent);
+ },
+ successFn: nextTest,
+ failureFn: nextTest,
+ });
+
+ yield;
+ testDriver.next();
+ yield;
+}
+
+function setStringFilter(aValue) {
+ hud.ui.filterBox.value = aValue;
+ hud.ui.adjustVisibilityOnSearchStringChange();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_copying_multiple_messages_inserts_newlines_in_between.js b/browser/devtools/webconsole/test/browser_webconsole_copying_multiple_messages_inserts_newlines_in_between.js
new file mode 100644
index 000000000..85f2ce847
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_copying_multiple_messages_inserts_newlines_in_between.js
@@ -0,0 +1,67 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that copying multiple messages inserts newlines in between.
+
+const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 586142";
+
+let hud;
+
+function test()
+{
+ addTab(TEST_URI);
+ browser.addEventListener("DOMContentLoaded", onLoad, false);
+}
+
+function onLoad() {
+ browser.removeEventListener("DOMContentLoaded", onLoad, false);
+ openConsole(null, testNewlines);
+}
+
+function testNewlines(aHud) {
+ hud = aHud;
+ hud.jsterm.clearOutput();
+
+ for (let i = 0; i < 20; i++) {
+ content.console.log("Hello world #" + i);
+ }
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "Hello world #19",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(testClipboard);
+}
+
+function testClipboard() {
+ let outputNode = hud.outputNode;
+
+ info("messages in output: " + outputNode.itemCount);
+ ok(outputNode.itemCount >= 20, "expected number of messages");
+
+ outputNode.selectAll();
+ outputNode.focus();
+
+ let clipboardTexts = [];
+ for (let i = 0; i < outputNode.itemCount; i++) {
+ let item = outputNode.getItemAtIndex(i);
+ clipboardTexts.push("[" +
+ WCU_l10n.timestampString(item.timestamp) +
+ "] " + item.clipboardText);
+ }
+
+ waitForClipboard(clipboardTexts.join("\n"),
+ function() { goDoCommand("cmd_copy"); },
+ finishTest, finishTest);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_execution_scope.js b/browser/devtools/webconsole/test/browser_webconsole_execution_scope.js
new file mode 100644
index 000000000..23c4cd8f3
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_execution_scope.js
@@ -0,0 +1,45 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that commands run by the user are executed in content space.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testExecutionScope);
+ }, true);
+}
+
+function testExecutionScope(hud) {
+ let jsterm = hud.jsterm;
+
+ jsterm.clearOutput();
+ jsterm.execute("window.location.href;");
+
+ waitForSuccess({
+ name: "jsterm execution output (two nodes)",
+ validatorFn: function()
+ {
+ return jsterm.outputNode.querySelectorAll(".hud-msg-node").length == 2;
+ },
+ successFn: function()
+ {
+ let nodes = jsterm.outputNode.querySelectorAll(".hud-msg-node");
+
+ is(/window.location.href;/.test(nodes[0].textContent), true,
+ "'window.location.href;' written to output");
+
+ isnot(nodes[1].textContent.indexOf(TEST_URI), -1,
+ "command was executed in the window scope");
+
+ executeSoon(finishTest);
+ },
+ failureFn: finishTest,
+ });
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_for_of.js b/browser/devtools/webconsole/test/browser_webconsole_for_of.js
new file mode 100644
index 000000000..fc925535b
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_for_of.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// A for-of loop in Web Console code can loop over a content NodeList.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-for-of.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testForOf);
+ }, true);
+}
+
+function testForOf(hud) {
+ var jsterm = hud.jsterm;
+ jsterm.execute("{ [x.tagName for (x of document.body.childNodes) if (x.nodeType === 1)].join(' '); }");
+
+ waitForSuccess({
+ name: "jsterm output displayed",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ let node = hud.outputNode.querySelector(".webconsole-msg-output");
+ ok(/H1 DIV H2 P/.test(node.textContent),
+ "for-of loop should find all top-level nodes");
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_history.js b/browser/devtools/webconsole/test/browser_webconsole_history.js
new file mode 100644
index 000000000..bb39cd60f
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_history.js
@@ -0,0 +1,66 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the console history feature accessed via the up and down arrow keys.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+// Constants used for defining the direction of JSTerm input history navigation.
+const HISTORY_BACK = -1;
+const HISTORY_FORWARD = 1;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testHistory);
+ }, true);
+}
+
+function testHistory(hud) {
+ let jsterm = hud.jsterm;
+ let input = jsterm.inputNode;
+
+ let executeList = ["document", "window", "window.location"];
+
+ for each (var item in executeList) {
+ input.value = item;
+ jsterm.execute();
+ }
+
+ for (var i = executeList.length - 1; i != -1; i--) {
+ jsterm.historyPeruse(HISTORY_BACK);
+ is (input.value, executeList[i], "check history previous idx:" + i);
+ }
+
+ jsterm.historyPeruse(HISTORY_BACK);
+ is (input.value, executeList[0], "test that item is still index 0");
+
+ jsterm.historyPeruse(HISTORY_BACK);
+ is (input.value, executeList[0], "test that item is still still index 0");
+
+ for (var i = 1; i < executeList.length; i++) {
+ jsterm.historyPeruse(HISTORY_FORWARD);
+ is (input.value, executeList[i], "check history next idx:" + i);
+ }
+
+ jsterm.historyPeruse(HISTORY_FORWARD);
+ is (input.value, "", "check input is empty again");
+
+ // Simulate pressing Arrow_Down a few times and then if Arrow_Up shows
+ // the previous item from history again.
+ jsterm.historyPeruse(HISTORY_FORWARD);
+ jsterm.historyPeruse(HISTORY_FORWARD);
+ jsterm.historyPeruse(HISTORY_FORWARD);
+
+ is (input.value, "", "check input is still empty");
+
+ let idxLast = executeList.length - 1;
+ jsterm.historyPeruse(HISTORY_BACK);
+ is (input.value, executeList[idxLast], "check history next idx:" + idxLast);
+
+ executeSoon(finishTest);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_js_input_and_output_styling.js b/browser/devtools/webconsole/test/browser_webconsole_js_input_and_output_styling.js
new file mode 100644
index 000000000..b888b0f5c
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_js_input_and_output_styling.js
@@ -0,0 +1,48 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the correct CSS styles are applied to the lines of console
+// output.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testJSInputAndOutputStyling);
+ }, true);
+}
+
+function testJSInputAndOutputStyling(hud) {
+ let jsterm = hud.jsterm;
+
+ jsterm.clearOutput();
+ jsterm.execute("2 + 2");
+
+ waitForSuccess({
+ name: "jsterm output is displayed",
+ validatorFn: function()
+ {
+ return jsterm.outputNode.querySelector(".webconsole-msg-output");
+ },
+ successFn: function()
+ {
+ let jsInputNode = jsterm.outputNode.querySelector(".hud-msg-node");
+ isnot(jsInputNode.textContent.indexOf("2 + 2"), -1,
+ "JS input node contains '2 + 2'");
+ ok(jsInputNode.classList.contains("webconsole-msg-input"),
+ "JS input node is of the CSS class 'webconsole-msg-input'");
+
+ let output = jsterm.outputNode.querySelector(".webconsole-msg-output");
+ isnot(output.textContent.indexOf("4"), -1,
+ "JS output node contains '4'");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_js_input_expansion.js b/browser/devtools/webconsole/test/browser_webconsole_js_input_expansion.js
new file mode 100644
index 000000000..2dce91293
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_js_input_expansion.js
@@ -0,0 +1,60 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the input box expands as the user types long lines.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testJSInputExpansion);
+ }, true);
+}
+
+function testJSInputExpansion(hud) {
+ let jsterm = hud.jsterm;
+ let input = jsterm.inputNode;
+ input.focus();
+
+ is(input.getAttribute("multiline"), "true", "multiline is enabled");
+ // Tests if the inputNode expands.
+ input.value = "hello\nworld\n";
+ let length = input.value.length;
+ input.selectionEnd = length;
+ input.selectionStart = length;
+ function getHeight()
+ {
+ return input.clientHeight;
+ }
+ let initialHeight = getHeight();
+ // Performs an "d". This will trigger/test for the input event that should
+ // change the "row" attribute of the inputNode.
+ EventUtils.synthesizeKey("d", {});
+ let newHeight = getHeight();
+ ok(initialHeight < newHeight, "Height changed: " + newHeight);
+
+ // Add some more rows. Tests for the 8 row limit.
+ input.value = "row1\nrow2\nrow3\nrow4\nrow5\nrow6\nrow7\nrow8\nrow9\nrow10\n";
+ length = input.value.length;
+ input.selectionEnd = length;
+ input.selectionStart = length;
+ EventUtils.synthesizeKey("d", {});
+ let newerHeight = getHeight();
+
+ ok(newerHeight > newHeight, "height changed: " + newerHeight);
+
+ // Test if the inputNode shrinks again.
+ input.value = "";
+ EventUtils.synthesizeKey("d", {});
+ let height = getHeight();
+ info("height: " + height);
+ info("initialHeight: " + initialHeight);
+ let finalHeightDifference = Math.abs(initialHeight - height);
+ ok(finalHeightDifference <= 1, "height shrank to original size within 1px");
+
+ finishTest();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_jsterm.js b/browser/devtools/webconsole/test/browser_webconsole_jsterm.js
new file mode 100644
index 000000000..bf0ea3ba5
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_jsterm.js
@@ -0,0 +1,194 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let jsterm, testDriver;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, function(hud) {
+ testDriver = testJSTerm(hud);
+ testDriver.next();
+ });
+ }, true);
+}
+
+function nextTest() {
+ testDriver.next();
+}
+
+function checkResult(msg, desc, lines) {
+ waitForSuccess({
+ name: "correct number of results shown for " + desc,
+ validatorFn: function()
+ {
+ let nodes = jsterm.outputNode.querySelectorAll(".webconsole-msg-output");
+ return nodes.length == lines;
+ },
+ successFn: function()
+ {
+ let labels = jsterm.outputNode.querySelectorAll(".webconsole-msg-output");
+ if (typeof msg == "string") {
+ is(labels[lines-1].textContent.trim(), msg,
+ "correct message shown for " + desc);
+ }
+ else if (typeof msg == "function") {
+ ok(msg(labels), "correct message shown for " + desc);
+ }
+
+ nextTest();
+ },
+ failureFn: nextTest,
+ });
+}
+
+function testJSTerm(hud)
+{
+ jsterm = hud.jsterm;
+
+ jsterm.clearOutput();
+ jsterm.execute("'id=' + $('#header').getAttribute('id')");
+ checkResult('"id=header"', "$() worked", 1);
+ yield;
+
+ jsterm.clearOutput();
+ jsterm.execute("headerQuery = $$('h1')");
+ jsterm.execute("'length=' + headerQuery.length");
+ checkResult('"length=1"', "$$() worked", 2);
+ yield;
+
+ jsterm.clearOutput();
+ jsterm.execute("xpathQuery = $x('.//*', document.body);");
+ jsterm.execute("'headerFound=' + (xpathQuery[0] == headerQuery[0])");
+ checkResult('"headerFound=true"', "$x() worked", 2);
+ yield;
+
+ // no jsterm.clearOutput() here as we clear the output using the clear() fn.
+ jsterm.execute("clear()");
+
+ waitForSuccess({
+ name: "clear() worked",
+ validatorFn: function()
+ {
+ return jsterm.outputNode.childNodes.length == 0;
+ },
+ successFn: nextTest,
+ failureFn: nextTest,
+ });
+
+ yield;
+
+ jsterm.clearOutput();
+ jsterm.execute("'keysResult=' + (keys({b:1})[0] == 'b')");
+ checkResult('"keysResult=true"', "keys() worked", 1);
+ yield;
+
+ jsterm.clearOutput();
+ jsterm.execute("'valuesResult=' + (values({b:1})[0] == 1)");
+ checkResult('"valuesResult=true"', "values() worked", 1);
+ yield;
+
+ jsterm.clearOutput();
+
+ let tabs = gBrowser.tabs.length;
+
+ jsterm.execute("help()");
+ let output = jsterm.outputNode.querySelector(".webconsole-msg-output");
+ ok(!output, "help() worked");
+
+ jsterm.execute("help");
+ output = jsterm.outputNode.querySelector(".webconsole-msg-output");
+ ok(!output, "help worked");
+
+ jsterm.execute("?");
+ output = jsterm.outputNode.querySelector(".webconsole-msg-output");
+ ok(!output, "? worked");
+
+ let foundTab = null;
+ waitForSuccess({
+ name: "help tabs opened",
+ validatorFn: function()
+ {
+ let newTabOpen = gBrowser.tabs.length == tabs + 3;
+ if (!newTabOpen) {
+ return false;
+ }
+
+ foundTab = gBrowser.tabs[tabs];
+ return true;
+ },
+ successFn: function()
+ {
+ gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
+ gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
+ gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
+ nextTest();
+ },
+ failureFn: nextTest,
+ });
+ yield;
+
+ jsterm.clearOutput();
+ jsterm.execute("pprint({b:2, a:1})");
+ checkResult('" b: 2\n a: 1"', "pprint()", 1);
+ yield;
+
+ // check instanceof correctness, bug 599940
+ jsterm.clearOutput();
+ jsterm.execute("[] instanceof Array");
+ checkResult("true", "[] instanceof Array == true", 1);
+ yield;
+
+ jsterm.clearOutput();
+ jsterm.execute("({}) instanceof Object");
+ checkResult("true", "({}) instanceof Object == true", 1);
+ yield;
+
+ // check for occurrences of Object XRayWrapper, bug 604430
+ jsterm.clearOutput();
+ jsterm.execute("document");
+ checkResult(function(nodes) {
+ return nodes[0].textContent.search(/\[object xraywrapper/i) == -1;
+ }, "document - no XrayWrapper", 1);
+ yield;
+
+ // check that pprint(window) and keys(window) don't throw, bug 608358
+ jsterm.clearOutput();
+ jsterm.execute("pprint(window)");
+ checkResult(null, "pprint(window)", 1);
+ yield;
+
+ jsterm.clearOutput();
+ jsterm.execute("keys(window)");
+ checkResult(null, "keys(window)", 1);
+ yield;
+
+ // bug 614561
+ jsterm.clearOutput();
+ jsterm.execute("pprint('hi')");
+ checkResult('" 0: "h"\n 1: "i""', "pprint('hi')", 1);
+ yield;
+
+ // check that pprint(function) shows function source, bug 618344
+ jsterm.clearOutput();
+ jsterm.execute("pprint(print)");
+ checkResult(function(nodes) {
+ return nodes[0].textContent.indexOf("aOwner.helperResult") > -1;
+ }, "pprint(function) shows source", 1);
+ yield;
+
+ // check that an evaluated null produces "null", bug 650780
+ jsterm.clearOutput();
+ jsterm.execute("null");
+ checkResult("null", "null is null", 1);
+ yield;
+
+ jsterm = testDriver = null;
+ executeSoon(finishTest);
+ yield;
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_live_filtering_of_message_types.js b/browser/devtools/webconsole/test/browser_webconsole_live_filtering_of_message_types.js
new file mode 100644
index 000000000..eaba9f1e5
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_live_filtering_of_message_types.js
@@ -0,0 +1,66 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the message type filter checkboxes work.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let hud;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(aHud) {
+ hud = aHud;
+ hud.jsterm.clearOutput();
+
+ let console = content.console;
+
+ for (let i = 0; i < 50; i++) {
+ console.log("foobarz #" + i);
+ }
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "foobarz #49",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(testLiveFilteringOfMessageTypes);
+}
+
+function testLiveFilteringOfMessageTypes() {
+ is(hud.outputNode.itemCount, 50, "number of messages");
+
+ hud.setFilterState("log", false);
+ is(countMessageNodes(), 0, "the log nodes are hidden when the " +
+ "corresponding filter is switched off");
+
+ hud.setFilterState("log", true);
+ is(countMessageNodes(), 50, "the log nodes reappear when the " +
+ "corresponding filter is switched on");
+
+ finishTest();
+}
+
+function countMessageNodes() {
+ let messageNodes = hud.outputNode.querySelectorAll(".hud-log");
+ let displayedMessageNodes = 0;
+ let view = hud.iframeWindow;
+ for (let i = 0; i < messageNodes.length; i++) {
+ let computedStyle = view.getComputedStyle(messageNodes[i], null);
+ if (computedStyle.display !== "none") {
+ displayedMessageNodes++;
+ }
+ }
+
+ return displayedMessageNodes;
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_live_filtering_on_search_strings.js b/browser/devtools/webconsole/test/browser_webconsole_live_filtering_on_search_strings.js
new file mode 100644
index 000000000..e66e66fe3
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_live_filtering_on_search_strings.js
@@ -0,0 +1,106 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the text filter box works.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+let hud;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(aHud) {
+ hud = aHud;
+ hud.jsterm.clearOutput();
+ let console = content.console;
+
+ for (let i = 0; i < 50; i++) {
+ console.log("http://www.example.com/ " + i);
+ }
+
+ waitForMessages({
+ webconsole: hud,
+ messages: [{
+ text: "http://www.example.com/ 49",
+ category: CATEGORY_WEBDEV,
+ severity: SEVERITY_LOG,
+ }],
+ }).then(testLiveFilteringOnSearchStrings);
+}
+
+function testLiveFilteringOnSearchStrings() {
+ is(hud.outputNode.itemCount, 50, "number of messages");
+
+ setStringFilter("http");
+ isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
+ "search string is set to \"http\"");
+
+ setStringFilter("hxxp");
+ is(countMessageNodes(), 0, "the log nodes are hidden when the search " +
+ "string is set to \"hxxp\"");
+
+ setStringFilter("ht tp");
+ isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
+ "search string is set to \"ht tp\"");
+
+ setStringFilter(" zzzz zzzz ");
+ is(countMessageNodes(), 0, "the log nodes are hidden when the search " +
+ "string is set to \" zzzz zzzz \"");
+
+ setStringFilter("");
+ isnot(countMessageNodes(), 0, "the log nodes are not hidden when the " +
+ "search string is removed");
+
+ setStringFilter("\u9f2c");
+ is(countMessageNodes(), 0, "the log nodes are hidden when searching " +
+ "for weasels");
+
+ setStringFilter("\u0007");
+ is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
+ "the bell character");
+
+ setStringFilter('"foo"');
+ is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
+ 'the string "foo"');
+
+ setStringFilter("'foo'");
+ is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
+ "the string 'foo'");
+
+ setStringFilter("foo\"bar'baz\"boo'");
+ is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
+ "the string \"foo\"bar'baz\"boo'\"");
+
+ finishTest();
+}
+
+function countMessageNodes() {
+ let outputNode = hud.outputNode;
+
+ let messageNodes = outputNode.querySelectorAll(".hud-log");
+ let displayedMessageNodes = 0;
+ let view = hud.iframeWindow;
+ for (let i = 0; i < messageNodes.length; i++) {
+ let computedStyle = view.getComputedStyle(messageNodes[i], null);
+ if (computedStyle.display !== "none") {
+ displayedMessageNodes++;
+ }
+ }
+
+ return displayedMessageNodes;
+}
+
+function setStringFilter(aValue)
+{
+ hud.ui.filterBox.value = aValue;
+ hud.ui.adjustVisibilityOnSearchStringChange();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_log_node_classes.js b/browser/devtools/webconsole/test/browser_webconsole_log_node_classes.js
new file mode 100644
index 000000000..cc030f8f5
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_log_node_classes.js
@@ -0,0 +1,71 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that console logging via the console API produces nodes of the correct
+// CSS classes.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, consoleOpened);
+ }, true);
+}
+
+function consoleOpened(aHud) {
+ let console = content.console;
+ outputNode = aHud.outputNode;
+
+ ok(console, "console exists");
+ console.log("I am a log message");
+ console.error("I am an error");
+ console.info("I am an info message");
+ console.warn("I am a warning message");
+
+ waitForSuccess({
+ name: "console.warn displayed",
+ validatorFn: function()
+ {
+ return aHud.outputNode.textContent.indexOf("a warning") > -1;
+ },
+ successFn: testLogNodeClasses,
+ failureFn: finishTest,
+ });
+}
+
+function testLogNodeClasses() {
+ let domLogEntries = outputNode.childNodes;
+
+ let count = outputNode.childNodes.length;
+ ok(count > 0, "LogCount: " + count);
+
+ let klasses = ["hud-log",
+ "hud-warn",
+ "hud-info",
+ "hud-error",
+ "hud-exception",
+ "hud-network"];
+
+ function verifyClass(classList) {
+ let len = klasses.length;
+ for (var i = 0; i < len; i++) {
+ if (classList.contains(klasses[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ for (var i = 0; i < count; i++) {
+ let classList = domLogEntries[i].classList;
+ ok(verifyClass(classList),
+ "Log Node class verified: " + domLogEntries[i].getAttribute("class"));
+ }
+
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_message_node_id.js b/browser/devtools/webconsole/test/browser_webconsole_message_node_id.js
new file mode 100644
index 000000000..77c560ca8
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_message_node_id.js
@@ -0,0 +1,29 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("DOMContentLoaded", onLoad, false);
+}
+
+function onLoad() {
+ browser.removeEventListener("DOMContentLoaded", onLoad, false);
+ openConsole(null, function(hud) {
+ content.console.log("a log message");
+
+ waitForSuccess({
+ name: "console.log message shown with an ID attribute",
+ validatorFn: function()
+ {
+ let node = hud.outputNode.querySelector(".hud-msg-node");
+ return node && node.getAttribute("id");
+ },
+ successFn: finishTest,
+ failureFn: finishTest,
+ });
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_netlogging.js b/browser/devtools/webconsole/test/browser_webconsole_netlogging.js
new file mode 100644
index 000000000..8bc835fa1
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_netlogging.js
@@ -0,0 +1,211 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Julian Viereck <jviereck@mozilla.com>
+ * Patrick Walton <pcwalton@mozilla.com>
+ * Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Tests that network log messages bring up the network panel.
+
+const TEST_NETWORK_REQUEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-network-request.html";
+
+const TEST_IMG = "http://example.com/browser/browser/devtools/webconsole/test/test-image.png";
+
+const TEST_DATA_JSON_CONTENT =
+ '{ id: "test JSON data", myArray: [ "foo", "bar", "baz", "biff" ] }';
+
+let lastRequest = null;
+let requestCallback = null;
+
+function test()
+{
+ addTab("data:text/html;charset=utf-8,Web Console network logging tests");
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+
+ openConsole(null, function(aHud) {
+ hud = aHud;
+
+ HUDService.lastFinishedRequestCallback = requestCallbackWrapper;
+
+ executeSoon(testPageLoad);
+ });
+ }, true);
+}
+
+function requestCallbackWrapper(aRequest)
+{
+ lastRequest = aRequest;
+
+ hud.ui.webConsoleClient.getResponseContent(lastRequest.actor,
+ function(aResponse) {
+ lastRequest.response.content = aResponse.content;
+ lastRequest.discardResponseBody = aResponse.contentDiscarded;
+
+ hud.ui.webConsoleClient.getRequestPostData(lastRequest.actor,
+ function(aResponse) {
+ lastRequest.request.postData = aResponse.postData;
+ lastRequest.discardRequestBody = aResponse.postDataDiscarded;
+
+ if (requestCallback) {
+ requestCallback();
+ }
+ });
+ });
+}
+
+function testPageLoad()
+{
+ requestCallback = function() {
+ // Check if page load was logged correctly.
+ ok(lastRequest, "Page load was logged");
+
+ is(lastRequest.request.url, TEST_NETWORK_REQUEST_URI,
+ "Logged network entry is page load");
+ is(lastRequest.request.method, "GET", "Method is correct");
+ ok(!lastRequest.request.postData.text, "No request body was stored");
+ ok(lastRequest.discardRequestBody, "Request body was discarded");
+ ok(!lastRequest.response.content.text, "No response body was stored");
+ ok(lastRequest.discardResponseBody, "Response body was discarded");
+
+ lastRequest = null;
+ requestCallback = null;
+ executeSoon(testPageLoadBody);
+ };
+
+ content.location = TEST_NETWORK_REQUEST_URI;
+}
+
+function testPageLoadBody()
+{
+ // Turn on logging of request bodies and check again.
+ hud.ui.setSaveRequestAndResponseBodies(true).then(() => {
+ ok(hud.ui._saveRequestAndResponseBodies,
+ "The saveRequestAndResponseBodies property was successfully set.");
+
+ testPageLoadBodyAfterSettingUpdate();
+ });
+}
+
+function testPageLoadBodyAfterSettingUpdate()
+{
+ let loaded = false;
+ let requestCallbackInvoked = false;
+
+ requestCallback = function() {
+ ok(lastRequest, "Page load was logged again");
+ ok(!lastRequest.discardResponseBody, "Response body was not discarded");
+ is(lastRequest.response.content.text.indexOf("<!DOCTYPE HTML>"), 0,
+ "Response body's beginning is okay");
+
+ lastRequest = null;
+ requestCallback = null;
+ requestCallbackInvoked = true;
+
+ if (loaded) {
+ executeSoon(testXhrGet);
+ }
+ };
+
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ loaded = true;
+
+ if (requestCallbackInvoked) {
+ executeSoon(testXhrGet);
+ }
+ }, true);
+
+ content.location.reload();
+}
+
+function testXhrGet()
+{
+ requestCallback = function() {
+ ok(lastRequest, "testXhrGet() was logged");
+ is(lastRequest.request.method, "GET", "Method is correct");
+ ok(!lastRequest.request.postData.text, "No request body was sent");
+ ok(!lastRequest.discardRequestBody, "Request body was not discarded");
+ is(lastRequest.response.content.text, TEST_DATA_JSON_CONTENT,
+ "Response is correct");
+
+ lastRequest = null;
+ requestCallback = null;
+ executeSoon(testXhrPost);
+ };
+
+ // Start the XMLHttpRequest() GET test.
+ content.wrappedJSObject.testXhrGet();
+}
+
+function testXhrPost()
+{
+ requestCallback = function() {
+ ok(lastRequest, "testXhrPost() was logged");
+ is(lastRequest.request.method, "POST", "Method is correct");
+ is(lastRequest.request.postData.text, "Hello world!",
+ "Request body was logged");
+ is(lastRequest.response.content.text, TEST_DATA_JSON_CONTENT,
+ "Response is correct");
+
+ lastRequest = null;
+ requestCallback = null;
+ executeSoon(testFormSubmission);
+ };
+
+ // Start the XMLHttpRequest() POST test.
+ content.wrappedJSObject.testXhrPost();
+}
+
+function testFormSubmission()
+{
+ // Start the form submission test. As the form is submitted, the page is
+ // loaded again. Bind to the load event to catch when this is done.
+ requestCallback = function() {
+ ok(lastRequest, "testFormSubmission() was logged");
+ is(lastRequest.request.method, "POST", "Method is correct");
+ isnot(lastRequest.request.postData.text.
+ indexOf("Content-Type: application/x-www-form-urlencoded"), -1,
+ "Content-Type is correct");
+ isnot(lastRequest.request.postData.text.
+ indexOf("Content-Length: 20"), -1, "Content-length is correct");
+ isnot(lastRequest.request.postData.text.
+ indexOf("name=foo+bar&age=144"), -1, "Form data is correct");
+ is(lastRequest.response.content.text.indexOf("<!DOCTYPE HTML>"), 0,
+ "Response body's beginning is okay");
+
+ executeSoon(testNetworkPanel);
+ };
+
+ let form = content.document.querySelector("form");
+ ok(form, "we have the HTML form");
+ form.submit();
+}
+
+function testNetworkPanel()
+{
+ // Open the NetworkPanel. The functionality of the NetworkPanel is tested
+ // within separate test files.
+ let networkPanel = hud.ui.openNetworkPanel(hud.ui.filterBox, lastRequest);
+
+ networkPanel.panel.addEventListener("popupshown", function onPopupShown() {
+ networkPanel.panel.removeEventListener("popupshown", onPopupShown, true);
+
+ is(hud.ui.filterBox._netPanel, networkPanel,
+ "Network panel stored on anchor node");
+ ok(true, "NetworkPanel was opened");
+
+ // All tests are done. Shutdown.
+ networkPanel.panel.hidePopup();
+ lastRequest = null;
+ HUDService.lastFinishedRequestCallback = null;
+ executeSoon(finishTest);
+ }, true);
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_network_panel.js b/browser/devtools/webconsole/test/browser_webconsole_network_panel.js
new file mode 100644
index 000000000..678597224
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_network_panel.js
@@ -0,0 +1,543 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that the network panel works.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+const TEST_IMG = "http://example.com/browser/browser/devtools/webconsole/test/test-image.png";
+const TEST_ENCODING_ISO_8859_1 = "http://example.com/browser/browser/devtools/webconsole/test/test-encoding-ISO-8859-1.html";
+
+const TEST_IMG_BASE64 =
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAVRJREFU" +
+ "OI2lk7FLw0AUxr+YpC1CBqcMWfsvCCLdXFzqEJCgDl1EQRGxg9AhSBEJONhFhG52UCuFDjq5dxD8" +
+ "FwoO0qGDOBQkl7vLOeWa2EQDffDBvTu+373Hu1OEEJgntGgxGD6J+7fLXKbt5VNUyhsKAChRBQcP" +
+ "FVFeWskFGH694mZroCQqCLlAwPxcgJBP254CmAD5B7C7dgHLMLF3uzoL4DQEod+Z5sP1FizDxGgy" +
+ "BqfhLID9AahX29J89bwPFgMsSEAQglAf9WobhPpScbPXr4FQHyzIADTsDizDRMPuIOC+zEeTMZo9" +
+ "BwH3EfAMACccbtfGaDKGZZg423yUZrdrg3EqxQlPr0BTdTR7joREN2uqnlBmCwW1hIJagtev4f3z" +
+ "A16/JvfiigMSYyzqJXlw/XKUyOORMUaBor6YavgdjKa8xGOnidadmwtwsnMu18q83/kHSou+bFND" +
+ "Dr4AAAAASUVORK5CYII=";
+
+let testDriver;
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testNetworkPanel);
+ }, true);
+}
+
+function testNetworkPanel() {
+ testDriver = testGen();
+ testDriver.next();
+}
+
+function checkIsVisible(aPanel, aList) {
+ for (let id in aList) {
+ let node = aPanel.document.getElementById(id);
+ let isVisible = aList[id];
+ is(node.style.display, (isVisible ? "block" : "none"), id + " isVisible=" + isVisible);
+ }
+}
+
+function checkNodeContent(aPanel, aId, aContent) {
+ let node = aPanel.document.getElementById(aId);
+ if (node == null) {
+ ok(false, "Tried to access node " + aId + " that doesn't exist!");
+ }
+ else if (node.textContent.indexOf(aContent) != -1) {
+ ok(true, "checking content of " + aId);
+ }
+ else {
+ ok(false, "Got false value for " + aId + ": " + node.textContent + " doesn't have " + aContent);
+ }
+}
+
+function checkNodeKeyValue(aPanel, aId, aKey, aValue) {
+ let node = aPanel.document.getElementById(aId);
+
+ let headers = node.querySelectorAll("th");
+ for (let i = 0; i < headers.length; i++) {
+ if (headers[i].textContent == (aKey + ":")) {
+ is(headers[i].nextElementSibling.textContent, aValue,
+ "checking content of " + aId + " for key " + aKey);
+ return;
+ }
+ }
+
+ ok(false, "content check failed for " + aId + ", key " + aKey);
+}
+
+function testGen() {
+ let hud = HUDService.getHudByWindow(content);
+ let filterBox = hud.ui.filterBox;
+
+ let httpActivity = {
+ updates: [],
+ discardRequestBody: true,
+ discardResponseBody: true,
+ startedDateTime: (new Date()).toISOString(),
+ request: {
+ url: "http://www.testpage.com",
+ method: "GET",
+ cookies: [],
+ headers: [
+ { name: "foo", value: "bar" },
+ ],
+ },
+ response: {
+ headers: [],
+ content: {},
+ cookies: [],
+ },
+ timings: {},
+ };
+
+ let networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+
+ is(filterBox._netPanel, networkPanel,
+ "Network panel stored on the anchor object");
+
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ info("test 1");
+
+ checkIsVisible(networkPanel, {
+ requestCookie: false,
+ requestFormData: false,
+ requestBody: false,
+ responseContainer: false,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ checkNodeContent(networkPanel, "header", "http://www.testpage.com");
+ checkNodeContent(networkPanel, "header", "GET");
+ checkNodeKeyValue(networkPanel, "requestHeadersContent", "foo", "bar");
+
+ // Test request body.
+ info("test 2: request body");
+ httpActivity.discardRequestBody = false;
+ httpActivity.request.postData = { text: "hello world" };
+ networkPanel.update();
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestFormData: false,
+ requestCookie: false,
+ responseContainer: false,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+ checkNodeContent(networkPanel, "requestBodyContent", "hello world");
+
+ // Test response header.
+ info("test 3: response header");
+ httpActivity.timings.wait = 10;
+ httpActivity.response.httpVersion = "HTTP/3.14";
+ httpActivity.response.status = 999;
+ httpActivity.response.statusText = "earthquake win";
+ httpActivity.response.content.mimeType = "text/html";
+ httpActivity.response.headers.push(
+ { name: "Content-Type", value: "text/html" },
+ { name: "leaveHouses", value: "true" }
+ );
+
+ networkPanel.update();
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestFormData: false,
+ requestCookie: false,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ checkNodeContent(networkPanel, "header", "HTTP/3.14 999 earthquake win");
+ checkNodeKeyValue(networkPanel, "responseHeadersContent", "leaveHouses", "true");
+ checkNodeContent(networkPanel, "responseHeadersInfo", "10ms");
+
+ info("test 4");
+
+ httpActivity.discardResponseBody = false;
+ httpActivity.timings.receive = 2;
+ networkPanel.update();
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestCookie: false,
+ requestFormData: false,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ info("test 5");
+
+ httpActivity.updates.push("responseContent", "eventTimings");
+ networkPanel.update();
+
+ checkNodeContent(networkPanel, "responseNoBodyInfo", "2ms");
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestCookie: false,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: true,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ networkPanel.panel.hidePopup();
+
+ // Second run: Test for cookies and response body.
+ info("test 6: cookies and response body");
+ httpActivity.request.cookies.push(
+ { name: "foo", value: "bar" },
+ { name: "hello", value: "world" }
+ );
+ httpActivity.response.content.text = "get out here";
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ is(filterBox._netPanel, networkPanel,
+ "Network panel stored on httpActivity object");
+
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestFormData: false,
+ requestCookie: true,
+ responseContainer: true,
+ responseCookie: false,
+ responseBody: true,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ checkNodeKeyValue(networkPanel, "requestCookieContent", "foo", "bar");
+ checkNodeKeyValue(networkPanel, "requestCookieContent", "hello", "world");
+ checkNodeContent(networkPanel, "responseBodyContent", "get out here");
+ checkNodeContent(networkPanel, "responseBodyInfo", "2ms");
+
+ networkPanel.panel.hidePopup();
+
+ // Third run: Test for response cookies.
+ info("test 6b: response cookies");
+ httpActivity.response.cookies.push(
+ { name: "foobar", value: "boom" },
+ { name: "foobaz", value: "omg" }
+ );
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ is(filterBox._netPanel, networkPanel,
+ "Network panel stored on httpActivity object");
+
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestFormData: false,
+ requestCookie: true,
+ responseContainer: true,
+ responseCookie: true,
+ responseBody: true,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false,
+ responseBodyFetchLink: false,
+ });
+
+ checkNodeKeyValue(networkPanel, "responseCookieContent", "foobar", "boom");
+ checkNodeKeyValue(networkPanel, "responseCookieContent", "foobaz", "omg");
+
+ networkPanel.panel.hidePopup();
+
+ // Check image request.
+ info("test 7: image request");
+ httpActivity.response.headers[1].value = "image/png";
+ httpActivity.response.content.mimeType = "image/png";
+ httpActivity.response.content.text = TEST_IMG_BASE64;
+ httpActivity.request.url = TEST_IMG;
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestFormData: false,
+ requestCookie: true,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: true,
+ responseImageCached: false,
+ responseBodyFetchLink: false,
+ });
+
+ let imgNode = networkPanel.document.getElementById("responseImageNode");
+ is(imgNode.getAttribute("src"), "data:image/png;base64," + TEST_IMG_BASE64,
+ "Displayed image is correct");
+
+ function checkImageResponseInfo() {
+ checkNodeContent(networkPanel, "responseImageInfo", "2ms");
+ checkNodeContent(networkPanel, "responseImageInfo", "16x16px");
+ }
+
+ // Check if the image is loaded already.
+ imgNode.addEventListener("load", function onLoad() {
+ imgNode.removeEventListener("load", onLoad, false);
+ checkImageResponseInfo();
+ networkPanel.panel.hidePopup();
+ testDriver.next();
+ }, false);
+ yield;
+
+ // Check cached image request.
+ info("test 8: cached image request");
+ httpActivity.response.httpVersion = "HTTP/1.1";
+ httpActivity.response.status = 304;
+ httpActivity.response.statusText = "Not Modified";
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: true,
+ requestFormData: false,
+ requestCookie: true,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: true
+ });
+
+ let imgNode = networkPanel.document.getElementById("responseImageCachedNode");
+ is(imgNode.getAttribute("src"), "data:image/png;base64," + TEST_IMG_BASE64,
+ "Displayed image is correct");
+
+ networkPanel.panel.hidePopup();
+
+ // Test sent form data.
+ info("test 9: sent form data");
+ httpActivity.request.postData.text = [
+ "Content-Type: application/x-www-form-urlencoded",
+ "Content-Length: 59",
+ "name=rob&age=20"
+ ].join("\n");
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: false,
+ requestFormData: true,
+ requestCookie: true,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: true
+ });
+
+ checkNodeKeyValue(networkPanel, "requestFormDataContent", "name", "rob");
+ checkNodeKeyValue(networkPanel, "requestFormDataContent", "age", "20");
+ networkPanel.panel.hidePopup();
+
+ // Test no space after Content-Type:
+ info("test 10: no space after Content-Type header in post data");
+ httpActivity.request.postData.text = "Content-Type:application/x-www-form-urlencoded\n";
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: false,
+ requestFormData: true,
+ requestCookie: true,
+ responseContainer: true,
+ responseBody: false,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: true
+ });
+
+ networkPanel.panel.hidePopup();
+
+ // Test cached data.
+
+ info("test 11: cached data");
+
+ httpActivity.request.url = TEST_ENCODING_ISO_8859_1;
+ httpActivity.response.headers[1].value = "application/json";
+ httpActivity.response.content.mimeType = "application/json";
+ httpActivity.response.content.text = "my cached data is here!";
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: false,
+ requestFormData: true,
+ requestCookie: true,
+ responseContainer: true,
+ responseBody: false,
+ responseBodyCached: true,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ checkNodeContent(networkPanel, "responseBodyCachedContent",
+ "my cached data is here!");
+
+ networkPanel.panel.hidePopup();
+
+ // Test a response with a content type that can't be displayed in the
+ // NetworkPanel.
+ info("test 12: unknown content type");
+ httpActivity.response.headers[1].value = "application/x-shockwave-flash";
+ httpActivity.response.content.mimeType = "application/x-shockwave-flash";
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ networkPanel._onUpdate = function() {
+ networkPanel._onUpdate = null;
+ executeSoon(function() {
+ testDriver.next();
+ });
+ };
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: false,
+ requestFormData: true,
+ requestCookie: true,
+ responseContainer: true,
+ responseBody: false,
+ responseBodyCached: false,
+ responseBodyUnknownType: true,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ let responseString =
+ WCU_l10n.getFormatStr("NetworkPanel.responseBodyUnableToDisplay.content",
+ ["application/x-shockwave-flash"]);
+ checkNodeContent(networkPanel, "responseBodyUnknownTypeContent", responseString);
+ networkPanel.panel.hidePopup();
+
+ /*
+
+ // This test disabled. See bug 603620.
+
+ // Test if the NetworkPanel figures out the content type based on an URL as
+ // well.
+ delete httpActivity.response.header["Content-Type"];
+ httpActivity.url = "http://www.test.com/someCrazyFile.swf?done=right&ending=txt";
+
+ networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity);
+ networkPanel.isDoneCallback = function NP_doneCallback() {
+ networkPanel.isDoneCallback = null;
+ testDriver.next();
+ }
+
+ yield;
+
+ checkIsVisible(networkPanel, {
+ requestBody: false,
+ requestFormData: true,
+ requestCookie: true,
+ responseContainer: true,
+ responseBody: false,
+ responseBodyCached: false,
+ responseBodyUnknownType: true,
+ responseNoBody: false,
+ responseImage: false,
+ responseImageCached: false
+ });
+
+ // Systems without Flash installed will return an empty string here. Ignore.
+ if (networkPanel.document.getElementById("responseBodyUnknownTypeContent").textContent !== "")
+ checkNodeContent(networkPanel, "responseBodyUnknownTypeContent", responseString);
+ else
+ ok(true, "Flash not installed");
+
+ networkPanel.panel.hidePopup(); */
+
+ // All done!
+ testDriver = null;
+ executeSoon(finishTest);
+
+ yield;
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_notifications.js b/browser/devtools/webconsole/test/browser_webconsole_notifications.js
new file mode 100644
index 000000000..c70605635
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_notifications.js
@@ -0,0 +1,70 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>Web Console test for notifications";
+
+function test() {
+ observer.init();
+ addTab(TEST_URI);
+ browser.addEventListener("load", onLoad, true);
+}
+
+function webConsoleCreated(aID)
+{
+ Services.obs.removeObserver(observer, "web-console-created");
+ ok(HUDService.hudReferences[aID], "We have a hud reference");
+ content.wrappedJSObject.console.log("adding a log message");
+}
+
+function webConsoleDestroyed(aID)
+{
+ Services.obs.removeObserver(observer, "web-console-destroyed");
+ ok(!HUDService.hudReferences[aID], "We do not have a hud reference");
+ executeSoon(finishTest);
+}
+
+function webConsoleMessage(aID, aNodeID)
+{
+ Services.obs.removeObserver(observer, "web-console-message-created");
+ ok(aID, "we have a console ID");
+ is(typeof aNodeID, "string", "message node id is a string");
+ executeSoon(closeConsole);
+}
+
+let observer = {
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function observe(aSubject, aTopic, aData)
+ {
+ aSubject = aSubject.QueryInterface(Ci.nsISupportsString);
+
+ switch(aTopic) {
+ case "web-console-created":
+ webConsoleCreated(aSubject);
+ break;
+ case "web-console-destroyed":
+ webConsoleDestroyed(aSubject);
+ break;
+ case "web-console-message-created":
+ webConsoleMessage(aSubject, aData);
+ break;
+ default:
+ break;
+ }
+ },
+
+ init: function init()
+ {
+ Services.obs.addObserver(this, "web-console-created", false);
+ Services.obs.addObserver(this, "web-console-destroyed", false);
+ Services.obs.addObserver(this, "web-console-message-created", false);
+ }
+};
+
+function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole();
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_null_and_undefined_output.js b/browser/devtools/webconsole/test/browser_webconsole_null_and_undefined_output.js
new file mode 100644
index 000000000..fff74534a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_null_and_undefined_output.js
@@ -0,0 +1,62 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Test that JavaScript expressions that evaluate to null or undefined produce
+// meaningful output.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testNullAndUndefinedOutput);
+ }, true);
+}
+
+function testNullAndUndefinedOutput(hud) {
+ let jsterm = hud.jsterm;
+ let outputNode = jsterm.outputNode;
+
+ jsterm.clearOutput();
+ jsterm.execute("null;");
+
+ waitForSuccess({
+ name: "null displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-msg-node").length == 2;
+ },
+ successFn: function()
+ {
+ let nodes = outputNode.querySelectorAll(".hud-msg-node");
+ isnot(nodes[1].textContent.indexOf("null"), -1,
+ "'null' printed to output");
+
+ jsterm.clearOutput();
+ jsterm.execute("undefined;");
+ waitForSuccess(waitForUndefined);
+ },
+ failureFn: finishTest,
+ });
+
+ let waitForUndefined = {
+ name: "undefined displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-msg-node").length == 2;
+ },
+ successFn: function()
+ {
+ let nodes = outputNode.querySelectorAll(".hud-msg-node");
+ isnot(nodes[1].textContent.indexOf("undefined"), -1,
+ "'undefined' printed to output");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ };
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_output_order.js b/browser/devtools/webconsole/test/browser_webconsole_output_order.js
new file mode 100644
index 000000000..63e9ecd6a
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_output_order.js
@@ -0,0 +1,44 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests that any output created from calls to the console API comes after the
+// echoed JavaScript.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, testOutputOrder);
+ }, true);
+}
+
+function testOutputOrder(hud) {
+ let jsterm = hud.jsterm;
+ let outputNode = jsterm.outputNode;
+
+ jsterm.clearOutput();
+ jsterm.execute("console.log('foo', 'bar');");
+
+ waitForSuccess({
+ name: "console.log message displayed",
+ validatorFn: function()
+ {
+ return outputNode.querySelectorAll(".hud-msg-node").length == 3;
+ },
+ successFn: function()
+ {
+ let nodes = outputNode.querySelectorAll(".hud-msg-node");
+ let executedStringFirst =
+ /console\.log\('foo', 'bar'\);/.test(nodes[0].textContent);
+ let outputSecond = /"foo" "bar"/.test(nodes[2].textContent);
+ ok(executedStringFirst && outputSecond, "executed string comes first");
+
+ finishTest();
+ },
+ failureFn: finishTest,
+ });
+}
diff --git a/browser/devtools/webconsole/test/browser_webconsole_property_provider.js b/browser/devtools/webconsole/test/browser_webconsole_property_provider.js
new file mode 100644
index 000000000..9d36a98ba
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_property_provider.js
@@ -0,0 +1,42 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the property provider, which is part of the code completion
+// infrastructure.
+
+const TEST_URI = "data:text/html;charset=utf8,<p>test the JS property provider";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", testPropertyProvider, true);
+}
+
+function testPropertyProvider() {
+ browser.removeEventListener("load", testPropertyProvider, true);
+
+ let tmp = {};
+ Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
+ let JSPropertyProvider = tmp.JSPropertyProvider;
+ tmp = null;
+
+ let completion = JSPropertyProvider(content, "thisIsNotDefined");
+ is (completion.matches.length, 0, "no match for 'thisIsNotDefined");
+
+ // This is a case the PropertyProvider can't handle. Should return null.
+ completion = JSPropertyProvider(content, "window[1].acb");
+ is (completion, null, "no match for 'window[1].acb");
+
+ // A very advanced completion case.
+ var strComplete =
+ 'function a() { }document;document.getElementById(window.locatio';
+ completion = JSPropertyProvider(content, strComplete);
+ ok(completion.matches.length == 2, "two matches found");
+ ok(completion.matchProp == "locatio", "matching part is 'test'");
+ ok(completion.matches[0] == "location", "the first match is 'location'");
+ ok(completion.matches[1] == "locationbar", "the second match is 'locationbar'");
+
+ finishTest();
+}
+
diff --git a/browser/devtools/webconsole/test/browser_webconsole_view_source.js b/browser/devtools/webconsole/test/browser_webconsole_view_source.js
new file mode 100644
index 000000000..b4fe223be
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_view_source.js
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that source URLs in the Web Console can be clicked to display the
+// standard View Source window.
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-error.html";
+
+function test() {
+ addTab(TEST_URI);
+ browser.addEventListener("load", function onLoad() {
+ browser.removeEventListener("load", onLoad, true);
+ openConsole(null, function(hud) {
+ executeSoon(function() {
+ testViewSource(hud);
+ });
+ });
+ }, true);
+}
+
+function testViewSource(hud) {
+ let button = content.document.querySelector("button");
+ button = XPCNativeWrapper.unwrap(button);
+ ok(button, "we have the button on the page");
+
+ expectUncaughtException();
+ EventUtils.sendMouseEvent({ type: "click" }, button, XPCNativeWrapper.unwrap(content));
+
+ waitForSuccess({
+ name: "find the location node",
+ validatorFn: function()
+ {
+ return hud.outputNode.querySelector(".webconsole-location");
+ },
+ successFn: function()
+ {
+ let locationNode = hud.outputNode.querySelector(".webconsole-location");
+
+ Services.ww.registerNotification(observer);
+
+ EventUtils.sendMouseEvent({ type: "click" }, locationNode);
+ },
+ failureFn: finishTest,
+ });
+}
+
+let observer = {
+ observe: function(aSubject, aTopic, aData) {
+ if (aTopic != "domwindowopened") {
+ return;
+ }
+
+ ok(true, "the view source window was opened in response to clicking " +
+ "the location node");
+
+ // executeSoon() is necessary to avoid crashing Firefox. See bug 611543.
+ executeSoon(function() {
+ aSubject.close();
+ finishTest();
+ });
+ }
+};
+
+registerCleanupFunction(function() {
+ Services.ww.unregisterNotification(observer);
+});
diff --git a/browser/devtools/webconsole/test/head.js b/browser/devtools/webconsole/test/head.js
new file mode 100644
index 000000000..0f90d37fb
--- /dev/null
+++ b/browser/devtools/webconsole/test/head.js
@@ -0,0 +1,1247 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+let tempScope = {};
+Cu.import("resource:///modules/HUDService.jsm", tempScope);
+let HUDService = tempScope.HUDService;
+Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tempScope);
+let WebConsoleUtils = tempScope.WebConsoleUtils;
+Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
+let gDevTools = tempScope.gDevTools;
+Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
+let TargetFactory = tempScope.devtools.TargetFactory;
+Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
+let console = tempScope.console;
+let Promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
+
+let gPendingOutputTest = 0;
+
+// The various categories of messages.
+const CATEGORY_NETWORK = 0;
+const CATEGORY_CSS = 1;
+const CATEGORY_JS = 2;
+const CATEGORY_WEBDEV = 3;
+const CATEGORY_INPUT = 4;
+const CATEGORY_OUTPUT = 5;
+const CATEGORY_SECURITY = 6;
+
+// The possible message severities.
+const SEVERITY_ERROR = 0;
+const SEVERITY_WARNING = 1;
+const SEVERITY_INFO = 2;
+const SEVERITY_LOG = 3;
+
+const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
+let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
+
+function log(aMsg)
+{
+ dump("*** WebConsoleTest: " + aMsg + "\n");
+}
+
+function pprint(aObj)
+{
+ for (let prop in aObj) {
+ if (typeof aObj[prop] == "function") {
+ log("function " + prop);
+ }
+ else {
+ log(prop + ": " + aObj[prop]);
+ }
+ }
+}
+
+let tab, browser, hudId, hud, hudBox, filterBox, outputNode, cs;
+
+function addTab(aURL)
+{
+ gBrowser.selectedTab = gBrowser.addTab(aURL);
+ tab = gBrowser.selectedTab;
+ browser = gBrowser.getBrowserForTab(tab);
+}
+
+function afterAllTabsLoaded(callback, win) {
+ win = win || window;
+
+ let stillToLoad = 0;
+
+ function onLoad() {
+ this.removeEventListener("load", onLoad, true);
+ stillToLoad--;
+ if (!stillToLoad)
+ callback();
+ }
+
+ for (let a = 0; a < win.gBrowser.tabs.length; a++) {
+ let browser = win.gBrowser.tabs[a].linkedBrowser;
+ if (browser.contentDocument.readyState != "complete") {
+ stillToLoad++;
+ browser.addEventListener("load", onLoad, true);
+ }
+ }
+
+ if (!stillToLoad)
+ callback();
+}
+
+/**
+ * Check if a log entry exists in the HUD output node.
+ *
+ * @param {Element} aOutputNode
+ * the HUD output node.
+ * @param {string} aMatchString
+ * the string you want to check if it exists in the output node.
+ * @param {string} aMsg
+ * the message describing the test
+ * @param {boolean} [aOnlyVisible=false]
+ * find only messages that are visible, not hidden by the filter.
+ * @param {boolean} [aFailIfFound=false]
+ * fail the test if the string is found in the output node.
+ * @param {string} aClass [optional]
+ * find only messages with the given CSS class.
+ */
+function testLogEntry(aOutputNode, aMatchString, aMsg, aOnlyVisible,
+ aFailIfFound, aClass)
+{
+ let selector = ".hud-msg-node";
+ // Skip entries that are hidden by the filter.
+ if (aOnlyVisible) {
+ selector += ":not(.hud-filtered-by-type)";
+ }
+ if (aClass) {
+ selector += "." + aClass;
+ }
+
+ let msgs = aOutputNode.querySelectorAll(selector);
+ let found = false;
+ for (let i = 0, n = msgs.length; i < n; i++) {
+ let message = msgs[i].textContent.indexOf(aMatchString);
+ if (message > -1) {
+ found = true;
+ break;
+ }
+
+ // Search the labels too.
+ let labels = msgs[i].querySelectorAll("label");
+ for (let j = 0; j < labels.length; j++) {
+ if (labels[j].getAttribute("value").indexOf(aMatchString) > -1) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ is(found, !aFailIfFound, aMsg);
+}
+
+/**
+ * A convenience method to call testLogEntry().
+ *
+ * @param string aString
+ * The string to find.
+ */
+function findLogEntry(aString)
+{
+ testLogEntry(outputNode, aString, "found " + aString);
+}
+
+/**
+ * Open the Web Console for the given tab.
+ *
+ * @param nsIDOMElement [aTab]
+ * Optional tab element for which you want open the Web Console. The
+ * default tab is taken from the global variable |tab|.
+ * @param function [aCallback]
+ * Optional function to invoke after the Web Console completes
+ * initialization (web-console-created).
+ */
+function openConsole(aTab, aCallback = function() { })
+{
+ let target = TargetFactory.forTab(aTab || tab);
+ gDevTools.showToolbox(target, "webconsole").then(function(toolbox) {
+ let hud = toolbox.getCurrentPanel().hud;
+ hud.jsterm._lazyVariablesView = false;
+ aCallback(hud);
+ });
+}
+
+/**
+ * Close the Web Console for the given tab.
+ *
+ * @param nsIDOMElement [aTab]
+ * Optional tab element for which you want close the Web Console. The
+ * default tab is taken from the global variable |tab|.
+ * @param function [aCallback]
+ * Optional function to invoke after the Web Console completes
+ * closing (web-console-destroyed).
+ */
+function closeConsole(aTab, aCallback = function() { })
+{
+ let target = TargetFactory.forTab(aTab || tab);
+ let toolbox = gDevTools.getToolbox(target);
+ if (toolbox) {
+ let panel = toolbox.getPanel("webconsole");
+ if (panel) {
+ let hudId = panel.hud.hudId;
+ toolbox.destroy().then(aCallback.bind(null, hudId)).then(null, console.debug);
+ }
+ else {
+ toolbox.destroy().then(aCallback.bind(null));
+ }
+ }
+ else {
+ aCallback();
+ }
+}
+
+/**
+ * Wait for a context menu popup to open.
+ *
+ * @param nsIDOMElement aPopup
+ * The XUL popup you expect to open.
+ * @param nsIDOMElement aButton
+ * The button/element that receives the contextmenu event. This is
+ * expected to open the popup.
+ * @param function aOnShown
+ * Function to invoke on popupshown event.
+ * @param function aOnHidden
+ * Function to invoke on popuphidden event.
+ */
+function waitForContextMenu(aPopup, aButton, aOnShown, aOnHidden)
+{
+ function onPopupShown() {
+ info("onPopupShown");
+ aPopup.removeEventListener("popupshown", onPopupShown);
+
+ aOnShown();
+
+ // Use executeSoon() to get out of the popupshown event.
+ aPopup.addEventListener("popuphidden", onPopupHidden);
+ executeSoon(() => aPopup.hidePopup());
+ }
+ function onPopupHidden() {
+ info("onPopupHidden");
+ aPopup.removeEventListener("popuphidden", onPopupHidden);
+ aOnHidden();
+ }
+
+ aPopup.addEventListener("popupshown", onPopupShown);
+
+ info("wait for the context menu to open");
+ let eventDetails = { type: "contextmenu", button: 2};
+ EventUtils.synthesizeMouse(aButton, 2, 2, eventDetails,
+ aButton.ownerDocument.defaultView);
+}
+
+/**
+ * Dump the output of all open Web Consoles - used only for debugging purposes.
+ */
+function dumpConsoles()
+{
+ if (gPendingOutputTest) {
+ console.log("dumpConsoles start");
+ for each (let hud in HUDService.hudReferences) {
+ if (!hud.outputNode) {
+ console.debug("no output content for", hud.hudId);
+ continue;
+ }
+
+ console.debug("output content for", hud.hudId);
+ for (let elem of hud.outputNode.childNodes) {
+ dumpMessageElement(elem);
+ }
+ }
+ console.log("dumpConsoles end");
+
+ gPendingOutputTest = 0;
+ }
+}
+
+/**
+ * Dump to output debug information for the given webconsole message.
+ *
+ * @param nsIDOMNode aMessage
+ * The message element you want to display.
+ */
+function dumpMessageElement(aMessage)
+{
+ let text = getMessageElementText(aMessage);
+ let repeats = aMessage.querySelector(".webconsole-msg-repeat");
+ if (repeats) {
+ repeats = repeats.getAttribute("value");
+ }
+ console.debug("id", aMessage.getAttribute("id"),
+ "date", aMessage.timestamp,
+ "class", aMessage.className,
+ "category", aMessage.category,
+ "severity", aMessage.severity,
+ "repeats", repeats,
+ "clipboardText", aMessage.clipboardText,
+ "text", text);
+}
+
+function finishTest()
+{
+ browser = hudId = hud = filterBox = outputNode = cs = null;
+
+ dumpConsoles();
+
+ if (HUDConsoleUI.browserConsole) {
+ let hud = HUDConsoleUI.browserConsole;
+
+ if (hud.jsterm) {
+ hud.jsterm.clearOutput(true);
+ }
+
+ HUDConsoleUI.toggleBrowserConsole().then(finishTest);
+ return;
+ }
+
+ let hud = HUDService.getHudByWindow(content);
+ if (!hud) {
+ finish();
+ return;
+ }
+
+ if (hud.jsterm) {
+ hud.jsterm.clearOutput(true);
+ }
+
+ closeConsole(hud.target.tab, finish);
+
+ hud = null;
+}
+
+function tearDown()
+{
+ dumpConsoles();
+
+ if (HUDConsoleUI.browserConsole) {
+ HUDConsoleUI.toggleBrowserConsole();
+ }
+
+ let target = TargetFactory.forTab(gBrowser.selectedTab);
+ gDevTools.closeToolbox(target);
+ while (gBrowser.tabs.length > 1) {
+ gBrowser.removeCurrentTab();
+ }
+ WCU_l10n = tab = browser = hudId = hud = filterBox = outputNode = cs = null;
+}
+
+registerCleanupFunction(tearDown);
+
+waitForExplicitFinish();
+
+/**
+ * Polls a given function waiting for it to become true.
+ *
+ * @param object aOptions
+ * Options object with the following properties:
+ * - validatorFn
+ * A validator function that returns a boolean. This is called every few
+ * milliseconds to check if the result is true. When it is true, succesFn
+ * is called and polling stops. If validatorFn never returns true, then
+ * polling timeouts after several tries and a failure is recorded.
+ * - successFn
+ * A function called when the validator function returns true.
+ * - failureFn
+ * A function called if the validator function timeouts - fails to return
+ * true in the given time.
+ * - name
+ * Name of test. This is used to generate the success and failure
+ * messages.
+ * - timeout
+ * Timeout for validator function, in milliseconds. Default is 5000.
+ */
+function waitForSuccess(aOptions)
+{
+ let start = Date.now();
+ let timeout = aOptions.timeout || 5000;
+
+ function wait(validatorFn, successFn, failureFn)
+ {
+ if ((Date.now() - start) > timeout) {
+ // Log the failure.
+ ok(false, "Timed out while waiting for: " + aOptions.name);
+ failureFn(aOptions);
+ return;
+ }
+
+ if (validatorFn(aOptions)) {
+ ok(true, aOptions.name);
+ successFn();
+ }
+ else {
+ setTimeout(function() wait(validatorFn, successFn, failureFn), 100);
+ }
+ }
+
+ wait(aOptions.validatorFn, aOptions.successFn, aOptions.failureFn);
+}
+
+function openInspector(aCallback, aTab = gBrowser.selectedTab)
+{
+ let target = TargetFactory.forTab(aTab);
+ gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+ aCallback(toolbox.getCurrentPanel());
+ });
+}
+
+/**
+ * Find variables or properties in a VariablesView instance.
+ *
+ * @param object aView
+ * The VariablesView instance.
+ * @param array aRules
+ * The array of rules you want to match. Each rule is an object with:
+ * - name (string|regexp): property name to match.
+ * - value (string|regexp): property value to match.
+ * - isIterator (boolean): check if the property is an iterator.
+ * - isGetter (boolean): check if the property is a getter.
+ * - isGenerator (boolean): check if the property is a generator.
+ * - dontMatch (boolean): make sure the rule doesn't match any property.
+ * @param object aOptions
+ * Options for matching:
+ * - webconsole: the WebConsole instance we work with.
+ * @return object
+ * A Promise object that is resolved when all the rules complete
+ * matching. The resolved callback is given an array of all the rules
+ * you wanted to check. Each rule has a new property: |matchedProp|
+ * which holds a reference to the Property object instance from the
+ * VariablesView. If the rule did not match, then |matchedProp| is
+ * undefined.
+ */
+function findVariableViewProperties(aView, aRules, aOptions)
+{
+ // Initialize the search.
+ function init()
+ {
+ // Separate out the rules that require expanding properties throughout the
+ // view.
+ let expandRules = [];
+ let rules = aRules.filter((aRule) => {
+ if (typeof aRule.name == "string" && aRule.name.indexOf(".") > -1) {
+ expandRules.push(aRule);
+ return false;
+ }
+ return true;
+ });
+
+ // Search through the view those rules that do not require any properties to
+ // be expanded. Build the array of matchers, outstanding promises to be
+ // resolved.
+ let outstanding = [];
+ finder(rules, aView, outstanding);
+
+ // Process the rules that need to expand properties.
+ let lastStep = processExpandRules.bind(null, expandRules);
+
+ // Return the results - a Promise resolved to hold the updated aRules array.
+ let returnResults = onAllRulesMatched.bind(null, aRules);
+
+ return Promise.all(outstanding).then(lastStep).then(returnResults);
+ }
+
+ function onMatch(aProp, aRule, aMatched)
+ {
+ if (aMatched && !aRule.matchedProp) {
+ aRule.matchedProp = aProp;
+ }
+ }
+
+ function finder(aRules, aVar, aPromises)
+ {
+ for (let [id, prop] in aVar) {
+ for (let rule of aRules) {
+ let matcher = matchVariablesViewProperty(prop, rule, aOptions);
+ aPromises.push(matcher.then(onMatch.bind(null, prop, rule)));
+ }
+ }
+ }
+
+ function processExpandRules(aRules)
+ {
+ let rule = aRules.shift();
+ if (!rule) {
+ return Promise.resolve(null);
+ }
+
+ let deferred = Promise.defer();
+ let expandOptions = {
+ rootVariable: aView,
+ expandTo: rule.name,
+ webconsole: aOptions.webconsole,
+ };
+
+ variablesViewExpandTo(expandOptions).then(function onSuccess(aProp) {
+ let name = rule.name;
+ let lastName = name.split(".").pop();
+ rule.name = lastName;
+
+ let matched = matchVariablesViewProperty(aProp, rule, aOptions);
+ return matched.then(onMatch.bind(null, aProp, rule)).then(function() {
+ rule.name = name;
+ });
+ }, function onFailure() {
+ return Promise.resolve(null);
+ }).then(processExpandRules.bind(null, aRules)).then(function() {
+ deferred.resolve(null);
+ });
+
+ return deferred.promise;
+ }
+
+ function onAllRulesMatched(aRules)
+ {
+ for (let rule of aRules) {
+ let matched = rule.matchedProp;
+ if (matched && !rule.dontMatch) {
+ ok(true, "rule " + rule.name + " matched for property " + matched.name);
+ }
+ else if (matched && rule.dontMatch) {
+ ok(false, "rule " + rule.name + " should not match property " +
+ matched.name);
+ }
+ else {
+ ok(rule.dontMatch, "rule " + rule.name + " did not match any property");
+ }
+ }
+ return aRules;
+ }
+
+ return init();
+}
+
+/**
+ * Check if a given Property object from the variables view matches the given
+ * rule.
+ *
+ * @param object aProp
+ * The variable's view Property instance.
+ * @param object aRule
+ * Rules for matching the property. See findVariableViewProperties() for
+ * details.
+ * @param object aOptions
+ * Options for matching. See findVariableViewProperties().
+ * @return object
+ * A Promise that is resolved when all the checks complete. Resolution
+ * result is a boolean that tells your promise callback the match
+ * result: true or false.
+ */
+function matchVariablesViewProperty(aProp, aRule, aOptions)
+{
+ function resolve(aResult) {
+ return Promise.resolve(aResult);
+ }
+
+ if (aRule.name) {
+ let match = aRule.name instanceof RegExp ?
+ aRule.name.test(aProp.name) :
+ aProp.name == aRule.name;
+ if (!match) {
+ return resolve(false);
+ }
+ }
+
+ if (aRule.value) {
+ let displayValue = aProp.displayValue;
+ if (aProp.displayValueClassName == "token-string") {
+ displayValue = displayValue.substring(1, displayValue.length - 1);
+ }
+
+ let match = aRule.value instanceof RegExp ?
+ aRule.value.test(displayValue) :
+ displayValue == aRule.value;
+ if (!match) {
+ info("rule " + aRule.name + " did not match value, expected '" +
+ aRule.value + "', found '" + displayValue + "'");
+ return resolve(false);
+ }
+ }
+
+ if ("isGetter" in aRule) {
+ let isGetter = !!(aProp.getter && aProp.get("get"));
+ if (aRule.isGetter != isGetter) {
+ info("rule " + aRule.name + " getter test failed");
+ return resolve(false);
+ }
+ }
+
+ if ("isGenerator" in aRule) {
+ let isGenerator = aProp.displayValue == "[object Generator]";
+ if (aRule.isGenerator != isGenerator) {
+ info("rule " + aRule.name + " generator test failed");
+ return resolve(false);
+ }
+ }
+
+ let outstanding = [];
+
+ if ("isIterator" in aRule) {
+ let isIterator = isVariableViewPropertyIterator(aProp, aOptions.webconsole);
+ outstanding.push(isIterator.then((aResult) => {
+ if (aResult != aRule.isIterator) {
+ info("rule " + aRule.name + " iterator test failed");
+ }
+ return aResult == aRule.isIterator;
+ }));
+ }
+
+ outstanding.push(Promise.resolve(true));
+
+ return Promise.all(outstanding).then(function _onMatchDone(aResults) {
+ let ruleMatched = aResults.indexOf(false) == -1;
+ return resolve(ruleMatched);
+ });
+}
+
+/**
+ * Check if the given variables view property is an iterator.
+ *
+ * @param object aProp
+ * The Property instance you want to check.
+ * @param object aWebConsole
+ * The WebConsole instance to work with.
+ * @return object
+ * A Promise that is resolved when the check completes. The resolved
+ * callback is given a boolean: true if the property is an iterator, or
+ * false otherwise.
+ */
+function isVariableViewPropertyIterator(aProp, aWebConsole)
+{
+ if (aProp.displayValue == "[object Iterator]") {
+ return Promise.resolve(true);
+ }
+
+ let deferred = Promise.defer();
+
+ variablesViewExpandTo({
+ rootVariable: aProp,
+ expandTo: "__proto__.__iterator__",
+ webconsole: aWebConsole,
+ }).then(function onSuccess(aProp) {
+ deferred.resolve(true);
+ }, function onFailure() {
+ deferred.resolve(false);
+ });
+
+ return deferred.promise;
+}
+
+
+/**
+ * Recursively expand the variables view up to a given property.
+ *
+ * @param aOptions
+ * Options for view expansion:
+ * - rootVariable: start from the given scope/variable/property.
+ * - expandTo: string made up of property names you want to expand.
+ * For example: "body.firstChild.nextSibling" given |rootVariable:
+ * document|.
+ * - webconsole: a WebConsole instance. If this is not provided all
+ * property expand() calls will be considered sync. Things may fail!
+ * @return object
+ * A Promise that is resolved only when the last property in |expandTo|
+ * is found, and rejected otherwise. Resolution reason is always the
+ * last property - |nextSibling| in the example above. Rejection is
+ * always the last property that was found.
+ */
+function variablesViewExpandTo(aOptions)
+{
+ let root = aOptions.rootVariable;
+ let expandTo = aOptions.expandTo.split(".");
+ let jsterm = (aOptions.webconsole || {}).jsterm;
+ let lastDeferred = Promise.defer();
+
+ function fetch(aProp)
+ {
+ if (!aProp.onexpand) {
+ ok(false, "property " + aProp.name + " cannot be expanded: !onexpand");
+ return Promise.reject(aProp);
+ }
+
+ let deferred = Promise.defer();
+
+ if (aProp._fetched || !jsterm) {
+ executeSoon(function() {
+ deferred.resolve(aProp);
+ });
+ }
+ else {
+ jsterm.once("variablesview-fetched", function _onFetchProp() {
+ executeSoon(() => deferred.resolve(aProp));
+ });
+ }
+
+ aProp.expand();
+
+ return deferred.promise;
+ }
+
+ function getNext(aProp)
+ {
+ let name = expandTo.shift();
+ let newProp = aProp.get(name);
+
+ if (expandTo.length > 0) {
+ ok(newProp, "found property " + name);
+ if (newProp) {
+ fetch(newProp).then(getNext, fetchError);
+ }
+ else {
+ lastDeferred.reject(aProp);
+ }
+ }
+ else {
+ if (newProp) {
+ lastDeferred.resolve(newProp);
+ }
+ else {
+ lastDeferred.reject(aProp);
+ }
+ }
+ }
+
+ function fetchError(aProp)
+ {
+ lastDeferred.reject(aProp);
+ }
+
+ if (!root._fetched) {
+ fetch(root).then(getNext, fetchError);
+ }
+ else {
+ getNext(root);
+ }
+
+ return lastDeferred.promise;
+}
+
+
+/**
+ * Update the content of a property in the variables view.
+ *
+ * @param object aOptions
+ * Options for the property update:
+ * - property: the property you want to change.
+ * - field: string that tells what you want to change:
+ * - use "name" to change the property name,
+ * - or "value" to change the property value.
+ * - string: the new string to write into the field.
+ * - webconsole: reference to the Web Console instance we work with.
+ * - callback: function to invoke after the property is updated.
+ */
+function updateVariablesViewProperty(aOptions)
+{
+ let view = aOptions.property._variablesView;
+ view.window.focus();
+ aOptions.property.focus();
+
+ switch (aOptions.field) {
+ case "name":
+ EventUtils.synthesizeKey("VK_ENTER", { shiftKey: true }, view.window);
+ break;
+ case "value":
+ EventUtils.synthesizeKey("VK_ENTER", {}, view.window);
+ break;
+ default:
+ throw new Error("options.field is incorrect");
+ return;
+ }
+
+ executeSoon(() => {
+ EventUtils.synthesizeKey("A", { accelKey: true }, view.window);
+
+ for (let c of aOptions.string) {
+ EventUtils.synthesizeKey(c, {}, gVariablesView.window);
+ }
+
+ if (aOptions.webconsole) {
+ aOptions.webconsole.jsterm.once("variablesview-fetched", aOptions.callback);
+ }
+
+ EventUtils.synthesizeKey("VK_ENTER", {}, view.window);
+
+ if (!aOptions.webconsole) {
+ executeSoon(aOptions.callback);
+ }
+ });
+}
+
+/**
+ * Open the JavaScript debugger.
+ *
+ * @param object aOptions
+ * Options for opening the debugger:
+ * - tab: the tab you want to open the debugger for.
+ * @return object
+ * A Promise that is resolved once the debugger opens, or rejected if
+ * the open fails. The resolution callback is given one argument, an
+ * object that holds the following properties:
+ * - target: the Target object for the Tab.
+ * - toolbox: the Toolbox instance.
+ * - panel: the jsdebugger panel instance.
+ * - panelWin: the window object of the panel iframe.
+ */
+function openDebugger(aOptions = {})
+{
+ if (!aOptions.tab) {
+ aOptions.tab = gBrowser.selectedTab;
+ }
+
+ let deferred = Promise.defer();
+
+ let target = TargetFactory.forTab(aOptions.tab);
+ let toolbox = gDevTools.getToolbox(target);
+ let dbgPanelAlreadyOpen = toolbox.getPanel("jsdebugger");
+
+ gDevTools.showToolbox(target, "jsdebugger").then(function onSuccess(aToolbox) {
+ let panel = aToolbox.getCurrentPanel();
+ let panelWin = panel.panelWin;
+
+ panel._view.Variables.lazyEmpty = false;
+ panel._view.Variables.lazyAppend = false;
+
+ let resolveObject = {
+ target: target,
+ toolbox: aToolbox,
+ panel: panel,
+ panelWin: panelWin,
+ };
+
+ if (dbgPanelAlreadyOpen) {
+ deferred.resolve(resolveObject);
+ }
+ else {
+ panelWin.addEventListener("Debugger:AfterSourcesAdded",
+ function onAfterSourcesAdded() {
+ panelWin.removeEventListener("Debugger:AfterSourcesAdded",
+ onAfterSourcesAdded);
+ deferred.resolve(resolveObject);
+ });
+ }
+ }, function onFailure(aReason) {
+ console.debug("failed to open the toolbox for 'jsdebugger'", aReason);
+ deferred.reject(aReason);
+ });
+
+ return deferred.promise;
+}
+
+/**
+ * Get the full text displayed by a Web Console message.
+ *
+ * @param nsIDOMElement aElement
+ * The message element from the Web Console output.
+ * @return string
+ * The full text displayed by the given message element.
+ */
+function getMessageElementText(aElement)
+{
+ let text = aElement.textContent;
+ let labels = aElement.querySelectorAll("label");
+ for (let label of labels) {
+ text += " " + label.getAttribute("value");
+ }
+ return text;
+}
+
+/**
+ * Wait for messages in the Web Console output.
+ *
+ * @param object aOptions
+ * Options for what you want to wait for:
+ * - webconsole: the webconsole instance you work with.
+ * - messages: an array of objects that tells which messages to wait for.
+ * Properties:
+ * - text: string or RegExp to match the textContent of each new
+ * message.
+ * - noText: string or RegExp that must not match in the message
+ * textContent.
+ * - repeats: the number of message repeats, as displayed by the Web
+ * Console.
+ * - category: match message category. See CATEGORY_* constants at
+ * the top of this file.
+ * - severity: match message severity. See SEVERITY_* constants at
+ * the top of this file.
+ * - count: how many unique web console messages should be matched by
+ * this rule.
+ * - consoleTrace: boolean, set to |true| to match a console.trace()
+ * message. Optionally this can be an object of the form
+ * { file, fn, line } that can match the specified file, function
+ * and/or line number in the trace message.
+ * - consoleTime: string that matches a console.time() timer name.
+ * Provide this if you want to match a console.time() message.
+ * - consoleTimeEnd: same as above, but for console.timeEnd().
+ * - consoleDir: boolean, set to |true| to match a console.dir()
+ * message.
+ * - longString: boolean, set to |true} to match long strings in the
+ * message.
+ * - objects: boolean, set to |true| if you expect inspectable
+ * objects in the message.
+ * - source: object of the shape { url, line }. This is used to
+ * match the source URL and line number of the error message or
+ * console API call.
+ * @return object
+ * A Promise object is returned once the messages you want are found.
+ * The promise is resolved with the array of rule objects you give in
+ * the |messages| property. Each objects is the same as provided, with
+ * additional properties:
+ * - matched: a Set of web console messages that matched the rule.
+ * - clickableElements: a list of inspectable objects. This is available
+ * if any of the following properties are present in the rule:
+ * |consoleTrace| or |objects|.
+ * - longStrings: a list of long string ellipsis elements you can click
+ * in the message element, to expand a long string. This is available
+ * only if |longString| is present in the matching rule.
+ */
+function waitForMessages(aOptions)
+{
+ gPendingOutputTest++;
+ let webconsole = aOptions.webconsole;
+ let rules = WebConsoleUtils.cloneObject(aOptions.messages, true);
+ let rulesMatched = 0;
+ let listenerAdded = false;
+ let deferred = Promise.defer();
+
+ function checkText(aRule, aText)
+ {
+ let result;
+ if (typeof aRule == "string") {
+ result = aText.indexOf(aRule) > -1;
+ }
+ else if (aRule instanceof RegExp) {
+ result = aRule.test(aText);
+ }
+ return result;
+ }
+
+ function checkConsoleTrace(aRule, aElement)
+ {
+ let elemText = getMessageElementText(aElement);
+ let trace = aRule.consoleTrace;
+
+ if (!checkText("Stack trace from ", elemText)) {
+ return false;
+ }
+
+ let clickable = aElement.querySelector(".hud-clickable");
+ if (!clickable) {
+ ok(false, "console.trace() message is missing .hud-clickable");
+ displayErrorContext(aRule, aElement);
+ return false;
+ }
+ aRule.clickableElements = [clickable];
+
+ if (trace.file &&
+ !checkText("from " + trace.file + ", ", elemText)) {
+ ok(false, "console.trace() message is missing the file name: " +
+ trace.file);
+ displayErrorContext(aRule, aElement);
+ return false;
+ }
+
+ if (trace.fn &&
+ !checkText(", function " + trace.fn + ", ", elemText)) {
+ ok(false, "console.trace() message is missing the function name: " +
+ trace.fn);
+ displayErrorContext(aRule, aElement);
+ return false;
+ }
+
+ if (trace.line &&
+ !checkText(", line " + trace.line + ".", elemText)) {
+ ok(false, "console.trace() message is missing the line number: " +
+ trace.line);
+ displayErrorContext(aRule, aElement);
+ return false;
+ }
+
+ aRule.category = CATEGORY_WEBDEV;
+ aRule.severity = SEVERITY_LOG;
+
+ return true;
+ }
+
+ function checkConsoleTime(aRule, aElement)
+ {
+ let elemText = getMessageElementText(aElement);
+ let time = aRule.consoleTime;
+
+ if (!checkText(time + ": timer started", elemText)) {
+ return false;
+ }
+
+ aRule.category = CATEGORY_WEBDEV;
+ aRule.severity = SEVERITY_LOG;
+
+ return true;
+ }
+
+ function checkConsoleTimeEnd(aRule, aElement)
+ {
+ let elemText = getMessageElementText(aElement);
+ let time = aRule.consoleTimeEnd;
+ let regex = new RegExp(time + ": -?\\d+ms");
+
+ if (!checkText(regex, elemText)) {
+ return false;
+ }
+
+ aRule.category = CATEGORY_WEBDEV;
+ aRule.severity = SEVERITY_LOG;
+
+ return true;
+ }
+
+ function checkConsoleDir(aRule, aElement)
+ {
+ if (!aElement.classList.contains("webconsole-msg-inspector")) {
+ return false;
+ }
+
+ let elemText = getMessageElementText(aElement);
+ if (!checkText(aRule.consoleDir, elemText)) {
+ return false;
+ }
+
+ let iframe = aElement.querySelector("iframe");
+ if (!iframe) {
+ ok(false, "console.dir message has no iframe");
+ return false;
+ }
+
+ return true;
+ }
+
+ function checkSource(aRule, aElement)
+ {
+ let location = aElement.querySelector(".webconsole-location");
+ if (!location) {
+ return false;
+ }
+
+ if (!checkText(aRule.source.url, location.getAttribute("title"))) {
+ return false;
+ }
+
+ if ("line" in aRule.source && location.sourceLine != aRule.source.line) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function checkMessage(aRule, aElement)
+ {
+ let elemText = getMessageElementText(aElement);
+
+ if (aRule.text && !checkText(aRule.text, elemText)) {
+ return false;
+ }
+
+ if (aRule.noText && checkText(aRule.noText, elemText)) {
+ return false;
+ }
+
+ if (aRule.consoleTrace && !checkConsoleTrace(aRule, aElement)) {
+ return false;
+ }
+
+ if (aRule.consoleTime && !checkConsoleTime(aRule, aElement)) {
+ return false;
+ }
+
+ if (aRule.consoleTimeEnd && !checkConsoleTimeEnd(aRule, aElement)) {
+ return false;
+ }
+
+ if (aRule.consoleDir && !checkConsoleDir(aRule, aElement)) {
+ return false;
+ }
+
+ if (aRule.source && !checkSource(aRule, aElement)) {
+ return false;
+ }
+
+ let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
+ aRule.consoleTimeEnd);
+
+ if (aRule.category && aElement.category != aRule.category) {
+ if (partialMatch) {
+ is(aElement.category, aRule.category,
+ "message category for rule: " + displayRule(aRule));
+ displayErrorContext(aRule, aElement);
+ }
+ return false;
+ }
+
+ if (aRule.severity && aElement.severity != aRule.severity) {
+ if (partialMatch) {
+ is(aElement.severity, aRule.severity,
+ "message severity for rule: " + displayRule(aRule));
+ displayErrorContext(aRule, aElement);
+ }
+ return false;
+ }
+
+ if (aRule.repeats) {
+ let repeats = aElement.querySelector(".webconsole-msg-repeat");
+ if (!repeats || repeats.getAttribute("value") != aRule.repeats) {
+ return false;
+ }
+ }
+
+ if ("longString" in aRule) {
+ let longStrings = aElement.querySelectorAll(".longStringEllipsis");
+ if (aRule.longString != !!longStrings[0]) {
+ if (partialMatch) {
+ is(!!longStrings[0], aRule.longString,
+ "long string existence check failed for message rule: " +
+ displayRule(aRule));
+ displayErrorContext(aRule, aElement);
+ }
+ return false;
+ }
+ aRule.longStrings = longStrings;
+ }
+
+ if ("objects" in aRule) {
+ let clickables = aElement.querySelectorAll(".hud-clickable");
+ if (aRule.objects != !!clickables[0]) {
+ if (partialMatch) {
+ is(!!clickables[0], aRule.objects,
+ "objects existence check failed for message rule: " +
+ displayRule(aRule));
+ displayErrorContext(aRule, aElement);
+ }
+ return false;
+ }
+ aRule.clickableElements = clickables;
+ }
+
+ let count = aRule.count || 1;
+ if (!aRule.matched) {
+ aRule.matched = new Set();
+ }
+ aRule.matched.add(aElement);
+
+ return aRule.matched.size == count;
+ }
+
+ function onMessagesAdded(aEvent, aNewElements)
+ {
+ for (let elem of aNewElements) {
+ let location = elem.querySelector(".webconsole-location");
+ if (location) {
+ let url = location.getAttribute("title");
+ // Prevent recursion with the browser console and any potential
+ // messages coming from head.js.
+ if (url.indexOf("browser/devtools/webconsole/test/head.js") != -1) {
+ continue;
+ }
+ }
+
+ for (let rule of rules) {
+ if (rule._ruleMatched) {
+ continue;
+ }
+
+ let matched = checkMessage(rule, elem);
+ if (matched) {
+ rule._ruleMatched = true;
+ rulesMatched++;
+ ok(1, "matched rule: " + displayRule(rule));
+ if (maybeDone()) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ function maybeDone()
+ {
+ if (rulesMatched == rules.length) {
+ if (listenerAdded) {
+ webconsole.ui.off("messages-added", onMessagesAdded);
+ webconsole.ui.off("messages-updated", onMessagesAdded);
+ }
+ gPendingOutputTest--;
+ deferred.resolve(rules);
+ return true;
+ }
+ return false;
+ }
+
+ function testCleanup() {
+ if (rulesMatched == rules.length) {
+ return;
+ }
+
+ if (webconsole.ui) {
+ webconsole.ui.off("messages-added", onMessagesAdded);
+ }
+
+ for (let rule of rules) {
+ if (!rule._ruleMatched) {
+ ok(false, "failed to match rule: " + displayRule(rule));
+ }
+ }
+ }
+
+ function displayRule(aRule)
+ {
+ return aRule.name || aRule.text;
+ }
+
+ function displayErrorContext(aRule, aElement)
+ {
+ console.log("error occured during rule " + displayRule(aRule));
+ console.log("while checking the following message");
+ dumpMessageElement(aElement);
+ }
+
+ executeSoon(() => {
+ onMessagesAdded("messages-added", webconsole.outputNode.childNodes);
+ if (rulesMatched != rules.length) {
+ listenerAdded = true;
+ registerCleanupFunction(testCleanup);
+ webconsole.ui.on("messages-added", onMessagesAdded);
+ webconsole.ui.on("messages-updated", onMessagesAdded);
+ }
+ });
+
+ return deferred.promise;
+}
+
+
+/**
+ * Scroll the Web Console output to the given node.
+ *
+ * @param nsIDOMNode aNode
+ * The node to scroll to.
+ */
+function scrollOutputToNode(aNode)
+{
+ let richListBoxNode = aNode.parentNode;
+ while (richListBoxNode.tagName != "richlistbox") {
+ richListBoxNode = richListBoxNode.parentNode;
+ }
+
+ let boxObject = richListBoxNode.scrollBoxObject;
+ let nsIScrollBoxObject = boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+ nsIScrollBoxObject.ensureElementIsVisible(aNode);
+}
+
+function whenDelayedStartupFinished(aWindow, aCallback)
+{
+ Services.obs.addObserver(function observer(aSubject, aTopic) {
+ if (aWindow == aSubject) {
+ Services.obs.removeObserver(observer, aTopic);
+ executeSoon(aCallback);
+ }
+ }, "browser-delayed-startup-finished", false);
+}
diff --git a/browser/devtools/webconsole/test/moz.build b/browser/devtools/webconsole/test/moz.build
new file mode 100644
index 000000000..895d11993
--- /dev/null
+++ b/browser/devtools/webconsole/test/moz.build
@@ -0,0 +1,6 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
diff --git a/browser/devtools/webconsole/test/test-bug-585956-console-trace.html b/browser/devtools/webconsole/test/test-bug-585956-console-trace.html
new file mode 100644
index 000000000..e658ba633
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-585956-console-trace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head><meta charset="utf-8">
+ <title>Web Console test for bug 585956 - console.trace()</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+<script type="application/javascript">
+window.foobar585956c = function(a) {
+ console.trace();
+ return a+"c";
+};
+
+function foobar585956b(a) {
+ return foobar585956c(a+"b");
+}
+
+function foobar585956a(omg) {
+ return foobar585956b(omg + "a");
+}
+
+foobar585956a("omg");
+</script>
+ </head>
+ <body>
+ <p>Web Console test for bug 585956 - console.trace().</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud-iframe.html b/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud-iframe.html
new file mode 100644
index 000000000..ebf9c515f
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud-iframe.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>WebConsole test: iframe associated to the wrong HUD</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>WebConsole test: iframe associated to the wrong HUD.</p>
+ <p>This is the iframe!</p>
+ </body>
+ </html>
diff --git a/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud.html b/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud.html
new file mode 100644
index 000000000..5b12278d1
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>WebConsole test: iframe associated to the wrong HUD</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>WebConsole test: iframe associated to the wrong HUD.</p>
+ <iframe
+ src="http://example.com/browser/browser/devtools/webconsole/test/test-bug-593003-iframe-wrong-hud-iframe.html"></iframe>
+ </body>
+ </html>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-canvas-css.html b/browser/devtools/webconsole/test/test-bug-595934-canvas-css.html
new file mode 100644
index 000000000..3c9cf03a5
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-canvas-css.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: CSS Parser (with
+ Canvas)</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript"
+ src="test-bug-595934-canvas-css.js"></script>
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "CSS Parser" (with
+ Canvas).</p>
+ <p><canvas width="200" height="200">Canvas support is required!</canvas></p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-canvas-css.js b/browser/devtools/webconsole/test/test-bug-595934-canvas-css.js
new file mode 100644
index 000000000..cc364d6a3
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-canvas-css.js
@@ -0,0 +1,10 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+window.addEventListener("DOMContentLoaded", function() {
+ var canvas = document.querySelector("canvas");
+ var context = canvas.getContext("2d");
+ context.strokeStyle = "foobarCanvasCssParser";
+}, false);
diff --git a/browser/devtools/webconsole/test/test-bug-595934-canvas.html b/browser/devtools/webconsole/test/test-bug-595934-canvas.html
new file mode 100644
index 000000000..399b62098
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-canvas.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: Canvas</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript"
+ src="test-bug-595934-canvas.js"></script>
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "Canvas".</p>
+ <p><canvas width="200" height="200">Canvas support is required!</canvas></p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-canvas.js b/browser/devtools/webconsole/test/test-bug-595934-canvas.js
new file mode 100644
index 000000000..7d77d7696
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-canvas.js
@@ -0,0 +1,11 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+window.addEventListener("DOMContentLoaded", function() {
+ var canvas = document.querySelector("canvas");
+ var context = canvas.getContext("2d");
+ context.strokeStyle = document;
+}, false);
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-css-loader.css b/browser/devtools/webconsole/test/test-bug-595934-css-loader.css
new file mode 100644
index 000000000..b4224430f
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-css-loader.css
@@ -0,0 +1,10 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+body {
+ color: #0f0;
+ font-weight: bold;
+}
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-css-loader.css^headers^ b/browser/devtools/webconsole/test/test-bug-595934-css-loader.css^headers^
new file mode 100644
index 000000000..e7be84a71
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-css-loader.css^headers^
@@ -0,0 +1 @@
+Content-Type: image/png
diff --git a/browser/devtools/webconsole/test/test-bug-595934-css-loader.html b/browser/devtools/webconsole/test/test-bug-595934-css-loader.html
new file mode 100644
index 000000000..6bb0d54c5
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-css-loader.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: CSS Loader</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <link rel="stylesheet" href="test-bug-595934-css-loader.css">
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "CSS Loader".</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-css-parser.css b/browser/devtools/webconsole/test/test-bug-595934-css-parser.css
new file mode 100644
index 000000000..f6db82398
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-css-parser.css
@@ -0,0 +1,10 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+p {
+ color: #0f0;
+ foobarCssParser: failure;
+}
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-css-parser.html b/browser/devtools/webconsole/test/test-bug-595934-css-parser.html
new file mode 100644
index 000000000..a4ea74ba3
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-css-parser.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: CSS Parser</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <link rel="stylesheet" type="text/css"
+ href="test-bug-595934-css-parser.css">
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "CSS Parser".</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.html b/browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.html
new file mode 100644
index 000000000..a70f9011b
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: DOM.
+ (empty getElementById())</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript"
+ src="test-bug-595934-empty-getelementbyid.js"></script>
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "DOM"
+ (empty getElementById()).</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.js b/browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.js
new file mode 100644
index 000000000..dd94d716d
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-empty-getelementbyid.js
@@ -0,0 +1,8 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+window.addEventListener("load", function() {
+ document.getElementById("");
+}, false);
diff --git a/browser/devtools/webconsole/test/test-bug-595934-html.html b/browser/devtools/webconsole/test/test-bug-595934-html.html
new file mode 100644
index 000000000..fe35afef6
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: HTML</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "HTML".</p>
+ <form action="?" enctype="multipart/form-data">
+ <p><label>Input <input type="text" value="test value"></label></p>
+ </form>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-image.html b/browser/devtools/webconsole/test/test-bug-595934-image.html
new file mode 100644
index 000000000..312ecd49f
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-image.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: Image</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category Image.</p>
+ <p><img src="test-bug-595934-image.jpg" alt="corrupted image"></p>
+ </body>
+</html>
+
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-image.jpg b/browser/devtools/webconsole/test/test-bug-595934-image.jpg
new file mode 100644
index 000000000..947e5f11b
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-image.jpg
Binary files differ
diff --git a/browser/devtools/webconsole/test/test-bug-595934-imagemap.html b/browser/devtools/webconsole/test/test-bug-595934-imagemap.html
new file mode 100644
index 000000000..007c3c01b
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-imagemap.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: ImageMap</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "ImageMap".</p>
+ <p><img src="test-image.png" usemap="#testMap" alt="Test image"></p>
+ <map name="testMap">
+ <area shape="rect" coords="0,0,10,10,5" href="#" alt="Test area" />
+ </map>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.html b/browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.html
new file mode 100644
index 000000000..2fd8beac5
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: malformed-xml.
+ (external file)</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript"><!--
+ var req = new XMLHttpRequest();
+ req.open("GET", "test-bug-595934-malformedxml-external.xml", true);
+ req.send(null);
+ // --></script>
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "malformed-xml"
+ (external file).</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.xml b/browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.xml
new file mode 100644
index 000000000..4812786f1
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-malformedxml-external.xml
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "malformed-xml".</p>
+ </body>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-malformedxml.xhtml b/browser/devtools/webconsole/test/test-bug-595934-malformedxml.xhtml
new file mode 100644
index 000000000..62689c567
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-malformedxml.xhtml
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Web Console test for bug 595934 - category: malformed-xml</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "malformed-xml".</p>
+ </body>
diff --git a/browser/devtools/webconsole/test/test-bug-595934-svg.xhtml b/browser/devtools/webconsole/test/test-bug-595934-svg.xhtml
new file mode 100644
index 000000000..572382c64
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-svg.xhtml
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Web Console test for bug 595934 - category: SVG</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - category "SVG".</p>
+ <svg version="1.1" width="120" height="fooBarSVG"
+ xmlns="http://www.w3.org/2000/svg">
+ <ellipse fill="#0f0" stroke="#000" cx="50%"
+ cy="50%" rx="50%" ry="50%" />
+ </svg>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-workers.html b/browser/devtools/webconsole/test/test-bug-595934-workers.html
new file mode 100644
index 000000000..baf5a6215
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-workers.html
@@ -0,0 +1,18 @@
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 595934 - category: DOM Worker
+ javascript</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p id="foobar">Web Console test for bug 595934 - category "DOM Worker
+ javascript".</p>
+ <script type="text/javascript">
+ var myWorker = new Worker("test-bug-595934-workers.js");
+ myWorker.postMessage("hello world");
+ </script>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-595934-workers.js b/browser/devtools/webconsole/test/test-bug-595934-workers.js
new file mode 100644
index 000000000..4e93c967b
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-595934-workers.js
@@ -0,0 +1,9 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+onmessage = function() {
+ fooBarWorker();
+}
+
diff --git a/browser/devtools/webconsole/test/test-bug-597136-external-script-errors.html b/browser/devtools/webconsole/test/test-bug-597136-external-script-errors.html
new file mode 100644
index 000000000..25bdeecc5
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-597136-external-script-errors.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+<!--
+ ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK *****
+ -->
+ <title>Test for bug 597136: external script errors</title>
+ </head>
+ <body>
+ <h1>Test for bug 597136: external script errors</h1>
+ <p><button onclick="f()">Click me</button</p>
+
+ <script type="text/javascript"
+ src="test-bug-597136-external-script-errors.js"></script>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-597136-external-script-errors.js b/browser/devtools/webconsole/test/test-bug-597136-external-script-errors.js
new file mode 100644
index 000000000..87c0aff8e
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-597136-external-script-errors.js
@@ -0,0 +1,14 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function f() {
+ bogus.g();
+}
+
diff --git a/browser/devtools/webconsole/test/test-bug-597756-reopen-closed-tab.html b/browser/devtools/webconsole/test/test-bug-597756-reopen-closed-tab.html
new file mode 100644
index 000000000..68e19e677
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-597756-reopen-closed-tab.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Bug 597756: test error logging after tab close and reopen</title>
+ <!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ </head>
+ <body>
+ <h1>Bug 597756: test error logging after tab close and reopen.</h1>
+
+ <script type="text/javascript"><!--
+ fooBug597756_error.bar();
+ // --></script>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs b/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs
new file mode 100644
index 000000000..2e78d6b7b
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs
@@ -0,0 +1,25 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response)
+{
+ var Etag = '"4c881ab-b03-435f0a0f9ef00"';
+ var IfNoneMatch = request.hasHeader("If-None-Match")
+ ? request.getHeader("If-None-Match")
+ : "";
+
+ var page = "<!DOCTYPE html><html><body><p>hello world!</p></body></html>";
+
+ response.setHeader("Etag", Etag, false);
+
+ if (IfNoneMatch == Etag) {
+ response.setStatusLine(request.httpVersion, "304", "Not Modified");
+ }
+ else {
+ response.setHeader("Content-Type", "text/html", false);
+ response.setHeader("Content-Length", page.length + "", false);
+ response.write(page);
+ }
+}
diff --git a/browser/devtools/webconsole/test/test-bug-600183-charset.html b/browser/devtools/webconsole/test/test-bug-600183-charset.html
new file mode 100644
index 000000000..040490a6b
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-600183-charset.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="gb2312">
+ <title>Console HTTP test page (chinese)</title>
+ </head>
+ <body>
+ <p>µÄÎʺò!</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-600183-charset.html^headers^ b/browser/devtools/webconsole/test/test-bug-600183-charset.html^headers^
new file mode 100644
index 000000000..9f3e2302f
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-600183-charset.html^headers^
@@ -0,0 +1 @@
+Content-Type: text/html; charset=gb2312
diff --git a/browser/devtools/webconsole/test/test-bug-601177-log-levels.html b/browser/devtools/webconsole/test/test-bug-601177-log-levels.html
new file mode 100644
index 000000000..a59213907
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-601177-log-levels.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 601177: log levels</title>
+ <script src="test-bug-601177-log-levels.js" type="text/javascript"></script>
+ <script type="text/javascript"><!--
+ window.undefinedPropertyBug601177;
+ // --></script>
+ <!--
+ - Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ </head>
+ <body>
+ <h1>Web Console test for bug 601177: log levels</h1>
+ <img src="test-image.png?bug601177">
+ <img src="foobar-known-to-fail.png?bug601177">
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-601177-log-levels.js b/browser/devtools/webconsole/test/test-bug-601177-log-levels.js
new file mode 100644
index 000000000..ea37f533d
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-601177-log-levels.js
@@ -0,0 +1,8 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+foobarBug601177strictError = "strict error";
+
+window.foobarBug601177exception();
diff --git a/browser/devtools/webconsole/test/test-bug-603750-websocket.html b/browser/devtools/webconsole/test/test-bug-603750-websocket.html
new file mode 100644
index 000000000..f0097dd77
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-603750-websocket.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 603750 - Web Socket errors</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Web Console test for bug 595934 - Web Socket errors.</p>
+ <iframe src="data:text/html;charset=utf-8,hello world!"></iframe>
+ <script type="text/javascript" src="test-bug-603750-websocket.js"></script>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-603750-websocket.js b/browser/devtools/webconsole/test/test-bug-603750-websocket.js
new file mode 100644
index 000000000..3746424cc
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-603750-websocket.js
@@ -0,0 +1,18 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+window.addEventListener("load", function () {
+ var ws1 = new WebSocket("ws://0.0.0.0:81");
+ ws1.onopen = function() {
+ ws1.send("test 1");
+ ws1.close();
+ };
+
+ var ws2 = new window.frames[0].WebSocket("ws://0.0.0.0:82");
+ ws2.onopen = function() {
+ ws2.send("test 2");
+ ws2.close();
+ };
+}, false);
diff --git a/browser/devtools/webconsole/test/test-bug-613013-console-api-iframe.html b/browser/devtools/webconsole/test/test-bug-613013-console-api-iframe.html
new file mode 100644
index 000000000..edf40e80e
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-613013-console-api-iframe.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>test for bug 613013</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>test for bug 613013</p>
+ <script type="text/javascript"><!--
+ (function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = 'data:text/html;charset=utf-8,little iframe';
+ document.body.appendChild(iframe);
+
+ console.log("foobarBug613013");
+ })();
+ // --></script>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-618078-network-exceptions.html b/browser/devtools/webconsole/test/test-bug-618078-network-exceptions.html
new file mode 100644
index 000000000..ac755e1b9
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-618078-network-exceptions.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 618078 - exception in async network request
+ callback</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript">
+ var req = new XMLHttpRequest();
+ req.open('GET', 'http://example.com', true);
+ req.onreadystatechange = function() {
+ if (req.readyState == 4) {
+ bug618078exception();
+ }
+ };
+ req.send(null);
+ </script>
+ </head>
+ <body>
+ <p>Web Console test for bug 618078 - exception in async network request
+ callback.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-621644-jsterm-dollar.html b/browser/devtools/webconsole/test/test-bug-621644-jsterm-dollar.html
new file mode 100644
index 000000000..09c986703
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-621644-jsterm-dollar.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 621644</title>
+ <script>
+ function $(elem) {
+ return elem.innerHTML;
+ }
+ function $$(doc) {
+ return doc.title;
+ }
+ </script>
+ <!--
+ - Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ </head>
+ <body>
+ <h1>Web Console test for bug 621644</h1>
+ <p>hello world!</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-630733-response-redirect-headers.sjs b/browser/devtools/webconsole/test/test-bug-630733-response-redirect-headers.sjs
new file mode 100644
index 000000000..f92e0fe65
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-630733-response-redirect-headers.sjs
@@ -0,0 +1,16 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response)
+{
+ var page = "<!DOCTYPE html><html><body><p>hello world! bug 630733</p></body></html>";
+
+ response.setStatusLine(request.httpVersion, "301", "Moved Permanently");
+ response.setHeader("Content-Type", "text/html", false);
+ response.setHeader("Content-Length", page.length + "", false);
+ response.setHeader("x-foobar-bug630733", "bazbaz", false);
+ response.setHeader("Location", "/redirect-from-bug-630733", false);
+ response.write(page);
+}
diff --git a/browser/devtools/webconsole/test/test-bug-632275-getters.html b/browser/devtools/webconsole/test/test-bug-632275-getters.html
new file mode 100644
index 000000000..349c301f3
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-632275-getters.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 632275 - getters</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+
+<script type="application/javascript;version=1.8">
+ document.foobar = {
+ _val: 5,
+ get val() { return ++this._val; }
+ };
+</script>
+
+ </head>
+ <body>
+ <p>Web Console test for bug 632275 - getters.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html b/browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html
new file mode 100644
index 000000000..ae6e5201c
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 632347 - iterators and generators</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+<script type="application/javascript;version=1.8">
+(function(){
+function genFunc() {
+ var a = 5;
+ while (a < 10) {
+ yield a++;
+ }
+}
+
+window.gen1 = genFunc();
+gen1.next();
+
+var obj = { foo: "bar", baz: "baaz", hay: "stack" };
+window.iter1 = Iterator(obj);
+
+function Range(low, high) {
+ this.low = low;
+ this.high = high;
+}
+
+function RangeIterator(range) {
+ this.range = range;
+ this.current = this.range.low;
+}
+
+RangeIterator.prototype.next = function() {
+ if (this.current > this.range.high) {
+ throw StopIteration;
+ } else {
+ return this.current++;
+ }
+}
+
+Range.prototype.__iterator__ = function() {
+ return new RangeIterator(this);
+}
+
+window.iter2 = new Range(3, 15);
+
+window.gen2 = (i * 2 for (i in iter2));
+})();
+</script>
+ </head>
+ <body>
+ <p>Web Console test for bug 632347 - iterators and generators.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-644419-log-limits.html b/browser/devtools/webconsole/test/test-bug-644419-log-limits.html
new file mode 100644
index 000000000..21d99ba14
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-644419-log-limits.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for bug 644419: console log limits</title>
+ </head>
+ <body>
+ <h1>Test for bug 644419: Console should have user-settable log limits for
+ each message category</h1>
+
+ <script type="text/javascript">
+ function foo() {
+ bar.baz();
+ }
+ foo();
+ </script>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-646025-console-file-location.html b/browser/devtools/webconsole/test/test-bug-646025-console-file-location.html
new file mode 100644
index 000000000..7c80f1446
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-646025-console-file-location.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Console file location test</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script src="test-file-location.js"></script>
+ </head>
+ <body>
+ <h1>Web Console File Location Test Page</h1>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-658368-time-methods.html b/browser/devtools/webconsole/test/test-bug-658368-time-methods.html
new file mode 100644
index 000000000..cc50b6313
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-658368-time-methods.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for bug 658368: Expand console object with time and timeEnd
+ methods</title>
+ </head>
+ <body>
+ <h1>Test for bug 658368: Expand console object with time and timeEnd
+ methods</h1>
+
+ <script type="text/javascript">
+ function foo() {
+ console.timeEnd("aTimer");
+ }
+ console.time("aTimer");
+ foo();
+ console.time("bTimer");
+ </script>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html b/browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html
new file mode 100644
index 000000000..db83274f0
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf8">
+ <title>Mixed Content test - http on https</title>
+ <script src="testscript.js"></script>
+ <!--
+ - Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ </head>
+ <body>
+ <iframe src = "http://example.com"></iframe>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-766001-console-log.js b/browser/devtools/webconsole/test/test-bug-766001-console-log.js
new file mode 100644
index 000000000..41594d76a
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-766001-console-log.js
@@ -0,0 +1,8 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+window.addEventListener("load", function() {
+ console.log("Blah Blah");
+}, false);
diff --git a/browser/devtools/webconsole/test/test-bug-766001-js-console-links.html b/browser/devtools/webconsole/test/test-bug-766001-js-console-links.html
new file mode 100644
index 000000000..6a6ac6008
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-766001-js-console-links.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 766001 : Open JS/Console call Links in Debugger</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript" src="test-bug-766001-js-errors.js"></script>
+ <script type="text/javascript" src="test-bug-766001-console-log.js"></script>
+ </head>
+ <body>
+ <p>Web Console test for bug 766001 : Open JS/Console call Links in Debugger.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-766001-js-errors.js b/browser/devtools/webconsole/test/test-bug-766001-js-errors.js
new file mode 100644
index 000000000..932204395
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-766001-js-errors.js
@@ -0,0 +1,7 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+window.addEventListener("load", function() {
+ document.bar();
+}, false);
diff --git a/browser/devtools/webconsole/test/test-bug-782653-css-errors-1.css b/browser/devtools/webconsole/test/test-bug-782653-css-errors-1.css
new file mode 100644
index 000000000..ad7fd1999
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-782653-css-errors-1.css
@@ -0,0 +1,10 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+body {
+ color: #0f0;
+ font-weight: green;
+}
+
diff --git a/browser/devtools/webconsole/test/test-bug-782653-css-errors-2.css b/browser/devtools/webconsole/test/test-bug-782653-css-errors-2.css
new file mode 100644
index 000000000..91b14137a
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-782653-css-errors-2.css
@@ -0,0 +1,10 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+body {
+ color: #0fl;
+ font-weight: bold;
+}
+
diff --git a/browser/devtools/webconsole/test/test-bug-782653-css-errors.html b/browser/devtools/webconsole/test/test-bug-782653-css-errors.html
new file mode 100644
index 000000000..7ca11fc34
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-782653-css-errors.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 782653 : Open CSS Links in Style Editor</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <link rel="stylesheet" href="test-bug-782653-css-errors-1.css">
+ <link rel="stylesheet" href="test-bug-782653-css-errors-2.css">
+ </head>
+ <body>
+ <p>Web Console test for bug 782653 : Open CSS Links in Style Editor.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-821877-csperrors.html b/browser/devtools/webconsole/test/test-bug-821877-csperrors.html
new file mode 100644
index 000000000..25d9da1c0
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-821877-csperrors.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>Bug 821877 - Log CSP Errors to Web Console</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>This page is served with a deprecated CSP header.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-821877-csperrors.html^headers^ b/browser/devtools/webconsole/test/test-bug-821877-csperrors.html^headers^
new file mode 100644
index 000000000..426d8738c
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-821877-csperrors.html^headers^
@@ -0,0 +1 @@
+X-Content-Security-Policy: default-src *; options inline-script
diff --git a/browser/devtools/webconsole/test/test-bug-837351-security-errors.html b/browser/devtools/webconsole/test/test-bug-837351-security-errors.html
new file mode 100644
index 000000000..db83274f0
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-837351-security-errors.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf8">
+ <title>Mixed Content test - http on https</title>
+ <script src="testscript.js"></script>
+ <!--
+ - Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ </head>
+ <body>
+ <iframe src = "http://example.com"></iframe>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-bug-859170-longstring-hang.html b/browser/devtools/webconsole/test/test-bug-859170-longstring-hang.html
new file mode 100644
index 000000000..509e424d0
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-859170-longstring-hang.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head><meta charset="utf-8">
+ <title>Web Console test for bug 859170 - very long strings hang the browser</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+<script type="application/javascript">
+(function() {
+var longString = "abbababazomglolztest";
+for (var i = 0; i < 10; i++) {
+ longString += longString + longString;
+}
+
+longString = "foobar" + (new Array(20000)).join("a") + "foobaz" +
+ longString + "boom!";
+console.log(longString);
+})();
+</script>
+ </head>
+ <body>
+ <p>Web Console test for bug 859170 - very long strings hang the browser.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-869003-iframe.html b/browser/devtools/webconsole/test/test-bug-869003-iframe.html
new file mode 100644
index 000000000..5a29728e5
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-869003-iframe.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 869003</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript"><!--
+ window.onload = function testConsoleLogging()
+ {
+ var o = { hello: "world!", bug: 869003 };
+ console.log("foobar", o);
+ };
+ // --></script>
+ </head>
+ <body>
+ <p>Make sure users can inspect objects from cross-domain iframes.</p>
+ <p>Iframe window.</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-bug-869003-top-window.html b/browser/devtools/webconsole/test/test-bug-869003-top-window.html
new file mode 100644
index 000000000..ab3b87542
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-869003-top-window.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test for bug 869003</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Make sure users can inspect objects from cross-domain iframes.</p>
+ <p>Top window.</p>
+ <iframe src="http://example.org/browser/browser/devtools/webconsole/test/test-bug-869003-iframe.html"></iframe>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-console-extras.html b/browser/devtools/webconsole/test/test-console-extras.html
new file mode 100644
index 000000000..6e05a96eb
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-console-extras.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Console extended API test</title>
+ <script type="text/javascript">
+ function test() {
+ console.log("start");
+ console.exception()
+ console.assert()
+ console.clear()
+ console.dirxml()
+ console.profile()
+ console.profileEnd()
+ console.count()
+ console.table()
+ console.log("end");
+ }
+ </script>
+ </head>
+ <body>
+ <h1 id="header">Heads Up Display Demo</h1>
+ <button onclick="test();">Test Extended API</button>
+ <div id="myDiv"></div>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-console-replaced-api.html b/browser/devtools/webconsole/test/test-console-replaced-api.html
new file mode 100644
index 000000000..2b05d023a
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-console-replaced-api.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Console test replaced API</title>
+ </head>
+ <body>
+ <h1 id="header">Web Console Replace API Test</h1>
+ <script type="text/javascript">
+ window.console = {log: function (msg){}, info: function (msg){}, warn: function (msg){}, error: function (msg){}};
+ </script>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-console.html b/browser/devtools/webconsole/test/test-console.html
new file mode 100644
index 000000000..23126642a
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-console.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Console test</title>
+ <script type="text/javascript">
+ function test() {
+ var str = "Dolske Digs Bacon, Now and Forevermore."
+ for (var i=0; i < 5; i++) {
+ console.log(str);
+ }
+ }
+ console.info("INLINE SCRIPT:");
+ test();
+ console.warn("I'm warning you, he will eat up all yr bacon.");
+ console.error("Error Message");
+ </script>
+ </head>
+ <body>
+ <h1 id="header">Heads Up Display Demo</h1>
+ <button onclick="test();">Log stuff about Dolske</button>
+ <div id="myDiv"></div>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-data.json b/browser/devtools/webconsole/test/test-data.json
new file mode 100644
index 000000000..471d240b5
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-data.json
@@ -0,0 +1 @@
+{ id: "test JSON data", myArray: [ "foo", "bar", "baz", "biff" ] } \ No newline at end of file
diff --git a/browser/devtools/webconsole/test/test-data.json^headers^ b/browser/devtools/webconsole/test/test-data.json^headers^
new file mode 100644
index 000000000..7b5e82d4b
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-data.json^headers^
@@ -0,0 +1 @@
+Content-Type: application/json
diff --git a/browser/devtools/webconsole/test/test-duplicate-error.html b/browser/devtools/webconsole/test/test-duplicate-error.html
new file mode 100644
index 000000000..1b2691672
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-duplicate-error.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Console duplicate error test</title>
+ <!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+
+ See https://bugzilla.mozilla.org/show_bug.cgi?id=582201
+ -->
+ </head>
+ <body>
+ <h1>Heads Up Display - duplicate error test</h1>
+
+ <script type="text/javascript"><!--
+ fooDuplicateError1.bar();
+ // --></script>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-encoding-ISO-8859-1.html b/browser/devtools/webconsole/test/test-encoding-ISO-8859-1.html
new file mode 100644
index 000000000..cf19629f4
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-encoding-ISO-8859-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+</head>
+<body>üöä</body>
+</html> \ No newline at end of file
diff --git a/browser/devtools/webconsole/test/test-error.html b/browser/devtools/webconsole/test/test-error.html
new file mode 100644
index 000000000..abf62a3f1
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-error.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Console error test</title>
+ </head>
+ <body>
+ <h1>Heads Up Display - error test</h1>
+ <p><button>generate error</button></p>
+
+ <script type="text/javascript"><!--
+ var button = document.getElementsByTagName("button")[0];
+
+ button.addEventListener("click", function clicker () {
+ button.removeEventListener("click", clicker, false);
+ fooBazBaz.bar();
+ }, false);
+ // --></script>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-eval-in-stackframe.html b/browser/devtools/webconsole/test/test-eval-in-stackframe.html
new file mode 100644
index 000000000..ec1bf3f30
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-eval-in-stackframe.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html dir="ltr" lang="en">
+ <head>
+ <meta charset="utf8">
+ <!--
+ - Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ <title>Test for bug 783499 - use the debugger API in the web console</title>
+ <script>
+ var foo = "globalFooBug783499";
+ var fooObj = {
+ testProp: "testValue",
+ };
+
+ function firstCall()
+ {
+ var foo = "fooFirstCall";
+ var foo3 = "foo3FirstCall";
+ secondCall();
+ }
+
+ function secondCall()
+ {
+ var foo2 = "foo2SecondCall";
+ var fooObj = {
+ testProp2: "testValue2",
+ };
+ var fooObj2 = {
+ testProp22: "testValue22",
+ };
+ debugger;
+ }
+ </script>
+ </head>
+ <body>
+ <p>Hello world!</p>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-file-location.js b/browser/devtools/webconsole/test/test-file-location.js
new file mode 100644
index 000000000..f97ce5725
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-file-location.js
@@ -0,0 +1,9 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+console.log("message for level log");
+console.info("message for level info");
+console.warn("message for level warn");
+console.error("message for level error");
+console.debug("message for level debug");
diff --git a/browser/devtools/webconsole/test/test-filter.html b/browser/devtools/webconsole/test/test-filter.html
new file mode 100644
index 000000000..219177bb2
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-filter.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Console test</title>
+ <script type="text/javascript">
+ </script>
+ </head>
+ <body>
+ <h1>Heads Up Display Filter Test Page</h1>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-for-of.html b/browser/devtools/webconsole/test/test-for-of.html
new file mode 100644
index 000000000..876010c9e
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-for-of.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<meta charset="utf-8">
+<body>
+<h1>a</h1>
+<div><p>b</p></div>
+<h2>c</h2>
+<p>d</p>
diff --git a/browser/devtools/webconsole/test/test-image.png b/browser/devtools/webconsole/test/test-image.png
new file mode 100644
index 000000000..769c63634
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-image.png
Binary files differ
diff --git a/browser/devtools/webconsole/test/test-mutation.html b/browser/devtools/webconsole/test/test-mutation.html
new file mode 100644
index 000000000..e80933b06
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-mutation.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Console mutation test</title>
+ <script>
+ window.onload = function (){
+ var node = document.createElement("div");
+ document.body.appendChild(node);
+ };
+ </script>
+ </head>
+ <body>
+ <h1>Heads Up Display DOM Mutation Test Page</h1>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-network-request.html b/browser/devtools/webconsole/test/test-network-request.html
new file mode 100644
index 000000000..3cb699865
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-network-request.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Console HTTP test page</title>
+ <script type="text/javascript"><!--
+ function makeXhr(aMethod, aUrl, aRequestBody, aCallback) {
+ var xmlhttp = new XMLHttpRequest();
+ xmlhttp.open(aMethod, aUrl, true);
+ xmlhttp.onreadystatechange = function() {
+ if (aCallback && xmlhttp.readyState == 4) {
+ aCallback();
+ }
+ };
+ xmlhttp.send(aRequestBody);
+ }
+
+ function testXhrGet(aCallback) {
+ makeXhr('get', 'test-data.json', null, aCallback);
+ }
+
+ function testXhrPost(aCallback) {
+ makeXhr('post', 'test-data.json', "Hello world!", aCallback);
+ }
+ // --></script>
+ </head>
+ <body>
+ <h1>Heads Up Display HTTP Logging Testpage</h1>
+ <h2>This page is used to test the HTTP logging.</h2>
+
+ <form action="http://example.com/browser/browser/devtools/webconsole/test/test-network-request.html" method="post">
+ <input name="name" type="text" value="foo bar"><br>
+ <input name="age" type="text" value="144"><br>
+ </form>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-network.html b/browser/devtools/webconsole/test/test-network.html
new file mode 100644
index 000000000..9c591479e
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-network.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Console network test</title>
+ <script src="testscript.js"></script>
+ </head>
+ <body>
+ <h1>Heads Up Display Network Test Page</h1>
+ <img src="test-image.png"></img>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-observe-http-ajax.html b/browser/devtools/webconsole/test/test-observe-http-ajax.html
new file mode 100644
index 000000000..5abcefdad
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-observe-http-ajax.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Console HTTP test page</title>
+ <script type="text/javascript">
+ function test() {
+ var xmlhttp = new XMLHttpRequest();
+ xmlhttp.open('get', 'test-data.json', false);
+ xmlhttp.send(null);
+ }
+ </script>
+ </head>
+ <body onload="test();">
+ <h1>Heads Up Display HTTP & AJAX Test Page</h1>
+ <h2>This page fires an ajax request so we can see the http logging of the console</h2>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-own-console.html b/browser/devtools/webconsole/test/test-own-console.html
new file mode 100644
index 000000000..d1d18ebc2
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-own-console.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+<head>
+<meta charset="utf-8">
+<script>
+ var _console = {
+ foo: "bar"
+ }
+
+ window.console = _console;
+
+ function loadIFrame() {
+ var iframe = document.body.querySelector("iframe");
+ iframe.addEventListener("load", function() {
+ iframe.removeEventListener("load", arguments.callee, true);
+ }, true);
+
+ iframe.setAttribute("src", "test-console.html");
+ }
+</script>
+</head>
+<body>
+ <iframe></iframe>
+</body>
diff --git a/browser/devtools/webconsole/test/test-property-provider.html b/browser/devtools/webconsole/test/test-property-provider.html
new file mode 100644
index 000000000..532b00f44
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-property-provider.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <meta charset="utf-8">
+ <title>Property provider test</title>
+ <script>
+ var testObj = {
+ testProp: 'testValue'
+ };
+ </script>
+ </head>
+ <body>
+ <h1>Heads Up Property Provider Test Page</h1>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-repeated-messages.html b/browser/devtools/webconsole/test/test-repeated-messages.html
new file mode 100644
index 000000000..5bbc8fd5a
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-repeated-messages.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf8">
+ <title>Test for bugs 720180, 800510 and 865288</title>
+ <script>
+ function testConsole() {
+ console.log("foo repeat"); console.log("foo repeat");
+ console.log("foo repeat"); console.error("foo repeat");
+ }
+ function testConsoleObjects() {
+ for (var i = 0; i < 3; i++) {
+ var o = { id: "abba" + i };
+ console.log("abba", o);
+ }
+ }
+ </script>
+ <style>
+ body {
+ background-image: foobarz;
+ }
+ p {
+ background-image: foobarz;
+ }
+ </style>
+ <!--
+ - Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ </head>
+ <body>
+ <p>Hello world!</p>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test-result-format-as-string.html b/browser/devtools/webconsole/test/test-result-format-as-string.html
new file mode 100644
index 000000000..73b7b8be5
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-result-format-as-string.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Web Console test: jsterm eval format as a string</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ </head>
+ <body>
+ <p>Make sure js eval results are formatted as strings.</p>
+ <script>
+ document.querySelector("p").toSource = function() {
+ var element = document.createElement("div");
+ element.textContent = "bug772506_content";
+ element.setAttribute("onmousemove",
+ "(function () {" +
+ " gBrowser._bug772506 = 'foobar';" +
+ "})();"
+ );
+ return element;
+ };
+ </script>
+ </body>
+</html>
diff --git a/browser/devtools/webconsole/test/test-webconsole-error-observer.html b/browser/devtools/webconsole/test/test-webconsole-error-observer.html
new file mode 100644
index 000000000..8466bc6f2
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-webconsole-error-observer.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>WebConsoleErrorObserver test - bug 611032</title>
+ <!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+ <script type="text/javascript">
+ console.log("log Bazzle");
+ console.info("info Bazzle");
+ console.warn("warn Bazzle");
+ console.error("error Bazzle");
+
+ var foo = {};
+ foo.bazBug611032();
+ </script>
+ <style type="text/css">
+ .foo { color: cssColorBug611032; }
+ </style>
+ </head>
+ <body>
+ <h1>WebConsoleErrorObserver test</h1>
+ </body>
+</html>
+
diff --git a/browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html b/browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html
new file mode 100644
index 000000000..eb0c52c3a
--- /dev/null
+++ b/browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 770099 - bad policy-uri</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=770099">Mozilla Bug 770099</a>
+</body>
+</html>
diff --git a/browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html^headers^ b/browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html^headers^
new file mode 100644
index 000000000..b64692028
--- /dev/null
+++ b/browser/devtools/webconsole/test/test_bug_770099_bad_policy_uri.html^headers^
@@ -0,0 +1,2 @@
+X-Content-Security-Policy: policy-uri http://example.com/some_policy
+Content-type: text/html; charset=utf-8
diff --git a/browser/devtools/webconsole/test/test_bug_770099_violation.html b/browser/devtools/webconsole/test/test_bug_770099_violation.html
new file mode 100644
index 000000000..ccbded87a
--- /dev/null
+++ b/browser/devtools/webconsole/test/test_bug_770099_violation.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 770099 - policy violation</title>
+<!-- Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ -->
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=770099">Mozilla Bug 770099</a>
+<img src="http://some.example.com/test.png">
+</body>
+</html>
diff --git a/browser/devtools/webconsole/test/test_bug_770099_violation.html^headers^ b/browser/devtools/webconsole/test/test_bug_770099_violation.html^headers^
new file mode 100644
index 000000000..5374efd3e
--- /dev/null
+++ b/browser/devtools/webconsole/test/test_bug_770099_violation.html^headers^
@@ -0,0 +1 @@
+X-Content-Security-Policy: default-src 'self'
diff --git a/browser/devtools/webconsole/test/testscript.js b/browser/devtools/webconsole/test/testscript.js
new file mode 100644
index 000000000..c69919df4
--- /dev/null
+++ b/browser/devtools/webconsole/test/testscript.js
@@ -0,0 +1 @@
+console.log("running network console logging tests");