Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* Any copyright is dedicated to the Public Domain.
"use strict";
const TEST_FILE = "test-network-request.html";
const TEST_PATH =
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"
);
}