зеркало из 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;
|
font-weight: bolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
#colorways-section-heading {
|
.colorways-section > .list-section-heading {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,11 +210,6 @@
|
||||||
<button id="colorways-button" class="primary" action="open-colorways" data-l10n-id="theme-colorways-button"></button>
|
<button id="colorways-button" class="primary" action="open-colorways" data-l10n-id="theme-colorways-button"></button>
|
||||||
</template>
|
</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">
|
<template name="addon-name-container-in-disco-card">
|
||||||
<div class="disco-card-head">
|
<div class="disco-card-head">
|
||||||
<h3 class="disco-addon-name"></h3>
|
<h3 class="disco-addon-name"></h3>
|
||||||
|
|
|
@ -3693,6 +3693,12 @@ class AddonCard extends HTMLElement {
|
||||||
customElements.define("addon-card", AddonCard);
|
customElements.define("addon-card", AddonCard);
|
||||||
|
|
||||||
class ColorwayClosetCard extends HTMLElement {
|
class ColorwayClosetCard extends HTMLElement {
|
||||||
|
connectedCallback() {
|
||||||
|
if (this.childElementCount === 0) {
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let card = importTemplate("card").firstElementChild;
|
let card = importTemplate("card").firstElementChild;
|
||||||
let heading = card.querySelector(".addon-name-container");
|
let heading = card.querySelector(".addon-name-container");
|
||||||
|
@ -4144,7 +4150,11 @@ class AddonList extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
createSectionHeading(headingIndex) {
|
createSectionHeading(headingIndex) {
|
||||||
let { headingId, subheadingId } = this.sections[headingIndex];
|
let {
|
||||||
|
headingId,
|
||||||
|
subheadingId,
|
||||||
|
sectionPreambleCustomElement,
|
||||||
|
} = this.sections[headingIndex];
|
||||||
let frag = document.createDocumentFragment();
|
let frag = document.createDocumentFragment();
|
||||||
let heading = document.createElement("h2");
|
let heading = document.createElement("h2");
|
||||||
heading.classList.add("list-section-heading");
|
heading.classList.add("list-section-heading");
|
||||||
|
@ -4154,11 +4164,19 @@ class AddonList extends HTMLElement {
|
||||||
if (subheadingId) {
|
if (subheadingId) {
|
||||||
let subheading = document.createElement("h3");
|
let subheading = document.createElement("h3");
|
||||||
subheading.classList.add("list-section-subheading");
|
subheading.classList.add("list-section-subheading");
|
||||||
heading.className = "header-name";
|
|
||||||
document.l10n.setAttributes(subheading, subheadingId);
|
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);
|
frag.append(subheading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sectionPreambleCustomElement) {
|
||||||
|
frag.append(document.createElement(sectionPreambleCustomElement));
|
||||||
|
}
|
||||||
|
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4190,9 +4208,12 @@ class AddonList extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSectionIfEmpty(section) {
|
updateSectionIfEmpty(section) {
|
||||||
// The header is added before any add-on cards, so if there's only one
|
// We should empty out the section if there are no more cards to display,
|
||||||
// child then it's the header. In that case we should empty out the section.
|
// (unless the section is configured to stay visible and rendered even when
|
||||||
if (section.children.length == 1) {
|
// 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 = "";
|
section.textContent = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4201,8 +4222,12 @@ class AddonList extends HTMLElement {
|
||||||
let section = this.getSection(sectionIndex);
|
let section = this.getSection(sectionIndex);
|
||||||
let sectionCards = this.getCards(section);
|
let sectionCards = this.getCards(section);
|
||||||
|
|
||||||
// If this is the first card in the section, create the heading.
|
const { shouldRenderIfEmpty } = this.sections[sectionIndex];
|
||||||
if (!sectionCards.length) {
|
|
||||||
|
// 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));
|
section.appendChild(this.createSectionHeading(sectionIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4392,7 +4417,7 @@ class AddonList extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSection(addons, index) {
|
renderSection(addons, index) {
|
||||||
const { sectionClass, sectionPreambleCustomElement } = this.sections[index];
|
const { sectionClass, shouldRenderIfEmpty } = this.sections[index];
|
||||||
|
|
||||||
let section = document.createElement("section");
|
let section = document.createElement("section");
|
||||||
section.setAttribute("section", index);
|
section.setAttribute("section", index);
|
||||||
|
@ -4401,20 +4426,15 @@ class AddonList extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the heading and add-ons if there are any.
|
// Render the heading and add-ons if there are any.
|
||||||
if (addons.length) {
|
if (shouldRenderIfEmpty || addons.length) {
|
||||||
if (sectionPreambleCustomElement) {
|
|
||||||
section.appendChild(
|
|
||||||
document.createElement(sectionPreambleCustomElement)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
section.appendChild(this.createSectionHeading(index));
|
section.appendChild(this.createSectionHeading(index));
|
||||||
|
}
|
||||||
|
|
||||||
for (let addon of addons) {
|
for (let addon of addons) {
|
||||||
let card = document.createElement("addon-card");
|
let card = document.createElement("addon-card");
|
||||||
card.setAddon(addon);
|
card.setAddon(addon);
|
||||||
card.render();
|
card.render();
|
||||||
section.appendChild(card);
|
section.appendChild(card);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return section;
|
return section;
|
||||||
|
@ -4517,22 +4537,6 @@ class AddonList extends HTMLElement {
|
||||||
}
|
}
|
||||||
customElements.define("addon-list", AddonList);
|
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 {
|
class RecommendedAddonList extends HTMLElement {
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
if (this.isConnected) {
|
if (this.isConnected) {
|
||||||
|
@ -4828,15 +4832,12 @@ gViewController.defineView("list", async type => {
|
||||||
return null;
|
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 () =>
|
const areColorwayThemesInstalled = async () =>
|
||||||
(await AddonManager.getAllAddons()).some(
|
(await AddonManager.getAllAddons()).some(
|
||||||
addon =>
|
addon =>
|
||||||
BuiltInThemes.isMonochromaticTheme(addon.id) &&
|
BuiltInThemes.isMonochromaticTheme(addon.id) &&
|
||||||
!BuiltInThemes.themeIsExpired(addon.id)
|
!BuiltInThemes.themeIsExpired(addon.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
let frag = document.createDocumentFragment();
|
let frag = document.createDocumentFragment();
|
||||||
let list = document.createElement("addon-list");
|
let list = document.createElement("addon-list");
|
||||||
list.type = type;
|
list.type = type;
|
||||||
|
@ -4848,43 +4849,68 @@ gViewController.defineView("list", async type => {
|
||||||
filterFn: addon =>
|
filterFn: addon =>
|
||||||
!addon.hidden && addon.isActive && !isPending(addon, "uninstall"),
|
!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 =>
|
filterFn: addon =>
|
||||||
!addon.hidden &&
|
!addon.hidden &&
|
||||||
!addon.isActive &&
|
!addon.isActive &&
|
||||||
!isPending(addon, "uninstall") &&
|
!isPending(addon, "uninstall") &&
|
||||||
// For performance related details about this check see the
|
// For performance related details about this check see the
|
||||||
// documentation for themeIsExpired in BuiltInThemeConfig.jsm.
|
// documentation for themeIsExpired in BuiltInThemeConfig.jsm.
|
||||||
(!BuiltInThemes.isMonochromaticTheme(addon.id) ||
|
BuiltInThemes.isMonochromaticTheme(addon.id) &&
|
||||||
BuiltInThemes.isRetainedExpiredTheme(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";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
list.setSections(sections);
|
||||||
frag.appendChild(list);
|
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");
|
let monochromaticList = document.createElement("addon-list");
|
||||||
monochromaticList.classList.add("monochromatic-addon-list");
|
monochromaticList.classList.add("monochromatic-addon-list");
|
||||||
monochromaticList.type = type;
|
monochromaticList.type = type;
|
||||||
|
|
|
@ -11,10 +11,14 @@ const { BuiltInThemeConfig } = ChromeUtils.import(
|
||||||
const { ColorwayClosetOpener } = ChromeUtils.import(
|
const { ColorwayClosetOpener } = ChromeUtils.import(
|
||||||
"resource:///modules/ColorwayClosetOpener.jsm"
|
"resource:///modules/ColorwayClosetOpener.jsm"
|
||||||
);
|
);
|
||||||
|
const { BuiltInThemes } = ChromeUtils.import(
|
||||||
|
"resource:///modules/BuiltInThemes.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
AddonTestUtils.initMochitest(this);
|
AddonTestUtils.initMochitest(this);
|
||||||
|
|
||||||
const kTestThemeId = "test-colorway@mozilla.org";
|
const kTestThemeId = "test-colorway@mozilla.org";
|
||||||
|
const kTestExpiredThemeId = `expired-${kTestThemeId}`;
|
||||||
|
|
||||||
// Return a mock expiry date set 1 year ahead from the current date.
|
// Return a mock expiry date set 1 year ahead from the current date.
|
||||||
function getMockExpiry() {
|
function getMockExpiry() {
|
||||||
|
@ -23,6 +27,66 @@ function getMockExpiry() {
|
||||||
return expireDate;
|
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() {
|
add_setup(async function() {
|
||||||
info("Register mock fluent locale strings");
|
info("Register mock fluent locale strings");
|
||||||
|
|
||||||
|
@ -89,15 +153,9 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
||||||
// Mock BuiltInThemeConfig.findActiveColorwaysCollection with test colorways.
|
// Mock BuiltInThemeConfig.findActiveColorwaysCollection with test colorways.
|
||||||
const originalFindActiveCollection =
|
const originalFindActiveCollection =
|
||||||
BuiltInThemeConfig.findActiveColorwayCollection;
|
BuiltInThemeConfig.findActiveColorwayCollection;
|
||||||
const clearBuiltInThemeConfigMock = () => {
|
registerCleanupFunction(() => {
|
||||||
if (
|
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||||
BuiltInThemeConfig.findActiveColorwayCollection !==
|
});
|
||||||
originalFindActiveCollection
|
|
||||||
) {
|
|
||||||
BuiltInThemeConfig.findActiveColorwayCollection = originalFindActiveCollection;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
registerCleanupFunction(clearBuiltInThemeConfigMock);
|
|
||||||
|
|
||||||
// Mock collection l10n part of the mocked fluent resources.
|
// Mock collection l10n part of the mocked fluent resources.
|
||||||
const mockL10nId = "colorway-collection-test-mock";
|
const mockL10nId = "colorway-collection-test-mock";
|
||||||
|
@ -118,27 +176,9 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
info("Now mocking BuiltInThemeConfig.findActiveColorwayCollection");
|
setBuiltInThemeConfigMock({ mockExpiry, mockL10nId });
|
||||||
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 },
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const themeXpi = AddonTestUtils.createTempWebExtensionFile({
|
const themeXpi = getMockThemeXpi(kTestThemeId);
|
||||||
manifest: {
|
|
||||||
name: "Monochromatic Theme",
|
|
||||||
applications: { gecko: { id: kTestThemeId } },
|
|
||||||
theme: {},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
||||||
|
|
||||||
let win = await loadInitialView("theme");
|
let win = await loadInitialView("theme");
|
||||||
|
@ -151,28 +191,27 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
||||||
// Add mocked fluent resources for the mocked active colorway collection.
|
// Add mocked fluent resources for the mocked active colorway collection.
|
||||||
doc.l10n.addResourceIds(["mock-colorwaycloset.ftl"]);
|
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
|
// Make sure fluent strings have all been translated before
|
||||||
// asserting the expected element to not have empty textContent.
|
// 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");
|
info("Verifying colorway closet list contents");
|
||||||
ok(colorwayClosetList, "colorway closet list was found");
|
|
||||||
ok(
|
ok(
|
||||||
colorwayClosetList.querySelector("#colorways-section-heading"),
|
colorwaySection.querySelector(".list-section-heading"),
|
||||||
"colorway closet heading was found"
|
"colorway closet heading was found"
|
||||||
);
|
);
|
||||||
ok(
|
ok(
|
||||||
colorwayClosetList.querySelector("#colorways-section-subheading"),
|
colorwaySection.querySelector(".list-section-subheading"),
|
||||||
"colorway closet subheading was found"
|
"colorway closet subheading was found"
|
||||||
);
|
);
|
||||||
|
|
||||||
let cards = colorwayClosetList.querySelectorAll("colorways-card");
|
let card = colorwaySection.querySelector("colorways-card");
|
||||||
ok(cards.length, "At least one colorway closet card was found");
|
ok(card, "colorway closet card was found");
|
||||||
|
|
||||||
info("Verifying colorway closet card contents");
|
info("Verifying colorway closet card contents");
|
||||||
let card = cards[0];
|
|
||||||
ok(
|
ok(
|
||||||
card.querySelector("#colorways-preview-text-container"),
|
card.querySelector("#colorways-preview-text-container"),
|
||||||
"Preview text container found"
|
"Preview text container found"
|
||||||
|
@ -210,7 +249,8 @@ add_task(async function testColorwayClosetPrefEnabled() {
|
||||||
|
|
||||||
await closeView(win);
|
await closeView(win);
|
||||||
await addon.uninstall(true);
|
await addon.uninstall(true);
|
||||||
clearBuiltInThemeConfigMock();
|
await SpecialPowers.popPrefEnv();
|
||||||
|
clearBuiltInThemeConfigMock(originalFindActiveCollection);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,23 +261,17 @@ add_task(async function testColorwayClosetSectionPrefDisabled() {
|
||||||
await SpecialPowers.pushPrefEnv({
|
await SpecialPowers.pushPrefEnv({
|
||||||
set: [["browser.theme.colorway-closet", false]],
|
set: [["browser.theme.colorway-closet", false]],
|
||||||
});
|
});
|
||||||
const themeXpi = AddonTestUtils.createTempWebExtensionFile({
|
const themeXpi = getMockThemeXpi(kTestThemeId);
|
||||||
manifest: {
|
|
||||||
name: "Monochromatic Theme",
|
|
||||||
applications: { gecko: { id: kTestThemeId } },
|
|
||||||
theme: {},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
||||||
|
|
||||||
let win = await loadInitialView("theme");
|
let win = await loadInitialView("theme");
|
||||||
let doc = win.document;
|
let doc = win.document;
|
||||||
let colorwayClosetList = doc.querySelector("colorways-list");
|
let colorwaySection = getSection(doc, "colorways-section");
|
||||||
|
ok(!colorwaySection, "colorway section should not be found");
|
||||||
ok(!colorwayClosetList, "colorway closet list should not be found");
|
|
||||||
|
|
||||||
await closeView(win);
|
await closeView(win);
|
||||||
await addon.uninstall(true);
|
await addon.uninstall(true);
|
||||||
|
await SpecialPowers.popPrefEnv();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -249,6 +283,20 @@ add_task(async function testButtonOpenModal() {
|
||||||
set: [["browser.theme.colorway-closet", true]],
|
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;
|
let originalOpenModal = ColorwayClosetOpener.openModal;
|
||||||
const clearOpenModalMock = () => {
|
const clearOpenModalMock = () => {
|
||||||
if (originalOpenModal) {
|
if (originalOpenModal) {
|
||||||
|
@ -258,25 +306,19 @@ add_task(async function testButtonOpenModal() {
|
||||||
};
|
};
|
||||||
registerCleanupFunction(clearOpenModalMock);
|
registerCleanupFunction(clearOpenModalMock);
|
||||||
|
|
||||||
const themeXpi = AddonTestUtils.createTempWebExtensionFile({
|
const themeXpi = getMockThemeXpi(kTestThemeId);
|
||||||
manifest: {
|
|
||||||
name: "Monochromatic Theme",
|
|
||||||
applications: { gecko: { id: kTestThemeId } },
|
|
||||||
theme: {},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
const { addon } = await AddonTestUtils.promiseInstallFile(themeXpi);
|
||||||
|
|
||||||
let win = await loadInitialView("theme");
|
let win = await loadInitialView("theme");
|
||||||
let doc = win.document;
|
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");
|
let card = colorwaySection.querySelector("colorways-card");
|
||||||
ok(cards.length, "At least one colorway closet card was found");
|
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");
|
ok(colorwaysButton, "colorway collection button found");
|
||||||
let colorwayOpenerPromise = new Promise(resolve => {
|
let colorwayOpenerPromise = new Promise(resolve => {
|
||||||
ColorwayClosetOpener.openModal = () => {
|
ColorwayClosetOpener.openModal = () => {
|
||||||
|
@ -291,4 +333,191 @@ add_task(async function testButtonOpenModal() {
|
||||||
await closeView(win);
|
await closeView(win);
|
||||||
await addon.uninstall(true);
|
await addon.uninstall(true);
|
||||||
clearOpenModalMock();
|
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);
|
||||||
});
|
});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче