#include "chrome/browser/ui/views/user_education/browser_feature_promo_controller.h"
#include <optional>
#include <string>
#include <vector>
#include "base/callback_list.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_element_identifiers.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
#include "chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h"
#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/browser/ui/views/user_education/browser_feature_promo_controller.h"
#include "chrome/browser/user_education/user_education_service.h"
#include "chrome/browser/user_education/user_education_service_factory.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/testing_profile.h"
#include "components/feature_engagement/public/configuration.h"
#include "components/feature_engagement/public/feature_list.h"
#include "components/feature_engagement/public/tracker.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "components/strings/grit/components_strings.h"
#include "components/user_education/common/feature_promo_controller.h"
#include "components/user_education/common/feature_promo_data.h"
#include "components/user_education/common/feature_promo_handle.h"
#include "components/user_education/common/feature_promo_registry.h"
#include "components/user_education/common/feature_promo_result.h"
#include "components/user_education/common/feature_promo_specification.h"
#include "components/user_education/common/feature_promo_storage_service.h"
#include "components/user_education/common/help_bubble_factory_registry.h"
#include "components/user_education/common/help_bubble_params.h"
#include "components/user_education/common/product_messaging_controller.h"
#include "components/user_education/common/tutorial.h"
#include "components/user_education/common/tutorial_description.h"
#include "components/user_education/common/tutorial_service.h"
#include "components/user_education/common/user_education_class_properties.h"
#include "components/user_education/common/user_education_features.h"
#include "components/user_education/test/feature_promo_session_test_util.h"
#include "components/user_education/views/help_bubble_factory_views.h"
#include "components/user_education/views/help_bubble_view.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/interaction/element_tracker.h"
#include "ui/base/interaction/expect_call_in_scope.h"
#include "ui/base/interaction/state_observer.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event_modifiers.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/interaction/element_tracker_views.h"
#include "ui/views/interaction/interaction_test_util_views.h"
#include "ui/views/interaction/interactive_views_test.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/view_class_properties.h"
_;
AnyNumber;
NiceMock;
Ref;
Return;
namespace {
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
constexpr char kTestTutorialIdentifier[] = …;
DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(…);
}
FeaturePromoClosedReason;
FeaturePromoController;
FeaturePromoData;
FeaturePromoHandle;
FeaturePromoPolicyData;
FeaturePromoRegistry;
FeaturePromoResult;
FeaturePromoSessionData;
FeaturePromoSpecification;
FeaturePromoStatus;
FeaturePromoStorageService;
HelpBubble;
HelpBubbleArrow;
HelpBubbleFactoryRegistry;
HelpBubbleParams;
HelpBubbleView;
HelpBubbleViews;
TutorialDescription;
class BrowserFeaturePromoControllerTest : public TestWithBrowserView { … };
BubbleCloseCallback;
TEST_F(BrowserFeaturePromoControllerTest, GetForView) { … }
TEST_F(BrowserFeaturePromoControllerTest, NotifyFeatureUsedIfValidIsValid) { … }
TEST_F(BrowserFeaturePromoControllerTest,
FeatureEngagementTrackerEvents_DoNotBlockPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest,
FeatureEngagementTrackerEvents_DoBlockPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, AsksBackendIfPromoShouldBeShown) { … }
TEST_F(BrowserFeaturePromoControllerTest, AsksBackendToShowPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, AsksBackendToShowStartupPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest,
DoesNotAskBackendWhenShowingFromDemoPage) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowsBubble) { … }
TEST_F(BrowserFeaturePromoControllerTest, BubbleBlocksCanShowPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowsStartupBubble) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowStartupBlockedWithAsyncCallback) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowStartupBubbleWithAsyncCallback) { … }
TEST_F(BrowserFeaturePromoControllerTest,
ShowStartupBubbleFailsWhenAlreadyShowing) { … }
TEST_F(BrowserFeaturePromoControllerTest,
ShowStartupBubbleFailsWhenAlreadyPending) { … }
TEST_F(BrowserFeaturePromoControllerTest, CancelPromoBeforeStartup) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowsBubbleAnyContext) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowsBubbleWithFilter) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowsBubbleWithFilterAnyContext) { … }
TEST_F(BrowserFeaturePromoControllerTest,
DismissNonCriticalBubbleInRegion_RegionDoesNotOverlap) { … }
TEST_F(BrowserFeaturePromoControllerTest,
DismissNonCriticalBubbleInRegion_RegionOverlaps) { … }
TEST_F(BrowserFeaturePromoControllerTest,
DismissNonCriticalBubbleInRegion_CriticalPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, RequiredNoticeBlocksPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, NewProfileBlocksPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, SnoozeServiceBlocksPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, PromoEndsWhenRequested) { … }
TEST_F(BrowserFeaturePromoControllerTest,
CloseBubbleDoesNothingIfPromoNotShowing) { … }
TEST_F(BrowserFeaturePromoControllerTest,
CloseBubbleDoesNothingIfDifferentPromoShowing) { … }
TEST_F(BrowserFeaturePromoControllerTest, PromoEndsOnBubbleClosure) { … }
TEST_F(BrowserFeaturePromoControllerTest,
ContinuedPromoDefersBackendDismissed) { … }
TEST_F(BrowserFeaturePromoControllerTest, ContinuedPromoDismissesOnForceEnd) { … }
TEST_F(BrowserFeaturePromoControllerTest, PromoHandleDismissesPromoOnRelease) { … }
TEST_F(BrowserFeaturePromoControllerTest,
PromoHandleDismissesPromoOnOverwrite) { … }
TEST_F(BrowserFeaturePromoControllerTest,
PromoHandleDismissesPromoExactlyOnce) { … }
TEST_F(BrowserFeaturePromoControllerTest,
PromoHandleDismissesPromoAfterMoveConstruction) { … }
TEST_F(BrowserFeaturePromoControllerTest,
PromoHandleDismissesPromoAfterMoveAssignment) { … }
TEST_F(BrowserFeaturePromoControllerTest,
PropertySetOnAnchorViewWhileBubbleOpen) { … }
TEST_F(BrowserFeaturePromoControllerTest, CriticalPromoBlocksNormalPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, CriticalPromoPreemptsNormalPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest, FirstCriticalPromoHasPrecedence) { … }
TEST_F(BrowserFeaturePromoControllerTest, CloseBubbleForCriticalPromo) { … }
TEST_F(BrowserFeaturePromoControllerTest,
CloseBubbleForCriticalPromoDoesNothingAfterClose) { … }
TEST_F(BrowserFeaturePromoControllerTest, ShowNewCriticalPromoAfterClose) { … }
TEST_F(BrowserFeaturePromoControllerTest, FailsIfBubbleIsShowing) { … }
TEST_F(BrowserFeaturePromoControllerTest, StartsTutorial) { … }
TEST_F(BrowserFeaturePromoControllerTest, PerformsCustomAction) { … }
TEST_F(BrowserFeaturePromoControllerTest, PerformsCustomActionAsDefault) { … }
TEST_F(BrowserFeaturePromoControllerTest, DoesNotPerformCustomAction) { … }
TEST_F(BrowserFeaturePromoControllerTest, DoesNotPerformDefaultCustomAction) { … }
TEST_F(BrowserFeaturePromoControllerTest, CustomActionHidesAnchorView) { … }
TEST_F(BrowserFeaturePromoControllerTest, GetAnchorContext) { … }
TEST_F(BrowserFeaturePromoControllerTest, GetAcceleratorProvider) { … }
TEST_F(BrowserFeaturePromoControllerTest, GetFocusHelpBubbleScreenReaderHint) { … }
namespace {
const int kStringWithNoSubstitution = …;
const int kStringWithSingleSubstitution = …;
const int kStringWithMultipleSubstitutions = …;
const int kStringWithPluralSubstitution = …;
const std::u16string kSubstitution1{ … };
const std::u16string kSubstitution2{ … };
const std::u16string kSubstitution3{ … };
}
class BrowserFeaturePromoControllerViewsTest
: public views::test::InteractiveViewsTestT<
BrowserFeaturePromoControllerTest> { … };
TEST_F(BrowserFeaturePromoControllerViewsTest,
BodyTextSubstitution_SingleString) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
BodyTextSubstitution_MultipleStrings) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest, BodyTextSubstitution_Singular) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest, BodyTextSubstitution_Plural) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
TitleTextSubstitution_SingleString) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
TitleTextSubstitution_MultipleStrings) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest, TitleTextSubstitution_Singular) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest, TitleTextSubstitution_Plural) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
ScreenreaderTextSubstitution_Accelerator) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
ScreenreaderTextSubstitution_SingleString) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
ScreenreaderTextSubstitution_MultipleStrings) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
ScreenreaderTextSubstitution_Singular) { … }
TEST_F(BrowserFeaturePromoControllerViewsTest,
ScreenreaderTextSubstitution_Plural) { … }
namespace {
BASE_FEATURE(…);
}
class BrowserFeaturePromoControllerRotatingPromoTest
: public BrowserFeaturePromoControllerViewsTest { … };
TEST_F(BrowserFeaturePromoControllerRotatingPromoTest, OnePromo) { … }
TEST_F(BrowserFeaturePromoControllerRotatingPromoTest, ToastHasDismissButton) { … }
TEST_F(BrowserFeaturePromoControllerRotatingPromoTest, TwoPromosRotating) { … }
TEST_F(BrowserFeaturePromoControllerRotatingPromoTest, SnoozeButtonRepeats) { … }
TEST_F(BrowserFeaturePromoControllerRotatingPromoTest, RotatesPastGaps) { … }
TEST_F(BrowserFeaturePromoControllerRotatingPromoTest,
ContinuesWithNewRotatingPromo) { … }
TEST_F(BrowserFeaturePromoControllerRotatingPromoTest,
ContinuesAfterPromoRemoved) { … }
namespace {
const base::Time kSessionStartTime = …;
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
class StartupCallbackObserver : public ui::test::StateObserver<bool> { … };
DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(…);
class RequiredNotice { … };
class NoticeCallbackObserver : public ui::test::StateObserver<bool> { … };
DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(…);
DEFINE_LOCAL_REQUIRED_NOTICE_IDENTIFIER(…);
}
class BrowserFeaturePromoControllerPriorityTest
: public BrowserFeaturePromoControllerViewsTest { … };
TEST_F(BrowserFeaturePromoControllerPriorityTest,
MultipleStartupPromosHighPriority) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
MultipleStartupPromosHighPriorityToastThenLowPriorityAllowed) { … }
TEST_F(
BrowserFeaturePromoControllerPriorityTest,
MultipleStartupPromosHighPriorityLowPriorityToastAllowedAfterHeavyweight) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
MultipleStartupPromosHighPriorityLowPriorityBlockedAfterHeavyweight) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
RequiredNoticeDelaysLegalNotice) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
LegalNoticeDelaysRequiredNotice) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
MultipleStartupPromosHighThenNoticeThenLow) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
RegularPromoBlockedWhenPromoIsQueued) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
LegalNoticeNotBlockedWhenPromoIsQueued) { … }
TEST_F(BrowserFeaturePromoControllerPriorityTest,
SecondPromoNotCanceledWhenFirstQueuedPromoIsOverridden) { … }
namespace {
BASE_FEATURE(…);
BASE_FEATURE(…);
constexpr char kAppName1[] = …;
constexpr char kAppName2[] = …;
}
class BrowserFeaturePromoControllerReshowTest
: public BrowserFeaturePromoControllerPriorityTest { … };
TEST_F(BrowserFeaturePromoControllerReshowTest, ReshowLegalNoticeWithNoLimit) { … }
TEST_F(BrowserFeaturePromoControllerReshowTest, ReshowLegalNoticeWithLimit) { … }
TEST_F(BrowserFeaturePromoControllerReshowTest, ReshowKeyedPromoNoLimit) { … }
TEST_F(BrowserFeaturePromoControllerReshowTest, ReshowKeyedPromoWithLimit) { … }
class BrowserFeaturePromoControllerPolicyTest
: public BrowserFeaturePromoControllerPriorityTest,
public testing::WithParamInterface<bool> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(BrowserFeaturePromoControllerPolicyTest, TwoLowPriorityPromos) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
ActionableAlertOverridesLowPriority) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest, TwoActionableAlerts) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
LegalNoticeOverridesLowPriority) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
LegalNoticeOverridesActionableAlert) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest, TwoLegalNotices) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
GracePeriodBlocksHeavyweightInV2) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
GracePeriodDoesNotBlockLightweightInV2) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
GracePeriodDoesNotBlockHeavyweightLegalNotice) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
GracePeriodDoesNotBlockActionableAlert) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
GracePeriodBlocksHeavyweightInV2AfterNewSession) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
GracePeriodDoesNotBlocksHeavyweightLongAfterNewSession) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest, CooldownPreventsPromoInV2) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
CooldownDoesNotPreventLightweightPromo) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
LightweightPromoDoesNotTriggerCooldown) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
CooldownDoesNotPreventLegalNotice) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
CooldownDoesNotPreventActionableAlert) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
ExpiredCooldownDoesNotPreventPromo) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
AbortedPromoDoesNotTriggerCooldown) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
AbortedPromoDoesTriggerIndividualCooldown) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
AbortedPromoDoesNotTriggerSnooze) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest, SnoozeButtonDisappearsInV2) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
TutorialSnoozeButtonChangesInV2) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest, IdleAtStartupStillShowsPromo) { … }
TEST_P(BrowserFeaturePromoControllerPolicyTest,
IdleAtStartupPromoBlockedByNewSession) { … }