chromium/chrome/browser/ui/views/user_education/browser_feature_promo_controller_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#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();
}  // namespace

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 that a feature promo can chain into a tutorial.
TEST_F(BrowserFeaturePromoControllerTest, StartsTutorial) {}

// Test that a feature promo can perform a custom action.
TEST_F(BrowserFeaturePromoControllerTest, PerformsCustomAction) {}

// Test that a feature promo can perform a custom action that is the default.
TEST_F(BrowserFeaturePromoControllerTest, PerformsCustomActionAsDefault) {}

// Test that a feature promo does not perform a custom action when the default
// "Got it" button is clicked.
TEST_F(BrowserFeaturePromoControllerTest, DoesNotPerformCustomAction) {}

// Test that a feature promo does not perform a custom action when a non-default
// "Got it" button is clicked.
TEST_F(BrowserFeaturePromoControllerTest, DoesNotPerformDefaultCustomAction) {}

// Test that the promo controller can handle the anchor view disappearing from
// under the bubble during the button callback.
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{};
}  // namespace

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 {
// Somewhere around 2020.
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();

}  // namespace

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[] =;
}  // namespace

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) {}