const { AddonTestUtils } = ChromeUtils.import(
"resource://testing-common/AddonTestUtils.jsm",
{}
);
AddonTestUtils.initMochitest(this);
let gManagerWindow;
let gCategoryUtilities;
const TELEMETRY_METHODS = ["action", "link", "view"];
const addonId = "extension@mochi.test";
registerCleanupFunction(() => {
// AddonTestUtils with open_manager cause this reference to be maintained and creates a leak.
gManagerWindow = null;
});
add_task(function setupPromptService() {
let promptService = mockPromptService();
promptService._response = 0; // Accept dialogs.
});
async function installTheme() {
let id = "theme@mochi.test";
let extension = ExtensionTestUtils.loadExtension({
manifest: {
applications: { gecko: { id } },
manifest_version: 2,
name: "atheme",
description: "wow. such theme.",
author: "Pixel Pusher",
version: "1",
theme: {},
},
useAddonManager: "temporary",
});
await extension.startup();
return extension;
}
async function installExtension(manifest = {}) {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
applications: { gecko: { id: addonId } },
manifest_version: 2,
name: "extension",
description: "wow. such extension.",
author: "Code Pusher",
version: "1",
chrome_url_overrides: { newtab: "new.html" },
options_ui: { page: "options.html", open_in_tab: true },
browser_action: { default_popup: "action.html" },
page_action: { default_popup: "action.html" },
...manifest,
},
files: {
"new.html": "
yo
",
"options.html": "options
",
"action.html": "do something
",
},
useAddonManager: "permanent",
});
await extension.startup();
return extension;
}
function getAddonCard(doc, id) {
return doc.querySelector(`addon-card[addon-id="${id}"]`);
}
function openDetailView(doc, id) {
let card = getAddonCard(doc, id);
card.querySelector('[action="expand"]').click();
}
async function enableAndDisable(doc, row) {
let toggleButton = row.querySelector('[action="toggle-disabled"]');
let disabled = BrowserTestUtils.waitForEvent(row, "update");
toggleButton.click();
await disabled;
let enabled = BrowserTestUtils.waitForEvent(row, "update");
toggleButton.click();
await enabled;
}
async function removeAddonAndUndo(doc, row) {
let id = row.addon.id;
let started = AddonTestUtils.promiseWebExtensionStartup(id);
let removed = BrowserTestUtils.waitForEvent(row, "remove");
row.querySelector('[action="remove"]').click();
await removed;
let undoBanner = doc.querySelector(`message-bar[addon-id="${row.addon.id}"]`);
undoBanner.querySelector('[action="undo"]').click();
await TestUtils.waitForCondition(() => getAddonCard(doc, row.addon.id));
await started;
}
async function openPrefs(doc, row) {
row.querySelector('[action="preferences"]').click();
}
function changeAutoUpdates(doc) {
let row = doc.querySelector(".addon-detail-row-updates");
let checked = row.querySelector(":checked");
is(checked.value, "1", "Use default is selected");
row.querySelector('[value="0"]').click();
row.querySelector('[action="update-check"]').click();
row.querySelector('[value="2"]').click();
row.querySelector('[value="1"]').click();
}
function clickLinks(doc) {
let links = ["author", "homepage", "rating"];
for (let linkType of links) {
doc.querySelector(`.addon-detail-row-${linkType} a`).click();
}
}
async function init(startPage) {
gManagerWindow = await open_manager(null);
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
// When about:addons initially loads it will load the last view that
// was open. If that's different than startPage, then clear the events
// so that we can reliably test them.
if (gCategoryUtilities.selectedCategory != startPage) {
Services.telemetry.clearEvents();
}
await gCategoryUtilities.openType(startPage);
return gManagerWindow.document.getElementById("html-view-browser")
.contentDocument;
}
/* Test functions start here. */
add_task(async function setup() {
// Clear out any telemetry data that existed before this file is run.
Services.telemetry.clearEvents();
});
add_task(async function testBasicViewTelemetry() {
let addons = await Promise.all([installTheme(), installExtension()]);
let doc = await init("discover");
await gCategoryUtilities.openType("theme");
openDetailView(doc, "theme@mochi.test");
await wait_for_view_load(gManagerWindow);
await gCategoryUtilities.openType("extension");
openDetailView(doc, "extension@mochi.test");
await wait_for_view_load(gManagerWindow);
assertAboutAddonsTelemetryEvents(
[
["addonsManager", "view", "aboutAddons", "discover"],
["addonsManager", "view", "aboutAddons", "list", { type: "theme" }],
[
"addonsManager",
"view",
"aboutAddons",
"detail",
{ type: "theme", addonId: "theme@mochi.test" },
],
["addonsManager", "view", "aboutAddons", "list", { type: "extension" }],
[
"addonsManager",
"view",
"aboutAddons",
"detail",
{ type: "extension", addonId: "extension@mochi.test" },
],
],
{ methods: ["view"] }
);
await close_manager(gManagerWindow);
await Promise.all(addons.map(addon => addon.unload()));
});
add_task(async function testExtensionEvents() {
let addon = await installExtension();
let type = "extension";
let doc = await init("extension");
// Check/clear the current telemetry.
assertAboutAddonsTelemetryEvents(
[["addonsManager", "view", "aboutAddons", "list", { type: "extension" }]],
{ methods: ["view"] }
);
let row = getAddonCard(doc, addonId);
// Check disable/enable.
await enableAndDisable(doc, row);
assertAboutAddonsTelemetryEvents(
[
[
"addonsManager",
"action",
"aboutAddons",
null,
{ action: "disable", addonId, type, view: "list" },
],
[
"addonsManager",
"action",
"aboutAddons",
null,
{ action: "enable", addonId, type, view: "list" },
],
],
{ methods: ["action"] }
);
// Check remove/undo.
await removeAddonAndUndo(doc, row);
let uninstallValue = "accepted";
assertAboutAddonsTelemetryEvents(
[
[
"addonsManager",
"action",
"aboutAddons",
uninstallValue,
{ action: "uninstall", addonId, type, view: "list" },
],
[
"addonsManager",
"action",
"aboutAddons",
null,
{ action: "undo", addonId, type, view: "list" },
],
],
{ methods: ["action"] }
);
// Open the preferences page.
let waitForNewTab = BrowserTestUtils.waitForNewTab(gBrowser);
// Find the row again since it was modified on uninstall.
row = getAddonCard(doc, addonId);
await openPrefs(doc, row);
BrowserTestUtils.removeTab(await waitForNewTab);
assertAboutAddonsTelemetryEvents(
[
[
"addonsManager",
"action",
"aboutAddons",
"external",
{ action: "preferences", type, addonId, view: "list" },
],
],
{ methods: ["action"] }
);
// Go to the detail view.
openDetailView(doc, addonId);
await wait_for_view_load(gManagerWindow);
assertAboutAddonsTelemetryEvents(
[["addonsManager", "view", "aboutAddons", "detail", { type, addonId }]],
{ methods: ["view"] }
);
// Check updates.
changeAutoUpdates(doc);
assertAboutAddonsTelemetryEvents(
[
[
"addonsManager",
"action",
"aboutAddons",
"",
{ action: "setAddonUpdate", type, addonId, view: "detail" },
],
[
"addonsManager",
"action",
"aboutAddons",
null,
{ action: "checkForUpdate", type, addonId, view: "detail" },
],
[
"addonsManager",
"action",
"aboutAddons",
"enabled",
{ action: "setAddonUpdate", type, addonId, view: "detail" },
],
[
"addonsManager",
"action",
"aboutAddons",
"default",
{ action: "setAddonUpdate", type, addonId, view: "detail" },
],
],
{ methods: ["action"] }
);
// These links don't actually have a URL, so they don't open a tab. They're only
// shown when there is a URL though.
clickLinks(doc);
// The support button will open a new tab.
waitForNewTab = BrowserTestUtils.waitForNewTab(gBrowser);
doc.getElementById("help-button").click();
BrowserTestUtils.removeTab(await waitForNewTab);
// Check that the preferences button includes the view.
waitForNewTab = BrowserTestUtils.waitForNewTab(gBrowser);
row = getAddonCard(doc, addonId);
await openPrefs(doc, row);
BrowserTestUtils.removeTab(await waitForNewTab);
assertAboutAddonsTelemetryEvents(
[
["addonsManager", "link", "aboutAddons", "author", { view: "detail" }],
["addonsManager", "link", "aboutAddons", "homepage", { view: "detail" }],
["addonsManager", "link", "aboutAddons", "rating", { view: "detail" }],
["addonsManager", "link", "aboutAddons", "support", { view: "detail" }],
[
"addonsManager",
"action",
"aboutAddons",
"external",
{ action: "preferences", type, addonId, view: "detail" },
],
],
{ methods: ["action", "link"] }
);
// Update the preferences and check that inline changes.
await gCategoryUtilities.openType("extension");
let upgraded = await installExtension({
options_ui: { page: "options.html" },
version: "2",
});
row = getAddonCard(doc, addonId);
await openPrefs(doc, row);
await wait_for_view_load(gManagerWindow);
assertAboutAddonsTelemetryEvents(
[
["addonsManager", "view", "aboutAddons", "list", { type }],
[
"addonsManager",
"action",
"aboutAddons",
"inline",
{ action: "preferences", type, addonId, view: "list" },
],
[
"addonsManager",
"view",
"aboutAddons",
"detail",
{ type: "extension", addonId: "extension@mochi.test" },
],
],
{ methods: ["action", "view"] }
);
await close_manager(gManagerWindow);
await addon.unload();
await upgraded.unload();
});
add_task(async function testGeneralActions() {
let win = await loadInitialView("extension");
info("Loaded");
let doc = win.document;
let pageOptionsButton = doc.querySelector('[action="page-options"]');
let menu = doc.querySelector("#page-options panel-list");
let checkForUpdates = menu.querySelector('[action="check-for-updates"]');
let recentUpdates = menu.querySelector('[action="view-recent-updates"]');
let updatePolicy = menu.querySelector('[action="set-update-automatically"]');
let resetUpdatePolicy = menu.querySelector('[action="reset-update-states"]');
let debugAddons = menu.querySelector('[action="debug-addons"]');
let manageShortcuts = menu.querySelector('[action="manage-shortcuts"]');
async function clickInGearMenu(item) {
info(`Opening menu to click ${item.getAttribute("action")}`);
let shown = BrowserTestUtils.waitForEvent(menu, "shown");
// This should perform a click on the button to ensure that works. Other
// tests might just open the menu directly, or click items when it's closed.
EventUtils.synthesizeMouseAtCenter(pageOptionsButton, {}, win);
await shown;
info(`Clicking ${item.getAttribute("action")}`);
item.click();
}
await clickInGearMenu(checkForUpdates);
let recentUpdatesLoaded = waitForViewLoad(win);
await clickInGearMenu(recentUpdates);
await recentUpdatesLoaded;
await clickInGearMenu(updatePolicy);
await clickInGearMenu(updatePolicy);
await clickInGearMenu(resetUpdatePolicy);
// Check shortcuts view.
let shortcutsLoaded = waitForViewLoad(win);
await clickInGearMenu(manageShortcuts);
await shortcutsLoaded;
await clickInGearMenu(checkForUpdates);
let waitForNewTab = BrowserTestUtils.waitForNewTab(gBrowser);
await clickInGearMenu(debugAddons);
info("Waiting for about:debugging tab");
let tab = await waitForNewTab;
BrowserTestUtils.removeTab(tab);
waitForNewTab = BrowserTestUtils.waitForNewTab(gBrowser);
let searchBox = doc.querySelector("search-addons").input.inputField;
searchBox.value = "something";
searchBox.focus();
EventUtils.synthesizeKey("KEY_Enter", {}, win);
info("Waiting for AMO search tab");
tab = await waitForNewTab;
BrowserTestUtils.removeTab(tab);
assertAboutAddonsTelemetryEvents(
[
["addonsManager", "view", "aboutAddons", "list", { type: "extension" }],
[
"addonsManager",
"action",
"aboutAddons",
null,
{ action: "checkForUpdates", view: "list" },
],
["addonsManager", "view", "aboutAddons", "updates", { type: "recent" }],
[
"addonsManager",
"action",
"aboutAddons",
"default,enabled",
{ action: "setUpdatePolicy", view: "updates" },
],
[
"addonsManager",
"action",
"aboutAddons",
"enabled",
{ action: "setUpdatePolicy", view: "updates" },
],
[
"addonsManager",
"action",
"aboutAddons",
null,
{ action: "resetUpdatePolicy", view: "updates" },
],
["addonsManager", "view", "aboutAddons", "shortcuts"],
[
"addonsManager",
"action",
"aboutAddons",
null,
{ action: "checkForUpdates", view: "shortcuts" },
],
[
"addonsManager",
"link",
"aboutAddons",
"about:debugging",
{ view: "shortcuts" },
],
[
"addonsManager",
"link",
"aboutAddons",
"search",
{ view: "shortcuts", type: "shortcuts" },
],
],
{ methods: TELEMETRY_METHODS }
);
await closeView(win);
assertAboutAddonsTelemetryEvents([]);
});
add_task(async function testPreferencesLink() {
assertAboutAddonsTelemetryEvents([]);
let doc = await init("theme");
// Open the about:preferences page from about:addons.
let waitForNewTab = BrowserTestUtils.waitForNewTab(
gBrowser,
"about:preferences",
true
);
doc.getElementById("preferencesButton").click();
let tab = await waitForNewTab;
let getAddonsButton = () =>
tab.linkedBrowser.contentDocument.getElementById("addonsButton");
// Open the about:addons page from about:preferences.
getAddonsButton().click();
// Close the about:preferences tab.
BrowserTestUtils.removeTab(tab);
TelemetryTestUtils.assertEvents(
[
["addonsManager", "view", "aboutAddons", "list", { type: "theme" }],
[
"addonsManager",
"link",
"aboutAddons",
"about:preferences",
{ view: "list" },
],
["addonsManager", "link", "aboutPreferences", "about:addons"],
],
{
category: "addonsManager",
method: /^(link|view)$/,
}
);
await close_manager(gManagerWindow);
});