chromium/components/autofill/core/browser/address_suggestion_generator_unittest.cc

// Copyright 2021 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/autofill/core/browser/address_suggestion_generator.h"

#include <optional>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/uuid.h"
#include "components/autofill/core/browser/address_data_manager.h"
#include "components/autofill/core/browser/autofill_granular_filling_utils.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/autofill_profile_test_api.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/geo/phone_number_i18n.h"
#include "components/autofill/core/browser/test_address_data_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/autofill/core/browser/ui/suggestion_test_helpers.h"
#include "components/autofill/core/browser/ui/suggestion_type.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/test/test_sync_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"

namespace autofill {

namespace {

Field;
IsEmpty;
Matcher;

#if !BUILDFLAG(IS_IOS)
constexpr AutofillSuggestionTriggerSource kDefaultTriggerSource =;
#endif  // !BUILDFLAG(IS_IOS)

constexpr char kAddressesSuppressedHistogramName[] =;

Matcher<Suggestion> EqualLabels(
    const std::vector<std::vector<Suggestion::Text>>& suggestion_objects) {}

Matcher<Suggestion> EqualLabels(
    const std::vector<std::vector<std::u16string>>& labels) {}

Matcher<Suggestion> EqualsFieldByFieldFillingSuggestion(
    SuggestionType id,
    const std::u16string& main_text,
    FieldType field_by_field_filling_type_used,
    const Suggestion::Payload& payload,
    const std::vector<std::vector<Suggestion::Text>>& labels = {}

#if !BUILDFLAG(IS_IOS)
Matcher<Suggestion> EqualsUndoAutofillSuggestion() {}
#endif

Matcher<Suggestion> EqualsManageAddressesSuggestion() {}

// Checks that `arg` contains necessary address footer suggestions. `arg`
// has to be of type std::vector<Suggestion>.
MATCHER(ContainsAddressFooterSuggestions, "") {}

}  // namespace

class AddressSuggestionGeneratorTest : public testing::Test {};

// Tests that special characters will be used while prefix matching the user's
// field input with the available emails to suggest.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_UseSpecialCharactersInEmail) {}

TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_HideSubsets) {}

// Drawing takes noticeable time when there are more than 10 profiles.
// Therefore, we keep only the 10 first suggested profiles.
TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_SuggestionsLimit) {}

// Deduping takes noticeable time when there are more than 50 profiles.
// Therefore, keep only the 50 first pre-dedupe matching profiles.
TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_ProfilesLimit) {}

// Tests that GetProfilesToSuggest orders its suggestions based on the
// ranking formula.
TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_Ranking) {}

// Tests that GetProfilesToSuggest returns all profiles suggestions.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_NumberOfSuggestions) {}

// Tests that phone number types are correctly deduplicated for suggestions.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_PhoneNumberDeduplication) {}

// Tests that disused profiles are suppressed when suppression is enabled and
// the input field is empty.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_SuppressDisusedProfilesOnEmptyField) {}

// Give two suggestions with the same name, and no other field to compare.
// Expect only one unique suggestion.
TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_SingleDedupe) {}

// Given two suggestions with the same name and one with a different, and also
// last name field to compare, Expect all profiles listed as unique suggestions.
TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_MultipleDedupe) {}

// Test the limit of number of deduplicated profiles.
TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_DedupeLimit) {}

TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_EmptyMatchingProfiles) {}

// Tests that `kAccount` profiles are preferred over `kLocalOrSyncable` profile
// in case of a duplicate.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_kAccountPrecedence) {}

TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_GetMatchingProfile) {}

TEST_F(AddressSuggestionGeneratorTest, GetProfilesToSuggest_NoMatchingProfile) {}

TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_EmptyProfilesInput) {}

// Tests that disused profiles get removed.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_RemoveDisusedProfiles_FeatureDisabled) {}

// Tests that disused profiles get removed, but that this doesn't affect the
// first few profiles in the list, depending on the parameterization of the
// feature AutofillChangeDisusedAddressSuggestionTreatment.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_RemoveDisusedProfiles_FeatureEnabled) {}

TEST_F(AddressSuggestionGeneratorTest, CreateSuggestionsFromProfiles) {}

TEST_F(AddressSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_PhoneSubstring) {}

TEST_F(AddressSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_PartialNameFieldHasFullNameMainText) {}

// TODO(crbug.com/40274514): Move AutofillChildrenSuggestionGeneratorTest.
// CreateSuggestionsFromProfiles_GroupFillingLabels_* tests under this fixture.
// Text fixture for label generation related tests. Parameterized by triggering
// field type since how we build labels depends highly on it.
class AutofillLabelSuggestionGeneratorTest
    : public AddressSuggestionGeneratorTest,
      public testing::WithParamInterface<FieldType> {};

INSTANTIATE_TEST_SUITE_P();

// Suggestions for `ADDRESS_HOME_LINE1` should have `NAME_FULL` as the label.
// Suggestions for name or address fields which do not include
// `ADDRESS_HOME_LINE1` should have `ADDRESS_HOME_LINE1` as the label.
TEST_P(
    AutofillLabelSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_FullFormFilling_SuggestionsHaveCorrectLabels) {}

TEST_P(
    AutofillLabelSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_FullFormFilling_SuggestionsNeedMoreLabelsForDifferentiation) {}

// The logic which adds the country as a differentiating label is slightly
// different than the logic which adds any other differentiating label. Since
// the country is the last candidate for a differentiating label, this test also
// prevents random label behaviour (such as non-differentiating label being
// chosen or label not showing at all).
TEST_P(
    AutofillLabelSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_FullFormFilling_CountryIsChosenAsDifferentiatingLabel) {}

class AutofillChildrenSuggestionGeneratorTest
    : public AddressSuggestionGeneratorTest {};

// Test that only "Fill address" is added when the target field is
// `ADDRESS_HOME_LINE1` and no other suggestion exist with the same
// `Suggestion::main_text` and `ADDRESS_HOME_LINE1`.
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_GroupFillingLabels_AddOnlyFillAddress) {}

// Test that a differentiating label is added when the `Suggestion::main_text`
// and detailing label are not unique across suggestions.
TEST_F(
    AutofillChildrenSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_GroupFillingLabels_AddFillAddressAndDifferentiatingLabel) {}

// Test similar to the one above. However also makes sure that
// `ADDRESS_HOME_LINE1` value is added to the label if
// the target field does not contain street address related information
// (ADDRESS_LINE1, ADDRESS_LINE2 and ADDRESS_STREET_NAME).
TEST_F(
    AutofillChildrenSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_GroupFillingLabels_AddFillAddressAddressLine1AndDifferentiatingLabel) {}

// When there is no need to detailing or differentiating label, we add only the
// granular filling label, either "Fill full name" or "Fill address".
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_GroupFillingLabels_AddOnlyFillName) {}

// Test that no labels are added when filling targets only one field.
TEST_F(
    AutofillChildrenSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_GroupFillingLabels_SingleFieldFillingHasNoLabels) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_FirstLevelChildrenSuggestions) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       IncognitoMode_EditAndDeleteSuggestionsAreNotAdded) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       FillEverythingFromAddressProfile_FullFormFilling_NotAdded) {}

// TODO(crbug.com/40274514): Merge this test with
// `FillEverythingFromAddressProfile_FullFormFilling_NotAdded` once the feature
// is launched.
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       FillEverythingFromAddressProfile_FullFormFilling_AddedAtTheTop) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       FillEverythingFromAddressProfile_FieldByFieldFilling_Added) {}

// TODO(crbug.com/40274514): Merge this test with
// `FillEverythingFromAddressProfile_FieldByFieldFilling_Added` once the
// feature is launched.
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       FillEverythingFromAddressProfile_FieldByFieldFilling_AddedAtTheTop) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       FillEverythingFromAddressProfile_GroupFilling_Added) {}

// TODO(crbug.com/40274514): Merge this test with
// `FillEverythingFromAddressProfile_GroupFilling_Added` once the feature is
// launched.
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       FillEverythingFromAddressProfile_GroupFilling_AddedAtTheTop) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_SecondLevelChildrenSuggestions) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_FieldByFieldFilling) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_GroupFilling) {}

// Note that only full form filling has an icon.
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_FullFormFilling) {}

TEST_F(
    AutofillChildrenSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_LastTargetedFieldsContainOnlyEmail_FieldByField) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_LastTargetedFieldsAreNone_FieldByField) {}

// Asserts that when the triggering field is a phone field, the phone number
// suggestion is of type `SuggestionType::kFillFullPhoneNumber`. In other
// scenarios, phone number is of type
// `SuggestionType::kAddressFieldByFieldFilling` as the user expressed intent
// to use their phone number their phone number on a "random" field.
TEST_F(
    AutofillChildrenSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_ChildrenSuggestionsPhoneField_International) {}

// Asserts that when the triggering field is a phone field, the phone number
// suggestion is of type `SuggestionType::kFillFullPhoneNumber`. In other
// scenarios, phone number is of type
// `SuggestionType::kAddressFieldByFieldFilling` as the user expressed intent
// to use their phone number on a "random" field.
TEST_F(
    AutofillChildrenSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_ChildrenSuggestionsPhoneField_CountryCode) {}

// Asserts that when the triggering field is a phone field, the phone number
// suggestion is of type `SuggestionType::kFillFullPhoneNumber`. In other
// scenarios, phone number is of type
// `SuggestionType::kAddressFieldByFieldFilling` as the user expressed intent
// to use their phone number their phone number on a "random" field.
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_ChildrenSuggestionsPhoneField_Local) {}

// Same as above but for email fields.
TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_ChildrenSuggestionsEmailField) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_ChildrenSuggestionsAddressField) {}

TEST_F(AutofillChildrenSuggestionGeneratorTest,
       CreateSuggestionsFromProfiles_ChildrenSuggestionsCompanyField) {}

TEST_F(
    AutofillChildrenSuggestionGeneratorTest,
    CreateSuggestionsFromProfiles_ChildrenSuggestions_HouseNumberAndStreetNameCanBeNestedUnderDifferentAddressLines) {}

// This fixture contains tests for autofill being triggered from the context
// menu on a field which is not classified as an address.
class AutofillNonAddressFieldsSuggestionGeneratorTest
    : public AutofillChildrenSuggestionGeneratorTest {};

TEST_F(AutofillNonAddressFieldsSuggestionGeneratorTest,
       AllProfilesGenerateSuggestions) {}

// Generally, a profile is displayed with name as main text and address as
// label. But with incomplete profiles, it might be problematic. This test
// creates various incomplete profiles and makes sure that a main text and a
// label are always chosen from the available fields (or only main_text if the
// profile has only one field).
TEST_F(AutofillNonAddressFieldsSuggestionGeneratorTest,
       SuggestionsAreCorrectAndExpectedLabelsAndIconsAreCreated) {}

// This test checks that the resulting string of
// `AutofillProfile::CreateDifferentiatingLabels()` is split correctly into main
// text and labels. In Japanese, the resulting string doesn't have separators.
TEST_F(AutofillNonAddressFieldsSuggestionGeneratorTest,
       MainTextAndLabelsAreCorrect_Japanese) {}

// This test checks that the resulting string of
// `AutofillProfile::CreateDifferentiatingLabels()` is split correctly into main
// text and labels. In Arabic, the resulting string is separated by arabic
// comma.
TEST_F(AutofillNonAddressFieldsSuggestionGeneratorTest,
       MainTextAndLabelsAreCorrect_Arabic) {}

// This test checks that the resulting string of
// `AutofillProfile::CreateDifferentiatingLabels()` is split correctly into main
// text and labels. In Thai, the resulting string is separated by space.
TEST_F(AutofillNonAddressFieldsSuggestionGeneratorTest,
       MainTextAndLabelsAreCorrect_Thai) {}

// Tests that a non-address field suggestion has all the profile fields as
// children, and doesn't have children like "Fill address" or "Fill full
// name".
TEST_F(AutofillNonAddressFieldsSuggestionGeneratorTest,
       SuggestionHasCorrectChildren) {}

// Tests the scenario when:
// - autofill is triggered from the context menu on a field which is classified
// as an address field;
// - there is no profile which has values to fill the respective field.
// In this scenario, suggestions should look the same as the ones for an
// unclassified field.
TEST_F(AddressSuggestionGeneratorTest,
       NoProfilesHaveValuesForClassifiedField_AddressManualFallback) {}

// Tests that regular suggestions are filtered by the triggering field's value,
// but manual fallback suggestions are not.
TEST_F(AddressSuggestionGeneratorTest, GetSuggestionsForProfiles_Filtering) {}

// Tests that regular suggestions are filtered by the last usage timestamp, but
// manual fallback suggestions are not.
TEST_F(AddressSuggestionGeneratorTest,
       GetProfilesToSuggest_TimestampFiltering) {}

#if !BUILDFLAG(IS_IOS)
TEST_F(AddressSuggestionGeneratorTest, UndoAutofillOnAddressForm) {}
#endif

TEST_F(AddressSuggestionGeneratorTest,
       TestAddressSuggestion_AddressField_ReturnSuggestion) {}

TEST_F(AddressSuggestionGeneratorTest,
       TestAddressSuggestion_NonAddressField_DoNotReturnSuggestion) {}

}  // namespace autofill