From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- ...rowser_aboutwelcome_multistage_experimentAPI.js | 597 +++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100644 browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js (limited to 'browser/components/newtab/test/browser/browser_aboutwelcome_multistage_experimentAPI.js') 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: "", + }, + 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: "", + }, + 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(); +}); -- cgit v1.2.3