summaryrefslogtreecommitdiffstats
path: root/devtools/shared/commands/resource/tests/browser_resources_network_events_cache.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/commands/resource/tests/browser_resources_network_events_cache.js')
-rw-r--r--devtools/shared/commands/resource/tests/browser_resources_network_events_cache.js236
1 files changed, 236 insertions, 0 deletions
diff --git a/devtools/shared/commands/resource/tests/browser_resources_network_events_cache.js b/devtools/shared/commands/resource/tests/browser_resources_network_events_cache.js
new file mode 100644
index 0000000000..6708ef19e1
--- /dev/null
+++ b/devtools/shared/commands/resource/tests/browser_resources_network_events_cache.js
@@ -0,0 +1,236 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the ResourceCommand API internal cache / ignoreExistingResources around NETWORK_EVENT
+
+const ResourceCommand = require("resource://devtools/shared/commands/resource/resource-command.js");
+
+const EXAMPLE_DOMAIN = "https://example.com/";
+const TEST_URI = `${URL_ROOT_SSL}network_document.html`;
+
+add_task(async function () {
+ info("Test basic NETWORK_EVENT resources against ResourceCommand cache");
+ await testNetworkEventResourcesWithExistingResources();
+ await testNetworkEventResourcesWithoutExistingResources();
+});
+
+async function testNetworkEventResourcesWithExistingResources() {
+ info(`Tests for network event resources with the existing resources`);
+ await testNetworkEventResourcesWithCachedRequest({
+ ignoreExistingResources: false,
+ // 1 available event fired, for the existing resource in the cache.
+ // 1 available event fired, when live request is created.
+ expectedResourcesOnAvailable: {
+ [`${EXAMPLE_DOMAIN}cached_post.html`]: {
+ resourceType: ResourceCommand.TYPES.NETWORK_EVENT,
+ method: "POST",
+ isNavigationRequest: false,
+ },
+ [`${EXAMPLE_DOMAIN}live_get.html`]: {
+ resourceType: ResourceCommand.TYPES.NETWORK_EVENT,
+ method: "GET",
+ isNavigationRequest: false,
+ },
+ },
+ // 1 update events fired, when live request is updated.
+ expectedResourcesOnUpdated: {
+ [`${EXAMPLE_DOMAIN}live_get.html`]: {
+ resourceType: ResourceCommand.TYPES.NETWORK_EVENT,
+ method: "GET",
+ },
+ },
+ });
+}
+
+async function testNetworkEventResourcesWithoutExistingResources() {
+ info(`Tests for network event resources without the existing resources`);
+ await testNetworkEventResourcesWithCachedRequest({
+ ignoreExistingResources: true,
+ // 1 available event fired, when live request is created.
+ expectedResourcesOnAvailable: {
+ [`${EXAMPLE_DOMAIN}live_get.html`]: {
+ resourceType: ResourceCommand.TYPES.NETWORK_EVENT,
+ method: "GET",
+ isNavigationRequest: false,
+ },
+ },
+ // 1 update events fired, when live request is updated.
+ expectedResourcesOnUpdated: {
+ [`${EXAMPLE_DOMAIN}live_get.html`]: {
+ resourceType: ResourceCommand.TYPES.NETWORK_EVENT,
+ method: "GET",
+ },
+ },
+ });
+}
+
+/**
+ * This test helper is slightly complex as we workaround the fact
+ * that the server is not able to record network request done in the past.
+ * Because of that we have to start observer requests via ResourceCommand.watchResources
+ * before doing a request, and, before doing the actual call to watchResources
+ * we want to assert the behavior of.
+ */
+async function testNetworkEventResourcesWithCachedRequest(options) {
+ const tab = await addTab(TEST_URI);
+ const commands = await CommandsFactory.forTab(tab);
+ await commands.targetCommand.startListening();
+
+ const { resourceCommand } = commands;
+
+ info(
+ `Trigger some network requests *before* calling ResourceCommand.watchResources
+ in order to assert the behavior of already existing network events.`
+ );
+
+ // Register a first empty listener in order to ensure populating ResourceCommand
+ // internal cache of NETWORK_EVENT's. We can't retrieved past network requests
+ // when calling server's `watchResources`.
+ let resolveCachedRequestAvailable;
+ const onCachedRequestAvailable = new Promise(
+ r => (resolveCachedRequestAvailable = r)
+ );
+ const onAvailableToPopulateInternalCache = () => {};
+ const onUpdatedToPopulateInternalCache = resolveCachedRequestAvailable;
+ await resourceCommand.watchResources([resourceCommand.TYPES.NETWORK_EVENT], {
+ ignoreExistingResources: true,
+ onAvailable: onAvailableToPopulateInternalCache,
+ onUpdated: onUpdatedToPopulateInternalCache,
+ });
+
+ // We can only trigger the requests once `watchResources` settles,
+ // otherwise we might miss some events and they won't be present in the cache
+ const cachedRequest = `await fetch("/cached_post.html", { method: "POST" });`;
+ await triggerNetworkRequests(tab.linkedBrowser, [cachedRequest]);
+
+ // We have to ensure that ResourceCommand processed the Resource for this first
+ // cached request before calling watchResource a second time and report it.
+ // Wait for the updated notification to avoid receiving it during the next call
+ // to watchResources.
+ await onCachedRequestAvailable;
+
+ const actualResourcesOnAvailable = {};
+ const actualResourcesOnUpdated = {};
+
+ const {
+ expectedResourcesOnAvailable,
+ expectedResourcesOnUpdated,
+
+ ignoreExistingResources,
+ } = options;
+
+ const onAvailable = resources => {
+ for (const resource of resources) {
+ is(
+ resource.resourceType,
+ resourceCommand.TYPES.NETWORK_EVENT,
+ "Received a network event resource"
+ );
+ actualResourcesOnAvailable[resource.url] = resource;
+ }
+ };
+
+ const onUpdated = updates => {
+ for (const { resource } of updates) {
+ is(
+ resource.resourceType,
+ resourceCommand.TYPES.NETWORK_EVENT,
+ "Received a network update event resource"
+ );
+ actualResourcesOnUpdated[resource.url] = resource;
+ }
+ };
+
+ await resourceCommand.watchResources([resourceCommand.TYPES.NETWORK_EVENT], {
+ onAvailable,
+ onUpdated,
+ ignoreExistingResources,
+ });
+
+ info(
+ `Trigger the rest of the requests *after* calling ResourceCommand.watchResources
+ in order to assert the behavior of live network events.`
+ );
+ const liveRequest = `await fetch("/live_get.html", { method: "GET" });`;
+ await triggerNetworkRequests(tab.linkedBrowser, [liveRequest]);
+
+ info("Check the resources on available");
+
+ await waitUntil(
+ () =>
+ Object.keys(actualResourcesOnAvailable).length ==
+ Object.keys(expectedResourcesOnAvailable).length
+ );
+
+ is(
+ Object.keys(actualResourcesOnAvailable).length,
+ Object.keys(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 expectedResourcesOnAvailable) {
+ const expected = expectedResourcesOnAvailable[key];
+ const actual = actualResourcesOnAvailable[key];
+ assertResources(actual, expected);
+ }
+
+ info("Check the resources on updated");
+
+ await waitUntil(
+ () =>
+ Object.keys(actualResourcesOnUpdated).length ==
+ Object.keys(expectedResourcesOnUpdated).length
+ );
+
+ is(
+ Object.keys(actualResourcesOnUpdated).length,
+ Object.keys(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 expectedResourcesOnUpdated) {
+ const expected = expectedResourcesOnUpdated[key];
+ const actual = actualResourcesOnUpdated[key];
+ assertResources(actual, expected);
+ // assert that the resourceId for the the available and updated events match
+ is(
+ actual.resourceId,
+ actualResourcesOnAvailable[key].resourceId,
+ `Available and update resource ids for ${key} are the same`
+ );
+ }
+
+ resourceCommand.unwatchResources([resourceCommand.TYPES.NETWORK_EVENT], {
+ onAvailable,
+ onUpdated,
+ ignoreExistingResources,
+ });
+
+ resourceCommand.unwatchResources([resourceCommand.TYPES.NETWORK_EVENT], {
+ onAvailable: onAvailableToPopulateInternalCache,
+ });
+
+ await commands.destroy();
+
+ BrowserTestUtils.removeTab(tab);
+}
+
+function assertResources(actual, expected) {
+ is(
+ actual.resourceType,
+ expected.resourceType,
+ "The resource type is correct"
+ );
+ is(actual.method, expected.method, "The method is correct");
+ if ("isNavigationRequest" in expected) {
+ is(
+ actual.isNavigationRequest,
+ expected.isNavigationRequest,
+ "The isNavigationRequest attribute is correct"
+ );
+ }
+}