diff options
Diffstat (limited to 'devtools/client/netmonitor/test/browser_net_cause.js')
-rw-r--r-- | devtools/client/netmonitor/test/browser_net_cause.js | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/test/browser_net_cause.js b/devtools/client/netmonitor/test/browser_net_cause.js new file mode 100644 index 000000000..2e73965d0 --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_cause.js @@ -0,0 +1,147 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests if request cause is reported correctly. + */ + +const CAUSE_FILE_NAME = "html_cause-test-page.html"; +const CAUSE_URL = EXAMPLE_URL + CAUSE_FILE_NAME; + +const EXPECTED_REQUESTS = [ + { + method: "GET", + url: CAUSE_URL, + causeType: "document", + causeUri: "", + // The document load has internal privileged JS code on the stack + stack: true + }, + { + method: "GET", + url: EXAMPLE_URL + "stylesheet_request", + causeType: "stylesheet", + causeUri: CAUSE_URL, + stack: false + }, + { + method: "GET", + url: EXAMPLE_URL + "img_request", + causeType: "img", + causeUri: CAUSE_URL, + stack: false + }, + { + method: "GET", + url: EXAMPLE_URL + "xhr_request", + causeType: "xhr", + causeUri: CAUSE_URL, + stack: [{ fn: "performXhrRequest", file: CAUSE_FILE_NAME, line: 22 }] + }, + { + method: "GET", + url: EXAMPLE_URL + "fetch_request", + causeType: "fetch", + causeUri: CAUSE_URL, + stack: [{ fn: "performFetchRequest", file: CAUSE_FILE_NAME, line: 26 }] + }, + { + method: "GET", + url: EXAMPLE_URL + "promise_fetch_request", + causeType: "fetch", + causeUri: CAUSE_URL, + stack: [ + { fn: "performPromiseFetchRequest", file: CAUSE_FILE_NAME, line: 38 }, + { fn: null, file: CAUSE_FILE_NAME, line: 37, asyncCause: "promise callback" }, + ] + }, + { + method: "GET", + url: EXAMPLE_URL + "timeout_fetch_request", + causeType: "fetch", + causeUri: CAUSE_URL, + stack: [ + { fn: "performTimeoutFetchRequest", file: CAUSE_FILE_NAME, line: 40 }, + { fn: "performPromiseFetchRequest", file: CAUSE_FILE_NAME, line: 39, + asyncCause: "setTimeout handler" }, + ] + }, + { + method: "POST", + url: EXAMPLE_URL + "beacon_request", + causeType: "beacon", + causeUri: CAUSE_URL, + stack: [{ fn: "performBeaconRequest", file: CAUSE_FILE_NAME, line: 30 }] + }, +]; + +add_task(function* () { + // Async stacks aren't on by default in all builds + yield SpecialPowers.pushPrefEnv({ set: [["javascript.options.asyncstack", true]] }); + + // the initNetMonitor function clears the network request list after the + // page is loaded. That's why we first load a bogus page from SIMPLE_URL, + // and only then load the real thing from CAUSE_URL - we want to catch + // all the requests the page is making, not only the XHRs. + // We can't use about:blank here, because initNetMonitor checks that the + // page has actually made at least one request. + let { tab, monitor } = yield initNetMonitor(SIMPLE_URL); + let { $, NetMonitorView } = monitor.panelWin; + let { RequestsMenu } = NetMonitorView; + RequestsMenu.lazyUpdate = false; + + let wait = waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length); + tab.linkedBrowser.loadURI(CAUSE_URL); + yield wait; + + is(RequestsMenu.itemCount, EXPECTED_REQUESTS.length, + "All the page events should be recorded."); + + EXPECTED_REQUESTS.forEach((spec, i) => { + let { method, url, causeType, causeUri, stack } = spec; + + let requestItem = RequestsMenu.getItemAtIndex(i); + verifyRequestItemTarget(requestItem, + method, url, { cause: { type: causeType, loadingDocumentUri: causeUri } } + ); + + let { stacktrace } = requestItem.attachment.cause; + let stackLen = stacktrace ? stacktrace.length : 0; + + if (stack) { + ok(stacktrace, `Request #${i} has a stacktrace`); + ok(stackLen > 0, + `Request #${i} (${causeType}) has a stacktrace with ${stackLen} items`); + + // if "stack" is array, check the details about the top stack frames + if (Array.isArray(stack)) { + stack.forEach((frame, j) => { + is(stacktrace[j].functionName, frame.fn, + `Request #${i} has the correct function on JS stack frame #${j}`); + is(stacktrace[j].filename.split("/").pop(), frame.file, + `Request #${i} has the correct file on JS stack frame #${j}`); + is(stacktrace[j].lineNumber, frame.line, + `Request #${i} has the correct line number on JS stack frame #${j}`); + is(stacktrace[j].asyncCause, frame.asyncCause, + `Request #${i} has the correct async cause on JS stack frame #${j}`); + }); + } + } else { + is(stackLen, 0, `Request #${i} (${causeType}) has an empty stacktrace`); + } + }); + + // Sort the requests by cause and check the order + EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-cause-button")); + let expectedOrder = EXPECTED_REQUESTS.map(r => r.causeType).sort(); + expectedOrder.forEach((expectedCause, i) => { + let { target } = RequestsMenu.getItemAtIndex(i); + let causeLabel = target.querySelector(".requests-menu-cause-label"); + let cause = causeLabel.getAttribute("value"); + is(cause, expectedCause, `The request #${i} has the expected cause after sorting`); + }); + + yield teardown(monitor); +}); |