Bug 1644191 - Add tests for network event resources (WIP) r=nchevobbe
☠☠ backed out by 2107c6ef98d8 ☠ ☠
authorHubert Boma Manilla <hmanilla@mozilla.com>
Thu, 23 Jul 2020 16:09:44 +0000
changeset 541773 99d945043967404848b87c46834c45930bac9ccc
parent 541772 fd212b7e336c16f77e1922f5db32267009e833e9
child 541774 8848caa5b12536f42ec340569debb3b291d4ecc9
push id37633
push userccoroiu@mozilla.com
push dateFri, 24 Jul 2020 09:32:06 +0000
treeherdermozilla-central@141543043270 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnchevobbe
bugs1644191
milestone80.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1644191 - Add tests for network event resources (WIP) r=nchevobbe Differential Revision: https://phabricator.services.mozilla.com/D84167
devtools/shared/resources/tests/browser.ini
devtools/shared/resources/tests/browser_resources_network_events.js
devtools/shared/resources/tests/network_document.html
--- a/devtools/shared/resources/tests/browser.ini
+++ b/devtools/shared/resources/tests/browser.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
   !/devtools/client/shared/test/shared-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
   !/devtools/client/shared/test/test-actor.js
   head.js
+  network_document.html
   fission_document.html
   fission_iframe.html
   style_document.css
   style_document.html
   style_iframe.css
   style_iframe.html
   test_service_worker.js
   test_sw_page.html
@@ -19,16 +20,17 @@ support-files =
 
 [browser_resources_client_caching.js]
 [browser_resources_console_messages.js]
 [browser_resources_css_changes.js]
 [browser_resources_css_messages.js]
 [browser_resources_document_events.js]
 [browser_resources_error_messages.js]
 [browser_resources_getAllResources.js]
+[browser_resources_network_events.js]
 [browser_resources_platform_messages.js]
 [browser_resources_root_node.js]
 [browser_resources_several_resources.js]
 [browser_resources_stylesheets.js]
 [browser_resources_target_destroy.js]
 [browser_target_list_frames.js]
 [browser_target_list_getAllTargets.js]
 [browser_target_list_preffedoff.js]
new file mode 100644
--- /dev/null
+++ b/devtools/shared/resources/tests/browser_resources_network_events.js
@@ -0,0 +1,281 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the ResourceWatcher API around NETWORK_EVENT
+
+const {
+  ResourceWatcher,
+} = require("devtools/shared/resources/resource-watcher");
+
+const EXAMPLE_DOMAIN = "https://example.com/";
+const TEST_URI = `${URL_ROOT_SSL}/network_document.html`;
+
+add_task(async function() {
+  info("Test network events legacy listener");
+  await pushPref("devtools.testing.enableServerWatcherSupport", false);
+  await testNetworkEventResourcesWithExistingResources();
+  await testNetworkEventResourcesWithoutExistingResources();
+
+  // These tests would be enabled when the server-side work is done. See Bug 1644191
+  // info("Test network events server listener");
+  // await pushPref("devtools.testing.enableServerWatcherSupport", true);
+  // await testNetworkEventResources();
+  // await testNetworkEventResourcesWithIgnoreExistingResources();
+});
+
+const UPDATES = [
+  "requestHeaders",
+  "requestCookies",
+  "responseStart",
+  "securityInfo",
+  "responseHeaders",
+  "responseCookies",
+  "eventTimings",
+  "responseContent",
+];
+
+async function testNetworkEventResourcesWithExistingResources() {
+  info(`Tests for network event resources with the existing resources`);
+  await testNetworkEventResources({
+    ignoreExistingResources: false,
+    // 1 available event fired, for the existing resource in the cache.
+    // 1 available event fired, when live request is created.
+    expectedOnAvailableCounts: 2,
+    // 8 update events fired, when live request is updated.
+    expectedOnUpdatedCounts: 8,
+    expectedResourcesOnAvailable: {
+      [`${EXAMPLE_DOMAIN}existing_xhr_post.html`]: {
+        resourceType: ResourceWatcher.TYPES.NETWORK_EVENT,
+        request: {
+          url: `${EXAMPLE_DOMAIN}existing_xhr_post.html`,
+          method: "POST",
+        },
+        updates: UPDATES,
+      },
+      [`${EXAMPLE_DOMAIN}live_xhr_get.html`]: {
+        resourceType: ResourceWatcher.TYPES.NETWORK_EVENT,
+        request: {
+          url: `${EXAMPLE_DOMAIN}live_xhr_get.html`,
+          method: "GET",
+        },
+        updates: [],
+      },
+    },
+    expectedResourcesOnUpdated: {
+      [`${EXAMPLE_DOMAIN}live_xhr_get.html`]: {
+        resourceType: ResourceWatcher.TYPES.NETWORK_EVENT,
+        request: {
+          url: `${EXAMPLE_DOMAIN}live_xhr_get.html`,
+          method: "GET",
+        },
+        updates: UPDATES,
+      },
+    },
+  });
+}
+
+async function testNetworkEventResourcesWithoutExistingResources() {
+  info(`Tests for network event resources without the existing resources`);
+  await testNetworkEventResources({
+    ignoreExistingResources: true,
+    // 1 available event fired, when live request is created.
+    expectedOnAvailableCounts: 1,
+    // 8 update events fired, when live request is updated.
+    expectedOnUpdatedCounts: 8,
+    expectedResourcesOnAvailable: {
+      [`${EXAMPLE_DOMAIN}live_xhr_get.html`]: {
+        resourceType: ResourceWatcher.TYPES.NETWORK_EVENT,
+        request: {
+          url: `${EXAMPLE_DOMAIN}live_xhr_get.html`,
+          method: "GET",
+        },
+        updates: [],
+      },
+    },
+    expectedResourcesOnUpdated: {
+      [`${EXAMPLE_DOMAIN}live_xhr_get.html`]: {
+        resourceType: ResourceWatcher.TYPES.NETWORK_EVENT,
+        request: {
+          url: `${EXAMPLE_DOMAIN}live_xhr_get.html`,
+          method: "GET",
+        },
+        updates: UPDATES,
+      },
+    },
+  });
+}
+
+async function testNetworkEventResources(options) {
+  const tab = await addTab(TEST_URI);
+  const {
+    client,
+    resourceWatcher,
+    targetList,
+  } = await initResourceWatcherAndTarget(tab);
+
+  const actualResourcesOnAvailable = {};
+  const actualResourcesOnUpdated = {};
+
+  info(
+    `Trigger some network requests *before* calling ResourceWatcher.watchResources
+     in order to assert the behavior of already existing network events.`
+  );
+
+  const waitForAllExpectedUpdates = new Promise(resolve => {
+    resourceWatcher.watchResources([ResourceWatcher.TYPES.NETWORK_EVENT], {
+      onAvailable: ({ resource }) => {
+        // A blocked request would not fire updates and would have only 2 updates
+        // (requestHeaders,requestCookies), so lets also resolve here
+        if (resource.updates.length == 2) {
+          resolve();
+        }
+      },
+      onUpdated: ({ resource }) => {
+        // Wait until all the update events have fired
+        // for the existing request.
+        if (resource.updates.length == 8) {
+          resolve();
+        }
+      },
+    });
+  });
+  await triggerNetworkRequests(tab.linkedBrowser, EXISTING_REQUESTS_COMMANDS);
+  await waitForAllExpectedUpdates;
+
+  let {
+    expectedOnAvailableCounts,
+    expectedOnUpdatedCounts,
+    ignoreExistingResources,
+  } = options;
+
+  const waitForAllOnAvailableEvents = waitUntil(
+    () => expectedOnAvailableCounts == 0
+  );
+  const waitForAllOnUpdatedEvents = waitUntil(
+    () => expectedOnUpdatedCounts == 0
+  );
+
+  const onAvailable = ({ resourceType, targetFront, resource }) => {
+    is(
+      resourceType,
+      ResourceWatcher.TYPES.NETWORK_EVENT,
+      "Received a network event resource"
+    );
+    actualResourcesOnAvailable[resource.request.url] = {
+      resourceType: resource.resourceType,
+      request: resource.request,
+      updates: [...resource.updates],
+    };
+    expectedOnAvailableCounts--;
+  };
+
+  const onUpdated = ({ resourceType, targetFront, resource }) => {
+    is(
+      resourceType,
+      ResourceWatcher.TYPES.NETWORK_EVENT,
+      "Received a network update event resource"
+    );
+    actualResourcesOnUpdated[resource.request.url] = {
+      resourceType: resource.resourceType,
+      request: resource.request,
+      updates: [...resource.updates],
+    };
+    expectedOnUpdatedCounts--;
+  };
+
+  await resourceWatcher.watchResources([ResourceWatcher.TYPES.NETWORK_EVENT], {
+    onAvailable,
+    onUpdated,
+    ignoreExistingResources,
+  });
+
+  info(
+    `Trigger the rest of the requests *after* calling ResourceWatcher.watchResources
+     in order to assert the behavior of live network events.`
+  );
+  await triggerNetworkRequests(tab.linkedBrowser, LIVE_REQUESTS_COMMANDS);
+
+  await Promise.all([waitForAllOnAvailableEvents, waitForAllOnUpdatedEvents]);
+
+  info("Check the resources on available");
+  is(
+    Object.keys(actualResourcesOnAvailable).length,
+    Object.keys(options.expectedResourcesOnAvailable).length,
+    "Got the expected number of network events fired onAvailable"
+  );
+
+  // assert the resources emitted when the network event is created
+  for (const key in options.expectedResourcesOnAvailable) {
+    const expected = options.expectedResourcesOnAvailable[key];
+    const actual = actualResourcesOnAvailable[key];
+    assertResources(actual, expected);
+  }
+
+  info("Check the resources on updated");
+
+  is(
+    Object.keys(actualResourcesOnUpdated).length,
+    Object.keys(options.expectedResourcesOnUpdated).length,
+    "Got the expected number of network events fired onUpdated"
+  );
+
+  // assert the resources emitted when the network event is updated
+  for (const key in options.expectedResourcesOnUpdated) {
+    const expected = options.expectedResourcesOnUpdated[key];
+    const actual = actualResourcesOnUpdated[key];
+    assertResources(actual, expected);
+  }
+
+  await resourceWatcher.unwatchResources(
+    [ResourceWatcher.TYPES.NETWORK_EVENT],
+    {
+      onAvailable,
+      onUpdated,
+      ignoreExistingResources,
+    }
+  );
+  await targetList.stopListening();
+  await client.close();
+}
+
+function assertResources(actual, expected) {
+  is(
+    actual.resourceType,
+    expected.resourceType,
+    "The resource type is correct"
+  );
+
+  is(actual.request.url, expected.request.url, "The url is correct");
+  is(actual.request.method, expected.request.method, "The method is correct");
+  is(
+    actual.updates.length,
+    expected.updates.length,
+    "The number of updates is correct"
+  );
+}
+
+const EXISTING_REQUESTS_COMMANDS = [
+  `await fetch("/existing_xhr_post.html", { method: "POST" });`,
+];
+
+const LIVE_REQUESTS_COMMANDS = [
+  `await fetch("/live_xhr_get.html", { method: "GET" });`,
+];
+
+async function triggerNetworkRequests(browser, commands) {
+  for (let i = 0; i < commands.length; i++) {
+    await SpecialPowers.spawn(browser, [commands[i]], async function(code) {
+      const script = content.document.createElement("script");
+      script.append(
+        content.document.createTextNode(
+          `async function triggerRequest() {${code}}`
+        )
+      );
+      content.document.body.append(script);
+      await content.wrappedJSObject.triggerRequest();
+      script.remove();
+    });
+  }
+}
new file mode 100644
--- /dev/null
+++ b/devtools/shared/resources/tests/network_document.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <meta http-equiv="Expires" content="0" />
+    <title>Test for network events</title>
+  </head>
+  <body>
+    <p>Test for network events</p>
+  </body>
+</html>
\ No newline at end of file