diff options
Diffstat (limited to 'devtools/server/tests/browser/browser_navigateEvents.js')
-rw-r--r-- | devtools/server/tests/browser/browser_navigateEvents.js | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/devtools/server/tests/browser/browser_navigateEvents.js b/devtools/server/tests/browser/browser_navigateEvents.js new file mode 100644 index 0000000000..d46dea96de --- /dev/null +++ b/devtools/server/tests/browser/browser_navigateEvents.js @@ -0,0 +1,198 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const URL1 = MAIN_DOMAIN + "navigate-first.html"; +const URL2 = MAIN_DOMAIN + "navigate-second.html"; + +var isE10s = Services.appinfo.browserTabsRemoteAutostart; + +SpecialPowers.pushPrefEnv({ + set: [["dom.require_user_interaction_for_beforeunload", false]], +}); + +SpecialPowers.pushPrefEnv({ + set: [["prompts.contentPromptSubDialog", false]], +}); + +var signalAllEventsReceived; +var onAllEventsReceived = new Promise(resolve => { + signalAllEventsReceived = resolve; +}); + +// State machine to check events order +var i = 0; +function assertEvent(event, data) { + switch (i++) { + case 0: + is(event, "request", "Get first page load"); + is(data, URL1); + break; + case 1: + is(event, "load-new-document", "Ask to load the second page"); + break; + case 2: + is(event, "unload-dialog", "We get the dialog on first page unload"); + break; + case 3: + is( + event, + "will-navigate", + "The very first event is will-navigate on server side" + ); + is(data.newURI, URL2, "newURI property is correct"); + break; + case isE10s ? 4 : 5: // When e10s is disabled tabNavigated/request order is swapped + is( + event, + "tabNavigated", + "After the request, the client receive tabNavigated" + ); + is(data.state, "start", "state is start"); + is(data.url, URL2, "url property is correct"); + is(data.nativeConsoleAPI, true, "nativeConsoleAPI is correct"); + break; + case isE10s ? 5 : 4: + is( + event, + "request", + "RDP is async with messageManager, the request happens after will-navigate" + ); + is(data, URL2); + break; + case 6: + is(event, "DOMContentLoaded"); + is(data.readyState, "interactive"); + break; + case 7: + is(event, "load"); + is(data.readyState, "complete"); + break; + case 8: + is( + event, + "navigate", + "Then once the second doc is loaded, we get the navigate event" + ); + break; + case 9: + is(event, "tabNavigated", "Finally, the receive the client event"); + is(data.state, "stop", "state is stop"); + is(data.url, URL2, "url property is correct"); + is(data.nativeConsoleAPI, true, "nativeConsoleAPI is correct"); + + signalAllEventsReceived(); + break; + } +} + +function waitForOnBeforeUnloadDialog(browser, callback) { + browser.addEventListener( + "DOMWillOpenModalDialog", + async function(event) { + const stack = browser.parentNode; + const dialogs = stack.getElementsByTagName("tabmodalprompt"); + await waitUntil(() => dialogs[0]); + const { button0, button1 } = browser.tabModalPromptBox.getPrompt( + dialogs[0] + ).ui; + callback(button0, button1); + }, + { capture: true, once: true } + ); +} + +var httpObserver = function(subject, topic, state) { + const channel = subject.QueryInterface(Ci.nsIHttpChannel); + const url = channel.URI.spec; + // Only listen for our document request, as many other requests can happen + if (url == URL1 || url == URL2) { + assertEvent("request", url); + } +}; +Services.obs.addObserver(httpObserver, "http-on-modify-request"); + +function onMessage({ data }) { + assertEvent(data.event, data.data); +} + +async function connectAndAttachTab(tab) { + const target = await TargetFactory.forTab(tab); + await target.attach(); + const actorID = target.actorID; + target.on("tabNavigated", function(packet) { + assertEvent("tabNavigated", packet); + }); + // In order to listen to internal will-navigate/navigate events + target.on("will-navigate", function(data) { + assertEvent("will-navigate", { + newURI: data.url, + }); + }); + target.on("navigate", () => assertEvent("navigate")); + return { target, actorID }; +} + +add_task(async function() { + // Open a test tab + const browser = await addTab(URL1); + + // Listen for alert() call being made in navigate-first during unload + waitForOnBeforeUnloadDialog(browser, function(btnLeave, btnStay) { + assertEvent("unload-dialog"); + // accept to quit this page to another + btnLeave.click(); + }); + + // Listen for messages sent by the content task + browser.messageManager.addMessageListener("devtools-test:event", onMessage); + + const tab = gBrowser.getTabForBrowser(browser); + const { target, actorID } = await connectAndAttachTab(tab); + await ContentTask.spawn(browser, [actorID], async function(actorId) { + // Forward DOMContentLoaded and load events + addEventListener( + "DOMContentLoaded", + function() { + sendSyncMessage("devtools-test:event", { + event: "DOMContentLoaded", + data: { readyState: content.document.readyState }, + }); + }, + { capture: true } + ); + addEventListener( + "load", + function() { + sendSyncMessage("devtools-test:event", { + event: "load", + data: { readyState: content.document.readyState }, + }); + }, + { capture: true } + ); + }); + + // Load another document in this doc to dispatch these events + assertEvent("load-new-document"); + + // Use BrowserTestUtils instead of navigateTo as there is no toolbox opened + const onBrowserLoaded = BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser + ); + BrowserTestUtils.loadURI(gBrowser.selectedBrowser, URL2); + await onBrowserLoaded; + + // Wait for all events to be received + await onAllEventsReceived; + + // Cleanup + browser.messageManager.removeMessageListener( + "devtools-test:event", + onMessage + ); + await target.destroy(); + Services.obs.addObserver(httpObserver, "http-on-modify-request"); + DevToolsServer.destroy(); +}); |