michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: // Tests the selection part of the post-app-update dialog michael@0: michael@0: var gProvider; michael@0: var gWin; michael@0: michael@0: const PROFILE = AddonManager.SCOPE_PROFILE; michael@0: const USER = AddonManager.SCOPE_USER; michael@0: const APP = AddonManager.SCOPE_APPLICATION; michael@0: const SYSTEM = AddonManager.SCOPE_SYSTEM; michael@0: const DIST = -1; michael@0: michael@0: // The matrix of testcases for the selection part of the UI michael@0: // Note that the isActive flag has the value it had when the previous version michael@0: // of the application ran with this add-on. michael@0: var ADDONS = [ michael@0: //userDisabled wasAppDisabled isAppDisabled isActive hasUpdate autoUpdate scope defaultKeep position keepString disableString michael@0: [false, true, false, false, false, true, PROFILE, true, 42, "enabled", ""], // 0 michael@0: [false, true, false, false, true, true, PROFILE, true, 43, "enabled", ""], // 1 michael@0: [false, true, false, false, true, false, PROFILE, true, 52, "unneededupdate", ""], // 2 michael@0: [false, false, false, true, false, true, PROFILE, true, 53, "", "disabled"], // 3 michael@0: [false, false, false, true, true, true, PROFILE, true, 54, "", "disabled"], // 4 michael@0: [false, false, false, true, true, false, PROFILE, true, 55, "unneededupdate", "disabled"], // 5 michael@0: [false, true, true, false, false, true, PROFILE, true, 56, "incompatible", ""], // 6 michael@0: [false, true, true, false, true, true, PROFILE, true, 57, "autoupdate", ""], // 7 michael@0: [false, true, true, false, true, false, PROFILE, true, 58, "neededupdate", ""], // 8 michael@0: [false, false, true, true, false, true, PROFILE, true, 59, "incompatible", "disabled"], // 9 michael@0: [false, true, true, true, true, true, PROFILE, true, 44, "autoupdate", "disabled"], // 10 michael@0: [false, true, true, true, true, false, PROFILE, true, 45, "neededupdate", "disabled"], // 11 michael@0: [true, false, false, false, false, true, PROFILE, false, 46, "enabled", ""], // 12 michael@0: [true, false, false, false, true, true, PROFILE, false, 47, "enabled", ""], // 13 michael@0: [true, false, false, false, true, false, PROFILE, false, 48, "unneededupdate", ""], // 14 michael@0: michael@0: // userDisabled and isActive cannot be true on startup michael@0: michael@0: [true, true, true, false, false, true, PROFILE, false, 49, "incompatible", ""], // 15 michael@0: [true, true, true, false, true, true, PROFILE, false, 50, "autoupdate", ""], // 16 michael@0: [true, true, true, false, true, false, PROFILE, false, 51, "neededupdate", ""], // 17 michael@0: michael@0: // userDisabled and isActive cannot be true on startup michael@0: michael@0: // Being in a different scope should make little difference except no updates are possible so don't exhaustively test each michael@0: [false, false, false, true, true, false, USER, false, 0, "", "disabled"], // 18 michael@0: [true, true, false, false, true, false, USER, false, 1, "enabled", ""], // 19 michael@0: [false, true, true, true, true, false, USER, false, 2, "incompatible", "disabled"], // 20 michael@0: [true, true, true, false, true, false, USER, false, 3, "incompatible", ""], // 21 michael@0: [false, false, false, true, true, false, SYSTEM, false, 4, "", "disabled"], // 22 michael@0: [true, true, false, false, true, false, SYSTEM, false, 5, "enabled", ""], // 23 michael@0: [false, true, true, true, true, false, SYSTEM, false, 6, "incompatible", "disabled"], // 24 michael@0: [true, true, true, false, true, false, SYSTEM, false, 7, "incompatible", ""], // 25 michael@0: [false, false, false, true, true, false, APP, false, 8, "", "disabled"], // 26 michael@0: [true, true, false, false, true, false, APP, false, 9, "enabled", ""], // 27 michael@0: [false, true, true, true, true, false, APP, false, 10, "incompatible", "disabled"], // 28 michael@0: [true, true, true, false, true, false, APP, false, 11, "incompatible", ""], // 29 michael@0: ]; michael@0: michael@0: function waitForView(aView, aCallback) { michael@0: var view = gWin.document.getElementById(aView); michael@0: if (view.parentNode.selectedPanel == view) { michael@0: aCallback(); michael@0: return; michael@0: } michael@0: michael@0: view.addEventListener("ViewChanged", function() { michael@0: view.removeEventListener("ViewChanged", arguments.callee, false); michael@0: aCallback(); michael@0: }, false); michael@0: } michael@0: michael@0: function getString(aName) { michael@0: if (!aName) michael@0: return ""; michael@0: michael@0: var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties"); michael@0: return strings.GetStringFromName("action." + aName); michael@0: } michael@0: michael@0: function getSourceString(aSource) { michael@0: if (!aSource) michael@0: return ""; michael@0: michael@0: var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties"); michael@0: switch (aSource) { michael@0: case PROFILE: michael@0: return strings.GetStringFromName("source.profile"); michael@0: case DIST: michael@0: return strings.GetStringFromName("source.bundled"); michael@0: default: michael@0: return strings.GetStringFromName("source.other"); michael@0: } michael@0: } michael@0: michael@0: function test() { michael@0: waitForExplicitFinish(); michael@0: michael@0: gProvider = new MockProvider(); michael@0: michael@0: // Set prefs for Distributed Extension Source tests. michael@0: Services.prefs.setBoolPref("extensions.installedDistroAddon.test3@tests.mozilla.org", true); michael@0: Services.prefs.setBoolPref("extensions.installedDistroAddon.test12@tests.mozilla.org", true); michael@0: Services.prefs.setBoolPref("extensions.installedDistroAddon.test15@tests.mozilla.org", true); michael@0: michael@0: for (let pos in ADDONS) { michael@0: let addonItem = ADDONS[pos]; michael@0: let addon = new MockAddon("test" + pos + "@tests.mozilla.org", michael@0: "Test Add-on " + pos, "extension"); michael@0: addon.version = "1.0"; michael@0: addon.userDisabled = addonItem[0]; michael@0: addon.appDisabled = addonItem[1]; michael@0: addon.isActive = addonItem[3]; michael@0: addon.applyBackgroundUpdates = addonItem[5] ? AddonManager.AUTOUPDATE_ENABLE michael@0: : AddonManager.AUTOUPDATE_DISABLE; michael@0: addon.scope = addonItem[6]; michael@0: michael@0: // Remove the upgrade permission from non-profile add-ons michael@0: if (addon.scope != AddonManager.SCOPE_PROFILE) michael@0: addon._permissions -= AddonManager.PERM_CAN_UPGRADE; michael@0: michael@0: addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) { michael@0: addon.appDisabled = addonItem[2]; michael@0: addon.isActive = addon.shouldBeActive; michael@0: michael@0: if (addonItem[4]) { michael@0: var newAddon = new MockAddon(this.id, this.name, "extension"); michael@0: newAddon.version = "2.0"; michael@0: var install = new MockInstall(this.name, this.type, newAddon); michael@0: install.existingAddon = this; michael@0: aListener.onUpdateAvailable(this, install); michael@0: } michael@0: michael@0: aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR); michael@0: }; michael@0: michael@0: gProvider.addAddon(addon); michael@0: } michael@0: michael@0: gWin = Services.ww.openWindow(null, michael@0: "chrome://mozapps/content/extensions/selectAddons.xul", michael@0: "", michael@0: "chrome,centerscreen,dialog,titlebar", michael@0: null); michael@0: waitForFocus(function() { michael@0: waitForView("select", run_next_test); michael@0: }, gWin); michael@0: } michael@0: michael@0: function end_test() { michael@0: gWin.close(); michael@0: finish(); michael@0: } michael@0: michael@0: // Minimal test for the checking UI michael@0: add_test(function checking_test() { michael@0: // By the time we're here the progress bar should be full michael@0: var progress = gWin.document.getElementById("checking-progress"); michael@0: is(progress.mode, "determined", "Should be a determined progress bar"); michael@0: is(progress.value, progress.max, "Should be at full progress"); michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: // Tests that the selection UI behaves correctly michael@0: add_test(function selection_test() { michael@0: function check_state() { michael@0: var str = addon[keep.checked ? 9 : 10]; michael@0: var expected = getString(str); michael@0: var showCheckbox = str == "neededupdate" || str == "unneededupdate"; michael@0: is(action.textContent, expected, "Action message should have the right text"); michael@0: is(!is_hidden(update), showCheckbox, "Checkbox should have the right visibility"); michael@0: is(is_hidden(action), showCheckbox, "Message should have the right visibility"); michael@0: if (showCheckbox) michael@0: ok(update.checked, "Optional update checkbox should be checked"); michael@0: michael@0: if (keep.checked) { michael@0: is(row.hasAttribute("active"), !addon[2] || hasUpdate, michael@0: "Add-on will be active if it isn't appDisabled or an update is available"); michael@0: michael@0: if (showCheckbox) { michael@0: info("Flipping update checkbox"); michael@0: EventUtils.synthesizeMouseAtCenter(update, { }, gWin); michael@0: is(row.hasAttribute("active"), str == "unneededupdate", michael@0: "If the optional update isn't needed then the add-on will still be active"); michael@0: michael@0: info("Flipping update checkbox"); michael@0: EventUtils.synthesizeMouseAtCenter(update, { }, gWin); michael@0: is(row.hasAttribute("active"), !addon[2] || hasUpdate, michael@0: "Add-on will be active if it isn't appDisabled or an update is available"); michael@0: } michael@0: } michael@0: else { michael@0: ok(!row.hasAttribute("active"), "Add-on won't be active when not keeping"); michael@0: michael@0: if (showCheckbox) { michael@0: info("Flipping update checkbox"); michael@0: EventUtils.synthesizeMouseAtCenter(update, { }, gWin); michael@0: ok(!row.hasAttribute("active"), michael@0: "Unchecking the update checkbox shouldn't make the add-on active"); michael@0: michael@0: info("Flipping update checkbox"); michael@0: EventUtils.synthesizeMouseAtCenter(update, { }, gWin); michael@0: ok(!row.hasAttribute("active"), michael@0: "Re-checking the update checkbox shouldn't make the add-on active"); michael@0: } michael@0: } michael@0: } michael@0: michael@0: is(gWin.document.getElementById("view-deck").selectedPanel.id, "select", michael@0: "Should be on the right view"); michael@0: michael@0: var pos = 0; michael@0: var scrollbox = gWin.document.getElementById("select-scrollbox"); michael@0: var scrollBoxObject = scrollbox.boxObject.QueryInterface(Ci.nsIScrollBoxObject); michael@0: for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { michael@0: // Ignore separators but increase the position by a large amount so we michael@0: // can verify they were in the right place michael@0: if (row.localName == "separator") { michael@0: pos += 30; michael@0: continue; michael@0: } michael@0: michael@0: is(row._addon.type, "extension", "Should only be listing extensions"); michael@0: michael@0: // Ignore non-test add-ons that may be present michael@0: if (row.id.substr(-18) != "@tests.mozilla.org") michael@0: continue; michael@0: michael@0: var id = parseInt(row.id.substring(4, row.id.length - 18)); michael@0: var addon = ADDONS[id]; michael@0: michael@0: info("Testing add-on " + id); michael@0: scrollBoxObject.ensureElementIsVisible(row); michael@0: var keep = gWin.document.getAnonymousElementByAttribute(row, "anonid", "keep"); michael@0: var action = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-action-message"); michael@0: var update = gWin.document.getAnonymousElementByAttribute(row, "anonid", "update"); michael@0: var source = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-source"); michael@0: michael@0: if (id == 3 || id == 12 || id == 15) { michael@0: // Distro Installed To Profile michael@0: is(source.textContent, getSourceString(DIST), "Source message should have the right text for Distributed Addons"); michael@0: } else { michael@0: is(source.textContent, getSourceString(addon[6]), "Source message should have the right text"); michael@0: } michael@0: michael@0: // Non-profile add-ons don't appear to have updates since we won't install michael@0: // them michael@0: var hasUpdate = addon[4] && addon[6] == PROFILE; michael@0: michael@0: is(pos, addon[8], "Should have been in the right position"); michael@0: is(keep.checked, addon[7], "Keep checkbox should be in the right state"); michael@0: michael@0: check_state(); michael@0: michael@0: info("Flipping keep"); michael@0: EventUtils.synthesizeMouseAtCenter(keep, { }, gWin); michael@0: is(keep.checked, !addon[7], "Keep checkbox should be in the right state"); michael@0: michael@0: check_state(); michael@0: michael@0: pos++; michael@0: } michael@0: michael@0: is(pos, 60, "Should have seen the right number of add-ons"); michael@0: michael@0: run_next_test(); michael@0: });