Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* -*- 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<string>} 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]),
]);
// If we open these windows in parallel, there is a risk
// that a window will be occluded by the next one before
// it can finish first paint, which will prevent
// the firing of browser-delayed-startup-finished
await openWindow(["http://example.com"]);
await openWindow(["http://example.com", "http://example.org"]);
await openWindow([
]);
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();
});