summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/extensions/test/browser/browser_html_updates.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps/extensions/test/browser/browser_html_updates.js')
-rw-r--r--toolkit/mozapps/extensions/test/browser/browser_html_updates.js743
1 files changed, 743 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/test/browser/browser_html_updates.js b/toolkit/mozapps/extensions/test/browser/browser_html_updates.js
new file mode 100644
index 0000000000..33dba886cd
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_html_updates.js
@@ -0,0 +1,743 @@
+/* eslint max-len: ["error", 80] */
+
+const { AddonTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/AddonTestUtils.sys.mjs"
+);
+
+AddonTestUtils.initMochitest(this);
+
+const server = AddonTestUtils.createHttpServer();
+
+const initialAutoUpdate = AddonManager.autoUpdateDefault;
+registerCleanupFunction(() => {
+ AddonManager.autoUpdateDefault = initialAutoUpdate;
+});
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [["extensions.checkUpdateSecurity", false]],
+ });
+
+ Services.telemetry.clearEvents();
+ registerCleanupFunction(() => {
+ cleanupPendingNotifications();
+ });
+});
+
+function loadDetailView(win, id) {
+ let doc = win.document;
+ let card = doc.querySelector(`addon-card[addon-id="${id}"]`);
+ let loaded = waitForViewLoad(win);
+ EventUtils.synthesizeMouseAtCenter(card, { clickCount: 1 }, win);
+ return loaded;
+}
+
+add_task(async function testChangeAutoUpdates() {
+ let id = "test@mochi.test";
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ name: "Test",
+ browser_specific_settings: { gecko: { id } },
+ },
+ // Use permanent so the add-on can be updated.
+ useAddonManager: "permanent",
+ });
+
+ await extension.startup();
+ let addon = await AddonManager.getAddonByID(id);
+
+ let win = await loadInitialView("extension");
+ let doc = win.document;
+
+ let getInputs = updateRow => ({
+ default: updatesRow.querySelector('input[value="1"]'),
+ on: updatesRow.querySelector('input[value="2"]'),
+ off: updatesRow.querySelector('input[value="0"]'),
+ checkForUpdate: updatesRow.querySelector('[action="update-check"]'),
+ });
+
+ await loadDetailView(win, id);
+
+ let card = doc.querySelector(`addon-card[addon-id="${id}"]`);
+ ok(card.querySelector("addon-details"), "The card now has details");
+
+ let updatesRow = card.querySelector(".addon-detail-row-updates");
+ let inputs = getInputs(updatesRow);
+ is(addon.applyBackgroundUpdates, 1, "Default is set");
+ ok(inputs.default.checked, "The default option is selected");
+ ok(inputs.checkForUpdate.hidden, "Update check is hidden");
+
+ inputs.on.click();
+ is(addon.applyBackgroundUpdates, "2", "Updates are now enabled");
+ ok(inputs.on.checked, "The on option is selected");
+ ok(inputs.checkForUpdate.hidden, "Update check is hidden");
+
+ inputs.off.click();
+ is(addon.applyBackgroundUpdates, "0", "Updates are now disabled");
+ ok(inputs.off.checked, "The off option is selected");
+ ok(!inputs.checkForUpdate.hidden, "Update check is visible");
+
+ // Go back to the list view and check the details view again.
+ let loaded = waitForViewLoad(win);
+ doc.querySelector(".back-button").click();
+ await loaded;
+
+ // Load the detail view again.
+ await loadDetailView(win, id);
+
+ card = doc.querySelector(`addon-card[addon-id="${id}"]`);
+ updatesRow = card.querySelector(".addon-detail-row-updates");
+ inputs = getInputs(updatesRow);
+
+ ok(inputs.off.checked, "Off is still selected");
+
+ // Disable global updates.
+ let updated = BrowserTestUtils.waitForEvent(card, "update");
+ AddonManager.autoUpdateDefault = false;
+ await updated;
+
+ // Updates are still the same.
+ is(addon.applyBackgroundUpdates, "0", "Updates are now disabled");
+ ok(inputs.off.checked, "The off option is selected");
+ ok(!inputs.checkForUpdate.hidden, "Update check is visible");
+
+ // Check default.
+ inputs.default.click();
+ is(addon.applyBackgroundUpdates, "1", "Default is set");
+ ok(inputs.default.checked, "The default option is selected");
+ ok(!inputs.checkForUpdate.hidden, "Update check is visible");
+
+ inputs.on.click();
+ is(addon.applyBackgroundUpdates, "2", "Updates are now enabled");
+ ok(inputs.on.checked, "The on option is selected");
+ ok(inputs.checkForUpdate.hidden, "Update check is hidden");
+
+ // Enable updates again.
+ updated = BrowserTestUtils.waitForEvent(card, "update");
+ AddonManager.autoUpdateDefault = true;
+ await updated;
+
+ await closeView(win);
+ await extension.unload();
+});
+
+async function setupExtensionWithUpdate(
+ id,
+ { releaseNotes, cancelUpdate } = {}
+) {
+ let serverHost = `http://localhost:${server.identity.primaryPort}`;
+ let updatesPath = `/ext-updates-${id}.json`;
+
+ let baseManifest = {
+ name: "Updates",
+ icons: { 48: "an-icon.png" },
+ browser_specific_settings: {
+ gecko: {
+ id,
+ update_url: serverHost + updatesPath,
+ },
+ },
+ };
+
+ let updateXpi = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ ...baseManifest,
+ version: "2",
+ // Include a permission in the updated extension, to make
+ // sure that we trigger the permission prompt as expected
+ // (and that we can accept or cancel the update by observing
+ // the underlying observerService notification).
+ permissions: ["http://*.example.com/*"],
+ },
+ });
+
+ let releaseNotesExtra = {};
+ if (releaseNotes) {
+ let notesPath = "/notes.txt";
+ server.registerPathHandler(notesPath, (request, response) => {
+ if (releaseNotes == "ERROR") {
+ response.setStatusLine(null, 404, "Not Found");
+ } else {
+ response.setStatusLine(null, 200, "OK");
+ response.write(releaseNotes);
+ }
+ response.processAsync();
+ response.finish();
+ });
+ releaseNotesExtra.update_info_url = serverHost + notesPath;
+ }
+
+ let xpiFilename = `/update-${id}.xpi`;
+ server.registerFile(xpiFilename, updateXpi);
+ AddonTestUtils.registerJSON(server, updatesPath, {
+ addons: {
+ [id]: {
+ updates: [
+ {
+ version: "2",
+ update_link: serverHost + xpiFilename,
+ ...releaseNotesExtra,
+ },
+ ],
+ },
+ },
+ });
+
+ handlePermissionPrompt({ addonId: id, reject: cancelUpdate });
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ ...baseManifest,
+ version: "1",
+ },
+ // Use permanent so the add-on can be updated.
+ useAddonManager: "permanent",
+ });
+ await extension.startup();
+ return extension;
+}
+
+function disableAutoUpdates(card) {
+ // Check button should be hidden.
+ let updateCheckButton = card.querySelector('button[action="update-check"]');
+ ok(updateCheckButton.hidden, "The button is initially hidden");
+
+ // Disable updates, update check button is now visible.
+ card.querySelector('input[name="autoupdate"][value="0"]').click();
+ ok(!updateCheckButton.hidden, "The button is now visible");
+
+ // There shouldn't be an update shown to the user.
+ assertUpdateState({ card, shown: false });
+}
+
+function checkForUpdate(card, expected) {
+ let updateCheckButton = card.querySelector('button[action="update-check"]');
+ let updateFound = BrowserTestUtils.waitForEvent(card, expected);
+ updateCheckButton.click();
+ return updateFound;
+}
+
+function installUpdate(card, expected) {
+ // Install the update.
+ let updateInstalled = BrowserTestUtils.waitForEvent(card, expected);
+ let updated = BrowserTestUtils.waitForEvent(card, "update");
+ card.querySelector('panel-item[action="install-update"]').click();
+ return Promise.all([updateInstalled, updated]);
+}
+
+async function findUpdatesForAddonId(id) {
+ let addon = await AddonManager.getAddonByID(id);
+ await new Promise(resolve => {
+ addon.findUpdates(
+ { onUpdateAvailable: resolve },
+ AddonManager.UPDATE_WHEN_USER_REQUESTED
+ );
+ });
+}
+
+function assertUpdateState({
+ card,
+ shown,
+ expanded = true,
+ releaseNotes = false,
+}) {
+ let menuButton = card.querySelector(".more-options-button");
+ ok(
+ menuButton.classList.contains("more-options-button-badged") == shown,
+ "The menu button is badged"
+ );
+ let installButton = card.querySelector('panel-item[action="install-update"]');
+ ok(
+ installButton.hidden != shown,
+ `The install button is ${shown ? "hidden" : "shown"}`
+ );
+ if (expanded) {
+ let updateCheckButton = card.querySelector('button[action="update-check"]');
+ ok(
+ updateCheckButton.hidden == shown,
+ `The update check button is ${shown ? "hidden" : "shown"}`
+ );
+
+ let { tabGroup } = card.details;
+ is(tabGroup.hidden, false, "The tab group is shown");
+ let notesBtn = tabGroup.querySelector('[name="release-notes"]');
+ is(
+ notesBtn.hidden,
+ !releaseNotes,
+ `The release notes button is ${releaseNotes ? "shown" : "hidden"}`
+ );
+ }
+}
+
+add_task(async function testUpdateAvailable() {
+ let id = "update@mochi.test";
+ let extension = await setupExtensionWithUpdate(id);
+
+ let win = await loadInitialView("extension");
+ let doc = win.document;
+
+ await loadDetailView(win, id);
+
+ let card = doc.querySelector("addon-card");
+
+ // Disable updates and then check.
+ disableAutoUpdates(card);
+ await checkForUpdate(card, "update-found");
+
+ // There should now be an update.
+ assertUpdateState({ card, shown: true });
+
+ // The version was 1.
+ let versionRow = card.querySelector(".addon-detail-row-version");
+ is(versionRow.lastChild.textContent, "1", "The version started as 1");
+
+ await installUpdate(card, "update-installed");
+
+ // The version is now 2.
+ versionRow = card.querySelector(".addon-detail-row-version");
+ is(versionRow.lastChild.textContent, "2", "The version has updated");
+
+ // No update is shown again.
+ assertUpdateState({ card, shown: false });
+
+ // Check for updates again, there shouldn't be an update.
+ await checkForUpdate(card, "no-update");
+
+ await closeView(win);
+ await extension.unload();
+});
+
+add_task(async function testReleaseNotesLoad() {
+ Services.telemetry.clearEvents();
+ let id = "update-with-notes@mochi.test";
+ let extension = await setupExtensionWithUpdate(id, {
+ releaseNotes: `
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <head><link rel="stylesheet" href="remove-me.css"/></head>
+ <body>
+ <script src="no-scripts.js"></script>
+ <h1>My release notes</h1>
+ <img src="http://example.com/tracker.png"/>
+ <ul>
+ <li onclick="alert('hi')">A thing</li>
+ </ul>
+ <a href="http://example.com/">Go somewhere</a>
+ </body>
+ </html>
+ `,
+ });
+
+ let win = await loadInitialView("extension");
+ let doc = win.document;
+
+ await loadDetailView(win, id);
+
+ let card = doc.querySelector("addon-card");
+ let { deck, tabGroup } = card.details;
+
+ // Disable updates and then check.
+ disableAutoUpdates(card);
+ await checkForUpdate(card, "update-found");
+
+ // There should now be an update.
+ assertUpdateState({ card, shown: true, releaseNotes: true });
+
+ info("Check release notes");
+ let notesBtn = tabGroup.querySelector('[name="release-notes"]');
+ let notes = card.querySelector("update-release-notes");
+ let loading = BrowserTestUtils.waitForEvent(notes, "release-notes-loading");
+ let loaded = BrowserTestUtils.waitForEvent(notes, "release-notes-loaded");
+ // Don't use notesBtn.click() since it causes an assertion to fail.
+ // See bug 1551621 for more info.
+ EventUtils.synthesizeMouseAtCenter(notesBtn, {}, win);
+ await loading;
+ is(
+ doc.l10n.getAttributes(notes.firstElementChild).id,
+ "release-notes-loading",
+ "The loading message is shown"
+ );
+ await loaded;
+ info("Checking HTML release notes");
+ let [h1, ul, a] = notes.children;
+ is(h1.tagName, "H1", "There's a heading");
+ is(h1.textContent, "My release notes", "The heading has content");
+ is(ul.tagName, "UL", "There's a list");
+ is(ul.children.length, 1, "There's one item in the list");
+ let [li] = ul.children;
+ is(li.tagName, "LI", "There's a list item");
+ is(li.textContent, "A thing", "The text is set");
+ ok(!li.hasAttribute("onclick"), "The onclick was removed");
+ ok(!notes.querySelector("link"), "The link tag was removed");
+ ok(!notes.querySelector("script"), "The script tag was removed");
+ is(a.textContent, "Go somewhere", "The link text is preserved");
+ is(a.href, "http://example.com/", "The link href is preserved");
+
+ info("Verify the link opened in a new tab");
+ let tabOpened = BrowserTestUtils.waitForNewTab(gBrowser, a.href);
+ a.click();
+ let tab = await tabOpened;
+ BrowserTestUtils.removeTab(tab);
+
+ let originalContent = notes.innerHTML;
+
+ info("Switch away and back to release notes");
+ // Load details view.
+ let detailsBtn = tabGroup.querySelector('.tab-button[name="details"]');
+ let viewChanged = BrowserTestUtils.waitForEvent(deck, "view-changed");
+ detailsBtn.click();
+ await viewChanged;
+
+ // Load release notes again, verify they weren't loaded.
+ viewChanged = BrowserTestUtils.waitForEvent(deck, "view-changed");
+ let notesCached = BrowserTestUtils.waitForEvent(
+ notes,
+ "release-notes-cached"
+ );
+ notesBtn.click();
+ await viewChanged;
+ await notesCached;
+ is(notes.innerHTML, originalContent, "The content didn't change");
+
+ info("Install the update to clean it up");
+ await installUpdate(card, "update-installed");
+
+ // There's no more update but release notes are still shown.
+ assertUpdateState({ card, shown: false, releaseNotes: true });
+
+ await closeView(win);
+ await extension.unload();
+});
+
+add_task(async function testReleaseNotesError() {
+ let id = "update-with-notes-error@mochi.test";
+ let extension = await setupExtensionWithUpdate(id, { releaseNotes: "ERROR" });
+
+ let win = await loadInitialView("extension");
+ let doc = win.document;
+
+ await loadDetailView(win, id);
+
+ let card = doc.querySelector("addon-card");
+ let { deck, tabGroup } = card.details;
+
+ // Disable updates and then check.
+ disableAutoUpdates(card);
+ await checkForUpdate(card, "update-found");
+
+ // There should now be an update.
+ assertUpdateState({ card, shown: true, releaseNotes: true });
+
+ info("Check release notes");
+ let notesBtn = tabGroup.querySelector('[name="release-notes"]');
+ let notes = card.querySelector("update-release-notes");
+ let loading = BrowserTestUtils.waitForEvent(notes, "release-notes-loading");
+ let errored = BrowserTestUtils.waitForEvent(notes, "release-notes-error");
+ // Don't use notesBtn.click() since it causes an assertion to fail.
+ // See bug 1551621 for more info.
+ EventUtils.synthesizeMouseAtCenter(notesBtn, {}, win);
+ await loading;
+ is(
+ doc.l10n.getAttributes(notes.firstElementChild).id,
+ "release-notes-loading",
+ "The loading message is shown"
+ );
+ await errored;
+ is(
+ doc.l10n.getAttributes(notes.firstElementChild).id,
+ "release-notes-error",
+ "The error message is shown"
+ );
+
+ info("Switch away and back to release notes");
+ // Load details view.
+ let detailsBtn = tabGroup.querySelector('.tab-button[name="details"]');
+ let viewChanged = BrowserTestUtils.waitForEvent(deck, "view-changed");
+ detailsBtn.click();
+ await viewChanged;
+
+ // Load release notes again, verify they weren't loaded.
+ viewChanged = BrowserTestUtils.waitForEvent(deck, "view-changed");
+ let notesCached = BrowserTestUtils.waitForEvent(
+ notes,
+ "release-notes-cached"
+ );
+ notesBtn.click();
+ await viewChanged;
+ await notesCached;
+
+ info("Install the update to clean it up");
+ await installUpdate(card, "update-installed");
+
+ await closeView(win);
+ await extension.unload();
+});
+
+add_task(async function testUpdateCancelled() {
+ let id = "update@mochi.test";
+ let extension = await setupExtensionWithUpdate(id, { cancelUpdate: true });
+
+ let win = await loadInitialView("extension");
+ let doc = win.document;
+
+ await loadDetailView(win, "update@mochi.test");
+ let card = doc.querySelector("addon-card");
+
+ // Disable updates and then check.
+ disableAutoUpdates(card);
+ await checkForUpdate(card, "update-found");
+
+ // There should now be an update.
+ assertUpdateState({ card, shown: true });
+
+ // The add-on starts as version 1.
+ let versionRow = card.querySelector(".addon-detail-row-version");
+ is(versionRow.lastChild.textContent, "1", "The version started as 1");
+
+ // Force the install to be cancelled.
+ let install = card.updateInstall;
+ ok(install, "There was an install found");
+
+ await installUpdate(card, "update-cancelled");
+
+ // The add-on is still version 1.
+ versionRow = card.querySelector(".addon-detail-row-version");
+ is(versionRow.lastChild.textContent, "1", "The version hasn't changed");
+
+ // The update has been removed.
+ assertUpdateState({ card, shown: false });
+
+ await closeView(win);
+ await extension.unload();
+});
+
+add_task(async function testAvailableUpdates() {
+ let ids = ["update1@mochi.test", "update2@mochi.test", "update3@mochi.test"];
+ let addons = await Promise.all(ids.map(id => setupExtensionWithUpdate(id)));
+
+ // Disable global add-on updates.
+ AddonManager.autoUpdateDefault = false;
+
+ let win = await loadInitialView("extension");
+ let doc = win.document;
+ let updatesMessage = doc.getElementById("updates-message");
+ let categoryUtils = new CategoryUtilities(win);
+
+ let availableCat = categoryUtils.get("available-updates");
+
+ ok(availableCat.hidden, "Available updates is hidden");
+ is(availableCat.badgeCount, 0, "There are no updates");
+ ok(updatesMessage, "There is an updates message");
+ is_element_hidden(updatesMessage, "The message is hidden");
+ ok(!updatesMessage.message.textContent, "The message is empty");
+ ok(!updatesMessage.button.textContent, "The button is empty");
+
+ // Check for all updates.
+ let updatesFound = TestUtils.topicObserved("EM-update-check-finished");
+ doc.querySelector('#page-options [action="check-for-updates"]').click();
+
+ is_element_visible(updatesMessage, "The message is visible");
+ ok(!updatesMessage.message.textContent, "The message is empty");
+ ok(updatesMessage.button.hidden, "The view updates button is hidden");
+
+ // Make sure the message gets populated by fluent.
+ await TestUtils.waitForCondition(
+ () => updatesMessage.message.textContent,
+ "wait for message text"
+ );
+
+ await updatesFound;
+
+ // The button should be visible, and should get some text from fluent.
+ ok(!updatesMessage.button.hidden, "The view updates button is visible");
+ await TestUtils.waitForCondition(
+ () => updatesMessage.button.textContent,
+ "wait for button text"
+ );
+
+ // Wait for the available updates count to finalize, it's async.
+ await BrowserTestUtils.waitForCondition(() => availableCat.badgeCount == 3);
+
+ // The category shows the correct update count.
+ ok(!availableCat.hidden, "Available updates is visible");
+ is(availableCat.badgeCount, 3, "There are 3 updates");
+
+ // Go to the available updates page.
+ let loaded = waitForViewLoad(win);
+ availableCat.click();
+ await loaded;
+
+ // Check the updates are shown.
+ let cards = doc.querySelectorAll("addon-card");
+ is(cards.length, 3, "There are 3 cards");
+
+ // Each card should have an update.
+ for (let card of cards) {
+ assertUpdateState({ card, shown: true, expanded: false });
+ }
+
+ // Check the detail page for the first add-on.
+ await loadDetailView(win, ids[0]);
+ is(
+ categoryUtils.getSelectedViewId(),
+ "addons://list/extension",
+ "The extensions category is selected"
+ );
+
+ // Go back to the last view.
+ loaded = waitForViewLoad(win);
+ doc.querySelector(".back-button").click();
+ await loaded;
+
+ // We're back on the updates view.
+ is(
+ categoryUtils.getSelectedViewId(),
+ "addons://updates/available",
+ "The available updates category is selected"
+ );
+
+ // Find the cards again.
+ cards = doc.querySelectorAll("addon-card");
+ is(cards.length, 3, "There are 3 cards");
+
+ // Install the first update.
+ await installUpdate(cards[0], "update-installed");
+ assertUpdateState({ card: cards[0], shown: false, expanded: false });
+
+ // The count goes down but the card stays.
+ is(availableCat.badgeCount, 2, "There are only 2 updates now");
+ is(
+ doc.querySelectorAll("addon-card").length,
+ 3,
+ "All 3 cards are still visible on the updates page"
+ );
+
+ // Install the other two updates.
+ await installUpdate(cards[1], "update-installed");
+ assertUpdateState({ card: cards[1], shown: false, expanded: false });
+ await installUpdate(cards[2], "update-installed");
+ assertUpdateState({ card: cards[2], shown: false, expanded: false });
+
+ // The count goes down but the card stays.
+ is(availableCat.badgeCount, 0, "There are no more updates");
+ is(
+ doc.querySelectorAll("addon-card").length,
+ 3,
+ "All 3 cards are still visible on the updates page"
+ );
+
+ // Enable global add-on updates again.
+ AddonManager.autoUpdateDefault = true;
+
+ await closeView(win);
+ await Promise.all(addons.map(addon => addon.unload()));
+});
+
+add_task(async function testUpdatesShownOnLoad() {
+ let id = "has-update@mochi.test";
+ let addon = await setupExtensionWithUpdate(id);
+
+ // Find the update for our addon.
+ AddonManager.autoUpdateDefault = false;
+ await findUpdatesForAddonId(id);
+
+ let win = await loadInitialView("extension");
+ let categoryUtils = new CategoryUtilities(win);
+ let updatesButton = categoryUtils.get("available-updates");
+
+ ok(!updatesButton.hidden, "The updates button is shown");
+ is(updatesButton.badgeCount, 1, "There is an update");
+
+ let loaded = waitForViewLoad(win);
+ updatesButton.click();
+ await loaded;
+
+ let cards = win.document.querySelectorAll("addon-card");
+
+ is(cards.length, 1, "There is one update card");
+
+ let card = cards[0];
+ is(card.addon.id, id, "The update is for the expected add-on");
+
+ await installUpdate(card, "update-installed");
+
+ ok(!updatesButton.hidden, "The updates button is still shown");
+ is(updatesButton.badgeCount, 0, "There are no more updates");
+
+ info("Check that the updates section is hidden when re-opened");
+ await closeView(win);
+ win = await loadInitialView("extension");
+ categoryUtils = new CategoryUtilities(win);
+ updatesButton = categoryUtils.get("available-updates");
+
+ ok(updatesButton.hidden, "Available updates is hidden");
+ is(updatesButton.badgeCount, 0, "There are no updates");
+
+ AddonManager.autoUpdateDefault = true;
+ await closeView(win);
+ await addon.unload();
+});
+
+add_task(async function testPromptOnBackgroundUpdateCheck() {
+ const id = "test-prompt-on-background-check@mochi.test";
+ const extension = await setupExtensionWithUpdate(id);
+
+ AddonManager.autoUpdateDefault = false;
+
+ const addon = await AddonManager.getAddonByID(id);
+ await AddonTestUtils.promiseFindAddonUpdates(
+ addon,
+ AddonManager.UPDATE_WHEN_PERIODIC_UPDATE
+ );
+ let win = await loadInitialView("extension");
+
+ let card = getAddonCard(win, id);
+
+ const promisePromptInfo = promisePermissionPrompt(id);
+ await installUpdate(card, "update-installed");
+ const promptInfo = await promisePromptInfo;
+ ok(promptInfo, "Got a permission prompt as expected");
+
+ AddonManager.autoUpdateDefault = true;
+
+ await closeView(win);
+ await extension.unload();
+});
+
+add_task(async function testNoUpdateAvailableOnUnrelatedAddonCards() {
+ let idNoUpdate = "no-update@mochi.test";
+
+ let extensionNoUpdate = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {
+ name: "TestAddonNoUpdate",
+ browser_specific_settings: { gecko: { id: idNoUpdate } },
+ },
+ });
+ await extensionNoUpdate.startup();
+
+ let win = await loadInitialView("extension");
+
+ let cardNoUpdate = getAddonCard(win, idNoUpdate);
+ ok(cardNoUpdate, `Got AddonCard for ${idNoUpdate}`);
+
+ // Assert that there is not an update badge
+ assertUpdateState({ card: cardNoUpdate, shown: false, expanded: false });
+
+ // Trigger a onNewInstall event by install another unrelated addon.
+ const XPI_URL = `${SECURE_TESTROOT}../xpinstall/amosigned.xpi`;
+ let install = await AddonManager.getInstallForURL(XPI_URL);
+ await AddonManager.installAddonFromAOM(
+ gBrowser.selectedBrowser,
+ win.document.documentURIObject,
+ install
+ );
+
+ // Cancel the install used to trigger the onNewInstall install event.
+ await install.cancel();
+ // Assert that the previously installed addon isn't marked with the
+ // update available badge after installing an unrelated addon.
+ assertUpdateState({ card: cardNoUpdate, shown: false, expanded: false });
+
+ await closeView(win);
+ await extensionNoUpdate.unload();
+});