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

#include "components/search_engines/ui_utils.h"

#include <memory>
#include <string>
#include <vector>

#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_data.h"
#include "components/search_engines/template_url_data_util.h"
#include "components/search_engines/template_url_service.h"
#include "components/search_engines/template_url_service_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/icu/source/common/unicode/locid.h"
#include "third_party/icu/source/i18n/unicode/coll.h"

namespace {

// Helper function to create a TemplateURL with specified properties
std::unique_ptr<TemplateURL> CreateTemplateURL(const std::u16string& short_name,
                                               const std::u16string& keyword,
                                               const std::string& url,
                                               bool created_by_policy = false,
                                               int prepopulate_id = 0) {
  TemplateURLData data;
  data.SetShortName(short_name);
  data.SetKeyword(keyword);
  data.SetURL(url);
  data.is_active = TemplateURLData::ActiveStatus::kTrue;
  data.policy_origin = created_by_policy
                           ? TemplateURLData::PolicyOrigin::kSiteSearch
                           : TemplateURLData::PolicyOrigin::kNoPolicy;
  data.prepopulate_id = prepopulate_id;
  return std::make_unique<TemplateURL>(data);
}

}  // namespace

// Test fixture for the internal sorting logic
class OrderTemplateUrlsByManagedAndAlphabeticallyTest : public testing::Test {
 public:
  OrderTemplateUrlsByManagedAndAlphabeticallyTest() = default;
  ~OrderTemplateUrlsByManagedAndAlphabeticallyTest() override = default;

 protected:
  void SetUp() override {
    comparator_ = std::make_unique<
        internal::OrderTemplateUrlsByManagedAndAlphabetically>();
  }

  std::unique_ptr<internal::OrderTemplateUrlsByManagedAndAlphabetically>
      comparator_;
};

// Test basic alphabetical sorting
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest,
       BasicAlphabeticalSorting) {
  auto google = CreateTemplateURL(u"Google", u"google.com",
                                  "https://google.com/search?q={searchTerms}");
  auto bing = CreateTemplateURL(u"Bing", u"bing.com",
                                "https://bing.com/search?q={searchTerms}");
  auto yahoo = CreateTemplateURL(u"Yahoo", u"yahoo.com",
                                 "https://yahoo.com/search?q={searchTerms}");

  // Bing should come before Google, Google before Yahoo
  EXPECT_TRUE((*comparator_)(bing.get(), google.get()));
  EXPECT_TRUE((*comparator_)(google.get(), yahoo.get()));
  EXPECT_TRUE((*comparator_)(bing.get(), yahoo.get()));

  // Reverse comparisons should be false
  EXPECT_FALSE((*comparator_)(google.get(), bing.get()));
  EXPECT_FALSE((*comparator_)(yahoo.get(), google.get()));
  EXPECT_FALSE((*comparator_)(yahoo.get(), bing.get()));
}

// Test that managed engines come before non-managed engines
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest, ManagedEnginesFirst) {
  auto managed_yahoo = CreateTemplateURL(
      u"Yahoo", u"yahoo.com", "https://yahoo.com/search?q={searchTerms}", true);
  auto regular_bing = CreateTemplateURL(
      u"Bing", u"bing.com", "https://bing.com/search?q={searchTerms}", false);

  // Even though Bing comes before Yahoo alphabetically, managed Yahoo should
  // come first
  EXPECT_TRUE((*comparator_)(managed_yahoo.get(), regular_bing.get()));
  EXPECT_FALSE((*comparator_)(regular_bing.get(), managed_yahoo.get()));
}

// Test sorting within managed and non-managed groups
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest, SortingWithinGroups) {
  auto managed_google =
      CreateTemplateURL(u"Google", u"google.com",
                        "https://google.com/search?q={searchTerms}", true);
  auto managed_bing = CreateTemplateURL(
      u"Bing", u"bing.com", "https://bing.com/search?q={searchTerms}", true);
  auto regular_yahoo =
      CreateTemplateURL(u"Yahoo", u"yahoo.com",
                        "https://yahoo.com/search?q={searchTerms}", false);
  auto regular_ask = CreateTemplateURL(
      u"Ask", u"ask.com", "https://ask.com/search?q={searchTerms}", false);

  // Within managed group: Bing before Google
  EXPECT_TRUE((*comparator_)(managed_bing.get(), managed_google.get()));

  // Within regular group: Ask before Yahoo
  EXPECT_TRUE((*comparator_)(regular_ask.get(), regular_yahoo.get()));

  // Managed engines before regular engines
  EXPECT_TRUE((*comparator_)(managed_google.get(), regular_ask.get()));
  EXPECT_TRUE((*comparator_)(managed_bing.get(), regular_yahoo.get()));
}

// Test case-insensitive sorting
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest,
       CaseInsensitiveSorting) {
  auto lower_google = CreateTemplateURL(
      u"google", u"google.com", "https://google.com/search?q={searchTerms}");
  auto upper_bing = CreateTemplateURL(
      u"BING", u"bing.com", "https://bing.com/search?q={searchTerms}");

  // Should still sort alphabetically regardless of case
  EXPECT_TRUE((*comparator_)(upper_bing.get(), lower_google.get()));
  EXPECT_FALSE((*comparator_)(lower_google.get(), upper_bing.get()));
}

// Test Unicode string handling
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest, UnicodeStringHandling) {
  auto ascii_engine = CreateTemplateURL(
      u"Google", u"google.com", "https://google.com/search?q={searchTerms}");
  auto unicode_engine = CreateTemplateURL(
      u"Яндекс", u"yandex.ru", "https://yandex.ru/search?q={searchTerms}");
  auto accented_engine = CreateTemplateURL(
      u"Écosía", u"ecosia.org", "https://ecosia.org/search?q={searchTerms}");

  // The exact sorting order may depend on locale, but the function should not
  // crash and should produce consistent results
  bool result1 = (*comparator_)(ascii_engine.get(), unicode_engine.get());
  bool result2 = (*comparator_)(unicode_engine.get(), ascii_engine.get());
  EXPECT_NE(result1, result2);  // One should be true, the other false

  bool result3 = (*comparator_)(ascii_engine.get(), accented_engine.get());
  bool result4 = (*comparator_)(accented_engine.get(), ascii_engine.get());
  EXPECT_NE(result3, result4);
}

// Test fallback to keyword when short names are identical
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest, FallbackToKeyword) {
  auto engine1 = CreateTemplateURL(
      u"Search", u"search1.com", "https://search1.com/search?q={searchTerms}");
  auto engine2 = CreateTemplateURL(
      u"Search", u"search2.com", "https://search2.com/search?q={searchTerms}");

  // Should sort by keyword when short names are identical
  EXPECT_TRUE((*comparator_)(engine1.get(), engine2.get()));
  EXPECT_FALSE((*comparator_)(engine2.get(), engine1.get()));
}

// Test buffer overflow protection in GetShortNameSortKey
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest,
       BufferOverflowProtection) {
  // Create a very long string that would exceed the 1000 byte buffer
  std::u16string very_long_name;
  // Use multi-byte Unicode characters to more easily exceed buffer
  for (int i = 0; i < 500; i++) {
    very_long_name += u"测试";  // Each character is 3 bytes in UTF-8
  }

  auto long_name_engine =
      CreateTemplateURL(very_long_name, u"longname.com",
                        "https://longname.com/search?q={searchTerms}");
  auto short_name_engine = CreateTemplateURL(
      u"Short", u"short.com", "https://short.com/search?q={searchTerms}");

  // Should not crash even with very long names
  bool result1 =
      (*comparator_)(long_name_engine.get(), short_name_engine.get());
  bool result2 =
      (*comparator_)(short_name_engine.get(), long_name_engine.get());

  // Results should be consistent (one true, one false)
  EXPECT_NE(result1, result2);

  // Test that GetShortNameSortKey doesn't crash with very long strings
  std::string sort_key =
      comparator_->GetShortNameSortKeyForTesting(very_long_name);
  EXPECT_FALSE(sort_key.empty());

  // The sort key should be truncated but still valid
  EXPECT_LT(sort_key.length(), 1000u);
}

// Test GetShortNameSortKey with various Unicode scenarios
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest,
       GetShortNameSortKeyUnicode) {
  // Test with ASCII
  std::string ascii_key = comparator_->GetShortNameSortKeyForTesting(u"Google");
  EXPECT_FALSE(ascii_key.empty());

  // Test with Unicode
  std::string unicode_key =
      comparator_->GetShortNameSortKeyForTesting(u"Яндекс");
  EXPECT_FALSE(unicode_key.empty());

  // Test with accented characters
  std::string accented_key =
      comparator_->GetShortNameSortKeyForTesting(u"Écosía");
  EXPECT_FALSE(accented_key.empty());

  // Test with empty string
  std::string empty_key = comparator_->GetShortNameSortKeyForTesting(u"");
  // Empty string should produce empty or very short key
  EXPECT_LE(empty_key.length(), 1u);
}

// Test edge cases with special characters
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest, SpecialCharacters) {
  auto numeric_engine =
      CreateTemplateURL(u"123Search", u"123search.com",
                        "https://123search.com/search?q={searchTerms}");
  auto symbol_engine =
      CreateTemplateURL(u"@Search", u"atsearch.com",
                        "https://atsearch.com/search?q={searchTerms}");
  auto mixed_engine =
      CreateTemplateURL(u"A1@Search", u"a1search.com",
                        "https://a1search.com/search?q={searchTerms}");

  // Should handle special characters without crashing
  bool result1 = (*comparator_)(numeric_engine.get(), symbol_engine.get());
  bool result2 = (*comparator_)(symbol_engine.get(), mixed_engine.get());
  bool result3 = (*comparator_)(numeric_engine.get(), mixed_engine.get());

  // Results should be consistent
  EXPECT_EQ(result1,
            !(*comparator_)(symbol_engine.get(), numeric_engine.get()));
  EXPECT_EQ(result2, !(*comparator_)(mixed_engine.get(), symbol_engine.get()));
  EXPECT_EQ(result3, !(*comparator_)(mixed_engine.get(), numeric_engine.get()));
}

// Test with extremely long Unicode sequences that could cause buffer issues
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest, ExtremelyLongUnicode) {
  // Create string with combining characters that could expand during
  // normalization
  std::u16string base_char = u"a";
  std::u16string combining_chars;
  for (int i = 0; i < 200; i++) {
    combining_chars += u"\u0301";  // Combining acute accent
  }
  std::u16string extreme_string = base_char + combining_chars;

  auto extreme_engine =
      CreateTemplateURL(extreme_string, u"extreme.com",
                        "https://extreme.com/search?q={searchTerms}");
  auto normal_engine = CreateTemplateURL(
      u"Normal", u"normal.com", "https://normal.com/search?q={searchTerms}");

  // Should handle extreme Unicode without crashing
  EXPECT_NO_FATAL_FAILURE({
    bool result = (*comparator_)(extreme_engine.get(), normal_engine.get());
    (void)result;  // Suppress unused variable warning
  });

  // GetShortNameSortKey should handle this without crashing
  EXPECT_NO_FATAL_FAILURE({
    std::string sort_key =
        comparator_->GetShortNameSortKeyForTesting(extreme_string);
    EXPECT_LE(sort_key.length(), 1000u);
  });
}

// Test with exact buffer boundary conditions
TEST_F(OrderTemplateUrlsByManagedAndAlphabeticallyTest,
       BufferBoundaryConditions) {
  // Test string that should be exactly at buffer limit
  std::u16string near_limit_string;
  // Create a string that when converted to sort key approaches the 1000 byte
  // limit
  for (int i = 0; i < 100; i++) {
    near_limit_string += u"abcdefghij";  // 10 ASCII chars per iteration
  }

  auto near_limit_engine =
      CreateTemplateURL(near_limit_string, u"nearlimit.com",
                        "https://nearlimit.com/search?q={searchTerms}");
  auto normal_engine = CreateTemplateURL(
      u"Normal", u"normal.com", "https://normal.com/search?q={searchTerms}");

  // Should handle near-limit strings without issues
  EXPECT_NO_FATAL_FAILURE({
    bool result = (*comparator_)(near_limit_engine.get(), normal_engine.get());
    std::string sort_key =
        comparator_->GetShortNameSortKeyForTesting(near_limit_string);
    EXPECT_FALSE(sort_key.empty());
    EXPECT_LT(sort_key.length(), 1000u);
    (void)result;  // Suppress unused variable warning
  });
}

class OrderTemplateUrlsByPrepopulatedAndManagedAndAlphabetically
    : public testing::Test {};

// Test that regional prepopulated engines are added first, then non-regional
// ones, then custom ones.
TEST_F(OrderTemplateUrlsByPrepopulatedAndManagedAndAlphabetically,
       PrepopulatedEnginesFirst) {
  std::unique_ptr<TemplateURLData> bing_data =
      TemplateURLDataFromPrepopulatedEngine(TemplateURLPrepopulateData::bing);

  auto bing_engine = CreateTemplateURL(
      u"Bing", u"bing.com", "https://bing.com/search?q={searchTerms}",
      /*created_by_policy=*/false, bing_data->prepopulate_id);
  auto prepopulated_engine = CreateTemplateURL(
      u"CustomPrepop", u"customprepop.com",
      "https://customprepop.com/search?q={searchTerms}",
      /*created_by_policy=*/false, bing_data->prepopulate_id + 1);
  auto custom_engine =
      CreateTemplateURL(u"A-Engine", u"aengine.com",
                        "https://aengine.com/search?q={searchTerms}");

  std::vector<std::unique_ptr<TemplateURLData>> prepopulated_urls;
  prepopulated_urls.push_back(std::move(bing_data));

  auto comparator = std::make_unique<
      internal::OrderTemplateUrlsByPrepopulatedAndManagedAndAlphabetically>(
      std::move(prepopulated_urls));

  // Even though the alphabetical order is different, the prepopulated engines
  // are added first.
  EXPECT_TRUE((*comparator)(bing_engine.get(), prepopulated_engine.get()));
  EXPECT_FALSE((*comparator)(prepopulated_engine.get(), bing_engine.get()));

  EXPECT_TRUE((*comparator)(bing_engine.get(), custom_engine.get()));
  EXPECT_FALSE((*comparator)(custom_engine.get(), bing_engine.get()));

  EXPECT_TRUE((*comparator)(prepopulated_engine.get(), custom_engine.get()));
  EXPECT_FALSE((*comparator)(custom_engine.get(), prepopulated_engine.get()));
}

// Test that prepopulated engines are added in the order of
// `prepopulated_engines`.
TEST_F(OrderTemplateUrlsByPrepopulatedAndManagedAndAlphabetically,
       PrepopulatedEnginesSorted) {
  std::unique_ptr<TemplateURLData> yahoo_data =
      TemplateURLDataFromPrepopulatedEngine(TemplateURLPrepopulateData::yahoo);
  std::unique_ptr<TemplateURLData> bing_data =
      TemplateURLDataFromPrepopulatedEngine(TemplateURLPrepopulateData::bing);
  std::unique_ptr<TemplateURLData> google_data =
      TemplateURLDataFromPrepopulatedEngine(TemplateURLPrepopulateData::google);

  auto yahoo_engine = CreateTemplateURL(
      u"Yahoo", u"yahoo.com", "https://yahoo.com/search?q={searchTerms}",
      /*created_by_policy=*/false, yahoo_data->prepopulate_id);
  auto bing_engine = CreateTemplateURL(
      u"Bing", u"bing.com", "https://bing.com/search?q={searchTerms}",
      /*created_by_policy=*/false, bing_data->prepopulate_id);
  auto google_engine = CreateTemplateURL(
      u"Google", u"google.com", "https://google.com/search?q={searchTerms}",
      /*created_by_policy=*/false, google_data->prepopulate_id);

  std::vector<std::unique_ptr<TemplateURLData>> prepopulated_urls;
  prepopulated_urls.push_back(std::move(yahoo_data));
  prepopulated_urls.push_back(std::move(bing_data));
  prepopulated_urls.push_back(std::move(google_data));

  auto comparator = std::make_unique<
      internal::OrderTemplateUrlsByPrepopulatedAndManagedAndAlphabetically>(
      std::move(prepopulated_urls));

  // Even though the alphabetical order is different, the engines are added in
  // the order of `prepopulated_urls`.
  EXPECT_TRUE((*comparator)(yahoo_engine.get(), bing_engine.get()));
  EXPECT_FALSE((*comparator)(bing_engine.get(), yahoo_engine.get()));

  EXPECT_TRUE((*comparator)(yahoo_engine.get(), google_engine.get()));
  EXPECT_FALSE((*comparator)(google_engine.get(), yahoo_engine.get()));

  EXPECT_TRUE((*comparator)(bing_engine.get(), google_engine.get()));
  EXPECT_FALSE((*comparator)(google_engine.get(), bing_engine.get()));
}

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
class SortAndFilterRecentlyVisitedURLsTest : public testing::Test {
 protected:
  std::unique_ptr<TemplateURL> CreateSearchEngineWithVisitTime(
      base::Time last_visited) {
    TemplateURLData data;
    data.SetShortName(u"Test Engine");
    data.SetKeyword(u"test");
    data.SetURL("https://test.com/search?q={searchTerms}");
    data.last_visited = last_visited;
    return std::make_unique<TemplateURL>(data);
  }
};

// Test that search engines visited longer than 2 days ago are filtered out.
TEST_F(SortAndFilterRecentlyVisitedURLsTest, FiltersOutOldVisits) {
  base::Time now = base::Time::Now();

  auto engine_recent_1 = CreateSearchEngineWithVisitTime(now - base::Hours(1));
  auto engine_recent_2 = CreateSearchEngineWithVisitTime(now - base::Days(1));
  auto engine_expired_1 =
      CreateSearchEngineWithVisitTime(now - base::Days(2) - base::Seconds(1));
  auto engine_expired_2 = CreateSearchEngineWithVisitTime(now - base::Days(10));

  TemplateURL::TemplateURLVector recently_visited = {
      engine_expired_1.get(), engine_recent_1.get(), engine_expired_2.get(),
      engine_recent_2.get()};

  internal::SortAndFilterRecentlyVisitedURLs(recently_visited);

  // Only the two non-expired engines should remain, sorted by recency.
  ASSERT_EQ(recently_visited.size(), 2u);
  EXPECT_EQ(recently_visited[0], engine_recent_1.get());
  EXPECT_EQ(recently_visited[1], engine_recent_2.get());
}

// Test that only the top 3 (kMaxCustomSearchEngines) most recently visited
// engines are kept.
TEST_F(SortAndFilterRecentlyVisitedURLsTest, LimitsToMaxThreeEngines) {
  base::Time now = base::Time::Now();

  // Create 5 engines, all within the valid 2-day window, with distinct visit
  // times.
  auto engine_1st = CreateSearchEngineWithVisitTime(now - base::Minutes(5));
  auto engine_2nd = CreateSearchEngineWithVisitTime(now - base::Hours(1));
  auto engine_3rd = CreateSearchEngineWithVisitTime(now - base::Hours(12));
  auto engine_4th = CreateSearchEngineWithVisitTime(now - base::Days(1));
  auto engine_5th = CreateSearchEngineWithVisitTime(now - base::Hours(36));

  // Push them in an unsorted order
  TemplateURL::TemplateURLVector recently_visited = {
      engine_4th.get(), engine_2nd.get(), engine_5th.get(), engine_1st.get(),
      engine_3rd.get()};

  internal::SortAndFilterRecentlyVisitedURLs(recently_visited);

  // Vector must be capped to exactly 3 elements, sorted by most recent first.
  ASSERT_EQ(recently_visited.size(), 3u);
  EXPECT_EQ(recently_visited[0], engine_1st.get());
  EXPECT_EQ(recently_visited[1], engine_2nd.get());
  EXPECT_EQ(recently_visited[2], engine_3rd.get());
}

// Test that empty inputs do not cause crashes or unexpected behaviors.
TEST_F(SortAndFilterRecentlyVisitedURLsTest, HandlesEmptyVector) {
  TemplateURL::TemplateURLVector recently_visited;

  internal::SortAndFilterRecentlyVisitedURLs(recently_visited);

  EXPECT_TRUE(recently_visited.empty());
}

// Test handling of vectors with fewer elements than the maximum allowed
// capacity.
TEST_F(SortAndFilterRecentlyVisitedURLsTest, HandlesFewerThanMaxEngines) {
  base::Time now = base::Time::Now();

  auto engine_newer = CreateSearchEngineWithVisitTime(now - base::Hours(2));
  auto engine_older = CreateSearchEngineWithVisitTime(now - base::Hours(10));

  TemplateURL::TemplateURLVector recently_visited = {engine_older.get(),
                                                     engine_newer.get()};

  internal::SortAndFilterRecentlyVisitedURLs(recently_visited);

  // Both should be kept because we are below the limit of 3, but sorted by
  // recency.
  ASSERT_EQ(recently_visited.size(), 2u);
  EXPECT_EQ(recently_visited[0], engine_newer.get());
  EXPECT_EQ(recently_visited[1], engine_older.get());
}
#endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)

class GetDisabledStarterPackIdsTest : public testing::Test {};

TEST_F(GetDisabledStarterPackIdsTest, AiMode) {
  auto disabled_ids_with_ai = internal::GetDisabledStarterPackIds(
      /*ai_mode_enabled=*/true, /*gemini_enabled=*/true);
  EXPECT_FALSE(disabled_ids_with_ai.Has(
      template_url_starter_pack_data::StarterPackId::kAiMode));

  auto disabled_ids_without_ai = internal::GetDisabledStarterPackIds(
      /*ai_mode_enabled=*/false, /*gemini_enabled=*/true);
  EXPECT_TRUE(disabled_ids_without_ai.Has(
      template_url_starter_pack_data::StarterPackId::kAiMode));
}

TEST_F(GetDisabledStarterPackIdsTest, GeminiWithStarterPackExpansion) {
  base::test::ScopedFeatureList feature_list{omnibox::kStarterPackExpansion};

  auto disabled_ids = internal::GetDisabledStarterPackIds(
      /*ai_mode_enabled=*/true, /*gemini_enabled=*/true);
  EXPECT_FALSE(
      disabled_ids.Has(template_url_starter_pack_data::StarterPackId::kGemini));
}

TEST_F(GetDisabledStarterPackIdsTest, GeminiWithoutStarterPackExpansion) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndDisableFeature(omnibox::kStarterPackExpansion);

  auto disabled_ids = internal::GetDisabledStarterPackIds(
      /*ai_mode_enabled=*/true, /*gemini_enabled=*/false);
  EXPECT_TRUE(
      disabled_ids.Has(template_url_starter_pack_data::StarterPackId::kGemini));
}

TEST_F(GetDisabledStarterPackIdsTest, PageWithStarterPackPage) {
  omnibox_feature_configs::ScopedConfigForTesting<
      omnibox_feature_configs::ContextualSearch>
      scoped_config;
  scoped_config.Get().starter_pack_page = true;

  auto disabled_ids = internal::GetDisabledStarterPackIds(
      /*ai_mode_enabled=*/true, /*gemini_enabled=*/true);
  EXPECT_FALSE(
      disabled_ids.Has(template_url_starter_pack_data::StarterPackId::kPage));
}

TEST_F(GetDisabledStarterPackIdsTest, PageWithoutStarterPackPage) {
  omnibox_feature_configs::ScopedConfigForTesting<
      omnibox_feature_configs::ContextualSearch>
      scoped_config;
  scoped_config.Get().starter_pack_page = false;

  auto disabled_ids = internal::GetDisabledStarterPackIds(
      /*ai_mode_enabled=*/true, /*gemini_enabled=*/true);
  EXPECT_TRUE(
      disabled_ids.Has(template_url_starter_pack_data::StarterPackId::kPage));
}
