fune/toolkit/components/normandy/test/browser/browser_about_studies.js

198 lines
6.2 KiB
JavaScript

"use strict";
ChromeUtils.import("resource://normandy/lib/AddonStudies.jsm", this);
ChromeUtils.import("resource://normandy/lib/RecipeRunner.jsm", this);
ChromeUtils.import("resource://normandy-content/AboutPages.jsm", this);
function withAboutStudies(testFunc) {
return async (...args) => (
BrowserTestUtils.withNewTab("about:studies", async browser => (
testFunc(...args, browser)
))
);
}
decorate_task(
withAboutStudies,
async function testAboutStudiesWorks(browser) {
ok(browser.contentDocumentAsCPOW.getElementById("app"), "App element was found");
}
);
decorate_task(
withPrefEnv({
set: [["app.normandy.shieldLearnMoreUrl", "http://test/%OS%/"]],
}),
withAboutStudies,
async function testLearnMore(browser) {
ContentTask.spawn(browser, null, () => {
content.document.getElementById("shield-studies-learn-more").click();
});
await BrowserTestUtils.waitForLocationChange(gBrowser);
const location = browser.currentURI.spec;
is(
location,
AboutPages.aboutStudies.getShieldLearnMoreHref(),
"Clicking Learn More opens the correct page on SUMO.",
);
ok(!location.includes("%OS%"), "The Learn More URL is formatted.");
}
);
decorate_task(
withAboutStudies,
async function testUpdatePreferencesNewOrganization(browser) {
let loadPromise = BrowserTestUtils.firstBrowserLoaded(window);
// We have to use gBrowser instead of browser in most spots since we're
// dealing with a new tab outside of the about:studies tab.
const tab = await BrowserTestUtils.switchTab(gBrowser, () => {
ContentTask.spawn(browser, null, () => {
content.document.getElementById("shield-studies-update-preferences").click();
});
});
await loadPromise;
const location = gBrowser.currentURI.spec;
is(
location,
"about:preferences#privacy",
"Clicking Update Preferences opens the privacy section of the new about:preferences.",
);
BrowserTestUtils.removeTab(tab);
}
);
decorate_task(
AddonStudies.withStudies([
// Sort order should be study3, study1, study2 (order by enabled, then most recent).
studyFactory({
name: "A Fake Study",
active: true,
description: "A fake description",
studyStartDate: new Date(2017),
}),
studyFactory({
name: "B Fake Study",
active: false,
description: "A fake description",
studyStartDate: new Date(2019),
}),
studyFactory({
name: "C Fake Study",
active: true,
description: "A fake description",
studyStartDate: new Date(2018),
}),
]),
withAboutStudies,
async function testStudyListing([study1, study2, study3], browser) {
await ContentTask.spawn(browser, [study1, study2, study3], async ([cStudy1, cStudy2, cStudy3]) => {
const doc = content.document;
function getStudyRow(docElem, studyName) {
return docElem.querySelector(`.study[data-study-name="${studyName}"]`);
}
await ContentTaskUtils.waitForCondition(() => doc.querySelectorAll(".study-list .study").length);
const studyRows = doc.querySelectorAll(".study-list .study");
const names = Array.from(studyRows).map(row => row.querySelector(".study-name").textContent);
Assert.deepEqual(
names,
[cStudy3.name, cStudy1.name, cStudy2.name],
"Studies are sorted first by enabled status, and then by descending start date."
);
const study1Row = getStudyRow(doc, cStudy1.name);
ok(
study1Row.querySelector(".study-description").textContent.includes(cStudy1.description),
"Study descriptions are shown in about:studies."
);
is(
study1Row.querySelector(".study-status").textContent,
"Active",
"Active studies show an 'Active' indicator."
);
ok(
study1Row.querySelector(".remove-button"),
"Active studies show a remove button"
);
is(
study1Row.querySelector(".study-icon").textContent.toLowerCase(),
"a",
"Study icons use the first letter of the study name."
);
const study2Row = getStudyRow(doc, cStudy2.name);
is(
study2Row.querySelector(".study-status").textContent,
"Complete",
"Inactive studies are marked as complete."
);
ok(
!study2Row.querySelector(".remove-button"),
"Inactive studies do not show a remove button"
);
study1Row.querySelector(".remove-button").click();
await ContentTaskUtils.waitForCondition(() => (
getStudyRow(doc, cStudy1.name).matches(".disabled")
));
ok(
getStudyRow(doc, cStudy1.name).matches(".disabled"),
"Clicking the remove button updates the UI to show that the study has been disabled."
);
});
const updatedStudy1 = await AddonStudies.get(study1.recipeId);
ok(
!updatedStudy1.active,
"Clicking the remove button marks the study as inactive in storage."
);
}
);
decorate_task(
AddonStudies.withStudies([]),
withAboutStudies,
async function testStudyListing(studies, browser) {
await ContentTask.spawn(browser, null, async () => {
const doc = content.document;
await ContentTaskUtils.waitForCondition(() => doc.querySelectorAll(".study-list").length);
const studyRows = doc.querySelectorAll(".study-list .study");
is(studyRows.length, 0, "There should be no studies");
is(
doc.querySelector(".study-list-info").textContent,
"You have not participated in any studies.",
"A message is shown when no studies exist",
);
});
}
);
decorate_task(
withAboutStudies,
async function testStudyListing(browser) {
try {
RecipeRunner.disable();
await ContentTask.spawn(browser, null, async () => {
const doc = content.document;
await ContentTaskUtils.waitForCondition(() => !!doc.querySelector(".info-box-content > span"));
is(
doc.querySelector(".info-box-content > span").textContent,
"This is a list of studies that you have participated in. No new studies will run.",
"A message is shown when studies are disabled",
);
});
} finally {
// reset RecipeRunner.enabled
RecipeRunner.checkPrefs();
}
}
);