1// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import "ios/web_view/internal/autofill/cwv_credit_card_saver_internal.h"
6
7#import <UIKit/UIKit.h>
8#include <memory>
9
10#include "base/bind.h"
11#include "base/run_loop.h"
12#include "base/test/bind.h"
13#import "base/test/ios/wait_util.h"
14#include "components/autofill/core/browser/autofill_client.h"
15#include "components/autofill/core/browser/autofill_test_utils.h"
16#include "components/autofill/core/browser/payments/legal_message_line.h"
17#include "components/autofill/core/browser/payments/test_legal_message_line.h"
18#include "ios/web/public/test/web_task_environment.h"
19#import "ios/web_view/internal/autofill/cwv_credit_card_internal.h"
20#include "ios/web_view/test/test_with_locale_and_resources.h"
21#include "testing/gtest/include/gtest/gtest.h"
22#include "testing/gtest_mac.h"
23
24#if !defined(__has_feature) || !__has_feature(objc_arc)
25#error "This file requires ARC support."
26#endif
27
28using base::test::ios::kWaitForActionTimeout;
29using base::test::ios::WaitUntilConditionOrTimeout;
30
31namespace ios_web_view {
32class CWVCreditCardSaverTest : public TestWithLocaleAndResources {
33 protected:
34  CWVCreditCardSaverTest() {}
35
36  web::WebTaskEnvironment task_environment_;
37};
38
39// Tests CWVCreditCardSaver properly initializes.
40TEST_F(CWVCreditCardSaverTest, Initialization) {
41  autofill::CreditCard credit_card = autofill::test::GetCreditCard();
42  autofill::AutofillClient::SaveCreditCardOptions options;
43  autofill::LegalMessageLines legal_message_lines = {
44      autofill::TestLegalMessageLine("Test line 1",
45                                     {autofill::LegalMessageLine::Link(
46                                         5, 9, "http://www.chromium.org/")})};
47  autofill::AutofillClient::UploadSaveCardPromptCallback callback;
48
49  CWVCreditCardSaver* credit_card_saver =
50      [[CWVCreditCardSaver alloc] initWithCreditCard:credit_card
51                                         saveOptions:options
52                                   legalMessageLines:legal_message_lines
53                                  savePromptCallback:std::move(callback)];
54
55  EXPECT_EQ(credit_card, *credit_card_saver.creditCard.internalCard);
56  ASSERT_EQ(1U, credit_card_saver.legalMessages.count);
57  NSAttributedString* legal_message =
58      credit_card_saver.legalMessages.firstObject;
59  EXPECT_NSEQ(@"Test line 1", legal_message.string);
60  NSRange range;
61  id link = [legal_message attribute:NSLinkAttributeName
62                             atIndex:5
63                      effectiveRange:&range];
64  EXPECT_NSEQ([NSURL URLWithString:@"http://www.chromium.org/"], link);
65  EXPECT_TRUE(NSEqualRanges(NSMakeRange(5, 4), range));
66}
67
68// Tests when user ignores credit card save.
69TEST_F(CWVCreditCardSaverTest, Ignore) {
70  autofill::CreditCard credit_card = autofill::test::GetCreditCard();
71  autofill::AutofillClient::SaveCreditCardOptions options;
72
73  BOOL callback_called = NO;
74  autofill::AutofillClient::UploadSaveCardPromptCallback callback =
75      base::BindLambdaForTesting(
76          [&](autofill::AutofillClient::SaveCardOfferUserDecision decision,
77              const autofill::AutofillClient::UserProvidedCardDetails&
78                  user_provided_card_details) {
79            callback_called = YES;
80            EXPECT_EQ(autofill::AutofillClient::IGNORED, decision);
81          });
82
83  CWVCreditCardSaver* credit_card_saver =
84      [[CWVCreditCardSaver alloc] initWithCreditCard:credit_card
85                                         saveOptions:options
86                                   legalMessageLines:{}
87                                  savePromptCallback:std::move(callback)];
88  // Force -[CWVCreditCardSaver dealloc].
89  credit_card_saver = nil;
90
91  EXPECT_TRUE(callback_called);
92}
93
94// Tests when user declines a save.
95TEST_F(CWVCreditCardSaverTest, Decline) {
96  autofill::CreditCard credit_card = autofill::test::GetCreditCard();
97  autofill::AutofillClient::SaveCreditCardOptions options;
98  autofill::AutofillClient::LocalSaveCardPromptCallback local_callback;
99
100  BOOL callback_called = NO;
101  autofill::AutofillClient::UploadSaveCardPromptCallback callback =
102      base::BindLambdaForTesting(
103          [&](autofill::AutofillClient::SaveCardOfferUserDecision decision,
104              const autofill::AutofillClient::UserProvidedCardDetails&
105                  user_provided_card_details) {
106            callback_called = YES;
107            EXPECT_EQ(autofill::AutofillClient::DECLINED, decision);
108          });
109
110  CWVCreditCardSaver* credit_card_saver =
111      [[CWVCreditCardSaver alloc] initWithCreditCard:credit_card
112                                         saveOptions:options
113                                   legalMessageLines:{}
114                                  savePromptCallback:std::move(callback)];
115  [credit_card_saver decline];
116
117  EXPECT_TRUE(callback_called);
118}
119
120// Tests when user accepts a save.
121TEST_F(CWVCreditCardSaverTest, Accept) {
122  autofill::CreditCard credit_card = autofill::test::GetCreditCard();
123  autofill::AutofillClient::SaveCreditCardOptions options;
124
125  BOOL callback_called = NO;
126  autofill::AutofillClient::UploadSaveCardPromptCallback callback =
127      base::BindLambdaForTesting(
128          [&](autofill::AutofillClient::SaveCardOfferUserDecision decision,
129              const autofill::AutofillClient::UserProvidedCardDetails&
130                  user_provided_card_details) {
131            callback_called = YES;
132            EXPECT_EQ(autofill::AutofillClient::ACCEPTED, decision);
133          });
134
135  CWVCreditCardSaver* credit_card_saver =
136      [[CWVCreditCardSaver alloc] initWithCreditCard:credit_card
137                                         saveOptions:options
138                                   legalMessageLines:{}
139                                  savePromptCallback:std::move(callback)];
140  BOOL risk_data_used = NO;
141  [credit_card_saver loadRiskData:base::BindLambdaForTesting(
142                                      [&](const std::string& risk_data) {
143                                        EXPECT_EQ(risk_data, "dummy-risk-data");
144                                        risk_data_used = YES;
145                                      })];
146  __block BOOL completion_called = NO;
147  [credit_card_saver acceptWithRiskData:@"dummy-risk-data"
148                      completionHandler:^(BOOL cardSaved) {
149                        EXPECT_TRUE(cardSaved);
150                        completion_called = YES;
151                      }];
152  [credit_card_saver handleCreditCardUploadCompleted:YES];
153
154  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^bool {
155    base::RunLoop().RunUntilIdle();
156    return completion_called;
157  }));
158
159  EXPECT_TRUE(risk_data_used);
160  EXPECT_TRUE(callback_called);
161}
162
163}  // namespace ios_web_view
164