diff options
Diffstat (limited to 'devtools/client/responsive/test/browser/browser_ext_messaging.js')
-rw-r--r-- | devtools/client/responsive/test/browser/browser_ext_messaging.js | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/devtools/client/responsive/test/browser/browser_ext_messaging.js b/devtools/client/responsive/test/browser/browser_ext_messaging.js new file mode 100644 index 0000000000..5d1b5cf317 --- /dev/null +++ b/devtools/client/responsive/test/browser/browser_ext_messaging.js @@ -0,0 +1,231 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* eslint-env webextensions */ + +"use strict"; + +const TEST_URL = "https://example.com/"; + +// These allowed rejections are copied from +// browser/components/extensions/test/browser/head.js. +const { PromiseTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PromiseTestUtils.sys.mjs" +); +PromiseTestUtils.allowMatchingRejectionsGlobally( + /Message manager disconnected/ +); +PromiseTestUtils.allowMatchingRejectionsGlobally( + /Receiving end does not exist/ +); + +const extension = ExtensionTestUtils.loadExtension({ + manifest: { + content_scripts: [ + { + matches: [TEST_URL], + js: ["content-script.js"], + run_at: "document_start", + }, + ], + }, + background() { + let currentPort; + + browser.runtime.onConnect.addListener(port => { + currentPort = port; + port.onDisconnect.addListener(() => + browser.test.sendMessage("port-disconnected") + ); + port.onMessage.addListener(msg => + browser.test.sendMessage("port-message-received", msg) + ); + browser.test.sendMessage("port-connected"); + }); + + browser.test.onMessage.addListener(async msg => { + if (msg !== "test:port-message-send") { + browser.test.fail(`Unexpected test message received: ${msg}`); + } + + currentPort.postMessage("ping"); + }); + + browser.test.sendMessage("background:ready"); + }, + files: { + "content-script.js": function contentScript() { + const port = browser.runtime.connect(); + port.onMessage.addListener(msg => port.postMessage(`${msg}-pong`)); + }, + }, +}); + +add_task(async function setup_first_test() { + await extension.startup(); + + await extension.awaitMessage("background:ready"); +}); + +addRDMTaskWithPreAndPost( + TEST_URL, + async function pre_task() { + await extension.awaitMessage("port-connected"); + }, + async function test_port_kept_connected_on_switch_to_RDB() { + extension.sendMessage("test:port-message-send"); + + is( + await extension.awaitMessage("port-message-received"), + "ping-pong", + "Got the expected message back from the content script" + ); + }, + async function post_task() { + extension.sendMessage("test:port-message-send"); + + is( + await extension.awaitMessage("port-message-received"), + "ping-pong", + "Got the expected message back from the content script" + ); + } +); + +add_task(async function cleanup_first_test() { + await extension.awaitMessage("port-disconnected"); + + await extension.unload(); +}); + +addRDMTask(TEST_URL, async function test_tab_sender() { + const extension2 = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["tabs"], + + content_scripts: [ + { + matches: [TEST_URL], + js: ["content-script.js"], + run_at: "document_start", + }, + ], + }, + + async background() { + const TEST_URL = "https://example.com/"; // eslint-disable-line no-shadow + + browser.test.log("Background script init"); + + let extTab; + const contentMessage = new Promise(resolve => { + browser.test.log("Listen to content"); + const listener = async (msg, sender, respond) => { + browser.test.assertEq( + msg, + "hello-from-content", + "Background script got hello-from-content message" + ); + + const tabs = await browser.tabs.query({ + currentWindow: true, + active: true, + }); + browser.test.assertEq( + tabs.length, + 1, + "One tab is active in the current window" + ); + extTab = tabs[0]; + browser.test.log(`Tab: id ${extTab.id}, url ${extTab.url}`); + browser.test.assertEq(extTab.url, TEST_URL, "Tab has the test URL"); + + browser.test.assertTrue(!!sender, "Message has a sender"); + browser.test.assertTrue(!!sender.tab, "Message has a sender.tab"); + browser.test.assertEq( + sender.tab.id, + extTab.id, + "Sender's tab ID matches the RDM tab ID" + ); + browser.test.assertEq( + sender.tab.url, + extTab.url, + "Sender's tab URL matches the RDM tab URL" + ); + + browser.runtime.onMessage.removeListener(listener); + resolve(); + }; + browser.runtime.onMessage.addListener(listener); + }); + + // Wait for "resume" message so we know the content script is also ready. + await new Promise(resolve => { + browser.test.onMessage.addListener(resolve); + browser.test.sendMessage("background-script-ready"); + }); + + await contentMessage; + + browser.test.log("Send message from background to content"); + const contentSender = await browser.tabs.sendMessage( + extTab.id, + "hello-from-background" + ); + browser.test.assertEq( + contentSender.id, + browser.runtime.id, + "The sender ID in content matches this extension" + ); + + browser.test.notifyPass("rdm-messaging"); + }, + + files: { + "content-script.js": async function () { + browser.test.log("Content script init"); + + browser.test.log("Listen to background"); + browser.runtime.onMessage.addListener((msg, sender, respond) => { + browser.test.assertEq( + msg, + "hello-from-background", + "Content script got hello-from-background message" + ); + + browser.test.assertTrue(!!sender, "Message has a sender"); + browser.test.assertTrue(!!sender.id, "Message has a sender.id"); + + const { id } = sender; + respond({ id }); + }); + + // Wait for "resume" message so we know the background script is also ready. + await new Promise(resolve => { + browser.test.onMessage.addListener(resolve); + browser.test.sendMessage("content-script-ready"); + }); + + browser.test.log("Send message from content to background"); + browser.runtime.sendMessage("hello-from-content"); + }, + }, + }); + + const contentScriptReady = extension2.awaitMessage("content-script-ready"); + const backgroundScriptReady = extension2.awaitMessage( + "background-script-ready" + ); + const finish = extension2.awaitFinish("rdm-messaging"); + + await extension2.startup(); + + // It appears the background script and content script can loaded in either order, so + // we'll wait for the both to listen before proceeding. + await backgroundScriptReady; + await contentScriptReady; + extension2.sendMessage("resume"); + + await finish; + await extension2.unload(); +}); |