blob: ed9757c551825cfb04a5c2f4d5eca236824d3811 [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/content/payment_response_helper.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/payments/content/payment_request_spec.h"
#include "components/payments/core/autofill_payment_instrument.h"
#include "components/payments/core/payment_request_delegate.h"
#include "components/payments/mojom/payment_request.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace payments {
class FakePaymentRequestDelegate : public PaymentRequestDelegate {
public:
FakePaymentRequestDelegate(
autofill::PersonalDataManager* personal_data_manager)
: personal_data_manager_(personal_data_manager),
locale_("en-US"),
last_committed_url_("https://shop.com") {}
void ShowDialog(PaymentRequest* request) override {}
void CloseDialog() override {}
void ShowErrorMessage() override {}
autofill::PersonalDataManager* GetPersonalDataManager() override {
return personal_data_manager_;
}
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 {
result_delegate->OnFullCardRequestSucceeded(credit_card,
base::ASCIIToUTF16("123"));
}
std::unique_ptr<const ::i18n::addressinput::Source> GetAddressInputSource()
override {
return nullptr;
}
std::unique_ptr<::i18n::addressinput::Storage> GetAddressInputStorage()
override {
return nullptr;
}
private:
autofill::PersonalDataManager* personal_data_manager_;
std::string locale_;
const GURL last_committed_url_;
DISALLOW_COPY_AND_ASSIGN(FakePaymentRequestDelegate);
};
class PaymentResponseHelperTest : public testing::Test,
public PaymentResponseHelper::Delegate {
protected:
PaymentResponseHelperTest()
: payment_request_delegate_(&test_personal_data_manager_),
address_(autofill::test::GetFullProfile()),
billing_addresses_({&address_}) {
test_personal_data_manager_.AddTestingProfile(&address_);
// Setup the autofill payment instrument.
autofill::CreditCard visa_card = autofill::test::GetCreditCard();
visa_card.set_billing_address_id(address_.guid());
visa_card.set_use_count(5u);
autofill_instrument_ = base::MakeUnique<AutofillPaymentInstrument>(
"visa", visa_card, billing_addresses_, "en-US",
&payment_request_delegate_);
}
~PaymentResponseHelperTest() override {}
// PaymentRequestState::Delegate:
void OnPaymentResponseReady(mojom::PaymentResponsePtr response) override {
payment_response_ = std::move(response);
};
// Convenience method to create a PaymentRequestSpec with specified |details|
// and |method_data|.
void RecreateSpecWithOptionsAndDetails(
mojom::PaymentOptionsPtr options,
mojom::PaymentDetailsPtr details,
std::vector<mojom::PaymentMethodDataPtr> method_data) {
// The spec will be based on the |options| and |details| passed in.
spec_ = base::MakeUnique<PaymentRequestSpec>(
std::move(options), std::move(details), std::move(method_data), nullptr,
"en-US");
}
// Convenience method to create a PaymentRequestSpec with default details
// (one shipping option) and method data (only supports visa).
void RecreateSpecWithOptions(mojom::PaymentOptionsPtr options) {
// Create dummy PaymentDetails with a single shipping option.
std::vector<mojom::PaymentShippingOptionPtr> shipping_options;
mojom::PaymentShippingOptionPtr option =
mojom::PaymentShippingOption::New();
option->id = "option:1";
shipping_options.push_back(std::move(option));
mojom::PaymentDetailsPtr details = mojom::PaymentDetails::New();
details->shipping_options = std::move(shipping_options);
RecreateSpecWithOptionsAndDetails(std::move(options), std::move(details),
GetMethodDataForVisa());
}
// Convenience method that returns MethodData that supports Visa.
std::vector<mojom::PaymentMethodDataPtr> GetMethodDataForVisa() {
std::vector<mojom::PaymentMethodDataPtr> method_data;
mojom::PaymentMethodDataPtr entry = mojom::PaymentMethodData::New();
entry->supported_methods.push_back("visa");
method_data.push_back(std::move(entry));
return method_data;
}
PaymentRequestSpec* spec() { return spec_.get(); }
const mojom::PaymentResponsePtr& response() { return payment_response_; }
autofill::AutofillProfile* test_address() { return &address_; }
PaymentInstrument* test_instrument() { return autofill_instrument_.get(); }
private:
std::unique_ptr<PaymentRequestSpec> spec_;
mojom::PaymentResponsePtr payment_response_;
autofill::TestPersonalDataManager test_personal_data_manager_;
FakePaymentRequestDelegate payment_request_delegate_;
// Test data.
autofill::AutofillProfile address_;
const std::vector<autofill::AutofillProfile*> billing_addresses_;
std::unique_ptr<AutofillPaymentInstrument> autofill_instrument_;
};
// Test generating a PaymentResponse.
TEST_F(PaymentResponseHelperTest, GeneratePaymentResponse_SupportedMethod) {
// Default options (no shipping, no contact info).
RecreateSpecWithOptions(mojom::PaymentOptions::New());
// TODO(mathp): Currently synchronous, when async will need a RunLoop.
// "visa" is specified directly in the supportedMethods so it is returned
// as the method name.
PaymentResponseHelper helper("en-US", spec(), test_instrument(),
test_address(), test_address(), this);
EXPECT_EQ("visa", response()->method_name);
EXPECT_EQ(
"{\"billingAddress\":"
"{\"addressLine\":[\"666 Erebus St.\",\"Apt 8\"],"
"\"city\":\"Elysium\","
"\"country\":\"US\","
"\"organization\":\"Underworld\","
"\"phone\":\"16502111111\","
"\"postalCode\":\"91111\","
"\"recipient\":\"John H. Doe\","
"\"region\":\"CA\"},"
"\"cardNumber\":\"4111111111111111\","
"\"cardSecurityCode\":\"123\","
"\"cardholderName\":\"Test User\","
"\"expiryMonth\":\"11\","
"\"expiryYear\":\"2022\"}",
response()->stringified_details);
}
// Test generating a PaymentResponse when the method is specified through
// "basic-card".
TEST_F(PaymentResponseHelperTest, GeneratePaymentResponse_BasicCard) {
// The method data supports visa through basic-card.
mojom::PaymentMethodDataPtr entry = mojom::PaymentMethodData::New();
entry->supported_methods.push_back("basic-card");
entry->supported_networks.push_back(mojom::BasicCardNetwork::VISA);
std::vector<mojom::PaymentMethodDataPtr> method_data;
method_data.push_back(std::move(entry));
RecreateSpecWithOptionsAndDetails(mojom::PaymentOptions::New(),
mojom::PaymentDetails::New(),
std::move(method_data));
// TODO(mathp): Currently synchronous, when async will need a RunLoop.
// "basic-card" is specified so it is returned as the method name.
PaymentResponseHelper helper("en-US", spec(), test_instrument(),
test_address(), test_address(), this);
EXPECT_EQ("basic-card", response()->method_name);
EXPECT_EQ(
"{\"billingAddress\":"
"{\"addressLine\":[\"666 Erebus St.\",\"Apt 8\"],"
"\"city\":\"Elysium\","
"\"country\":\"US\","
"\"organization\":\"Underworld\","
"\"phone\":\"16502111111\","
"\"postalCode\":\"91111\","
"\"recipient\":\"John H. Doe\","
"\"region\":\"CA\"},"
"\"cardNumber\":\"4111111111111111\","
"\"cardSecurityCode\":\"123\","
"\"cardholderName\":\"Test User\","
"\"expiryMonth\":\"11\","
"\"expiryYear\":\"2022\"}",
response()->stringified_details);
}
// Tests the the generated PaymentResponse has the correct values for the
// shipping address.
TEST_F(PaymentResponseHelperTest, GeneratePaymentResponse_ShippingAddress) {
// Setup so that a shipping address is requested.
std::vector<mojom::PaymentShippingOptionPtr> shipping_options;
mojom::PaymentShippingOptionPtr option = mojom::PaymentShippingOption::New();
option->id = "option:1";
option->selected = true;
shipping_options.push_back(std::move(option));
mojom::PaymentDetailsPtr details = mojom::PaymentDetails::New();
details->shipping_options = std::move(shipping_options);
mojom::PaymentOptionsPtr options = mojom::PaymentOptions::New();
options->request_shipping = true;
RecreateSpecWithOptionsAndDetails(std::move(options), std::move(details),
GetMethodDataForVisa());
PaymentResponseHelper helper("en-US", spec(), test_instrument(),
test_address(), test_address(), this);
// Check that all the expected values were set.
EXPECT_EQ("US", response()->shipping_address->country);
EXPECT_EQ("666 Erebus St.", response()->shipping_address->address_line[0]);
EXPECT_EQ("Apt 8", response()->shipping_address->address_line[1]);
EXPECT_EQ("CA", response()->shipping_address->region);
EXPECT_EQ("Elysium", response()->shipping_address->city);
EXPECT_EQ("", response()->shipping_address->dependent_locality);
EXPECT_EQ("91111", response()->shipping_address->postal_code);
EXPECT_EQ("", response()->shipping_address->sorting_code);
EXPECT_EQ("", response()->shipping_address->language_code);
EXPECT_EQ("Underworld", response()->shipping_address->organization);
EXPECT_EQ("John H. Doe", response()->shipping_address->recipient);
EXPECT_EQ("16502111111", response()->shipping_address->phone);
}
// Tests the the generated PaymentResponse has the correct values for the
// contact details when all values are requested.
TEST_F(PaymentResponseHelperTest, GeneratePaymentResponse_ContactDetails_All) {
// Request all contact detail values.
mojom::PaymentOptionsPtr options = mojom::PaymentOptions::New();
options->request_payer_name = true;
options->request_payer_phone = true;
options->request_payer_email = true;
RecreateSpecWithOptions(std::move(options));
PaymentResponseHelper helper("en-US", spec(), test_instrument(),
test_address(), test_address(), this);
// Check that all the expected values were set.
EXPECT_EQ("John H. Doe", response()->payer_name.value());
EXPECT_EQ("+16502111111", response()->payer_phone.value());
EXPECT_EQ("johndoe@hades.com", response()->payer_email.value());
}
// Tests the the generated PaymentResponse has the correct values for the
// contact details when all values are requested.
TEST_F(PaymentResponseHelperTest, GeneratePaymentResponse_ContactDetails_Some) {
// Request one contact detail value.
mojom::PaymentOptionsPtr options = mojom::PaymentOptions::New();
options->request_payer_name = true;
RecreateSpecWithOptions(std::move(options));
PaymentResponseHelper helper("en-US", spec(), test_instrument(),
test_address(), test_address(), this);
// Check that the name was set, but not the other values.
EXPECT_EQ("John H. Doe", response()->payer_name.value());
EXPECT_FALSE(response()->payer_phone.has_value());
EXPECT_FALSE(response()->payer_email.has_value());
}
// Tests the the generated PaymentResponse has the correct values for the
// contact details when all values are requested.
TEST_F(PaymentResponseHelperTest,
GeneratePaymentResponse_ContactPhoneIsFormatted) {
// Request one contact detail value.
mojom::PaymentOptionsPtr options = mojom::PaymentOptions::New();
options->request_payer_phone = true;
test_address()->SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
base::UTF8ToUTF16("(515) 123-1234"));
RecreateSpecWithOptions(std::move(options));
PaymentResponseHelper helper("en-US", spec(), test_instrument(),
test_address(), test_address(), this);
// Check that the phone was formatted.
EXPECT_EQ("+15151231234", response()->payer_phone.value());
}
} // namespace payments