blob: 2622e1b8f6ead4173381ebcaa55df13b4ef7ce77 [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.
#import "ios/chrome/browser/payments/payment_response_helper.h"
#include <memory>
#include <string>
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_task_environment.h"
#include "components/autofill/core/browser/autofill_data_util.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/core/basic_card_response.h"
#include "components/payments/core/payment_request_data_util.h"
#import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#include "ios/chrome/browser/payments/payment_request_test_util.h"
#import "ios/chrome/browser/payments/test_payment_request.h"
#import "ios/chrome/browser/web/chrome_web_test.h"
#import "ios/testing/ocmock_complex_type_helper.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "third_party/ocmock/OCMock/OCMock.h"
#include "third_party/ocmock/gtest_support.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface PaymentResponseHelperConsumerMock
: OCMockComplexTypeHelper<PaymentResponseHelperConsumer>
@end
@implementation PaymentResponseHelperConsumerMock
typedef void (^mock_payment_response_helper_did_complete_with_payment_response)(
const payments::PaymentResponse&);
- (void)paymentResponseHelperDidReceivePaymentMethodDetails {
}
- (void)paymentResponseHelperDidFailToReceivePaymentMethodDetails {
}
- (void)paymentResponseHelperDidCompleteWithPaymentResponse:
(const payments::PaymentResponse&)paymentResponse {
return static_cast<
mock_payment_response_helper_did_complete_with_payment_response>(
[self blockForSelector:_cmd])(paymentResponse);
}
@end
namespace payments {
class PaymentRequestPaymentResponseHelperTest : public PlatformTest {
protected:
PaymentRequestPaymentResponseHelperTest()
: profile_(autofill::test::GetFullProfile()),
credit_card_(autofill::test::GetCreditCard()),
chrome_browser_state_(TestChromeBrowserState::Builder().Build()) {
personal_data_manager_.SetAutofillProfileEnabled(true);
personal_data_manager_.SetAutofillCreditCardEnabled(true);
personal_data_manager_.SetAutofillWalletImportEnabled(true);
personal_data_manager_.AddProfile(profile_);
payment_request_ = std::make_unique<TestPaymentRequest>(
payment_request_test_util::CreateTestWebPaymentRequest(),
chrome_browser_state_.get(), &web_state_, &personal_data_manager_);
}
std::string GetMethodName() {
return autofill::data_util::GetPaymentRequestData(credit_card_.network())
.basic_card_issuer_network;
}
std::string GetStringifiedDetails() {
autofill::AutofillProfile billing_address;
std::unique_ptr<base::DictionaryValue> response_value =
data_util::GetBasicCardResponseFromAutofillCreditCard(
credit_card_, base::ASCIIToUTF16("123"), billing_address, "en-US")
->ToDictionaryValue();
std::string stringified_details;
base::JSONWriter::Write(*response_value, &stringified_details);
return stringified_details;
}
TestPaymentRequest* payment_request() { return payment_request_.get(); }
private:
base::test::ScopedTaskEnvironment scoped_task_evironment_;
autofill::AutofillProfile profile_;
autofill::CreditCard credit_card_;
web::TestWebState web_state_;
autofill::TestPersonalDataManager personal_data_manager_;
std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
std::unique_ptr<TestPaymentRequest> payment_request_;
};
// Tests that calling the PaymentResponseHelper's delegate method which signals
// that the full payment method details have been successfully received, causes
// the PaymentResponseHelper's delegate method to get called with the
// appropriate payment response.
TEST_F(PaymentRequestPaymentResponseHelperTest, PaymentResponse) {
// Mock the consumer.
id consumer =
[OCMockObject mockForProtocol:@protocol(PaymentResponseHelperConsumer)];
id consumer_mock([[PaymentResponseHelperConsumerMock alloc]
initWithRepresentedObject:consumer]);
SEL selector =
@selector(paymentResponseHelperDidCompleteWithPaymentResponse:);
[consumer_mock onSelector:selector
callBlockExpectation:^(const PaymentResponse& response) {
// Check if all the expected values were set.
EXPECT_EQ(GetMethodName(), response.method_name);
EXPECT_EQ(GetStringifiedDetails(), response.details);
EXPECT_TRUE(!!response.shipping_address);
EXPECT_EQ("US", response.shipping_address->country);
ASSERT_EQ(2U, response.shipping_address->address_line.size());
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(std::string(),
response.shipping_address->dependent_locality);
EXPECT_EQ("91111", response.shipping_address->postal_code);
EXPECT_EQ(std::string(), response.shipping_address->sorting_code);
EXPECT_EQ(std::string(), 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);
EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"), response.payer_name);
EXPECT_EQ(base::ASCIIToUTF16("+16502111111"), response.payer_phone);
EXPECT_EQ(base::ASCIIToUTF16("johndoe@hades.com"),
response.payer_email);
}];
PaymentResponseHelper payment_response_helper(consumer_mock,
payment_request());
payment_response_helper.OnInstrumentDetailsReady(GetMethodName(),
GetStringifiedDetails());
}
// Tests that the generated PaymentResponse has a shipping address only if one
// is requested.
TEST_F(PaymentRequestPaymentResponseHelperTest, PaymentResponseNoShipping) {
// Mock the consumer.
id consumer =
[OCMockObject mockForProtocol:@protocol(PaymentResponseHelperConsumer)];
id consumer_mock([[PaymentResponseHelperConsumerMock alloc]
initWithRepresentedObject:consumer]);
SEL selector =
@selector(paymentResponseHelperDidCompleteWithPaymentResponse:);
[consumer_mock onSelector:selector
callBlockExpectation:^(const PaymentResponse& response) {
EXPECT_FALSE(!!response.shipping_address);
EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"), response.payer_name);
EXPECT_EQ(base::ASCIIToUTF16("+16502111111"), response.payer_phone);
EXPECT_EQ(base::ASCIIToUTF16("johndoe@hades.com"),
response.payer_email);
}];
payment_request()->web_payment_request().options.request_shipping = false;
PaymentResponseHelper payment_response_helper(consumer_mock,
payment_request());
payment_response_helper.OnInstrumentDetailsReady(GetMethodName(),
GetStringifiedDetails());
}
// Tests that the generated PaymentResponse has contact information only if it
// is requested.
TEST_F(PaymentRequestPaymentResponseHelperTest, PaymentResponseNoContact) {
// Mock the consumer.
id consumer =
[OCMockObject mockForProtocol:@protocol(PaymentResponseHelperConsumer)];
id consumer_mock([[PaymentResponseHelperConsumerMock alloc]
initWithRepresentedObject:consumer]);
SEL selector =
@selector(paymentResponseHelperDidCompleteWithPaymentResponse:);
[consumer_mock onSelector:selector
callBlockExpectation:^(const PaymentResponse& response) {
EXPECT_EQ(base::string16(), response.payer_name);
EXPECT_EQ(base::string16(), response.payer_phone);
EXPECT_EQ(base::string16(), response.payer_email);
}];
payment_request()->web_payment_request().options.request_payer_name = false;
payment_request()->web_payment_request().options.request_payer_phone = false;
payment_request()->web_payment_request().options.request_payer_email = false;
PaymentResponseHelper payment_response_helper(consumer_mock,
payment_request());
payment_response_helper.OnInstrumentDetailsReady(GetMethodName(),
GetStringifiedDetails());
}
// Tests that the generated PaymentResponse has contact information only if it
// is requested.
TEST_F(PaymentRequestPaymentResponseHelperTest, PaymentResponseOneContact) {
// Mock the consumer.
id consumer =
[OCMockObject mockForProtocol:@protocol(PaymentResponseHelperConsumer)];
id consumer_mock([[PaymentResponseHelperConsumerMock alloc]
initWithRepresentedObject:consumer]);
SEL selector =
@selector(paymentResponseHelperDidCompleteWithPaymentResponse:);
[consumer_mock onSelector:selector
callBlockExpectation:^(const PaymentResponse& response) {
EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"), response.payer_name);
EXPECT_EQ(base::string16(), response.payer_phone);
EXPECT_EQ(base::string16(), response.payer_email);
}];
payment_request()->web_payment_request().options.request_payer_phone = false;
payment_request()->web_payment_request().options.request_payer_email = false;
PaymentResponseHelper payment_response_helper(consumer_mock,
payment_request());
payment_response_helper.OnInstrumentDetailsReady(GetMethodName(),
GetStringifiedDetails());
}
// Tests that the generated PaymentResponse has contact information only if it
// is requested.
TEST_F(PaymentRequestPaymentResponseHelperTest, PaymentResponseSomeContact) {
// Mock the consumer.
id consumer =
[OCMockObject mockForProtocol:@protocol(PaymentResponseHelperConsumer)];
id consumer_mock([[PaymentResponseHelperConsumerMock alloc]
initWithRepresentedObject:consumer]);
SEL selector =
@selector(paymentResponseHelperDidCompleteWithPaymentResponse:);
[consumer_mock onSelector:selector
callBlockExpectation:^(const PaymentResponse& response) {
EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"), response.payer_name);
EXPECT_EQ(base::ASCIIToUTF16("johndoe@hades.com"),
response.payer_email);
EXPECT_EQ(base::string16(), response.payer_phone);
}];
payment_request()->web_payment_request().options.request_payer_phone = false;
PaymentResponseHelper payment_response_helper(consumer_mock,
payment_request());
payment_response_helper.OnInstrumentDetailsReady(GetMethodName(),
GetStringifiedDetails());
}
// Tests that the phone number in the contact information of the generated
// PaymentResponse is formatted into E.164 if the number is valid.
TEST_F(PaymentRequestPaymentResponseHelperTest,
PaymentResponseContactPhoneIsFormatted_IfNumberIsValid) {
// Mock the consumer.
id consumer =
[OCMockObject mockForProtocol:@protocol(PaymentResponseHelperConsumer)];
id consumer_mock([[PaymentResponseHelperConsumerMock alloc]
initWithRepresentedObject:consumer]);
SEL selector =
@selector(paymentResponseHelperDidCompleteWithPaymentResponse:);
[consumer_mock onSelector:selector
callBlockExpectation:^(const PaymentResponse& response) {
EXPECT_EQ(base::ASCIIToUTF16("+15152231234"), response.payer_phone);
}];
payment_request()->selected_contact_profile()->SetRawInfo(
autofill::PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("(515) 223-1234"));
payment_request()->web_payment_request().options.request_payer_name = false;
payment_request()->web_payment_request().options.request_payer_email = false;
PaymentResponseHelper payment_response_helper(consumer_mock,
payment_request());
payment_response_helper.OnInstrumentDetailsReady(GetMethodName(),
GetStringifiedDetails());
}
// Tests that the phone number in the contact information of the generated
// PaymentResponse is not minimumly formatted(removing non-digit letters) if
// the number is invalid.
TEST_F(PaymentRequestPaymentResponseHelperTest,
PaymentResponseContactPhoneIsMinimumlyFormatted_IfNumberIsInValid) {
// Mock the consumer.
id consumer =
[OCMockObject mockForProtocol:@protocol(PaymentResponseHelperConsumer)];
id consumer_mock([[PaymentResponseHelperConsumerMock alloc]
initWithRepresentedObject:consumer]);
SEL selector =
@selector(paymentResponseHelperDidCompleteWithPaymentResponse:);
[consumer_mock onSelector:selector
callBlockExpectation:^(const PaymentResponse& response) {
EXPECT_EQ(base::ASCIIToUTF16("5151231234"), response.payer_phone);
}];
payment_request()->selected_contact_profile()->SetRawInfo(
autofill::PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("(515) 123-1234"));
payment_request()->web_payment_request().options.request_payer_name = false;
payment_request()->web_payment_request().options.request_payer_email = false;
PaymentResponseHelper payment_response_helper(consumer_mock,
payment_request());
payment_response_helper.OnInstrumentDetailsReady(GetMethodName(),
GetStringifiedDetails());
}
} // payments