diff options
Diffstat (limited to 'browser/devtools/webconsole/test')
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 Binary files differnew file mode 100644 index 000000000..947e5f11b --- /dev/null +++ b/browser/devtools/webconsole/test/test-bug-595934-image.jpg 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 Binary files differnew file mode 100644 index 000000000..769c63634 --- /dev/null +++ b/browser/devtools/webconsole/test/test-image.png 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"); |