diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2014-05-21 11:38:25 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2014-05-21 11:38:25 +0200 |
commit | d25ba7d760b017b038e5aa6c0a605b4a330eb68d (patch) | |
tree | 16ec27edc7d5f83986f16236d3a36a2682a0f37e /browser/devtools/netmonitor/test | |
parent | a942906574671868daf122284a9c4689e6924f74 (diff) | |
download | palemoon-gre-d25ba7d760b017b038e5aa6c0a605b4a330eb68d.tar.gz |
Recommit working copy to repo with proper line endings.
Diffstat (limited to 'browser/devtools/netmonitor/test')
54 files changed, 5026 insertions, 0 deletions
diff --git a/browser/devtools/netmonitor/test/Makefile.in b/browser/devtools/netmonitor/test/Makefile.in new file mode 100644 index 000000000..7ec624bac --- /dev/null +++ b/browser/devtools/netmonitor/test/Makefile.in @@ -0,0 +1,73 @@ +# 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_TESTS = \ + browser_net_aaa_leaktest.js \ + browser_net_autoscroll.js \ + browser_net_simple-init.js \ + browser_net_page-nav.js \ + browser_net_prefs-and-l10n.js \ + browser_net_prefs-reload.js \ + browser_net_pane-collapse.js \ + browser_net_pane-toggle.js \ + browser_net_simple-request.js \ + browser_net_simple-request-data.js \ + browser_net_simple-request-details.js \ + browser_net_content-type.js \ + browser_net_cyrillic-01.js \ + browser_net_cyrillic-02.js \ + browser_net_large-response.js \ + browser_net_status-codes.js \ + browser_net_post-data-01.js \ + browser_net_post-data-02.js \ + browser_net_jsonp.js \ + browser_net_json-long.js \ + browser_net_json-malformed.js \ + browser_net_timeline_ticks.js \ + browser_net_sort-01.js \ + browser_net_sort-02.js \ + browser_net_sort-03.js \ + browser_net_filter-01.js \ + browser_net_filter-02.js \ + browser_net_filter-03.js \ + browser_net_accessibility-01.js \ + browser_net_accessibility-02.js \ + browser_net_footer-summary.js \ + browser_net_req-resp-bodies.js \ + head.js \ + $(NULL) + +MOCHITEST_BROWSER_PAGES = \ + test-image.png \ + html_simple-test-page.html \ + html_navigate-test-page.html \ + html_content-type-test-page.html \ + html_cyrillic-test-page.html \ + html_status-codes-test-page.html \ + html_post-data-test-page.html \ + html_post-raw-test-page.html \ + html_jsonp-test-page.html \ + html_json-long-test-page.html \ + html_json-malformed-test-page.html \ + html_sorting-test-page.html \ + html_filter-test-page.html \ + html_infinite-get-page.html \ + html_custom-get-page.html \ + sjs_simple-test-server.sjs \ + sjs_content-type-test-server.sjs \ + sjs_status-codes-test-server.sjs \ + sjs_sorting-test-server.sjs \ + $(NULL) + +MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES + +include $(topsrcdir)/config/rules.mk diff --git a/browser/devtools/netmonitor/test/browser_net_aaa_leaktest.js b/browser/devtools/netmonitor/test/browser_net_aaa_leaktest.js new file mode 100644 index 000000000..a9cd6fea7 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_aaa_leaktest.js @@ -0,0 +1,28 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if the network monitor leaks on initialization and sudden destruction. + * You can also use this initialization format as a template for other tests. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, NetMonitorView, NetMonitorController } = aMonitor.panelWin; + let { RequestsMenu, NetworkDetails } = NetMonitorView; + + ok(aTab, "Should have a tab available."); + ok(aDebuggee, "Should have a debuggee available."); + ok(aMonitor, "Should have a network monitor pane available."); + + ok(document, "Should have a document available."); + ok(NetMonitorView, "Should have a NetMonitorView object available."); + ok(NetMonitorController, "Should have a NetMonitorController object available."); + ok(RequestsMenu, "Should have a RequestsMenu object available."); + ok(NetworkDetails, "Should have a NetworkDetails object available."); + + teardown(aMonitor).then(finish); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_accessibility-01.js b/browser/devtools/netmonitor/test/browser_net_accessibility-01.js new file mode 100644 index 000000000..7c9f54391 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_accessibility-01.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if focus modifiers work for the SideMenuWidget. + */ + +function test() { + initNetMonitor(CUSTOM_GET_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 2).then(() => { + check(-1, false); + + RequestsMenu.focusLastVisibleItem(); + check(1, true); + RequestsMenu.focusFirstVisibleItem(); + check(0, true); + + RequestsMenu.focusNextItem(); + check(1, true); + RequestsMenu.focusPrevItem(); + check(0, true); + + RequestsMenu.focusItemAtDelta(+1); + check(1, true); + RequestsMenu.focusItemAtDelta(-1); + check(0, true); + + RequestsMenu.focusItemAtDelta(+10); + check(1, true); + RequestsMenu.focusItemAtDelta(-10); + check(0, true); + + aDebuggee.performRequests(18); + return waitForNetworkEvents(aMonitor, 18); + }) + .then(() => { + RequestsMenu.focusLastVisibleItem(); + check(19, true); + RequestsMenu.focusFirstVisibleItem(); + check(0, true); + + RequestsMenu.focusNextItem(); + check(1, true); + RequestsMenu.focusPrevItem(); + check(0, true); + + RequestsMenu.focusItemAtDelta(+10); + check(10, true); + RequestsMenu.focusItemAtDelta(-10); + check(0, true); + + RequestsMenu.focusItemAtDelta(+100); + check(19, true); + RequestsMenu.focusItemAtDelta(-100); + check(0, true); + + teardown(aMonitor).then(finish); + }); + + let count = 0; + + function check(aSelectedIndex, aPaneVisibility) { + info("Performing check " + (count++) + "."); + + is(RequestsMenu.selectedIndex, aSelectedIndex, + "The selected item in the requests menu was incorrect."); + is(NetMonitorView.detailsPaneHidden, !aPaneVisibility, + "The network requests details pane visibility state was incorrect."); + } + + aDebuggee.performRequests(2); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_accessibility-02.js b/browser/devtools/netmonitor/test/browser_net_accessibility-02.js new file mode 100644 index 000000000..aac9162e1 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_accessibility-02.js @@ -0,0 +1,123 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if keyboard and mouse navigation works in the network requests menu. + */ + +function test() { + initNetMonitor(CUSTOM_GET_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { window, $, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 2).then(() => { + check(-1, false); + + EventUtils.sendKey("DOWN", window); + check(0, true); + EventUtils.sendKey("UP", window); + check(0, true); + + EventUtils.sendKey("PAGE_DOWN", window); + check(1, true); + EventUtils.sendKey("PAGE_UP", window); + check(0, true); + + EventUtils.sendKey("END", window); + check(1, true); + EventUtils.sendKey("HOME", window); + check(0, true); + + aDebuggee.performRequests(18); + return waitForNetworkEvents(aMonitor, 18); + }) + .then(() => { + EventUtils.sendKey("DOWN", window); + check(1, true); + EventUtils.sendKey("DOWN", window); + check(2, true); + EventUtils.sendKey("UP", window); + check(1, true); + EventUtils.sendKey("UP", window); + check(0, true); + + EventUtils.sendKey("PAGE_DOWN", window); + check(4, true); + EventUtils.sendKey("PAGE_DOWN", window); + check(8, true); + EventUtils.sendKey("PAGE_UP", window); + check(4, true); + EventUtils.sendKey("PAGE_UP", window); + check(0, true); + + EventUtils.sendKey("HOME", window); + check(0, true); + EventUtils.sendKey("HOME", window); + check(0, true); + EventUtils.sendKey("PAGE_UP", window); + check(0, true); + EventUtils.sendKey("HOME", window); + check(0, true); + + EventUtils.sendKey("END", window); + check(19, true); + EventUtils.sendKey("END", window); + check(19, true); + EventUtils.sendKey("PAGE_DOWN", window); + check(19, true); + EventUtils.sendKey("END", window); + check(19, true); + + EventUtils.sendKey("PAGE_UP", window); + check(15, true); + EventUtils.sendKey("PAGE_UP", window); + check(11, true); + EventUtils.sendKey("UP", window); + check(10, true); + EventUtils.sendKey("UP", window); + check(9, true); + EventUtils.sendKey("PAGE_DOWN", window); + check(13, true); + EventUtils.sendKey("PAGE_DOWN", window); + check(17, true); + EventUtils.sendKey("PAGE_DOWN", window); + check(19, true); + EventUtils.sendKey("PAGE_DOWN", window); + check(19, true); + + EventUtils.sendKey("HOME", window); + check(0, true); + EventUtils.sendKey("DOWN", window); + check(1, true); + EventUtils.sendKey("END", window); + check(19, true); + EventUtils.sendKey("DOWN", window); + check(19, true); + + EventUtils.sendMouseEvent({ type: "mousedown" }, $("#details-pane-toggle")); + check(-1, false); + + EventUtils.sendMouseEvent({ type: "mousedown" }, $(".side-menu-widget-item")); + check(0, true); + + teardown(aMonitor).then(finish); + }); + + let count = 0; + + function check(aSelectedIndex, aPaneVisibility) { + info("Performing check " + (count++) + "."); + + is(RequestsMenu.selectedIndex, aSelectedIndex, + "The selected item in the requests menu was incorrect."); + is(NetMonitorView.detailsPaneHidden, !aPaneVisibility, + "The network requests details pane visibility state was incorrect."); + } + + aDebuggee.performRequests(2); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_autoscroll.js b/browser/devtools/netmonitor/test/browser_net_autoscroll.js new file mode 100644 index 000000000..64f60badf --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_autoscroll.js @@ -0,0 +1,89 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Bug 863102 - Automatically scroll down upon new network requests. + */ + +function test() { + let monitor, debuggee, requestsContainer, scrollTop; + + initNetMonitor(INFINITE_GET_URL).then(([aTab, aDebuggee, aMonitor]) => { + monitor = aMonitor; + debuggee = aDebuggee; + let win = monitor.panelWin; + let topNode = win.document.getElementById("requests-menu-contents"); + requestsContainer = topNode.getElementsByTagName("scrollbox")[0]; + ok(!!requestsContainer, "Container element exists as expected."); + }) + + // (1) Check that the scroll position is maintained at the bottom + // when the requests overflow the vertical size of the container. + .then(() => { + return waitForRequestsToOverflowContainer(monitor, requestsContainer); + }) + .then(() => { + ok(scrolledToBottom(requestsContainer), "Scrolled to bottom on overflow."); + }) + + // (2) Now set the scroll position somewhere in the middle and check + // that additional requests do not change the scroll position. + .then(() => { + let children = requestsContainer.childNodes; + let middleNode = children.item(children.length / 2); + middleNode.scrollIntoView(); + ok(!scrolledToBottom(requestsContainer), "Not scrolled to bottom."); + scrollTop = requestsContainer.scrollTop; // save for comparison later + return waitForNetworkEvents(monitor, 8); + }) + .then(() => { + is(requestsContainer.scrollTop, scrollTop, "Did not scroll."); + }) + + // (3) Now set the scroll position back at the bottom and check that + // additional requests *do* cause the container to scroll down. + .then(() => { + requestsContainer.scrollTop = requestsContainer.scrollHeight; + ok(scrolledToBottom(requestsContainer), "Set scroll position to bottom."); + return waitForNetworkEvents(monitor, 8); + }) + .then(() => { + ok(scrolledToBottom(requestsContainer), "Still scrolled to bottom."); + }) + + // (4) Now select an item in the list and check that additional requests + // do not change the scroll position. + .then(() => { + monitor.panelWin.NetMonitorView.RequestsMenu.selectedIndex = 0; + return waitForNetworkEvents(monitor, 8); + }) + .then(() => { + is(requestsContainer.scrollTop, 0, "Did not scroll."); + }) + + // Done; clean up. + .then(() => { + return teardown(monitor).then(finish); + }) + + // Handle exceptions in the chain of promises. + .then(null, (err) => { + ok(false, err); + finish(); + }); + + function waitForRequestsToOverflowContainer (aMonitor, aContainer) { + return waitForNetworkEvents(aMonitor, 1).then(() => { + if (aContainer.scrollHeight > aContainer.clientHeight) { + // Wait for some more just for good measure. + return waitForNetworkEvents(aMonitor, 8); + } else { + return waitForRequestsToOverflowContainer(aMonitor, aContainer); + } + }); + } + + function scrolledToBottom(aElement) { + return aElement.scrollTop + aElement.clientHeight >= aElement.scrollHeight; + } +} diff --git a/browser/devtools/netmonitor/test/browser_net_content-type.js b/browser/devtools/netmonitor/test/browser_net_content-type.js new file mode 100644 index 000000000..3c7ed2d62 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_content-type.js @@ -0,0 +1,228 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if different response content types are handled correctly. + */ + +function test() { + initNetMonitor(CONTENT_TYPE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 6).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CONTENT_TYPE_SJS + "?fmt=xml", { + status: 200, + statusText: "OK", + type: "xml", + fullMimeType: "text/xml; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1), + "GET", CONTENT_TYPE_SJS + "?fmt=css", { + status: 200, + statusText: "OK", + type: "css", + fullMimeType: "text/css; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(2), + "GET", CONTENT_TYPE_SJS + "?fmt=js", { + status: 200, + statusText: "OK", + type: "js", + fullMimeType: "application/javascript; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3), + "GET", CONTENT_TYPE_SJS + "?fmt=json", { + status: 200, + statusText: "OK", + type: "json", + fullMimeType: "application/json; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4), + "GET", CONTENT_TYPE_SJS + "?fmt=bogus", { + status: 404, + statusText: "Not Found", + type: "html", + fullMimeType: "text/html; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5), + "GET", TEST_IMAGE, { + status: 200, + statusText: "OK", + type: "png", + fullMimeType: "image/png", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.75), + time: true + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + + testResponseTab("xml") + .then(() => { + RequestsMenu.selectedIndex = 1; + return testResponseTab("css"); + }) + .then(() => { + RequestsMenu.selectedIndex = 2; + return testResponseTab("js"); + }) + .then(() => { + RequestsMenu.selectedIndex = 3; + return testResponseTab("json"); + }) + .then(() => { + RequestsMenu.selectedIndex = 4; + return testResponseTab("html"); + }) + .then(() => { + RequestsMenu.selectedIndex = 5; + return testResponseTab("png"); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + + function testResponseTab(aType) { + let tab = document.querySelectorAll("#details-pane tab")[3]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3]; + + is(tab.getAttribute("selected"), "true", + "The response tab in the network details pane should be selected."); + + function checkVisibility(aBox) { + is(tabpanel.querySelector("#response-content-info-header") + .hasAttribute("hidden"), true, + "The response info header doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-json-box") + .hasAttribute("hidden"), aBox != "json", + "The response content json box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-textarea-box") + .hasAttribute("hidden"), aBox != "textarea", + "The response content textarea box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-image-box") + .hasAttribute("hidden"), aBox != "image", + "The response content image box doesn't have the intended visibility."); + } + + switch (aType) { + case "xml": { + checkVisibility("textarea"); + + return NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText(), "<label value='greeting'>Hello XML!</label>", + "The text shown in the source editor is incorrect for the xml request."); + is(aEditor.getMode(), SourceEditor.MODES.HTML, + "The mode active in the source editor is incorrect for the xml request."); + }); + } + case "css": { + checkVisibility("textarea"); + + return NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText(), "body:pre { content: 'Hello CSS!' }", + "The text shown in the source editor is incorrect for the xml request."); + is(aEditor.getMode(), SourceEditor.MODES.CSS, + "The mode active in the source editor is incorrect for the xml request."); + }); + } + case "js": { + checkVisibility("textarea"); + + return NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText(), "function() { return 'Hello JS!'; }", + "The text shown in the source editor is incorrect for the xml request."); + is(aEditor.getMode(), SourceEditor.MODES.JAVASCRIPT, + "The mode active in the source editor is incorrect for the xml request."); + }); + } + case "json": { + checkVisibility("json"); + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 1, + "There should be 1 json scope displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-property").length, 2, + "There should be 2 json properties displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0, + "The empty notice should not be displayed in this tabpanel."); + + let jsonScope = tabpanel.querySelectorAll(".variables-view-scope")[0]; + + is(jsonScope.querySelector(".name").getAttribute("value"), + L10N.getStr("jsonScopeName"), + "The json scope doesn't have the correct title."); + + is(jsonScope.querySelectorAll(".variables-view-property .name")[0].getAttribute("value"), + "greeting", "The first json property name was incorrect."); + is(jsonScope.querySelectorAll(".variables-view-property .value")[0].getAttribute("value"), + "\"Hello JSON!\"", "The first json property value was incorrect."); + + is(jsonScope.querySelectorAll(".variables-view-property .name")[1].getAttribute("value"), + "__proto__", "The second json property name was incorrect."); + is(jsonScope.querySelectorAll(".variables-view-property .value")[1].getAttribute("value"), + "[object Object]", "The second json property value was incorrect."); + + return Promise.resolve(); + } + case "html": { + checkVisibility("textarea"); + + return NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText(), "<blink>Not Found</blink>", + "The text shown in the source editor is incorrect for the xml request."); + is(aEditor.getMode(), SourceEditor.MODES.HTML, + "The mode active in the source editor is incorrect for the xml request."); + }); + } + case "png": { + checkVisibility("image"); + + let imageNode = tabpanel.querySelector("#response-content-image"); + let deferred = Promise.defer(); + + imageNode.addEventListener("load", function onLoad() { + imageNode.removeEventListener("load", onLoad); + + is(tabpanel.querySelector("#response-content-image-name-value") + .getAttribute("value"), "test-image.png", + "The image name info isn't correct."); + is(tabpanel.querySelector("#response-content-image-mime-value") + .getAttribute("value"), "image/png", + "The image mime info isn't correct."); + is(tabpanel.querySelector("#response-content-image-encoding-value") + .getAttribute("value"), "base64", + "The image encoding info isn't correct."); + is(tabpanel.querySelector("#response-content-image-dimensions-value") + .getAttribute("value"), "16 x 16", + "The image dimensions info isn't correct."); + + deferred.resolve(); + }); + + return deferred.promise; + } + } + } + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_cyrillic-01.js b/browser/devtools/netmonitor/test/browser_net_cyrillic-01.js new file mode 100644 index 000000000..f9da54b31 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_cyrillic-01.js @@ -0,0 +1,41 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if cyrillic text is rendered correctly in the source editor. + */ + +function test() { + initNetMonitor(CYRILLIC_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CONTENT_TYPE_SJS + "?fmt=txt", { + status: 200, + statusText: "DA DA DA" + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + + NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText().indexOf("\u044F"), 26, // я + "The text shown in the source editor is incorrect."); + is(aEditor.getMode(), SourceEditor.MODES.TEXT, + "The mode active in the source editor is incorrect."); + + teardown(aMonitor).then(finish); + }); + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_cyrillic-02.js b/browser/devtools/netmonitor/test/browser_net_cyrillic-02.js new file mode 100644 index 000000000..d47d8e4af --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_cyrillic-02.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if cyrillic text is rendered correctly in the source editor + * when loaded directly from an HTML page. + */ + +function test() { + initNetMonitor(CYRILLIC_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CYRILLIC_URL, { + status: 200, + statusText: "OK" + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + + NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText().indexOf("\u044F"), 189, // я + "The text shown in the source editor is incorrect."); + is(aEditor.getMode(), SourceEditor.MODES.HTML, + "The mode active in the source editor is incorrect."); + + teardown(aMonitor).then(finish); + }); + }); + + aDebuggee.location.reload(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_filter-01.js b/browser/devtools/netmonitor/test/browser_net_filter-01.js new file mode 100644 index 000000000..c6d36e57f --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_filter-01.js @@ -0,0 +1,184 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if filtering items in the network table works correctly. + */ + +function test() { + initNetMonitor(FILTERING_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { $, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 8).then(() => { + EventUtils.sendMouseEvent({ type: "mousedown" }, $("#details-pane-toggle")); + + isnot(RequestsMenu.selectedItem, null, + "There should be a selected item in the requests menu."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be selected in the requests menu."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should not be hidden after toggle button was pressed."); + + testButtons("all"); + testContents([1, 1, 1, 1, 1, 1, 1, 1]) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-html-button")); + testButtons("html"); + return testContents([1, 0, 0, 0, 0, 0, 0, 0]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-css-button")); + testButtons("css"); + return testContents([0, 1, 0, 0, 0, 0, 0, 0]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-js-button")); + testButtons("js"); + return testContents([0, 0, 1, 0, 0, 0, 0, 0]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-xhr-button")); + testButtons("xhr"); + return testContents([1, 1, 1, 1, 1, 1, 1, 1]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-fonts-button")); + testButtons("fonts"); + return testContents([0, 0, 0, 1, 0, 0, 0, 0]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-images-button")); + testButtons("images"); + return testContents([0, 0, 0, 0, 1, 0, 0, 0]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-media-button")); + testButtons("media"); + return testContents([0, 0, 0, 0, 0, 1, 1, 0]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-flash-button")); + testButtons("flash"); + return testContents([0, 0, 0, 0, 0, 0, 0, 1]); + }) + .then(() => { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-all-button")); + testButtons("all"); + return testContents([1, 1, 1, 1, 1, 1, 1, 1]); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + }); + + function testButtons(aFilterType) { + let doc = aMonitor.panelWin.document; + let target = doc.querySelector("#requests-menu-filter-" + aFilterType + "-button"); + let buttons = doc.querySelectorAll(".requests-menu-footer-button"); + + for (let button of buttons) { + if (button != target) { + is(button.hasAttribute("checked"), false, + "The " + button.id + " button should not have a 'checked' attribute."); + } else { + is(button.hasAttribute("checked"), true, + "The " + button.id + " button should have a 'checked' attribute."); + } + } + } + + function testContents(aVisibility) { + isnot(RequestsMenu.selectedItem, null, + "There should still be a selected item after filtering."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be still selected after filtering."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should still be visible after filtering."); + + is(RequestsMenu.orderedItems.length, aVisibility.length, + "There should be a specific amount of items in the requests menu."); + is(RequestsMenu.visibleItems.length, aVisibility.filter(e => e).length, + "There should be a specific amount of visbile items in the requests menu."); + + for (let i = 0; i < aVisibility.length; i++) { + is(RequestsMenu.getItemAtIndex(i).target.hidden, !aVisibility[i], + "The item at index " + i + " doesn't have the correct hidden state."); + } + + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CONTENT_TYPE_SJS + "?fmt=html", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "html", + fullMimeType: "text/html; charset=utf-8" + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1), + "GET", CONTENT_TYPE_SJS + "?fmt=css", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "css", + fullMimeType: "text/css; charset=utf-8" + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(2), + "GET", CONTENT_TYPE_SJS + "?fmt=js", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "js", + fullMimeType: "application/javascript; charset=utf-8" + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3), + "GET", CONTENT_TYPE_SJS + "?fmt=font", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "woff", + fullMimeType: "font/woff" + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4), + "GET", CONTENT_TYPE_SJS + "?fmt=image", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "png", + fullMimeType: "image/png" + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5), + "GET", CONTENT_TYPE_SJS + "?fmt=audio", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "ogg", + fullMimeType: "audio/ogg" + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(6), + "GET", CONTENT_TYPE_SJS + "?fmt=video", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "webm", + fullMimeType: "video/webm" + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(7), + "GET", CONTENT_TYPE_SJS + "?fmt=flash", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "x-shockwave-flash", + fullMimeType: "application/x-shockwave-flash" + }); + + return Promise.resolve(null); + } + + aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }'); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_filter-02.js b/browser/devtools/netmonitor/test/browser_net_filter-02.js new file mode 100644 index 000000000..5b8c6457a --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_filter-02.js @@ -0,0 +1,181 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if filtering items in the network table works correctly with new requests. + */ + +function test() { + initNetMonitor(FILTERING_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { $, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 8).then(() => { + EventUtils.sendMouseEvent({ type: "mousedown" }, $("#details-pane-toggle")); + + isnot(RequestsMenu.selectedItem, null, + "There should be a selected item in the requests menu."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be selected in the requests menu."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should not be hidden after toggle button was pressed."); + + testButtons("all"); + testContents([1, 1, 1, 1, 1, 1, 1, 1]) + .then(() => { + info("Testing html filtering."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-html-button")); + testButtons("html"); + return testContents([1, 0, 0, 0, 0, 0, 0, 0]); + }) + .then(() => { + info("Performing more requests."); + aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }'); + return waitForNetworkEvents(aMonitor, 8); + }) + .then(() => { + info("Testing html filtering again."); + testButtons("html"); + return testContents([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]); + }) + .then(() => { + info("Performing more requests."); + aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }'); + return waitForNetworkEvents(aMonitor, 8); + }) + .then(() => { + info("Testing html filtering again."); + testButtons("html"); + return testContents([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + }); + + function testButtons(aFilterType) { + let doc = aMonitor.panelWin.document; + let target = doc.querySelector("#requests-menu-filter-" + aFilterType + "-button"); + let buttons = doc.querySelectorAll(".requests-menu-footer-button"); + + for (let button of buttons) { + if (button != target) { + is(button.hasAttribute("checked"), false, + "The " + button.id + " button should not have a 'checked' attribute."); + } else { + is(button.hasAttribute("checked"), true, + "The " + button.id + " button should have a 'checked' attribute."); + } + } + } + + function testContents(aVisibility) { + isnot(RequestsMenu.selectedItem, null, + "There should still be a selected item after filtering."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be still selected after filtering."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should still be visible after filtering."); + + is(RequestsMenu.orderedItems.length, aVisibility.length, + "There should be a specific amount of items in the requests menu."); + is(RequestsMenu.visibleItems.length, aVisibility.filter(e => e).length, + "There should be a specific amount of visbile items in the requests menu."); + + for (let i = 0; i < aVisibility.length; i++) { + is(RequestsMenu.getItemAtIndex(i).target.hidden, !aVisibility[i], + "The item at index " + i + " doesn't have the correct hidden state."); + } + + for (let i = 0; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=html", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "html", + fullMimeType: "text/html; charset=utf-8" + }); + } + for (let i = 1; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=css", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "css", + fullMimeType: "text/css; charset=utf-8" + }); + } + for (let i = 2; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=js", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "js", + fullMimeType: "application/javascript; charset=utf-8" + }); + } + for (let i = 3; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=font", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "woff", + fullMimeType: "font/woff" + }); + } + for (let i = 4; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=image", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "png", + fullMimeType: "image/png" + }); + } + for (let i = 5; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=audio", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "ogg", + fullMimeType: "audio/ogg" + }); + } + for (let i = 6; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=video", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "webm", + fullMimeType: "video/webm" + }); + } + for (let i = 7; i < aVisibility.length; i += 8) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), + "GET", CONTENT_TYPE_SJS + "?fmt=flash", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "x-shockwave-flash", + fullMimeType: "application/x-shockwave-flash" + }); + } + + return Promise.resolve(null); + } + + aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }'); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_filter-03.js b/browser/devtools/netmonitor/test/browser_net_filter-03.js new file mode 100644 index 000000000..e874a02ad --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_filter-03.js @@ -0,0 +1,186 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if filtering items in the network table works correctly with new requests + * and while sorting is enabled. + */ + +function test() { + initNetMonitor(FILTERING_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { $, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 7).then(() => { + EventUtils.sendMouseEvent({ type: "mousedown" }, $("#details-pane-toggle")); + + isnot(RequestsMenu.selectedItem, null, + "There should be a selected item in the requests menu."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be selected in the requests menu."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should not be hidden after toggle button was pressed."); + + testButtons("all"); + testContents([0, 1, 2, 3, 4, 5, 6], 7, 0) + .then(() => { + info("Sorting by size, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-size-button")); + testButtons("all"); + return testContents([6, 4, 5, 0, 1, 2, 3], 7, 6); + }) + .then(() => { + info("Testing html filtering."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-html-button")); + testButtons("html"); + return testContents([6, 4, 5, 0, 1, 2, 3], 1, 6); + }) + .then(() => { + info("Performing more requests."); + aDebuggee.performRequests('{ "getMedia": true }'); + return waitForNetworkEvents(aMonitor, 7); + }) + .then(() => { + info("Testing html filtering again."); + resetSorting(); + testButtons("html"); + return testContents([8, 13, 9, 11, 10, 12, 0, 4, 1, 5, 2, 6, 3, 7], 2, 13); + }) + .then(() => { + info("Performing more requests."); + aDebuggee.performRequests('{ "getMedia": true }'); + return waitForNetworkEvents(aMonitor, 7); + }) + .then(() => { + info("Testing html filtering again."); + resetSorting(); + testButtons("html"); + return testContents([12, 13, 20, 14, 16, 18, 15, 17, 19, 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11], 3, 20); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + }); + + function resetSorting() { + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-waterfall-button")); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-size-button")); + } + + function testButtons(aFilterType) { + let doc = aMonitor.panelWin.document; + let target = doc.querySelector("#requests-menu-filter-" + aFilterType + "-button"); + let buttons = doc.querySelectorAll(".requests-menu-footer-button"); + + for (let button of buttons) { + if (button != target) { + is(button.hasAttribute("checked"), false, + "The " + button.id + " button should not have a 'checked' attribute."); + } else { + is(button.hasAttribute("checked"), true, + "The " + button.id + " button should have a 'checked' attribute."); + } + } + } + + function testContents(aOrder, aVisible, aSelection) { + isnot(RequestsMenu.selectedItem, null, + "There should still be a selected item after filtering."); + is(RequestsMenu.selectedIndex, aSelection, + "The first item should be still selected after filtering."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should still be visible after filtering."); + + is(RequestsMenu.orderedItems.length, aOrder.length, + "There should be a specific amount of items in the requests menu."); + is(RequestsMenu.visibleItems.length, aVisible, + "There should be a specific amount of visbile items in the requests menu."); + + for (let i = 0; i < aOrder.length; i++) { + is(RequestsMenu.getItemAtIndex(i), RequestsMenu.orderedItems[i], + "The requests menu items aren't ordered correctly. Misplaced item " + i + "."); + } + + for (let i = 0, len = aOrder.length / 7; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i]), + "GET", CONTENT_TYPE_SJS + "?fmt=html", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "html", + fullMimeType: "text/html; charset=utf-8" + }); + } + for (let i = 0, len = aOrder.length / 7; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len]), + "GET", CONTENT_TYPE_SJS + "?fmt=css", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "css", + fullMimeType: "text/css; charset=utf-8" + }); + } + for (let i = 0, len = aOrder.length / 7; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 2]), + "GET", CONTENT_TYPE_SJS + "?fmt=js", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "js", + fullMimeType: "application/javascript; charset=utf-8" + }); + } + for (let i = 0, len = aOrder.length / 7; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 3]), + "GET", CONTENT_TYPE_SJS + "?fmt=font", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "woff", + fullMimeType: "font/woff" + }); + } + for (let i = 0, len = aOrder.length / 7; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 4]), + "GET", CONTENT_TYPE_SJS + "?fmt=image", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "png", + fullMimeType: "image/png" + }); + } + for (let i = 0, len = aOrder.length / 7; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 5]), + "GET", CONTENT_TYPE_SJS + "?fmt=audio", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "ogg", + fullMimeType: "audio/ogg" + }); + } + for (let i = 0, len = aOrder.length / 7; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 6]), + "GET", CONTENT_TYPE_SJS + "?fmt=video", { + fuzzyUrl: true, + status: 200, + statusText: "OK", + type: "webm", + fullMimeType: "video/webm" + }); + } + + return Promise.resolve(null); + } + + let str = "'<p>'" + new Array(10).join(Math.random(10)) + "'</p>'"; + aDebuggee.performRequests('{ "htmlContent": "' + str + '", "getMedia": true }'); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_footer-summary.js b/browser/devtools/netmonitor/test/browser_net_footer-summary.js new file mode 100644 index 000000000..4ef217f53 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_footer-summary.js @@ -0,0 +1,121 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if the summary text displayed in the network requests menu footer + * is correct. + */ + +function test() { + let { PluralForm } = Cu.import("resource://gre/modules/PluralForm.jsm", {}); + + initNetMonitor(FILTERING_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { $, L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + testStatus(); + + waitForNetworkEvents(aMonitor, 8).then(() => { + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-html-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-css-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-js-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-xhr-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-fonts-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-images-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-media-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-flash-button")); + testStatus(); + + info("Performing more requests."); + aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }'); + return waitForNetworkEvents(aMonitor, 8); + }) + .then(() => { + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-html-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-css-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-js-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-xhr-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-fonts-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-images-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-media-button")); + testStatus(); + + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-flash-button")); + testStatus(); + + teardown(aMonitor).then(finish); + }) + + function testStatus() { + let summary = $("#request-menu-network-summary"); + let value = summary.getAttribute("value"); + info("Current summary: " + value); + + let visibleItems = RequestsMenu.visibleItems; + let visibleRequestsCount = visibleItems.length; + let totalRequestsCount = RequestsMenu.itemCount; + info("Current requests: " + visibleRequestsCount + " of " + totalRequestsCount + "."); + + if (!totalRequestsCount) { + is(value, "", + "The current summary text is incorrect, expected an empty string."); + return; + } + + if (!visibleRequestsCount) { + is(value, L10N.getStr("networkMenu.empty"), + "The current summary text is incorrect, expected an 'empty' label."); + return; + } + + let totalBytes = RequestsMenu._getTotalBytesOfRequests(visibleItems); + let totalMillis = + RequestsMenu._getNewestRequest(visibleItems).attachment.endedMillis - + RequestsMenu._getOldestRequest(visibleItems).attachment.startedMillis; + + info("Computed total bytes: " + totalBytes); + info("Computed total millis: " + totalMillis); + + is(value, PluralForm.get(visibleRequestsCount, L10N.getStr("networkMenu.summary")) + .replace("#1", visibleRequestsCount) + .replace("#2", L10N.numberWithDecimals((totalBytes || 0) / 1024, 2)) + .replace("#3", L10N.numberWithDecimals((totalMillis || 0) / 1000, 2)) + , "The current summary text is incorrect.") + } + + aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }'); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_json-long.js b/browser/devtools/netmonitor/test/browser_net_json-long.js new file mode 100644 index 000000000..c683b8cda --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_json-long.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if very long JSON responses are handled correctly. + */ + +function test() { + initNetMonitor(JSON_LONG_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + // This is receiving over 80 KB of json and will populate over 6000 items + // in a variables view instance. Debug builds are slow. + requestLongerTimeout(4); + + let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CONTENT_TYPE_SJS + "?fmt=json-long", { + status: 200, + statusText: "OK", + type: "json", + fullMimeType: "text/json; charset=utf-8", + size: L10N.getFormatStr("networkMenu.sizeKB", L10N.numberWithDecimals(85975/1024, 2)), + time: true + }); + + aMonitor.panelWin.once("NetMonitor:ResponseBodyAvailable", () => { + testResponseTab(); + teardown(aMonitor).then(finish); + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + + function testResponseTab() { + let tab = document.querySelectorAll("#details-pane tab")[3]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3]; + + is(tab.getAttribute("selected"), "true", + "The response tab in the network details pane should be selected."); + + is(tabpanel.querySelector("#response-content-info-header") + .hasAttribute("hidden"), true, + "The response info header doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-json-box") + .hasAttribute("hidden"), false, + "The response content json box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-textarea-box") + .hasAttribute("hidden"), true, + "The response content textarea box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-image-box") + .hasAttribute("hidden"), true, + "The response content image box doesn't have the intended visibility."); + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 1, + "There should be 1 json scope displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-property").length, 6057, + "There should be 6057 json properties displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0, + "The empty notice should not be displayed in this tabpanel."); + + let jsonScope = tabpanel.querySelectorAll(".variables-view-scope")[0]; + let names = ".variables-view-property .name"; + let values = ".variables-view-property .value"; + + is(jsonScope.querySelector(".name").getAttribute("value"), + L10N.getStr("jsonScopeName"), + "The json scope doesn't have the correct title."); + + is(jsonScope.querySelectorAll(names)[0].getAttribute("value"), + "0", "The first json property name was incorrect."); + is(jsonScope.querySelectorAll(values)[0].getAttribute("value"), + "[object Object]", "The first json property value was incorrect."); + + is(jsonScope.querySelectorAll(names)[1].getAttribute("value"), + "greeting", "The second json property name was incorrect."); + is(jsonScope.querySelectorAll(values)[1].getAttribute("value"), + "\"Hello long string JSON!\"", "The second json property value was incorrect."); + + is(Array.slice(jsonScope.querySelectorAll(names), -1).shift().getAttribute("value"), + "__proto__", "The last json property name was incorrect."); + is(Array.slice(jsonScope.querySelectorAll(values), -1).shift().getAttribute("value"), + "[object Object]", "The last json property value was incorrect."); + } + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_json-malformed.js b/browser/devtools/netmonitor/test/browser_net_json-malformed.js new file mode 100644 index 000000000..1ea3124d4 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_json-malformed.js @@ -0,0 +1,71 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if malformed JSON responses are handled correctly. + */ + +function test() { + initNetMonitor(JSON_MALFORMED_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CONTENT_TYPE_SJS + "?fmt=json-malformed", { + status: 200, + statusText: "OK", + type: "json", + fullMimeType: "text/json; charset=utf-8" + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + + let tab = document.querySelectorAll("#details-pane tab")[3]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3]; + + is(tab.getAttribute("selected"), "true", + "The response tab in the network details pane should be selected."); + + is(tabpanel.querySelector("#response-content-info-header") + .hasAttribute("hidden"), false, + "The response info header doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-info-header") + .getAttribute("value"), + "SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data", + "The response info header doesn't have the intended value attribute."); + is(tabpanel.querySelector("#response-content-info-header") + .getAttribute("tooltiptext"), + "SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data", + "The response info header doesn't have the intended tooltiptext attribute."); + + is(tabpanel.querySelector("#response-content-json-box") + .hasAttribute("hidden"), true, + "The response content json box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-textarea-box") + .hasAttribute("hidden"), false, + "The response content textarea box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-image-box") + .hasAttribute("hidden"), true, + "The response content image box doesn't have the intended visibility."); + + NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText(), "{ \"greeting\": \"Hello malformed JSON!\" },", + "The text shown in the source editor is incorrect."); + is(aEditor.getMode(), SourceEditor.MODES.JAVASCRIPT, + "The mode active in the source editor is incorrect."); + + teardown(aMonitor).then(finish); + }); + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_jsonp.js b/browser/devtools/netmonitor/test/browser_net_jsonp.js new file mode 100644 index 000000000..a3b3f03c9 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_jsonp.js @@ -0,0 +1,83 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if JSONP responses are handled correctly. + */ + +function test() { + initNetMonitor(JSONP_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CONTENT_TYPE_SJS + "?fmt=jsonp&jsonp=$_0123Fun", { + status: 200, + statusText: "OK", + type: "json", + fullMimeType: "text/json; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04), + time: true + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + + testResponseTab(); + teardown(aMonitor).then(finish); + + function testResponseTab() { + let tab = document.querySelectorAll("#details-pane tab")[3]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3]; + + is(tab.getAttribute("selected"), "true", + "The response tab in the network details pane should be selected."); + + is(tabpanel.querySelector("#response-content-info-header") + .hasAttribute("hidden"), true, + "The response info header doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-json-box") + .hasAttribute("hidden"), false, + "The response content json box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-textarea-box") + .hasAttribute("hidden"), true, + "The response content textarea box doesn't have the intended visibility."); + is(tabpanel.querySelector("#response-content-image-box") + .hasAttribute("hidden"), true, + "The response content image box doesn't have the intended visibility."); + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 1, + "There should be 1 json scope displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-property").length, 2, + "There should be 2 json properties displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0, + "The empty notice should not be displayed in this tabpanel."); + + let jsonScope = tabpanel.querySelectorAll(".variables-view-scope")[0]; + + is(jsonScope.querySelector(".name").getAttribute("value"), + L10N.getFormatStr("jsonpScopeName", "$_0123Fun"), + "The json scope doesn't have the correct title."); + + is(jsonScope.querySelectorAll(".variables-view-property .name")[0].getAttribute("value"), + "greeting", "The first json property name was incorrect."); + is(jsonScope.querySelectorAll(".variables-view-property .value")[0].getAttribute("value"), + "\"Hello JSONP!\"", "The first json property value was incorrect."); + + is(jsonScope.querySelectorAll(".variables-view-property .name")[1].getAttribute("value"), + "__proto__", "The second json property name was incorrect."); + is(jsonScope.querySelectorAll(".variables-view-property .value")[1].getAttribute("value"), + "[object Object]", "The second json property value was incorrect."); + } + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_large-response.js b/browser/devtools/netmonitor/test/browser_net_large-response.js new file mode 100644 index 000000000..41561ed50 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_large-response.js @@ -0,0 +1,47 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if very large response contents are just displayed as plain text. + */ + +function test() { + initNetMonitor(CUSTOM_GET_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + // This test could potentially be slow because over 100 KB of stuff + // is going to be requested and displayed in the source editor. + requestLongerTimeout(2); + + let { document, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "GET", CONTENT_TYPE_SJS + "?fmt=html-long", { + status: 200, + statusText: "OK" + }); + + aMonitor.panelWin.once("NetMonitor:ResponseBodyAvailable", () => { + NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + ok(aEditor.getText().match(/^<p>/), + "The text shown in the source editor is incorrect."); + is(aEditor.getMode(), SourceEditor.MODES.TEXT, + "The mode active in the source editor is incorrect."); + + teardown(aMonitor).then(finish); + }); + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + }); + + aDebuggee.performRequests(1, CONTENT_TYPE_SJS + "?fmt=html-long"); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_page-nav.js b/browser/devtools/netmonitor/test/browser_net_page-nav.js new file mode 100644 index 000000000..690a3b8c1 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_page-nav.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if page navigation ("close", "navigate", etc.) triggers an appropriate + * action in the network monitor. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + testNavigate(() => testNavigateBack(() => testClose(() => finish()))); + + function testNavigate(aCallback) { + info("Navigating forward..."); + + aMonitor.panelWin.once("NetMonitor:TargetWillNavigate", () => { + is(aDebuggee.location, SIMPLE_URL, + "Target started navigating to the correct location."); + + aMonitor.panelWin.once("NetMonitor:TargetNavigate", () => { + is(aDebuggee.location, NAVIGATE_URL, + "Target finished navigating to the correct location."); + + aCallback(); + }); + }); + + aDebuggee.location = NAVIGATE_URL; + } + + function testNavigateBack(aCallback) { + info("Navigating backward..."); + + aMonitor.panelWin.once("NetMonitor:TargetWillNavigate", () => { + is(aDebuggee.location, NAVIGATE_URL, + "Target started navigating back to the previous location."); + + aMonitor.panelWin.once("NetMonitor:TargetNavigate", () => { + is(aDebuggee.location, SIMPLE_URL, + "Target finished navigating back to the previous location."); + + aCallback(); + }); + }); + + aDebuggee.location = SIMPLE_URL; + } + + function testClose(aCallback) { + info("Closing..."); + + aMonitor.once("destroyed", () => { + ok(!aMonitor._controller.client, + "There shouldn't be a client available after destruction."); + ok(!aMonitor._controller.tabClient, + "There shouldn't be a tabClient available after destruction."); + ok(!aMonitor._controller.webConsoleClient, + "There shouldn't be a webConsoleClient available after destruction."); + + aCallback(); + }); + + removeTab(aTab); + } + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_pane-collapse.js b/browser/devtools/netmonitor/test/browser_net_pane-collapse.js new file mode 100644 index 000000000..6434aa259 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_pane-collapse.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if the network monitor panes collapse properly. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, Prefs, NetMonitorView } = aMonitor.panelWin; + let detailsPane = document.getElementById("details-pane"); + let detailsPaneToggleButton = document.getElementById("details-pane-toggle"); + + ok(detailsPane.hasAttribute("pane-collapsed") && + detailsPaneToggleButton.hasAttribute("pane-collapsed"), + "The details pane should initially be hidden."); + + NetMonitorView.toggleDetailsPane({ visible: true, animated: false }); + + let width = ~~(detailsPane.getAttribute("width")); + is(width, Prefs.networkDetailsWidth, + "The details pane has an incorrect width."); + is(detailsPane.style.marginLeft, "0px", + "The details pane has an incorrect left margin."); + is(detailsPane.style.marginRight, "0px", + "The details pane has an incorrect right margin."); + ok(!detailsPane.hasAttribute("animated"), + "The details pane has an incorrect animated attribute."); + ok(!detailsPane.hasAttribute("pane-collapsed") && + !detailsPaneToggleButton.hasAttribute("pane-collapsed"), + "The details pane should at this point be visible."); + + NetMonitorView.toggleDetailsPane({ visible: false, animated: true }); + + let margin = -(width + 1) + "px"; + is(width, Prefs.networkDetailsWidth, + "The details pane has an incorrect width after collapsing."); + is(detailsPane.style.marginLeft, margin, + "The details pane has an incorrect left margin after collapsing."); + is(detailsPane.style.marginRight, margin, + "The details pane has an incorrect right margin after collapsing."); + ok(detailsPane.hasAttribute("animated"), + "The details pane has an incorrect attribute after an animated collapsing."); + ok(detailsPane.hasAttribute("pane-collapsed") && + detailsPaneToggleButton.hasAttribute("pane-collapsed"), + "The details pane should not be visible after collapsing."); + + NetMonitorView.toggleDetailsPane({ visible: true, animated: false }); + + is(width, Prefs.networkDetailsWidth, + "The details pane has an incorrect width after uncollapsing."); + is(detailsPane.style.marginLeft, "0px", + "The details pane has an incorrect left margin after uncollapsing."); + is(detailsPane.style.marginRight, "0px", + "The details pane has an incorrect right margin after uncollapsing."); + ok(!detailsPane.hasAttribute("animated"), + "The details pane has an incorrect attribute after an unanimated uncollapsing."); + ok(!detailsPane.hasAttribute("pane-collapsed") && + !detailsPaneToggleButton.hasAttribute("pane-collapsed"), + "The details pane should be visible again after uncollapsing."); + + teardown(aMonitor).then(finish); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_pane-toggle.js b/browser/devtools/netmonitor/test/browser_net_pane-toggle.js new file mode 100644 index 000000000..552c39cda --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_pane-toggle.js @@ -0,0 +1,79 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if toggling the details pane works as expected. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + is(document.querySelector("#details-pane-toggle") + .hasAttribute("disabled"), true, + "The pane toggle button should be disabled when the frontend is opened."); + is(document.querySelector("#details-pane-toggle") + .hasAttribute("pane-collapsed"), true, + "The pane toggle button should indicate that the details pane is " + + "collapsed when the frontend is opened."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should be hidden when the frontend is opened."); + is(RequestsMenu.selectedItem, null, + "There should be no selected item in the requests menu."); + + aMonitor.panelWin.once("NetMonitor:NetworkEvent", () => { + is(document.querySelector("#details-pane-toggle") + .hasAttribute("disabled"), false, + "The pane toggle button should be enabled after the first request."); + is(document.querySelector("#details-pane-toggle") + .hasAttribute("pane-collapsed"), true, + "The pane toggle button should still indicate that the details pane is " + + "collapsed after the first request."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should still be hidden after the first request."); + is(RequestsMenu.selectedItem, null, + "There should still be no selected item in the requests menu."); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + + is(document.querySelector("#details-pane-toggle") + .hasAttribute("disabled"), false, + "The pane toggle button should still be enabled after being pressed."); + is(document.querySelector("#details-pane-toggle") + .hasAttribute("pane-collapsed"), false, + "The pane toggle button should now indicate that the details pane is " + + "not collapsed anymore after being pressed."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should not be hidden after toggle button was pressed."); + isnot(RequestsMenu.selectedItem, null, + "There should be a selected item in the requests menu."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be selected in the requests menu."); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + + is(document.querySelector("#details-pane-toggle") + .hasAttribute("disabled"), false, + "The pane toggle button should still be enabled after being pressed again."); + is(document.querySelector("#details-pane-toggle") + .hasAttribute("pane-collapsed"), true, + "The pane toggle button should now indicate that the details pane is " + + "collapsed after being pressed again."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should now be hidden after the toggle button was pressed again."); + is(RequestsMenu.selectedItem, null, + "There should now be no selected item in the requests menu."); + + teardown(aMonitor).then(finish); + }); + + aDebuggee.location.reload(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_post-data-01.js b/browser/devtools/netmonitor/test/browser_net_post-data-01.js new file mode 100644 index 000000000..1e23adeb3 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_post-data-01.js @@ -0,0 +1,153 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if the POST requests display the correct information in the UI. + */ + +function test() { + initNetMonitor(POST_DATA_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu, NetworkDetails } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + NetworkDetails._params.lazyEmpty = false; + + waitForNetworkEvents(aMonitor, 0, 2).then(() => { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0), + "POST", SIMPLE_SJS + "?foo=bar&baz=42&type=urlencoded", { + status: 200, + statusText: "Och Aye", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1), + "POST", SIMPLE_SJS + "?foo=bar&baz=42&type=multipart", { + status: 200, + statusText: "Och Aye", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01), + time: true + }); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[2]); + + testParamsTab("urlencoded") + .then(() => { + RequestsMenu.selectedIndex = 1; + return testParamsTab("multipart"); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + + function testParamsTab(aType) { + let tab = document.querySelectorAll("#details-pane tab")[2]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2]; + + is(tab.getAttribute("selected"), "true", + "The params tab in the network details pane should be selected."); + + function checkVisibility(aBox) { + is(tabpanel.querySelector("#request-params-box") + .hasAttribute("hidden"), !aBox.contains("params"), + "The request params box doesn't have the indended visibility."); + is(tabpanel.querySelector("#request-post-data-textarea-box") + .hasAttribute("hidden"), !aBox.contains("textarea"), + "The request post data textarea box doesn't have the indended visibility."); + } + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 2, + "There should be 2 param scopes displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0, + "The empty notice should not be displayed in this tabpanel."); + + let queryScope = tabpanel.querySelectorAll(".variables-view-scope")[0]; + let postScope = tabpanel.querySelectorAll(".variables-view-scope")[1]; + + is(queryScope.querySelector(".name").getAttribute("value"), + L10N.getStr("paramsQueryString"), + "The query scope doesn't have the correct title."); + + is(postScope.querySelector(".name").getAttribute("value"), + L10N.getStr(aType == "urlencoded" ? "paramsFormData" : "paramsPostPayload"), + "The post scope doesn't have the correct title."); + + is(queryScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"), + "foo", "The first query param name was incorrect."); + is(queryScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"), + "\"bar\"", "The first query param value was incorrect."); + is(queryScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"), + "baz", "The second query param name was incorrect."); + is(queryScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"), + "\"42\"", "The second query param value was incorrect."); + is(queryScope.querySelectorAll(".variables-view-variable .name")[2].getAttribute("value"), + "type", "The third query param name was incorrect."); + is(queryScope.querySelectorAll(".variables-view-variable .value")[2].getAttribute("value"), + "\"" + aType + "\"", "The third query param value was incorrect."); + + if (aType == "urlencoded") { + checkVisibility("params"); + + is(tabpanel.querySelectorAll(".variables-view-variable").length, 5, + "There should be 5 param values displayed in this tabpanel."); + is(queryScope.querySelectorAll(".variables-view-variable").length, 3, + "There should be 3 param values displayed in the query scope."); + is(postScope.querySelectorAll(".variables-view-variable").length, 2, + "There should be 2 param values displayed in the post scope."); + + is(postScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"), + "foo", "The first post param name was incorrect."); + is(postScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"), + "\"bar\"", "The first post param value was incorrect."); + is(postScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"), + "baz", "The second post param name was incorrect."); + is(postScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"), + "\"123\"", "The second post param value was incorrect."); + + return Promise.resolve(); + } + else { + checkVisibility("params textarea"); + + is(tabpanel.querySelectorAll(".variables-view-variable").length, 3, + "There should be 3 param values displayed in this tabpanel."); + is(queryScope.querySelectorAll(".variables-view-variable").length, 3, + "There should be 3 param values displayed in the query scope."); + is(postScope.querySelectorAll(".variables-view-variable").length, 0, + "There should be 0 param values displayed in the post scope."); + + return NetMonitorView.editor("#request-post-data-textarea").then((aEditor) => { + ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"text\""), + "The text shown in the source editor is incorrect (1.1)."); + ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"email\""), + "The text shown in the source editor is incorrect (2.1)."); + ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"range\""), + "The text shown in the source editor is incorrect (3.1)."); + ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"Custom field\""), + "The text shown in the source editor is incorrect (4.1)."); + ok(aEditor.getText().contains("Some text..."), + "The text shown in the source editor is incorrect (2.2)."); + ok(aEditor.getText().contains("42"), + "The text shown in the source editor is incorrect (3.2)."); + ok(aEditor.getText().contains("Extra data"), + "The text shown in the source editor is incorrect (4.2)."); + is(aEditor.getMode(), SourceEditor.MODES.TEXT, + "The mode active in the source editor is incorrect."); + }); + } + } + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_post-data-02.js b/browser/devtools/netmonitor/test/browser_net_post-data-02.js new file mode 100644 index 000000000..b3d200a9e --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_post-data-02.js @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if the POST requests display the correct information in the UI, + * even for raw payloads without attached content-type headers. + */ + +function test() { + initNetMonitor(POST_RAW_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu, NetworkDetails } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + NetworkDetails._params.lazyEmpty = false; + + waitForNetworkEvents(aMonitor, 0, 1).then(() => { + NetMonitorView.toggleDetailsPane({ visible: true }, 2) + RequestsMenu.selectedIndex = 0; + + let tab = document.querySelectorAll("#details-pane tab")[2]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2]; + + is(tab.getAttribute("selected"), "true", + "The params tab in the network details pane should be selected."); + + is(tabpanel.querySelector("#request-params-box") + .hasAttribute("hidden"), false, + "The request params box doesn't have the indended visibility."); + is(tabpanel.querySelector("#request-post-data-textarea-box") + .hasAttribute("hidden"), true, + "The request post data textarea box doesn't have the indended visibility."); + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 1, + "There should be 1 param scopes displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0, + "The empty notice should not be displayed in this tabpanel."); + + let postScope = tabpanel.querySelectorAll(".variables-view-scope")[0]; + is(postScope.querySelector(".name").getAttribute("value"), + L10N.getStr("paramsFormData"), + "The post scope doesn't have the correct title."); + + is(postScope.querySelectorAll(".variables-view-variable").length, 2, + "There should be 2 param values displayed in the post scope."); + is(postScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"), + "foo", "The first query param name was incorrect."); + is(postScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"), + "\"bar\"", "The first query param value was incorrect."); + is(postScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"), + "baz", "The second query param name was incorrect."); + is(postScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"), + "\"123\"", "The second query param value was incorrect."); + + teardown(aMonitor).then(finish); + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_prefs-and-l10n.js b/browser/devtools/netmonitor/test/browser_net_prefs-and-l10n.js new file mode 100644 index 000000000..ce0f31ff7 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_prefs-and-l10n.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if the preferences and localization objects work correctly. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + ok(aMonitor.panelWin.L10N, + "Should have a localization object available on the panel window."); + ok(aMonitor.panelWin.Prefs, + "Should have a preferences object available on the panel window."); + + function testL10N() { + let { L10N } = aMonitor.panelWin; + + ok(L10N.stringBundle, + "The localization object should have a string bundle available."); + + let bundleName = "chrome://browser/locale/devtools/netmonitor.properties"; + let stringBundle = Services.strings.createBundle(bundleName); + + is(L10N.getStr("netmonitor.label"), + stringBundle.GetStringFromName("netmonitor.label"), + "The getStr() method didn't return the expected string."); + + is(L10N.getFormatStr("networkMenu.totalMS", "foo"), + stringBundle.formatStringFromName("networkMenu.totalMS", ["foo"], 1), + "The getFormatStr() method didn't return the expected string."); + } + + function testPrefs() { + let { Prefs } = aMonitor.panelWin; + + is(Prefs.root, "devtools.netmonitor", + "The preferences object should have a correct root path."); + + is(Prefs.networkDetailsWidth, + Services.prefs.getIntPref("devtools.netmonitor.panes-network-details-width"), + "Getting a pref should work correctly."); + + let previousValue = Prefs.networkDetailsWidth; + let bogusValue = ~~(Math.random() * 100); + Prefs.networkDetailsWidth = bogusValue; + is(Prefs.networkDetailsWidth, + Services.prefs.getIntPref("devtools.netmonitor.panes-network-details-width"), + "Getting a pref after it has been modified should work correctly."); + is(Prefs.networkDetailsWidth, bogusValue, + "The pref wasn't updated correctly in the preferences object."); + + Prefs.networkDetailsWidth = previousValue; + is(Prefs.networkDetailsWidth, + Services.prefs.getIntPref("devtools.netmonitor.panes-network-details-width"), + "Getting a pref after it has been modified again should work correctly."); + is(Prefs.networkDetailsWidth, previousValue, + "The pref wasn't updated correctly again in the preferences object."); + } + + testL10N(); + testPrefs(); + + teardown(aMonitor).then(finish); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_prefs-reload.js b/browser/devtools/netmonitor/test/browser_net_prefs-reload.js new file mode 100644 index 000000000..d5fd61c43 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_prefs-reload.js @@ -0,0 +1,217 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if the prefs that should survive across tool reloads work. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + // This test reopens the network monitor a bunch of times, for different + // hosts (bottom, side, window). This seems to be slow on debug builds. + requestLongerTimeout(3); + + let prefsToCheck = { + networkDetailsWidth: { + newValue: ~~(Math.random() * 200 + 100), + validate: ($) => ~~$("#details-pane").getAttribute("width"), + modifyFrontend: ($, aValue) => $("#details-pane").setAttribute("width", aValue) + }, + networkDetailsHeight: { + newValue: ~~(Math.random() * 300 + 100), + validate: ($) => ~~$("#details-pane").getAttribute("height"), + modifyFrontend: ($, aValue) => $("#details-pane").setAttribute("height", aValue) + }, + /* add more prefs here... */ + }; + + function storeFirstPrefValues() { + info("Caching initial pref values."); + + for (let name in prefsToCheck) { + let currentValue = aMonitor.panelWin.Prefs[name]; + prefsToCheck[name].firstValue = currentValue; + } + } + + function validateFirstPrefValues() { + info("Validating current pref values to the UI elements."); + + for (let name in prefsToCheck) { + let currentValue = aMonitor.panelWin.Prefs[name]; + let firstValue = prefsToCheck[name].firstValue; + let validate = prefsToCheck[name].validate; + + is(currentValue, firstValue, + "Pref " + name + " should be equal to first value: " + firstValue); + is(currentValue, validate(aMonitor.panelWin.$), + "Pref " + name + " should validate: " + currentValue); + } + } + + function modifyFrontend() { + info("Modifying UI elements to the specified new values."); + + for (let name in prefsToCheck) { + let currentValue = aMonitor.panelWin.Prefs[name]; + let firstValue = prefsToCheck[name].firstValue; + let newValue = prefsToCheck[name].newValue; + let validate = prefsToCheck[name].validate; + let modifyFrontend = prefsToCheck[name].modifyFrontend; + + modifyFrontend(aMonitor.panelWin.$, newValue); + info("Modified UI element affecting " + name + " to: " + newValue); + + is(currentValue, firstValue, + "Pref " + name + " should still be equal to first value: " + firstValue); + isnot(currentValue, newValue, + "Pref " + name + " should't yet be equal to second value: " + newValue); + is(newValue, validate(aMonitor.panelWin.$), + "The UI element affecting " + name + " should validate: " + newValue); + } + } + + function validateNewPrefValues() { + info("Invalidating old pref values to the modified UI elements."); + + for (let name in prefsToCheck) { + let currentValue = aMonitor.panelWin.Prefs[name]; + let firstValue = prefsToCheck[name].firstValue; + let newValue = prefsToCheck[name].newValue; + let validate = prefsToCheck[name].validate; + + isnot(currentValue, firstValue, + "Pref " + name + " should't be equal to first value: " + firstValue); + is(currentValue, newValue, + "Pref " + name + " should now be equal to second value: " + newValue); + is(newValue, validate(aMonitor.panelWin.$), + "The UI element affecting " + name + " should validate: " + newValue); + } + } + + function resetFrontend() { + info("Resetting UI elements to the cached initial pref values."); + + for (let name in prefsToCheck) { + let currentValue = aMonitor.panelWin.Prefs[name]; + let firstValue = prefsToCheck[name].firstValue; + let newValue = prefsToCheck[name].newValue; + let validate = prefsToCheck[name].validate; + let modifyFrontend = prefsToCheck[name].modifyFrontend; + + modifyFrontend(aMonitor.panelWin.$, firstValue); + info("Modified UI element affecting " + name + " to: " + firstValue); + + isnot(currentValue, firstValue, + "Pref " + name + " should't yet be equal to first value: " + firstValue); + is(currentValue, newValue, + "Pref " + name + " should still be equal to second value: " + newValue); + is(firstValue, validate(aMonitor.panelWin.$), + "The UI element affecting " + name + " should validate: " + firstValue); + } + } + + function testBottom() { + info("Testing prefs reload for a bottom host."); + storeFirstPrefValues(); + + // Validate and modify while toolbox is on the bottom. + validateFirstPrefValues(); + modifyFrontend(); + + return restartNetMonitor(aMonitor) + .then(([,, aNewMonitor]) => { + aMonitor = aNewMonitor; + + // Revalidate and reset frontend while toolbox is on the bottom. + validateNewPrefValues(); + resetFrontend(); + + return restartNetMonitor(aMonitor); + }) + .then(([,, aNewMonitor]) => { + aMonitor = aNewMonitor; + + // Revalidate. + validateFirstPrefValues(); + }); + } + + function testSide() { + info("Moving toolbox to the side..."); + + return aMonitor._toolbox.switchHost(Toolbox.HostType.SIDE) + .then(() => { + info("Testing prefs reload for a side host."); + storeFirstPrefValues(); + + // Validate and modify frontend while toolbox is on the side. + validateFirstPrefValues(); + modifyFrontend(); + + return restartNetMonitor(aMonitor); + }) + .then(([,, aNewMonitor]) => { + aMonitor = aNewMonitor; + + // Revalidate and reset frontend while toolbox is on the side. + validateNewPrefValues(); + resetFrontend(); + + return restartNetMonitor(aMonitor); + }) + .then(([,, aNewMonitor]) => { + aMonitor = aNewMonitor; + + // Revalidate. + validateFirstPrefValues(); + }); + } + + function testWindow() { + info("Moving toolbox into a window..."); + + return aMonitor._toolbox.switchHost(Toolbox.HostType.WINDOW) + .then(() => { + info("Testing prefs reload for a window host."); + storeFirstPrefValues(); + + // Validate and modify frontend while toolbox is in a window. + validateFirstPrefValues(); + modifyFrontend(); + + return restartNetMonitor(aMonitor); + }) + .then(([,, aNewMonitor]) => { + aMonitor = aNewMonitor; + + // Revalidate and reset frontend while toolbox is in a window. + validateNewPrefValues(); + resetFrontend(); + + return restartNetMonitor(aMonitor); + }) + .then(([,, aNewMonitor]) => { + aMonitor = aNewMonitor; + + // Revalidate. + validateFirstPrefValues(); + }); + } + + function cleanupAndFinish() { + info("Moving toolbox back to the bottom..."); + + aMonitor._toolbox.switchHost(Toolbox.HostType.BOTTOM) + .then(() => teardown(aMonitor)) + .then(finish); + } + + testBottom() + .then(testSide) + .then(testWindow) + .then(cleanupAndFinish); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_req-resp-bodies.js b/browser/devtools/netmonitor/test/browser_net_req-resp-bodies.js new file mode 100644 index 000000000..1f1a55a16 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_req-resp-bodies.js @@ -0,0 +1,60 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if request and response body logging stays on after opening the console. + */ + +function test() { + initNetMonitor(JSON_LONG_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + function verifyRequest(aOffset) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOffset), + "GET", CONTENT_TYPE_SJS + "?fmt=json-long", { + status: 200, + statusText: "OK", + type: "json", + fullMimeType: "text/json; charset=utf-8", + size: L10N.getFormatStr("networkMenu.sizeKB", L10N.numberWithDecimals(85975/1024, 2)), + time: true + }); + } + + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequest(0); + + aMonitor._toolbox.once("webconsole-selected", () => { + aMonitor._toolbox.once("netmonitor-selected", () => { + + waitForNetworkEvents(aMonitor, 1).then(() => { + waitForNetworkEvents(aMonitor, 1).then(() => { + verifyRequest(1); + teardown(aMonitor).then(finish); + }); + + // Perform another batch of requests. + aDebuggee.performRequests(); + }); + + // Reload debugee. + aDebuggee.location.reload(); + }); + + // Switch back to the netmonitor. + aMonitor._toolbox.selectTool("netmonitor"); + }); + + // Switch to the webconsole. + aMonitor._toolbox.selectTool("webconsole"); + }); + + // Perform first batch of requests. + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_simple-init.js b/browser/devtools/netmonitor/test/browser_net_simple-init.js new file mode 100644 index 000000000..9f444bb49 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_simple-init.js @@ -0,0 +1,84 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Simple check if the network monitor starts up and shuts down properly. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + is(aTab.linkedBrowser.contentWindow.wrappedJSObject.location, SIMPLE_URL, + "The current tab's location is the correct one."); + is(aDebuggee.location, SIMPLE_URL, + "The current debuggee's location is the correct one."); + + function checkIfInitialized(aTag) { + info("Checking if initialization is ok (" + aTag + ")."); + + ok(aMonitor._view, + "The network monitor view object exists (" + aTag + ")."); + ok(aMonitor._view._isInitialized, + "The network monitor view object exists and is initialized (" + aTag + ")."); + + ok(aMonitor._controller, + "The network monitor controller object exists (" + aTag + ")."); + ok(aMonitor._controller._isInitialized, + "The network monitor controller object exists and is initialized (" + aTag + ")."); + + ok(aMonitor.isReady, + "The network monitor panel appears to be ready (" + aTag + ")."); + + ok(aMonitor._controller.client, + "There should be a client available at this point (" + aTag + ")."); + ok(aMonitor._controller.tabClient, + "There should be a tabClient available at this point (" + aTag + ")."); + ok(aMonitor._controller.webConsoleClient, + "There should be a webConsoleClient available at this point (" + aTag + ")."); + } + + function checkIfDestroyed(aTag) { + info("Checking if destruction is ok."); + + ok(!aMonitor._controller.client, + "There shouldn't be a client available after destruction (" + aTag + ")."); + ok(!aMonitor._controller.tabClient, + "There shouldn't be a tabClient available after destruction (" + aTag + ")."); + ok(!aMonitor._controller.webConsoleClient, + "There shouldn't be a webConsoleClient available after destruction (" + aTag + ")."); + } + + executeSoon(() => { + checkIfInitialized(1); + + aMonitor._controller.startupNetMonitor() + .then(() => { + info("Starting up again shouldn't do anything special."); + checkIfInitialized(2); + return aMonitor._controller.connect(); + }) + .then(() => { + info("Connecting again shouldn't do anything special."); + checkIfInitialized(3); + return teardown(aMonitor); + }) + .then(finish); + }); + + registerCleanupFunction(() => { + checkIfDestroyed(1); + + aMonitor._controller.shutdownNetMonitor() + .then(() => { + info("Shutting down again shouldn't do anything special."); + checkIfDestroyed(2); + return aMonitor._controller.disconnect(); + }) + .then(() => { + info("Disconnecting again shouldn't do anything special."); + checkIfDestroyed(3); + }); + }); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_simple-request-data.js b/browser/devtools/netmonitor/test/browser_net_simple-request-data.js new file mode 100644 index 000000000..d9efa5eeb --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_simple-request-data.js @@ -0,0 +1,237 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if requests render correct information in the menu UI. + */ + +function test() { + initNetMonitor(SIMPLE_SJS).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1) + .then(() => teardown(aMonitor)) + .then(finish); + + aMonitor.panelWin.once("NetMonitor:NetworkEvent", () => { + is(RequestsMenu.selectedItem, null, + "There shouldn't be any selected item in the requests menu."); + is(RequestsMenu.itemCount, 1, + "The requests menu should not be empty after the first request."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should still be hidden after the first request."); + + let requestItem = RequestsMenu.getItemAtIndex(0); + let target = requestItem.target; + + is(typeof requestItem.value, "string", + "The attached request id is incorrect."); + isnot(requestItem.value, "", + "The attached request id should not be empty."); + + is(typeof requestItem.attachment.startedDeltaMillis, "number", + "The attached startedDeltaMillis is incorrect."); + is(requestItem.attachment.startedDeltaMillis, 0, + "The attached startedDeltaMillis should be zero."); + + is(typeof requestItem.attachment.startedMillis, "number", + "The attached startedMillis is incorrect."); + isnot(requestItem.attachment.startedMillis, 0, + "The attached startedMillis should not be zero."); + + is(requestItem.attachment.requestHeaders, undefined, + "The requestHeaders should not yet be set."); + is(requestItem.attachment.requestCookies, undefined, + "The requestCookies should not yet be set."); + is(requestItem.attachment.requestPostData, undefined, + "The requestPostData should not yet be set."); + + is(requestItem.attachment.responseHeaders, undefined, + "The responseHeaders should not yet be set."); + is(requestItem.attachment.responseCookies, undefined, + "The responseCookies should not yet be set."); + + is(requestItem.attachment.httpVersion, undefined, + "The httpVersion should not yet be set."); + is(requestItem.attachment.status, undefined, + "The status should not yet be set."); + is(requestItem.attachment.statusText, undefined, + "The statusText should not yet be set."); + + is(requestItem.attachment.headersSize, undefined, + "The headersSize should not yet be set."); + is(requestItem.attachment.contentSize, undefined, + "The contentSize should not yet be set."); + + is(requestItem.attachment.mimeType, undefined, + "The mimeType should not yet be set."); + is(requestItem.attachment.responseContent, undefined, + "The responseContent should not yet be set."); + + is(requestItem.attachment.totalTime, undefined, + "The totalTime should not yet be set."); + is(requestItem.attachment.eventTimings, undefined, + "The eventTimings should not yet be set."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:RequestHeaders", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + ok(requestItem.attachment.requestHeaders, + "There should be a requestHeaders attachment available."); + ok(requestItem.attachment.requestHeaders.headers.length >= 6, + "The requestHeaders attachment has an incorrect |headers| property."); + // Can't test for an exact total number of headers, because it seems to + // vary across pgo/non-pgo builds. + isnot(requestItem.attachment.requestHeaders.headersSize, 0, + "The requestHeaders attachment has an incorrect |headersSize| property."); + // Can't test for the exact request headers size because the value may + // vary across platforms ("User-Agent" header differs). + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:RequestCookies", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + ok(requestItem.attachment.requestCookies, + "There should be a requestCookies attachment available."); + is(requestItem.attachment.requestCookies.cookies.length, 0, + "The requestCookies attachment has an incorrect |cookies| property."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:RequestPostData", () => { + ok(false, "Trap listener: this request doesn't have any post data.") + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:ResponseHeaders", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + ok(requestItem.attachment.responseHeaders, + "There should be a responseHeaders attachment available."); + is(requestItem.attachment.responseHeaders.headers.length, 6, + "The responseHeaders attachment has an incorrect |headers| property."); + is(requestItem.attachment.responseHeaders.headersSize, 173, + "The responseHeaders attachment has an incorrect |headersSize| property."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:ResponseCookies", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + ok(requestItem.attachment.responseCookies, + "There should be a responseCookies attachment available."); + is(requestItem.attachment.responseCookies.cookies.length, 0, + "The responseCookies attachment has an incorrect |cookies| property."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdating:ResponseStart", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + is(requestItem.attachment.httpVersion, "HTTP/1.1", + "The httpVersion attachment has an incorrect value."); + is(requestItem.attachment.status, "200", + "The status attachment has an incorrect value."); + is(requestItem.attachment.statusText, "Och Aye", + "The statusText attachment has an incorrect value."); + is(requestItem.attachment.headersSize, 173, + "The headersSize attachment has an incorrect value."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, { + status: "200", + statusText: "Och Aye" + }); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdating:ResponseContent", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + is(requestItem.attachment.contentSize, "12", + "The contentSize attachment has an incorrect value."); + is(requestItem.attachment.mimeType, "text/plain; charset=utf-8", + "The mimeType attachment has an incorrect value."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, { + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01), + }); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:ResponseContent", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + ok(requestItem.attachment.responseContent, + "There should be a responseContent attachment available."); + is(requestItem.attachment.responseContent.content.mimeType, "text/plain; charset=utf-8", + "The responseContent attachment has an incorrect |content.mimeType| property."); + is(requestItem.attachment.responseContent.content.text, "Hello world!", + "The responseContent attachment has an incorrect |content.text| property."); + is(requestItem.attachment.responseContent.content.size, 12, + "The responseContent attachment has an incorrect |content.size| property."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, { + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01), + }); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdating:EventTimings", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + is(typeof requestItem.attachment.totalTime, "number", + "The attached totalTime is incorrect."); + ok(requestItem.attachment.totalTime >= 0, + "The attached totalTime should be positive."); + + is(typeof requestItem.attachment.endedMillis, "number", + "The attached endedMillis is incorrect."); + ok(requestItem.attachment.endedMillis >= 0, + "The attached endedMillis should be positive."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, { + time: true + }); + }); + + aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:EventTimings", () => { + let requestItem = RequestsMenu.getItemAtIndex(0); + + ok(requestItem.attachment.eventTimings, + "There should be a eventTimings attachment available."); + is(typeof requestItem.attachment.eventTimings.timings.blocked, "number", + "The eventTimings attachment has an incorrect |timings.blocked| property."); + is(typeof requestItem.attachment.eventTimings.timings.dns, "number", + "The eventTimings attachment has an incorrect |timings.dns| property."); + is(typeof requestItem.attachment.eventTimings.timings.connect, "number", + "The eventTimings attachment has an incorrect |timings.connect| property."); + is(typeof requestItem.attachment.eventTimings.timings.send, "number", + "The eventTimings attachment has an incorrect |timings.send| property."); + is(typeof requestItem.attachment.eventTimings.timings.wait, "number", + "The eventTimings attachment has an incorrect |timings.wait| property."); + is(typeof requestItem.attachment.eventTimings.timings.receive, "number", + "The eventTimings attachment has an incorrect |timings.receive| property."); + is(typeof requestItem.attachment.eventTimings.totalTime, "number", + "The eventTimings attachment has an incorrect |totalTime| property."); + + verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, { + time: true + }); + }); + + aDebuggee.location.reload(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_simple-request-details.js b/browser/devtools/netmonitor/test/browser_net_simple-request-details.js new file mode 100644 index 000000000..c43afb222 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_simple-request-details.js @@ -0,0 +1,239 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if requests render correct information in the details UI. + */ + +function test() { + initNetMonitor(SIMPLE_SJS).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu, NetworkDetails } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 1).then(() => { + is(RequestsMenu.selectedItem, null, + "There shouldn't be any selected item in the requests menu."); + is(RequestsMenu.itemCount, 1, + "The requests menu should not be empty after the first request."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should still be hidden after the first request."); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.getElementById("details-pane-toggle")); + + isnot(RequestsMenu.selectedItem, null, + "There should be a selected item in the requests menu."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be selected in the requests menu."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should not be hidden after toggle button was pressed."); + + testHeadersTab(); + testCookiesTab(); + testParamsTab(); + testResponseTab() + .then(() => { + testTimingsTab(); + return teardown(aMonitor); + }) + .then(finish); + }); + + function testHeadersTab() { + let tab = document.querySelectorAll("#details-pane tab")[0]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[0]; + + is(tab.getAttribute("selected"), "true", + "The headers tab in the network details pane should be selected."); + + is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"), + SIMPLE_SJS, "The url summary value is incorrect."); + is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("tooltiptext"), + SIMPLE_SJS, "The url summary tooltiptext is incorrect."); + is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"), + "GET", "The method summary value is incorrect."); + is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("code"), + "200", "The status summary code is incorrect."); + is(tabpanel.querySelector("#headers-summary-status-value").getAttribute("value"), + "200 Och Aye", "The status summary value is incorrect."); + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 2, + "There should be 2 header scopes displayed in this tabpanel."); + ok(tabpanel.querySelectorAll(".variable-or-property").length >= 12, + "There should be at least 12 header values displayed in this tabpanel."); + // Can't test for an exact total number of headers, because it seems to + // vary across pgo/non-pgo builds. + + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0, + "The empty notice should not be displayed in this tabpanel."); + + let responseScope = tabpanel.querySelectorAll(".variables-view-scope")[0]; + let requestScope = tabpanel.querySelectorAll(".variables-view-scope")[1]; + + is(responseScope.querySelector(".name").getAttribute("value"), + L10N.getStr("responseHeaders") + " (" + + L10N.getFormatStr("networkMenu.sizeKB", L10N.numberWithDecimals(173/1024, 3)) + ")", + "The response headers scope doesn't have the correct title."); + + ok(requestScope.querySelector(".name").getAttribute("value").contains( + L10N.getStr("requestHeaders") + " (0"), + "The request headers scope doesn't have the correct title."); + // Can't test for full request headers title because the size may + // vary across platforms ("User-Agent" header differs). We're pretty + // sure it's smaller than 1 MB though, so it starts with a 0. + + is(responseScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"), + "Connection", "The first response header name was incorrect."); + is(responseScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"), + "\"close\"", "The first response header value was incorrect."); + is(responseScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"), + "Content-Length", "The second response header name was incorrect."); + is(responseScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"), + "\"12\"", "The second response header value was incorrect."); + is(responseScope.querySelectorAll(".variables-view-variable .name")[2].getAttribute("value"), + "Content-Type", "The third response header name was incorrect."); + is(responseScope.querySelectorAll(".variables-view-variable .value")[2].getAttribute("value"), + "\"text/plain; charset=utf-8\"", "The third response header value was incorrect."); + is(responseScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"), + "foo-bar", "The last response header name was incorrect."); + is(responseScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"), + "\"baz\"", "The last response header value was incorrect."); + + is(requestScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"), + "Host", "The first request header name was incorrect."); + is(requestScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"), + "\"example.com\"", "The first request header value was incorrect."); + is(requestScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"), + "Connection", "The penultimate request header name was incorrect."); + is(requestScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"), + "\"keep-alive\"", "The penultimate request header value was incorrect."); + + let lastReqHeaderName = requestScope.querySelectorAll(".variables-view-variable .name")[6]; + let lastReqHeaderValue = requestScope.querySelectorAll(".variables-view-variable .value")[6]; + if (lastReqHeaderName && lastReqHeaderValue) { + is(lastReqHeaderName.getAttribute("value"), + "Cache-Control", "The last request header name was incorrect."); + is(lastReqHeaderValue.getAttribute("value"), + "\"max-age=0\"", "The last request header value was incorrect."); + } else { + info("The number of request headers was 6 instead of 7. Technically, " + + "not a failure in this particular test, but needs investigation."); + } + } + + function testCookiesTab() { + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[1]); + + let tab = document.querySelectorAll("#details-pane tab")[1]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[1]; + + is(tab.getAttribute("selected"), "true", + "The cookies tab in the network details pane should be selected."); + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 0, + "There should be no cookie scopes displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variable-or-property").length, 0, + "There should be no cookie values displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1, + "The empty notice should be displayed in this tabpanel."); + } + + function testParamsTab() { + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[2]); + + let tab = document.querySelectorAll("#details-pane tab")[2]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2]; + + is(tab.getAttribute("selected"), "true", + "The params tab in the network details pane should be selected."); + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 0, + "There should be no param scopes displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variable-or-property").length, 0, + "There should be no param values displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1, + "The empty notice should be displayed in this tabpanel."); + + is(tabpanel.querySelector("#request-params-box") + .hasAttribute("hidden"), false, + "The request params box should not be hidden."); + is(tabpanel.querySelector("#request-post-data-textarea-box") + .hasAttribute("hidden"), true, + "The request post data textarea box should be hidden."); + } + + function testResponseTab() { + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[3]); + + let tab = document.querySelectorAll("#details-pane tab")[3]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3]; + + is(tab.getAttribute("selected"), "true", + "The response tab in the network details pane should be selected."); + + is(tabpanel.querySelector("#response-content-info-header") + .hasAttribute("hidden"), true, + "The response info header should be hidden."); + is(tabpanel.querySelector("#response-content-json-box") + .hasAttribute("hidden"), true, + "The response content json box should be hidden."); + is(tabpanel.querySelector("#response-content-textarea-box") + .hasAttribute("hidden"), false, + "The response content textarea box should not be hidden."); + is(tabpanel.querySelector("#response-content-image-box") + .hasAttribute("hidden"), true, + "The response content image box should be hidden."); + + return NetMonitorView.editor("#response-content-textarea").then((aEditor) => { + is(aEditor.getText(), "Hello world!", + "The text shown in the source editor is incorrect."); + is(aEditor.getMode(), SourceEditor.MODES.TEXT, + "The mode active in the source editor is incorrect."); + }); + } + + function testTimingsTab() { + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[4]); + + let tab = document.querySelectorAll("#details-pane tab")[4]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[4]; + + is(tab.getAttribute("selected"), "true", + "The timings tab in the network details pane should be selected."); + + ok(tabpanel.querySelector("#timings-summary-blocked .requests-menu-timings-total") + .getAttribute("value").match(/[0-9]+/), + "The blocked timing info does not appear to be correct."); + + ok(tabpanel.querySelector("#timings-summary-dns .requests-menu-timings-total") + .getAttribute("value").match(/[0-9]+/), + "The dns timing info does not appear to be correct."); + + ok(tabpanel.querySelector("#timings-summary-connect .requests-menu-timings-total") + .getAttribute("value").match(/[0-9]+/), + "The connect timing info does not appear to be correct."); + + ok(tabpanel.querySelector("#timings-summary-send .requests-menu-timings-total") + .getAttribute("value").match(/[0-9]+/), + "The send timing info does not appear to be correct."); + + ok(tabpanel.querySelector("#timings-summary-wait .requests-menu-timings-total") + .getAttribute("value").match(/[0-9]+/), + "The wait timing info does not appear to be correct."); + + ok(tabpanel.querySelector("#timings-summary-receive .requests-menu-timings-total") + .getAttribute("value").match(/[0-9]+/), + "The receive timing info does not appear to be correct."); + } + + aDebuggee.location.reload(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_simple-request.js b/browser/devtools/netmonitor/test/browser_net_simple-request.js new file mode 100644 index 000000000..2544faf6b --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_simple-request.js @@ -0,0 +1,60 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if requests are handled correctly. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + is(document.querySelector("#details-pane-toggle") + .hasAttribute("disabled"), true, + "The pane toggle button should be disabled when the frontend is opened."); + is(document.querySelector("#requests-menu-empty-notice") + .hasAttribute("hidden"), false, + "An empty notice should be displayed when the frontend is opened."); + is(RequestsMenu.itemCount, 0, + "The requests menu should be empty when the frontend is opened."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should be hidden when the frontend is opened."); + + aMonitor.panelWin.once("NetMonitor:NetworkEvent", () => { + is(document.querySelector("#details-pane-toggle") + .hasAttribute("disabled"), false, + "The pane toggle button should be enabled after the first request."); + is(document.querySelector("#requests-menu-empty-notice") + .hasAttribute("hidden"), true, + "The empty notice should be hidden after the first request."); + is(RequestsMenu.itemCount, 1, + "The requests menu should not be empty after the first request."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should still be hidden after the first request."); + + aMonitor.panelWin.once("NetMonitor:NetworkEvent", () => { + is(document.querySelector("#details-pane-toggle") + .hasAttribute("disabled"), false, + "The pane toggle button should be still be enabled after a reload."); + is(document.querySelector("#requests-menu-empty-notice") + .hasAttribute("hidden"), true, + "The empty notice should be still hidden after a reload."); + is(RequestsMenu.itemCount, 1, + "The requests menu should not be empty after a reload."); + is(NetMonitorView.detailsPaneHidden, true, + "The details pane should still be hidden after a reload."); + + teardown(aMonitor).then(finish); + }); + + aDebuggee.location.reload(); + }); + + aDebuggee.location.reload(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_sort-01.js b/browser/devtools/netmonitor/test/browser_net_sort-01.js new file mode 100644 index 000000000..a57a5326d --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_sort-01.js @@ -0,0 +1,248 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if the sorting mechanism works correctly. + */ + +function test() { + initNetMonitor(STATUS_CODES_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 5).then(() => { + testContents([0, 1, 2, 3, 4]) + .then(() => { + info("Testing swap(0, 0)"); + RequestsMenu.swapItemsAtIndices(0, 0); + RequestsMenu.refreshZebra(); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing swap(0, 1)"); + RequestsMenu.swapItemsAtIndices(0, 1); + RequestsMenu.refreshZebra(); + return testContents([1, 0, 2, 3, 4]); + }) + .then(() => { + info("Testing swap(0, 2)"); + RequestsMenu.swapItemsAtIndices(0, 2); + RequestsMenu.refreshZebra(); + return testContents([1, 2, 0, 3, 4]); + }) + .then(() => { + info("Testing swap(0, 3)"); + RequestsMenu.swapItemsAtIndices(0, 3); + RequestsMenu.refreshZebra(); + return testContents([1, 2, 3, 0, 4]); + }) + .then(() => { + info("Testing swap(0, 4)"); + RequestsMenu.swapItemsAtIndices(0, 4); + RequestsMenu.refreshZebra(); + return testContents([1, 2, 3, 4, 0]); + }) + .then(() => { + info("Testing swap(1, 0)"); + RequestsMenu.swapItemsAtIndices(1, 0); + RequestsMenu.refreshZebra(); + return testContents([0, 2, 3, 4, 1]); + }) + .then(() => { + info("Testing swap(1, 1)"); + RequestsMenu.swapItemsAtIndices(1, 1); + RequestsMenu.refreshZebra(); + return testContents([0, 2, 3, 4, 1]); + }) + .then(() => { + info("Testing swap(1, 2)"); + RequestsMenu.swapItemsAtIndices(1, 2); + RequestsMenu.refreshZebra(); + return testContents([0, 1, 3, 4, 2]); + }) + .then(() => { + info("Testing swap(1, 3)"); + RequestsMenu.swapItemsAtIndices(1, 3); + RequestsMenu.refreshZebra(); + return testContents([0, 3, 1, 4, 2]); + }) + .then(() => { + info("Testing swap(1, 4)"); + RequestsMenu.swapItemsAtIndices(1, 4); + RequestsMenu.refreshZebra(); + return testContents([0, 3, 4, 1, 2]); + }) + .then(() => { + info("Testing swap(2, 0)"); + RequestsMenu.swapItemsAtIndices(2, 0); + RequestsMenu.refreshZebra(); + return testContents([2, 3, 4, 1, 0]); + }) + .then(() => { + info("Testing swap(2, 1)"); + RequestsMenu.swapItemsAtIndices(2, 1); + RequestsMenu.refreshZebra(); + return testContents([1, 3, 4, 2, 0]); + }) + .then(() => { + info("Testing swap(2, 2)"); + RequestsMenu.swapItemsAtIndices(2, 2); + RequestsMenu.refreshZebra(); + return testContents([1, 3, 4, 2, 0]); + }) + .then(() => { + info("Testing swap(2, 3)"); + RequestsMenu.swapItemsAtIndices(2, 3); + RequestsMenu.refreshZebra(); + return testContents([1, 2, 4, 3, 0]); + }) + .then(() => { + info("Testing swap(2, 4)"); + RequestsMenu.swapItemsAtIndices(2, 4); + RequestsMenu.refreshZebra(); + return testContents([1, 4, 2, 3, 0]); + }) + .then(() => { + info("Testing swap(3, 0)"); + RequestsMenu.swapItemsAtIndices(3, 0); + RequestsMenu.refreshZebra(); + return testContents([1, 4, 2, 0, 3]); + }) + .then(() => { + info("Testing swap(3, 1)"); + RequestsMenu.swapItemsAtIndices(3, 1); + RequestsMenu.refreshZebra(); + return testContents([3, 4, 2, 0, 1]); + }) + .then(() => { + info("Testing swap(3, 2)"); + RequestsMenu.swapItemsAtIndices(3, 2); + RequestsMenu.refreshZebra(); + return testContents([2, 4, 3, 0, 1]); + }) + .then(() => { + info("Testing swap(3, 3)"); + RequestsMenu.swapItemsAtIndices(3, 3); + RequestsMenu.refreshZebra(); + return testContents([2, 4, 3, 0, 1]); + }) + .then(() => { + info("Testing swap(3, 4)"); + RequestsMenu.swapItemsAtIndices(3, 4); + RequestsMenu.refreshZebra(); + return testContents([2, 3, 4, 0, 1]); + }) + .then(() => { + info("Testing swap(4, 0)"); + RequestsMenu.swapItemsAtIndices(4, 0); + RequestsMenu.refreshZebra(); + return testContents([2, 3, 0, 4, 1]); + }) + .then(() => { + info("Testing swap(4, 1)"); + RequestsMenu.swapItemsAtIndices(4, 1); + RequestsMenu.refreshZebra(); + return testContents([2, 3, 0, 1, 4]); + }) + .then(() => { + info("Testing swap(4, 2)"); + RequestsMenu.swapItemsAtIndices(4, 2); + RequestsMenu.refreshZebra(); + return testContents([4, 3, 0, 1, 2]); + }) + .then(() => { + info("Testing swap(4, 3)"); + RequestsMenu.swapItemsAtIndices(4, 3); + RequestsMenu.refreshZebra(); + return testContents([3, 4, 0, 1, 2]); + }) + .then(() => { + info("Testing swap(4, 4)"); + RequestsMenu.swapItemsAtIndices(4, 4); + RequestsMenu.refreshZebra(); + return testContents([3, 4, 0, 1, 2]); + }) + .then(() => { + info("Clearing sort."); + RequestsMenu.sortBy(); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + }); + + function testContents([a, b, c, d, e]) { + is(RequestsMenu.orderedItems.length, 5, + "There should be a total of 5 items in the requests menu."); + is(RequestsMenu.visibleItems.length, 5, + "There should be a total of 5 visbile items in the requests menu."); + + is(RequestsMenu.getItemAtIndex(0), RequestsMenu.orderedItems[0], + "The requests menu items aren't ordered correctly. First item is misplaced."); + is(RequestsMenu.getItemAtIndex(1), RequestsMenu.orderedItems[1], + "The requests menu items aren't ordered correctly. Second item is misplaced."); + is(RequestsMenu.getItemAtIndex(2), RequestsMenu.orderedItems[2], + "The requests menu items aren't ordered correctly. Third item is misplaced."); + is(RequestsMenu.getItemAtIndex(3), RequestsMenu.orderedItems[3], + "The requests menu items aren't ordered correctly. Fourth item is misplaced."); + is(RequestsMenu.getItemAtIndex(4), RequestsMenu.orderedItems[4], + "The requests menu items aren't ordered correctly. Fifth item is misplaced."); + + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(a), + "GET", STATUS_CODES_SJS + "?sts=100", { + status: 101, + statusText: "Switching Protocols", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(b), + "GET", STATUS_CODES_SJS + "?sts=200", { + status: 202, + statusText: "Created", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(c), + "GET", STATUS_CODES_SJS + "?sts=300", { + status: 303, + statusText: "See Other", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(d), + "GET", STATUS_CODES_SJS + "?sts=400", { + status: 404, + statusText: "Not Found", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(e), + "GET", STATUS_CODES_SJS + "?sts=500", { + status: 501, + statusText: "Not Implemented", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + + return Promise.resolve(null); + } + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_sort-02.js b/browser/devtools/netmonitor/test/browser_net_sort-02.js new file mode 100644 index 000000000..b2e9cfe46 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_sort-02.js @@ -0,0 +1,249 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if sorting columns in the network table works correctly. + */ + +function test() { + initNetMonitor(SORTING_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + // It seems that this test may be slow on debug builds. This could be because + // of the heavy dom manipulation associated with sorting. + requestLongerTimeout(2); + + let { $, L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 5).then(() => { + EventUtils.sendMouseEvent({ type: "mousedown" }, $("#details-pane-toggle")); + + isnot(RequestsMenu.selectedItem, null, + "There should be a selected item in the requests menu."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be selected in the requests menu."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should not be hidden after toggle button was pressed."); + + testHeaders(); + testContents([0, 2, 4, 3, 1]) + .then(() => { + info("Testing status sort, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-status-button")); + testHeaders("status", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing status sort, descending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-status-button")); + testHeaders("status", "descending"); + return testContents([4, 3, 2, 1, 0]); + }) + .then(() => { + info("Testing status sort, ascending. Checking sort loops correctly."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-status-button")); + testHeaders("status", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing method sort, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-method-button")); + testHeaders("method", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing method sort, descending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-method-button")); + testHeaders("method", "descending"); + return testContents([4, 3, 2, 1, 0]); + }) + .then(() => { + info("Testing method sort, ascending. Checking sort loops correctly."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-method-button")); + testHeaders("method", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing file sort, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-file-button")); + testHeaders("file", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing file sort, descending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-file-button")); + testHeaders("file", "descending"); + return testContents([4, 3, 2, 1, 0]); + }) + .then(() => { + info("Testing file sort, ascending. Checking sort loops correctly."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-file-button")); + testHeaders("file", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing type sort, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-type-button")); + testHeaders("type", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing type sort, descending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-type-button")); + testHeaders("type", "descending"); + return testContents([4, 3, 2, 1, 0]); + }) + .then(() => { + info("Testing type sort, ascending. Checking sort loops correctly."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-type-button")); + testHeaders("type", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing size sort, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-size-button")); + testHeaders("size", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing size sort, descending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-size-button")); + testHeaders("size", "descending"); + return testContents([4, 3, 2, 1, 0]); + }) + .then(() => { + info("Testing size sort, ascending. Checking sort loops correctly."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-size-button")); + testHeaders("size", "ascending"); + return testContents([0, 1, 2, 3, 4]); + }) + .then(() => { + info("Testing waterfall sort, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-waterfall-button")); + testHeaders("waterfall", "ascending"); + return testContents([0, 2, 4, 3, 1]); + }) + .then(() => { + info("Testing waterfall sort, descending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-waterfall-button")); + testHeaders("waterfall", "descending"); + return testContents([4, 2, 0, 1, 3]); + }) + .then(() => { + info("Testing waterfall sort, ascending. Checking sort loops correctly."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-waterfall-button")); + testHeaders("waterfall", "ascending"); + return testContents([0, 2, 4, 3, 1]); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + }); + + function testHeaders(aSortType, aDirection) { + let doc = aMonitor.panelWin.document; + let target = doc.querySelector("#requests-menu-" + aSortType + "-button"); + let headers = doc.querySelectorAll(".requests-menu-header-button"); + + for (let header of headers) { + if (header != target) { + is(header.hasAttribute("sorted"), false, + "The " + header.id + " header should not have a 'sorted' attribute."); + is(header.hasAttribute("tooltiptext"), false, + "The " + header.id + " header should not have a 'tooltiptext' attribute."); + } else { + is(header.getAttribute("sorted"), aDirection, + "The " + header.id + " header has an incorrect 'sorted' attribute."); + is(header.getAttribute("tooltiptext"), aDirection == "ascending" + ? L10N.getStr("networkMenu.sortedAsc") + : L10N.getStr("networkMenu.sortedDesc"), + "The " + header.id + " has an incorrect 'tooltiptext' attribute."); + } + } + } + + function testContents([a, b, c, d, e]) { + isnot(RequestsMenu.selectedItem, null, + "There should still be a selected item after sorting."); + is(RequestsMenu.selectedIndex, a, + "The first item should be still selected after sorting."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should still be visible after sorting."); + + is(RequestsMenu.orderedItems.length, 5, + "There should be a total of 5 items in the requests menu."); + is(RequestsMenu.visibleItems.length, 5, + "There should be a total of 5 visbile items in the requests menu."); + + is(RequestsMenu.getItemAtIndex(0), RequestsMenu.orderedItems[0], + "The requests menu items aren't ordered correctly. First item is misplaced."); + is(RequestsMenu.getItemAtIndex(1), RequestsMenu.orderedItems[1], + "The requests menu items aren't ordered correctly. Second item is misplaced."); + is(RequestsMenu.getItemAtIndex(2), RequestsMenu.orderedItems[2], + "The requests menu items aren't ordered correctly. Third item is misplaced."); + is(RequestsMenu.getItemAtIndex(3), RequestsMenu.orderedItems[3], + "The requests menu items aren't ordered correctly. Fourth item is misplaced."); + is(RequestsMenu.getItemAtIndex(4), RequestsMenu.orderedItems[4], + "The requests menu items aren't ordered correctly. Fifth item is misplaced."); + + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(a), + "GET1", SORTING_SJS + "?index=1", { + fuzzyUrl: true, + status: 101, + statusText: "Meh", + type: "1", + fullMimeType: "text/1", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(b), + "GET2", SORTING_SJS + "?index=2", { + fuzzyUrl: true, + status: 200, + statusText: "Meh", + type: "2", + fullMimeType: "text/2", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(c), + "GET3", SORTING_SJS + "?index=3", { + fuzzyUrl: true, + status: 300, + statusText: "Meh", + type: "3", + fullMimeType: "text/3", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(d), + "GET4", SORTING_SJS + "?index=4", { + fuzzyUrl: true, + status: 400, + statusText: "Meh", + type: "4", + fullMimeType: "text/4", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03), + time: true + }); + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(e), + "GET5", SORTING_SJS + "?index=5", { + fuzzyUrl: true, + status: 500, + statusText: "Meh", + type: "5", + fullMimeType: "text/5", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04), + time: true + }); + + return Promise.resolve(null); + } + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_sort-03.js b/browser/devtools/netmonitor/test/browser_net_sort-03.js new file mode 100644 index 000000000..c6f9214bc --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_sort-03.js @@ -0,0 +1,177 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test if sorting columns in the network table works correctly with new requests. + */ + +function test() { + initNetMonitor(SORTING_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + // It seems that this test may be slow on debug builds. This could be because + // of the heavy dom manipulation associated with sorting. + requestLongerTimeout(2); + + let { $, L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + waitForNetworkEvents(aMonitor, 5).then(() => { + EventUtils.sendMouseEvent({ type: "mousedown" }, $("#details-pane-toggle")); + + isnot(RequestsMenu.selectedItem, null, + "There should be a selected item in the requests menu."); + is(RequestsMenu.selectedIndex, 0, + "The first item should be selected in the requests menu."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should not be hidden after toggle button was pressed."); + + testHeaders(); + testContents([0, 2, 4, 3, 1], 0) + .then(() => { + info("Testing status sort, ascending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-status-button")); + testHeaders("status", "ascending"); + return testContents([0, 1, 2, 3, 4], 0); + }) + .then(() => { + info("Performing more requests."); + aDebuggee.performRequests(); + return waitForNetworkEvents(aMonitor, 5); + }) + .then(() => { + info("Testing status sort again, ascending."); + testHeaders("status", "ascending"); + return testContents([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0); + }) + .then(() => { + info("Testing status sort, descending."); + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-status-button")); + testHeaders("status", "descending"); + return testContents([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9); + }) + .then(() => { + info("Performing more requests."); + aDebuggee.performRequests(); + return waitForNetworkEvents(aMonitor, 5); + }) + .then(() => { + info("Testing status sort again, descending."); + testHeaders("status", "descending"); + return testContents([14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 12); + }) + .then(() => { + return teardown(aMonitor); + }) + .then(finish); + }); + + function testHeaders(aSortType, aDirection) { + let doc = aMonitor.panelWin.document; + let target = doc.querySelector("#requests-menu-" + aSortType + "-button"); + let headers = doc.querySelectorAll(".requests-menu-header-button"); + + for (let header of headers) { + if (header != target) { + is(header.hasAttribute("sorted"), false, + "The " + header.id + " header should not have a 'sorted' attribute."); + is(header.hasAttribute("tooltiptext"), false, + "The " + header.id + " header should not have a 'tooltiptext' attribute."); + } else { + is(header.getAttribute("sorted"), aDirection, + "The " + header.id + " header has an incorrect 'sorted' attribute."); + is(header.getAttribute("tooltiptext"), aDirection == "ascending" + ? L10N.getStr("networkMenu.sortedAsc") + : L10N.getStr("networkMenu.sortedDesc"), + "The " + header.id + " has an incorrect 'tooltiptext' attribute."); + } + } + } + + function testContents(aOrder, aSelection) { + isnot(RequestsMenu.selectedItem, null, + "There should still be a selected item after sorting."); + is(RequestsMenu.selectedIndex, aSelection, + "The first item should be still selected after sorting."); + is(NetMonitorView.detailsPaneHidden, false, + "The details pane should still be visible after sorting."); + + is(RequestsMenu.orderedItems.length, aOrder.length, + "There should be a specific number of items in the requests menu."); + is(RequestsMenu.visibleItems.length, aOrder.length, + "There should be a specific number of visbile items in the requests menu."); + + for (let i = 0; i < aOrder.length; i++) { + is(RequestsMenu.getItemAtIndex(i), RequestsMenu.orderedItems[i], + "The requests menu items aren't ordered correctly. Misplaced item " + i + "."); + } + + for (let i = 0, len = aOrder.length / 5; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i]), + "GET1", SORTING_SJS + "?index=1", { + fuzzyUrl: true, + status: 101, + statusText: "Meh", + type: "1", + fullMimeType: "text/1", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0), + time: true + }); + } + for (let i = 0, len = aOrder.length / 5; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len]), + "GET2", SORTING_SJS + "?index=2", { + fuzzyUrl: true, + status: 200, + statusText: "Meh", + type: "2", + fullMimeType: "text/2", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01), + time: true + }); + } + for (let i = 0, len = aOrder.length / 5; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 2]), + "GET3", SORTING_SJS + "?index=3", { + fuzzyUrl: true, + status: 300, + statusText: "Meh", + type: "3", + fullMimeType: "text/3", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + } + for (let i = 0, len = aOrder.length / 5; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 3]), + "GET4", SORTING_SJS + "?index=4", { + fuzzyUrl: true, + status: 400, + statusText: "Meh", + type: "4", + fullMimeType: "text/4", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03), + time: true + }); + } + for (let i = 0, len = aOrder.length / 5; i < len; i++) { + verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 4]), + "GET5", SORTING_SJS + "?index=5", { + fuzzyUrl: true, + status: 500, + statusText: "Meh", + type: "5", + fullMimeType: "text/5", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04), + time: true + }); + } + + return Promise.resolve(null); + } + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_status-codes.js b/browser/devtools/netmonitor/test/browser_net_status-codes.js new file mode 100644 index 000000000..0e62f8071 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_status-codes.js @@ -0,0 +1,155 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if requests display the correct status code and text in the UI. + */ + +function test() { + initNetMonitor(STATUS_CODES_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu, NetworkDetails } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + NetworkDetails._params.lazyEmpty = false; + + waitForNetworkEvents(aMonitor, 5).then(() => { + let requestItems = []; + + verifyRequestItemTarget(requestItems[0] = RequestsMenu.getItemAtIndex(0), + "GET", STATUS_CODES_SJS + "?sts=100", { + status: 101, + statusText: "Switching Protocols", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0), + time: true + }); + verifyRequestItemTarget(requestItems[1] = RequestsMenu.getItemAtIndex(1), + "GET", STATUS_CODES_SJS + "?sts=200", { + status: 202, + statusText: "Created", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + verifyRequestItemTarget(requestItems[2] = RequestsMenu.getItemAtIndex(2), + "GET", STATUS_CODES_SJS + "?sts=300", { + status: 303, + statusText: "See Other", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0), + time: true + }); + verifyRequestItemTarget(requestItems[3] = RequestsMenu.getItemAtIndex(3), + "GET", STATUS_CODES_SJS + "?sts=400", { + status: 404, + statusText: "Not Found", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + verifyRequestItemTarget(requestItems[4] = RequestsMenu.getItemAtIndex(4), + "GET", STATUS_CODES_SJS + "?sts=500", { + status: 501, + statusText: "Not Implemented", + type: "plain", + fullMimeType: "text/plain; charset=utf-8", + size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02), + time: true + }); + + // Test summaries... + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[0]); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[0].target); + testSummary("GET", STATUS_CODES_SJS + "?sts=100", "101", "Switching Protocols"); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[1].target); + testSummary("GET", STATUS_CODES_SJS + "?sts=200", "202", "Created"); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[2].target); + testSummary("GET", STATUS_CODES_SJS + "?sts=300", "303", "See Other"); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[3].target); + testSummary("GET", STATUS_CODES_SJS + "?sts=400", "404", "Not Found"); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[4].target); + testSummary("GET", STATUS_CODES_SJS + "?sts=500", "501", "Not Implemented"); + + // Test params... + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll("#details-pane tab")[2]); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[0].target); + testParamsTab("\"100\""); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[1].target); + testParamsTab("\"200\""); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[2].target); + testParamsTab("\"300\""); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[3].target); + testParamsTab("\"400\""); + + EventUtils.sendMouseEvent({ type: "mousedown" }, requestItems[4].target); + testParamsTab("\"500\""); + + // We're done here. + teardown(aMonitor).then(finish); + + function testSummary(aMethod, aUrl, aStatus, aStatusText) { + let tab = document.querySelectorAll("#details-pane tab")[0]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[0]; + + is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"), + aUrl, "The url summary value is incorrect."); + is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"), + aMethod, "The method summary value is incorrect."); + is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("code"), + aStatus, "The status summary code is incorrect."); + is(tabpanel.querySelector("#headers-summary-status-value").getAttribute("value"), + aStatus + " " + aStatusText, "The status summary value is incorrect."); + } + + function testParamsTab(aStatusParamValue) { + let tab = document.querySelectorAll("#details-pane tab")[2]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2]; + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 1, + "There should be 1 param scope displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variable-or-property").length, 1, + "There should be 1 param value displayed in this tabpanel."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0, + "The empty notice should not be displayed in this tabpanel."); + + let paramsScope = tabpanel.querySelectorAll(".variables-view-scope")[0]; + + is(paramsScope.querySelector(".name").getAttribute("value"), + L10N.getStr("paramsQueryString"), + "The params scope doesn't have the correct title."); + + is(paramsScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"), + "sts", "The param name was incorrect."); + is(paramsScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"), + aStatusParamValue, "The param value was incorrect."); + + is(tabpanel.querySelector("#request-params-box") + .hasAttribute("hidden"), false, + "The request params box should not be hidden."); + is(tabpanel.querySelector("#request-post-data-textarea-box") + .hasAttribute("hidden"), true, + "The request post data textarea box should be hidden."); + } + }); + + aDebuggee.performRequests(); + }); +} diff --git a/browser/devtools/netmonitor/test/browser_net_timeline_ticks.js b/browser/devtools/netmonitor/test/browser_net_timeline_ticks.js new file mode 100644 index 000000000..a56bff992 --- /dev/null +++ b/browser/devtools/netmonitor/test/browser_net_timeline_ticks.js @@ -0,0 +1,135 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if timeline correctly displays interval divisions. + */ + +function test() { + initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => { + info("Starting test... "); + + let { document, L10N, NetMonitorView } = aMonitor.panelWin; + let { RequestsMenu } = NetMonitorView; + + RequestsMenu.lazyUpdate = false; + + ok(document.querySelector("#requests-menu-waterfall-label"), + "An timeline label should be displayed when the frontend is opened."); + ok(document.querySelectorAll(".requests-menu-timings-division").length == 0, + "No tick labels should be displayed when the frontend is opened."); + + ok(!RequestsMenu._canvas, + "No canvas should be created when the frontend is opened."); + ok(!RequestsMenu._ctx, + "No 2d context should be created when the frontend is opened."); + + waitForNetworkEvents(aMonitor, 1).then(() => { + ok(!document.querySelector("#requests-menu-waterfall-label"), + "The timeline label should be hidden after the first request."); + ok(document.querySelectorAll(".requests-menu-timings-division").length >= 3, + "There should be at least 3 tick labels in the network requests header."); + + is(document.querySelectorAll(".requests-menu-timings-division")[0] + .getAttribute("value"), L10N.getFormatStr("networkMenu.divisionMS", 0), + "The first tick label has an incorrect value"); + is(document.querySelectorAll(".requests-menu-timings-division")[1] + .getAttribute("value"), L10N.getFormatStr("networkMenu.divisionMS", 80), + "The second tick label has an incorrect value"); + is(document.querySelectorAll(".requests-menu-timings-division")[2] + .getAttribute("value"), L10N.getFormatStr("networkMenu.divisionMS", 160), + "The third tick label has an incorrect value"); + + is(document.querySelectorAll(".requests-menu-timings-division")[0] + .style.transform, "translateX(0px)", + "The first tick label has an incorrect translation"); + is(document.querySelectorAll(".requests-menu-timings-division")[1] + .style.transform, "translateX(80px)", + "The second tick label has an incorrect translation"); + is(document.querySelectorAll(".requests-menu-timings-division")[2] + .style.transform, "translateX(160px)", + "The third tick label has an incorrect translation"); + + ok(RequestsMenu._canvas, + "A canvas should be created after the first request."); + ok(RequestsMenu._ctx, + "A 2d context should be created after the first request."); + + let imageData = RequestsMenu._ctx.getImageData(0, 0, 161, 1); + ok(imageData, "The image data should have been created."); + + let data = imageData.data; + ok(data, "The image data should contain a pixel array."); + + ok( hasPixelAt(0), "The tick at 0 is should not be empty."); + ok(!hasPixelAt(1), "The tick at 1 is should be empty."); + ok(!hasPixelAt(19), "The tick at 19 is should be empty."); + ok( hasPixelAt(20), "The tick at 20 is should not be empty."); + ok(!hasPixelAt(21), "The tick at 21 is should be empty."); + ok(!hasPixelAt(39), "The tick at 39 is should be empty."); + ok( hasPixelAt(40), "The tick at 40 is should not be empty."); + ok(!hasPixelAt(41), "The tick at 41 is should be empty."); + ok(!hasPixelAt(59), "The tick at 59 is should be empty."); + ok( hasPixelAt(60), "The tick at 60 is should not be empty."); + ok(!hasPixelAt(61), "The tick at 61 is should be empty."); + ok(!hasPixelAt(79), "The tick at 79 is should be empty."); + ok( hasPixelAt(80), "The tick at 80 is should not be empty."); + ok(!hasPixelAt(81), "The tick at 81 is should be empty."); + ok(!hasPixelAt(159), "The tick at 159 is should be empty."); + ok( hasPixelAt(160), "The tick at 160 is should not be empty."); + ok(!hasPixelAt(161), "The tick at 161 is should be empty."); + + ok(isPixelBrighterAtThan(0, 20), + "The tick at 0 should be brighter than the one at 20"); + ok(isPixelBrighterAtThan(40, 20), + "The tick at 40 should be brighter than the one at 20"); + ok(isPixelBrighterAtThan(40, 60), + "The tick at 40 should be brighter than the one at 60"); + ok(isPixelBrighterAtThan(80, 60), + "The tick at 80 should be brighter than the one at 60"); + + ok(isPixelBrighterAtThan(80, 100), + "The tick at 80 should be brighter than the one at 100"); + ok(isPixelBrighterAtThan(120, 100), + "The tick at 120 should be brighter than the one at 100"); + ok(isPixelBrighterAtThan(120, 140), + "The tick at 120 should be brighter than the one at 140"); + ok(isPixelBrighterAtThan(160, 140), + "The tick at 160 should be brighter than the one at 140"); + + ok(isPixelEquallyBright(20, 60), + "The tick at 20 should be equally bright to the one at 60"); + ok(isPixelEquallyBright(100, 140), + "The tick at 100 should be equally bright to the one at 140"); + + ok(isPixelEquallyBright(40, 120), + "The tick at 40 should be equally bright to the one at 120"); + + ok(isPixelEquallyBright(0, 80), + "The tick at 80 should be equally bright to the one at 160"); + ok(isPixelEquallyBright(80, 160), + "The tick at 80 should be equally bright to the one at 160"); + + function hasPixelAt(x) { + let i = (x | 0) * 4; + return data[i] && data[i + 1] && data[i + 2] && data[i + 3]; + } + + function isPixelBrighterAtThan(x1, x2) { + let i = (x1 | 0) * 4; + let j = (x2 | 0) * 4; + return data[i + 3] > data [j + 3]; + } + + function isPixelEquallyBright(x1, x2) { + let i = (x1 | 0) * 4; + let j = (x2 | 0) * 4; + return data[i + 3] == data [j + 3]; + } + + teardown(aMonitor).then(finish); + }); + + aDebuggee.location.reload(); + }); +} diff --git a/browser/devtools/netmonitor/test/head.js b/browser/devtools/netmonitor/test/head.js new file mode 100644 index 000000000..dca1dc3cc --- /dev/null +++ b/browser/devtools/netmonitor/test/head.js @@ -0,0 +1,283 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; + +let { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); +let { Promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}); +let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}); +let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); +let TargetFactory = devtools.TargetFactory; +let Toolbox = devtools.Toolbox; + +const EXAMPLE_URL = "http://example.com/browser/browser/devtools/netmonitor/test/"; + +const SIMPLE_URL = EXAMPLE_URL + "html_simple-test-page.html"; +const NAVIGATE_URL = EXAMPLE_URL + "html_navigate-test-page.html"; +const CONTENT_TYPE_URL = EXAMPLE_URL + "html_content-type-test-page.html"; +const CYRILLIC_URL = EXAMPLE_URL + "html_cyrillic-test-page.html"; +const STATUS_CODES_URL = EXAMPLE_URL + "html_status-codes-test-page.html"; +const POST_DATA_URL = EXAMPLE_URL + "html_post-data-test-page.html"; +const POST_RAW_URL = EXAMPLE_URL + "html_post-raw-test-page.html"; +const JSONP_URL = EXAMPLE_URL + "html_jsonp-test-page.html"; +const JSON_LONG_URL = EXAMPLE_URL + "html_json-long-test-page.html"; +const JSON_MALFORMED_URL = EXAMPLE_URL + "html_json-malformed-test-page.html"; +const SORTING_URL = EXAMPLE_URL + "html_sorting-test-page.html"; +const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html"; +const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html"; +const CUSTOM_GET_URL = EXAMPLE_URL + "html_custom-get-page.html"; + +const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs"; +const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs"; +const STATUS_CODES_SJS = EXAMPLE_URL + "sjs_status-codes-test-server.sjs"; +const SORTING_SJS = EXAMPLE_URL + "sjs_sorting-test-server.sjs"; + +const TEST_IMAGE = EXAMPLE_URL + "test-image.png"; + +// All tests are asynchronous. +waitForExplicitFinish(); + +// Enable logging for all the relevant tests. +let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log"); +Services.prefs.setBoolPref("devtools.debugger.log", true); + +registerCleanupFunction(() => { + info("finish() was called, cleaning up..."); + Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging); +}); + +function addTab(aUrl, aWindow) { + info("Adding tab: " + aUrl); + + let deferred = Promise.defer(); + let targetWindow = aWindow || window; + let targetBrowser = targetWindow.gBrowser; + + targetWindow.focus(); + let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl); + let browser = tab.linkedBrowser; + + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); + deferred.resolve(tab); + }, true); + + return deferred.promise; +} + +function removeTab(aTab, aWindow) { + info("Removing tab."); + + let targetWindow = aWindow || window; + let targetBrowser = targetWindow.gBrowser; + + targetBrowser.removeTab(aTab); +} + +function initNetMonitor(aUrl, aWindow) { + info("Initializing a network monitor pane."); + + return addTab(aUrl).then((aTab) => { + info("Net tab added successfully: " + aUrl); + + let deferred = Promise.defer(); + let debuggee = aTab.linkedBrowser.contentWindow.wrappedJSObject; + let target = TargetFactory.forTab(aTab); + + gDevTools.showToolbox(target, "netmonitor").then((aToolbox) => { + info("Netork monitor pane shown successfully."); + + let monitor = aToolbox.getCurrentPanel(); + deferred.resolve([aTab, debuggee, monitor]); + }); + + return deferred.promise; + }); +} + +function restartNetMonitor(aMonitor, aNewUrl) { + info("Restarting the specified network monitor."); + + let deferred = Promise.defer(); + let tab = aMonitor.target.tab; + let url = aNewUrl || tab.linkedBrowser.contentWindow.wrappedJSObject.location.href; + + aMonitor.once("destroyed", () => initNetMonitor(url).then(deferred.resolve)); + removeTab(tab); + + return deferred.promise; +} + +function teardown(aMonitor) { + info("Destroying the specified network monitor."); + + let deferred = Promise.defer(); + let tab = aMonitor.target.tab; + + aMonitor.once("destroyed", () => executeSoon(deferred.resolve)); + removeTab(tab); + + return deferred.promise; +} + +function waitForNetworkEvents(aMonitor, aGetRequests, aPostRequests = 0) { + let deferred = Promise.defer(); + + let panel = aMonitor.panelWin; + let genericEvents = 0; + let postEvents = 0; + + function onGenericEvent() { + genericEvents++; + maybeResolve(); + } + + function onPostEvent() { + postEvents++; + maybeResolve(); + } + + function maybeResolve() { + info("> Network events progress: " + + genericEvents + "/" + ((aGetRequests + aPostRequests) * 13) + ", " + + postEvents + "/" + (aPostRequests * 2)); + + // There are 15 updates which need to be fired for a request to be + // considered finished. RequestPostData isn't fired for non-POST requests. + if (genericEvents == (aGetRequests + aPostRequests) * 13 && + postEvents == aPostRequests * 2) { + + panel.off("NetMonitor:NetworkEventUpdating:RequestHeaders", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdated:RequestHeaders", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdating:RequestCookies", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdating:RequestPostData", onPostEvent); + panel.off("NetMonitor:NetworkEventUpdated:RequestPostData", onPostEvent); + panel.off("NetMonitor:NetworkEventUpdated:RequestCookies", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdating:ResponseHeaders", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdated:ResponseHeaders", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdating:ResponseCookies", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdated:ResponseCookies", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdating:ResponseStart", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdating:ResponseContent", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdated:ResponseContent", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdating:EventTimings", onGenericEvent); + panel.off("NetMonitor:NetworkEventUpdated:EventTimings", onGenericEvent); + + executeSoon(deferred.resolve); + } + } + + panel.on("NetMonitor:NetworkEventUpdating:RequestHeaders", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdated:RequestHeaders", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdating:RequestCookies", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdating:RequestPostData", onPostEvent); + panel.on("NetMonitor:NetworkEventUpdated:RequestPostData", onPostEvent); + panel.on("NetMonitor:NetworkEventUpdated:RequestCookies", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdating:ResponseHeaders", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdated:ResponseHeaders", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdating:ResponseCookies", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdated:ResponseCookies", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdating:ResponseStart", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdating:ResponseContent", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdated:ResponseContent", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdating:EventTimings", onGenericEvent); + panel.on("NetMonitor:NetworkEventUpdated:EventTimings", onGenericEvent); + + return deferred.promise; +} + +function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) { + info("> Verifying: " + aMethod + " " + aUrl + " " + aData.toSource()); + info("> Request: " + aRequestItem.attachment.toSource()); + + let requestsMenu = aRequestItem.ownerView; + let widgetIndex = requestsMenu.indexOfItem(aRequestItem); + let visibleIndex = requestsMenu.orderedVisibleItems.indexOf(aRequestItem); + + info("Widget index of item: " + widgetIndex); + info("Visible index of item: " + visibleIndex); + + let { fuzzyUrl, status, statusText, type, fullMimeType, size, time } = aData; + let { attachment, target } = aRequestItem + + let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL); + let name = uri.fileName || "/"; + let query = uri.query; + let hostPort = uri.hostPort; + + if (fuzzyUrl) { + ok(attachment.method.startsWith(aMethod), "The attached method is incorrect."); + ok(attachment.url.startsWith(aUrl), "The attached url is incorrect."); + } else { + is(attachment.method, aMethod, "The attached method is incorrect."); + is(attachment.url, aUrl, "The attached url is incorrect."); + } + + is(target.querySelector(".requests-menu-method").getAttribute("value"), + aMethod, "The displayed method is incorrect."); + + if (fuzzyUrl) { + ok(target.querySelector(".requests-menu-file").getAttribute("value").startsWith( + name + (query ? "?" + query : "")), "The displayed file is incorrect."); + ok(target.querySelector(".requests-menu-file").getAttribute("tooltiptext").startsWith( + name + (query ? "?" + query : "")), "The tooltip file is incorrect."); + } else { + is(target.querySelector(".requests-menu-file").getAttribute("value"), + name + (query ? "?" + query : ""), "The displayed file is incorrect."); + is(target.querySelector(".requests-menu-file").getAttribute("tooltiptext"), + name + (query ? "?" + query : ""), "The tooltip file is incorrect."); + } + + is(target.querySelector(".requests-menu-domain").getAttribute("value"), + hostPort, "The displayed domain is incorrect."); + is(target.querySelector(".requests-menu-domain").getAttribute("tooltiptext"), + hostPort, "The tooltip domain is incorrect."); + + if (status !== undefined) { + let value = target.querySelector(".requests-menu-status").getAttribute("code"); + let tooltip = target.querySelector(".requests-menu-status-and-method").getAttribute("tooltiptext"); + info("Displayed status: " + value); + info("Tooltip status: " + tooltip); + is(value, status, "The displayed status is incorrect."); + is(tooltip, status + " " + statusText, "The tooltip status is incorrect."); + } + if (type !== undefined) { + let value = target.querySelector(".requests-menu-type").getAttribute("value"); + let tooltip = target.querySelector(".requests-menu-type").getAttribute("tooltiptext"); + info("Displayed type: " + value); + info("Tooltip type: " + tooltip); + is(value, type, "The displayed type is incorrect."); + is(tooltip, fullMimeType, "The tooltip type is incorrect."); + } + if (size !== undefined) { + let value = target.querySelector(".requests-menu-size").getAttribute("value"); + let tooltip = target.querySelector(".requests-menu-size").getAttribute("tooltiptext"); + info("Displayed size: " + value); + info("Tooltip size: " + tooltip); + is(value, size, "The displayed size is incorrect."); + is(tooltip, size, "The tooltip size is incorrect."); + } + if (time !== undefined) { + let value = target.querySelector(".requests-menu-timings-total").getAttribute("value"); + let tooltip = target.querySelector(".requests-menu-timings-total").getAttribute("tooltiptext"); + info("Displayed time: " + value); + info("Tooltip time: " + tooltip); + ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is incorrect."); + ok(~~(tooltip.match(/[0-9]+/)) >= 0, "The tooltip time is incorrect."); + } + + if (visibleIndex != -1) { + if (visibleIndex % 2 == 0) { + ok(aRequestItem.target.hasAttribute("even"), + "Unexpected 'even' attribute for " + aRequestItem.value); + ok(!aRequestItem.target.hasAttribute("odd"), + "Unexpected 'odd' attribute for " + aRequestItem.value); + } else { + ok(!aRequestItem.target.hasAttribute("even"), + "Unexpected 'even' attribute for " + aRequestItem.value); + ok(aRequestItem.target.hasAttribute("odd"), + "Unexpected 'odd' attribute for " + aRequestItem.value); + } + } +} diff --git a/browser/devtools/netmonitor/test/html_content-type-test-page.html b/browser/devtools/netmonitor/test/html_content-type-test-page.html new file mode 100644 index 000000000..506ba21c1 --- /dev/null +++ b/browser/devtools/netmonitor/test/html_content-type-test-page.html @@ -0,0 +1,43 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Content type test</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests() { + get("sjs_content-type-test-server.sjs?fmt=xml", function() { + get("sjs_content-type-test-server.sjs?fmt=css", function() { + get("sjs_content-type-test-server.sjs?fmt=js", function() { + get("sjs_content-type-test-server.sjs?fmt=json", function() { + get("sjs_content-type-test-server.sjs?fmt=bogus", function() { + get("test-image.png", function() { + // Done. + }); + }); + }); + }); + }); + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_custom-get-page.html b/browser/devtools/netmonitor/test/html_custom-get-page.html new file mode 100644 index 000000000..b01ae09eb --- /dev/null +++ b/browser/devtools/netmonitor/test/html_custom-get-page.html @@ -0,0 +1,39 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Performing a custom number of GETs</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + // Use a count parameter to defeat caching. + var count = 0; + + function performRequests(aTotal, aUrl, aTimeout = 0) { + if (!aTotal) { + return; + } + get(aUrl || "request_" + (count++), function() { + setTimeout(performRequests.bind(this, --aTotal, aUrl, aTimeout), aTimeout); + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_cyrillic-test-page.html b/browser/devtools/netmonitor/test/html_cyrillic-test-page.html new file mode 100644 index 000000000..b9a0dc9d0 --- /dev/null +++ b/browser/devtools/netmonitor/test/html_cyrillic-test-page.html @@ -0,0 +1,34 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Cyrillic type test</p> + <p>Братан, ты вообще качаешься?</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests() { + get("sjs_content-type-test-server.sjs?fmt=txt", function() { + // Done. + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_filter-test-page.html b/browser/devtools/netmonitor/test/html_filter-test-page.html new file mode 100644 index 000000000..6719991d9 --- /dev/null +++ b/browser/devtools/netmonitor/test/html_filter-test-page.html @@ -0,0 +1,55 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Filtering test</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + // Use a random parameter to defeat caching. + xhr.open("GET", aAddress + "&" + Math.random(), true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests(aOptions) { + var options = JSON.parse(aOptions); + get("sjs_content-type-test-server.sjs?fmt=html&res=" + options.htmlContent, function() { + get("sjs_content-type-test-server.sjs?fmt=css", function() { + get("sjs_content-type-test-server.sjs?fmt=js", function() { + if (!options.getMedia) { + return; + } + get("sjs_content-type-test-server.sjs?fmt=font", function() { + get("sjs_content-type-test-server.sjs?fmt=image", function() { + get("sjs_content-type-test-server.sjs?fmt=audio", function() { + get("sjs_content-type-test-server.sjs?fmt=video", function() { + if (!options.getFlash) { + return; + } + get("sjs_content-type-test-server.sjs?fmt=flash", function() { + // Done. + }); + }); + }); + }); + }); + }); + }); + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_infinite-get-page.html b/browser/devtools/netmonitor/test/html_infinite-get-page.html new file mode 100644 index 000000000..882dc57de --- /dev/null +++ b/browser/devtools/netmonitor/test/html_infinite-get-page.html @@ -0,0 +1,36 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Infinite GETs</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + // Use a count parameter to defeat caching. + var count = 0; + + (function performRequests() { + get("request_" + (count++), function() { + setTimeout(performRequests, 50); + }); + })(); + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_json-long-test-page.html b/browser/devtools/netmonitor/test/html_json-long-test-page.html new file mode 100644 index 000000000..4889d76c7 --- /dev/null +++ b/browser/devtools/netmonitor/test/html_json-long-test-page.html @@ -0,0 +1,33 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>JSON long string test</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests() { + get("sjs_content-type-test-server.sjs?fmt=json-long", function() { + // Done. + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_json-malformed-test-page.html b/browser/devtools/netmonitor/test/html_json-malformed-test-page.html new file mode 100644 index 000000000..3c47c797f --- /dev/null +++ b/browser/devtools/netmonitor/test/html_json-malformed-test-page.html @@ -0,0 +1,33 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>JSON malformed test</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests() { + get("sjs_content-type-test-server.sjs?fmt=json-malformed", function() { + // Done. + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_jsonp-test-page.html b/browser/devtools/netmonitor/test/html_jsonp-test-page.html new file mode 100644 index 000000000..7cf0c6bbb --- /dev/null +++ b/browser/devtools/netmonitor/test/html_jsonp-test-page.html @@ -0,0 +1,33 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>JSONP test</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests() { + get("sjs_content-type-test-server.sjs?fmt=jsonp&jsonp=$_0123Fun", function() { + // Done. + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_navigate-test-page.html b/browser/devtools/netmonitor/test/html_navigate-test-page.html new file mode 100644 index 000000000..69284120a --- /dev/null +++ b/browser/devtools/netmonitor/test/html_navigate-test-page.html @@ -0,0 +1,13 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Navigation test</p> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_post-data-test-page.html b/browser/devtools/netmonitor/test/html_post-data-test-page.html new file mode 100644 index 000000000..4be478226 --- /dev/null +++ b/browser/devtools/netmonitor/test/html_post-data-test-page.html @@ -0,0 +1,72 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + <style> + input { + display: block; + margin: 12px; + } + </style> + </head> + + <body> + <p>POST data test</p> + <form enctype="multipart/form-data" method="post" name="form-name"> + <input type="text" name="text" placeholder="text" value="Some text..."/> + <input type="email" name="email" placeholder="email"/> + <input type="range" name="range" value="42"/> + <input type="button" value="Post me!" onclick="window.form()"> + </form> + + <script type="text/javascript"> + function post(aAddress, aMessage, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("POST", aAddress, true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + + var data = ""; + for (var i in aMessage) { + data += "&" + i + "=" + aMessage[i]; + } + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(data); + } + + function form(aAddress, aForm, aCallback) { + var formData = new FormData(document.forms.namedItem(aForm)); + formData.append("Custom field", "Extra data"); + + var xhr = new XMLHttpRequest(); + xhr.open("POST", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(formData); + } + + function performRequests() { + var url = "sjs_simple-test-server.sjs"; + var url1 = url + "?foo=bar&baz=42&type=urlencoded"; + var url2 = url + "?foo=bar&baz=42&type=multipart"; + + post(url1, { foo: "bar", baz: 123 }, function() { + form(url2, "form-name", function() { + // Done. + }); + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_post-raw-test-page.html b/browser/devtools/netmonitor/test/html_post-raw-test-page.html new file mode 100644 index 000000000..b3148a77e --- /dev/null +++ b/browser/devtools/netmonitor/test/html_post-raw-test-page.html @@ -0,0 +1,34 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>POST raw test</p> + + <script type="text/javascript"> + function post(aAddress, aMessage, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("POST", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(aMessage); + } + + function performRequests() { + var rawData = "Content-Type: application/x-www-form-urlencoded\r\n\r\nfoo=bar&baz=123"; + post("sjs_simple-test-server.sjs", rawData, function() { + // Done. + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_simple-test-page.html b/browser/devtools/netmonitor/test/html_simple-test-page.html new file mode 100644 index 000000000..a8eae55bf --- /dev/null +++ b/browser/devtools/netmonitor/test/html_simple-test-page.html @@ -0,0 +1,13 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Simple test</p> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_sorting-test-page.html b/browser/devtools/netmonitor/test/html_sorting-test-page.html new file mode 100644 index 000000000..9326ded2d --- /dev/null +++ b/browser/devtools/netmonitor/test/html_sorting-test-page.html @@ -0,0 +1,42 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Sorting test</p> + + <script type="text/javascript"> + function get(aAddress, aIndex, aCallback) { + var xhr = new XMLHttpRequest(); + // Use a random parameter to defeat caching. + xhr.open("GET" + aIndex, aAddress + "?index=" + aIndex + "&" + Math.random(), true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests() { + get("sjs_sorting-test-server.sjs", 1, function() { + get("sjs_sorting-test-server.sjs", 5, function() { + get("sjs_sorting-test-server.sjs", 2, function() { + get("sjs_sorting-test-server.sjs", 4, function() { + get("sjs_sorting-test-server.sjs", 3, function() { + // Done. + }); + }); + }); + }); + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/html_status-codes-test-page.html b/browser/devtools/netmonitor/test/html_status-codes-test-page.html new file mode 100644 index 000000000..f19570e71 --- /dev/null +++ b/browser/devtools/netmonitor/test/html_status-codes-test-page.html @@ -0,0 +1,41 @@ +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Network Monitor test page</title> + </head> + + <body> + <p>Status codes test</p> + + <script type="text/javascript"> + function get(aAddress, aCallback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aAddress, true); + + xhr.onreadystatechange = function() { + if (this.readyState == this.DONE) { + aCallback(); + } + }; + xhr.send(null); + } + + function performRequests() { + get("sjs_status-codes-test-server.sjs?sts=100", function() { + get("sjs_status-codes-test-server.sjs?sts=200", function() { + get("sjs_status-codes-test-server.sjs?sts=300", function() { + get("sjs_status-codes-test-server.sjs?sts=400", function() { + get("sjs_status-codes-test-server.sjs?sts=500", function() { + // Done. + }); + }); + }); + }); + }); + } + </script> + </body> + +</html> diff --git a/browser/devtools/netmonitor/test/moz.build b/browser/devtools/netmonitor/test/moz.build new file mode 100644 index 000000000..58ce5e273 --- /dev/null +++ b/browser/devtools/netmonitor/test/moz.build @@ -0,0 +1,5 @@ +# 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/netmonitor/test/sjs_content-type-test-server.sjs b/browser/devtools/netmonitor/test/sjs_content-type-test-server.sjs new file mode 100644 index 000000000..a0cb4ec65 --- /dev/null +++ b/browser/devtools/netmonitor/test/sjs_content-type-test-server.sjs @@ -0,0 +1,127 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { classes: Cc, interfaces: Ci } = Components; + +function handleRequest(request, response) { + response.processAsync(); + + let params = request.queryString.split("&"); + let format = params.filter((s) => s.contains("fmt="))[0].split("=")[1]; + + Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer).initWithCallback(() => { + switch (format) { + case "txt": { + response.setStatusLine(request.httpVersion, 200, "DA DA DA"); + response.setHeader("Content-Type", "text/plain", false); + response.write("Братан, ты вообще качаешься?"); + response.finish(); + break; + } + case "xml": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/xml; charset=utf-8", false); + response.write("<label value='greeting'>Hello XML!</label>"); + response.finish(); + break; + } + case "html": { + let content = params.filter((s) => s.contains("res="))[0].split("=")[1]; + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.write(content || "<p>Hello HTML!</p>"); + response.finish(); + break; + } + case "html-long": { + let str = new Array(102400 /* 100 KB in bytes */).join("."); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.write("<p>" + str + "</p>"); + response.finish(); + break; + } + case "css": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/css; charset=utf-8", false); + response.write("body:pre { content: 'Hello CSS!' }"); + response.finish(); + break; + } + case "js": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "application/javascript; charset=utf-8", false); + response.write("function() { return 'Hello JS!'; }"); + response.finish(); + break; + } + case "json": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "application/json; charset=utf-8", false); + response.write("{ \"greeting\": \"Hello JSON!\" }"); + response.finish(); + break; + } + case "jsonp": { + let fun = params.filter((s) => s.contains("jsonp="))[0].split("=")[1]; + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/json; charset=utf-8", false); + response.write(fun + "({ \"greeting\": \"Hello JSONP!\" })"); + response.finish(); + break; + } + case "json-long": { + let str = "{ \"greeting\": \"Hello long string JSON!\" },"; + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/json; charset=utf-8", false); + response.write("[" + new Array(2048).join(str).slice(0, -1) + "]"); + response.finish(); + break; + } + case "json-malformed": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/json; charset=utf-8", false); + response.write("{ \"greeting\": \"Hello malformed JSON!\" },"); + response.finish(); + break; + } + case "font": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "font/woff", false); + response.finish(); + break; + } + case "image": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "image/png", false); + response.finish(); + break; + } + case "audio": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "audio/ogg", false); + response.finish(); + break; + } + case "video": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "video/webm", false); + response.finish(); + break; + } + case "flash": { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "application/x-shockwave-flash", false); + response.finish(); + break; + } + default: { + response.setStatusLine(request.httpVersion, 404, "Not Found"); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.write("<blink>Not Found</blink>"); + response.finish(); + break; + } + } + }, 10, Ci.nsITimer.TYPE_ONE_SHOT); // Make sure this request takes a few ms. +} diff --git a/browser/devtools/netmonitor/test/sjs_simple-test-server.sjs b/browser/devtools/netmonitor/test/sjs_simple-test-server.sjs new file mode 100644 index 000000000..15fe9f8ae --- /dev/null +++ b/browser/devtools/netmonitor/test/sjs_simple-test-server.sjs @@ -0,0 +1,9 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(request, response) { + response.setStatusLine(request.httpVersion, 200, "Och Aye"); + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + response.setHeader("Foo-Bar", "baz", false); + response.write("Hello world!"); +} diff --git a/browser/devtools/netmonitor/test/sjs_sorting-test-server.sjs b/browser/devtools/netmonitor/test/sjs_sorting-test-server.sjs new file mode 100644 index 000000000..fd31b3266 --- /dev/null +++ b/browser/devtools/netmonitor/test/sjs_sorting-test-server.sjs @@ -0,0 +1,18 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { classes: Cc, interfaces: Ci } = Components; + +function handleRequest(request, response) { + response.processAsync(); + + let params = request.queryString.split("&"); + let index = params.filter((s) => s.contains("index="))[0].split("=")[1]; + + Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer).initWithCallback(() => { + response.setStatusLine(request.httpVersion, index == 1 ? 101 : index * 100, "Meh"); + response.setHeader("Content-Type", "text/" + index, false); + response.write(new Array(index * 10).join(index)); // + 0.01 KB + response.finish(); + }, 10, Ci.nsITimer.TYPE_ONE_SHOT); // Make sure this request takes a few ms. +} diff --git a/browser/devtools/netmonitor/test/sjs_status-codes-test-server.sjs b/browser/devtools/netmonitor/test/sjs_status-codes-test-server.sjs new file mode 100644 index 000000000..bc07336ee --- /dev/null +++ b/browser/devtools/netmonitor/test/sjs_status-codes-test-server.sjs @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { classes: Cc, interfaces: Ci } = Components; + +function handleRequest(request, response) { + response.processAsync(); + + let params = request.queryString.split("&"); + let status = params.filter((s) => s.contains("sts="))[0].split("=")[1]; + + Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer).initWithCallback(() => { + switch (status) { + case "100": + response.setStatusLine(request.httpVersion, 101, "Switching Protocols"); + break; + case "200": + response.setStatusLine(request.httpVersion, 202, "Created"); + break; + case "300": + response.setStatusLine(request.httpVersion, 303, "See Other"); + break; + case "400": + response.setStatusLine(request.httpVersion, 404, "Not Found"); + break; + case "500": + response.setStatusLine(request.httpVersion, 501, "Not Implemented"); + break; + } + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + response.write("Hello status code " + status + "!"); + response.finish(); + }, 10, Ci.nsITimer.TYPE_ONE_SHOT); // Make sure this request takes a few ms. +} diff --git a/browser/devtools/netmonitor/test/test-image.png b/browser/devtools/netmonitor/test/test-image.png Binary files differnew file mode 100644 index 000000000..769c63634 --- /dev/null +++ b/browser/devtools/netmonitor/test/test-image.png |