summaryrefslogtreecommitdiffstats
path: root/devtools/client/framework/test/browser_toolbox_backward_forward_navigation.js
blob: 413e6b4b1f815ee32069cea9904904187da16c7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

// The test can take a while to run
requestLongerTimeout(3);

const FILENAME = "doc_backward_forward_navigation.html";
const TEST_URI_ORG = `${URL_ROOT_ORG_SSL}${FILENAME}`;
const TEST_URI_COM = `${URL_ROOT_COM_SSL}${FILENAME}`;

Services.scriptloader.loadSubScript(
  "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js",
  this
);

add_task(async function testMultipleNavigations() {
  // Disable bfcache for Fission for now.
  // If Fission is disabled, the pref is no-op.
  await SpecialPowers.pushPrefEnv({
    set: [["fission.bfcacheInParent", false]],
  });

  info(
    "Test that DevTools works fine after multiple backward/forward navigations"
  );
  // Don't show the third panel to limit the logs and activity.
  await pushPref("devtools.inspector.three-pane-enabled", false);
  await pushPref("devtools.inspector.activeSidebar", "ruleview");
  const DATA_URL = `data:text/html,<meta charset=utf8>`;
  const tab = await addTab(DATA_URL);

  // Select the debugger so there will be more activity
  const toolbox = await openToolboxForTab(tab, "jsdebugger");
  const inspector = await toolbox.selectTool("inspector");

  info("Navigate to the ORG test page");
  // We don't use `navigateTo` as the page is adding stylesheets and js files which might
  // delay the load event indefinitely (and we don't need for anything to be loaded, or
  // ready, just to register the initial navigation so we can go back and forth between urls)
  let onLocationChange = BrowserTestUtils.waitForLocationChange(
    gBrowser,
    TEST_URI_ORG
  );
  BrowserTestUtils.loadURIString(gBrowser, TEST_URI_ORG);
  await onLocationChange;

  info("And then navigate to a different origin");
  onLocationChange = BrowserTestUtils.waitForLocationChange(
    gBrowser,
    TEST_URI_COM
  );
  BrowserTestUtils.loadURIString(gBrowser, TEST_URI_COM);
  await onLocationChange;

  info(
    "Navigate backward and forward multiple times between the two origins, with different delays"
  );
  await navigateBackAndForth(TEST_URI_ORG, TEST_URI_COM);

  // Navigate one last time to a document with less activity so we don't have to deal
  // with pending promises when we destroy the toolbox
  const onInspectorReloaded = inspector.once("reloaded");
  info("Navigate to final document");
  await navigateTo(`${TEST_URI_ORG}?no-mutation`);
  info("Waiting for inspector to reload…");
  await onInspectorReloaded;
  info("-> inspector reloaded");
  await checkToolboxState(toolbox);
});

add_task(async function testSingleBackAndForthInstantNavigation() {
  // Disable bfcache for Fission for now.
  // If Fission is disabled, the pref is no-op.
  await SpecialPowers.pushPrefEnv({
    set: [["fission.bfcacheInParent", false]],
  });

  info(
    "Test that DevTools works fine after navigating backward and forward right after"
  );

  // Don't show the third panel to limit the logs and activity.
  await pushPref("devtools.inspector.three-pane-enabled", false);
  await pushPref("devtools.inspector.activeSidebar", "ruleview");
  const DATA_URL = `data:text/html,<meta charset=utf8>`;
  const tab = await addTab(DATA_URL);

  // Select the debugger so there will be more activity
  const toolbox = await openToolboxForTab(tab, "jsdebugger");
  const inspector = await toolbox.selectTool("inspector");

  info("Navigate to a different origin");
  await navigateTo(TEST_URI_COM);

  info("Then navigate back, and forth immediatly");
  // We can't call goBack and right away goForward as goForward and even the call to navigateTo
  // a bit later might be ignored. So we wait at least for the location to change.
  await safelyGoBack(DATA_URL);
  await safelyGoForward(TEST_URI_COM);

  // Navigate one last time to a document with less activity so we don't have to deal
  // with pending promises when we destroy the toolbox
  const onInspectorReloaded = inspector.once("reloaded");
  info("Navigate to final document");
  await navigateTo(`${TEST_URI_ORG}?no-mutation`);
  info("Waiting for inspector to reload…");
  await onInspectorReloaded;
  info("-> inspector reloaded");
  await checkToolboxState(toolbox);
});

async function checkToolboxState(toolbox) {
  info("Check that the toolbox toolbar is still visible");
  const toolboxTabsEl = toolbox.doc.querySelector(".toolbox-tabs");
  ok(toolboxTabsEl, "Toolbar is still visible");

  info(
    "Check that the markup view is rendered correctly and elements can be selected"
  );
  const inspector = await toolbox.selectTool("inspector");
  await waitFor(
    () =>
      inspector.markup &&
      inspector.markup.win.document.body.innerText.includes(
        `<body class="no-mutation">`
      ),
    `wait for <body class="no-mutation"> to be displayed in the markup view, got: ${inspector.markup?.win.document.body.innerText}`,
    100,
    100
  );
  ok(true, "the markup view is still rendered fine");
  await selectNode("ul.logs", inspector);
  ok(true, "Nodes can be selected");

  info("Check that the debugger has some sources");
  const dbgPanel = await toolbox.selectTool("jsdebugger");
  const dbg = createDebuggerContext(toolbox);

  info(`Wait for ${FILENAME} to be displayed in the debugger source panel`);
  const rootNode = await waitFor(() =>
    dbgPanel.panelWin.document.querySelector(selectors.sourceTreeRootNode)
  );
  await expandAllSourceNodes(dbg, rootNode);
  const sourcesTreeScriptNode = await waitFor(() =>
    findSourceNodeWithText(dbg, FILENAME)
  );

  ok(
    sourcesTreeScriptNode.innerText.includes(FILENAME),
    "The debugger has the expected source"
  );
}

async function navigateBackAndForth(
  expectedUrlAfterBackwardNavigation,
  expectedUrlAfterForwardNavigation
) {
  const delays = [100, 0, 500];
  for (const delay of delays) {
    // For each delays, do 3 back/forth navigations
    for (let i = 0; i < 3; i++) {
      await safelyGoBack(expectedUrlAfterBackwardNavigation);
      await wait(delay);
      await safelyGoForward(expectedUrlAfterForwardNavigation);
      await wait(delay);
    }
  }
}

async function safelyGoBack(expectedUrl) {
  const onLocationChange = BrowserTestUtils.waitForLocationChange(
    gBrowser,
    expectedUrl
  );
  gBrowser.goBack();
  await onLocationChange;
}

async function safelyGoForward(expectedUrl) {
  const onLocationChange = BrowserTestUtils.waitForLocationChange(
    gBrowser,
    expectedUrl
  );
  gBrowser.goForward();
  await onLocationChange;
}