blob: 44611c9ba04e0133d0520bf46c550b6f30dd2416 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/payments/core/autofill_payment_instrument.h"
#include <memory>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/address_normalizer.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/credit_card.h"
#include "components/autofill/core/browser/payments/full_card_request.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/test_address_normalizer.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/payments/core/test_payment_request_delegate.h"
#include "components/strings/grit/components_strings.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
namespace payments {
namespace {
class FakePaymentInstrumentDelegate : public PaymentInstrument::Delegate {
public:
FakePaymentInstrumentDelegate() {}
void OnInstrumentDetailsReady(
const std::string& method_name,
const std::string& stringified_details) override {
on_instrument_details_ready_called_ = true;
}
void OnInstrumentDetailsError() override {
on_instrument_details_error_called_ = true;
}
bool WasOnInstrumentDetailsReadyCalled() {
return on_instrument_details_ready_called_;
}
bool WasOnInstrumentDetailsErrorCalled() {
return on_instrument_details_error_called_;
}
private:
bool on_instrument_details_ready_called_ = false;
bool on_instrument_details_error_called_ = false;
};
class FakePaymentRequestDelegate : public PaymentRequestDelegate {
public:
FakePaymentRequestDelegate()
: locale_("en-US"),
last_committed_url_("https://shop.com"),
personal_data_("en-US"),
test_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)),
payments_client_(test_shared_loader_factory_,
/*identity_manager=*/nullptr,
/*account_info_getter=*/nullptr),
full_card_request_(&autofill_client_,
&payments_client_,
&personal_data_) {}
void ShowDialog(PaymentRequest* request) override {}
void CloseDialog() override {}
void ShowErrorMessage() override {}
autofill::PersonalDataManager* GetPersonalDataManager() override {
return nullptr;
}
const std::string& GetApplicationLocale() const override { return locale_; }
bool IsIncognito() const override { return false; }
bool IsSslCertificateValid() override { return true; }
const GURL& GetLastCommittedURL() const override {
return last_committed_url_;
}
void DoFullCardRequest(
const autofill::CreditCard& credit_card,
base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>
result_delegate) override {
full_card_request_card_ = credit_card;
full_card_result_delegate_ = result_delegate;
}
autofill::AddressNormalizer* GetAddressNormalizer() override {
return &address_normalizer_;
}
void CompleteFullCardRequest() {
full_card_result_delegate_->OnFullCardRequestSucceeded(
full_card_request_, full_card_request_card_, base::ASCIIToUTF16("123"));
}
autofill::RegionDataLoader* GetRegionDataLoader() override { return nullptr; }
ukm::UkmRecorder* GetUkmRecorder() override { return nullptr; }
private:
std::string locale_;
const GURL last_committed_url_;
autofill::TestAddressNormalizer address_normalizer_;
autofill::PersonalDataManager personal_data_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
autofill::TestAutofillClient autofill_client_;
autofill::payments::PaymentsClient payments_client_;
autofill::payments::FullCardRequest full_card_request_;
autofill::CreditCard full_card_request_card_;
base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>
full_card_result_delegate_;
DISALLOW_COPY_AND_ASSIGN(FakePaymentRequestDelegate);
};
} // namespace
class AutofillPaymentInstrumentTest : public testing::Test {
protected:
AutofillPaymentInstrumentTest()
: address_(autofill::test::GetFullProfile()),
local_card_(autofill::test::GetCreditCard()),
billing_profiles_({&address_}) {
local_card_.set_billing_address_id(address_.guid());
}
autofill::CreditCard& local_credit_card() { return local_card_; }
const std::vector<autofill::AutofillProfile*>& billing_profiles() {
return billing_profiles_;
}
private:
autofill::AutofillProfile address_;
autofill::CreditCard local_card_;
std::vector<autofill::AutofillProfile*> billing_profiles_;
DISALLOW_COPY_AND_ASSIGN(AutofillPaymentInstrumentTest);
};
// A valid local credit card is a valid instrument for payment.
TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment) {
AutofillPaymentInstrument instrument(
"visa", local_credit_card(),
/*matches_merchant_card_type_exactly=*/true, billing_profiles(), "en-US",
nullptr);
EXPECT_TRUE(instrument.IsCompleteForPayment());
EXPECT_TRUE(instrument.GetMissingInfoLabel().empty());
}
// An expired local card is still a valid instrument for payment.
TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment_Expired) {
autofill::CreditCard& card = local_credit_card();
card.SetExpirationYear(2016); // Expired.
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_TRUE(instrument.IsCompleteForPayment());
EXPECT_EQ(base::string16(), instrument.GetMissingInfoLabel());
}
// A local card with no name is not a valid instrument for payment.
TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment_NoName) {
autofill::CreditCard& card = local_credit_card();
card.SetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
base::ASCIIToUTF16(""), "en-US");
base::string16 missing_info;
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_FALSE(instrument.IsCompleteForPayment());
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_NAME_ON_CARD_REQUIRED),
instrument.GetMissingInfoLabel());
}
// A local card with no name is not a valid instrument for payment.
TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment_NoNumber) {
autofill::CreditCard& card = local_credit_card();
card.SetNumber(base::ASCIIToUTF16(""));
base::string16 missing_info;
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_FALSE(instrument.IsCompleteForPayment());
EXPECT_EQ(l10n_util::GetStringUTF16(
IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE),
instrument.GetMissingInfoLabel());
}
// A local card with no billing address id is not a valid instrument for
// payment.
TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment_NoBillinbAddressId) {
autofill::CreditCard& card = local_credit_card();
card.set_billing_address_id("");
base::string16 missing_info;
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_FALSE(instrument.IsCompleteForPayment());
EXPECT_EQ(
l10n_util::GetStringUTF16(IDS_PAYMENTS_CARD_BILLING_ADDRESS_REQUIRED),
instrument.GetMissingInfoLabel());
}
// A local card with an invalid billing address id is not a valid instrument for
// payment.
TEST_F(AutofillPaymentInstrumentTest,
IsCompleteForPayment_InvalidBillinbAddressId) {
autofill::CreditCard& card = local_credit_card();
card.set_billing_address_id("InvalidBillingAddressId");
base::string16 missing_info;
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_FALSE(instrument.IsCompleteForPayment());
EXPECT_EQ(
l10n_util::GetStringUTF16(IDS_PAYMENTS_CARD_BILLING_ADDRESS_REQUIRED),
instrument.GetMissingInfoLabel());
}
// A local card with no name and no number is not a valid instrument for
// payment.
TEST_F(AutofillPaymentInstrumentTest,
IsCompleteForPayment_MultipleThingsMissing) {
autofill::CreditCard& card = local_credit_card();
card.SetNumber(base::ASCIIToUTF16(""));
card.SetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
base::ASCIIToUTF16(""), "en-US");
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_FALSE(instrument.IsCompleteForPayment());
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_MORE_INFORMATION_REQUIRED),
instrument.GetMissingInfoLabel());
}
// A Masked (server) card is a valid instrument for payment.
TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment_MaskedCard) {
autofill::CreditCard card = autofill::test::GetMaskedServerCard();
ASSERT_GT(billing_profiles().size(), 0UL);
card.set_billing_address_id(billing_profiles()[0]->guid());
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_TRUE(instrument.IsCompleteForPayment());
EXPECT_TRUE(instrument.GetMissingInfoLabel().empty());
}
// An expired masked (server) card is still a valid instrument for payment.
TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment_ExpiredMaskedCard) {
autofill::CreditCard card = autofill::test::GetMaskedServerCard();
ASSERT_GT(billing_profiles().size(), 0UL);
card.set_billing_address_id(billing_profiles()[0]->guid());
card.SetExpirationYear(2016); // Expired.
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_TRUE(instrument.IsCompleteForPayment());
EXPECT_EQ(base::string16(), instrument.GetMissingInfoLabel());
}
// An expired card is a valid instrument for canMakePayment.
TEST_F(AutofillPaymentInstrumentTest, IsValidForCanMakePayment_Minimal) {
autofill::CreditCard& card = local_credit_card();
card.SetExpirationYear(2016); // Expired.
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_TRUE(instrument.IsValidForCanMakePayment());
}
// An expired Masked (server) card is a valid instrument for canMakePayment.
TEST_F(AutofillPaymentInstrumentTest, IsValidForCanMakePayment_MaskedCard) {
autofill::CreditCard card = autofill::test::GetMaskedServerCard();
card.SetExpirationYear(2016); // Expired.
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_TRUE(instrument.IsValidForCanMakePayment());
}
// A card with no name is not a valid instrument for canMakePayment.
TEST_F(AutofillPaymentInstrumentTest, IsValidForCanMakePayment_NoName) {
autofill::CreditCard& card = local_credit_card();
card.SetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
base::ASCIIToUTF16(""), "en-US");
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_FALSE(instrument.IsValidForCanMakePayment());
}
// A card with no number is not a valid instrument for canMakePayment.
TEST_F(AutofillPaymentInstrumentTest, IsValidForCanMakePayment_NoNumber) {
autofill::CreditCard& card = local_credit_card();
card.SetNumber(base::ASCIIToUTF16(""));
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", nullptr);
EXPECT_FALSE(instrument.IsValidForCanMakePayment());
}
// Tests that the autofill instrument only calls OnInstrumentDetailsReady when
// the billing address has been normalized and the card has been unmasked.
TEST_F(AutofillPaymentInstrumentTest,
InvokePaymentApp_NormalizationBeforeUnmask) {
auto personal_data_manager =
std::make_unique<autofill::TestPersonalDataManager>();
TestPaymentRequestDelegate delegate(personal_data_manager.get());
delegate.DelayFullCardRequestCompletion();
delegate.test_address_normalizer()->DelayNormalization();
autofill::CreditCard& card = local_credit_card();
card.SetNumber(base::ASCIIToUTF16(""));
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", &delegate);
FakePaymentInstrumentDelegate instrument_delegate;
instrument.InvokePaymentApp(&instrument_delegate);
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled());
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled());
delegate.test_address_normalizer()->CompleteAddressNormalization();
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled());
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled());
delegate.CompleteFullCardRequest();
EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsReadyCalled());
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled());
}
// Tests that the autofill instrument only calls OnInstrumentDetailsReady when
// the billing address has been normalized and the card has been unmasked.
TEST_F(AutofillPaymentInstrumentTest,
InvokePaymentApp_UnmaskBeforeNormalization) {
auto personal_data_manager =
std::make_unique<autofill::TestPersonalDataManager>();
TestPaymentRequestDelegate delegate(personal_data_manager.get());
delegate.DelayFullCardRequestCompletion();
delegate.test_address_normalizer()->DelayNormalization();
autofill::CreditCard& card = local_credit_card();
card.SetNumber(base::ASCIIToUTF16(""));
AutofillPaymentInstrument instrument(
"visa", card, /*matches_merchant_card_type_exactly=*/true,
billing_profiles(), "en-US", &delegate);
FakePaymentInstrumentDelegate instrument_delegate;
instrument.InvokePaymentApp(&instrument_delegate);
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled());
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled());
delegate.CompleteFullCardRequest();
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled());
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled());
delegate.test_address_normalizer()->CompleteAddressNormalization();
EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsReadyCalled());
EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled());
}
} // namespace payments