diff options
Diffstat (limited to 'toolkit/mozapps/extensions/test/browser/browser_interaction_telemetry.js')
-rw-r--r-- | toolkit/mozapps/extensions/test/browser/browser_interaction_telemetry.js | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/test/browser/browser_interaction_telemetry.js b/toolkit/mozapps/extensions/test/browser/browser_interaction_telemetry.js new file mode 100644 index 0000000000..039e08c54b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_interaction_telemetry.js @@ -0,0 +1,533 @@ +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: { + browser_specific_settings: { 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: { + browser_specific_settings: { 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": "<h1>yo</h1>", + "options.html": "<h1>options</h1>", + "action.html": "<h1>do something</h1>", + }, + useAddonManager: "permanent", + }); + await extension.startup(); + return extension; +} + +function openDetailView(doc, id) { + let card = getAddonCard(doc.defaultView, 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(); + const win = doc.defaultView; + await TestUtils.waitForCondition(() => getAddonCard(win, 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; +} + +/* Test functions start here. */ + +add_setup(async function() { + // 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", + { taar_enabled: "0" }, + ], + ["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"); + let win = doc.defaultView; + + // Check/clear the current telemetry. + assertAboutAddonsTelemetryEvents( + [["addonsManager", "view", "aboutAddons", "list", { type: "extension" }]], + { methods: ["view"] } + ); + + let row = getAddonCard(win, 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(win, 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(win, 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(win, 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); +}); |