welcome_tour: Advancing to V3
We will have small changes to the V2: 1. Use V1 intro dialogue copy 2. Keep the V2 Files step 3. Remove the Quick Settings step 4. Update copy in the Explore step to remove mention of 'apps' Bug: 383375717 Test: Manual tested and updated tests Change-Id: Icd68b07d0b7759ce25b959a4f00c6944924e32d5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6091397 Commit-Queue: Tao Wu <wutao@chromium.org> Reviewed-by: Li Lin <llin@chromium.org> Cr-Commit-Position: refs/heads/main@{#1395718}
This commit is contained in:
ash
ash_strings.grd
ash_strings_grd
IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2.png.sha1IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2.png.sha1IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT.png.sha1
constants
user_education
chrome/browser/ui/ash/user_education/welcome_tour
testing/variations
tools/metrics/histograms/metadata/ash_user_education
@ -8212,17 +8212,11 @@ To shut down the device, press and hold the power button on the device again.
|
||||
<message name="IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT" desc="Text shown in the body of the dialog as part of the System UI Welcome Tour.">
|
||||
Take a quick tour to learn how to get around your <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph>. Get up and running in 5 steps.
|
||||
</message>
|
||||
<message name="IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2" desc="Text shown in the body of the dialog as part of the System UI Welcome Tour V2.">
|
||||
Take a quick tour to learn how to get around your <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph>
|
||||
</message>
|
||||
<message name="IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT" desc="Text shown as the Welcome Tour dialog title.">
|
||||
Hi there. <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> is a little different.
|
||||
</message>
|
||||
<message name="IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2" desc="Text shown as the Welcome Tour V2 dialog title.">
|
||||
6 tips to get started on <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph>
|
||||
</message>
|
||||
<message name="IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT" desc="Text shown in the body of a help bubble anchored to the Explore app as part of the System UI Welcome Tour.">
|
||||
Those were the basics! Continue in Explore, our built-in app for tips and help. You’ll find tips for getting started, recommended apps, special offers, and the newest <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> features.
|
||||
Those were the basics! Continue in Explore, our built-in app for tips and help. You’ll find tips for getting started, special offers, and the newest <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> features.
|
||||
</message>
|
||||
<message name="IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_ACCNAME" desc="The accessible name of a help bubble anchored to the Files app as part of the System UI Welcome Tour.">
|
||||
Tour step <ph name="STEP">$1<ex>1</ex></ph> of <ph name="TOTAL_STEPS">$2<ex>5</ex></ph>. You can find the Files app in Launcher. Manage your local files and your Google Drive files, all in the Files app.
|
||||
|
@ -1 +0,0 @@
|
||||
51a3652b0cb8ef770f15462f0519ea031f18d413
|
@ -1 +0,0 @@
|
||||
51a3652b0cb8ef770f15462f0519ea031f18d413
|
@ -1 +1 @@
|
||||
3e66510f6e69fdb7d266853f790053f92bb45bf3
|
||||
436236cc943f42618bc1d415957f6c71a4918893
|
@ -3115,10 +3115,10 @@ BASE_FEATURE(kWelcomeTourHoldbackArm,
|
||||
"WelcomeTourHoldbackArm",
|
||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
|
||||
// Enables the Welcome Tour V2 that has different strings and steps than V1.
|
||||
// Enables the Welcome Tour V3 that has different strings and steps than V1.
|
||||
// Enabling this flag has no effect unless `kWelcomeTour` is also enabled.
|
||||
BASE_FEATURE(kWelcomeTourV2,
|
||||
"WelcomeTourV2",
|
||||
BASE_FEATURE(kWelcomeTourV3,
|
||||
"WelcomeTourV3",
|
||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
|
||||
// Controls whether to enable MAC Address Randomization on WiFi connection.
|
||||
@ -4677,8 +4677,8 @@ bool IsWelcomeTourHoldbackEnabled() {
|
||||
base::FeatureList::IsEnabled(kWelcomeTourHoldbackArm);
|
||||
}
|
||||
|
||||
bool IsWelcomeTourV2Enabled() {
|
||||
return IsWelcomeTourEnabled() && base::FeatureList::IsEnabled(kWelcomeTourV2);
|
||||
bool IsWelcomeTourV3Enabled() {
|
||||
return IsWelcomeTourEnabled() && base::FeatureList::IsEnabled(kWelcomeTourV3);
|
||||
}
|
||||
|
||||
bool IsWifiConcurrencyEnabled() {
|
||||
|
@ -993,7 +993,7 @@ BASE_DECLARE_FEATURE(kWelcomeTourForceUserEligibility);
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS)
|
||||
BASE_DECLARE_FEATURE(kWelcomeTourHoldbackArm);
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS)
|
||||
BASE_DECLARE_FEATURE(kWelcomeTourV2);
|
||||
BASE_DECLARE_FEATURE(kWelcomeTourV3);
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS)
|
||||
BASE_DECLARE_FEATURE(kWifiConnectMacAddressRandomization);
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kWifiConcurrency);
|
||||
@ -1413,7 +1413,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourCounterfactuallyEnabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourEnabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourForceUserEligibilityEnabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourHoldbackEnabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourV2Enabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourV3Enabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWifiConcurrencyEnabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWifiDirectEnabled();
|
||||
COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWifiSyncAndroidEnabled();
|
||||
|
@ -66,9 +66,8 @@ namespace {
|
||||
// The singleton instance owned by the `UserEducationController`.
|
||||
WelcomeTourController* g_instance = nullptr;
|
||||
|
||||
// Strings.
|
||||
constexpr char16_t kTotalStepsV1[] = u"5";
|
||||
constexpr char16_t kTotalStepsV2[] = u"6";
|
||||
// Strings. V3 adds a Files app step, but removes the status area step.
|
||||
constexpr char16_t kTotalSteps[] = u"5";
|
||||
|
||||
// Helpers ---------------------------------------------------------------------
|
||||
|
||||
@ -184,11 +183,29 @@ ui::ElementContext WelcomeTourController::GetInitialElementContext() const {
|
||||
GetMatchingViewInPrimaryRootWindow(kShelfViewElementId));
|
||||
}
|
||||
|
||||
// There are some difference between V1 and V3. Here are the steps in summary.
|
||||
// V1:
|
||||
// 0. Optin dialog
|
||||
// 1. Shelf
|
||||
// 2. Status area
|
||||
// 3. Home button
|
||||
// 4. Search box
|
||||
// 5. Settings app
|
||||
// 6. Explore app
|
||||
// 7. Explore app window
|
||||
//
|
||||
// V3:
|
||||
// 0. Optin dialog
|
||||
// 1. Shelf
|
||||
// 2. Home button
|
||||
// 3. Search box
|
||||
// 4. Files app
|
||||
// 5. Settings app
|
||||
// 6. Explore app
|
||||
// 7. Explore app window
|
||||
user_education::TutorialDescription
|
||||
WelcomeTourController::GetTutorialDescription() const {
|
||||
const std::u16string product_name = ui::GetChromeOSDeviceName();
|
||||
const std::u16string total_steps =
|
||||
features::IsWelcomeTourV2Enabled() ? kTotalStepsV2 : kTotalStepsV1;
|
||||
int current_step = 1;
|
||||
|
||||
user_education::TutorialDescription tutorial_description;
|
||||
@ -219,59 +236,70 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
/*accessible_name=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps),
|
||||
base::NumberToString16(current_step++), kTotalSteps),
|
||||
/*body_text=*/
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_BODY_TEXT)))
|
||||
.AddCustomNextButton(DefaultNextButtonCallback().Then(
|
||||
base::BindRepeating(&WelcomeTourController::SetCurrentStep,
|
||||
weak_ptr_factory_.GetMutableWeakPtr(),
|
||||
welcome_tour_metrics::Step::kStatusArea))));
|
||||
.AddCustomNextButton(
|
||||
DefaultNextButtonCallback().Then(base::BindRepeating(
|
||||
&WelcomeTourController::SetCurrentStep,
|
||||
weak_ptr_factory_.GetMutableWeakPtr(),
|
||||
features::IsWelcomeTourV3Enabled()
|
||||
? welcome_tour_metrics::Step::kHomeButton
|
||||
: welcome_tour_metrics::Step::kStatusArea))));
|
||||
|
||||
// Wait for "Next" button click before proceeding to the next bubble step.
|
||||
// NOTE: This event step also ensures that the next bubble step will show on
|
||||
// the primary display by naming the primary root window's status area.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::EventStep(
|
||||
user_education::kHelpBubbleNextButtonClickedEvent,
|
||||
kShelfViewElementId)
|
||||
.NameElements(NameMatchingElementInPrimaryRootWindowCallback(
|
||||
kUnifiedSystemTrayElementId, kUnifiedSystemTrayElementName))
|
||||
.InSameContext());
|
||||
if (!features::IsWelcomeTourV3Enabled()) {
|
||||
// Wait for "Next" button click before proceeding to the next bubble step.
|
||||
// NOTE: This event step also ensures that the next bubble step will show on
|
||||
// the primary display by naming the primary root window's status area.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::EventStep(
|
||||
user_education::kHelpBubbleNextButtonClickedEvent,
|
||||
kShelfViewElementId)
|
||||
.NameElements(NameMatchingElementInPrimaryRootWindowCallback(
|
||||
kUnifiedSystemTrayElementId, kUnifiedSystemTrayElementName))
|
||||
.InSameContext());
|
||||
|
||||
// Step 2: Status area.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::BubbleStep(
|
||||
kUnifiedSystemTrayElementName)
|
||||
.SetBubbleArrow(user_education::HelpBubbleArrow::kBottomRight)
|
||||
.SetBubbleBodyText(IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT)
|
||||
.SetExtendedProperties(CreateHelpBubbleExtendedProperties(
|
||||
HelpBubbleId::kWelcomeTourStatusArea,
|
||||
/*accessible_name=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps),
|
||||
/*body_text=*/
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT)))
|
||||
.AddCustomNextButton(DefaultNextButtonCallback().Then(
|
||||
base::BindRepeating(&WelcomeTourController::SetCurrentStep,
|
||||
weak_ptr_factory_.GetMutableWeakPtr(),
|
||||
welcome_tour_metrics::Step::kHomeButton)))
|
||||
.InAnyContext());
|
||||
// Step 2 in V1: Status area.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::BubbleStep(
|
||||
kUnifiedSystemTrayElementName)
|
||||
.SetBubbleArrow(user_education::HelpBubbleArrow::kBottomRight)
|
||||
.SetBubbleBodyText(IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT)
|
||||
.SetExtendedProperties(CreateHelpBubbleExtendedProperties(
|
||||
HelpBubbleId::kWelcomeTourStatusArea,
|
||||
/*accessible_name=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), kTotalSteps),
|
||||
/*body_text=*/
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT)))
|
||||
.AddCustomNextButton(DefaultNextButtonCallback().Then(
|
||||
base::BindRepeating(&WelcomeTourController::SetCurrentStep,
|
||||
weak_ptr_factory_.GetMutableWeakPtr(),
|
||||
welcome_tour_metrics::Step::kHomeButton)))
|
||||
.InAnyContext());
|
||||
}
|
||||
|
||||
// Wait for "Next" button click before proceeding to the next bubble step.
|
||||
// NOTE: This event step also ensures that the next bubble step will show on
|
||||
// the primary display by naming the primary root window's home button.
|
||||
std::variant<ui::ElementIdentifier, std::string> current_element;
|
||||
if (features::IsWelcomeTourV3Enabled()) {
|
||||
current_element = kShelfViewElementId;
|
||||
} else {
|
||||
current_element = kUnifiedSystemTrayElementName;
|
||||
}
|
||||
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::EventStep(
|
||||
user_education::kHelpBubbleNextButtonClickedEvent,
|
||||
kUnifiedSystemTrayElementName)
|
||||
user_education::kHelpBubbleNextButtonClickedEvent, current_element)
|
||||
.NameElements(NameMatchingElementInPrimaryRootWindowCallback(
|
||||
kHomeButtonElementId, kHomeButtonElementName))
|
||||
.InSameContext());
|
||||
|
||||
// Step 3: Home button.
|
||||
// Step 3 in V1 and step 2 in V3: Home button.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::BubbleStep(kHomeButtonElementName)
|
||||
.SetBubbleArrow(user_education::HelpBubbleArrow::kBottomLeft)
|
||||
@ -281,7 +309,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
/*accessible_name=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps,
|
||||
base::NumberToString16(current_step++), kTotalSteps,
|
||||
product_name),
|
||||
/*body_text=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
@ -303,7 +331,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
welcome_tour_metrics::Step::kSearch)))
|
||||
.InAnyContext());
|
||||
|
||||
// Step 4: Search box.
|
||||
// Step 4 in V1 and step 3 in V3: Search box.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::BubbleStep(kSearchBoxViewElementId)
|
||||
.SetBubbleArrow(user_education::HelpBubbleArrow::kTopCenter)
|
||||
@ -313,7 +341,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
/*accessible_name=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps,
|
||||
base::NumberToString16(current_step++), kTotalSteps,
|
||||
product_name),
|
||||
/*body_text=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
@ -323,7 +351,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
DefaultNextButtonCallback().Then(base::BindRepeating(
|
||||
&WelcomeTourController::SetCurrentStep,
|
||||
weak_ptr_factory_.GetMutableWeakPtr(),
|
||||
features::IsWelcomeTourV2Enabled()
|
||||
features::IsWelcomeTourV3Enabled()
|
||||
? welcome_tour_metrics::Step::kFilesApp
|
||||
: welcome_tour_metrics::Step::kSettingsApp)))
|
||||
.InAnyContext());
|
||||
@ -335,8 +363,8 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
kSearchBoxViewElementId)
|
||||
.InSameContext());
|
||||
|
||||
if (features::IsWelcomeTourV2Enabled()) {
|
||||
// Step 5 in V2: Files app.
|
||||
if (features::IsWelcomeTourV3Enabled()) {
|
||||
// Step 4 in V3: Files app.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::BubbleStep(kFilesAppElementId)
|
||||
.SetBubbleArrow(user_education::HelpBubbleArrow::kBottomLeft)
|
||||
@ -346,7 +374,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
/*accessible_name=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps),
|
||||
base::NumberToString16(current_step++), kTotalSteps),
|
||||
/*body_text=*/
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_BODY_TEXT)))
|
||||
@ -364,7 +392,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
.InSameContext());
|
||||
}
|
||||
|
||||
// Step 5 in V1 and step 6 in V2: Settings app.
|
||||
// Step 5: Settings app.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::BubbleStep(kSettingsAppElementId)
|
||||
.SetBubbleArrow(user_education::HelpBubbleArrow::kBottomLeft)
|
||||
@ -374,7 +402,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
/*accessible_name=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps,
|
||||
base::NumberToString16(current_step++), kTotalSteps,
|
||||
product_name),
|
||||
/*body_text=*/
|
||||
l10n_util::GetStringFUTF8(
|
||||
@ -393,7 +421,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
kSettingsAppElementId)
|
||||
.InSameContext());
|
||||
|
||||
// Step 6 in V1 and step 7 in V2: Explore app.
|
||||
// Step 6: Explore app.
|
||||
// NOTE: The accessible name is the same as the body text.
|
||||
tutorial_description.steps.emplace_back(
|
||||
user_education::TutorialDescription::BubbleStep(kExploreAppElementId)
|
||||
@ -406,7 +434,7 @@ WelcomeTourController::GetTutorialDescription() const {
|
||||
product_name)))
|
||||
.InSameContext());
|
||||
|
||||
// Step 7 in V1 and step 8 in V2: Explore app window.
|
||||
// Step 7: Explore app window.
|
||||
// Implemented in `WelcomeTourController::OnWelcomeTourEnded()`.
|
||||
|
||||
return tutorial_description;
|
||||
|
@ -102,8 +102,7 @@ using ContextMode = TutorialDescription::ContextMode;
|
||||
using ElementSpecifier = TutorialDescription::ElementSpecifier;
|
||||
|
||||
// Strings.
|
||||
constexpr char16_t kTotalStepsV1[] = u"5";
|
||||
constexpr char16_t kTotalStepsV2[] = u"6";
|
||||
constexpr char16_t kTotalSteps[] = u"5";
|
||||
|
||||
// Actions ---------------------------------------------------------------------
|
||||
|
||||
@ -570,31 +569,31 @@ TEST_F(WelcomeTourControllerTest, AbortsTourAndPropagatesEvents) {
|
||||
EXPECT_TRUE(ended_future.Wait());
|
||||
}
|
||||
|
||||
// WelcomeTourControllerV2Test -------------------------------------------------
|
||||
// WelcomeTourControllerV3Test -------------------------------------------------
|
||||
|
||||
// Base class for tests of the `WelcomeTourController` which are concerned with
|
||||
// the behavior of WelcomeTourV2 experiment arms, parameterized by whether the
|
||||
// Welcome Tour V2 feature is enabled.
|
||||
class WelcomeTourControllerV2Test
|
||||
// the behavior of WelcomeTourV3 experiment arms, parameterized by whether the
|
||||
// Welcome Tour V3 feature is enabled.
|
||||
class WelcomeTourControllerV3Test
|
||||
: public WelcomeTourControllerTest,
|
||||
public ::testing::WithParamInterface<std::tuple<
|
||||
/*is_welcome_tour_v2_enabled=*/bool,
|
||||
/*is_welcome_tour_v3_enabled=*/bool,
|
||||
/*is_welcome_tour_counterfactually_enabled=*/bool>> {
|
||||
public:
|
||||
WelcomeTourControllerV2Test() {
|
||||
WelcomeTourControllerV3Test() {
|
||||
// Only one of those features can be enabled at a time.
|
||||
scoped_feature_list_.InitWithFeatureStates(
|
||||
{{features::kWelcomeTourV2,
|
||||
IsWelcomeTourV2Enabled() && !IsWelcomeTourCounterfactuallyEnabled()},
|
||||
{{features::kWelcomeTourV3,
|
||||
IsWelcomeTourV3Enabled() && !IsWelcomeTourCounterfactuallyEnabled()},
|
||||
{features::kWelcomeTourCounterfactualArm,
|
||||
IsWelcomeTourCounterfactuallyEnabled()},
|
||||
{features::kWelcomeTourHoldbackArm, false}});
|
||||
}
|
||||
|
||||
protected:
|
||||
// Returns whether the WelcomeTourV2 feature is enabled given test
|
||||
// Returns whether the WelcomeTourV3 feature is enabled given test
|
||||
// parameterization.
|
||||
bool IsWelcomeTourV2Enabled() const { return std::get<0>(GetParam()); }
|
||||
bool IsWelcomeTourV3Enabled() const { return std::get<0>(GetParam()); }
|
||||
|
||||
// Returns whether the WelcomeTour feature is counterfactually enabled given
|
||||
// test parameterization.
|
||||
@ -608,19 +607,17 @@ class WelcomeTourControllerV2Test
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
All,
|
||||
WelcomeTourControllerV2Test,
|
||||
WelcomeTourControllerV3Test,
|
||||
testing::Combine(
|
||||
/*is_welcome_tour_v2_enabled=*/testing::Bool(),
|
||||
/*is_welcome_tour_v3_enabled=*/testing::Bool(),
|
||||
/*is_welcome_tour_counterfactually_enabled=*/testing::Bool()));
|
||||
|
||||
// Verifies that `GetTutorialDescription()` returns expected values.
|
||||
TEST_P(WelcomeTourControllerV2Test, GetTutorialDescription) {
|
||||
TEST_P(WelcomeTourControllerV3Test, GetTutorialDescription) {
|
||||
auto* welcome_tour_controller = WelcomeTourController::Get();
|
||||
ASSERT_TRUE(welcome_tour_controller);
|
||||
|
||||
const std::u16string product_name = ui::GetChromeOSDeviceName();
|
||||
const std::u16string total_steps =
|
||||
features::IsWelcomeTourV2Enabled() ? kTotalStepsV2 : kTotalStepsV1;
|
||||
int current_step = 1;
|
||||
|
||||
using ::testing::Matcher;
|
||||
@ -634,63 +631,73 @@ TEST_P(WelcomeTourControllerV2Test, GetTutorialDescription) {
|
||||
ElementSpecifier(kShelfViewElementId), ContextMode::kInitial,
|
||||
HelpBubbleId::kWelcomeTourShelf,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps),
|
||||
base::NumberToString16(current_step++), kTotalSteps),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringUTF8Eq(IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_BODY_TEXT),
|
||||
HelpBubbleArrow::kBottomCenter,
|
||||
/*has_next_button=*/true),
|
||||
EventStep(ElementSpecifier(kShelfViewElementId),
|
||||
ContextMode::kFromPreviousStep,
|
||||
/*has_name_elements_callback=*/true),
|
||||
BubbleStep(
|
||||
ElementSpecifier(kUnifiedSystemTrayElementName), ContextMode::kAny,
|
||||
HelpBubbleId::kWelcomeTourStatusArea,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT),
|
||||
HelpBubbleArrow::kBottomRight,
|
||||
/*has_next_button=*/true),
|
||||
EventStep(ElementSpecifier(kUnifiedSystemTrayElementName),
|
||||
ContextMode::kFromPreviousStep,
|
||||
/*has_name_elements_callback=*/true),
|
||||
BubbleStep(
|
||||
ElementSpecifier(kHomeButtonElementName), ContextMode::kAny,
|
||||
HelpBubbleId::kWelcomeTourHomeButton,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps,
|
||||
product_name),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringFUTF8Eq(
|
||||
(chromeos::GetDeviceType() == chromeos::DeviceType::kChromebook)
|
||||
? IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_CHROMEBOOK
|
||||
: IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_OTHER_DEVICE_TYPES,
|
||||
product_name),
|
||||
HelpBubbleArrow::kBottomLeft,
|
||||
/*has_next_button=*/true),
|
||||
BubbleStep(ElementSpecifier(kSearchBoxViewElementId), ContextMode::kAny,
|
||||
HelpBubbleId::kWelcomeTourSearchBox,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++),
|
||||
total_steps, product_name),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_BODY_TEXT,
|
||||
product_name),
|
||||
HelpBubbleArrow::kTopCenter,
|
||||
/*has_next_button=*/true),
|
||||
EventStep(ElementSpecifier(kSearchBoxViewElementId),
|
||||
ContextMode::kFromPreviousStep,
|
||||
/*has_name_elements_callback=*/false)};
|
||||
/*has_name_elements_callback=*/true)};
|
||||
|
||||
if (features::IsWelcomeTourV2Enabled()) {
|
||||
if (!features::IsWelcomeTourV3Enabled()) {
|
||||
// No status area step for V3.
|
||||
expected_steps.insert(
|
||||
expected_steps.end(),
|
||||
{// Files app step for V2.
|
||||
{BubbleStep(
|
||||
ElementSpecifier(kUnifiedSystemTrayElementName), ContextMode::kAny,
|
||||
HelpBubbleId::kWelcomeTourStatusArea,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), kTotalSteps),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT),
|
||||
HelpBubbleArrow::kBottomRight,
|
||||
/*has_next_button=*/true),
|
||||
EventStep(ElementSpecifier(kUnifiedSystemTrayElementName),
|
||||
ContextMode::kFromPreviousStep,
|
||||
/*has_name_elements_callback=*/true)});
|
||||
}
|
||||
|
||||
expected_steps.insert(
|
||||
expected_steps.end(),
|
||||
{BubbleStep(
|
||||
ElementSpecifier(kHomeButtonElementName), ContextMode::kAny,
|
||||
HelpBubbleId::kWelcomeTourHomeButton,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), kTotalSteps,
|
||||
product_name),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringFUTF8Eq(
|
||||
(chromeos::GetDeviceType() == chromeos::DeviceType::kChromebook)
|
||||
? IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_CHROMEBOOK
|
||||
: IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_OTHER_DEVICE_TYPES,
|
||||
product_name),
|
||||
HelpBubbleArrow::kBottomLeft,
|
||||
/*has_next_button=*/true),
|
||||
BubbleStep(
|
||||
ElementSpecifier(kSearchBoxViewElementId), ContextMode::kAny,
|
||||
HelpBubbleId::kWelcomeTourSearchBox,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), kTotalSteps,
|
||||
product_name),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_BODY_TEXT,
|
||||
product_name),
|
||||
HelpBubbleArrow::kTopCenter,
|
||||
/*has_next_button=*/true),
|
||||
EventStep(ElementSpecifier(kSearchBoxViewElementId),
|
||||
ContextMode::kFromPreviousStep,
|
||||
/*has_name_elements_callback=*/false)});
|
||||
|
||||
if (features::IsWelcomeTourV3Enabled()) {
|
||||
expected_steps.insert(
|
||||
expected_steps.end(),
|
||||
{// Files app step for V3.
|
||||
BubbleStep(
|
||||
ElementSpecifier(kFilesAppElementId),
|
||||
ContextMode::kFromPreviousStep, HelpBubbleId::kWelcomeTourFilesApp,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps),
|
||||
base::NumberToString16(current_step++), kTotalSteps),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringUTF8Eq(IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_BODY_TEXT),
|
||||
HelpBubbleArrow::kBottomLeft,
|
||||
@ -707,7 +714,7 @@ TEST_P(WelcomeTourControllerV2Test, GetTutorialDescription) {
|
||||
ContextMode::kFromPreviousStep,
|
||||
HelpBubbleId::kWelcomeTourSettingsApp,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_ACCNAME,
|
||||
base::NumberToString16(current_step++), total_steps,
|
||||
base::NumberToString16(current_step++), kTotalSteps,
|
||||
product_name),
|
||||
IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT,
|
||||
StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_BODY_TEXT,
|
||||
@ -878,7 +885,7 @@ class WelcomeTourControllerHoldbackTest
|
||||
if (const auto& is_holdback = IsHoldback()) {
|
||||
scoped_feature_list_.InitWithFeatureStates(
|
||||
{{features::kWelcomeTourHoldbackArm, is_holdback.value()},
|
||||
{features::kWelcomeTourV2, false},
|
||||
{features::kWelcomeTourV3, false},
|
||||
{features::kWelcomeTourCounterfactualArm, false}});
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ WelcomeTourDialog::WelcomeTourDialog(base::OnceClosure accept_callback,
|
||||
g_instance = this;
|
||||
|
||||
const std::u16string product_name = ui::GetChromeOSDeviceName();
|
||||
bool is_welcome_tour_v2_enabled = features::IsWelcomeTourV2Enabled();
|
||||
|
||||
views::Builder<SystemDialogDelegateView>(this)
|
||||
.SetAcceptButtonText(l10n_util::GetStringUTF16(
|
||||
@ -82,16 +81,11 @@ WelcomeTourDialog::WelcomeTourDialog(base::OnceClosure accept_callback,
|
||||
.SetCancelCallback(std::move(cancel_callback))
|
||||
.SetCloseCallback(std::move(close_callback))
|
||||
.SetDescription(l10n_util::GetStringFUTF16(
|
||||
is_welcome_tour_v2_enabled
|
||||
? IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2
|
||||
: IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT,
|
||||
product_name))
|
||||
IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT, product_name))
|
||||
.SetModalType(ui::mojom::ModalType::kSystem)
|
||||
.SetProperty(views::kElementIdentifierKey, kWelcomeTourDialogElementId)
|
||||
.SetTitleText(l10n_util::GetStringFUTF16(
|
||||
is_welcome_tour_v2_enabled ? IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2
|
||||
: IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT,
|
||||
product_name))
|
||||
IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT, product_name))
|
||||
.SetTopContentView(views::Builder<views::ImageView>()
|
||||
.SetImage(ui::ResourceBundle::GetSharedInstance()
|
||||
.GetThemedLottieImageNamed(
|
||||
|
@ -45,22 +45,22 @@ void MaybeActivateExperimentalArm(PrefService* prefs) {
|
||||
// NOTE: Checking feature flag state activates experimental arms.
|
||||
const bool is_holdback_enabled = features::IsWelcomeTourHoldbackEnabled();
|
||||
const bool is_v1_enabled = features::IsWelcomeTourCounterfactuallyEnabled();
|
||||
const bool is_v2_enabled = features::IsWelcomeTourV2Enabled();
|
||||
const bool is_v3_enabled = features::IsWelcomeTourV3Enabled();
|
||||
|
||||
bool changed_experimental_arm = false;
|
||||
const auto experimental_arm = first_experimental_arm.value();
|
||||
switch (experimental_arm) {
|
||||
case welcome_tour_metrics::ExperimentalArm::kHoldback:
|
||||
changed_experimental_arm =
|
||||
!is_holdback_enabled && (is_v1_enabled || is_v2_enabled);
|
||||
!is_holdback_enabled && (is_v1_enabled || is_v3_enabled);
|
||||
break;
|
||||
case welcome_tour_metrics::ExperimentalArm::kV1:
|
||||
changed_experimental_arm =
|
||||
!is_v1_enabled && (is_holdback_enabled || is_v2_enabled);
|
||||
!is_v1_enabled && (is_holdback_enabled || is_v3_enabled);
|
||||
break;
|
||||
case welcome_tour_metrics::ExperimentalArm::kV2:
|
||||
case welcome_tour_metrics::ExperimentalArm::kV3:
|
||||
changed_experimental_arm =
|
||||
!is_v2_enabled && (is_holdback_enabled || is_v1_enabled);
|
||||
!is_v3_enabled && (is_holdback_enabled || is_v1_enabled);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -78,16 +78,16 @@ void MaybeRecordExperimentalArm(PrefService* prefs) {
|
||||
std::optional<ExperimentalArm> experimental_arm;
|
||||
if (features::IsWelcomeTourCounterfactuallyEnabled()) {
|
||||
CHECK(!features::IsWelcomeTourHoldbackEnabled());
|
||||
CHECK(!features::IsWelcomeTourV2Enabled());
|
||||
CHECK(!features::IsWelcomeTourV3Enabled());
|
||||
experimental_arm = ExperimentalArm::kV1;
|
||||
} else if (features::IsWelcomeTourHoldbackEnabled()) {
|
||||
CHECK(!features::IsWelcomeTourCounterfactuallyEnabled());
|
||||
CHECK(!features::IsWelcomeTourV2Enabled());
|
||||
CHECK(!features::IsWelcomeTourV3Enabled());
|
||||
experimental_arm = ExperimentalArm::kHoldback;
|
||||
} else if (features::IsWelcomeTourV2Enabled()) {
|
||||
} else if (features::IsWelcomeTourV3Enabled()) {
|
||||
CHECK(!features::IsWelcomeTourCounterfactuallyEnabled());
|
||||
CHECK(!features::IsWelcomeTourHoldbackEnabled());
|
||||
experimental_arm = ExperimentalArm::kV2;
|
||||
experimental_arm = ExperimentalArm::kV3;
|
||||
}
|
||||
|
||||
if (!experimental_arm) {
|
||||
|
@ -52,8 +52,9 @@ enum class ExperimentalArm {
|
||||
kMinValue = 0,
|
||||
kHoldback = kMinValue,
|
||||
kV1 = 1,
|
||||
kV2 = 2,
|
||||
kMaxValue = kV2,
|
||||
// kV2 = 2, Deprecated.
|
||||
kV3 = 3,
|
||||
kMaxValue = kV3,
|
||||
};
|
||||
|
||||
static constexpr auto kAllExperimentalArmsSet =
|
||||
@ -62,7 +63,7 @@ static constexpr auto kAllExperimentalArmsSet =
|
||||
ExperimentalArm::kMaxValue>({
|
||||
ExperimentalArm::kHoldback,
|
||||
ExperimentalArm::kV1,
|
||||
ExperimentalArm::kV2,
|
||||
ExperimentalArm::kV3,
|
||||
});
|
||||
|
||||
// Enumeration of interactions users may engage in after the Welcome Tour. These
|
||||
|
@ -59,7 +59,7 @@ class WelcomeTourChangedExperimentalArmMetricTest
|
||||
scoped_feature_list.InitWithFeatureStates(
|
||||
{{features::kWelcomeTourCounterfactualArm, IsV1Enabled()},
|
||||
{features::kWelcomeTourHoldbackArm, IsHoldbackEnabled()},
|
||||
{features::kWelcomeTourV2, IsV2Enabled()},
|
||||
{features::kWelcomeTourV3, IsV3Enabled()},
|
||||
{features::kWelcomeTourForceUserEligibility, true}});
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ class WelcomeTourChangedExperimentalArmMetricTest
|
||||
|
||||
bool IsPrefValueV1() const { return GetPrefValue() == ExperimentalArm::kV1; }
|
||||
|
||||
bool IsPrefValueV2() const { return GetPrefValue() == ExperimentalArm::kV2; }
|
||||
bool IsPrefValueV3() const { return GetPrefValue() == ExperimentalArm::kV3; }
|
||||
|
||||
bool IsHoldbackEnabled() const {
|
||||
return GetEnabledArm() == ExperimentalArm::kHoldback;
|
||||
@ -85,7 +85,7 @@ class WelcomeTourChangedExperimentalArmMetricTest
|
||||
|
||||
bool IsV1Enabled() const { return GetEnabledArm() == ExperimentalArm::kV1; }
|
||||
|
||||
bool IsV2Enabled() const { return GetEnabledArm() == ExperimentalArm::kV2; }
|
||||
bool IsV3Enabled() const { return GetEnabledArm() == ExperimentalArm::kV3; }
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
@ -99,12 +99,12 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
::testing::Values(std::nullopt,
|
||||
std::make_optional(ExperimentalArm::kHoldback),
|
||||
std::make_optional(ExperimentalArm::kV1),
|
||||
std::make_optional(ExperimentalArm::kV2)),
|
||||
std::make_optional(ExperimentalArm::kV3)),
|
||||
/*enabled_arm=*/
|
||||
::testing::Values(std::nullopt,
|
||||
std::make_optional(ExperimentalArm::kHoldback),
|
||||
std::make_optional(ExperimentalArm::kV1),
|
||||
std::make_optional(ExperimentalArm::kV2))));
|
||||
std::make_optional(ExperimentalArm::kV3))));
|
||||
|
||||
// Tests -----------------------------------------------------------------------
|
||||
|
||||
@ -161,7 +161,7 @@ class WelcomeTourExperimentalArmMetricTest
|
||||
scoped_feature_list.InitWithFeatureStates(
|
||||
{{features::kWelcomeTourCounterfactualArm, IsV1Enabled()},
|
||||
{features::kWelcomeTourHoldbackArm, IsHoldbackEnabled()},
|
||||
{features::kWelcomeTourV2, IsV2Enabled()},
|
||||
{features::kWelcomeTourV3, IsV3Enabled()},
|
||||
{features::kWelcomeTourForceUserEligibility, true}});
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ class WelcomeTourExperimentalArmMetricTest
|
||||
|
||||
bool IsV1Enabled() const { return GetEnabledArm() == ExperimentalArm::kV1; }
|
||||
|
||||
bool IsV2Enabled() const { return GetEnabledArm() == ExperimentalArm::kV2; }
|
||||
bool IsV3Enabled() const { return GetEnabledArm() == ExperimentalArm::kV3; }
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
@ -186,7 +186,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
::testing::Values(std::nullopt,
|
||||
std::make_optional(ExperimentalArm::kHoldback),
|
||||
std::make_optional(ExperimentalArm::kV1),
|
||||
std::make_optional(ExperimentalArm::kV2)));
|
||||
std::make_optional(ExperimentalArm::kV3)));
|
||||
|
||||
// Tests -----------------------------------------------------------------------
|
||||
|
||||
@ -225,7 +225,7 @@ class WelcomeTourInteractionMetricsTest
|
||||
// Only one of those features can be enabled at a time.
|
||||
scoped_feature_list.InitWithFeatureStates(
|
||||
{{features::kWelcomeTourHoldbackArm, IsHoldback()},
|
||||
{features::kWelcomeTourV2, false},
|
||||
{features::kWelcomeTourV3, false},
|
||||
{features::kWelcomeTourCounterfactualArm, false}});
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ TEST_F(WelcomeTourMetricsEnumTest, AllExperimentalArms) {
|
||||
switch (arm) {
|
||||
case ExperimentalArm::kHoldback:
|
||||
case ExperimentalArm::kV1:
|
||||
case ExperimentalArm::kV2:
|
||||
case ExperimentalArm::kV3:
|
||||
should_exist_in_all_set = true;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@ namespace {
|
||||
// static constexpr char kReasonForFirstTourPrevention[] =
|
||||
// "ash.welcome_tour.prevented.first_reason";
|
||||
|
||||
// We will reuse the `v2` prefs for `v3` since there is no conflict.
|
||||
// TODO: crbug.com/353568276 - Clean up the prefs after full launch.
|
||||
static constexpr char kFirstExperimentalArm[] =
|
||||
"ash.welcome_tour.v2.experimental_arm.first";
|
||||
static constexpr char kTimeOfFirstInteractionPrefPrefix[] =
|
||||
|
@ -104,7 +104,7 @@ TEST_F(WelcomeTourPrefsTest, FirstExperimentalArm) {
|
||||
|
||||
// For any call beyond the first, the function should return false and the
|
||||
// marked first experimental arm should not change.
|
||||
EXPECT_FALSE(MarkFirstExperimentalArm(pref_service(), ExperimentalArm::kV2));
|
||||
EXPECT_FALSE(MarkFirstExperimentalArm(pref_service(), ExperimentalArm::kV3));
|
||||
EXPECT_EQ(GetFirstExperimentalArm(pref_service()),
|
||||
ExperimentalArm::kHoldback);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ using ::testing::Property;
|
||||
|
||||
using TestVariantsParam = std::tuple<
|
||||
/*is_apps_collections_enabled=*/bool,
|
||||
/*is_welcome_tour_v2_enabled=*/bool,
|
||||
/*is_welcome_tour_v3_enabled=*/bool,
|
||||
/*is_welcome_tour_counterfactaully_enabled=*/bool>;
|
||||
|
||||
// Matchers --------------------------------------------------------------------
|
||||
@ -66,7 +66,7 @@ bool IsAppsCollectionsEnabled(TestVariantsParam param) {
|
||||
return std::get<0>(param);
|
||||
}
|
||||
|
||||
bool IsWelcomeTourV2Enabled(TestVariantsParam param) {
|
||||
bool IsWelcomeTourV3Enabled(TestVariantsParam param) {
|
||||
return std::get<1>(param);
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ bool IsWelcomeTourCounterfactuallyEnabled(TestVariantsParam param) {
|
||||
std::string GenerateTestSuffix(
|
||||
const testing::TestParamInfo<TestVariantsParam>& info) {
|
||||
return base::StrCat(
|
||||
{IsWelcomeTourV2Enabled(info.param) ? "V2" : "V1", "_",
|
||||
{IsWelcomeTourV3Enabled(info.param) ? "V3" : "V1", "_",
|
||||
IsWelcomeTourCounterfactuallyEnabled(info.param) ? "Counterfactual_"
|
||||
: "",
|
||||
IsAppsCollectionsEnabled(info.param) ? "AppsCollectionsEnabled"
|
||||
@ -97,12 +97,12 @@ class WelcomeTourInteractiveUiTest
|
||||
// NOTE: These tests are not concerned with user eligibility, so explicitly
|
||||
// force user eligibility for the Welcome Tour.
|
||||
// Only one of `kWelcomeTourHoldbackArm`, `kWelcomeTourCounterfactualArm`
|
||||
// and `kWelcomeTourV2` can be enabled at a time.
|
||||
// and `kWelcomeTourV3` can be enabled at a time.
|
||||
scoped_feature_list_.InitWithFeatureStates(
|
||||
{{ash::features::kWelcomeTour, true},
|
||||
{ash::features::kWelcomeTourForceUserEligibility, true},
|
||||
{ash::features::kWelcomeTourV2,
|
||||
IsWelcomeTourV2Enabled() && !IsWelcomeTourCounterfactuallyEnabled()},
|
||||
{ash::features::kWelcomeTourV3,
|
||||
IsWelcomeTourV3Enabled() && !IsWelcomeTourCounterfactuallyEnabled()},
|
||||
{ash::features::kWelcomeTourCounterfactualArm,
|
||||
IsWelcomeTourCounterfactuallyEnabled()},
|
||||
{ash::features::kWelcomeTourHoldbackArm, false},
|
||||
@ -144,10 +144,10 @@ class WelcomeTourInteractiveUiTest
|
||||
return ::IsAppsCollectionsEnabled(GetParam());
|
||||
}
|
||||
|
||||
// Returns whether the WelcomeTourV2 feature is enabled given test
|
||||
// Returns whether the WelcomeTourV3 feature is enabled given test
|
||||
// parameterization.
|
||||
bool IsWelcomeTourV2Enabled() const {
|
||||
return ::IsWelcomeTourV2Enabled(GetParam());
|
||||
bool IsWelcomeTourV3Enabled() const {
|
||||
return ::IsWelcomeTourV3Enabled(GetParam());
|
||||
}
|
||||
|
||||
// Returns whether the WelcomeTour feature is counterfactually enabled given
|
||||
@ -306,7 +306,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
WelcomeTourInteractiveUiTest,
|
||||
testing::Combine(
|
||||
/*is_apps_collections_enabled=*/testing::Bool(),
|
||||
/*is_welcome_tour_v2_enabled=*/testing::Bool(),
|
||||
/*is_welcome_tour_v3_enabled=*/testing::Bool(),
|
||||
/*is_welcome_tour_counterfactually_enabled=*/testing::Bool()),
|
||||
&GenerateTestSuffix);
|
||||
|
||||
@ -319,17 +319,12 @@ IN_PROC_BROWSER_TEST_P(WelcomeTourInteractiveUiTest, WelcomeTour) {
|
||||
RunTestSequence(
|
||||
// Step 0: Dialog.
|
||||
InAnyContext(WaitForDialogVisibility(true)),
|
||||
InSameContext(
|
||||
Steps(CheckDialogAcceptButtonFocus(true),
|
||||
CheckDialogAcceptButtonText(), CheckDialogCancelButtonText(),
|
||||
CheckDialogDescription(
|
||||
ash::features::IsWelcomeTourV2Enabled()
|
||||
? IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2
|
||||
: IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT),
|
||||
CheckDialogTitle(ash::features::IsWelcomeTourV2Enabled()
|
||||
? IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2
|
||||
: IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT),
|
||||
PressDialogAcceptButton())),
|
||||
InSameContext(Steps(
|
||||
CheckDialogAcceptButtonFocus(true), CheckDialogAcceptButtonText(),
|
||||
CheckDialogCancelButtonText(),
|
||||
CheckDialogDescription(IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT),
|
||||
CheckDialogTitle(IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT),
|
||||
PressDialogAcceptButton())),
|
||||
|
||||
// Step 1: Shelf.
|
||||
InAnyContext(WaitForHelpBubble()),
|
||||
@ -341,17 +336,18 @@ IN_PROC_BROWSER_TEST_P(WelcomeTourInteractiveUiTest, WelcomeTour) {
|
||||
CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON),
|
||||
PressHelpBubbleDefaultButton())),
|
||||
|
||||
// Step 2: Status area.
|
||||
InAnyContext(WaitForHelpBubble()),
|
||||
InSameContext(
|
||||
Steps(CheckHelpBubbleAnchor(ash::kUnifiedSystemTrayElementId),
|
||||
CheckHelpBubbleBodyText(l10n_util::GetStringUTF16(
|
||||
IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT)),
|
||||
CheckHelpBubbleDefaultButtonFocus(true),
|
||||
CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON),
|
||||
PressHelpBubbleDefaultButton())),
|
||||
// Step 2 in V1: Status area.
|
||||
If([&] { return !ash::features::IsWelcomeTourV3Enabled(); },
|
||||
InAnyContext(
|
||||
Steps(WaitForHelpBubble(),
|
||||
CheckHelpBubbleAnchor(ash::kUnifiedSystemTrayElementId),
|
||||
CheckHelpBubbleBodyText(l10n_util::GetStringUTF16(
|
||||
IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT)),
|
||||
CheckHelpBubbleDefaultButtonFocus(true),
|
||||
CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON),
|
||||
PressHelpBubbleDefaultButton()))),
|
||||
|
||||
// Step 3: Home button.
|
||||
// Step 3 in V1 and step 2 in V3: Home button.
|
||||
InAnyContext(WaitForHelpBubble()),
|
||||
InSameContext(Steps(
|
||||
CheckHelpBubbleAnchor(ash::kHomeButtonElementId),
|
||||
@ -364,7 +360,7 @@ IN_PROC_BROWSER_TEST_P(WelcomeTourInteractiveUiTest, WelcomeTour) {
|
||||
CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON),
|
||||
PressHelpBubbleDefaultButton())),
|
||||
|
||||
// Step 4: Search box.
|
||||
// Step 4 in V1 and step 3 in V3: Search box.
|
||||
InAnyContext(WaitForHelpBubble()),
|
||||
InSameContext(Steps(
|
||||
CheckAppListBubbleVisibility(true),
|
||||
@ -375,8 +371,8 @@ IN_PROC_BROWSER_TEST_P(WelcomeTourInteractiveUiTest, WelcomeTour) {
|
||||
CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON),
|
||||
PressHelpBubbleDefaultButton())),
|
||||
|
||||
// Step 5 in V2: Files app.
|
||||
If([&] { return ash::features::IsWelcomeTourV2Enabled(); },
|
||||
// Step 4 in V3: Files app.
|
||||
If([&] { return ash::features::IsWelcomeTourV3Enabled(); },
|
||||
InAnyContext(
|
||||
Steps(WaitForHelpBubble(), CheckAppListBubbleVisibility(true),
|
||||
CheckHelpBubbleAnchor(ash::kFilesAppElementId),
|
||||
@ -386,7 +382,7 @@ IN_PROC_BROWSER_TEST_P(WelcomeTourInteractiveUiTest, WelcomeTour) {
|
||||
CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON),
|
||||
PressHelpBubbleDefaultButton()))),
|
||||
|
||||
// Step 5 in V1 and step 6 in V2: Settings app.
|
||||
// Step 5: Settings app.
|
||||
InAnyContext(WaitForHelpBubble()),
|
||||
InSameContext(
|
||||
Steps(CheckAppListBubbleVisibility(true),
|
||||
@ -398,7 +394,7 @@ IN_PROC_BROWSER_TEST_P(WelcomeTourInteractiveUiTest, WelcomeTour) {
|
||||
CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON),
|
||||
PressHelpBubbleDefaultButton())),
|
||||
|
||||
// Step 6 in V1 and step 7 in V2: Explore app.
|
||||
// Step 6: Explore app.
|
||||
InAnyContext(WaitForHelpBubble()),
|
||||
InSameContext(Steps(
|
||||
CheckAppListBubbleVisibility(true),
|
||||
@ -410,7 +406,7 @@ IN_PROC_BROWSER_TEST_P(WelcomeTourInteractiveUiTest, WelcomeTour) {
|
||||
IDS_ASH_WELCOME_TOUR_COMPLETE_BUTTON_TEXT),
|
||||
PressHelpBubbleDefaultButton())),
|
||||
|
||||
// Step 7 in V1 and step 8 in V2: Explore app window.
|
||||
// Step 7: Explore app window.
|
||||
InAnyContext(WaitForBrowser()),
|
||||
InSameContext(Steps(WaitForAppListBubbleToHide(),
|
||||
CheckBrowserIsForWebApp(ash::kHelpAppId))));
|
||||
|
@ -4868,11 +4868,12 @@
|
||||
{
|
||||
"name": "Enabled",
|
||||
"enable_features": [
|
||||
"WelcomeTourV2"
|
||||
"WelcomeTourV3"
|
||||
],
|
||||
"disable_features": [
|
||||
"WelcomeTourCounterfactualArm",
|
||||
"WelcomeTourHoldbackArm"
|
||||
"WelcomeTourHoldbackArm",
|
||||
"WelcomeTourV2"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -54,6 +54,7 @@ chromium-metrics-reviews@google.com.
|
||||
<int value="0" label="kHoldback"/>
|
||||
<int value="1" label="kV1"/>
|
||||
<int value="2" label="kV2"/>
|
||||
<int value="3" label="kV3"/>
|
||||
</enum>
|
||||
|
||||
<enum name="WelcomeTourInteraction">
|
||||
@ -75,6 +76,7 @@ chromium-metrics-reviews@google.com.
|
||||
<int value="6" label="kUserNotNewCrossDevice"/>
|
||||
<int value="7" label="kUserTypeNotRegular"/>
|
||||
<int value="8" label="kUserNotNewLocally"/>
|
||||
<int value="9" label="kHoldbackExperimentArm"/>
|
||||
</enum>
|
||||
|
||||
<enum name="WelcomeTourResult">
|
||||
|
Reference in New Issue
Block a user