diff options
Diffstat (limited to '')
-rw-r--r-- | mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html new file mode 100644 index 0000000000..cd708d942a --- /dev/null +++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html @@ -0,0 +1,302 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Tabs Events Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script> + <script type="text/javascript" src="head.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="text/javascript"> +"use strict"; + +add_task(async function testTabEvents() { + async function background() { + const events = []; + let eventPromise; + const checkEvents = () => { + if (eventPromise && events.length >= eventPromise.names.length) { + eventPromise.resolve(); + } + }; + + browser.tabs.onCreated.addListener(tab => { + events.push({type: "onCreated", tab}); + checkEvents(); + }); + + browser.tabs.onAttached.addListener((tabId, info) => { + events.push(Object.assign({type: "onAttached", tabId}, info)); + checkEvents(); + }); + + browser.tabs.onDetached.addListener((tabId, info) => { + events.push(Object.assign({type: "onDetached", tabId}, info)); + checkEvents(); + }); + + browser.tabs.onRemoved.addListener((tabId, info) => { + events.push(Object.assign({type: "onRemoved", tabId}, info)); + checkEvents(); + }); + + browser.tabs.onMoved.addListener((tabId, info) => { + events.push(Object.assign({type: "onMoved", tabId}, info)); + checkEvents(); + }); + + async function expectEvents(names) { + browser.test.log(`Expecting events: ${names.join(", ")}`); + + await new Promise(resolve => { + eventPromise = {names, resolve}; + checkEvents(); + }); + + browser.test.assertEq(names.length, events.length, "Got expected number of events"); + for (const [i, name] of names.entries()) { + browser.test.assertEq(name, i in events && events[i].type, + `Got expected ${name} event`); + } + return events.splice(0); + } + + try { + browser.test.log("Create tab"); + const tab = await browser.tabs.create({url: "about:blank"}); + const oldIndex = tab.index; + + const [created] = await expectEvents(["onCreated"]); + browser.test.assertEq(tab.id, created.tab.id, "Got expected tab ID"); + browser.test.assertEq(oldIndex, created.tab.index, "Got expected tab index"); + + + browser.test.log("Remove tab"); + await browser.tabs.remove(tab.id); + const [removed] = await expectEvents(["onRemoved"]); + + browser.test.assertEq(tab.id, removed.tabId, "Expected removed tab ID"); + browser.test.assertEq(tab.windowId, removed.windowId, "Expected removed tab window ID"); + // Note: We want to test for the actual boolean value false here. + browser.test.assertEq(false, removed.isWindowClosing, "Expected isWindowClosing value"); + + browser.test.notifyPass("tabs-events"); + } catch (e) { + browser.test.fail(`${e} :: ${e.stack}`); + browser.test.notifyFail("tabs-events"); + } + } + + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + "permissions": ["tabs"], + }, + background, + }); + + await extension.startup(); + await extension.awaitFinish("tabs-events"); + await extension.unload(); +}); + +add_task(async function testTabRemovalEvent() { + async function background() { + function awaitLoad(tabId) { + return new Promise(resolve => { + browser.tabs.onUpdated.addListener(function listener(tabId_, changed, tab) { + if (tabId == tabId_ && changed.status == "complete") { + browser.tabs.onUpdated.removeListener(listener); + resolve(); + } + }); + }); + } + + chrome.tabs.onRemoved.addListener((tabId, info) => { + browser.test.log("Make sure the removed tab is not available in the tabs.query callback."); + chrome.tabs.query({}, tabs => { + for (const tab of tabs) { + browser.test.assertTrue(tab.id != tabId, "Tab query should not include removed tabId"); + } + browser.test.notifyPass("tabs-events"); + }); + }); + + try { + const url = "http://example.com/mochitest/mobile/android/components/extensions/test/mochitest/context.html"; + const tab = await browser.tabs.create({url: url}); + await awaitLoad(tab.id); + + await browser.tabs.remove(tab.id); + } catch (e) { + browser.test.fail(`${e} :: ${e.stack}`); + browser.test.notifyFail("tabs-events"); + } + } + + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + "permissions": ["tabs"], + }, + background, + }); + + await extension.startup(); + await extension.awaitFinish("tabs-events"); + await extension.unload(); +}); + +add_task(async function testTabActivationEvent() { + // TODO bug 1565536: tabs.onActivated is not supported in GeckoView. + if (true) { + todo(false, "skipping testTabActivationEvent"); + return; + } + async function background() { + function makeExpectable() { + let expectation = null, resolver = null; + const expectable = param => { + if (expectation === null) { + browser.test.fail("unexpected call to expectable"); + } else { + try { + resolver(expectation(param)); + } catch (e) { + resolver(Promise.reject(e)); + } finally { + expectation = null; + } + } + }; + expectable.expect = e => { + expectation = e; + return new Promise(r => { resolver = r; }); + }; + return expectable; + } + try { + const listener = makeExpectable(); + browser.tabs.onActivated.addListener(listener); + + const [tab0] = await browser.tabs.query({active: true}); + const [, tab1] = await Promise.all([ + listener.expect(info => { + browser.test.assertEq(tab0.id, info.previousTabId, "Got expected previousTabId"); + }), + browser.tabs.create({url: "about:blank"}), + ]); + const [, tab2] = await Promise.all([ + listener.expect(info => { + browser.test.assertEq(tab1.id, info.previousTabId, "Got expected previousTabId"); + }), + browser.tabs.create({url: "about:blank"}), + ]); + + await Promise.all([ + listener.expect(info => { + browser.test.assertEq(tab1.id, info.tabId, "Got expected tabId"); + browser.test.assertEq(tab2.id, info.previousTabId, "Got expected previousTabId"); + }), + browser.tabs.update(tab1.id, {active: true}), + ]); + + await Promise.all([ + listener.expect(info => { + browser.test.assertEq(tab2.id, info.tabId, "Got expected tabId"); + browser.test.assertEq(undefined, info.previousTabId, "previousTabId should not be defined when previous tab was closed"); + }), + browser.tabs.remove(tab1.id), + ]); + + browser.tabs.onActivated.removeListener(listener); + await browser.tabs.remove(tab2.id); + + browser.test.notifyPass("tabs-events"); + } catch (e) { + browser.test.fail(`${e} :: ${e.stack}`); + browser.test.notifyFail("tabs-events"); + } + } + + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + "permissions": ["tabs"], + }, + + background, + }); + + await extension.startup(); + await extension.awaitFinish("tabs-events"); + await extension.unload(); +}); + +add_task(async function test_tabs_event_page() { + function background() { + const EVENTS = [ + "onActivated", + "onRemoved", + "onUpdated", + ]; + browser.tabs.onCreated.addListener(() => { + browser.test.sendMessage("onCreated"); + }); + for (const event of EVENTS) { + browser.tabs[event].addListener(() => { + }); + } + browser.test.onMessage.addListener(async msg => { + if (msg === "createTab") { + await browser.tabs.create({url: "about:blank"}); + } + }); + browser.test.sendMessage("ready"); + } + + const apiEvents = ["onActivated", "onCreated", "onRemoved", "onUpdated"]; + const apiNs = "tabs"; + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + browser_specific_settings: { gecko: { id: "eventpage@tabs" } }, + "permissions": ["tabs"], + background: { persistent: false }, + }, + background, + }); + + await extension.startup(); + info("Wait for event page to be started"); + await extension.awaitMessage("ready"); + // Sanity check + info("Wait for tabs.onCreated listener call"); + extension.sendMessage("createTab"); + await extension.awaitMessage("onCreated"); + + // on startup, all event listeners should not be primed + await assertPersistentListeners(extension, apiNs, apiEvents, { primed: false }); + + // when the extension is killed, all event listeners should be primed + info("Terminate event page"); + await extension.terminateBackground({ disableResetIdleForTest: true }); + await assertPersistentListeners(extension, apiNs, apiEvents, { primed: true }); + + // on start up again, all event listeners should not be primed + info("Wake up event page on a new tabs.onCreated event"); + const newWin = window.open(); + info("Wait for event page to be restarted"); + await extension.awaitMessage("ready"); + info("Wait for the primed tabs.onCreated to be received by the event page"); + await extension.awaitMessage("onCreated"); + await assertPersistentListeners(extension, apiNs, apiEvents, { primed: false }); + + await extension.unload(); + newWin.close(); +}); + +</script> + +</body> +</html> |