summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js')
-rw-r--r--browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js597
1 files changed, 597 insertions, 0 deletions
diff --git a/browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js b/browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js
new file mode 100644
index 0000000000..fea1ca961a
--- /dev/null
+++ b/browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js
@@ -0,0 +1,597 @@
+"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" },
+ },
+ },
+ help_text: {
+ text: "Here's some sample help text",
+ },
+ 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
+ */
+add_task(async function test_multistage_zeroOnboarding_experimentAPI() {
+ await setAboutWelcomePref(true);
+ await ExperimentAPI.ready();
+ let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
+ featureId: "aboutwelcome",
+ value: { enabled: false },
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:welcome",
+ true
+ );
+
+ registerCleanupFunction(() => {
+ BrowserTestUtils.removeTab(tab);
+ });
+
+ const browser = tab.linkedBrowser;
+
+ await test_screen_content(
+ browser,
+ "Opens new tab",
+ // Expected selectors:
+ ["div.search-wrapper", "body.activity-stream"],
+ // Unexpected selectors:
+ ["div.onboardingContainer", "main.AW_STEP1"]
+ );
+
+ await doExperimentCleanup();
+});
+
+/**
+ * Test the multistage welcome UI with test content theme as first screen
+ */
+add_task(async function test_multistage_aboutwelcome_experimentAPI() {
+ const TEST_CONTENT = [
+ {
+ id: "AW_STEP1",
+ content: {
+ title: "Step 1",
+ 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: "link",
+ },
+ secondary_button_top: {
+ label: "link top",
+ action: {
+ type: "SHOW_FIREFOX_ACCOUNTS",
+ data: { entrypoint: "test" },
+ },
+ },
+ has_noodles: true,
+ },
+ },
+ {
+ id: "AW_STEP2",
+ content: {
+ zap: true,
+ title: "Step 2 test",
+ primary_button: {
+ label: "Next",
+ action: {
+ navigate: true,
+ },
+ },
+ secondary_button: {
+ label: "link",
+ },
+ has_noodles: true,
+ },
+ },
+ {
+ id: "AW_STEP3",
+ content: {
+ logo: {},
+ title: "Step 3",
+ primary_button: {
+ label: "Next",
+ action: {
+ navigate: true,
+ },
+ },
+ secondary_button: {
+ label: "Import",
+ action: {
+ type: "SHOW_MIGRATION_WIZARD",
+ data: { source: "chrome" },
+ },
+ },
+ has_noodles: true,
+ },
+ },
+ ];
+ const sandbox = sinon.createSandbox();
+ NimbusFeatures.aboutwelcome._didSendExposureEvent = false;
+ await setAboutWelcomePref(true);
+ await ExperimentAPI.ready();
+
+ let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
+ featureId: "aboutwelcome",
+ enabled: true,
+ value: {
+ id: "my-mochitest-experiment",
+ screens: TEST_CONTENT,
+ },
+ });
+
+ sandbox.spy(ExperimentAPI, "recordExposureEvent");
+
+ Services.telemetry.clearScalars();
+ 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();
+ });
+
+ // Test first (theme) screen for non-win7.
+ if (!win7Content) {
+ await test_screen_content(
+ browser,
+ "multistage step 1",
+ // Expected selectors:
+ [
+ "div.onboardingContainer",
+ "main.AW_STEP1",
+ "div.secondary-cta",
+ "div.secondary-cta.top",
+ "button[value='secondary_button']",
+ "button[value='secondary_button_top']",
+ "label.theme",
+ "input[type='radio']",
+ ],
+ // Unexpected selectors:
+ ["main.AW_STEP2", "main.AW_STEP3", "div.tiles-container.info"]
+ );
+
+ await onButtonClick(browser, "button.primary");
+
+ const { callCount } = aboutWelcomeActor.onContentMessage;
+ ok(callCount >= 1, `${callCount} Stub was called`);
+ let clickCall;
+ for (let i = 0; i < callCount; i++) {
+ const call = aboutWelcomeActor.onContentMessage.getCall(i);
+ info(`Call #${i}: ${call.args[0]} ${JSON.stringify(call.args[1])}`);
+ if (call.calledWithMatch("", { event: "CLICK_BUTTON" })) {
+ clickCall = call;
+ }
+ }
+
+ Assert.equal(
+ clickCall.args[0],
+ "AWPage:TELEMETRY_EVENT",
+ "send telemetry event"
+ );
+
+ Assert.equal(
+ clickCall.args[1].message_id,
+ "MY-MOCHITEST-EXPERIMENT_0_AW_STEP1",
+ "Telemetry should join id defined in feature value with screen"
+ );
+ }
+
+ await test_screen_content(
+ browser,
+ "multistage step 2",
+ // Expected selectors:
+ [
+ "div.onboardingContainer",
+ "main.AW_STEP2",
+ "button[value='secondary_button']",
+ ],
+ // Unexpected selectors:
+ ["main.AW_STEP1", "main.AW_STEP3", "div.secondary-cta.top"]
+ );
+ await onButtonClick(browser, "button.primary");
+ await test_screen_content(
+ browser,
+ "multistage step 3",
+ // Expected selectors:
+ [
+ "div.onboardingContainer",
+ "main.AW_STEP3",
+ "img.brand-logo",
+ "div.welcome-text",
+ ],
+ // Unexpected selectors:
+ ["main.AW_STEP1", "main.AW_STEP2"]
+ );
+ await onButtonClick(browser, "button.primary");
+ await test_screen_content(
+ browser,
+ "home",
+ // Expected selectors:
+ ["body.activity-stream"],
+ // Unexpected selectors:
+ ["div.onboardingContainer"]
+ );
+
+ Assert.equal(
+ ExperimentAPI.recordExposureEvent.callCount,
+ 1,
+ "Called only once for exposure event"
+ );
+
+ const scalars = TelemetryTestUtils.getProcessScalars("parent", true, true);
+ TelemetryTestUtils.assertKeyedScalar(
+ scalars,
+ "telemetry.event_counts",
+ "normandy#expose#nimbus_experiment",
+ 1
+ );
+
+ 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() {
+ const sandbox = sinon.createSandbox();
+ const TEST_BACKDROP = "blue";
+
+ const TEST_CONTENT = [
+ {
+ id: "TEST_SCREEN",
+ content: {
+ position: "split",
+ logo: {},
+ title: "test",
+ },
+ },
+ ];
+ await setAboutWelcomePref(true);
+ await ExperimentAPI.ready();
+ await pushPrefs(["browser.aboutwelcome.backdrop", TEST_BACKDROP]);
+
+ const doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
+ featureId: "aboutwelcome",
+ value: {
+ id: "my-mochitest-experiment",
+ screens: TEST_CONTENT,
+ },
+ });
+
+ const tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:welcome",
+ true
+ );
+
+ const browser = tab.linkedBrowser;
+
+ registerCleanupFunction(() => {
+ BrowserTestUtils.removeTab(tab);
+ sandbox.restore();
+ });
+
+ await test_screen_content(
+ browser,
+ "multistage step 1",
+ // Expected selectors:
+ [`div.outer-wrapper.onboardingContainer[style*='${TEST_BACKDROP}']`]
+ );
+
+ await doExperimentCleanup();
+});
+
+add_task(async function test_multistage_aboutwelcome_utm_term() {
+ const sandbox = sinon.createSandbox();
+
+ const TEST_CONTENT = [
+ {
+ id: "TEST_SCREEN",
+ content: {
+ position: "split",
+ logo: {},
+ title: "test",
+ secondary_button_top: {
+ label: "test",
+ style: "link",
+ action: {
+ type: "OPEN_URL",
+ data: {
+ args: "https://www.mozilla.org/",
+ },
+ },
+ },
+ },
+ },
+ ];
+ await setAboutWelcomePref(true);
+ await ExperimentAPI.ready();
+
+ const doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
+ featureId: "aboutwelcome",
+ value: {
+ id: "my-mochitest-experiment",
+ screens: TEST_CONTENT,
+ UTMTerm: "test",
+ },
+ });
+
+ const tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:welcome",
+ true
+ );
+
+ const browser = tab.linkedBrowser;
+ const aboutWelcomeActor = await getAboutWelcomeParent(browser);
+
+ sandbox.stub(aboutWelcomeActor, "onContentMessage");
+
+ await onButtonClick(browser, "button[value='secondary_button_top']");
+
+ let actionCall;
+
+ const { callCount } = aboutWelcomeActor.onContentMessage;
+ for (let i = 0; i < callCount; i++) {
+ const call = aboutWelcomeActor.onContentMessage.getCall(i);
+ info(`Call #${i}: ${call.args[0]} ${JSON.stringify(call.args[1])}`);
+ if (call.calledWithMatch("SPECIAL")) {
+ actionCall = call;
+ }
+ }
+
+ Assert.equal(
+ actionCall.args[1].data.args,
+ "https://www.mozilla.org/?utm_source=activity-stream&utm_campaign=firstrun&utm_medium=referral&utm_term=test-screen",
+ "UTMTerm set in mobile"
+ );
+
+ registerCleanupFunction(() => {
+ sandbox.restore();
+ BrowserTestUtils.removeTab(tab);
+ });
+
+ await doExperimentCleanup();
+});