chromium/ios/chrome/browser/feature_engagement/model/feature_engagement_unittest.mm

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

#import "base/test/scoped_mock_clock_override.h"
#import "base/test/task_environment.h"
#import "components/feature_engagement/public/event_constants.h"
#import "components/feature_engagement/public/feature_constants.h"
#import "components/feature_engagement/public/tracker.h"
#import "components/feature_engagement/test/scoped_iph_feature_list.h"
#import "components/feature_engagement/test/test_tracker.h"
#import "testing/platform_test.h"

namespace {

// The minimum number of times Chrome must be opened in order for the Reading
// List Badge to be shown.
const int kMinChromeOpensRequiredForReadingList = 5;

// The minimum number of times url must be opened in order for the New Tab IPH
// to be displayed.
const int kMinURLOpensRequiredForNewTabIPH = 2;

// The minimum number of times url must be opened in order for the History IPH
// to be displayed.
const int kMinURLOpensRequiredForHistoryOnOverflowMenuIPH = 2;

// The maximum number of times the Password Manager widget promo can be
// triggered.
const int kMaxPasswordManagerWidgetPromoIPH = 3;

}  // namespace

// Unittests related to the triggering of In Product Help features. Anything
// that tests what events cause a feature to trigger should be tested there.
class FeatureEngagementTest : public PlatformTest {
 public:
  FeatureEngagementTest();
  ~FeatureEngagementTest() override;

  std::map<std::string, std::string> BadgedReadingListParams() {
    std::map<std::string, std::string> params;
    params["event_1"] =
        "name:chrome_opened;comparator:>=5;window:90;storage:90";
    params["event_trigger"] =
        "name:badged_reading_list_trigger;comparator:==0;window:1095;storage:"
        "1095";
    params["event_used"] =
        "name:viewed_reading_list;comparator:==0;window:90;storage:90";
    params["session_rate"] = "==0";
    params["availability"] = "any";
    return params;
  }

  std::map<std::string, std::string> BadgedTranslateManualTriggerParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "==0";
    params["event_used"] = "name:triggered_translate_infobar;comparator:==0;"
                           "window:360;storage:360";
    params["event_trigger"] = "name:badged_translate_manual_trigger_trigger;"
                              "comparator:==0;window:360;"
                              "storage:360";
    return params;
  }

  std::map<std::string, std::string> IPHiOSNewTabToolbarItemParams() {
    std::map<std::string, std::string> params;
    params["event_1"] =
        "name:open_url_from_omnibox;comparator:>=2;window:7;storage:7";
    params["event_trigger"] = "name:iph_new_tab_toolbar_item_trigger;"
                              "comparator:==0;window:7;storage:"
                              "7";
    params["event_used"] =
        "name:new_tab_toolbar_item_used;comparator:==0;window:365;storage:365";
    params["session_rate"] = "==0";
    params["availability"] = "any";
    return params;
  }

  std::map<std::string, std::string> IPHiOSPullToRefreshFeatureParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "==0";
    params["event_used"] = "name:pull_to_refresh_feature_used;comparator:==0;"
                           "window:61;storage:61";
    params["event_trigger"] = "name:iph_pull_to_refresh_trigger;comparator:==0;"
                              "window:7;storage:7";
    // Default variation.
    params["event_1"] = "name:iph_pull_to_refresh_trigger;comparator:<1;"
                        "window:61;storage:61";
    params["event_2"] = "name:multi_gesture_refresh_used;"
                        "comparator:>=2;window:7;storage:"
                        "7";
    return params;
  }

  std::map<std::string, std::string>
  IPHiOSTabGridSwipeRightForIncognitoParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "==0";
    params["event_used"] = "name:swipe_right_for_incognito_used;comparator:==0;"
                           "window:61;storage:61";
    params["event_trigger"] =
        "name:swipe_left_for_incognito_trigger;comparator:==0;"
        "window:7;storage:7";
    // Variation that allows >1 maximum impressions.
    params["event_1"] = "name:swipe_left_for_incognito_trigger;comparator:<2;"
                        "window:61;storage:61";
    params["event_2"] = "name:incognito_page_control_tapped;"
                        "comparator:>=2;window:7;storage:"
                        "7";
    return params;
  }

  std::map<std::string, std::string> IPHiOSTabGridToolbarItemParams() {
    std::map<std::string, std::string> params;
    params["event_trigger"] = "name:iph_tab_grid_toolbar_item_trigger;"
                              "comparator:==0;window:7;storage:"
                              "7";
    params["event_used"] =
        "name:tab_grid_toolbar_item_used;comparator:==0;window:365;storage:365";
    params["session_rate"] = "==0";
    params["availability"] = "any";
    return params;
  }

  std::map<std::string, std::string> IPHiOSHistoryOnOverflowMenuParams() {
    std::map<std::string, std::string> params;
    params["event_1"] =
        "name:open_url_from_omnibox;comparator:>=2;window:7;storage:30";
    params["event_trigger"] = "name:history_on_overflow_menu_trigger;"
                              "comparator:==0;window:7;storage:"
                              "7";
    params["event_used"] = "name:history_on_overflow_menu_used;comparator:==0;"
                           "window:365;storage:365";
    params["session_rate"] = "==0";
    params["availability"] = "any";
    return params;
  }

  std::map<std::string, std::string> IPHiOSShareParams() {
    std::map<std::string, std::string> params;
    params["event_trigger"] = "name:share_toolbar_item_trigger;"
                              "comparator:==0;window:7;storage:"
                              "7";
    params["event_used"] =
        "name:share_toolbar_item_used;comparator:==0;window:365;storage:365";
    params["session_rate"] = "==0";
    params["availability"] = "any";
    return params;
  }

  std::map<std::string, std::string> IPHiOSSwipeBackForwardFeatureParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "==0";
    params["event_used"] = "name:swiped_back_forward_used;comparator:==0;"
                           "window:61;storage:61";
    // Variation that allows one impression per month.
    params["event_trigger"] = "name:swipe_back_forward_trigger;comparator:==0;"
                              "window:30;storage:30";
    params["event_1"] = "name:swipe_back_forward_trigger;comparator:<2;"
                        "window:61;storage:61";
    params["event_2"] = "name:back_forward_button_tapped;"
                        "comparator:>=2;window:30;storage:"
                        "30";
    return params;
  }

  std::map<std::string, std::string>
  IPHiOSSwipeToolbarToChangeTabFeatureParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "==0";
    params["event_used"] =
        "name:swipe_toolbar_to_change_tab_used;comparator:==0;"
        "window:61;storage:61";
    params["event_trigger"] =
        "name:swipe_toolbar_to_change_tab_trigger;comparator:==0;"
        "window:61;storage:61";
    params["event_1"] =
        "name:tab_grid_adjacent_tab_tapped;comparator:>=2;window:60;storage:61";
    return params;
  }

  std::map<std::string, std::string> BottomToolbarTipParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "==0";
    params["event_used"] =
        "name:bottom_toolbar_opened;comparator:any;window:90;storage:90";
    params["event_trigger"] =
        "name:bottom_toolbar_trigger;comparator:==0;window:90;storage:90";
    return params;
  }

  std::map<std::string, std::string> LongPressTipParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "<=1";
    params["event_used"] =
        "name:long_press_toolbar_opened;comparator:any;window:90;storage:90";
    params["event_trigger"] =
        "name:long_press_toolbar_trigger;comparator:==0;window:90;storage:90";
    params["event_1"] =
        "name:bottom_toolbar_opened;comparator:>=1;window:90;storage:90";
    return params;
  }

  std::map<std::string, std::string> DefaultSiteViewTipParams() {
    std::map<std::string, std::string> params;
    params["availability"] = "any";
    params["session_rate"] = "<3";
    params["event_used"] =
        "name:default_site_view_used;comparator:==0;window:720;storage:720";
    params["event_trigger"] =
        "name:default_site_view_shown;comparator:==0;window:720;storage:720";
    params["event_1"] =
        "name:desktop_version_requested;comparator:>=3;window:60;storage:60";
    return params;
  }

  base::RepeatingCallback<void(bool)> BoolArgumentQuitClosure() {
    return base::IgnoreArgs<bool>(run_loop_.QuitClosure());
  }

 protected:
  base::test::TaskEnvironment task_environment_;

  base::RunLoop run_loop_;
};

FeatureEngagementTest::FeatureEngagementTest() {}

FeatureEngagementTest::~FeatureEngagementTest() {}

// Tests the Badged Reading List promo triggers if the user has opened Chrome
// enough times.
TEST_F(FeatureEngagementTest, TestBadgedReadingListTriggers) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHBadgedReadingListFeature,
        BadgedReadingListParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that Chrome has been launched enough times for the Badged Reading
  // List to appear.
  for (int index = 0; index < kMinChromeOpensRequiredForReadingList; index++) {
    tracker->NotifyEvent(feature_engagement::events::kChromeOpened);
  }

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHBadgedReadingListFeature));
}

// Tests the Badged Reading List promo does not trigger if the user has opened
// Chrome too few times.
TEST_F(FeatureEngagementTest, TestBadgedReadingListTooFewChromeOpens) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHBadgedReadingListFeature,
        BadgedReadingListParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Only open Chrome once
  tracker->NotifyEvent(feature_engagement::events::kChromeOpened);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHBadgedReadingListFeature));
}

// Tests the Badged Reading List promo does not trigger a second time after it
// has already triggered once
TEST_F(FeatureEngagementTest, TestBadgedReadingListAlreadyUsed) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHBadgedReadingListFeature,
        BadgedReadingListParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that Chrome has been launched enough times for the Badged Reading
  // List to appear.
  for (int index = 0; index < kMinChromeOpensRequiredForReadingList; index++) {
    tracker->NotifyEvent(feature_engagement::events::kChromeOpened);
  }

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHBadgedReadingListFeature));

  // Dismiss IPH.
  tracker->Dismissed(feature_engagement::kIPHBadgedReadingListFeature);

  // The IPH should not trigger the second time
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHBadgedReadingListFeature));
}

// Verifies that the Badged Manual Translate Trigger feature shows only once
// when the triggering conditions are met.
TEST_F(FeatureEngagementTest, TestBadgedTranslateManualTriggerShouldShowOnce) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHBadgedTranslateManualTriggerFeature,
        BadgedTranslateManualTriggerParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHBadgedTranslateManualTriggerFeature));

  // Dismiss IPH.
  tracker->Dismissed(
      feature_engagement::kIPHBadgedTranslateManualTriggerFeature);

  // The IPH should not trigger the second time
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHBadgedTranslateManualTriggerFeature));
}

// Verifies that the New Tab IPH is triggered after the proper conditions
// are met.
TEST_F(FeatureEngagementTest, TestNewTabToolbarItemIPHShouldShow) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSNewTabToolbarItemFeature,
        IPHiOSNewTabToolbarItemParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that url has been opened enough times to meet the trigger
  // condition.
  for (int index = 0; index < kMinURLOpensRequiredForNewTabIPH; index++) {
    tracker->NotifyEvent(feature_engagement::events::kOpenUrlFromOmnibox);
  }

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSNewTabToolbarItemFeature));
}

// Verifies that the New Tab IPH is not triggered.
TEST_F(FeatureEngagementTest, TestNewTabToolbarItemIPHShouldNotShow) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSNewTabToolbarItemFeature,
        IPHiOSNewTabToolbarItemParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  for (int index = 0; index < kMinURLOpensRequiredForNewTabIPH; index++) {
    tracker->NotifyEvent(feature_engagement::events::kOpenUrlFromOmnibox);
  }

  // The kNewTabToolbarItemUsed event will prevent the trigger.
  tracker->NotifyEvent(feature_engagement::events::kNewTabToolbarItemUsed);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSNewTabToolbarItemFeature));
}

// Verifies that the Tab Grid IPH is triggered after the proper conditions
// are met.
TEST_F(FeatureEngagementTest, TestTabGridToolbarItemIPHShouldShow) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSTabGridToolbarItemFeature,
        IPHiOSTabGridToolbarItemParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridToolbarItemFeature));
}

// Verifies that the Tab Grid IPH is not triggered due to being used already.
TEST_F(FeatureEngagementTest, TestTabGridToolbarItemIPHShouldNotShow) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSTabGridToolbarItemFeature,
        IPHiOSTabGridToolbarItemParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that the tab grid item has been used to prevent triggering.
  tracker->NotifyEvent(feature_engagement::events::kTabGridToolbarItemUsed);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridToolbarItemFeature));
}

// Verifies that the pull down to refresh IPH is not triggered
// due to being used already.
TEST_F(FeatureEngagementTest, TestPullDownToRefreshIPHShouldNotShowAfterUsed) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSPullToRefreshFeature,
        IPHiOSPullToRefreshFeatureParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();
  // Ensure that the pull-to-refresh has been used to prevent triggering.
  tracker->NotifyEvent(feature_engagement::events::kIOSPullToRefreshUsed);
  // Make sure other prerequisites are met.
  tracker->NotifyEvent(feature_engagement::events::kIOSMultiGestureRefreshUsed);
  tracker->NotifyEvent(feature_engagement::events::kIOSMultiGestureRefreshUsed);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPullToRefreshFeature));
}

// Verifies that the pull down to refresh IPH only happens after the user uses a
// multi-gesture tap to refresh twice.
TEST_F(FeatureEngagementTest,
       TestTabGridPullDownToRefreshShouldNotShowBeforeTwoMutiGestureRefreshes) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSPullToRefreshFeature,
        IPHiOSPullToRefreshFeatureParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Perform the mult-gesture refresh twice. The IPH should only show after the
  // second refresh.
  tracker->NotifyEvent(feature_engagement::events::kIOSMultiGestureRefreshUsed);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPullToRefreshFeature));
  tracker->NotifyEvent(feature_engagement::events::kIOSMultiGestureRefreshUsed);
  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPullToRefreshFeature));
}

// Verifies that the pull down to refresh IPH would NOT be triggered more than
// allowed by frequency configurations.
TEST_F(
    FeatureEngagementTest,
    TestTabGridPullDownToRefreshIPHShouldBeTriggeredWithinFrequencyConstraints) {
  base::ScopedMockClockOverride scoped_clock;
  scoped_clock.Advance(base::Time::UnixEpoch() - base::Time());
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSPullToRefreshFeature,
        IPHiOSPullToRefreshFeatureParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Assume that the IPH is already triggered.
  tracker->NotifyEvent("iph_pull_to_refresh_trigger");
  // Tap button within the event window.
  scoped_clock.Advance(base::Days(59));
  tracker->NotifyEvent(feature_engagement::events::kIOSMultiGestureRefreshUsed);
  tracker->NotifyEvent(feature_engagement::events::kIOSMultiGestureRefreshUsed);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPullToRefreshFeature));
}

// Verifies that the swipe for incognito IPH on the tab grid is not triggered
// due to being used already.
TEST_F(FeatureEngagementTest,
       TestTabGridSwipeToIncognitoIPHShouldNotShowAfterUsed) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSTabGridSwipeRightForIncognito,
        IPHiOSTabGridSwipeRightForIncognitoParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();
  // Ensure that the swipe for incognito has been used to prevent triggering.
  tracker->NotifyEvent(
      feature_engagement::events::kIOSSwipeRightForIncognitoUsed);
  // Make sure other prerequisites are met.
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridSwipeRightForIncognito));
}

// Verifies that the swipe for incognito IPH only happens after the user taps to
// go to incognito twice.
TEST_F(FeatureEngagementTest,
       TestTabGridSwipeToIncognitoIPHShouldNotShowBeforeTwoTapsToIncognito) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSTabGridSwipeRightForIncognito,
        IPHiOSTabGridSwipeRightForIncognitoParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Tap the page control to go to incognito twice. The IPH should only show
  // after the second tap.
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridSwipeRightForIncognito));
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridSwipeRightForIncognito));
}

// Verifies that the swipe for incognito IPH would NOT be triggered more than
// allowed by frequency configurations.
TEST_F(
    FeatureEngagementTest,
    TestTabGridSwipeToIncognitoIPHShouldBeTriggeredWithinFrequencyConstraints) {
  base::ScopedMockClockOverride scoped_clock;
  scoped_clock.Advance(base::Time::UnixEpoch() - base::Time());
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSTabGridSwipeRightForIncognito,
        IPHiOSTabGridSwipeRightForIncognitoParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Assume that the IPH is already triggered.
  tracker->NotifyEvent("swipe_left_for_incognito_trigger");
  // Tap button to go to incognito immediately; the IPH should NOT be triggered.
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridSwipeRightForIncognito));
  // Do so 7 days later; the IPH should be triggered since it has been 7 days
  // after last trigger.
  scoped_clock.Advance(base::Days(7));
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridSwipeRightForIncognito));
  tracker->Dismissed(feature_engagement::kIPHiOSTabGridSwipeRightForIncognito);
  // Do so 7 days later. The IPH should NOT be triggered since it has already
  // been triggered twice within the last 61 days.
  scoped_clock.Advance(base::Days(7));
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  tracker->NotifyEvent(
      feature_engagement::events::kIOSIncognitoPageControlTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSTabGridSwipeRightForIncognito));
}

// Verifies that the swipe back/forward IPH is not triggered
// due to being used already.
TEST_F(FeatureEngagementTest, TestSwipeBackForwardIPHShouldNotShowAfterUsed) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSSwipeBackForwardFeature,
        IPHiOSSwipeBackForwardFeatureParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();
  // Ensure that the swipe back/forward gesture has been used to prevent
  // triggering.
  tracker->NotifyEvent(feature_engagement::events::kIOSSwipeBackForwardUsed);
  // Make sure other prerequisites are met.
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSSwipeBackForwardFeature));
}

// Verifies that the swipe back/forward IPH only happens after the user taps to
// go back or forward twice.
TEST_F(FeatureEngagementTest,
       TestSwipeBackForwardIPHShouldNotShowBeforeTwoTapsToIncognito) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSSwipeBackForwardFeature,
        IPHiOSSwipeBackForwardFeatureParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Tap the back/forward button to navigate pages twice. The IPH should only
  // show after the second tap.
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSSwipeBackForwardFeature));
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSSwipeBackForwardFeature));
}

// Verifies that the swipe back/forward IPH would NOT be triggered more than
// allowed by frequency configurations.
TEST_F(FeatureEngagementTest,
       TestSwipeBackForwardIPHShouldBeTriggeredWithinFrequencyConstraints) {
  base::ScopedMockClockOverride scoped_clock;
  scoped_clock.Advance(base::Time::UnixEpoch() - base::Time());
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSSwipeBackForwardFeature,
        IPHiOSSwipeBackForwardFeatureParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Assume that the IPH is already triggered.
  tracker->NotifyEvent("swipe_back_forward_trigger");
  // Tap button to go to incognito immediately; the IPH should NOT be triggered.
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSSwipeBackForwardFeature));
  // Do so 7 days later; the IPH should NOT be triggered.
  scoped_clock.Advance(base::Days(7));
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  tracker->NotifyEvent(feature_engagement::events::kIOSBackForwardButtonTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSSwipeBackForwardFeature));
  // Check back 30 days after initial trigger.
  scoped_clock.Advance(base::Days(23));
  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSSwipeBackForwardFeature));
}

// Verifies that the swipe on toolbar IPH is not triggered after the user has
// swiped on the toolbar to switch tab.
TEST_F(FeatureEngagementTest,
       TestSwipeToolbarToChangeTabIPHShouldNotShowAfterUsed) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSSwipeToolbarToChangeTabFeature,
        IPHiOSSwipeToolbarToChangeTabFeatureParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();
  // Ensure that the swipe back/forward gesture has been used to prevent
  // triggering.
  tracker->NotifyEvent(
      feature_engagement::events::kIOSSwipeToolbarToChangeTabUsed);
  // Make sure other prerequisites are met.
  tracker->NotifyEvent(
      feature_engagement::events::kIOSTabGridAdjacentTabTapped);
  tracker->NotifyEvent(
      feature_engagement::events::kIOSTabGridAdjacentTabTapped);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSSwipeToolbarToChangeTabFeature));
}

// Verifies that the History IPH is triggered after the proper conditions
// are met.
TEST_F(FeatureEngagementTest, TestHistoryOnOverflowMenuIPHShouldShow) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSHistoryOnOverflowMenuFeature,
        IPHiOSHistoryOnOverflowMenuParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that url event is met.
  for (int index = 0; index < kMinURLOpensRequiredForHistoryOnOverflowMenuIPH;
       index++) {
    tracker->NotifyEvent(feature_engagement::events::kOpenUrlFromOmnibox);
  }

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSHistoryOnOverflowMenuFeature));
}

// Verifies that the History IPH is not triggered due to being used already.
TEST_F(FeatureEngagementTest,
       TestHistoryOnOverflowMenuIPHShouldNotShowDueToUsage) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSHistoryOnOverflowMenuFeature,
        IPHiOSHistoryOnOverflowMenuParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that the history has been used to prevent triggering the IPH.
  tracker->NotifyEvent(feature_engagement::events::kHistoryOnOverflowMenuUsed);

  // Ensure that the url event condition is met.
  for (int index = 0; index < kMinURLOpensRequiredForHistoryOnOverflowMenuIPH;
       index++) {
    tracker->NotifyEvent(feature_engagement::events::kOpenUrlFromOmnibox);
  }

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSHistoryOnOverflowMenuFeature));
}

// Verifies that the History IPH is not triggered due to not enough urls have
// been opened.
TEST_F(FeatureEngagementTest,
       TestHistoryOnOverflowMenuIPHShouldNotShowDueToNotEnoughUrls) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSHistoryOnOverflowMenuFeature,
        IPHiOSHistoryOnOverflowMenuParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that < `kMinURLOpensRequiredForHistoryOnOverflowMenuIPH` urls have
  // been opened.
  tracker->NotifyEvent(feature_engagement::events::kOpenUrlFromOmnibox);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSHistoryOnOverflowMenuFeature));
}

// Verifies that the Share IPH is triggered after the proper conditions
// are met.
TEST_F(FeatureEngagementTest, TestShareToolbarItemIPHShouldShow) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSShareToolbarItemFeature,
        IPHiOSShareParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSShareToolbarItemFeature));
}

// Verifies that the Share IPH is not triggered due to being used already.
TEST_F(FeatureEngagementTest, TestShareToolbarItemIPHShouldNotShowDueToUsage) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHiOSShareToolbarItemFeature,
        IPHiOSShareParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that the share has been used to prevent triggering the IPH.
  tracker->NotifyEvent(feature_engagement::events::kShareToolbarItemUsed);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSShareToolbarItemFeature));
}

// Verifies that the bottom toolbar tip triggers.
TEST_F(FeatureEngagementTest, TestBottomToolbarTipTriggers) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHBottomToolbarTipFeature,
        BottomToolbarTipParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHBottomToolbarTipFeature));
}

// Verifies that the longpress toolbar tip is displayed after the bottom toolbar
// tip is opened
TEST_F(FeatureEngagementTest, TestLongPressTipAppearAfterBottomToolbar) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHLongPressToolbarTipFeature,
        LongPressTipParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Open the bottom toolbar.
  tracker->NotifyEvent(feature_engagement::events::kBottomToolbarOpened);

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHLongPressToolbarTipFeature));
}

// Verifies that the IPH for Request desktop is triggered after 3 requests of
// the desktop version of a website.
TEST_F(FeatureEngagementTest, TestRequestDesktopTip) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHDefaultSiteViewFeature,
        DefaultSiteViewTipParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Request the desktop version of a website, this should not trigger the tip.
  tracker->NotifyEvent(feature_engagement::events::kDesktopVersionRequested);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHDefaultSiteViewFeature));

  // Second time, still no tip.
  tracker->NotifyEvent(feature_engagement::events::kDesktopVersionRequested);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHDefaultSiteViewFeature));

  // Third time, this should trigger the tip.
  tracker->NotifyEvent(feature_engagement::events::kDesktopVersionRequested);
  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHDefaultSiteViewFeature));

  tracker->Dismissed(feature_engagement::kIPHDefaultSiteViewFeature);

  // Fourth time, the tip should no longer trigger.
  tracker->NotifyEvent(feature_engagement::events::kDesktopVersionRequested);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHDefaultSiteViewFeature));
}

// Verifies that the IPH for Request desktop is not triggered if the user
// interacted with the default page mode.
TEST_F(FeatureEngagementTest,
       TestRequestDesktopTipAfterChangingDefaultPageMode) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeaturesWithParameters(
      {{feature_engagement::kIPHDefaultSiteViewFeature,
        DefaultSiteViewTipParams()}});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Interact with the default page mode.
  tracker->NotifyEvent(feature_engagement::events::kDefaultSiteViewUsed);

  // Request the desktop version of a website, this should not trigger the tip.
  tracker->NotifyEvent(feature_engagement::events::kDesktopVersionRequested);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHDefaultSiteViewFeature));

  // Second time, still no tip.
  tracker->NotifyEvent(feature_engagement::events::kDesktopVersionRequested);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHDefaultSiteViewFeature));

  // Third time, the tip should still not be shown.
  tracker->NotifyEvent(feature_engagement::events::kDesktopVersionRequested);
  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHDefaultSiteViewFeature));
}

// Verifies that the Password Manager widget promo IPH can't be triggered again
// after being triggered three times.
TEST_F(FeatureEngagementTest, TestPasswordManagerPromoIPHReachedTriggerLimit) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitWithExistingFeatures(
      {feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  // Ensure that the Password Manager widget promo has been triggered three
  // times.
  for (int index = 0; index < kMaxPasswordManagerWidgetPromoIPH; index++) {
    tracker->NotifyEvent(
        feature_engagement::events::kPasswordManagerWidgetPromoTriggered);
  }

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature));
}

// Verifies that the Password Manager widget promo IPH is not triggered again
// after the widget was used at least once.
TEST_F(FeatureEngagementTest, TestPasswordManagerPromoIPHReachedUsedLimit) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitWithExistingFeatures(
      {feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature));
  tracker->Dismissed(
      feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature);

  // Interact with the Password Manager widget.
  tracker->NotifyEvent(
      feature_engagement::events::kPasswordManagerWidgetPromoUsed);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature));
}

// Verifies that the Password Manager widget promo IPH is not triggered again
// after the promo was closed by the user.
TEST_F(FeatureEngagementTest, TestPasswordManagerPromoIPHWasClosed) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitWithExistingFeatures(
      {feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature));
  tracker->Dismissed(
      feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature);

  // Close the Password Manager widget promo.
  tracker->NotifyEvent(
      feature_engagement::events::kPasswordManagerWidgetPromoClosed);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature));
}

// Verifies that the Overflow Menu Customization promo IPH is only triggered
// after the user has chosen items that are offscreen by default at least twice.
TEST_F(FeatureEngagementTest, TestOverflowMenuCustomizationPromoShows) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitWithExistingFeatures(
      {feature_engagement::kIPHiOSOverflowMenuCustomizationFeature});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSOverflowMenuCustomizationFeature));

  tracker->NotifyEvent(
      feature_engagement::events::kIOSOverflowMenuOffscreenItemUsed);
  tracker->NotifyEvent(
      feature_engagement::events::kIOSOverflowMenuOffscreenItemUsed);

  EXPECT_TRUE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSOverflowMenuCustomizationFeature));
  tracker->Dismissed(
      feature_engagement::kIPHiOSOverflowMenuCustomizationFeature);
}

// Verifies that the Overflow Menu Customization promo IPH is not triggered
// after the user has used the customization screen.
TEST_F(FeatureEngagementTest,
       TestOverflowMenuCustomizationPromoDoesntShowIfCustomizationUsed) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitWithExistingFeatures(
      {feature_engagement::kIPHiOSOverflowMenuCustomizationFeature});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSOverflowMenuCustomizationFeature));

  // Using offscreen items twice should trigger the promo...
  tracker->NotifyEvent(
      feature_engagement::events::kIOSOverflowMenuOffscreenItemUsed);
  tracker->NotifyEvent(
      feature_engagement::events::kIOSOverflowMenuOffscreenItemUsed);

  EXPECT_TRUE(tracker->WouldTriggerHelpUI(
      feature_engagement::kIPHiOSOverflowMenuCustomizationFeature));

  // Unless the user has also used customization already.
  tracker->NotifyEvent(
      feature_engagement::events::kIOSOverflowMenuCustomizationUsed);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSOverflowMenuCustomizationFeature));
}

// Verifies that the Enhanced Safe Browsing Inline Promo IPH is triggered when
// notified and not triggered when the promo is closed by the user.
TEST_F(FeatureEngagementTest, TestEnhancedSafeBrowsingInlinePromoIsShown) {
  feature_engagement::test::ScopedIphFeatureList list;
  list.InitAndEnableFeatures(
      {feature_engagement::kIPHiOSInlineEnhancedSafeBrowsingPromoFeature});

  std::unique_ptr<feature_engagement::Tracker> tracker =
      feature_engagement::CreateTestTracker();
  // Make sure tracker is initialized.
  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
  run_loop_.Run();

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSInlineEnhancedSafeBrowsingPromoFeature));

  // Executing one of the pre-determined events should trigger the promo...
  tracker->NotifyEvent(
      feature_engagement::events::kEnhancedSafeBrowsingPromoCriterionMet);

  EXPECT_TRUE(tracker->WouldTriggerHelpUI(
      feature_engagement::kIPHiOSInlineEnhancedSafeBrowsingPromoFeature));

  // The promo should not be displayed if the user taps the promo's 'x' button.
  tracker->NotifyEvent(
      feature_engagement::events::kInlineEnhancedSafeBrowsingPromoClosed);

  EXPECT_FALSE(tracker->ShouldTriggerHelpUI(
      feature_engagement::kIPHiOSInlineEnhancedSafeBrowsingPromoFeature));
}