summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/test/browser_inspector_fission_frame_navigation.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/inspector/test/browser_inspector_fission_frame_navigation.js163
1 files changed, 163 insertions, 0 deletions
diff --git a/devtools/client/inspector/test/browser_inspector_fission_frame_navigation.js b/devtools/client/inspector/test/browser_inspector_fission_frame_navigation.js
new file mode 100644
index 0000000000..7ac3b51586
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_fission_frame_navigation.js
@@ -0,0 +1,163 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const EXAMPLE_COM_URI =
+ "https://example.com/document-builder.sjs?html=<div id=com>com";
+const EXAMPLE_NET_URI =
+ "https://example.net/document-builder.sjs?html=<div id=net>net";
+
+const ORG_URL_ROOT = URL_ROOT.replace("example.com", "example.org");
+const TEST_ORG_URI =
+ ORG_URL_ROOT + "doc_inspector_fission_frame_navigation.html";
+
+add_task(async function () {
+ const { inspector } = await openInspectorForURL(TEST_ORG_URI);
+ const tree = `
+ id="root"
+ iframe
+ #document
+ html
+ head
+ body
+ id="org"`;
+ // Note: the assertMarkupViewAsTree uses very high level APIs and is similar
+ // to what should happen when a user interacts with the markup view.
+ // It is important to avoid explicitly fetching walkers or node fronts during
+ // the test, as it might cause reparenting of remote frames and make the test
+ // succeed without actually testing that the feature works correctly.
+ await assertMarkupViewAsTree(tree, "#root", inspector);
+
+ await navigateIframeTo(inspector, EXAMPLE_COM_URI);
+ const treeAfterLoadingCom = `
+ id="root"
+ iframe
+ #document
+ html
+ head
+ body
+ id="com"`;
+ await assertMarkupViewAsTree(treeAfterLoadingCom, "#root", inspector);
+
+ await navigateIframeTo(inspector, EXAMPLE_NET_URI);
+ const treeAfterLoadingNet = `
+ id="root"
+ iframe
+ #document
+ html
+ head
+ body
+ id="net"`;
+ await assertMarkupViewAsTree(treeAfterLoadingNet, "#root", inspector);
+});
+
+/**
+ * This test will check the behavior when navigating a frame which is not
+ * visible in the markup view, because its parentNode has not been expanded yet.
+ *
+ * We expect a root-node resource to be emitted, but ideally we should not
+ * initialize the walker and inspector actors for the target of this root-node
+ * resource.
+ */
+add_task(async function navigateFrameNotExpandedInMarkupView() {
+ if (!isFissionEnabled()) {
+ // This test only makes sense with Fission and remote frames, otherwise the
+ // root-node resource will not be emitted for a frame navigation.
+ return;
+ }
+
+ const { inspector } = await openInspectorForURL(TEST_ORG_URI);
+ const resourceCommand = inspector.toolbox.resourceCommand;
+
+ // At this stage the expected layout of the markup view is
+ // v html (expanded)
+ // v body (expanded)
+ // > p (collapsed)
+ // > div (collapsed)
+ //
+ // The iframe we are about to navigate is therefore hidden and we are not
+ // watching it - ie, it is not in the list of known NodeFronts/Actors.
+ const resource = await navigateIframeTo(inspector, EXAMPLE_COM_URI);
+
+ is(
+ resource.resourceType,
+ resourceCommand.TYPES.ROOT_NODE,
+ "A resource with resourceType ROOT_NODE was received when navigating"
+ );
+
+ // This highlights what doesn't work with the current approach.
+ // Since the root-node resource is a NodeFront watched via the WalkerFront,
+ // watching it for a new remote frame target implies initializing the
+ // inspector & walker fronts.
+ //
+ // If the resource was not a front (eg ContentDOMreference?) and was emitted
+ // by the target actor instead of the walker actor, the client can decide if
+ // the inspector and walker fronts should be initialized or not.
+ //
+ // In this test scenario, the children of the iframe were not known by the
+ // inspector before this navigation. Per the explanation above, the new target
+ // should not have an already instantiated inspector front.
+ //
+ // This should be fixed when implementing the RootNode resource on the server
+ // in https://bugzilla.mozilla.org/show_bug.cgi?id=1644190
+ todo(
+ !resource.targetFront.getCachedFront("inspector"),
+ "The inspector front for the new target should not be initialized"
+ );
+});
+
+async function navigateIframeTo(inspector, url) {
+ info("Navigate the test iframe to " + url);
+
+ const { commands } = inspector;
+ const { resourceCommand } = inspector.toolbox;
+ const onTargetProcessed = waitForTargetProcessed(commands, url);
+
+ const { onResource: onNewRoot } = await resourceCommand.waitForNextResource(
+ resourceCommand.TYPES.ROOT_NODE,
+ {
+ ignoreExistingResources: true,
+ }
+ );
+
+ info("Update the src attribute of the iframe tag");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [url], function (_url) {
+ content.document.querySelector("iframe").setAttribute("src", _url);
+ });
+
+ info("Wait for frameLoad/newRoot to resolve");
+ const newRootResult = await onNewRoot;
+
+ info("Wait for pending children updates");
+ await inspector.markup._waitForChildren();
+
+ if (isFissionEnabled()) {
+ info("Wait until the new target has been processed by TargetCommand");
+ await onTargetProcessed;
+ }
+
+ // Note: the newRootResult changes when the test runs with or without fission.
+ return newRootResult;
+}
+
+/**
+ * Returns a promise that waits until the provided commands's TargetCommand has fully
+ * processed a target with the provided URL.
+ * This will avoid navigating again before the new resource command have fully
+ * attached to the new target.
+ */
+function waitForTargetProcessed(commands, url) {
+ return new Promise(resolve => {
+ const onTargetProcessed = targetFront => {
+ if (targetFront.url !== encodeURI(url)) {
+ return;
+ }
+ commands.targetCommand.off(
+ "processed-available-target",
+ onTargetProcessed
+ );
+ resolve();
+ };
+ commands.targetCommand.on("processed-available-target", onTargetProcessed);
+ });
+}