/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set sts=2 sw=2 et tw=80: */ /* eslint-disable mozilla/no-arbitrary-setTimeout */ "use strict"; add_task(async function testTabEvents() { async function background() { /** The list of active tab ID's */ let tabIds = []; /** * Stores the events that fire for each tab. * * events { * tabId1: [event1, event2, ...], * tabId2: [event1, event2, ...], * } */ let events = {}; browser.tabs.onActivated.addListener(info => { if (info.tabId in events) { events[info.tabId].push("onActivated"); } else { events[info.tabId] = ["onActivated"]; } }); browser.tabs.onCreated.addListener(info => { if (info.id in events) { events[info.id].push("onCreated"); } else { events[info.id] = ["onCreated"]; } }); browser.tabs.onHighlighted.addListener(info => { if (info.tabIds[0] in events) { events[info.tabIds[0]].push("onHighlighted"); } else { events[info.tabIds[0]] = ["onHighlighted"]; } }); /** * Asserts that the expected events are fired for the tab with id = tabId. * The events associated to the specified tab are removed after this check is made. * * @param {number} tabId * @param {Array} expectedEvents */ async function expectEvents(tabId, expectedEvents) { browser.test.log(`Expecting events: ${expectedEvents.join(", ")}`); // Wait up to 5000 ms for the expected number of events. for ( let i = 0; i < 50 && (!events[tabId] || events[tabId].length < expectedEvents.length); i++ ) { await new Promise(resolve => setTimeout(resolve, 100)); } browser.test.assertEq( expectedEvents.length, events[tabId].length, `Got expected number of events for ${tabId}` ); for (let name of expectedEvents) { browser.test.assertTrue( events[tabId].includes(name), `Got expected ${name} event` ); } if (expectedEvents.includes("onCreated")) { browser.test.assertEq( events[tabId].indexOf("onCreated"), 0, "onCreated happened first" ); } delete events[tabId]; } /** * Opens a new tab and asserts that the correct events are fired. * * @param {number} windowId */ async function openTab(windowId) { browser.test.assertEq( 0, Object.keys(events).length, "No events remaining before testing openTab." ); let tab = await browser.tabs.create({ windowId }); tabIds.push(tab.id); browser.test.log(`Opened tab ${tab.id}`); await expectEvents(tab.id, ["onCreated", "onActivated", "onHighlighted"]); } /** * Opens a new window and asserts that the correct events are fired. * * @param {Array} urls A list of urls for which to open tabs in the new window. */ async function openWindow(urls) { browser.test.assertEq( 0, Object.keys(events).length, "No events remaining before testing openWindow." ); let window = await browser.windows.create({ url: urls }); browser.test.log(`Opened new window ${window.id}`); for (let [i] of urls.entries()) { let tab = window.tabs[i]; tabIds.push(tab.id); let expectedEvents = ["onCreated", "onActivated", "onHighlighted"]; if (i !== 0) { expectedEvents.splice(1); } await expectEvents(window.tabs[i].id, expectedEvents); } } /** * Highlights an existing tab and asserts that the correct events are fired. * * @param {number} tabId */ async function highlightTab(tabId) { browser.test.assertEq( 0, Object.keys(events).length, "No events remaining before testing highlightTab." ); browser.test.log(`Highlighting tab ${tabId}`); let tab = await browser.tabs.update(tabId, { active: true }); browser.test.assertEq(tab.id, tabId, `Tab ${tab.id} highlighted`); await expectEvents(tab.id, ["onActivated", "onHighlighted"]); } /** * The main entry point to the tests. */ let tabs = await browser.tabs.query({ active: true, currentWindow: true }); let activeWindow = tabs[0].windowId; await Promise.all([ openTab(activeWindow), openTab(activeWindow), openTab(activeWindow), ]); await Promise.all([ highlightTab(tabIds[0]), highlightTab(tabIds[1]), highlightTab(tabIds[2]), ]); await Promise.all([ openWindow(["http://example.com"]), openWindow(["http://example.com", "http://example.org"]), openWindow([ "http://example.com", "http://example.org", "http://example.net", ]), ]); browser.test.assertEq( 0, Object.keys(events).length, "No events remaining after tests." ); await Promise.all(tabIds.map(id => browser.tabs.remove(id))); browser.test.notifyPass("tabs.highlight"); } let extension = ExtensionTestUtils.loadExtension({ manifest: { permissions: ["tabs"], }, background, }); await extension.startup(); await extension.awaitFinish("tabs.highlight"); await extension.unload(); });