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

// Copyright 2017 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/form_data_importer.h"

#include <stddef.h>

#include <algorithm>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/not_fatal_until.h"
#include "base/ranges/algorithm.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/uuid.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/address_data_manager.h"
#include "components/autofill/core/browser/address_data_manager_test_api.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_form_test_utils.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_data_importer_test_api.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/form_structure_test_api.h"
#include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
#include "components/autofill/core/browser/mock_autofill_plus_address_delegate.h"
#include "components/autofill/core/browser/payments/payments_autofill_client.h"
#include "components/autofill/core/browser/payments/test_credit_card_save_manager.h"
#include "components/autofill/core/browser/payments/test_virtual_card_enrollment_manager.h"
#include "components/autofill/core/browser/payments_data_manager.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/strike_databases/payments/iban_save_strike_database.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autocomplete_parsing_util.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_test_utils.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/credit_card_network_identifiers.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_test_api.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/html_field_types.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
#include "components/prefs/pref_service.h"
#include "components/sync/test/test_sync_service.h"

namespace autofill {

namespace {

UTF8ToUTF16;
CreateTestFormField;
CreateTestIbanFormData;
_;
NiceMock;

constexpr char kLocale[] =;

// Define values for the default address profile.
constexpr char kDefaultFullName[] =;
constexpr char kDefaultFirstName[] =;
constexpr char kDefaultLastName[] =;
constexpr char kDefaultMail[] =;
constexpr char kDefaultAddressLine1[] =;
constexpr char kDefaultStreetAddress[] =;
constexpr char kDefaultZip[] =;
constexpr char kDefaultCity[] =;
constexpr char kDefaultState[] =;
constexpr char kDefaultCountry[] =;
// Unlike phone numbers from other countries, US phone numbers are stored
// without a leading "+". Formatting a US or CA phone number drops the leading
// "+". As these tests check equality, we drop the "+" in the input as it would
// be gone in the output.
constexpr char kDefaultPhone[] =;
constexpr char kDefaultPhoneDomesticFormatting[] =;
constexpr char kDefaultPhoneAreaCode[] =;
constexpr char kDefaultPhonePrefix[] =;
constexpr char kDefaultPhoneSuffix[] =;

// Define values for a second address profile.
constexpr char kSecondFirstName[] =;
constexpr char kSecondLastName[] =;
constexpr char kSecondMail[] =;
constexpr char kSecondAddressLine1[] =;
constexpr char kSecondZip[] =;
constexpr char kSecondCity[] =;
constexpr char kSecondState[] =;
constexpr char kSecondPhone[] =;
constexpr char kSecondPhoneAreaCode[] =;
constexpr char kSecondPhonePrefix[] =;
constexpr char kSecondPhoneSuffix[] =;

// Define values for a third address profile.
constexpr char kThirdFirstName[] =;
constexpr char kThirdLastName[] =;
constexpr char kThirdMail[] =;
constexpr char kThirdAddressLine1[] =;
constexpr char kThirdZip[] =;
constexpr char kThirdCity[] =;
constexpr char kThirdState[] =;
constexpr char kThirdPhone[] =;

constexpr char kDefaultCreditCardName[] =;
constexpr char kDefaultCreditCardNumber[] =;
constexpr char kDefaultCreditCardExpMonth[] =;
constexpr char kDefaultCreditCardExpYear[] =;

constexpr char kDefaultPhoneGermany[] =;
constexpr char kDefaultPhoneMexico[] =;
constexpr char kDefaultPhoneArmenia[] =;

// For a given FieldType |type| returns a pair of field name and label
// that should be parsed into this type by our field type parsers.
std::pair<std::string, std::string> GetLabelAndNameForType(FieldType type) {}

TypeValuePairs;

// Constructs a FormData instance for |url| from a vector of type value pairs
// that defines a sequence of fields and the filled values.
// The field names and labels for the different types are relieved from
// |GetLabelAndNameForType(type)|
FormData ConstructFormDateFromTypeValuePairs(
    TypeValuePairs type_value_pairs,
    std::string url = "https://www.foo.com") {}

// Constructs a FormStructure instance from a FormData instance and determines
// the heuristic types.
std::unique_ptr<FormStructure> ConstructFormStructureFromFormData(
    const FormData& form,
    GeoIpCountryCode geo_country = GeoIpCountryCode("")) {}

// Constructs a FormStructure instance with fields and inserted values given by
// a vector of type and value pairs.
std::unique_ptr<FormStructure> ConstructFormStructureFromTypeValuePairs(
    TypeValuePairs type_value_pairs,
    std::string url = "https://www.foo.com") {}

// Construct and finalizes an AutofillProfile based on a vector of type and
// value pairs. The values are set as |VerificationStatus::kObserved| and the
// profile is finalizes in the end.
AutofillProfile ConstructProfileFromTypeValuePairs(
    TypeValuePairs type_value_pairs) {}

// Returns a vector of FieldType and value pairs used to construct the
// default AutofillProfile, or a FormStructure or FormData instance that carries
// that corresponding information.
TypeValuePairs GetDefaultProfileTypeValuePairs() {}

// Sets the value of `type` in `pairs` to `value`. If the `value` is empty, the
// `type` is removed entirely.
void SetValueForType(TypeValuePairs& pairs,
                     FieldType type,
                     const std::string& value) {}

// Wraps `GetDefaultProfileTypeValuePairs()` but replaces `kDefaultCountry` with
// `country`. If `country` is empty, ADDRESS_HOME_COUNTRY is removed entirely.
TypeValuePairs GetDefaultProfileTypeValuePairsWithOverriddenCountry(
    const std::string& country) {}

// Same as |GetDefaultProfileTypeValuePairs()|, but split into two parts to test
// multi-step imports. No part by itself satisfies the import requirements.
// |part| specifies the requested half and can be either 1 or 2.
TypeValuePairs GetSplitDefaultProfileTypeValuePairs(int part) {}

// Same as |GetDefaultProfileTypeValuePairs()| but with the second profile
// information.
TypeValuePairs GetSecondProfileTypeValuePairs() {}

// Same as |GetDefaultProfileTypeValuePairs()| but with the third profile
// information.
TypeValuePairs GetThirdProfileTypeValuePairs() {}

// Same as `GetDefaultProfileTypeValuePairs()`, but for credit cards.
TypeValuePairs GetDefaultCreditCardTypeValuePairs() {}

// Returns the default AutofillProfile used in this test file.
AutofillProfile ConstructDefaultProfile() {}

// Wraps `ConstructDefaultProfile()`, but overrides ADDRESS_HOME_COUNTRY with
// `country`.
AutofillProfile ConstructDefaultProfileWithOverriddenCountry(
    const std::string& country) {}

// Returns the second AutofillProfile used in this test file.
AutofillProfile ConstructSecondProfile() {}

// Returns the third AutofillProfile used in this test file.
AutofillProfile ConstructThirdProfile() {}

// Returns a form with the default profile. The AutofillProfile that is imported
// from this form should be similar to the profile create by calling
// `ConstructDefaultProfile()`.
std::unique_ptr<FormStructure> ConstructDefaultProfileFormStructure() {}

// Constructs a form structure containing only an email field, set to
// `kDefaultMail`. This is useful for testing multi-step complements.
std::unique_ptr<FormStructure> ConstructDefaultEmailFormStructure() {}

// Same as `ConstructDefaultFormStructure()` but split into two parts to test
// multi-step imports (see `GetSplitDefaultProfileTypeValuePairs()`).
std::unique_ptr<FormStructure> ConstructSplitDefaultProfileFormStructure(
    int part) {}

// Same as `ConstructDefaultFormStructure()` but for the second profile.
std::unique_ptr<FormStructure> ConstructSecondProfileFormStructure() {}

// Same as `ConstructDefaultFormStructure()` but for the third profile.
std::unique_ptr<FormStructure> ConstructThirdProfileFormStructure() {}

// Constructs a FormStructure with two address sections by concatenating
// the default profile and second profile form structures.
std::unique_ptr<FormStructure> ConstructShippingAndBillingFormStructure() {}

// Same as `ConstructDefaultFormStructure()` but for credit cards.
std::unique_ptr<FormStructure> ConstructDefaultCreditCardFormStructure() {}

// Constructs a |FormData| instance that carries the information of the default
// profile.
FormData ConstructDefaultFormData() {}

// Constructs a |FormData| instance with two address sections by concatenating
// the default profile and second profile.
FormData ConstructDefaultFormDataWithTwoAddresses() {}

// Same as |ConstructDefaultFormData()| but split into two parts to test multi-
// step imports (see |GetSplitDefaultProfileTypeValuePairs()|).
FormData ConstructSplitDefaultFormData(int part) {}

// Matches an AddressProfile or CreditCard pointer according to Compare().
// Takes `expected` by value to avoid a dangling reference.
template <typename T>
auto ComparesEqual(T expected) {}

// The below matchers follow ::testing::UnorderedElementsAre[Array] except that
// they accept AutofillProfile or CreditCard *pointers* and compare their
// pointees using ComparesEqual().

template <typename T>
auto UnorderedElementsCompareEqualArray(const std::vector<T>& expected_values) {}

template <typename... Matchers>
auto UnorderedElementsCompareEqual(Matchers... matchers) {}

}  // anonymous namespace

class MockVirtualCardEnrollmentManager
    : public TestVirtualCardEnrollmentManager {};

// TODO(crbug.com/40270301): Move MockCreditCardSaveManager to new header and cc
// file.
class MockCreditCardSaveManager : public TestCreditCardSaveManager {};

class FormDataImporterTest : public testing::Test {};

// Tests that the country is not complemented if a country is part of the form.
TEST_F(FormDataImporterTest, ComplementCountry_PartOfForm) {}

// Tests that the complemented country prefers the variation country code over
// the app locale (US). The form's country field is left empty.
TEST_F(FormDataImporterTest, ComplementCountry_VariationCountryCode) {}

// Tests that without a variation country code, the country is complemented by
// the app locale. The form's country field is left empty.
TEST_F(FormDataImporterTest, ComplementCountry_VariationConfigCountryCode) {}

// Tests that the country is complemented before parsing the phone number. This
// is important, since the phone number validation relies on the profile's
// country for nationally formatted numbers.
TEST_F(FormDataImporterTest, ComplementCountry_PhoneNumberParsing) {}

// This test verifies that a phone number is stored correctly in the following
// situation: A form contains a telephone number field that is classified as
// a PHONE_HOME_CITY_AND_NUMBER field (either due to heuristics or due to
// crowdsourcing). If a user enters an international phone number (e.g. +374 10
// 123456), this must be parsed as such, not as a local number in the assumed
// country. Otherwise, the stored value is incorrect. Before a fix, the
// number quoted above would be stored as "(010) 123456" for a DE address
// profile and not stored at all for a US address profile.
TEST_F(FormDataImporterTest, ParseI18nPhoneNumberInCityAndNumberField) {}

// Tests that invalid countries in submitted forms are ignored, and that the
// complement country logic overwrites it. In this case, expect the country to
// default to the locale's country "US".
TEST_F(FormDataImporterTest, InvalidCountry) {}

// Tests that invalid phone numbers are removed and importing continues.
TEST_F(FormDataImporterTest, InvalidPhoneNumber) {}

TEST_F(FormDataImporterTest, PlusAddressesExcluded) {}

// ImportAddressProfiles tests.
TEST_F(FormDataImporterTest, ImportStructuredNameProfile) {}

TEST_F(FormDataImporterTest,
       ImportStructuredAddressProfile_StreetNameAndHouseNumber) {}

TEST_F(
    FormDataImporterTest,
    ImportStructuredAddressProfile_StreetNameAndHouseNumberAndApartmentNumber) {}

TEST_F(FormDataImporterTest,
       ImportStructuredAddressProfile_GermanStreetNameAndHouseNumber) {}

TEST_F(FormDataImporterTest, ImportStructuredAddressProfile_I18nAddressFormMX) {}

TEST_F(FormDataImporterTest, ImportStructuredAddressProfile_I18nAddressFormBR) {}

// ImportAddressProfiles tests.
TEST_F(FormDataImporterTest, ImportStructuredNameAddressProfile) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles) {}

TEST_F(FormDataImporterTest, ImportSecondAddressProfiles) {}

TEST_F(FormDataImporterTest, ImportThirdAddressProfiles) {}

// Test that with dependent locality parsing enabled, dependent locality fields
// are imported.
TEST_F(FormDataImporterTest, ImportAddressProfiles_DependentLocality) {}

// Test that the storage is prevented if the structured address prompt feature
// is enabled, but address prompts are not allowed.
TEST_F(FormDataImporterTest, ImportAddressProfiles_DontAllowPrompt) {}

TEST_F(FormDataImporterTest, ImportAddressProfileFromUnifiedSection) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_BadEmail) {}

// Tests that a 'confirm email' field does not block profile import.
TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoEmails) {}

// Tests two email fields containing different values blocks profile import.
TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoDifferentEmails) {}

// Tests that multiple phone numbers do not block profile extraction and the
// first one is saved.
TEST_F(FormDataImporterTest, ImportAddressProfiles_MultiplePhoneNumbers) {}

// Tests that multiple phone numbers do not block profile import and the first
// one is saved.
TEST_F(FormDataImporterTest,
       ImportAddressProfiles_MultiplePhoneNumbersSplitAcrossMultipleFields) {}

// Tests that not enough filled fields will result in not importing an address.
TEST_F(FormDataImporterTest, ImportAddressProfiles_NotEnoughFilledFields) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressUSA) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressGB) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressGI) {}

TEST_F(FormDataImporterTest,
       ImportAddressProfiles_PhoneNumberSplitAcrossMultipleFields) {}

// Test that even from unfocusable fields we extract.
TEST_F(FormDataImporterTest, ImportAddressProfiles_UnfocusableFields) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_MultilineAddress) {}

TEST_F(FormDataImporterTest,
       ImportAddressProfiles_TwoValidProfilesDifferentForms) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoValidProfilesSameForm) {}

TEST_F(FormDataImporterTest,
       ImportAddressProfiles_OneValidProfileSameForm_PartsHidden) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInOld) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInNew) {}

TEST_F(FormDataImporterTest, ImportAddressProfiles_InsufficientAddress) {}

// Tests that an address can be imported from an Indian address form without
// synthesized field types.
TEST_F(FormDataImporterTest, ImportAddressProfiles_NoSynthesizedTypes) {}

// Tests that an address cannot be imported from an Indian address form which
// contains synthesized fields. We don't allow that because the address will
// likely look incomplete when shown to the user.
TEST_F(FormDataImporterTest, ImportAddressProfiles_ContainsSynthesizedTypes) {}

// Tests that a profile is created for countries with composed names.
TEST_F(FormDataImporterTest,
       ImportAddressProfiles_CompleteComposedCountryName) {}

// TODO(crbug.com/41267680): Create profiles if part of a standalone part of a
// composed country name is present. Currently this is treated as an invalid
// country, which is ignored on import.
TEST_F(FormDataImporterTest,
       ImportAddressProfiles_IncompleteComposedCountryName) {}

// ExtractCreditCard tests.

// Tests that a valid credit card is extracted.
TEST_F(FormDataImporterTest, ExtractCreditCard_Valid) {}

// Tests that an invalid credit card number is not extracted.
TEST_F(FormDataImporterTest, ExtractCreditCard_InvalidCardNumber) {}

// Tests that FormFieldData::user_input is preferred over FormFieldData::value
// for credit card numbers.
// Using FormFieldData::user_input enables showing the save-card prompt for
// sites which use JavaScript to set the credit-card <input> to '***'.
TEST_F(FormDataImporterTest,
       ExtractCreditCard_PreferUserInputForCreditCardNumber) {}

// Tests that a credit card with an empty expiration can be extracted due to the
// expiration date fix flow.
TEST_F(FormDataImporterTest,
       ExtractCreditCard_InvalidExpiryDate_EditableExpirationExpOn) {}

// Tests that an expired credit card can be extracted due to the expiration date
// fix flow.
TEST_F(FormDataImporterTest,
       ExtractCreditCard_ExpiredExpiryDate_EditableExpirationExpOn) {}

// Tests that a valid credit card is extracted when the option text for month
// select can't be parsed but its value can.
TEST_F(FormDataImporterTest, ExtractCreditCard_MonthSelectInvalidText) {}

TEST_F(FormDataImporterTest, ExtractCreditCard_TwoValidCards) {}

// This form has the expiration year as one field with MM/YY.
TEST_F(FormDataImporterTest, ExtractCreditCard_Month2DigitYearCombination) {}

// This form has the expiration year as one field with MM/YYYY.
TEST_F(FormDataImporterTest, ExtractCreditCard_Month4DigitYearCombination) {}

// This form has the expiration year as one field with M/YYYY.
TEST_F(FormDataImporterTest, ExtractCreditCard_1DigitMonth4DigitYear) {}

// This form has the expiration year as a 2-digit field.
TEST_F(FormDataImporterTest, ExtractCreditCard_2DigitYear) {}

// Tests that a credit card is extracted when the card matches a masked server
// card.
TEST_F(FormDataImporterTest,
       ExtractCreditCard_DuplicateServerCards_ExtractMaskedCard) {}

TEST_F(FormDataImporterTest, ExtractCreditCard_SameCreditCardWithConflict) {}

TEST_F(FormDataImporterTest, ExtractCreditCard_ShouldReturnLocalCard) {}

TEST_F(FormDataImporterTest,
       ExtractCreditCard_ShouldReturnLocalCard_WithExtractedCvc) {}

TEST_F(FormDataImporterTest, ExtractCreditCard_EmptyCardWithConflict) {}

TEST_F(FormDataImporterTest, ExtractCreditCard_MissingInfoInNew) {}

TEST_F(FormDataImporterTest, ExtractCreditCard_MissingInfoInOld) {}

// We allow the user to store a credit card number with separators via the UI.
// We should not try to re-aggregate the same card with the separators stripped.
TEST_F(FormDataImporterTest, ExtractCreditCard_SameCardWithSeparators) {}

// Ensure that if a verified credit card already exists, aggregated credit cards
// cannot modify it in any way.
TEST_F(FormDataImporterTest,
       ExtractCreditCard_ExistingVerifiedCardWithConflict) {}

// Ensures that
// `FormDataImporterTest::credit_card_import_type_` is set and
// reset correctly.
TEST_F(FormDataImporterTest,
       ExtractFormData_SecondImportResetsCreditCardRecordType) {}

// Ensures that
// `FormDataImporterTest::credit_card_import_type_` is set
// correctly.
TEST_F(FormDataImporterTest,
       ExtractFormData_ExtractCreditCardRecordType_NewCard) {}

// Ensures that `credit_card_import_type_` is set correctly.
TEST_F(FormDataImporterTest,
       ExtractFormData_ExtractCreditCardRecordType_LocalCard) {}

// Ensures that
// `FormDataImporterTest::credit_card_import_type_` is set
// correctly.
TEST_F(FormDataImporterTest,
       ExtractFormData_ExtractCreditCardRecordType_MaskedServerCard) {}

// Ensures that `FormDataImporterTest::credit_card_import_type_` and
// `record_type` denote that a duplicate card was extracted, and it is a server
// card when the flag is on.
TEST_F(
    FormDataImporterTest,
    ExtractFormData_ExtractCreditCardRecordType_DuplicateLocalAndMaskedServerCard) {}

// Ensures that
// `FormDataImporterTest::credit_card_import_type_` is set
// correctly.
TEST_F(FormDataImporterTest,
       ExtractFormData_ExtractCreditCardRecordType_NoCard_InvalidCardNumber) {}

// Ensures that
// `FormDataImporterTest::credit_card_import_type_` is set
// correctly.
TEST_F(FormDataImporterTest,
       ExtractFormData_ExtractCreditCardRecordType_NoCard_VirtualCard) {}

// Ensures that
// `FormDataImporterTest::credit_card_import_type_` is set
// correctly.
TEST_F(
    FormDataImporterTest,
    ExtractFormData_ExtractCreditCardRecordType_NewCard_ExpiredCard_WithExpDateFixFlow) {}

// Ensures that
// `FormDataImporterTest::credit_card_import_type_` is set
// correctly.
TEST_F(FormDataImporterTest,
       ExtractFormData_ExtractCreditCardRecordType_NoCard_NoCardOnForm) {}

// Ensures that `cvc` is set when a server card is found.
TEST_F(FormDataImporterTest,
       ExtractFormData_ExtractCreditCardRecordType_ServerCardWithCvc) {}

// Ensures that `credit_card_import_type_` is set as kNewCard when there is a
// masked server card with the same last four but different expiration date.
TEST_F(
    FormDataImporterTest,
    ExtractFormData_ExtractCreditCardRecordType_MaskedServerCardWithSameLastFour) {}

// Ensures that `credit_card_import_type_` is set correctly when there are two
// masked server card with the same last four and the extracted credit card has
// same last four with both of them.
// Also, verify that `SubmittedServerCardExpirationStatus` will be logged only
// once.
// This test includes two cases:
// 1. The extracted credit card has the same expiration with the second masked
//    server card.
// 2. The extracted credit card's expiration date is not the same as any of the
//    the masked server cards.
TEST_F(
    FormDataImporterTest,
    ExtractFormData_ExtractCreditCardRecordType_TwoMaskedServerCardWithSameLastFour) {}

// ExtractFormData tests (both addresses and credit cards).

// Test that a form with both address and credit card sections imports the
// address and the credit card.
TEST_F(FormDataImporterTest, ExtractFormData_OneAddressOneCreditCard) {}

// Test that a form with two address sections and a credit card section does not
// import the address but does import the credit card.
TEST_F(FormDataImporterTest, ExtractFormData_TwoAddressesOneCreditCard) {}

#if !BUILDFLAG(IS_IOS)
TEST_F(FormDataImporterTest, ExtractFormData_ImportIbanRecordType_NoIban) {}

TEST_F(FormDataImporterTest, ExtractFormData_SubmittingIbanFormUpdatesPref) {}

TEST_F(FormDataImporterTest,
       ExtractFormData_SubmittingCreditCardFormDoesNotUpdateIbanPref) {}

TEST_F(FormDataImporterTest,
       ExtractFormData_ImportIbanRecordType_IbanAutofill_NewInvalidIban) {}

TEST_F(FormDataImporterTest,
       ExtractFormData_ImportIbanRecordType_IbanAutofill_NewIban) {}

TEST_F(FormDataImporterTest, ExtractFormData_ImportIbanRecordType_LocalIban) {}

#endif  // !BUILDFLAG(IS_IOS)

// Test that a form with both address and credit card sections imports only the
// the credit card if addresses are disabled.
TEST_F(FormDataImporterTest, ExtractFormData_AddressesDisabledOneCreditCard) {}

// Test that a form with both address and credit card sections imports only the
// the address if credit cards are disabled.
TEST_F(FormDataImporterTest, ExtractFormData_OneAddressCreditCardDisabled) {}

// Test that a form with both address and credit card sections imports nothing
// if both addressed and credit cards are disabled.
TEST_F(FormDataImporterTest, ExtractFormData_AddressCreditCardDisabled) {}

TEST_F(FormDataImporterTest, DuplicateMaskedServerCard) {}

// Tests that a credit card form that is hidden after receiving input still
// imports the card.
TEST_F(FormDataImporterTest, ExtractFormData_HiddenCreditCardFormAfterEntered) {}

// Ensure that we don't offer to save if we already have same card stored as a
// server card and user submitted an invalid expiration date month.
TEST_F(FormDataImporterTest,
       Metrics_SubmittedServerCardExpirationStatus_EmptyExpirationMonth) {}

// Ensure that we don't offer to save if we already have same card stored as a
// server card and user submitted an invalid expiration date year.
TEST_F(FormDataImporterTest,
       Metrics_SubmittedServerCardExpirationStatus_EmptyExpirationYear) {}

// Ensure that we still offer to save if we have different cards stored as a
// server card and user submitted an invalid expiration date year.
TEST_F(
    FormDataImporterTest,
    Metrics_SubmittedDifferentServerCardExpirationStatus_EmptyExpirationYear) {}

TEST_F(FormDataImporterTest,
       Metrics_SubmittedServerCardExpirationStatus_MaskedServerCardMatch) {}

TEST_F(FormDataImporterTest,
       Metrics_SubmittedServerCardExpirationStatus_MaskedServerCardMismatch) {}

TEST_F(FormDataImporterTest, SilentlyUpdateExistingProfileByIncompleteProfile) {}

TEST_F(
    FormDataImporterTest,
    SilentlyUpdateExistingProfileByIncompleteProfile_DespiteDisallowedPrompts) {}

TEST_F(FormDataImporterTest, UnusableIncompleteProfile) {}

// Tests that metrics are correctly recorded when removing setting-inaccessible
// fields.
// Note that this function doesn't test the removal functionality itself. This
// is done in the AutofillProfile unit tests.
TEST_F(FormDataImporterTest, RemoveInaccessibleProfileValuesMetrics) {}

// Tests a 2-page multi-step extraction.
TEST_F(FormDataImporterTest, MultiStepImport) {}

// Tests that when multi-step complements are enabled, complete profiles those
// import was accepted are added as a multi-step candidate. This enables
// complementing the profile with additional information on further pages.
TEST_F(FormDataImporterTest, MultiStepImport_Complement) {}

// Tests that when an imported profile is modified through external means (e.g.
// via the settings), the multi-step complement candidate is updated accordingly
// and the correct profile update occurs.
TEST_F(FormDataImporterTest, MultiStepImport_Complement_ExternalUpdate) {}

// Tests that when an imported profile is deleted through external means (e.g.
// via the settings), the multi-step complement candidate is removed and no
// further updates related to it are offered.
TEST_F(FormDataImporterTest, MultiStepImport_Complement_ExternalRemove) {}

// Tests that multi-step candidate profiles from different origins are not
// merged.
TEST_F(FormDataImporterTest, MultiStepImport_DifferentOrigin) {}

// Tests that multi-step candidates profiles are invalidated after some TTL.
TEST_F(FormDataImporterTest, MultiStepImport_TTL) {}

// Tests that multi-step candidates profiles are cleared if the browsing history
// is deleted.
TEST_F(FormDataImporterTest, MultiStepImport_DeleteOnBrowsingHistoryCleared) {}

// Tests that the FormAssociator is correctly integrated in FormDataImporter and
// that multiple address form in the same form are associated with each other.
// The functionality itself is tested in form_data_importer_utils_unittest.cc.
TEST_F(FormDataImporterTest, FormAssociator) {}

// Tests that ac=unrecognized fields have a prediction, but are not imported.
TEST_F(FormDataImporterTest, SkipAutocompleteUnrecognizedFields) {}

#if !BUILDFLAG(IS_IOS)
TEST_F(FormDataImporterTest,
       ProcessIbanImportCandidate_ShouldOfferLocalSave_NewIban) {}

TEST_F(FormDataImporterTest,
       ExtractFormData_ProcessIbanImportCandidate_NoIban) {}

TEST_F(
    FormDataImporterTest,
    ExtractFormData_ProcessIbanImportCandidate_PaymentMethodsSettingDisabled) {}

TEST_F(FormDataImporterTest,
       ExtractFormData_ProcessIbanImportCandidate_NewIban) {}

TEST_F(FormDataImporterTest,
       ExtractFormData_ProcessIbanImportCandidate_LocalIban) {}

TEST_F(FormDataImporterTest,
       ExtractFormData_ProcessIbanImportCandidate_MaxStrikes) {}
#endif  // !BUILDFLAG(IS_IOS)

TEST_F(FormDataImporterTest, ProcessExtractedCreditCard_EmptyCreditCard) {}

#if !BUILDFLAG(IS_IOS)
TEST_F(FormDataImporterTest, ProcessExtractedCreditCard_VirtualCardEligible) {}
#endif

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
// Test that in the case where the MandatoryReauthManager denotes we should not
// offer re-auth opt-in, we do not start the opt-in flow.
TEST_F(FormDataImporterTest,
       ProcessExtractedCreditCard_MandatoryReauthNotOffered) {
  CreditCard extracted_credit_card = test::GetVirtualCard();
  std::unique_ptr<FormStructure> form_structure =
      ConstructDefaultCreditCardFormStructure();
  form_data_importer()
      .SetPaymentMethodTypeIfNonInteractiveAuthenticationFlowCompleted(
          NonInteractivePaymentMethodType::kVirtualCard);
  test_api(form_data_importer())
      .set_credit_card_import_type(
          FormDataImporter::CreditCardImportType::kVirtualCard);

  EXPECT_CALL(
      *static_cast<::testing::NiceMock<payments::MockMandatoryReauthManager>*>(
          autofill_client_->GetPaymentsAutofillClient()
              ->GetOrCreatePaymentsMandatoryReauthManager()),
      ShouldOfferOptin)
      .Times(1)
      .WillOnce(testing::Return(false));
  EXPECT_CALL(
      *static_cast<::testing::NiceMock<payments::MockMandatoryReauthManager>*>(
          autofill_client_->GetPaymentsAutofillClient()
              ->GetOrCreatePaymentsMandatoryReauthManager()),
      StartOptInFlow)
      .Times(0);

  test_api(form_data_importer())
      .ProcessExtractedCreditCard(*form_structure, extracted_credit_card,
                                  /*is_credit_card_upstream_enabled=*/true);
}

// Test that in the case where the MandatoryReauthManager denotes re-auth opt-in
// should be offered, but the card is a new card (presumed updated by the user
// after filling), re-auth opt-in is not offered.
TEST_F(FormDataImporterTest,
       ProcessExtractedCreditCard_MandatoryReauthNotOffered_NewCard) {
  std::unique_ptr<FormStructure> form_structure =
      ConstructDefaultCreditCardFormStructure();
  form_data_importer()
      .SetPaymentMethodTypeIfNonInteractiveAuthenticationFlowCompleted(
          NonInteractivePaymentMethodType::kLocalCard);
  test_api(form_data_importer())
      .set_credit_card_import_type(
          FormDataImporter::CreditCardImportType::kNewCard);

  EXPECT_CALL(
      *static_cast<::testing::NiceMock<payments::MockMandatoryReauthManager>*>(
          autofill_client_->GetPaymentsAutofillClient()
              ->GetOrCreatePaymentsMandatoryReauthManager()),
      ShouldOfferOptin)
      .Times(0);
  EXPECT_CALL(
      *static_cast<::testing::NiceMock<payments::MockMandatoryReauthManager>*>(
          autofill_client_->GetPaymentsAutofillClient()
              ->GetOrCreatePaymentsMandatoryReauthManager()),
      StartOptInFlow)
      .Times(0);

  test_api(form_data_importer())
      .ProcessExtractedCreditCard(*form_structure, test::GetCreditCard2(),
                                  /*is_credit_card_upstream_enabled=*/true);
}

// Test that in the case where the MandatoryReauthManager denotes we should
// offer re-auth opt-in, we start the opt-in in credit card processing flow if
// the card is not a new card.
TEST_F(FormDataImporterTest,
       ProcessExtractedCreditCard_MandatoryReauthOffered) {
  CreditCard extracted_credit_card = test::GetCreditCard2();
  std::unique_ptr<FormStructure> form_structure =
      ConstructDefaultCreditCardFormStructure();
  form_data_importer()
      .SetPaymentMethodTypeIfNonInteractiveAuthenticationFlowCompleted(
          NonInteractivePaymentMethodType::kLocalCard);
  test_api(form_data_importer())
      .set_credit_card_import_type(
          FormDataImporter::CreditCardImportType::kLocalCard);

  EXPECT_CALL(
      *static_cast<::testing::NiceMock<payments::MockMandatoryReauthManager>*>(
          autofill_client_->GetPaymentsAutofillClient()
              ->GetOrCreatePaymentsMandatoryReauthManager()),
      ShouldOfferOptin)
      .Times(1)
      .WillOnce(testing::Return(true));
  EXPECT_CALL(
      *static_cast<::testing::NiceMock<payments::MockMandatoryReauthManager>*>(
          autofill_client_->GetPaymentsAutofillClient()
              ->GetOrCreatePaymentsMandatoryReauthManager()),
      StartOptInFlow)
      .Times(1);

  EXPECT_TRUE(test_api(form_data_importer())
                  .ProcessExtractedCreditCard(
                      *form_structure, extracted_credit_card,
                      /*is_credit_card_upstream_enabled=*/true));

  // Ensure that we reset the record type at the end of the flow.
  EXPECT_FALSE(
      test_api(form_data_importer())
          .payment_method_type_if_non_interactive_authentication_flow_completed()
          .has_value());
}

// Test that in the case where the MandatoryReauthManager denotes we should
// offer re-auth opt-in, we start the opt-in in IBAN processing flow.
TEST_F(FormDataImporterTest, ProcessExtractedIban_MandatoryReauthOffered) {
  FormStructure form_structure(CreateTestIbanFormData());
  form_structure.DetermineHeuristicTypes(GeoIpCountryCode(""), nullptr,
                                         nullptr);
  form_data_importer()
      .SetPaymentMethodTypeIfNonInteractiveAuthenticationFlowCompleted(
          NonInteractivePaymentMethodType::kLocalIban);

  EXPECT_CALL(*autofill_client_->GetPaymentsAutofillClient()
                   ->GetOrCreatePaymentsMandatoryReauthManager(),
              ShouldOfferOptin)
      .WillOnce(testing::Return(true));
  EXPECT_CALL(*autofill_client_->GetPaymentsAutofillClient()
                   ->GetOrCreatePaymentsMandatoryReauthManager(),
              StartOptInFlow);

  EXPECT_TRUE(ExtractFormDataAndProcessIbanCandidates(
      form_structure, /*profile_autofill_enabled=*/true,
      /*payment_methods_autofill_enabled=*/true));

  // Ensure that we reset the record type at the end of the flow.
  EXPECT_FALSE(
      test_api(form_data_importer())
          .payment_method_type_if_non_interactive_authentication_flow_completed()
          .has_value());
}

// Test that in the case where the MandatoryReauthManager denotes we should not
// offer re-auth opt-in, we do not start the opt-in in IBAN processing flow.
TEST_F(FormDataImporterTest, ProcessExtractedIban_MandatoryReauthNotOffered) {
  FormStructure form_structure(CreateTestIbanFormData());
  form_structure.DetermineHeuristicTypes(GeoIpCountryCode(""), nullptr,
                                         nullptr);

  EXPECT_CALL(*autofill_client_->GetPaymentsAutofillClient()
                   ->GetOrCreatePaymentsMandatoryReauthManager(),
              ShouldOfferOptin)
      .WillOnce(testing::Return(false));
  EXPECT_CALL(*autofill_client_->GetPaymentsAutofillClient()
                   ->GetOrCreatePaymentsMandatoryReauthManager(),
              StartOptInFlow)
      .Times(0);

  EXPECT_TRUE(ExtractFormDataAndProcessIbanCandidates(
      form_structure, /*profile_autofill_enabled=*/true,
      /*payment_methods_autofill_enabled=*/true));

  // Ensure that we reset the record type at the end of the flow.
  EXPECT_FALSE(
      test_api(form_data_importer())
          .payment_method_type_if_non_interactive_authentication_flow_completed()
          .has_value());
}
#endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)

// Test that ProceedWithSavingIfApplicable gets called for server cards with the
// correct pre-requisites set.
TEST_F(FormDataImporterTest,
       ProcessExtractedCreditCard_ProceedWithSavingIfApplicable_Server) {}

// Test that ProceedWithSavingIfApplicable gets called for local cards with the
// correct pre-requisites set.
TEST_F(FormDataImporterTest,
       ProcessExtractedCreditCard_ProceedWithSavingIfApplicable_Local) {}

// Test that Autofill will not try to import from a field that was filled with
// fallback.
TEST_F(FormDataImporterTest,
       GetObservedFieldValues_SkipFieldsFilledWithFallback) {}

// Test the behavior of Autofill importing from fields with
// autocomplete=unrecognized.
TEST_F(FormDataImporterTest,
       GetObservedFieldValues_ImportFromAutocompleteUnrecognized) {}

// Test case for credit card extraction.
class FormDataImporterTest_ExtractCreditCardFromForm
    : public FormDataImporterTest {};

// Tests that inconsistent values from different priority classes do not prevent
// import.
// For example, the user-edited "Donald Trump" has higher priority than the
// autofilled "Joe Biden", which has still higher priority than default-value
// "Joe Average".
TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
       IgnoreInconsistentValuesFromDifferentPriorityClasses) {}

// Tests that equivalent values of different types do not prevent import:
// - first name + last names = full name;
// - month + year = expiration date.
TEST_F(FormDataImporterTest_ExtractCreditCardFromForm, MergeDerivedValues) {}

// Tests detection of inconsistent values (first names "Audrey" and "Katherine")
// in the same priority class (user-edited fields).
TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
       BlockImportForInconsistentValues) {}

// Tests that even editing only a first name (without editing the last name) is
// is reflected in the import candidate.
TEST_F(FormDataImporterTest_ExtractCreditCardFromForm, PartialFirstLastNames) {}

}  // namespace autofill