diff options
Diffstat (limited to 'devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js')
-rw-r--r-- | devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js b/devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js new file mode 100644 index 0000000000..1e25729b97 --- /dev/null +++ b/devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js @@ -0,0 +1,316 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_FILE = "test-network-request.html"; +const TEST_PATH = + "https://example.com/browser/devtools/client/webconsole/test/browser/"; +const TEST_URI = TEST_PATH + TEST_FILE; + +requestLongerTimeout(4); + +pushPref("devtools.webconsole.filter.net", false); +pushPref("devtools.webconsole.filter.netxhr", true); + +// Update waitFor default interval (10ms) to avoid test timeouts. +// The test often times out on waitFor statements use a 50ms interval instead. +waitFor.overrideIntervalForTestFile = 50; + +const tabs = [ + { + id: "headers", + testEmpty: testEmptyHeaders, + testContent: testHeaders, + }, + { + id: "cookies", + testEmpty: testEmptyCookies, + testContent: testCookies, + }, + { + id: "request", + testEmpty: testEmptyRequest, + testContent: testRequest, + }, + { + id: "response", + testEmpty: testEmptyResponse, + testContent: testResponse, + }, + { + id: "timings", + testEmpty: testEmptyTimings, + testContent: testTimings, + }, + { + id: "stack-trace", + testEmpty: testEmptyStackTrace, + testContent: testStackTrace, + }, + { + id: "security", + testEmpty: testEmptySecurity, + testContent: testSecurity, + }, +]; + +/** + * Main test for checking HTTP logs in the Console panel. + */ +add_task(async function task() { + const hud = await openNewTabAndConsole(TEST_URI); + + // Test proper UI update when request is opened. + // For every tab (with HTTP details): + // 1. Execute long-time request + // 2. Expand the net log before the request finishes (set default tab) + // 3. Check the default tab empty content + // 4. Wait till the request finishes + // 5. Check content of all tabs + for (const tab of tabs) { + info(`Test "${tab.id}" panel`); + await openRequestBeforeUpdates(hud, tab); + } +}); + +async function openRequestBeforeUpdates(hud, tab) { + const toolbox = hud.toolbox; + + await clearOutput(hud); + + const xhrUrl = TEST_PATH + "sjs_slow-response-test-server.sjs"; + const onMessage = waitForMessageByType(hud, xhrUrl, ".network"); + + // Fire an XHR POST request. + SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () { + content.wrappedJSObject.testXhrPostSlowResponse(); + }); + info(`Wait for ${xhrUrl} message`); + const { node: messageNode } = await onMessage; + ok(messageNode, "Network message found."); + + // Set the default panel. + const state = hud.ui.wrapper.getStore().getState(); + state.ui.networkMessageActiveTabId = tab.id; + + // Expand network log + await expandXhrMessage(messageNode); + + // Except the security tab. It isn't available till the + // "securityInfo" packet type is received, so doesn't + // fit this part of the test. + if (tab.id != "security") { + // Make sure the current tab is the expected one. + const currentTab = messageNode.querySelector(`#${tab.id}-tab`); + is( + currentTab.getAttribute("aria-selected"), + "true", + "The correct tab is selected" + ); + + if (tab.testEmpty) { + info("Test that the tab is empty"); + tab.testEmpty(messageNode); + } + } + + info("Test content of the default tab"); + await tab.testContent(messageNode); + + info("Test all tabs in the network log"); + await testNetworkMessage(toolbox, messageNode); +} + +// Panel testing helpers + +async function testNetworkMessage(toolbox, messageNode) { + await testStatusInfo(messageNode); + await testHeaders(messageNode); + await testCookies(messageNode); + await testRequest(messageNode); + await testResponse(messageNode); + await testTimings(messageNode); + await testStackTrace(messageNode); + await testSecurity(messageNode); + await waitForLazyRequests(toolbox); +} + +// Status Info +async function testStatusInfo(messageNode) { + const statusInfo = await waitFor(() => + messageNode.querySelector(".status-info") + ); + ok(statusInfo, "Status info is not empty"); +} + +// Headers +function testEmptyHeaders(messageNode) { + const emptyNotice = messageNode.querySelector("#headers-panel .empty-notice"); + ok(emptyNotice, "Headers tab is empty"); +} + +async function testHeaders(messageNode) { + const headersTab = messageNode.querySelector("#headers-tab"); + ok(headersTab, "Headers tab is available"); + + // Select Headers tab and check the content. + headersTab.click(); + await waitFor( + () => messageNode.querySelector("#headers-panel .headers-overview"), + "Wait for .header-overview to be rendered" + ); +} + +// Cookies +function testEmptyCookies(messageNode) { + const emptyNotice = messageNode.querySelector("#cookies-panel .empty-notice"); + ok(emptyNotice, "Cookies tab is empty"); +} + +async function testCookies(messageNode) { + const cookiesTab = messageNode.querySelector("#cookies-tab"); + ok(cookiesTab, "Cookies tab is available"); + + // Select tab and check the content. + cookiesTab.click(); + await waitFor( + () => messageNode.querySelector("#cookies-panel .treeValueCell"), + "Wait for .treeValueCell to be rendered" + ); +} + +// Request +function testEmptyRequest(messageNode) { + const emptyNotice = messageNode.querySelector("#request-panel .empty-notice"); + ok(emptyNotice, "Request tab is empty"); +} + +async function testRequest(messageNode) { + const requestTab = messageNode.querySelector("#request-tab"); + ok(requestTab, "Request tab is available"); + + // Select Request tab and check the content. CodeMirror initialization + // is delayed to prevent UI freeze, so wait for a little while. + requestTab.click(); + const requestPanel = messageNode.querySelector("#request-panel"); + await waitForSourceEditor(requestPanel); + const requestContent = requestPanel.querySelector( + ".panel-container .CodeMirror" + ); + ok(requestContent, "Request content is available"); + ok( + requestContent.textContent.includes("Hello world!"), + "Request POST body is correct" + ); +} + +// Response +function testEmptyResponse(messageNode) { + const panel = messageNode.querySelector("#response-panel .tab-panel"); + is( + panel.textContent, + "No response data available for this request", + "Cookies tab is empty" + ); +} + +async function testResponse(messageNode) { + const responseTab = messageNode.querySelector("#response-tab"); + ok(responseTab, "Response tab is available"); + + // Select Response tab and check the content. CodeMirror initialization + // is delayed, so again wait for a little while. + responseTab.click(); + const responsePanel = messageNode.querySelector("#response-panel"); + const responsePayloadHeader = await waitFor(() => + responsePanel.querySelector(".data-header") + ); + // Expand the header if it wasn't yet. + if (responsePayloadHeader.getAttribute("aria-expanded") === "false") { + responsePayloadHeader.click(); + } + await waitForSourceEditor(responsePanel); + const responseContent = messageNode.querySelector( + "#response-panel .editor-row-container .CodeMirror" + ); + ok(responseContent, "Response content is available"); + ok(responseContent.textContent, "Response text is available"); +} + +// Timings +function testEmptyTimings(messageNode) { + const panel = messageNode.querySelector("#timings-panel .tab-panel"); + is(panel.textContent, "No timings for this request", "Timings tab is empty"); +} + +async function testTimings(messageNode) { + const timingsTab = messageNode.querySelector("#timings-tab"); + ok(timingsTab, "Timings tab is available"); + + // Select Timings tab and check the content. + timingsTab.click(); + const timingsContent = await waitFor(() => + messageNode.querySelector( + "#timings-panel .timings-container .timings-label", + "Wait for .timings-label to be rendered" + ) + ); + ok(timingsContent, "Timings content is available"); + ok(timingsContent.textContent, "Timings text is available"); +} + +// Stack Trace +function testEmptyStackTrace(messageNode) { + const panel = messageNode.querySelector("#stack-trace-panel .tab-panel"); + is(panel.textContent, "", "StackTrace tab is empty"); +} + +async function testStackTrace(messageNode) { + const stackTraceTab = messageNode.querySelector("#stack-trace-tab"); + ok(stackTraceTab, "StackTrace tab is available"); + + // Select Stack Trace tab and check the content. + stackTraceTab.click(); + await waitFor( + () => messageNode.querySelector("#stack-trace-panel .frame-link"), + "Wait for .frame-link to be rendered" + ); +} + +// Security +function testEmptySecurity(messageNode) { + const panel = messageNode.querySelector("#security-panel .tab-panel"); + is(panel.textContent, "", "Security tab is empty"); +} + +async function testSecurity(messageNode) { + const securityTab = await waitFor(() => + messageNode.querySelector("#security-tab") + ); + ok(securityTab, "Security tab is available"); + + // Select Security tab and check the content. + securityTab.click(); + await waitFor( + () => messageNode.querySelector("#security-panel .treeTable .treeRow"), + "Wait for #security-panel .treeTable .treeRow to be rendered" + ); +} + +async function waitForSourceEditor(panel) { + return waitUntil(() => { + return !!panel.querySelector(".CodeMirror"); + }); +} + +function expandXhrMessage(node) { + info( + "Click on XHR message and wait for the network detail panel to be displayed" + ); + node.querySelector(".url").click(); + return waitFor( + () => node.querySelector(".network-info"), + "Wait for .network-info to be rendered" + ); +} |