Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

  • This test gets skipped with pattern: os == 'linux' && os_version == '18.04' && asan OR os == 'linux' && os_version == '18.04' && tsan OR os == 'linux' && os_version == '18.04' && debug OR os == 'linux' && os_version == '18.04' && socketprocess_networking
  • Manifest: browser/components/extensions/test/browser/browser.toml
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
async function runTests(options) {
async function background(getTests) {
let manifest = browser.runtime.getManifest();
let { manifest_version } = manifest;
const action = manifest_version < 3 ? "browserAction" : "action";
async function checkExtAPIDetails(expecting, details) {
let title = await browser[action].getTitle(details);
browser.test.assertEq(
expecting.title,
title,
"expected value from getTitle"
);
let popup = await browser[action].getPopup(details);
browser.test.assertEq(
expecting.popup,
popup,
"expected value from getPopup"
);
let badge = await browser[action].getBadgeText(details);
browser.test.assertEq(
expecting.badge,
badge,
"expected value from getBadge"
);
let badgeBackgroundColor = await browser[action].getBadgeBackgroundColor(
details
);
browser.test.assertEq(
String(expecting.badgeBackgroundColor),
String(badgeBackgroundColor),
"expected value from getBadgeBackgroundColor"
);
let badgeTextColor = await browser[action].getBadgeTextColor(details);
browser.test.assertEq(
String(expecting.badgeTextColor),
String(badgeTextColor),
"expected value from getBadgeTextColor"
);
let enabled = await browser[action].isEnabled(details);
browser.test.assertEq(
expecting.enabled,
enabled,
"expected value from isEnabled"
);
}
let tabs = [];
let windows = [];
let tests = getTests(tabs, windows);
{
let tabId = 0xdeadbeef;
let calls = [
() => browser[action].enable(tabId),
() => browser[action].disable(tabId),
() => browser[action].setTitle({ tabId, title: "foo" }),
() => browser[action].setIcon({ tabId, path: "foo.png" }),
() => browser[action].setPopup({ tabId, popup: "foo.html" }),
() => browser[action].setBadgeText({ tabId, text: "foo" }),
() =>
browser[action].setBadgeBackgroundColor({
tabId,
color: [0xff, 0, 0, 0xff],
}),
() =>
browser[action].setBadgeTextColor({
tabId,
color: [0, 0xff, 0xff, 0xff],
}),
];
for (let call of calls) {
await browser.test.assertRejects(
new Promise(resolve => resolve(call())),
RegExp(`Invalid tab ID: ${tabId}`),
"Expected invalid tab ID error"
);
}
}
// Runs the next test in the `tests` array, checks the results,
// and passes control back to the outer test scope.
function nextTest() {
let test = tests.shift();
test(async (expectTab, expectWindow, expectGlobal, expectDefault) => {
expectGlobal = { ...expectDefault, ...expectGlobal };
expectWindow = { ...expectGlobal, ...expectWindow };
expectTab = { ...expectWindow, ...expectTab };
// Check that the API returns the expected values, and then
// run the next test.
let [{ windowId, id: tabId }] = await browser.tabs.query({
active: true,
currentWindow: true,
});
await checkExtAPIDetails(expectTab, { tabId });
await checkExtAPIDetails(expectWindow, { windowId });
await checkExtAPIDetails(expectGlobal, {});
// Check that the actual icon has the expected values, then
// run the next test.
browser.test.sendMessage("nextTest", expectTab, windowId, tests.length);
});
}
browser.test.onMessage.addListener(msg => {
if (msg != "runNextTest") {
browser.test.fail("Expecting 'runNextTest' message");
}
nextTest();
});
let [{ id, windowId }] = await browser.tabs.query({
active: true,
currentWindow: true,
});
tabs.push(id);
windows.push(windowId);
nextTest();
}
let extension = ExtensionTestUtils.loadExtension({
manifest: options.manifest,
files: options.files || {},
background: `(${background})(${options.getTests})`,
});
function serializeColor([r, g, b, a]) {
if (a === 255) {
return `rgb(${r}, ${g}, ${b})`;
}
return `rgba(${r}, ${g}, ${b}, ${a / 255})`;
}
let browserActionId;
async function checkWidgetDetails(details, windowId) {
let { document } = Services.wm.getOuterWindowWithId(windowId);
if (!browserActionId) {
browserActionId = `${makeWidgetId(extension.id)}-browser-action`;
}
let node = document.getElementById(browserActionId);
let button = node.firstElementChild;
ok(button, "button exists");
let title = details.title || options.manifest.name;
// NOTE: resorting to waitForCondition to prevent frequent
// intermittent failures due to multiple action API calls
// being queued.
if (getListStyleImage(button) !== details.icon) {
info(`wait for action icon url to be set to ${details.icon}`);
await TestUtils.waitForCondition(
() => getListStyleImage(button) === details.icon,
"Wait for the expected icon URL to be set"
);
}
// NOTE: resorting to waitForCondition to prevent frequent
// intermittent failures due to multiple action API calls
// being queued.
if (button.getAttribute("tooltiptext") !== title) {
info(`wait for action tooltiptext to be set to ${title}`);
await TestUtils.waitForCondition(
() => button.getAttribute("tooltiptext") === title,
"Wait for expected title to be set"
);
}
is(getListStyleImage(button), details.icon, "icon URL is correct");
is(button.getAttribute("tooltiptext"), title, "image title is correct");
is(button.getAttribute("label"), title, "image label is correct");
is(
button.getAttribute("badge") || "",
details.badge,
"badge text is correct"
);
is(
button.getAttribute("disabled") == "true",
!details.enabled,
"disabled state is correct"
);
if (details.badge) {
let badge = button.badgeLabel;
let style = window.getComputedStyle(badge);
let expected = {
backgroundColor: serializeColor(details.badgeBackgroundColor),
color: serializeColor(details.badgeTextColor),
};
for (let [prop, value] of Object.entries(expected)) {
// NOTE: resorting to waitForCondition to prevent frequent
// intermittent failures due to multiple action API calls
// being queued.
if (style[prop] !== value) {
info(`wait for badge ${prop} to be set to ${value}`);
await TestUtils.waitForCondition(
() => window.getComputedStyle(badge)[prop] === value,
`Wait for expected badge ${prop} to be set`
);
}
}
}
// TODO: Popup URL.
}
let awaitFinish = new Promise(resolve => {
extension.onMessage(
"nextTest",
async (expecting, windowId, testsRemaining) => {
await promiseAnimationFrame();
await checkWidgetDetails(expecting, windowId);
if (testsRemaining) {
extension.sendMessage("runNextTest");
} else {
resolve();
}
}
);
});
await extension.startup();
await awaitFinish;
await extension.unload();
}
let tabSwitchTestData = {
files: {
"_locales/en/messages.json": {
popup: {
message: "default.html",
description: "Popup",
},
title: {
message: "Title",
description: "Title",
},
},
"default.png": imageBuffer,
"global.png": imageBuffer,
"1.png": imageBuffer,
"2.png": imageBuffer,
},
getTests: function (tabs) {
let manifest = browser.runtime.getManifest();
let { manifest_version } = manifest;
const action = manifest_version < 3 ? "browserAction" : "action";
let details = [
{
icon: browser.runtime.getURL("default.png"),
popup: browser.runtime.getURL("default.html"),
title: "Default Title",
badge: "",
badgeBackgroundColor: [0xd9, 0, 0, 255],
badgeTextColor: [0xff, 0xff, 0xff, 0xff],
enabled: true,
},
{ icon: browser.runtime.getURL("1.png") },
{
icon: browser.runtime.getURL("2.png"),
popup: browser.runtime.getURL("2.html"),
title: "Title 2",
badge: "2",
badgeBackgroundColor: [0xff, 0, 0, 0xff],
badgeTextColor: [0, 0xff, 0xff, 0xff],
enabled: false,
},
{
icon: browser.runtime.getURL("global.png"),
popup: browser.runtime.getURL("global.html"),
title: "Global Title",
badge: "g",
badgeBackgroundColor: [0, 0xff, 0, 0xff],
badgeTextColor: [0xff, 0, 0xff, 0xff],
enabled: false,
},
{
icon: browser.runtime.getURL("global.png"),
popup: browser.runtime.getURL("global.html"),
title: "Global Title",
badge: "g",
badgeBackgroundColor: [0, 0xff, 0, 0xff],
badgeTextColor: [0xff, 0, 0xff, 0xff],
},
];
let promiseTabLoad = details => {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(function listener(tabId, changed) {
if (tabId == details.id && changed.url == details.url) {
browser.tabs.onUpdated.removeListener(listener);
resolve();
}
});
});
};
return [
async expect => {
browser.test.log("Initial state, expect default properties.");
expect(null, null, null, details[0]);
},
async expect => {
browser.test.log(
"Change the icon in the current tab. Expect default properties excluding the icon."
);
browser[action].setIcon({ tabId: tabs[0], path: "1.png" });
expect(details[1], null, null, details[0]);
},
async expect => {
browser.test.log("Create a new tab. Expect default properties.");
let tab = await browser.tabs.create({
active: true,
url: "about:blank?0",
});
tabs.push(tab.id);
browser.test.log("Await tab load.");
let promise = promiseTabLoad({ id: tabs[1], url: "about:blank?0" });
let { url } = await browser.tabs.get(tabs[1]);
if (url === "about:blank") {
await promise;
}
expect(null, null, null, details[0]);
},
async expect => {
browser.test.log("Change properties. Expect new properties.");
let tabId = tabs[1];
browser[action].setIcon({ tabId, path: "2.png" });
browser[action].setPopup({ tabId, popup: "2.html" });
browser[action].setTitle({ tabId, title: "Title 2" });
browser[action].setBadgeText({ tabId, text: "2" });
browser[action].setBadgeBackgroundColor({
tabId,
color: "#ff0000",
});
browser[action].setBadgeTextColor({ tabId, color: "#00ffff" });
browser[action].disable(tabId);
expect(details[2], null, null, details[0]);
},
async expect => {
browser.test.log(
"Switch back to the first tab. Expect previously set properties."
);
await browser.tabs.update(tabs[0], { active: true });
expect(details[1], null, null, details[0]);
},
async expect => {
browser.test.log(
"Change global values, expect those changes reflected."
);
browser[action].setIcon({ path: "global.png" });
browser[action].setPopup({ popup: "global.html" });
browser[action].setTitle({ title: "Global Title" });
browser[action].setBadgeText({ text: "g" });
browser[action].setBadgeBackgroundColor({
color: [0, 0xff, 0, 0xff],
});
browser[action].setBadgeTextColor({
color: [0xff, 0, 0xff, 0xff],
});
browser[action].disable();
expect(details[1], null, details[3], details[0]);
},
async expect => {
browser.test.log("Re-enable globally. Expect enabled.");
browser[action].enable();
expect(details[1], null, details[4], details[0]);
},
async expect => {
browser.test.log(
"Switch back to tab 2. Expect former tab values, and new global values from previous steps."
);
await browser.tabs.update(tabs[1], { active: true });
expect(details[2], null, details[4], details[0]);
},
async expect => {
browser.test.log(
"Navigate to a new page. Expect tab-specific values to be cleared."
);
let promise = promiseTabLoad({ id: tabs[1], url: "about:blank?1" });
browser.tabs.update(tabs[1], { url: "about:blank?1" });
await promise;
expect(null, null, details[4], details[0]);
},
async expect => {
browser.test.log(
"Delete tab, switch back to tab 1. Expect previous results again."
);
await browser.tabs.remove(tabs[1]);
expect(details[1], null, details[4], details[0]);
},
async expect => {
browser.test.log("Create a new tab. Expect new global properties.");
let tab = await browser.tabs.create({
active: true,
url: "about:blank?2",
});
tabs.push(tab.id);
expect(null, null, details[4], details[0]);
},
async expect => {
browser.test.log("Delete tab.");
await browser.tabs.remove(tabs[2]);
expect(details[1], null, details[4], details[0]);
},
];
},
};
add_task(async function testTabSwitchContext() {
await runTests({
manifest: {
browser_action: {
default_icon: "default.png",
default_popup: "__MSG_popup__",
default_title: "Default __MSG_title__",
default_area: "navbar",
},
default_locale: "en",
permissions: ["tabs"],
},
...tabSwitchTestData,
});
});
add_task(async function testTabSwitchActionContext() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.manifestV3.enabled", true]],
});
await runTests({
manifest: {
manifest_version: 3,
action: {
default_icon: "default.png",
default_popup: "__MSG_popup__",
default_title: "Default __MSG_title__",
default_area: "navbar",
},
default_locale: "en",
permissions: ["tabs"],
},
...tabSwitchTestData,
});
});
add_task(async function testDefaultTitle() {
await runTests({
manifest: {
name: "Foo Extension",
browser_action: {
default_icon: "icon.png",
default_area: "navbar",
},
permissions: ["tabs"],
},
files: {
"icon.png": imageBuffer,
},
getTests: function (tabs) {
let details = [
{
title: "Foo Extension",
popup: "",
badge: "",
badgeBackgroundColor: [0xd9, 0, 0, 255],
badgeTextColor: [0xff, 0xff, 0xff, 0xff],
icon: browser.runtime.getURL("icon.png"),
enabled: true,
},
{ title: "Foo Title" },
{ title: "Bar Title" },
];
return [
async expect => {
browser.test.log("Initial state. Expect default properties.");
expect(null, null, null, details[0]);
},
async expect => {
browser.test.log("Change the tab title. Expect new title.");
browser.browserAction.setTitle({
tabId: tabs[0],
title: "Foo Title",
});
expect(details[1], null, null, details[0]);
},
async expect => {
browser.test.log("Change the global title. Expect same properties.");
browser.browserAction.setTitle({ title: "Bar Title" });
expect(details[1], null, details[2], details[0]);
},
async expect => {
browser.test.log("Clear the tab title. Expect new global title.");
browser.browserAction.setTitle({ tabId: tabs[0], title: null });
expect(null, null, details[2], details[0]);
},
async expect => {
browser.test.log("Clear the global title. Expect default title.");
browser.browserAction.setTitle({ title: null });
expect(null, null, null, details[0]);
},
async expect => {
browser.test.assertRejects(
browser.browserAction.setPopup({ popup: "about:addons" }),
/Access denied for URL about:addons/,
"unable to set popup to about:addons"
);
expect(null, null, null, details[0]);
},
];
},
});
});
add_task(async function testBadgeColorPersistence() {
const extension = ExtensionTestUtils.loadExtension({
background() {
browser.test.onMessage.addListener((msg, arg) => {
browser.browserAction[msg](arg);
});
},
manifest: {
browser_action: {
default_area: "navbar",
},
},
});
await extension.startup();
function getBadgeForWindow(win) {
const widget = getBrowserActionWidget(extension).forWindow(win).node;
return widget.firstElementChild.badgeLabel;
}
let badge = getBadgeForWindow(window);
const badgeChanged = new Promise(resolve => {
const observer = new MutationObserver(() => resolve());
observer.observe(badge, { attributes: true, attributeFilter: ["style"] });
});
extension.sendMessage("setBadgeText", { text: "hi" });
extension.sendMessage("setBadgeBackgroundColor", { color: [0, 255, 0, 255] });
await badgeChanged;
is(badge.textContent, "hi", "badge text is set in first window");
is(
badge.style.backgroundColor,
"rgb(0, 255, 0)",
"badge color is set in first window"
);
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow();
await windowOpenedPromise;
badge = getBadgeForWindow(win);
is(badge.textContent, "hi", "badge text is set in new window");
is(
badge.style.backgroundColor,
"rgb(0, 255, 0)",
"badge color is set in new window"
);
await BrowserTestUtils.closeWindow(win);
await extension.unload();
});
add_task(async function testPropertyRemoval() {
await runTests({
manifest: {
name: "Generated extension",
browser_action: {
default_icon: "default.png",
default_popup: "default.html",
default_title: "Default Title",
default_area: "navbar",
},
},
files: {
"default.png": imageBuffer,
"global.png": imageBuffer,
"global2.png": imageBuffer,
"window.png": imageBuffer,
"tab.png": imageBuffer,
},
getTests: function (tabs, windows) {
let details = [
{
icon: browser.runtime.getURL("default.png"),
popup: browser.runtime.getURL("default.html"),
title: "Default Title",
badge: "",
badgeBackgroundColor: [0xd9, 0x00, 0x00, 0xff],
badgeTextColor: [0xff, 0xff, 0xff, 0xff],
enabled: true,
},
{
icon: browser.runtime.getURL("global.png"),
popup: browser.runtime.getURL("global.html"),
title: "global",
badge: "global",
badgeBackgroundColor: [0x11, 0x11, 0x11, 0xff],
badgeTextColor: [0x99, 0x99, 0x99, 0xff],
},
{
icon: browser.runtime.getURL("window.png"),
popup: browser.runtime.getURL("window.html"),
title: "window",
badge: "window",
badgeBackgroundColor: [0x22, 0x22, 0x22, 0xff],
badgeTextColor: [0x88, 0x88, 0x88, 0xff],
},
{
icon: browser.runtime.getURL("tab.png"),
popup: browser.runtime.getURL("tab.html"),
title: "tab",
badge: "tab",
badgeBackgroundColor: [0x33, 0x33, 0x33, 0xff],
badgeTextColor: [0x77, 0x77, 0x77, 0xff],
},
{
icon: defaultIcon,
popup: "",
title: "",
badge: "",
badgeBackgroundColor: [0x33, 0x33, 0x33, 0xff],
badgeTextColor: [0x77, 0x77, 0x77, 0xff],
},
{
icon: browser.runtime.getURL("global2.png"),
popup: browser.runtime.getURL("global2.html"),
title: "global2",
badge: "global2",
badgeBackgroundColor: [0x44, 0x44, 0x44, 0xff],
badgeTextColor: [0x66, 0x66, 0x66, 0xff],
},
];
return [
async expect => {
browser.test.log("Initial state, expect default properties.");
expect(null, null, null, details[0]);
},
async expect => {
browser.test.log("Set global values, expect the new values.");
browser.browserAction.setIcon({ path: "global.png" });
browser.browserAction.setPopup({ popup: "global.html" });
browser.browserAction.setTitle({ title: "global" });
browser.browserAction.setBadgeText({ text: "global" });
browser.browserAction.setBadgeBackgroundColor({ color: "#111" });
browser.browserAction.setBadgeTextColor({ color: "#999" });
expect(null, null, details[1], details[0]);
},
async expect => {
browser.test.log("Set window values, expect the new values.");
let windowId = windows[0];
browser.browserAction.setIcon({ windowId, path: "window.png" });
browser.browserAction.setPopup({ windowId, popup: "window.html" });
browser.browserAction.setTitle({ windowId, title: "window" });
browser.browserAction.setBadgeText({ windowId, text: "window" });
browser.browserAction.setBadgeBackgroundColor({
windowId,
color: "#222",
});
browser.browserAction.setBadgeTextColor({ windowId, color: "#888" });
expect(null, details[2], details[1], details[0]);
},
async expect => {
browser.test.log("Set tab values, expect the new values.");
let tabId = tabs[0];
browser.browserAction.setIcon({ tabId, path: "tab.png" });
browser.browserAction.setPopup({ tabId, popup: "tab.html" });
browser.browserAction.setTitle({ tabId, title: "tab" });
browser.browserAction.setBadgeText({ tabId, text: "tab" });
browser.browserAction.setBadgeBackgroundColor({
tabId,
color: "#333",
});
browser.browserAction.setBadgeTextColor({ tabId, color: "#777" });
expect(details[3], details[2], details[1], details[0]);
},
async expect => {
browser.test.log(
"Set empty tab values, expect empty values except for colors."
);
let tabId = tabs[0];
browser.browserAction.setIcon({ tabId, path: "" });
browser.browserAction.setPopup({ tabId, popup: "" });
browser.browserAction.setTitle({ tabId, title: "" });
browser.browserAction.setBadgeText({ tabId, text: "" });
await browser.test.assertRejects(
browser.browserAction.setBadgeBackgroundColor({ tabId, color: "" }),
/^Invalid badge background color: ""$/,
"Expected invalid badge background color error"
);
await browser.test.assertRejects(
browser.browserAction.setBadgeTextColor({ tabId, color: "" }),
/^Invalid badge text color: ""$/,
"Expected invalid badge text color error"
);
expect(details[4], details[2], details[1], details[0]);
},
async expect => {
browser.test.log("Remove tab values, expect window values.");
let tabId = tabs[0];
browser.browserAction.setIcon({ tabId, path: null });
browser.browserAction.setPopup({ tabId, popup: null });
browser.browserAction.setTitle({ tabId, title: null });
browser.browserAction.setBadgeText({ tabId, text: null });
browser.browserAction.setBadgeBackgroundColor({ tabId, color: null });
browser.browserAction.setBadgeTextColor({ tabId, color: null });
expect(null, details[2], details[1], details[0]);
},
async expect => {
browser.test.log("Remove window values, expect global values.");
let windowId = windows[0];
browser.browserAction.setIcon({ windowId, path: null });
browser.browserAction.setPopup({ windowId, popup: null });
browser.browserAction.setTitle({ windowId, title: null });
browser.browserAction.setBadgeText({ windowId, text: null });
browser.browserAction.setBadgeBackgroundColor({
windowId,
color: null,
});
browser.browserAction.setBadgeTextColor({ windowId, color: null });
expect(null, null, details[1], details[0]);
},
async expect => {
browser.test.log("Change global values, expect the new values.");
browser.browserAction.setIcon({ path: "global2.png" });
browser.browserAction.setPopup({ popup: "global2.html" });
browser.browserAction.setTitle({ title: "global2" });
browser.browserAction.setBadgeText({ text: "global2" });
browser.browserAction.setBadgeBackgroundColor({ color: "#444" });
browser.browserAction.setBadgeTextColor({ color: "#666" });
expect(null, null, details[5], details[0]);
},
async expect => {
browser.test.log("Remove global values, expect defaults.");
browser.browserAction.setIcon({ path: null });
browser.browserAction.setPopup({ popup: null });
browser.browserAction.setBadgeText({ text: null });
browser.browserAction.setTitle({ title: null });
browser.browserAction.setBadgeBackgroundColor({ color: null });
browser.browserAction.setBadgeTextColor({ color: null });
expect(null, null, null, details[0]);
},
];
},
});
});
add_task(async function testMultipleWindows() {
await runTests({
manifest: {
browser_action: {
default_icon: "default.png",
default_popup: "default.html",
default_title: "Default Title",
default_area: "navbar",
},
},
files: {
"default.png": imageBuffer,
"window1.png": imageBuffer,
"window2.png": imageBuffer,
},
getTests: function (tabs, windows) {
let details = [
{
icon: browser.runtime.getURL("default.png"),
popup: browser.runtime.getURL("default.html"),
title: "Default Title",
badge: "",
badgeBackgroundColor: [0xd9, 0x00, 0x00, 0xff],
badgeTextColor: [0xff, 0xff, 0xff, 0xff],
enabled: true,
},
{
icon: browser.runtime.getURL("window1.png"),
popup: browser.runtime.getURL("window1.html"),
title: "window1",
badge: "w1",
badgeBackgroundColor: [0x11, 0x11, 0x11, 0xff],
badgeTextColor: [0x99, 0x99, 0x99, 0xff],
},
{
icon: browser.runtime.getURL("window2.png"),
popup: browser.runtime.getURL("window2.html"),
title: "window2",
badge: "w2",
badgeBackgroundColor: [0x22, 0x22, 0x22, 0xff],
badgeTextColor: [0x88, 0x88, 0x88, 0xff],
},
{ title: "tab" },
];
return [
async expect => {
browser.test.log("Initial state, expect default properties.");
expect(null, null, null, details[0]);
},
async expect => {
browser.test.log("Set window values, expect the new values.");
let windowId = windows[0];
browser.browserAction.setIcon({ windowId, path: "window1.png" });
browser.browserAction.setPopup({ windowId, popup: "window1.html" });
browser.browserAction.setTitle({ windowId, title: "window1" });
browser.browserAction.setBadgeText({ windowId, text: "w1" });
browser.browserAction.setBadgeBackgroundColor({
windowId,
color: "#111",
});
browser.browserAction.setBadgeTextColor({ windowId, color: "#999" });
expect(null, details[1], null, details[0]);
},
async expect => {
browser.test.log("Create a new tab, expect window values.");
let tab = await browser.tabs.create({ active: true });
tabs.push(tab.id);
expect(null, details[1], null, details[0]);
},
async expect => {
browser.test.log("Set a tab title, expect it.");
await browser.browserAction.setTitle({
tabId: tabs[1],
title: "tab",
});
expect(details[3], details[1], null, details[0]);
},
async expect => {
browser.test.log("Open a new window, expect default values.");
let { id } = await browser.windows.create();
windows.push(id);
expect(null, null, null, details[0]);
},
async expect => {
browser.test.log("Set window values, expect the new values.");
let windowId = windows[1];
browser.browserAction.setIcon({ windowId, path: "window2.png" });
browser.browserAction.setPopup({ windowId, popup: "window2.html" });
browser.browserAction.setTitle({ windowId, title: "window2" });
browser.browserAction.setBadgeText({ windowId, text: "w2" });
browser.browserAction.setBadgeBackgroundColor({
windowId,
color: "#222",
});
browser.browserAction.setBadgeTextColor({ windowId, color: "#888" });
expect(null, details[2], null, details[0]);
},
async expect => {
browser.test.log(
"Move tab from old window to the new one. Tab-specific data" +
" is preserved but inheritance is from the new window"
);
await browser.tabs.move(tabs[1], { windowId: windows[1], index: -1 });
await browser.tabs.update(tabs[1], { active: true });
expect(details[3], details[2], null, details[0]);
},
async expect => {
browser.test.log("Close the initial tab of the new window.");
let [{ id }] = await browser.tabs.query({
windowId: windows[1],
index: 0,
});
await browser.tabs.remove(id);
expect(details[3], details[2], null, details[0]);
},
async expect => {
browser.test.log(
"Move the previous tab to a 3rd window, the 2nd one will close."
);
await browser.windows.create({ tabId: tabs[1] });
expect(details[3], null, null, details[0]);
},
async expect => {
browser.test.log("Close the tab, go back to the 1st window.");
await browser.tabs.remove(tabs[1]);
expect(null, details[1], null, details[0]);
},
async expect => {
browser.test.log(
"Assert failures for bad parameters. Expect no change"
);
let calls = {
setIcon: { path: "default.png" },
setPopup: { popup: "default.html" },
setTitle: { title: "Default Title" },
setBadgeText: { text: "" },
setBadgeBackgroundColor: { color: [0xd9, 0x00, 0x00, 0xff] },
setBadgeTextColor: { color: [0xff, 0xff, 0xff, 0xff] },
getPopup: {},
getTitle: {},
getBadgeText: {},
getBadgeBackgroundColor: {},
};
for (let [method, arg] of Object.entries(calls)) {
browser.test.assertThrows(
() => browser.browserAction[method]({ ...arg, windowId: -3 }),
/-3 is too small \(must be at least -2\)/,
method + " with invalid windowId"
);
await browser.test.assertRejects(
browser.browserAction[method]({
...arg,
tabId: tabs[0],
windowId: windows[0],
}),
/Only one of tabId and windowId can be specified/,
method + " with both tabId and windowId"
);
}
expect(null, details[1], null, details[0]);
},
];
},
});
});
add_task(async function testDefaultBadgeTextColor() {
await runTests({
manifest: {
browser_action: {
default_icon: "default.png",
default_popup: "default.html",
default_title: "Default Title",
default_area: "navbar",
},
},
files: {
"default.png": imageBuffer,
"window1.png": imageBuffer,
"window2.png": imageBuffer,
},
getTests: function (tabs, windows) {
let details = [
{
icon: browser.runtime.getURL("default.png"),
popup: browser.runtime.getURL("default.html"),
title: "Default Title",
badge: "",
badgeBackgroundColor: [0xd9, 0x00, 0x00, 0xff],
badgeTextColor: [0xff, 0xff, 0xff, 0xff],
enabled: true,
},
{
badgeBackgroundColor: [0xff, 0xff, 0x00, 0xff],
badgeTextColor: [0x00, 0x00, 0x00, 0xff],
},
{
badgeBackgroundColor: [0x00, 0x00, 0xff, 0xff],
badgeTextColor: [0xff, 0xff, 0xff, 0xff],
},
{
badgeBackgroundColor: [0xff, 0xff, 0xff, 0x00],
badgeTextColor: [0x00, 0x00, 0x00, 0xff],
},
{
badgeBackgroundColor: [0x00, 0x00, 0xff, 0xff],
badgeTextColor: [0xff, 0x00, 0xff, 0xff],
},
{ badgeBackgroundColor: [0xff, 0xff, 0xff, 0x00] },
{
badgeBackgroundColor: [0x00, 0x00, 0x00, 0x00],
badgeTextColor: [0xff, 0xff, 0xff, 0xff],
},
];
return [
async expect => {
browser.test.log("Initial state, expect default properties.");
expect(null, null, null, details[0]);
},
async expect => {
browser.test.log("Set a global light bgcolor, expect black text.");
browser.browserAction.setBadgeBackgroundColor({ color: "#ff0" });
expect(null, null, details[1], details[0]);
},
async expect => {
browser.test.log(
"Set a window-specific dark bgcolor, expect white text."
);
let windowId = windows[0];
browser.browserAction.setBadgeBackgroundColor({
windowId,
color: "#00f",
});
expect(null, details[2], details[1], details[0]);
},
async expect => {
browser.test.log(
"Set a tab-specific transparent-white bgcolor, expect black text."
);
let tabId = tabs[0];
browser.browserAction.setBadgeBackgroundColor({
tabId,
color: "#fff0",
});
expect(details[3], details[2], details[1], details[0]);
},
async expect => {
browser.test.log(
"Set a window-specific text color, expect it in the tab."
);
let windowId = windows[0];
browser.browserAction.setBadgeTextColor({ windowId, color: "#f0f" });
expect(details[5], details[4], details[1], details[0]);
},
async expect => {
browser.test.log(
"Remove the window-specific text color, expect black again."
);
let windowId = windows[0];
browser.browserAction.setBadgeTextColor({ windowId, color: null });
expect(details[3], details[2], details[1], details[0]);
},
async expect => {
browser.test.log(
"Set a tab-specific transparent-black bgcolor, expect white text."
);
let tabId = tabs[0];
browser.browserAction.setBadgeBackgroundColor({
tabId,
color: "#0000",
});
expect(details[6], details[2], details[1], details[0]);
},
];
},
});
});
add_task(async function testNavigationClearsData() {
let url = "http://example.com/";
let default_title = "Default title";
let tab_title = "Tab title";
const {
Management: {
global: { tabTracker },
},
} = ChromeUtils.importESModule("resource://gre/modules/Extension.sys.mjs");
let extension,
tabs = [];
async function addTab(...args) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, ...args);
tabs.push(tab);
return tab;
}
async function sendMessage(method, param, expect, msg) {
extension.sendMessage({ method, param, expect, msg });
await extension.awaitMessage("done");
}
async function expectTabSpecificData(tab, msg) {
let tabId = tabTracker.getId(tab);
await sendMessage("getBadgeText", { tabId }, "foo", msg);
await sendMessage("getTitle", { tabId }, tab_title, msg);
}
async function expectDefaultData(tab, msg) {
let tabId = tabTracker.getId(tab);
await sendMessage("getBadgeText", { tabId }, "", msg);
await sendMessage("getTitle", { tabId }, default_title, msg);
}
async function setTabSpecificData(tab) {
let tabId = tabTracker.getId(tab);
await expectDefaultData(
tab,
"Expect default data before setting tab-specific data."
);
await sendMessage("setBadgeText", { tabId, text: "foo" });
await sendMessage("setTitle", { tabId, title: tab_title });
await expectTabSpecificData(
tab,
"Expect tab-specific data after setting it."
);
}
info("Load a tab before installing the extension");
let tab1 = await addTab(url, true, true);
extension = ExtensionTestUtils.loadExtension({
manifest: {
browser_action: { default_title },
},
background: function () {
browser.test.onMessage.addListener(
async ({ method, param, expect, msg }) => {
let result = await browser.browserAction[method](param);
if (expect !== undefined) {
browser.test.assertEq(expect, result, msg);
}
browser.test.sendMessage("done");
}
);
},
});
await extension.startup();
info("Set tab-specific data to the existing tab.");
await setTabSpecificData(tab1);
info("Add a hash. Does not cause navigation.");
await navigateTab(tab1, url + "#hash");
await expectTabSpecificData(
tab1,
"Adding a hash does not clear tab-specific data"
);
info("Remove the hash. Causes navigation.");
await navigateTab(tab1, url);
await expectDefaultData(tab1, "Removing hash clears tab-specific data");
info("Open a new tab, set tab-specific data to it.");
let tab2 = await addTab("about:newtab", false, false);
await setTabSpecificData(tab2);
info("Load a page in that tab.");
await navigateTab(tab2, url);
await expectDefaultData(tab2, "Loading a page clears tab-specific data.");
info("Set tab-specific data.");
await setTabSpecificData(tab2);
info("Push history state. Does not cause navigation.");
await historyPushState(tab2, url + "/path");
await expectTabSpecificData(
tab2,
"history.pushState() does not clear tab-specific data"
);
info("Navigate when the tab is not selected");
gBrowser.selectedTab = tab1;
await navigateTab(tab2, url);
await expectDefaultData(
tab2,
"Navigating clears tab-specific data, even when not selected."
);
for (let tab of tabs) {
await BrowserTestUtils.removeTab(tab);
}
await extension.unload();
});