summaryrefslogtreecommitdiffstats
path: root/browser/components/aboutwelcome/tests
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/aboutwelcome/tests')
-rw-r--r--browser/components/aboutwelcome/tests/browser/browser.toml5
-rw-r--r--browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_attribution.js2
-rw-r--r--browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_configurable_ui.js104
-rw-r--r--browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_experimentAPI.js208
-rw-r--r--browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_transitions.js219
-rw-r--r--browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_observer.js5
-rw-r--r--browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_toolbar_button.js64
-rw-r--r--browser/components/aboutwelcome/tests/unit/MultiStageAWProton.test.jsx103
-rw-r--r--browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeAttribution.js69
-rw-r--r--browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry.js90
-rw-r--r--browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry_glean.js238
-rw-r--r--browser/components/aboutwelcome/tests/xpcshell/xpcshell.toml9
12 files changed, 866 insertions, 250 deletions
diff --git a/browser/components/aboutwelcome/tests/browser/browser.toml b/browser/components/aboutwelcome/tests/browser/browser.toml
index 22d95272e8..96d1070645 100644
--- a/browser/components/aboutwelcome/tests/browser/browser.toml
+++ b/browser/components/aboutwelcome/tests/browser/browser.toml
@@ -37,6 +37,9 @@ skip-if = ["os == 'linux' && bits == 64"] # Bug 1757875
["browser_aboutwelcome_multistage_mr.js"]
skip-if = ["os == 'linux' && bits == 64 && debug"] # Bug 1812050
+["browser_aboutwelcome_multistage_transitions.js"]
+skip-if = ["debug"] # Bug 1875203
+
["browser_aboutwelcome_multistage_video.js"]
["browser_aboutwelcome_observer.js"]
@@ -50,6 +53,8 @@ skip-if = [
["browser_aboutwelcome_screen_targeting.js"]
+["browser_aboutwelcome_toolbar_button.js"]
+
["browser_aboutwelcome_upgrade_multistage_mr.js"]
skip-if = [
"win11_2009 && debug",
diff --git a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_attribution.js b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_attribution.js
index f0727c9b6f..d7076bd7c5 100644
--- a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_attribution.js
+++ b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_attribution.js
@@ -42,7 +42,6 @@ const TEST_PROTON_CONTENT = [
navigate: true,
},
},
- has_noodles: true,
},
},
{
@@ -58,7 +57,6 @@ const TEST_PROTON_CONTENT = [
data: {},
},
},
- has_noodles: true,
},
},
];
diff --git a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_configurable_ui.js b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_configurable_ui.js
index d53b5acc14..3081688a0c 100644
--- a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_configurable_ui.js
+++ b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_configurable_ui.js
@@ -334,46 +334,46 @@ add_task(async function test_aboutwelcome_dismiss_button() {
/**
* Test rendering a screen with the "split" position
*/
-add_task(async function test_aboutwelcome_split_position() {
- const TEST_SPLIT_STEP = makeTestContent("TEST_SPLIT_STEP", {
- position: "split",
- hero_text: "hero test",
- });
-
- const TEST_SPLIT_JSON = JSON.stringify([TEST_SPLIT_STEP]);
- let browser = await openAboutWelcome(TEST_SPLIT_JSON);
-
- await test_screen_content(
- browser,
- "renders screen secondary section containing hero text",
- // Expected selectors:
- [`main.screen[pos="split"]`, `.section-secondary`, `.message-text h1`]
- );
-
- // Ensure secondary section has split template styling
- await test_element_styles(
- browser,
- "main.screen .section-secondary",
- // Expected styles:
- {
- display: "flex",
- margin: "auto 0px auto auto",
- }
- );
-
- // Ensure secondary action has button styling
- await test_element_styles(
- browser,
- ".action-buttons .secondary-cta .secondary",
- // Expected styles:
- {
- // Override default text-link styles
- "background-color": "color(srgb 0.0823529 0.0784314 0.101961 / 0.07)",
- color: "rgb(21, 20, 26)",
- }
- );
- browser.closeBrowser();
-});
+// add_task(async function test_aboutwelcome_split_position() {
+// const TEST_SPLIT_STEP = makeTestContent("TEST_SPLIT_STEP", {
+// position: "split",
+// hero_text: "hero test",
+// });
+
+// const TEST_SPLIT_JSON = JSON.stringify([TEST_SPLIT_STEP]);
+// let browser = await openAboutWelcome(TEST_SPLIT_JSON);
+
+// await test_screen_content(
+// browser,
+// "renders screen secondary section containing hero text",
+// // Expected selectors:
+// [`main.screen[pos="split"]`, `.section-secondary`, `.message-text h1`]
+// );
+
+// // Ensure secondary section has split template styling
+// await test_element_styles(
+// browser,
+// "main.screen .section-secondary",
+// // Expected styles:
+// {
+// display: "flex",
+// margin: "auto 0px auto auto",
+// }
+// );
+
+// // Ensure secondary action has button styling
+// await test_element_styles(
+// browser,
+// ".action-buttons .secondary-cta .secondary",
+// // Expected styles:
+// {
+// // Override default text-link styles
+// "background-color": "color(srgb 0.0823529 0.0784314 0.101961 / 0.07)",
+// color: "rgb(21, 20, 26)",
+// }
+// );
+// browser.closeBrowser();
+// });
/**
* Test rendering a screen with a URL value and default color for backdrop
@@ -722,3 +722,27 @@ add_task(async function test_aboutwelcome_start_screen_configured() {
browser.closeBrowser();
sandbox.restore();
});
+
+/**
+ * Test rendering a screen with that doesn't use responsive design
+ */
+add_task(async function test_aboutwelcome_rdm_property() {
+ let screens = [makeTestContent(`TEST_NO_RDM`, { no_rdm: true })];
+
+ let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
+ featureId: "aboutwelcome",
+ value: { enabled: true, screens },
+ });
+
+ let browser = await openAboutWelcome();
+
+ await test_screen_content(
+ browser,
+ "render screen with 'no-rdm' attribute",
+ // Expected selectors:
+ ["main.TEST_NO_RDM[no-rdm]"]
+ );
+
+ await doExperimentCleanup();
+ browser.closeBrowser();
+});
diff --git a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_experimentAPI.js b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_experimentAPI.js
index 960d42a1f8..1e29e230ab 100644
--- a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_experimentAPI.js
+++ b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_experimentAPI.js
@@ -10,101 +10,6 @@ const { TelemetryTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/TelemetryTestUtils.sys.mjs"
);
-const TEST_PROTON_CONTENT = [
- {
- id: "AW_STEP1",
- content: {
- title: "Step 1",
- primary_button: {
- label: "Next",
- action: {
- navigate: true,
- },
- },
- secondary_button: {
- label: "link",
- },
- secondary_button_top: {
- label: "link top",
- action: {
- type: "SHOW_FIREFOX_ACCOUNTS",
- data: { entrypoint: "test" },
- },
- },
- has_noodles: true,
- },
- },
- {
- id: "AW_STEP2",
- content: {
- title: "Step 2",
- primary_button: {
- label: "Next",
- action: {
- navigate: true,
- },
- },
- secondary_button: {
- label: "link",
- },
- has_noodles: true,
- },
- },
- {
- id: "AW_STEP3",
- content: {
- title: "Step 3",
- tiles: {
- type: "theme",
- action: {
- theme: "<event>",
- },
- data: [
- {
- theme: "automatic",
- label: "theme-1",
- tooltip: "test-tooltip",
- },
- {
- theme: "dark",
- label: "theme-2",
- },
- ],
- },
- primary_button: {
- label: "Next",
- action: {
- navigate: true,
- },
- },
- secondary_button: {
- label: "Import",
- action: {
- type: "SHOW_MIGRATION_WIZARD",
- data: { source: "chrome" },
- },
- },
- has_noodles: true,
- },
- },
- {
- id: "AW_STEP4",
- content: {
- title: "Step 4",
- primary_button: {
- label: "Next",
- action: {
- navigate: true,
- },
- },
- secondary_button: {
- label: "link",
- },
- has_noodles: true,
- },
- },
-];
-
/**
* Test the zero onboarding using ExperimentAPI
*/
@@ -354,119 +259,6 @@ add_task(async function test_multistage_aboutwelcome_experimentAPI() {
await doExperimentCleanup();
});
-/**
- * Test the multistage proton welcome UI using ExperimentAPI with transitions
- */
-add_task(async function test_multistage_aboutwelcome_transitions() {
- const sandbox = sinon.createSandbox();
- await setAboutWelcomePref(true);
- await ExperimentAPI.ready();
-
- let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
- featureId: "aboutwelcome",
- value: {
- id: "my-mochitest-experiment",
- enabled: true,
- screens: TEST_PROTON_CONTENT,
- transitions: true,
- },
- });
-
- let tab = await BrowserTestUtils.openNewForegroundTab(
- gBrowser,
- "about:welcome",
- true
- );
-
- const browser = tab.linkedBrowser;
-
- let aboutWelcomeActor = await getAboutWelcomeParent(browser);
- // Stub AboutWelcomeParent Content Message Handler
- sandbox.spy(aboutWelcomeActor, "onContentMessage");
- registerCleanupFunction(() => {
- BrowserTestUtils.removeTab(tab);
- sandbox.restore();
- });
-
- await test_screen_content(
- browser,
- "multistage proton step 1",
- // Expected selectors:
- ["div.proton.transition- .screen"],
- // Unexpected selectors:
- ["div.proton.transition-out"]
- );
-
- // Double click should still only transition once.
- await onButtonClick(browser, "button.primary");
- await onButtonClick(browser, "button.primary");
-
- await test_screen_content(
- browser,
- "multistage proton step 1 transition to 2",
- // Expected selectors:
- ["div.proton.transition-out .screen", "div.proton.transition- .screen-1"]
- );
-
- await doExperimentCleanup();
-});
-
-/**
- * Test the multistage proton welcome UI using ExperimentAPI without transitions
- */
-add_task(async function test_multistage_aboutwelcome_transitions_off() {
- const sandbox = sinon.createSandbox();
- await setAboutWelcomePref(true);
- await ExperimentAPI.ready();
-
- let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
- featureId: "aboutwelcome",
- value: {
- id: "my-mochitest-experiment",
- enabled: true,
- screens: TEST_PROTON_CONTENT,
- transitions: false,
- },
- });
-
- let tab = await BrowserTestUtils.openNewForegroundTab(
- gBrowser,
- "about:welcome",
- true
- );
-
- const browser = tab.linkedBrowser;
-
- let aboutWelcomeActor = await getAboutWelcomeParent(browser);
- // Stub AboutWelcomeParent Content Message Handler
- sandbox.spy(aboutWelcomeActor, "onContentMessage");
- registerCleanupFunction(() => {
- BrowserTestUtils.removeTab(tab);
- sandbox.restore();
- });
-
- await test_screen_content(
- browser,
- "multistage proton step 1",
- // Expected selectors:
- ["div.proton.transition- .screen"],
- // Unexpected selectors:
- ["div.proton.transition-out"]
- );
-
- await onButtonClick(browser, "button.primary");
- await test_screen_content(
- browser,
- "multistage proton step 1 no transition to 2",
- // Expected selectors:
- [],
- // Unexpected selectors:
- ["div.proton.transition-out .screen-0"]
- );
-
- await doExperimentCleanup();
-});
-
/* Test multistage custom backdrop
*/
add_task(async function test_multistage_aboutwelcome_backdrop() {
diff --git a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_transitions.js b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_transitions.js
new file mode 100644
index 0000000000..d27674ef6c
--- /dev/null
+++ b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_multistage_transitions.js
@@ -0,0 +1,219 @@
+"use strict";
+
+const { ExperimentAPI } = ChromeUtils.importESModule(
+ "resource://nimbus/ExperimentAPI.sys.mjs"
+);
+const { ExperimentFakes } = ChromeUtils.importESModule(
+ "resource://testing-common/NimbusTestUtils.sys.mjs"
+);
+const { TelemetryTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TelemetryTestUtils.sys.mjs"
+);
+
+const TEST_PROTON_CONTENT = [
+ {
+ id: "AW_STEP1",
+ content: {
+ title: "Step 1",
+ primary_button: {
+ label: "Next",
+ action: {
+ navigate: true,
+ },
+ },
+ secondary_button: {
+ label: "link",
+ },
+ secondary_button_top: {
+ label: "link top",
+ action: {
+ type: "SHOW_FIREFOX_ACCOUNTS",
+ data: { entrypoint: "test" },
+ },
+ },
+ has_noodles: true,
+ },
+ },
+ {
+ id: "AW_STEP2",
+ content: {
+ title: "Step 2",
+ primary_button: {
+ label: "Next",
+ action: {
+ navigate: true,
+ },
+ },
+ secondary_button: {
+ label: "link",
+ },
+ has_noodles: true,
+ },
+ },
+ {
+ id: "AW_STEP3",
+ content: {
+ title: "Step 3",
+ tiles: {
+ type: "theme",
+ action: {
+ theme: "<event>",
+ },
+ data: [
+ {
+ theme: "automatic",
+ label: "theme-1",
+ tooltip: "test-tooltip",
+ },
+ {
+ theme: "dark",
+ label: "theme-2",
+ },
+ ],
+ },
+ primary_button: {
+ label: "Next",
+ action: {
+ navigate: true,
+ },
+ },
+ secondary_button: {
+ label: "Import",
+ action: {
+ type: "SHOW_MIGRATION_WIZARD",
+ data: { source: "chrome" },
+ },
+ },
+ has_noodles: true,
+ },
+ },
+ {
+ id: "AW_STEP4",
+ content: {
+ title: "Step 4",
+ primary_button: {
+ label: "Next",
+ action: {
+ navigate: true,
+ },
+ },
+ secondary_button: {
+ label: "link",
+ },
+ has_noodles: true,
+ },
+ },
+];
+
+/**
+ * Test the multistage proton welcome UI using ExperimentAPI with transitions
+ */
+add_task(async function test_multistage_aboutwelcome_transitions() {
+ const sandbox = sinon.createSandbox();
+ await setAboutWelcomePref(true);
+ await ExperimentAPI.ready();
+
+ let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
+ featureId: "aboutwelcome",
+ value: {
+ id: "my-mochitest-experiment",
+ enabled: true,
+ screens: TEST_PROTON_CONTENT,
+ transitions: true,
+ },
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:welcome",
+ true
+ );
+
+ const browser = tab.linkedBrowser;
+
+ let aboutWelcomeActor = await getAboutWelcomeParent(browser);
+ // Stub AboutWelcomeParent Content Message Handler
+ sandbox.spy(aboutWelcomeActor, "onContentMessage");
+ registerCleanupFunction(() => {
+ BrowserTestUtils.removeTab(tab);
+ sandbox.restore();
+ });
+
+ await test_screen_content(
+ browser,
+ "multistage proton step 1",
+ // Expected selectors:
+ ["div.proton.transition- .screen"],
+ // Unexpected selectors:
+ ["div.proton.transition-out"]
+ );
+
+ // Double click should still only transition once.
+ await onButtonClick(browser, "button.primary");
+ await onButtonClick(browser, "button.primary");
+
+ await test_screen_content(
+ browser,
+ "multistage proton step 1 transition to 2",
+ // Expected selectors:
+ ["div.proton.transition-out .screen", "div.proton.transition- .screen-1"]
+ );
+
+ await doExperimentCleanup();
+});
+
+/**
+ * Test the multistage proton welcome UI using ExperimentAPI without transitions
+ */
+add_task(async function test_multistage_aboutwelcome_transitions_off() {
+ const sandbox = sinon.createSandbox();
+ await setAboutWelcomePref(true);
+ await ExperimentAPI.ready();
+
+ let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
+ featureId: "aboutwelcome",
+ value: {
+ id: "my-mochitest-experiment",
+ enabled: true,
+ screens: TEST_PROTON_CONTENT,
+ transitions: false,
+ },
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:welcome",
+ true
+ );
+
+ const browser = tab.linkedBrowser;
+
+ let aboutWelcomeActor = await getAboutWelcomeParent(browser);
+ // Stub AboutWelcomeParent Content Message Handler
+ sandbox.spy(aboutWelcomeActor, "onContentMessage");
+ registerCleanupFunction(() => {
+ BrowserTestUtils.removeTab(tab);
+ sandbox.restore();
+ });
+
+ await test_screen_content(
+ browser,
+ "multistage proton step 1",
+ // Expected selectors:
+ ["div.proton.transition- .screen"],
+ // Unexpected selectors:
+ ["div.proton.transition-out"]
+ );
+
+ await onButtonClick(browser, "button.primary");
+ await test_screen_content(
+ browser,
+ "multistage proton step 1 no transition to 2",
+ // Expected selectors:
+ [],
+ // Unexpected selectors:
+ ["div.proton.transition-out .screen-0"]
+ );
+
+ await doExperimentCleanup();
+});
diff --git a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_observer.js b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_observer.js
index 58f9059532..d1fe0edc4c 100644
--- a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_observer.js
+++ b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_observer.js
@@ -70,4 +70,9 @@ add_task(async function test_About_Welcome_Location_Change() {
aboutWelcomeActor.AboutWelcomeObserver.AWTerminate.ADDRESS_BAR_NAVIGATED,
"Terminated due to location uri changed"
);
+
+ // Wait for the end of the any transition happening due to
+ // location change before closing the window, See bug 1882067
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+ await new Promise(r => setTimeout(r, 100));
});
diff --git a/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_toolbar_button.js b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_toolbar_button.js
new file mode 100644
index 0000000000..c9180ddf2d
--- /dev/null
+++ b/browser/components/aboutwelcome/tests/browser/browser_aboutwelcome_toolbar_button.js
@@ -0,0 +1,64 @@
+"use strict";
+
+const { AboutWelcomeTelemetry } = ChromeUtils.importESModule(
+ "resource:///modules/aboutwelcome/AboutWelcomeTelemetry.sys.mjs"
+);
+const { AWToolbarButton } = ChromeUtils.importESModule(
+ "resource:///modules/aboutwelcome/AWToolbarUtils.sys.mjs"
+);
+
+const TOOLBAR_PREF = "browser.aboutwelcome.toolbarButtonEnabled";
+const DID_SEE_FINAL_SCREEN_PREF = "browser.aboutwelcome.didSeeFinalScreen";
+
+async function openNewTab() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:newtab",
+ false
+ );
+
+ registerCleanupFunction(async () => {
+ BrowserTestUtils.removeTab(tab);
+ await SpecialPowers.popPrefEnv();
+ });
+
+ return tab.linkedBrowser;
+}
+
+add_task(async function test_add_and_remove_toolbar_button() {
+ // Clear the final screen pref, which may have been set by other tests
+ await SpecialPowers.pushPrefEnv({
+ set: [[DID_SEE_FINAL_SCREEN_PREF, false]],
+ });
+ // Open newtab
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+ win.BrowserOpenTab();
+ ok(win, "browser exists");
+ // Try to add the button. It shouldn't add because the pref is false
+ await AWToolbarButton.maybeAddSetupButton();
+ ok(
+ !win.document.getElementById("aboutwelcome-button"),
+ "Button should not exist"
+ );
+ // Set the pref and try again
+ await SpecialPowers.pushPrefEnv({
+ set: [[TOOLBAR_PREF, true]],
+ });
+ await AWToolbarButton.maybeAddSetupButton();
+ // The button should exist
+ ok(
+ win.document.getElementById("aboutwelcome-button"),
+ "Button should be added."
+ );
+ // Switch the pref to false and check again
+ await SpecialPowers.pushPrefEnv({
+ set: [[TOOLBAR_PREF, false]],
+ });
+ ok(
+ !win.document.getElementById("aboutwelcome-button"),
+ "Button should be removed"
+ );
+ // Cleanup
+ await SpecialPowers.popPrefEnv();
+ await BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/aboutwelcome/tests/unit/MultiStageAWProton.test.jsx b/browser/components/aboutwelcome/tests/unit/MultiStageAWProton.test.jsx
index a40af1c4a1..9b452d5c6b 100644
--- a/browser/components/aboutwelcome/tests/unit/MultiStageAWProton.test.jsx
+++ b/browser/components/aboutwelcome/tests/unit/MultiStageAWProton.test.jsx
@@ -385,6 +385,92 @@ describe("MultiStageAboutWelcomeProton module", () => {
assert.equal(textEl.at(0).prop("data-l10n-id"), "test-string-id");
assert.equal(textEl.at(1).prop("data-l10n-id"), "test-string-id-2");
});
+
+ it("should render above_button_content legal copy with MultiSelect tile", async () => {
+ const SCREEN_PROPS = {
+ content: {
+ tiles: {
+ type: "multiselect",
+ label: "Test Subtitle",
+ data: [
+ {
+ id: "checkbox-1",
+ type: "checkbox",
+ defaultValue: false,
+ label: { raw: "Checkbox 1" },
+ },
+ ],
+ },
+ above_button_content: [
+ {
+ type: "text",
+ text: {
+ string_id: "test-string-id",
+ },
+ font_styles: "legal",
+ link_keys: ["privacy_policy", "terms_of_use"],
+ },
+ ],
+ },
+ setScreenMultiSelects: sandbox.stub(),
+ setActiveMultiSelect: sandbox.stub(),
+ };
+
+ const wrapper = mount(<MultiStageProtonScreen {...SCREEN_PROPS} />);
+ assert.ok(wrapper.exists());
+ const legalText = wrapper.find(".legal-paragraph");
+ assert.equal(legalText.exists(), true);
+
+ const multiSelectContainer = wrapper.find(".multi-select-container");
+ assert.equal(multiSelectContainer.exists(), true);
+
+ sandbox.restore();
+ });
+
+ it("should not have no-rdm property when property is not in message content", () => {
+ const SCREEN_PROPS = {
+ content: {
+ title: "test title",
+ layout: "inline",
+ },
+ };
+ const wrapper = mount(<MultiStageProtonScreen {...SCREEN_PROPS} />);
+ assert.ok(wrapper.exists());
+ assert.notExists(wrapper.find("main").prop("no-rdm"));
+ });
+
+ it("should have no-rdm property when property is set in message content", () => {
+ const SCREEN_PROPS = {
+ content: {
+ title: "test title",
+ layout: "inline",
+ no_rdm: true,
+ },
+ };
+ const wrapper = mount(<MultiStageProtonScreen {...SCREEN_PROPS} />);
+ assert.ok(wrapper.exists());
+ assert.exists(wrapper.find("main").prop("no-rdm"));
+ });
+
+ it("should correctly set reverse-split prop", () => {
+ const SCREEN_PROPS = {
+ content: {
+ position: "split",
+ reverse_split: true,
+ title: "test title",
+ primary_button: {
+ label: "test primary button",
+ },
+ additional_button: {
+ label: "test additional button",
+ style: "link",
+ },
+ },
+ };
+ const wrapper = mount(<MultiStageProtonScreen {...SCREEN_PROPS} />);
+ assert.ok(wrapper.exists());
+ assert.equal(wrapper.find("main").prop("reverse-split"), "");
+ });
});
describe("AboutWelcomeDefaults for proton", () => {
@@ -568,4 +654,21 @@ describe("MultiStageAboutWelcomeProton module", () => {
);
});
});
+
+ describe("Embedded Migration Wizard", () => {
+ const SCREEN_PROPS = {
+ content: {
+ title: "test title",
+ tiles: {
+ type: "migration-wizard",
+ },
+ },
+ };
+
+ it("should render migration wizard", async () => {
+ const wrapper = mount(<MultiStageProtonScreen {...SCREEN_PROPS} />);
+ assert.ok(wrapper.exists());
+ assert.isTrue(wrapper.find("migration-wizard").exists());
+ });
+ });
});
diff --git a/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeAttribution.js b/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeAttribution.js
new file mode 100644
index 0000000000..3d83f473d5
--- /dev/null
+++ b/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeAttribution.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+"use strict";
+
+const { AboutWelcomeDefaults } = ChromeUtils.importESModule(
+ "resource:///modules/aboutwelcome/AboutWelcomeDefaults.sys.mjs"
+);
+const { sinon } = ChromeUtils.importESModule(
+ "resource://testing-common/Sinon.sys.mjs"
+);
+const { AttributionCode } = ChromeUtils.importESModule(
+ "resource:///modules/AttributionCode.sys.mjs"
+);
+const { AddonRepository } = ChromeUtils.importESModule(
+ "resource://gre/modules/addons/AddonRepository.sys.mjs"
+);
+
+const TEST_ATTRIBUTION_DATA = {
+ source: "addons.mozilla.org",
+ medium: "referral",
+ campaign: "non-fx-button",
+ content: "rta:iridium%40particlecore.github.io",
+};
+
+add_task(async function test_handleAddonInfoNotFound() {
+ let sandbox = sinon.createSandbox();
+ const stub = sandbox.stub(AttributionCode, "getAttrDataAsync").resolves(null);
+ let result = await AboutWelcomeDefaults.getAttributionContent();
+ equal(stub.callCount, 1, "Call was made");
+ equal(result, null, "No data is returned");
+
+ sandbox.restore();
+});
+
+add_task(async function test_UAAttribution() {
+ let sandbox = sinon.createSandbox();
+ const stub = sandbox
+ .stub(AttributionCode, "getAttrDataAsync")
+ .resolves({ ua: "test" });
+ let result = await AboutWelcomeDefaults.getAttributionContent();
+ equal(stub.callCount, 1, "Call was made");
+ equal(result.template, undefined, "Template was not returned");
+ equal(result.ua, "test", "UA was returned");
+
+ sandbox.restore();
+});
+
+add_task(async function test_formatAttributionData() {
+ let sandbox = sinon.createSandbox();
+ const TEST_ADDON_INFO = {
+ sourceURI: { scheme: "https", spec: "https://test.xpi" },
+ name: "Test Add-on",
+ icons: { 64: "http://test.svg" },
+ };
+ sandbox
+ .stub(AttributionCode, "getAttrDataAsync")
+ .resolves(TEST_ATTRIBUTION_DATA);
+ sandbox.stub(AddonRepository, "getAddonsByIDs").resolves([TEST_ADDON_INFO]);
+ let result = await AboutWelcomeDefaults.getAttributionContent(
+ TEST_ATTRIBUTION_DATA
+ );
+ equal(AddonRepository.getAddonsByIDs.callCount, 1, "Retrieve addon content");
+ equal(result.template, "return_to_amo", "RTAMO template returned");
+ equal(result.name, TEST_ADDON_INFO.name, "AddonInfo returned");
+
+ sandbox.restore();
+});
diff --git a/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry.js b/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry.js
new file mode 100644
index 0000000000..b8339fb39f
--- /dev/null
+++ b/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry.js
@@ -0,0 +1,90 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+"use strict";
+
+const { AboutWelcomeTelemetry } = ChromeUtils.importESModule(
+ "resource:///modules/aboutwelcome/AboutWelcomeTelemetry.sys.mjs"
+);
+const { AttributionCode } = ChromeUtils.importESModule(
+ "resource:///modules/AttributionCode.sys.mjs"
+);
+const { sinon } = ChromeUtils.importESModule(
+ "resource://testing-common/Sinon.sys.mjs"
+);
+const TELEMETRY_PREF = "browser.newtabpage.activity-stream.telemetry";
+
+add_setup(function setup() {
+ do_get_profile();
+ Services.fog.initializeFOG();
+});
+
+add_task(function test_enabled() {
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(TELEMETRY_PREF);
+ });
+ Services.prefs.setBoolPref(TELEMETRY_PREF, true);
+
+ const AWTelemetry = new AboutWelcomeTelemetry();
+
+ equal(AWTelemetry.telemetryEnabled, true, "Telemetry should be on");
+
+ Services.prefs.setBoolPref(TELEMETRY_PREF, false);
+
+ equal(AWTelemetry.telemetryEnabled, false, "Telemetry should be off");
+});
+
+add_task(async function test_pingPayload() {
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(TELEMETRY_PREF);
+ });
+ Services.prefs.setBoolPref(TELEMETRY_PREF, true);
+ const AWTelemetry = new AboutWelcomeTelemetry();
+ sinon.stub(AWTelemetry, "_createPing").resolves({ event: "MOCHITEST" });
+
+ let pingSubmitted = false;
+ GleanPings.messagingSystem.testBeforeNextSubmit(() => {
+ pingSubmitted = true;
+ Assert.equal(Glean.messagingSystem.event.testGetValue(), "MOCHITEST");
+ });
+ await AWTelemetry.sendTelemetry();
+
+ ok(pingSubmitted, "Glean ping was submitted");
+});
+
+add_task(function test_mayAttachAttribution() {
+ const sandbox = sinon.createSandbox();
+ const AWTelemetry = new AboutWelcomeTelemetry();
+
+ sandbox.stub(AttributionCode, "getCachedAttributionData").returns(null);
+
+ let ping = AWTelemetry._maybeAttachAttribution({});
+
+ equal(ping.attribution, undefined, "Should not set attribution if it's null");
+
+ sandbox.restore();
+ sandbox.stub(AttributionCode, "getCachedAttributionData").returns({});
+ ping = AWTelemetry._maybeAttachAttribution({});
+
+ equal(
+ ping.attribution,
+ undefined,
+ "Should not set attribution if it's empty"
+ );
+
+ const attr = {
+ source: "google.com",
+ medium: "referral",
+ campaign: "Firefox-Brand-US-Chrome",
+ content: "(not set)",
+ experiment: "(not set)",
+ variation: "(not set)",
+ ua: "chrome",
+ };
+ sandbox.restore();
+ sandbox.stub(AttributionCode, "getCachedAttributionData").returns(attr);
+ ping = AWTelemetry._maybeAttachAttribution({});
+
+ equal(ping.attribution, attr, "Should set attribution if it presents");
+});
diff --git a/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry_glean.js b/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry_glean.js
new file mode 100644
index 0000000000..5191f05d04
--- /dev/null
+++ b/browser/components/aboutwelcome/tests/xpcshell/test_AboutWelcomeTelemetry_glean.js
@@ -0,0 +1,238 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+"use strict";
+
+const { AboutWelcomeTelemetry } = ChromeUtils.importESModule(
+ "resource:///modules/aboutwelcome/AboutWelcomeTelemetry.sys.mjs"
+);
+const TELEMETRY_PREF = "browser.newtabpage.activity-stream.telemetry";
+
+add_setup(function setup() {
+ do_get_profile();
+ Services.fog.initializeFOG();
+});
+
+// We recognize two kinds of unexpected data that might reach
+// `submitGleanPingForPing`: unknown keys, and keys with unexpectedly-complex
+// data (ie, non-scalar).
+// We report the keys in special metrics to aid in system health monitoring.
+add_task(function test_weird_data() {
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(TELEMETRY_PREF);
+ });
+ Services.prefs.setBoolPref(TELEMETRY_PREF, true);
+
+ const AWTelemetry = new AboutWelcomeTelemetry();
+
+ const unknownKey = "some_unknown_key";
+ const camelUnknownKey = AWTelemetry._snakeToCamelCase(unknownKey);
+
+ let pingSubmitted = false;
+ GleanPings.messagingSystem.testBeforeNextSubmit(() => {
+ pingSubmitted = true;
+ Assert.equal(
+ Glean.messagingSystem.unknownKeys[camelUnknownKey].testGetValue(),
+ 1,
+ "caught the unknown key"
+ );
+ // TODO(bug 1600008): Also check the for-testing overall count.
+ Assert.equal(Glean.messagingSystem.unknownKeyCount.testGetValue(), 1);
+ });
+ AWTelemetry.submitGleanPingForPing({
+ [unknownKey]: "value doesn't matter",
+ });
+
+ Assert.ok(pingSubmitted, "Ping with unknown keys was submitted");
+
+ const invalidNestedDataKey = "event";
+ pingSubmitted = false;
+ GleanPings.messagingSystem.testBeforeNextSubmit(() => {
+ pingSubmitted = true;
+ Assert.equal(
+ Glean.messagingSystem.invalidNestedData[
+ invalidNestedDataKey
+ ].testGetValue("messaging-system"),
+ 1,
+ "caught the invalid nested data"
+ );
+ });
+ AWTelemetry.submitGleanPingForPing({
+ [invalidNestedDataKey]: { this_should: "not be", complex: "data" },
+ });
+
+ Assert.ok(pingSubmitted, "Ping with invalid nested data submitted");
+});
+
+// `event_context` is weird. It's an object, but it might have been stringified
+// before being provided for recording.
+add_task(function test_event_context() {
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(TELEMETRY_PREF);
+ });
+ Services.prefs.setBoolPref(TELEMETRY_PREF, true);
+
+ const AWTelemetry = new AboutWelcomeTelemetry();
+
+ const eventContext = {
+ reason: "reason",
+ page: "page",
+ source: "source",
+ something_else: "not specifically handled",
+ screen_family: "family",
+ screen_id: "screen_id",
+ screen_index: 0,
+ screen_initlals: "screen_initials",
+ };
+ const stringifiedEC = JSON.stringify(eventContext);
+
+ let pingSubmitted = false;
+ GleanPings.messagingSystem.testBeforeNextSubmit(() => {
+ pingSubmitted = true;
+ Assert.equal(
+ Glean.messagingSystem.eventReason.testGetValue(),
+ eventContext.reason,
+ "event_context.reason also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventPage.testGetValue(),
+ eventContext.page,
+ "event_context.page also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventSource.testGetValue(),
+ eventContext.source,
+ "event_context.source also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenFamily.testGetValue(),
+ eventContext.screen_family,
+ "event_context.screen_family also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenId.testGetValue(),
+ eventContext.screen_id,
+ "event_context.screen_id also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenIndex.testGetValue(),
+ eventContext.screen_index,
+ "event_context.screen_index also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenInitials.testGetValue(),
+ eventContext.screen_initials,
+ "event_context.screen_initials also in own metric."
+ );
+
+ Assert.equal(
+ Glean.messagingSystem.eventContext.testGetValue(),
+ stringifiedEC,
+ "whole event_context added as text."
+ );
+ });
+ AWTelemetry.submitGleanPingForPing({
+ event_context: eventContext,
+ });
+ Assert.ok(pingSubmitted, "Ping with object event_context submitted");
+
+ pingSubmitted = false;
+ GleanPings.messagingSystem.testBeforeNextSubmit(() => {
+ pingSubmitted = true;
+ Assert.equal(
+ Glean.messagingSystem.eventReason.testGetValue(),
+ eventContext.reason,
+ "event_context.reason also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventPage.testGetValue(),
+ eventContext.page,
+ "event_context.page also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventSource.testGetValue(),
+ eventContext.source,
+ "event_context.source also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenFamily.testGetValue(),
+ eventContext.screen_family,
+ "event_context.screen_family also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenId.testGetValue(),
+ eventContext.screen_id,
+ "event_context.screen_id also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenIndex.testGetValue(),
+ eventContext.screen_index,
+ "event_context.screen_index also in own metric."
+ );
+ Assert.equal(
+ Glean.messagingSystem.eventScreenInitials.testGetValue(),
+ eventContext.screen_initials,
+ "event_context.screen_initials also in own metric."
+ );
+
+ Assert.equal(
+ Glean.messagingSystem.eventContext.testGetValue(),
+ stringifiedEC,
+ "whole event_context added as text."
+ );
+ });
+ AWTelemetry.submitGleanPingForPing({
+ event_context: stringifiedEC,
+ });
+ Assert.ok(pingSubmitted, "Ping with string event_context submitted");
+});
+
+// For event_context to be more useful, we want to make sure we don't error
+// in cases where it doesn't make much sense, such as a plain string that
+// doesnt attempt to represent a valid object.
+add_task(function test_context_errors() {
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(TELEMETRY_PREF);
+ });
+ Services.prefs.setBoolPref(TELEMETRY_PREF, true);
+
+ const AWTelemetry = new AboutWelcomeTelemetry();
+
+ let weird_context_ping = {
+ event_context: "oops, this string isn't a valid JS object!",
+ };
+
+ let pingSubmitted = false;
+ GleanPings.messagingSystem.testBeforeNextSubmit(() => {
+ pingSubmitted = true;
+ Assert.equal(
+ Glean.messagingSystem.eventContextParseError.testGetValue(),
+ undefined,
+ "this poorly formed context shouldn't register because it was not an object!"
+ );
+ });
+
+ AWTelemetry.submitGleanPingForPing(weird_context_ping);
+
+ Assert.ok(pingSubmitted, "Ping with unknown keys was submitted");
+
+ weird_context_ping = {
+ event_context:
+ "{oops : {'this string isn't a valid JS object, but it sure looks like one!}}'",
+ };
+
+ pingSubmitted = false;
+ GleanPings.messagingSystem.testBeforeNextSubmit(() => {
+ pingSubmitted = true;
+ Assert.equal(
+ Glean.messagingSystem.eventContextParseError.testGetValue(),
+ 1,
+ "this poorly formed context should register because it was not an object!"
+ );
+ });
+
+ AWTelemetry.submitGleanPingForPing(weird_context_ping);
+
+ Assert.ok(pingSubmitted, "Ping with unknown keys was submitted");
+});
diff --git a/browser/components/aboutwelcome/tests/xpcshell/xpcshell.toml b/browser/components/aboutwelcome/tests/xpcshell/xpcshell.toml
new file mode 100644
index 0000000000..d68ee3e51e
--- /dev/null
+++ b/browser/components/aboutwelcome/tests/xpcshell/xpcshell.toml
@@ -0,0 +1,9 @@
+[DEFAULT]
+skip-if = ["os == 'android'"]
+firefox-appdir = "browser"
+
+["test_AboutWelcomeAttribution.js"]
+
+["test_AboutWelcomeTelemetry.js"]
+
+["test_AboutWelcomeTelemetry_glean.js"]