#include "components/autofill/core/browser/payments_suggestion_generator.h"
#include <optional>
#include <string>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.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/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_wallet_usage_data.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/data_model/credit_card_benefit.h"
#include "components/autofill/core/browser/data_model/iban.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/metrics/payments/card_metadata_metrics.h"
#include "components/autofill/core/browser/metrics/suggestions_list_metrics.h"
#include "components/autofill/core/browser/mock_autofill_optimization_guide.h"
#include "components/autofill/core/browser/payments/constants.h"
#include "components/autofill/core/browser/payments_data_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_payments_data_manager.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_payments_features.h"
#include "components/autofill/core/common/credit_card_network_identifiers.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/grit/components_scaled_resources.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/test/test_sync_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/mock_resource_bundle_delegate.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/resources/grit/ui_resources.h"
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#include "ui/native_theme/native_theme.h"
#endif
AreImagesEqual;
namespace autofill {
namespace {
ElementsAre;
Field;
IsEmpty;
Matcher;
UnorderedElementsAre;
UnorderedElementsAreArray;
constexpr auto kDefaultTriggerSource = …;
Matcher<Suggestion> EqualLabels(
const std::vector<std::vector<Suggestion::Text>>& suggestion_objects) { … }
Matcher<Suggestion> EqualLabels(
const std::vector<std::vector<std::u16string>>& labels) { … }
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
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 = { … }
#endif
Matcher<Suggestion> EqualsIbanSuggestion(
const std::u16string& identifier_string,
const Suggestion::Payload& payload,
const std::u16string& nickname) { … }
#if !BUILDFLAG(IS_IOS)
Matcher<Suggestion> EqualsUndoAutofillSuggestion() { … }
#endif
Matcher<Suggestion> EqualsManagePaymentsMethodsSuggestion(bool with_gpay_logo) { … }
MATCHER_P(ContainsCreditCardFooterSuggestions, with_gpay_logo, "") { … }
}
class PaymentsSuggestionGeneratorTest : public testing::Test { … };
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
class AutofillCreditCardBenefitsLabelTest
: public PaymentsSuggestionGeneratorTest,
public ::testing::WithParamInterface<
std::tuple<base::FunctionRef<CreditCardBenefit()>, std::string>> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(AutofillCreditCardBenefitsLabelTest, BenefitSuggestionLabel_Fpan) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionFeatureForIph_Fpan) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionFeatureForIph_VirtualCard) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionLabel_VirtualCard) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionLabel_MetadataLoggingContext) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionLabel_MetadataLoggingContext_FlagsDisabled) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionLabelNotDisplayed_MerchantUrlIsDifferent) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionLabelNotDisplayed_CategoryIsDifferent) { … }
TEST_P(AutofillCreditCardBenefitsLabelTest,
BenefitSuggestionLabelNotDisplayed_BlockedUrl) { … }
#endif
TEST_F(PaymentsSuggestionGeneratorTest,
NoCreditCardsHaveValuesForClassifiedField_PaymentsManualFallback) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
RemoveExpiredCreditCardsNotUsedSinceTimestamp) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
NoPrefixMatchingForCreditCardsIfFeatureIsTurnedOn) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
NoPrefixMatchingForCvcsIfFeatureIsTurnedOn) { … }
TEST_F(PaymentsSuggestionGeneratorTest, PaymentsFieldSwapping) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
ManualFallback_UnusedExpiredCardsAreNotSuppressed) { … }
TEST_F(PaymentsSuggestionGeneratorTest, GetServerCardForLocalCard) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
GetSuggestionsForCreditCards_StableSortBasedOnOffer) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
GetSuggestionsForVirtualCardStandaloneCvc) { … }
#if !BUILDFLAG(IS_IOS)
TEST_F(PaymentsSuggestionGeneratorTest,
GetSuggestionsForVirtualCardStandaloneCvc_UndoAutofill) { … }
#endif
TEST_F(PaymentsSuggestionGeneratorTest, GetCardSuggestionsWithCvc) { … }
TEST_F(PaymentsSuggestionGeneratorTest, ShouldDisplayGpayLogo) { … }
TEST_F(PaymentsSuggestionGeneratorTest, NoSuggestionsWhenNoUserData) { … }
TEST_F(PaymentsSuggestionGeneratorTest, ShouldShowScanCreditCard) { … }
TEST_F(PaymentsSuggestionGeneratorTest, ShouldShowCardsFromAccount) { … }
#if !BUILDFLAG(IS_IOS)
TEST_F(PaymentsSuggestionGeneratorTest,
FieldWasAutofilled_UndoAutofillOnCreditCardForm) { … }
#endif
TEST_F(PaymentsSuggestionGeneratorTest, ShouldShowVirtualCardOption) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
ShouldShowVirtualCardOption_AutofillOptimizationGuideNotPresent) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
ShouldShowVirtualCardOption_InDisabledStateForOptedOutMerchants) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
ShouldNotShowVirtualCardOption_MerchantOptedOutOfVirtualCards) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
ShouldNotShowVirtualCardOption_ServerCardNotEnrolledInVirtualCard) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
ShouldNotShowVirtualCardOption_LocalCardWithoutServerCardDuplicate) { … }
TEST_F(PaymentsSuggestionGeneratorTest, GetLocalIbanSuggestions) { … }
TEST_F(PaymentsSuggestionGeneratorTest, GetServerIbanSuggestions) { … }
TEST_F(PaymentsSuggestionGeneratorTest, GetLocalAndServerIbanSuggestions) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
GetPromoCodeSuggestionsFromPromoCodeOffers_ValidPromoCodes) { … }
TEST_F(PaymentsSuggestionGeneratorTest,
GetPromoCodeSuggestionsFromPromoCodeOffers_InvalidPromoCodeURL) { … }
class AutofillCreditCardSuggestionContentTest
: public PaymentsSuggestionGeneratorTest { … };
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_VirtualCardMetadata_NameField) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_VirtualCardMetadata_NumberField) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_MaskedServerCardMetadata_NameField) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_MaskedServerCardMetadata_NumberField) { … }
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback_VirtualCreditCard) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback_VirtualCreditCard_Labels) { … }
TEST_F(
AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback_VirtualCreditCard_NestedSuggestions) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback_NestedSuggestions) { … }
TEST_F(
AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback_NoExpiryDate_NestedSuggestions) { … }
TEST_F(
AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback_NoNameAndNumber_NestedSuggestions) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
CreateCreditCardSuggestion_ManualFallback_NestedExpiryDateSuggestions) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
GetSuggestionsForCreditCards_ManualFallbackSuggestionsNotFiltered) { … }
#endif
TEST_F(AutofillCreditCardSuggestionContentTest,
GetSuggestionsForCreditCards_CvcField) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
GetSuggestionsForCreditCards_Duplicate_CvcField) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
GetSuggestionsForCreditCards_VirtualCard_CvcField) { … }
TEST_F(AutofillCreditCardSuggestionContentTest,
GetSuggestionsForCreditCards_VirtualCard_Duplicate_CvcField) { … }
#if BUILDFLAG(IS_IOS)
TEST_F(AutofillCreditCardSuggestionContentTest,
GetSuggestionsForCreditCards_LargeKeyboardAccessoryFormat) {
autofill_client()->set_format_for_large_keyboard_accessory(true);
CreditCard server_card = CreateServerCard();
const std::u16string obfuscated_number =
CreditCard::GetObfuscatedStringForCardDigits(2, u"1111");
const std::u16string name_full =
server_card.GetRawInfo(CREDIT_CARD_NAME_FULL);
const std::u16string exp_date =
server_card.GetRawInfo(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
const std::u16string card_type = server_card.GetRawInfo(CREDIT_CARD_TYPE);
const std::u16string type_and_number =
base::StrCat({card_type, u" ", obfuscated_number});
Suggestion card_number_field_suggestion = CreateCreditCardSuggestionForTest(
server_card, *autofill_client(), CREDIT_CARD_NUMBER,
false,
false);
EXPECT_EQ(card_number_field_suggestion.main_text.value, type_and_number);
EXPECT_THAT(card_number_field_suggestion, EqualLabels({{exp_date}}));
card_number_field_suggestion = CreateCreditCardSuggestionForTest(
server_card, *autofill_client(), CREDIT_CARD_NAME_FULL,
false,
false);
EXPECT_EQ(card_number_field_suggestion.main_text.value,
base::StrCat({name_full}));
EXPECT_THAT(card_number_field_suggestion, EqualLabels({{type_and_number}}));
card_number_field_suggestion = CreateCreditCardSuggestionForTest(
server_card, *autofill_client(), CREDIT_CARD_EXP_MONTH,
false,
false);
EXPECT_EQ(card_number_field_suggestion.main_text.value,
base::StrCat({exp_date}));
EXPECT_THAT(card_number_field_suggestion, EqualLabels({{type_and_number}}));
server_card.set_record_type(CreditCard::RecordType::kVirtualCard);
card_number_field_suggestion = CreateCreditCardSuggestionForTest(
server_card, *autofill_client(), CREDIT_CARD_NUMBER,
true,
false);
EXPECT_EQ(card_number_field_suggestion.main_text.value,
base::StrCat({server_card.CardNameForAutofillDisplay(
server_card.nickname())}));
EXPECT_THAT(
card_number_field_suggestion,
EqualLabels({{l10n_util::GetStringUTF16(
IDS_AUTOFILL_VIRTUAL_CARD_SUGGESTION_OPTION_VALUE) +
u" • " + card_type + u" " + obfuscated_number}}));
}
#endif
class AutofillCreditCardSuggestionContentVcnMerchantOptOutTest
: public AutofillCreditCardSuggestionContentTest,
public testing::WithParamInterface<bool> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(
AutofillCreditCardSuggestionContentVcnMerchantOptOutTest,
CreateCreditCardSuggestion_VirtualCardMetadata_MerchantOptOut_NameField) { … }
TEST_P(
AutofillCreditCardSuggestionContentVcnMerchantOptOutTest,
CreateCreditCardSuggestion_VirtualCardMetadata_MerchantOptOut_NumberField) { … }
class PaymentsSuggestionGeneratorTestForMetadata
: public PaymentsSuggestionGeneratorTest,
public testing::WithParamInterface<std::tuple<bool, bool, bool>> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(PaymentsSuggestionGeneratorTestForMetadata,
CreateCreditCardSuggestion_ServerCard) { … }
TEST_P(PaymentsSuggestionGeneratorTestForMetadata,
CreateCreditCardSuggestion_LocalCard_NoServerDuplicate) { … }
TEST_P(PaymentsSuggestionGeneratorTestForMetadata,
CreateCreditCardSuggestion_LocalCard_ServerDuplicate) { … }
TEST_P(PaymentsSuggestionGeneratorTestForMetadata,
GetSuggestionsForCreditCards_MetadataLoggingContext) { … }
TEST_P(PaymentsSuggestionGeneratorTestForMetadata,
GetSuggestionsForCreditCards_CustomCardIcon) { … }
class PaymentsSuggestionGeneratorTestForOffer
: public PaymentsSuggestionGeneratorTest,
public testing::WithParamInterface<bool> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(PaymentsSuggestionGeneratorTestForOffer,
CreateCreditCardSuggestion_ServerCardWithOffer) { … }
TEST_P(PaymentsSuggestionGeneratorTestForOffer,
CreateCreditCardSuggestion_ServerCardWithOffer_MetadataEnabled) { … }
class PaymentsSuggestionGeneratorTestWithNewSuggestionRankingAlgorithm
: public PaymentsSuggestionGeneratorTest { … };
TEST_F(PaymentsSuggestionGeneratorTestWithNewSuggestionRankingAlgorithm,
GetSuggestionsForCreditCards_SuggestionRankingContext) { … }
TEST_F(
PaymentsSuggestionGeneratorTest,
GetSuggestionsForCreditCards_SuggestionRankingContext_ExperimentDisabled) { … }
TEST_F(
PaymentsSuggestionGeneratorTestWithNewSuggestionRankingAlgorithm,
GetSuggestionsForCreditCards_SuggestionRankingContext_NoRankingDifference) { … }
class AutofillCreditCardSuggestionContentForTouchToFillTest
: public AutofillCreditCardSuggestionContentTest,
public testing::WithParamInterface<bool> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(AutofillCreditCardSuggestionContentForTouchToFillTest,
GetCreditCardSuggestionsForTouchToFill_MainTextMinorTextMerchantOptOut) { … }
TEST_P(AutofillCreditCardSuggestionContentForTouchToFillTest,
GetCreditCardSuggestionsForTouchToFill_Labels) { … }
}