diff options
Diffstat (limited to 'devtools/client/netmonitor/test/browser_net_frame.js')
-rw-r--r-- | devtools/client/netmonitor/test/browser_net_frame.js | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/test/browser_net_frame.js b/devtools/client/netmonitor/test/browser_net_frame.js new file mode 100644 index 000000000..eeded652b --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_frame.js @@ -0,0 +1,221 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests for all expected requests when an iframe is loading a subdocument. + */ + +const TOP_FILE_NAME = "html_frame-test-page.html"; +const SUB_FILE_NAME = "html_frame-subdocument.html"; +const TOP_URL = EXAMPLE_URL + TOP_FILE_NAME; +const SUB_URL = EXAMPLE_URL + SUB_FILE_NAME; + +const EXPECTED_REQUESTS_TOP = [ + { + method: "GET", + url: TOP_URL, + causeType: "document", + causeUri: "", + stack: true + }, + { + method: "GET", + url: EXAMPLE_URL + "stylesheet_request", + causeType: "stylesheet", + causeUri: TOP_URL, + stack: false + }, + { + method: "GET", + url: EXAMPLE_URL + "img_request", + causeType: "img", + causeUri: TOP_URL, + stack: false + }, + { + method: "GET", + url: EXAMPLE_URL + "xhr_request", + causeType: "xhr", + causeUri: TOP_URL, + stack: [{ fn: "performXhrRequest", file: TOP_FILE_NAME, line: 23 }] + }, + { + method: "GET", + url: EXAMPLE_URL + "fetch_request", + causeType: "fetch", + causeUri: TOP_URL, + stack: [{ fn: "performFetchRequest", file: TOP_FILE_NAME, line: 27 }] + }, + { + method: "GET", + url: EXAMPLE_URL + "promise_fetch_request", + causeType: "fetch", + causeUri: TOP_URL, + stack: [ + { fn: "performPromiseFetchRequest", file: TOP_FILE_NAME, line: 39 }, + { fn: null, file: TOP_FILE_NAME, line: 38, asyncCause: "promise callback" }, + ] + }, + { + method: "GET", + url: EXAMPLE_URL + "timeout_fetch_request", + causeType: "fetch", + causeUri: TOP_URL, + stack: [ + { fn: "performTimeoutFetchRequest", file: TOP_FILE_NAME, line: 41 }, + { fn: "performPromiseFetchRequest", file: TOP_FILE_NAME, line: 40, + asyncCause: "setTimeout handler" }, + ] + }, + { + method: "POST", + url: EXAMPLE_URL + "beacon_request", + causeType: "beacon", + causeUri: TOP_URL, + stack: [{ fn: "performBeaconRequest", file: TOP_FILE_NAME, line: 31 }] + }, +]; + +const EXPECTED_REQUESTS_SUB = [ + { + method: "GET", + url: SUB_URL, + causeType: "subdocument", + causeUri: TOP_URL, + stack: false + }, + { + method: "GET", + url: EXAMPLE_URL + "stylesheet_request", + causeType: "stylesheet", + causeUri: SUB_URL, + stack: false + }, + { + method: "GET", + url: EXAMPLE_URL + "img_request", + causeType: "img", + causeUri: SUB_URL, + stack: false + }, + { + method: "GET", + url: EXAMPLE_URL + "xhr_request", + causeType: "xhr", + causeUri: SUB_URL, + stack: [{ fn: "performXhrRequest", file: SUB_FILE_NAME, line: 22 }] + }, + { + method: "GET", + url: EXAMPLE_URL + "fetch_request", + causeType: "fetch", + causeUri: SUB_URL, + stack: [{ fn: "performFetchRequest", file: SUB_FILE_NAME, line: 26 }] + }, + { + method: "GET", + url: EXAMPLE_URL + "promise_fetch_request", + causeType: "fetch", + causeUri: SUB_URL, + stack: [ + { fn: "performPromiseFetchRequest", file: SUB_FILE_NAME, line: 38 }, + { fn: null, file: SUB_FILE_NAME, line: 37, asyncCause: "promise callback" }, + ] + }, + { + method: "GET", + url: EXAMPLE_URL + "timeout_fetch_request", + causeType: "fetch", + causeUri: SUB_URL, + stack: [ + { fn: "performTimeoutFetchRequest", file: SUB_FILE_NAME, line: 40 }, + { fn: "performPromiseFetchRequest", file: SUB_FILE_NAME, line: 39, + asyncCause: "setTimeout handler" }, + ] + }, + { + method: "POST", + url: EXAMPLE_URL + "beacon_request", + causeType: "beacon", + causeUri: SUB_URL, + stack: [{ fn: "performBeaconRequest", file: SUB_FILE_NAME, line: 30 }] + }, +]; + +const REQUEST_COUNT = EXPECTED_REQUESTS_TOP.length + EXPECTED_REQUESTS_SUB.length; + +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 TOP_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; + + tab.linkedBrowser.loadURI(TOP_URL, null, null); + + yield waitForNetworkEvents(monitor, REQUEST_COUNT); + + is(RequestsMenu.itemCount, REQUEST_COUNT, + "All the page events should be recorded."); + + // While there is a defined order for requests in each document separately, the requests + // from different documents may interleave in various ways that change per test run, so + // there is not a single order when considering all the requests together. + let currentTop = 0; + let currentSub = 0; + for (let i = 0; i < REQUEST_COUNT; i++) { + let requestItem = RequestsMenu.getItemAtIndex(i); + + let itemUrl = requestItem.attachment.url; + let itemCauseUri = requestItem.target.querySelector(".requests-menu-cause-label") + .getAttribute("tooltiptext"); + let spec; + if (itemUrl == SUB_URL || itemCauseUri == SUB_URL) { + spec = EXPECTED_REQUESTS_SUB[currentSub++]; + } else { + spec = EXPECTED_REQUESTS_TOP[currentTop++]; + } + let { method, url, causeType, causeUri, stack } = spec; + + 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`); + } + } + + yield teardown(monitor); +}); |