Bug 1419336 - Update tests; r=nchevobbe draft
authorJan Odvarko <odvarko@gmail.com>
Thu, 07 Dec 2017 12:09:27 +0100
changeset 709685 9d091b9efebdaebe7126da6a82abb1ee3ced31be
parent 709684 2fcbbb6848c9fdbff06ffdf1f87d7ada2dcb0e00
child 743480 16637d7bdfaf33bb31bacebbb75707f3022fe15a
push id92714
push userjodvarko@mozilla.com
push dateFri, 08 Dec 2017 14:06:30 +0000
reviewersnchevobbe
bugs1419336
milestone59.0a1
Bug 1419336 - Update tests; r=nchevobbe MozReview-Commit-ID: 4EEUWLufth8
devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_expand.js
devtools/client/webconsole/new-console-output/test/mochitest/sjs_slow-response-test-server.sjs
devtools/client/webconsole/new-console-output/test/mochitest/test-network-request.html
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
@@ -2,16 +2,17 @@
 tags = devtools
 subsuite = devtools
 support-files =
   code_bundle_invalidmap.js
   code_bundle_invalidmap.js.map
   code_bundle_nosource.js
   code_bundle_nosource.js.map
   head.js
+  sjs_slow-response-test-server.sjs
   source-mapped.css
   source-mapped.css.map
   source-mapped.scss
   test_bug_1010953_cspro.html
   test_bug_1010953_cspro.html^headers^
   test_bug_1247459_violation.html
   test_bug_770099_violation.html
   test_bug_770099_violation.html^headers^
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_expand.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_expand.js
@@ -12,92 +12,272 @@ const XHR_PREF = "devtools.webconsole.fi
 
 Services.prefs.setBoolPref(NET_PREF, false);
 Services.prefs.setBoolPref(XHR_PREF, true);
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref(NET_PREF);
   Services.prefs.clearUserPref(XHR_PREF);
 });
 
+let tabs = [{
+  id: "headers",
+  testEmpty: testEmptyHeaders,
+  testContent: testHeaders,
+}, {
+  id: "cookies",
+  testEmpty: testEmptyCookies,
+  testContent: testCookies,
+}, {
+  id: "params",
+  testEmpty: testEmptyParams,
+  testContent: testParams,
+}, {
+  id: "response",
+  testEmpty: testEmptyResponse,
+  testContent: testResponse,
+}, {
+  id: "timings",
+  testEmpty: testEmptyTimings,
+  testContent: testTimings,
+}, {
+  id: "stack-trace",
+  testEmpty: testEmptyStackTrace,
+  testContent: testStackTrace,
+}];
+
+/**
+ * Main test for checking HTTP logs in the Console panel.
+ */
 add_task(async function task() {
   const hud = await openNewTabAndConsole(TEST_URI);
-
   const currentTab = gBrowser.selectedTab;
   let target = TargetFactory.forTab(currentTab);
+
+  // Execute XHR and expand it after all network
+  // update events are received. Consequently,
+  // check out content of all (HTTP details) tabs.
+  await openRequestAfterUpdates(target, hud);
+
+  // 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 (let tab of tabs) {
+    await openRequestBeforeUpdates(target, hud, tab);
+  }
+});
+
+async function openRequestAfterUpdates(target, hud) {
   let toolbox = gDevTools.getToolbox(target);
 
+  let xhrUrl = TEST_PATH + "sjs_slow-response-test-server.sjs";
+  let message = waitForMessage(hud, xhrUrl);
+
   // Fire an XHR POST request.
-  await ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
-    content.wrappedJSObject.testXhrPost();
+  ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
+    content.wrappedJSObject.testXhrPostSlowResponse();
   });
 
-  info("XHR executed");
+  let { node: messageNode } = await message;
+
+  info("Network message found.");
 
   await waitForRequestUpdates(toolbox);
 
-  let xhrUrl = TEST_PATH + "test-data.json";
-  let messageNode = await waitFor(() => findMessage(hud, xhrUrl));
+  let payload = waitForPayloadReady(toolbox);
+
+  // Expand network log
   let urlNode = messageNode.querySelector(".url");
+  urlNode.click();
+
+  await payload;
+  await testNetworkMessage(toolbox, messageNode);
+}
+
+async function openRequestBeforeUpdates(target, hud, tab) {
+  let toolbox = gDevTools.getToolbox(target);
+
+  hud.jsterm.clearOutput(true);
+
+  let xhrUrl = TEST_PATH + "sjs_slow-response-test-server.sjs";
+  let message = waitForMessage(hud, xhrUrl);
+
+  // Fire an XHR POST request.
+  ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
+    content.wrappedJSObject.testXhrPostSlowResponse();
+  });
+
+  let { node: messageNode } = await message;
+
   info("Network message found.");
 
-  let updates = waitForPayloadReady(toolbox);
+  let updates = waitForRequestUpdates(toolbox);
+  let payload = waitForPayloadReady(toolbox);
+
+  // Set the default panel.
+  const state = hud.ui.newConsoleOutput.getStore().getState();
+  state.ui.networkMessageActiveTabId = tab.id;
 
   // Expand network log
+  let urlNode = messageNode.querySelector(".url");
   urlNode.click();
 
+  // Make sure the current tab is the expected one.
+  let currentTab = messageNode.querySelector(`#${tab.id}-tab`);
+  is(currentTab.getAttribute("aria-selected"), "true",
+    "The correct tab is selected");
+
+  // The tab should be empty now.
+  tab.testEmpty(messageNode);
+
+  // Wait till all updates and payload are received.
   await updates;
-  await testNetworkMessage(messageNode);
-});
+  await payload;
+
+  // Test content of the default tab.
+  await tab.testContent(messageNode);
+
+  // Test all tabs in the network log.
+  await testNetworkMessage(toolbox, messageNode);
+}
 
-async function testNetworkMessage(messageNode) {
-  let headersTab = messageNode.querySelector("#headers-tab");
-  let cookiesTab = messageNode.querySelector("#cookies-tab");
-  let paramsTab = messageNode.querySelector("#params-tab");
-  let responseTab = messageNode.querySelector("#response-tab");
-  let timingsTab = messageNode.querySelector("#timings-tab");
+// Panel testing helpers
+
+async function testNetworkMessage(toolbox, messageNode) {
+  await testHeaders(messageNode);
+  await testCookies(messageNode);
+  await testParams(messageNode);
+  await testResponse(messageNode);
+  await testTimings(messageNode);
+  await testStackTrace(messageNode);
+  await waitForLazyRequests(toolbox);
+}
+
+// Headers
+
+function testEmptyHeaders(messageNode) {
+  let emptyNotice = messageNode.querySelector("#headers-panel .empty-notice");
+  ok(emptyNotice, "Headers tab is empty");
+}
 
+async function testHeaders(messageNode) {
+  let headersTab = messageNode.querySelector("#headers-tab");
   ok(headersTab, "Headers tab is available");
+
+  // Select Headers tab and check the content.
+  headersTab.click();
+  await waitUntil(() => {
+    return !!messageNode.querySelector("#headers-panel .headers-overview");
+  });
+}
+
+// Cookies
+
+function testEmptyCookies(messageNode) {
+  let emptyNotice = messageNode.querySelector("#cookies-panel .empty-notice");
+  ok(emptyNotice, "Cookies tab is empty");
+}
+
+async function testCookies(messageNode) {
+  let cookiesTab = messageNode.querySelector("#cookies-tab");
   ok(cookiesTab, "Cookies tab is available");
+
+  // Select tab and check the content.
+  cookiesTab.click();
+  await waitUntil(() => {
+    return !!messageNode.querySelector("#cookies-panel .treeValueCell");
+  });
+}
+
+// Params
+
+function testEmptyParams(messageNode) {
+  let emptyNotice = messageNode.querySelector("#params-panel .empty-notice");
+  ok(emptyNotice, "Params tab is empty");
+}
+
+async function testParams(messageNode) {
+  let paramsTab = messageNode.querySelector("#params-tab");
   ok(paramsTab, "Params tab is available");
-  ok(responseTab, "Response tab is available");
-  ok(timingsTab, "Timings tab is available");
-
-  // Headers tab should be selected by default, so just check its content.
-  let headersContent = messageNode.querySelector(
-    "#headers-panel .headers-overview");
-  ok(headersContent, "Headers content is available");
 
   // Select Params tab and check the content. CodeMirror initialization
   // is delayed to prevent UI freeze, so wait for a little while.
   paramsTab.click();
   let paramsPanel = messageNode.querySelector("#params-panel");
   await waitForSourceEditor(paramsPanel);
   let paramsContent = messageNode.querySelector(
     "#params-panel .panel-container .CodeMirror");
   ok(paramsContent, "Params content is available");
   ok(paramsContent.textContent.includes("Hello world!"), "Post body is correct");
+}
+
+// Response
+
+function testEmptyResponse(messageNode) {
+  let panel = messageNode.querySelector("#response-panel .tab-panel");
+  is(panel.textContent, "", "Cookies tab is empty");
+}
+
+async function testResponse(messageNode) {
+  let 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();
   let responsePanel = messageNode.querySelector("#response-panel");
   await waitForSourceEditor(responsePanel);
   let 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) {
+  let panel = messageNode.querySelector("#timings-panel .tab-panel");
+  is(panel.textContent, "", "Timings tab is empty");
+}
+
+async function testTimings(messageNode) {
+  let timingsTab = messageNode.querySelector("#timings-tab");
+  ok(timingsTab, "Timings tab is available");
 
   // Select Timings tab and check the content.
   timingsTab.click();
   let timingsContent = messageNode.querySelector(
     "#timings-panel .timings-container .timings-label");
   ok(timingsContent, "Timings content is available");
   ok(timingsContent.textContent, "Timings text is available");
 }
 
+// Stack Trace
+
+function testEmptyStackTrace(messageNode) {
+  let panel = messageNode.querySelector("#stack-trace-panel .stack-trace");
+  is(panel.textContent, "", "StackTrace tab is empty");
+}
+
+async function testStackTrace(messageNode) {
+  let stackTraceTab = messageNode.querySelector("#stack-trace-tab");
+  ok(stackTraceTab, "StackTrace tab is available");
+
+  // Select Timings tab and check the content.
+  stackTraceTab.click();
+  await waitUntil(() => {
+    return !!messageNode.querySelector("#stack-trace-panel .frame-link");
+  });
+}
+
+// Waiting helpers
+
 async function waitForPayloadReady(toolbox) {
   let {ui} = toolbox.getCurrentPanel().hud;
   return new Promise(resolve => {
     ui.jsterm.hud.on("network-request-payload-ready", () => {
       info("network-request-payload-ready received");
       resolve();
     });
   });
@@ -113,8 +293,16 @@ async function waitForRequestUpdates(too
   let {ui} = toolbox.getCurrentPanel().hud;
   return new Promise(resolve => {
     ui.jsterm.hud.on("network-message-updated", () => {
       info("network-message-updated received");
       resolve();
     });
   });
 }
+
+async function waitForLazyRequests(toolbox) {
+  let {ui} = toolbox.getCurrentPanel().hud;
+  let proxy = ui.jsterm.hud.proxy;
+  return waitUntil(() => {
+    return !proxy.networkDataProvider.lazyRequestData.size;
+  });
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/sjs_slow-response-test-server.sjs
@@ -0,0 +1,19 @@
+/* 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 timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+  timer.initWithCallback(() => {
+    // to avoid garbage collection
+    timer = null;
+    response.setStatusLine(request.httpVersion, 200, "OK");
+    response.setHeader("Content-Type", "text/plain", false);
+    response.setHeader("Set-Cookie", "foo=bar; Max-Age=10; HttpOnly", true);
+    response.write("Some response data");
+    response.finish();
+  }, 300, Ci.nsITimer.TYPE_ONE_SHOT); // Make sure this request takes a few hundred ms.
+}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/test-network-request.html
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/test-network-request.html
@@ -2,17 +2,17 @@
    - 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/. -->
 <!DOCTYPE HTML>
 <html dir="ltr" xml:lang="en-US" lang="en-US">
   <head>
     <meta charset="utf-8">
     <title>Console HTTP test page</title>
     <script type="text/javascript">
-      /* exported testXhrGet, testXhrWarn, testXhrPost */
+      /* exported testXhrGet, testXhrWarn, testXhrPost, testXhrPostSlowResponse */
       "use strict";
 
       function makeXhr(method, url, requestBody, callback) {
         let xmlhttp = new XMLHttpRequest();
         xmlhttp.open(method, url, true);
         xmlhttp.onreadystatechange = function () {
           if (callback && xmlhttp.readyState == 4) {
             callback();
@@ -27,16 +27,20 @@
 
       function testXhrWarn(callback) {
         makeXhr("get", "http://example.com/browser/devtools/client/netmonitor/test/sjs_cors-test-server.sjs", null, callback);
       }
 
       function testXhrPost(callback) {
         makeXhr("post", "test-data.json", "Hello world!", callback);
       }
+
+      function testXhrPostSlowResponse(callback) {
+        makeXhr("post", "sjs_slow-response-test-server.sjs", "Hello world!", callback);
+      }
     </script>
   </head>
   <body>
     <h1>Heads Up Display HTTP Logging Testpage</h1>
     <h2>This page is used to test the HTTP logging.</h2>
 
     <form action="https://example.com/browser/devtools/client/webconsole/test/test-network-request.html" method="post">
       <input name="name" type="text" value="foo bar"><br>