Bug 1816460 - Add Easy Setup as first screen in new user onboarding r=omc-reviewers,pdahiya

Differential Revision: https://phabricator.services.mozilla.com/D170683
This commit is contained in:
negin
2023-03-10 22:21:39 +00:00
parent 439082a84e
commit ea9bab44b1
6 changed files with 255 additions and 18 deletions

View File

@@ -36,8 +36,94 @@ const MR_ABOUT_WELCOME_DEFAULT = {
backdrop:
"var(--mr-welcome-background-color) var(--mr-welcome-background-gradient)",
screens: [
{
id: "AW_EASY_SETUP",
targeting:
"os.windowsBuildNumber >= 15063 && !isDefaultBrowser && !doesAppNeedPin",
content: {
position: "split",
split_narrow_bkg_position: "-60px",
image_alt_text: {
string_id: "mr2022-onboarding-default-image-alt",
},
background:
"url('chrome://activity-stream/content/data/content/assets/mr-settodefault.svg') var(--mr-secondary-position) no-repeat var(--mr-screen-background-color)",
progress_bar: true,
logo: {},
title: {
string_id: "mr2022-onboarding-set-default-title",
},
subtitle: {
string_id: "mr2022-onboarding-set-default-subtitle",
},
tiles: {
type: "multiselect",
data: [
{
id: "checkbox-1",
defaultValue: true,
label: {
string_id:
"mr2022-onboarding-easy-setup-set-default-checkbox-label",
},
action: {
type: "SET_DEFAULT_BROWSER",
},
},
{
id: "checkbox-2",
defaultValue: true,
label: {
string_id: "mr2022-onboarding-easy-setup-import-checkbox-label",
},
action: {
type: "SHOW_MIGRATION_WIZARD",
data: {},
},
},
],
},
primary_button: {
label: {
string_id: "mr2022-onboarding-easy-setup-primary-button-label",
},
action: {
type: "MULTI_ACTION",
collectSelect: true,
navigate: true,
data: {
actions: [],
},
},
},
secondary_button: {
label: {
string_id: "mr2022-onboarding-secondary-skip-button-label",
},
action: {
navigate: true,
},
has_arrow_icon: true,
},
secondary_button_top: {
label: {
string_id: "mr1-onboarding-sign-in-button-label",
},
action: {
data: {
entrypoint: "activity-stream-firstrun",
where: "tab",
},
type: "SHOW_FIREFOX_ACCOUNTS",
addFlowParams: true,
},
},
},
},
{
id: "AW_PIN_FIREFOX",
targeting:
"!(os.windowsBuildNumber >= 15063 && !isDefaultBrowser && !doesAppNeedPin)",
content: {
position: "split",
split_narrow_bkg_position: "-155px",
@@ -128,6 +214,8 @@ const MR_ABOUT_WELCOME_DEFAULT = {
},
{
id: "AW_SET_DEFAULT",
targeting:
"!(os.windowsBuildNumber >= 15063 && !isDefaultBrowser && !doesAppNeedPin)",
content: {
position: "split",
split_narrow_bkg_position: "-60px",
@@ -166,6 +254,8 @@ const MR_ABOUT_WELCOME_DEFAULT = {
},
{
id: "AW_IMPORT_SETTINGS",
targeting:
"!(os.windowsBuildNumber >= 15063 && !isDefaultBrowser && !doesAppNeedPin)",
content: {
position: "split",
split_narrow_bkg_position: "-42px",

View File

@@ -3,6 +3,12 @@
const { getAddonAndLocalAPIsMocker } = ChromeUtils.import(
"resource://testing-common/LangPackMatcherTestUtils.jsm"
);
const { AboutWelcomeDefaults } = ChromeUtils.import(
"resource://activity-stream/aboutwelcome/lib/AboutWelcomeDefaults.jsm"
);
const { AWScreenUtils } = ChromeUtils.import(
"resource://activity-stream/lib/AWScreenUtils.jsm"
);
const sandbox = sinon.createSandbox();
const mockAddonAndLocaleAPIs = getAddonAndLocalAPIsMocker(this, sandbox);
@@ -53,6 +59,14 @@ async function openAboutWelcome() {
);
sandbox.stub(ShellService, "doesAppNeedPin").returns(false);
const data = await AboutWelcomeDefaults.getDefaults();
const defaultMRArray = data.screens.filter(
screen => screen.id !== "AW_EASY_SETUP"
);
sandbox
.stub(AWScreenUtils, "evaluateTargetingAndRemoveScreens")
.resolves(defaultMRArray);
info("Opening about:welcome");
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,

View File

@@ -9,6 +9,12 @@ const {
} = ChromeUtils.importESModule(
"resource://testing-common/FirefoxViewTestUtils.sys.mjs"
);
const { AboutWelcomeDefaults } = ChromeUtils.import(
"resource://activity-stream/aboutwelcome/lib/AboutWelcomeDefaults.jsm"
);
const { AWScreenUtils } = ChromeUtils.import(
"resource://activity-stream/lib/AWScreenUtils.jsm"
);
async function clickVisibleButton(browser, selector) {
// eslint-disable-next-line no-shadow
@@ -83,7 +89,15 @@ add_task(async function test_aboutwelcome_mr_template_content() {
const sandbox = initSandbox();
let { browser, cleanup } = await openMRAboutWelcome();
const data = await AboutWelcomeDefaults.getDefaults();
const defaultMRArray = data.screens.filter(
screen => screen.id !== "AW_EASY_SETUP"
);
sandbox
.stub(AWScreenUtils, "evaluateTargetingAndRemoveScreens")
.resolves(defaultMRArray);
let { cleanup, browser } = await openMRAboutWelcome();
await test_screen_content(
browser,
@@ -130,6 +144,14 @@ add_task(async function test_aboutwelcome_mr_template_content_pin() {
const sandbox = initSandbox({ isDefault: true });
const data = await AboutWelcomeDefaults.getDefaults();
const defaultMRArray = data.screens.filter(
screen => screen.id !== "AW_EASY_SETUP"
);
sandbox
.stub(AWScreenUtils, "evaluateTargetingAndRemoveScreens")
.resolves(defaultMRArray);
let { browser, cleanup } = await openMRAboutWelcome();
await test_screen_content(
@@ -164,6 +186,13 @@ add_task(async function test_aboutwelcome_mr_template_only_default() {
await pushPrefs(["browser.shell.checkDefaultBrowser", true]);
const sandbox = initSandbox({ pin: false });
const data = await AboutWelcomeDefaults.getDefaults();
const defaultMRArray = data.screens.filter(
screen => screen.id !== "AW_EASY_SETUP"
);
sandbox
.stub(AWScreenUtils, "evaluateTargetingAndRemoveScreens")
.resolves(defaultMRArray);
let { browser, cleanup } = await openMRAboutWelcome();
@@ -189,6 +218,14 @@ add_task(async function test_aboutwelcome_mr_template_get_started() {
const sandbox = initSandbox({ pin: false, isDefault: true });
const data = await AboutWelcomeDefaults.getDefaults();
const defaultMRArray = data.screens.filter(
screen => screen.id !== "AW_EASY_SETUP"
);
sandbox
.stub(AWScreenUtils, "evaluateTargetingAndRemoveScreens")
.resolves(defaultMRArray);
let { browser, cleanup } = await openMRAboutWelcome();
//should render set default

View File

@@ -1,5 +1,13 @@
"use strict";
const { ShellService } = ChromeUtils.import(
"resource:///modules/ShellService.jsm"
);
const { TelemetryEnvironment } = ChromeUtils.importESModule(
"resource://gre/modules/TelemetryEnvironment.sys.mjs"
);
const TEST_DEFAULT_CONTENT = [
{
id: "AW_STEP1",
@@ -49,6 +57,16 @@ const TEST_DEFAULT_CONTENT = [
},
];
const sandbox = sinon.createSandbox();
add_setup(function initSandbox() {
requestLongerTimeout(2);
registerCleanupFunction(() => {
sandbox.restore();
});
});
const TEST_DEFAULT_JSON = JSON.stringify(TEST_DEFAULT_CONTENT);
async function openAboutWelcome() {
await setAboutWelcomePref(true);
@@ -66,7 +84,6 @@ async function openAboutWelcome() {
}
add_task(async function second_screen_filtered_by_targeting() {
const sandbox = sinon.createSandbox();
let browser = await openAboutWelcome();
let aboutWelcomeActor = await getAboutWelcomeParent(browser);
// Stub AboutWelcomeParent Content Message Handler
@@ -93,4 +110,43 @@ add_task(async function second_screen_filtered_by_targeting() {
);
sandbox.restore();
await popPrefs();
});
/**
* Test MR template easy setup content - Browser is pinned and
* not set as default and Windows 10 version 1703
*/
add_task(async function test_aboutwelcome_mr_template_easy_setup() {
if (!AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
return;
}
if (
//Windows version 1703
TelemetryEnvironment.currentEnvironment.system.os.windowsBuildNumber < 15063
) {
return;
}
sandbox.stub(ShellService, "doesAppNeedPin").returns(false);
sandbox.stub(ShellService, "isDefaultBrowser").returns(false);
await clearHistoryAndBookmarks();
const { browser, cleanup } = await openMRAboutWelcome();
//should render easy setup
await test_screen_content(
browser,
"doesn't render pin, import and set to default",
//Expected selectors:
["main.AW_EASY_SETUP"],
//Unexpected selectors:
["main.AW_PIN_FIREFOX", "main.AW_SET_DEFAULT", "main.AW_IMPORT_SETTINGS"]
);
await cleanup();
await popPrefs();
sandbox.restore();
});

View File

@@ -220,17 +220,29 @@ describe("MultiStageAboutWelcomeProton module", () => {
describe("AboutWelcomeDefaults for proton", () => {
const getData = () => AboutWelcomeDefaults.getDefaults();
async function prepConfig(config) {
async function prepConfig(config, evalFalseScreenIds) {
let data = await getData();
if (evalFalseScreenIds?.length) {
data.screens.forEach(async screen => {
if (evalFalseScreenIds.includes(screen.id)) {
screen.targeting = false;
}
});
data.screens = await AWScreenUtils.evaluateTargetingAndRemoveScreens(
data.screens
);
}
return AboutWelcomeDefaults.prepareContentForReact({
...(await getData()),
...data,
...config,
});
}
beforeEach(() => {
sandbox.stub(global.Services.prefs, "getBoolPref").returns(true);
sandbox
.stub(global.AWScreenUtils, "evaluateTargetingAndRemoveScreens")
.callsFake(() => AWScreenUtils.evaluateTargetingAndRemoveScreens());
sandbox.stub(AWScreenUtils, "evaluateScreenTargeting").returnsArg(0);
// This is necessary because there are still screens being removed with
// `removeScreens` in `prepareContentForReact()`. Once we've migrated
// to using screen targeting instead of manually removing screens,
@@ -242,8 +254,7 @@ describe("MultiStageAboutWelcomeProton module", () => {
);
});
it("should have 'pin' button by default", async () => {
const data = await getData();
const data = await prepConfig({ needPin: true }, ["AW_EASY_SETUP"]);
assert.propertyVal(
data.screens[0].content.primary_button.action,
"type",
@@ -251,7 +262,13 @@ describe("MultiStageAboutWelcomeProton module", () => {
);
});
it("should have 'pin' button if we need default and pin", async () => {
const data = await prepConfig({ needDefault: true, needPin: true });
const data = await prepConfig(
{
needDefault: true,
needPin: true,
},
["AW_EASY_SETUP"]
);
assert.propertyVal(
data.screens[0].content.primary_button.action,
@@ -260,28 +277,28 @@ describe("MultiStageAboutWelcomeProton module", () => {
);
assert.propertyVal(data.screens[0], "id", "AW_PIN_FIREFOX");
assert.propertyVal(data.screens[1], "id", "AW_SET_DEFAULT");
assert.lengthOf(data.screens, getData().screens.length - 1);
assert.lengthOf(data.screens, getData().screens.length - 2);
});
it("should keep 'pin' and remove 'default' if already default", async () => {
const data = await prepConfig({ needPin: true });
const data = await prepConfig({ needPin: true }, ["AW_EASY_SETUP"]);
assert.propertyVal(data.screens[0], "id", "AW_PIN_FIREFOX");
assert.propertyVal(data.screens[1], "id", "AW_IMPORT_SETTINGS");
assert.lengthOf(data.screens, getData().screens.length - 2);
assert.lengthOf(data.screens, getData().screens.length - 3);
});
it("should switch to 'default' if already pinned", async () => {
const data = await prepConfig({ needDefault: true });
const data = await prepConfig({ needDefault: true }, ["AW_EASY_SETUP"]);
assert.propertyVal(data.screens[0], "id", "AW_ONLY_DEFAULT");
assert.propertyVal(data.screens[1], "id", "AW_IMPORT_SETTINGS");
assert.lengthOf(data.screens, getData().screens.length - 2);
assert.lengthOf(data.screens, getData().screens.length - 3);
});
it("should switch to 'start' if already pinned and default", async () => {
const data = await prepConfig();
const data = await prepConfig({}, ["AW_EASY_SETUP"]);
assert.propertyVal(data.screens[0], "id", "AW_GET_STARTED");
assert.propertyVal(data.screens[1], "id", "AW_IMPORT_SETTINGS");
assert.lengthOf(data.screens, getData().screens.length - 2);
assert.lengthOf(data.screens, getData().screens.length - 3);
});
it("should have a FxA button", async () => {
const data = await prepConfig();

View File

@@ -66,8 +66,31 @@ describe("MultiStageAboutWelcome module", () => {
});
it("should handle primary Action", () => {
const screens = [
{
content: {
title: "test title",
subtitle: "test subtitle",
primary_button: {
label: "Test button",
action: {
navigate: true,
},
},
},
},
];
const PRIMARY_ACTION_PROPS = {
screens,
metricsFlowUri: "http://localhost/",
message_id: "DEFAULT_ABOUTWELCOME",
utm_term: "default",
startScreen: 0,
};
const stub = sinon.stub(AboutWelcomeUtils, "sendActionTelemetry");
let wrapper = mount(<MultiStageAboutWelcome {...DEFAULT_PROPS} />);
let wrapper = mount(<MultiStageAboutWelcome {...PRIMARY_ACTION_PROPS} />);
wrapper.update();
let welcomeScreenWrapper = wrapper.find(WelcomeScreen);