blob: a12ddc1ce892f1124951e671682f5d2431d3001e [file] [log] [blame]
// 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.
#import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h"
#import "components/omnibox/browser/actions/omnibox_pedal.h"
#import "components/omnibox/browser/autocomplete_match.h"
#import "components/omnibox/browser/autocomplete_match_test_util.h"
#import "components/omnibox/browser/autocomplete_result.h"
#import "components/omnibox/browser/omnibox_controller.h"
#import "components/omnibox/browser/test_omnibox_client.h"
#import "components/search_engines/search_engines_test_environment.h"
#import "components/search_engines/template_url.h"
#import "components/search_engines/template_url_service.h"
#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
#import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_delegate.h"
#import "ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h"
#import "ios/chrome/browser/omnibox/model/pedal_suggestion_wrapper.h"
#import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/platform_test.h"
@interface FakeAutocompleteResultWrapperDelegate
: NSObject <AutocompleteResultWrapperDelegate>
@end
@implementation FakeAutocompleteResultWrapperDelegate
- (void)autocompleteResultWrapper:(AutocompleteResultWrapper*)wrapper
didInvalidatePedals:(NSArray<id<AutocompleteSuggestionGroup>>*)
nonPedalSuggestionsGroups {
// NO-OP
}
@end
class AutocompleteResultWrapperTest : public PlatformTest {
public:
AutocompleteResultWrapperTest() {
_fake_autocomplete_wrapper_delegate =
[[FakeAutocompleteResultWrapperDelegate alloc] init];
auto omnibox_client = std::make_unique<TestOmniboxClient>();
omnibox_controller_ = std::make_unique<OmniboxController>(
/*view=*/nullptr, std::move(omnibox_client));
wrapper_ = [[AutocompleteResultWrapper alloc]
initWithOmniboxClient:omnibox_controller_->client()];
wrapper_.isIncognito = NO;
wrapper_.templateURLService =
search_engines_test_environment_.template_url_service();
wrapper_.delegate = _fake_autocomplete_wrapper_delegate;
wrapper_.pedalAnnotator = [[OmniboxPedalAnnotator alloc] init];
TestProfileIOS::Builder builder;
builder.AddTestingFactory(
ios::TemplateURLServiceFactory::GetInstance(),
ios::TemplateURLServiceFactory::GetDefaultFactory());
profile_ = std::move(builder).Build();
}
~AutocompleteResultWrapperTest() override { [wrapper_ disconnect]; }
base::test::TaskEnvironment task_environment_;
AutocompleteResultWrapper* wrapper_;
search_engines::SearchEnginesTestEnvironment search_engines_test_environment_;
std::unique_ptr<TestProfileIOS> profile_;
FakeAutocompleteResultWrapperDelegate* _fake_autocomplete_wrapper_delegate;
std::unique_ptr<OmniboxController> omnibox_controller_;
};
// Tests wrapping an autocomplete result with 2 non-pedal starred matches.
TEST_F(AutocompleteResultWrapperTest,
testWrapMatchesFromResultWithStarredMatch) {
AutocompleteMatch match1 = CreateActionInSuggestMatch(
u"Action", {omnibox::ActionInfo_ActionType_REVIEWS,
omnibox::ActionInfo_ActionType_DIRECTIONS});
AutocompleteMatch match2 = CreateSearchMatch(u"search");
AutocompleteResult result;
result.AppendMatches({match1, match2});
wrapper_.hasThumbnail = NO;
NSArray<id<AutocompleteSuggestionGroup>>* wrappedGroups =
[wrapper_ wrapAutocompleteResultInGroups:result];
// Expect 1 wrapped group.
EXPECT_EQ(wrappedGroups.count, 1u);
EXPECT_EQ(wrappedGroups[0].type,
SuggestionGroupType::kUnspecifiedSuggestionGroup);
// expect 2 wrapped suggestions in the group.
EXPECT_EQ(wrappedGroups[0].suggestions.count, 2u);
// Wrapped suggestions should be non pedals.
EXPECT_TRUE([wrappedGroups[0].suggestions[0]
isKindOfClass:[AutocompleteMatchFormatter class]]);
EXPECT_TRUE([wrappedGroups[0].suggestions[1]
isKindOfClass:[AutocompleteMatchFormatter class]]);
AutocompleteMatchFormatter* firstSuggestion = wrappedGroups[0].suggestions[0];
AutocompleteMatchFormatter* secondSuggestion =
wrappedGroups[0].suggestions[1];
EXPECT_FALSE(firstSuggestion.starred);
EXPECT_FALSE(secondSuggestion.starred);
EXPECT_FALSE(firstSuggestion.incognito);
EXPECT_FALSE(secondSuggestion.incognito);
EXPECT_TRUE(firstSuggestion.defaultSearchEngineIsGoogle);
EXPECT_TRUE(secondSuggestion.defaultSearchEngineIsGoogle);
EXPECT_FALSE(firstSuggestion.isMultimodal);
EXPECT_FALSE(secondSuggestion.isMultimodal);
EXPECT_EQ(firstSuggestion.actionsInSuggest.count, 2u);
EXPECT_EQ(secondSuggestion.actionsInSuggest.count, 0u);
}
// Tests wrapping an autocomplete result after changing the default search
// engine.
TEST_F(AutocompleteResultWrapperTest, testChangeSearchEngine) {
AutocompleteResult result;
AutocompleteMatch match1 = CreateActionInSuggestMatch(
u"Action", {omnibox::ActionInfo_ActionType_REVIEWS,
omnibox::ActionInfo_ActionType_DIRECTIONS});
AutocompleteMatch match2 = CreateSearchMatch(u"search");
result.AppendMatches({match1, match2});
TemplateURLService* template_url_service =
search_engines_test_environment_.template_url_service();
template_url_service->Load();
// Verify that Google is the default search provider.
ASSERT_EQ(SEARCH_ENGINE_GOOGLE,
template_url_service->GetDefaultSearchProvider()->GetEngineType(
template_url_service->search_terms_data()));
NSArray<id<AutocompleteSuggestionGroup>>* wrappedGroups =
[wrapper_ wrapAutocompleteResultInGroups:result];
EXPECT_EQ(wrappedGroups.count, 1u);
EXPECT_EQ(wrappedGroups[0].suggestions.count, 2u);
// Wrapped suggestions should be non pedals.
EXPECT_TRUE([wrappedGroups[0].suggestions[0]
isKindOfClass:[AutocompleteMatchFormatter class]]);
EXPECT_TRUE([wrappedGroups[0].suggestions[1]
isKindOfClass:[AutocompleteMatchFormatter class]]);
AutocompleteMatchFormatter* firstSuggestion = wrappedGroups[0].suggestions[0];
AutocompleteMatchFormatter* secondSuggestion =
wrappedGroups[0].suggestions[1];
// the `wrappedMatch` defaultSearchEngineIsGoogle should be true.
EXPECT_TRUE(firstSuggestion.defaultSearchEngineIsGoogle);
EXPECT_TRUE(secondSuggestion.defaultSearchEngineIsGoogle);
// Keep a reference to the Google default search provider.
const TemplateURL* google_provider =
template_url_service->GetDefaultSearchProvider();
// Change the default search provider to a non-Google one.
TemplateURLData non_google_provider_data;
non_google_provider_data.SetURL("https://www.nongoogle.com/?q={searchTerms}");
non_google_provider_data.suggestions_url =
"https://www.nongoogle.com/suggest/?q={searchTerms}";
auto* non_google_provider = template_url_service->Add(
std::make_unique<TemplateURL>(non_google_provider_data));
template_url_service->SetUserSelectedDefaultSearchProvider(
non_google_provider);
wrappedGroups = [wrapper_ wrapAutocompleteResultInGroups:result];
firstSuggestion = wrappedGroups[0].suggestions[0];
secondSuggestion = wrappedGroups[0].suggestions[1];
// the `wrappedMatch` defaultSearchEngineIsGoogle should now be false.
EXPECT_FALSE(firstSuggestion.defaultSearchEngineIsGoogle);
EXPECT_FALSE(secondSuggestion.defaultSearchEngineIsGoogle);
// Change the default search provider back to Google.
template_url_service->SetUserSelectedDefaultSearchProvider(
const_cast<TemplateURL*>(google_provider));
}
/// Tests Wrapping a result that contains a pedal match.
TEST_F(AutocompleteResultWrapperTest, testWrapPedalMatch) {
AutocompleteResult result;
AutocompleteMatch match;
scoped_refptr<OmniboxPedal> pedal =
base::WrapRefCounted(new TestOmniboxPedalClearBrowsingData());
match.actions.push_back(std::move(pedal));
result.AppendMatches({match});
NSArray<id<AutocompleteSuggestionGroup>>* wrappedGroups =
[wrapper_ wrapAutocompleteResultInGroups:result];
// The result should be wrapped into 2 groups where the first one is for
// pedal.
EXPECT_EQ(wrappedGroups.count, 2u);
EXPECT_EQ(wrappedGroups[0].type, SuggestionGroupType::kPedalSuggestionGroup);
EXPECT_EQ(wrappedGroups[1].type,
SuggestionGroupType::kUnspecifiedSuggestionGroup);
EXPECT_EQ(wrappedGroups[0].suggestions.count, 1u);
EXPECT_EQ(wrappedGroups[1].suggestions.count, 1u);
// Wrapped suggestions should be pedal.
EXPECT_TRUE([wrappedGroups[0].suggestions[0]
isKindOfClass:[PedalSuggestionWrapper class]]);
}