зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1769146 - Integrate previously saved colorway themes in Colorways section within about:addons. r=dao,rpl
Differential Revision: https://phabricator.services.mozilla.com/D148867
This commit is contained in:
Родитель
a523865d98
Коммит
76abd1c793
|
@ -842,7 +842,7 @@ section:not(:empty) ~ #empty-addons-message {
|
|||
font-weight: bolder;
|
||||
}
|
||||
|
||||
#colorways-section-heading {
|
||||
.colorways-section > .list-section-heading {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -210,11 +210,6 @@
|
|||
<button id="colorways-button" class="primary" action="open-colorways" data-l10n-id="theme-colorways-button"></button>
|
||||
</template>
|
||||
|
||||
<template name="colorways-list">
|
||||
<h2 id="colorways-section-heading" class="list-section-heading" data-l10n-id="theme-monochromatic-heading"></h2>
|
||||
<h3 id="colorways-section-subheading" class="list-section-subheading" data-l10n-id="theme-monochromatic-subheading"></h3>
|
||||
</template>
|
||||
|
||||
<template name="addon-name-container-in-disco-card">
|
||||
<div class="disco-card-head">
|
||||
<h3 class="disco-addon-name"></h3>
|
||||
|
|
|
@ -3693,6 +3693,12 @@ class AddonCard extends HTMLElement {
|
|||
customElements.define("addon-card", AddonCard);
|
||||
|
||||
class ColorwayClosetCard extends HTMLElement {
|
||||
connectedCallback() {
|
||||
if (this.childElementCount === 0) {
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let card = importTemplate("card").firstElementChild;
|
||||
let heading = card.querySelector(".addon-name-container");
|
||||
|
@ -4144,7 +4150,11 @@ class AddonList extends HTMLElement {
|
|||
}
|
||||
|
||||
createSectionHeading(headingIndex) {
|
||||
let { headingId, subheadingId } = this.sections[headingIndex];
|
||||
let {
|
||||
headingId,
|
||||
subheadingId,
|
||||
sectionPreambleCustomElement,
|
||||
} = this.sections[headingIndex];
|
||||
let frag = document.createDocumentFragment();
|
||||
let heading = document.createElement("h2");
|
||||
heading.classList.add("list-section-heading");
|
||||
|
@ -4154,11 +4164,19 @@ class AddonList extends HTMLElement {
|
|||
if (subheadingId) {
|
||||
let subheading = document.createElement("h3");
|
||||
subheading.classList.add("list-section-subheading");
|
||||
heading.className = "header-name";
|
||||
document.l10n.setAttributes(subheading, subheadingId);
|
||||
// Preserve the old colorway section header styling
|
||||
// while the colorway closet section is not yet ready to be enabled
|
||||
if (!COLORWAY_CLOSET_ENABLED) {
|
||||
heading.className = "header-name";
|
||||
}
|
||||
frag.append(subheading);
|
||||
}
|
||||
|
||||
if (sectionPreambleCustomElement) {
|
||||
frag.append(document.createElement(sectionPreambleCustomElement));
|
||||
}
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
|
@ -4190,9 +4208,12 @@ class AddonList extends HTMLElement {
|
|||
}
|
||||
|
||||
updateSectionIfEmpty(section) {
|
||||
// The header is added before any add-on cards, so if there's only one
|
||||
// child then it's the header. In that case we should empty out the section.
|
||||
if (section.children.length == 1) {
|
||||
// We should empty out the section if there are no more cards to display,
|
||||
// (unless the section is configured to stay visible and rendered even when
|
||||
// there is no addon listed, e.g. the "Colorways Closet" section).
|
||||
const sectionIndex = parseInt(section.getAttribute("section"));
|
||||
const { shouldRenderIfEmpty } = this.sections[sectionIndex];
|
||||
if (!this.getCards(section).length && !shouldRenderIfEmpty) {
|
||||
section.textContent = "";
|
||||
}
|
||||
}
|
||||
|
@ -4201,8 +4222,12 @@ class AddonList extends HTMLElement {
|
|||
let section = this.getSection(sectionIndex);
|
||||
let sectionCards = this.getCards(section);
|
||||
|
||||
// If this is the first card in the section, create the heading.
|
||||
if (!sectionCards.length) {
|
||||
const { shouldRenderIfEmpty } = this.sections[sectionIndex];
|
||||
|
||||
// If this is the first card in the section, and the section
|
||||
// isn't configure to render the headers even when empty,
|
||||
// we have to create the section heading first.
|
||||
if (!shouldRenderIfEmpty && !sectionCards.length) {
|
||||
section.appendChild(this.createSectionHeading(sectionIndex));
|
||||
}
|
||||
|
||||
|
@ -4392,7 +4417,7 @@ class AddonList extends HTMLElement {
|
|||
}
|
||||
|
||||
renderSection(addons, index) {
|
||||
const { sectionClass, sectionPreambleCustomElement } = this.sections[index];
|
||||
const { sectionClass, shouldRenderIfEmpty } = this.sections[index];
|
||||
|
||||
let section = document.createElement("section");
|
||||
section.setAttribute("section", index);
|
||||
|
@ -4401,20 +4426,15 @@ class AddonList extends HTMLElement {
|
|||
}
|
||||
|
||||
// Render the heading and add-ons if there are any.
|
||||
if (addons.length) {
|
||||
if (sectionPreambleCustomElement) {
|
||||
section.appendChild(
|
||||
document.createElement(sectionPreambleCustomElement)
|
||||
);
|
||||
}
|
||||
if (shouldRenderIfEmpty || addons.length) {
|
||||
section.appendChild(this.createSectionHeading(index));
|
||||
}
|
||||
|
||||
for (let addon of addons) {
|
||||
let card = document.createElement("addon-card");
|
||||
card.setAddon(addon);
|
||||
card.render();
|
||||
section.appendChild(card);
|
||||
}
|
||||
for (let addon of addons) {
|
||||
let card = document.createElement("addon-card");
|
||||
card.setAddon(addon);
|
||||
card.render();
|
||||
section.appendChild(card);
|
||||
}
|
||||
|
||||
return section;
|
||||
|
@ -4517,22 +4537,6 @@ class AddonList extends HTMLElement {
|
|||
}
|
||||
customElements.define("addon-list", AddonList);
|
||||
|
||||
class ColorwayClosetList extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.appendChild(importTemplate(this.template));
|
||||
let frag = document.createDocumentFragment();
|
||||
let card = document.createElement("colorways-card");
|
||||
card.render();
|
||||
frag.append(card);
|
||||
this.append(frag);
|
||||
}
|
||||
|
||||
get template() {
|
||||
return "colorways-list";
|
||||
}
|
||||
}
|
||||
customElements.define("colorways-list", ColorwayClosetList);
|
||||
|
||||
class RecommendedAddonList extends HTMLElement {
|
||||
connectedCallback() {
|
||||
if (this.isConnected) {
|
||||
|
@ -4828,15 +4832,12 @@ gViewController.defineView("list", async type => {
|
|||
return null;
|
||||
}
|
||||
|
||||
// If monochromatic themes are enabled and any are builtin to Firefox, we
|
||||
// display those themes together in a separate subsection.
|
||||
const areColorwayThemesInstalled = async () =>
|
||||
(await AddonManager.getAllAddons()).some(
|
||||
addon =>
|
||||
BuiltInThemes.isMonochromaticTheme(addon.id) &&
|
||||
!BuiltInThemes.themeIsExpired(addon.id)
|
||||
);
|
||||
|
||||
let frag = document.createDocumentFragment();
|
||||
let list = document.createElement("addon-list");
|
||||
list.type = type;
|
||||
|
@ -4848,43 +4849,68 @@ gViewController.defineView("list", async type => {
|
|||
filterFn: addon =>
|
||||
!addon.hidden && addon.isActive && !isPending(addon, "uninstall"),
|
||||
},
|
||||
{
|
||||
headingId: getL10nIdMapping(`${type}-disabled-heading`),
|
||||
sectionClass: `${type}-disabled-section`,
|
||||
];
|
||||
|
||||
if (type == "theme" && COLORWAY_CLOSET_ENABLED) {
|
||||
MozXULElement.insertFTLIfNeeded("preview/colorwaycloset.ftl");
|
||||
|
||||
const hasActiveColorways = !!BuiltInThemes.findActiveColorwayCollection?.();
|
||||
sections.push({
|
||||
headingId: "theme-monochromatic-heading",
|
||||
subheadingId: "theme-monochromatic-subheading",
|
||||
sectionClass: "colorways-section",
|
||||
// Insert colorway closet card as the first element in the colorways
|
||||
// section so that it is above any retained colorway themes.
|
||||
sectionPreambleCustomElement: hasActiveColorways
|
||||
? "colorways-card"
|
||||
: null,
|
||||
// This section should also be rendered when there is no addons that
|
||||
// match the filterFn, because we still want to show the headers and
|
||||
// colorways-card. But, we only expect the colorways-card to be visible
|
||||
// when there is an active colorway collection.
|
||||
shouldRenderIfEmpty: hasActiveColorways,
|
||||
filterFn: addon =>
|
||||
!addon.hidden &&
|
||||
!addon.isActive &&
|
||||
!isPending(addon, "uninstall") &&
|
||||
// For performance related details about this check see the
|
||||
// documentation for themeIsExpired in BuiltInThemeConfig.jsm.
|
||||
(!BuiltInThemes.isMonochromaticTheme(addon.id) ||
|
||||
BuiltInThemes.isRetainedExpiredTheme(addon.id)),
|
||||
},
|
||||
];
|
||||
|
||||
let colorwaysThemeInstalled;
|
||||
if (type == "theme") {
|
||||
colorwaysThemeInstalled = await areColorwayThemesInstalled();
|
||||
if (colorwaysThemeInstalled && COLORWAY_CLOSET_ENABLED) {
|
||||
// Avoid inserting colorway closet fluent strings in aboutaddons.html,
|
||||
// considering that there is a dependency on a browser-only resource.
|
||||
const fluentResourceId = "preview/colorwaycloset.ftl";
|
||||
if (!document.head.querySelector(`link[href='${fluentResourceId}']`)) {
|
||||
const fluentLink = document.createElement("link");
|
||||
fluentLink.setAttribute("rel", "localization");
|
||||
fluentLink.setAttribute("href", fluentResourceId);
|
||||
document.head.appendChild(fluentLink);
|
||||
}
|
||||
// Insert colorway closet card as the first element so that
|
||||
// it is positioned between the enabled and disabled sections.
|
||||
sections[1].sectionPreambleCustomElement = "colorways-list";
|
||||
}
|
||||
BuiltInThemes.isMonochromaticTheme(addon.id) &&
|
||||
BuiltInThemes.isRetainedExpiredTheme(addon.id),
|
||||
});
|
||||
}
|
||||
|
||||
const disabledAddonsFilterFn = addon =>
|
||||
!addon.hidden && !addon.isActive && !isPending(addon, "uninstall");
|
||||
|
||||
const disabledThemesFilterFn = addon =>
|
||||
disabledAddonsFilterFn(addon) &&
|
||||
((BuiltInThemes.isRetainedExpiredTheme(addon.id) &&
|
||||
!COLORWAY_CLOSET_ENABLED) ||
|
||||
!BuiltInThemes.isMonochromaticTheme(addon.id));
|
||||
|
||||
sections.push({
|
||||
headingId: getL10nIdMapping(`${type}-disabled-heading`),
|
||||
sectionClass: `${type}-disabled-section`,
|
||||
filterFn: addon => {
|
||||
if (addon.type === "theme") {
|
||||
return disabledThemesFilterFn(addon);
|
||||
}
|
||||
return disabledAddonsFilterFn(addon);
|
||||
},
|
||||
});
|
||||
|
||||
list.setSections(sections);
|
||||
frag.appendChild(list);
|
||||
|
||||
if (type == "theme" && colorwaysThemeInstalled) {
|
||||
// Add old colorways section if the new colorway closet is not enabled.
|
||||
// If monochromatic themes are enabled and any are builtin to Firefox, we
|
||||
// display those themes together in a separate subsection.
|
||||
if (
|
||||
type == "theme" &&
|
||||
!COLORWAY_CLOSET_ENABLED &&
|
||||
(await areColorwayThemesInstalled())
|
||||
) {
|
||||
let monochromaticList = document.createElement("addon-list");
|
||||
monochromaticList.classList.add("monochromatic-addon-list");
|
||||
monochromaticList.type = type;
|
||||
|
|
|
@ -11,10 +11,14 @@ const { BuiltInThemeConfig } = ChromeUtils.import(
|
|||
const { ColorwayClosetOpener } = ChromeUtils.import(
|
||||
"resource:///modules/ColorwayClosetOpener.jsm"
|
||||
);
|
||||
const { BuiltInThemes } = ChromeUtils.import(
|
||||
"resource:///modules/BuiltInThemes.jsm"
|
||||
);
|
||||
|
||||
AddonTestUtils.initMochitest(this);
|
||||
|
||||
const kTestThemeId = "test-colorway@mozilla.org";
|
||||
const kTestExpiredThemeId = `expired-${kTestThemeId}`;
|
||||
|
||||
// Return a mock expiry date set 1 year ahead from the current date.
|
||||
function getMockExpiry() {
|
||||
|
@ -23,6 +27,66 @@ function getMockExpiry() {
|
|||
return expireDate;
|
||||
}
|
||||
|
||||
function getMockThemeXpi(id) {
|
||||
return AddonTestUtils.createTempWebExtensionFile({
|
||||
manifest: {
|
||||
name: "Monochromatic Theme",
|
||||
applications: { gecko: { id } },
|
||||
theme: {},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function setMockThemeToExpired(id) {
|
||||
let yesterday = new Date();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
yesterday = yesterday.toISOString().split("T")[0];
|
||||
// Add the test theme to our list of built-in themes so that aboutaddons.js
|
||||
// will think this theme is expired.
|
||||
BuiltInThemes.builtInThemeMap.set(id, {
|
||||
version: "1.0",
|
||||
expiry: yesterday,
|
||||
// We use the manifest from Light theme since we know it will be in-tree
|
||||
// indefinitely.
|
||||
path: "resource://builtin-themes/light/",
|
||||
});
|
||||
}
|
||||
|
||||
function setBuiltInThemeConfigMock(...args) {
|
||||
info("Mocking BuiltInThemeConfig.findActiveColorwaysCollection");
|
||||
BuiltInThemeConfig.findActiveColorwayCollection = () => {
|
||||
// Return no active collection
|
||||
if (!args || !args.length) {
|
||||
info("Return no active collection");
|
||||
return null;
|
||||
}
|
||||
|
||||
const { mockExpiry, mockL10nId } = args[0];
|
||||
info(
|
||||
`Return mock active colorway collection with expiry set to: ${
|
||||
mockExpiry.toUTCString().split("T")[0]
|
||||
}`
|
||||
);
|
||||
return {
|
||||
id: "colorway-test-collection",
|
||||
expiry: mockExpiry,
|
||||
l10nId: {
|
||||
title: mockL10nId,
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function clearBuiltInThemeConfigMock(originalFindActiveCollection) {
|
||||
info("Cleaning up BuiltInThemeConfigMock");
|
||||
if (
|
||||
BuiltInThemeConfig.findActiveColorwayCollection !==
|
||||
originalFindActiveCollection
|
||||
) {
|
||||
BuiltInThemeConfig.findActiveColorwayCollection = originalFindActiveCollection;
|
||||
}
|
||||
}
|
||||
|
||||
add_setup(async function() {
|
||||
info("Register mock fluent locale strings");
|
||||
|
||||
|
@ -89,15 +153,9 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
|||
// Mock BuiltInThemeConfig.findActiveColorwaysCollection with test colorways.
|
||||
const originalFindActiveCollection =
|
||||
BuiltInThemeConfig.findActiveColorwayCollection;
|
||||
const clearBuiltInThemeConfigMock = () => {
|
||||
if (
|
||||
BuiltInThemeConfig.findActiveColorwayCollection !==
|
||||
originalFindActiveCollection
|
||||
) {
|
||||
BuiltInThemeConfig.findActiveColorwayCollection = originalFindActiveCollection;
|
||||
}
|
||||
};
|
||||
registerCleanupFunction(clearBuiltInThemeConfigMock);
|
||||
registerCleanupFunction(() => {
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
||||
// Mock collection l10n part of the mocked fluent resources.
|
||||
const mockL10nId = "colorway-collection-test-mock";
|
||||
|
@ -118,27 +176,9 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
|||
);
|
||||
}
|
||||
|
||||
info("Now mocking BuiltInThemeConfig.findActiveColorwayCollection");
|
||||
BuiltInThemeConfig.findActiveColorwayCollection = () => {
|
||||
info(
|
||||
`Return mock active colorway collection with expiry set to: ${
|
||||
mockExpiry.toUTCString().split("T")[0]
|
||||
}`
|
||||
);
|
||||
return {
|
||||
id: "colorway-test-collection",
|
||||
expiry: mockExpiry,
|
||||
l10nId: { title: mockL10nId },
|
||||
};
|
||||
};
|
||||
setBuiltInThemeConfigMock({ mockExpiry, mockL10nId });
|
||||
|
||||
const themeXpi = AddonTestUtils.createTempWebExtensionFile({
|
||||
manifest: {
|
||||
name: "Monochromatic Theme",
|
||||
applications: { gecko: { id: kTestThemeId } },
|
||||
theme: {},
|
||||
},
|
||||
});
|
||||
const themeXpi = getMockThemeXpi(kTestThemeId);
|
||||
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
||||
|
||||
let win = await loadInitialView("theme");
|
||||
|
@ -151,28 +191,27 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
|||
// Add mocked fluent resources for the mocked active colorway collection.
|
||||
doc.l10n.addResourceIds(["mock-colorwaycloset.ftl"]);
|
||||
|
||||
let colorwayClosetList = doc.querySelector("colorways-list");
|
||||
let colorwaySection = getSection(doc, "colorways-section");
|
||||
ok(colorwaySection, "colorway section was found");
|
||||
|
||||
// Make sure fluent strings have all been translated before
|
||||
// asserting the expected element to not have empty textContent.
|
||||
await doc.l10n.translateFragment(colorwayClosetList);
|
||||
await doc.l10n.translateFragment(colorwaySection);
|
||||
|
||||
info("Verifying colorway closet list contents");
|
||||
ok(colorwayClosetList, "colorway closet list was found");
|
||||
ok(
|
||||
colorwayClosetList.querySelector("#colorways-section-heading"),
|
||||
colorwaySection.querySelector(".list-section-heading"),
|
||||
"colorway closet heading was found"
|
||||
);
|
||||
ok(
|
||||
colorwayClosetList.querySelector("#colorways-section-subheading"),
|
||||
colorwaySection.querySelector(".list-section-subheading"),
|
||||
"colorway closet subheading was found"
|
||||
);
|
||||
|
||||
let cards = colorwayClosetList.querySelectorAll("colorways-card");
|
||||
ok(cards.length, "At least one colorway closet card was found");
|
||||
let card = colorwaySection.querySelector("colorways-card");
|
||||
ok(card, "colorway closet card was found");
|
||||
|
||||
info("Verifying colorway closet card contents");
|
||||
let card = cards[0];
|
||||
ok(
|
||||
card.querySelector("#colorways-preview-text-container"),
|
||||
"Preview text container found"
|
||||
|
@ -210,7 +249,8 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
|||
|
||||
await closeView(win);
|
||||
await addon.uninstall(true);
|
||||
clearBuiltInThemeConfigMock();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -221,23 +261,17 @@ add_task(async function testColorwayClosetSectionPrefDisabled() {
|
|||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.theme.colorway-closet", false]],
|
||||
});
|
||||
const themeXpi = AddonTestUtils.createTempWebExtensionFile({
|
||||
manifest: {
|
||||
name: "Monochromatic Theme",
|
||||
applications: { gecko: { id: kTestThemeId } },
|
||||
theme: {},
|
||||
},
|
||||
});
|
||||
const themeXpi = getMockThemeXpi(kTestThemeId);
|
||||
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
||||
|
||||
let win = await loadInitialView("theme");
|
||||
let doc = win.document;
|
||||
let colorwayClosetList = doc.querySelector("colorways-list");
|
||||
|
||||
ok(!colorwayClosetList, "colorway closet list should not be found");
|
||||
let colorwaySection = getSection(doc, "colorways-section");
|
||||
ok(!colorwaySection, "colorway section should not be found");
|
||||
|
||||
await closeView(win);
|
||||
await addon.uninstall(true);
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -249,6 +283,20 @@ add_task(async function testButtonOpenModal() {
|
|||
set: [["browser.theme.colorway-closet", true]],
|
||||
});
|
||||
|
||||
// Mock BuiltInThemeConfig.findActiveColorwaysCollection with test colorways.
|
||||
const originalFindActiveCollection =
|
||||
BuiltInThemeConfig.findActiveColorwayCollection;
|
||||
registerCleanupFunction(() => {
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
||||
// Mock collection l10n part of the mocked fluent resources.
|
||||
const mockL10nId = "colorway-collection-test-mock";
|
||||
|
||||
// Mock expiry date string and BuiltInThemeConfig.findActiveColorwayCollection()
|
||||
const mockExpiry = getMockExpiry();
|
||||
setBuiltInThemeConfigMock({ mockExpiry, mockL10nId });
|
||||
|
||||
let originalOpenModal = ColorwayClosetOpener.openModal;
|
||||
const clearOpenModalMock = () => {
|
||||
if (originalOpenModal) {
|
||||
|
@ -258,25 +306,19 @@ add_task(async function testButtonOpenModal() {
|
|||
};
|
||||
registerCleanupFunction(clearOpenModalMock);
|
||||
|
||||
const themeXpi = AddonTestUtils.createTempWebExtensionFile({
|
||||
manifest: {
|
||||
name: "Monochromatic Theme",
|
||||
applications: { gecko: { id: kTestThemeId } },
|
||||
theme: {},
|
||||
},
|
||||
});
|
||||
const themeXpi = getMockThemeXpi(kTestThemeId);
|
||||
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
||||
|
||||
let win = await loadInitialView("theme");
|
||||
let doc = win.document;
|
||||
let colorwayClosetList = doc.querySelector("colorways-list");
|
||||
let colorwaySection = getSection(doc, "colorways-section");
|
||||
|
||||
ok(colorwayClosetList, "colorway closet list was found");
|
||||
ok(colorwaySection, "colorway section was found");
|
||||
|
||||
let cards = colorwayClosetList.querySelectorAll("colorways-card");
|
||||
ok(cards.length, "At least one colorway closet card was found");
|
||||
let card = colorwaySection.querySelector("colorways-card");
|
||||
ok(card, "colorway closet card was found");
|
||||
|
||||
let colorwaysButton = cards[0].querySelector("#colorways-button");
|
||||
let colorwaysButton = card.querySelector("#colorways-button");
|
||||
ok(colorwaysButton, "colorway collection button found");
|
||||
let colorwayOpenerPromise = new Promise(resolve => {
|
||||
ColorwayClosetOpener.openModal = () => {
|
||||
|
@ -291,4 +333,191 @@ add_task(async function testButtonOpenModal() {
|
|||
await closeView(win);
|
||||
await addon.uninstall(true);
|
||||
clearOpenModalMock();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that disabled retained expired colorways appear in the list of retained
|
||||
* colorway themes, while disabled unexpired ones do not.
|
||||
*/
|
||||
add_task(async function testColorwayClosetSectionOneRetainedOneUnexpired() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.theme.colorway-closet", true]],
|
||||
});
|
||||
|
||||
// Mock BuiltInThemeConfig.findActiveColorwaysCollection with test colorways.
|
||||
const originalFindActiveCollection =
|
||||
BuiltInThemeConfig.findActiveColorwayCollection;
|
||||
registerCleanupFunction(() => {
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
||||
// Mock collection l10n part of the mocked fluent resources.
|
||||
const mockL10nId = "colorway-collection-test-mock";
|
||||
|
||||
// Mock expiry date string and BuiltInThemeConfig.findActiveColorwayCollection()
|
||||
const mockExpiry = getMockExpiry();
|
||||
setBuiltInThemeConfigMock({ mockExpiry, mockL10nId });
|
||||
|
||||
// Set expired theme as a retained colorway theme
|
||||
const retainedThemePrefName = "browser.theme.retainedExpiredThemes";
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [[retainedThemePrefName, JSON.stringify([kTestExpiredThemeId])]],
|
||||
});
|
||||
const themeXpiExpiredAddon = getMockThemeXpi(kTestExpiredThemeId);
|
||||
const expiredAddon = (
|
||||
await AddonTestUtils.promiseInstallFile(themeXpiExpiredAddon)
|
||||
).addon;
|
||||
|
||||
// Set up a valid addon that acts as a colorway theme that is not yet expired
|
||||
const validThemeId = `valid-${kTestThemeId}`;
|
||||
const themeXpiValidAddon = getMockThemeXpi(validThemeId);
|
||||
const validAddon = (
|
||||
await AddonTestUtils.promiseInstallFile(themeXpiValidAddon)
|
||||
).addon;
|
||||
|
||||
await expiredAddon.disable();
|
||||
await validAddon.disable();
|
||||
|
||||
// Make the test theme appear expired.
|
||||
setMockThemeToExpired(kTestExpiredThemeId);
|
||||
registerCleanupFunction(() => {
|
||||
BuiltInThemes.builtInThemeMap.delete(kTestExpiredThemeId);
|
||||
});
|
||||
|
||||
let win = await loadInitialView("theme");
|
||||
let doc = win.document;
|
||||
let colorwaySection = getSection(doc, "colorways-section");
|
||||
|
||||
info("Verifying colorway section order of elements");
|
||||
ok(
|
||||
colorwaySection.children.length,
|
||||
"colorway section should have at least 1 element"
|
||||
);
|
||||
is(
|
||||
colorwaySection.children[0].classList[0],
|
||||
"list-section-heading",
|
||||
"colorway section header should be first"
|
||||
);
|
||||
is(
|
||||
colorwaySection.children[1].classList[0],
|
||||
"list-section-subheading",
|
||||
"colorway section subheader should be second"
|
||||
);
|
||||
is(
|
||||
colorwaySection.children[2].tagName.toLowerCase(),
|
||||
"colorways-card",
|
||||
"colorway closet list should be third"
|
||||
);
|
||||
is(
|
||||
colorwaySection.children[3].tagName.toLowerCase(),
|
||||
"addon-card",
|
||||
"addon theme card should be fourth"
|
||||
);
|
||||
|
||||
info("Verifying cards in list of retained colorway themes");
|
||||
let expiredAddonCard = colorwaySection.querySelector(
|
||||
`addon-card[addon-id='${kTestExpiredThemeId}']`
|
||||
);
|
||||
ok(
|
||||
colorwaySection.contains(expiredAddonCard),
|
||||
"Colorways section contains the expired theme."
|
||||
);
|
||||
let disabledSection = getSection(doc, "theme-disabled-section");
|
||||
expiredAddonCard = disabledSection.querySelector(
|
||||
`addon-card[addon-id='${kTestExpiredThemeId}']`
|
||||
);
|
||||
ok(
|
||||
!disabledSection.contains(expiredAddonCard),
|
||||
"The regular, non-Colorways 'Disabled' section does not contain the expired theme."
|
||||
);
|
||||
|
||||
let validAddonCard = colorwaySection.querySelector(
|
||||
`addon-card[addon-id='${validThemeId}']`
|
||||
);
|
||||
ok(
|
||||
!colorwaySection.contains(validAddonCard),
|
||||
"Colorways section does not contain valid theme."
|
||||
);
|
||||
|
||||
await closeView(win);
|
||||
await expiredAddon.uninstall(true);
|
||||
await validAddon.uninstall(true);
|
||||
await SpecialPowers.popPrefEnv();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the Colorway Closet does not appear when there is no active
|
||||
* collection, and that retained themes are still visible.
|
||||
*/
|
||||
add_task(async function testColorwayNoActiveCollection() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.theme.colorway-closet", true]],
|
||||
});
|
||||
|
||||
// Mock BuiltInThemeConfig.findActiveColorwaysCollection with test colorways.
|
||||
const originalFindActiveCollection =
|
||||
BuiltInThemeConfig.findActiveColorwayCollection;
|
||||
registerCleanupFunction(() => {
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
||||
setBuiltInThemeConfigMock();
|
||||
|
||||
// Set expired theme as a retained colorway theme
|
||||
const retainedThemePrefName = "browser.theme.retainedExpiredThemes";
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [[retainedThemePrefName, JSON.stringify([kTestExpiredThemeId])]],
|
||||
});
|
||||
const themeXpiExpiredAddon = getMockThemeXpi(kTestExpiredThemeId);
|
||||
const expiredAddon = (
|
||||
await AddonTestUtils.promiseInstallFile(themeXpiExpiredAddon)
|
||||
).addon;
|
||||
|
||||
await expiredAddon.disable();
|
||||
|
||||
// Make the test theme appear expired.
|
||||
setMockThemeToExpired(kTestExpiredThemeId);
|
||||
registerCleanupFunction(() => {
|
||||
BuiltInThemes.builtInThemeMap.delete(kTestExpiredThemeId);
|
||||
});
|
||||
|
||||
let win = await loadInitialView("theme");
|
||||
let doc = win.document;
|
||||
let colorwaySection = getSection(doc, "colorways-section");
|
||||
ok(colorwaySection, "colorway section was found");
|
||||
|
||||
ok(
|
||||
!colorwaySection.querySelector("colorways-card"),
|
||||
"colorway closet card was not found"
|
||||
);
|
||||
|
||||
info("Verifying that header and subheader are still visible");
|
||||
is(
|
||||
colorwaySection.children[0].classList[0],
|
||||
"list-section-heading",
|
||||
"colorway section header should be first"
|
||||
);
|
||||
is(
|
||||
colorwaySection.children[1].classList[0],
|
||||
"list-section-subheading",
|
||||
"colorway section subheader should be second"
|
||||
);
|
||||
|
||||
let expiredAddonCard = colorwaySection.querySelector(
|
||||
`addon-card[addon-id='${kTestExpiredThemeId}']`
|
||||
);
|
||||
ok(
|
||||
colorwaySection.contains(expiredAddonCard),
|
||||
"Colorways section contains the expired theme."
|
||||
);
|
||||
|
||||
await closeView(win);
|
||||
await expiredAddon.uninstall(true);
|
||||
await SpecialPowers.popPrefEnv();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче