1 // Copyright 2016 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 #include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
6 
7 #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_currency_amount.h"
8 #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_details_modifier.h"
9 #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_method_data.h"
10 #include "third_party/blink/renderer/core/dom/document.h"
11 #include "third_party/blink/renderer/platform/bindings/script_state.h"
12 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
13 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
14 
15 namespace blink {
16 namespace {
17 
18 static int g_unique_id = 0;
19 // PaymentItem and PaymentShippingOption have identical structure
20 // except for the "id" field, which is present only in PaymentShippingOption.
21 template <typename PaymentItemOrPaymentShippingOption>
SetValues(PaymentItemOrPaymentShippingOption * original,PaymentTestDataToChange data,PaymentTestModificationType modification_type,const String & value_to_use)22 void SetValues(PaymentItemOrPaymentShippingOption* original,
23                PaymentTestDataToChange data,
24                PaymentTestModificationType modification_type,
25                const String& value_to_use) {
26   PaymentCurrencyAmount* item_amount = PaymentCurrencyAmount::Create();
27   if (data == kPaymentTestDataCurrencyCode) {
28     if (modification_type == kPaymentTestOverwriteValue)
29       item_amount->setCurrency(value_to_use);
30   } else {
31     item_amount->setCurrency("USD");
32   }
33 
34   if (data == kPaymentTestDataValue) {
35     if (modification_type == kPaymentTestOverwriteValue)
36       item_amount->setValue(value_to_use);
37   } else {
38     item_amount->setValue("9.99");
39   }
40 
41   if (data != kPaymentTestDataAmount ||
42       modification_type != kPaymentTestRemoveKey)
43     original->setAmount(item_amount);
44 
45   if (data == kPaymentTestDataLabel) {
46     if (modification_type == kPaymentTestOverwriteValue)
47       original->setLabel(value_to_use);
48   } else {
49     original->setLabel("Label");
50   }
51 }
52 
BuildPaymentDetailsBase(PaymentTestDetailToChange detail,PaymentTestDataToChange data,PaymentTestModificationType modification_type,const String & value_to_use,PaymentDetailsBase * details)53 void BuildPaymentDetailsBase(PaymentTestDetailToChange detail,
54                              PaymentTestDataToChange data,
55                              PaymentTestModificationType modification_type,
56                              const String& value_to_use,
57                              PaymentDetailsBase* details) {
58   PaymentItem* item = nullptr;
59   if (detail == kPaymentTestDetailItem) {
60     item = BuildPaymentItemForTest(data, modification_type, value_to_use);
61   } else {
62     item = BuildPaymentItemForTest();
63   }
64   DCHECK(item);
65 
66   PaymentShippingOption* shipping_option = nullptr;
67   if (detail == kPaymentTestDetailShippingOption) {
68     shipping_option =
69         BuildShippingOptionForTest(data, modification_type, value_to_use);
70   } else {
71     shipping_option = BuildShippingOptionForTest();
72   }
73   DCHECK(shipping_option);
74 
75   PaymentDetailsModifier* modifier = nullptr;
76   if (detail == kPaymentTestDetailModifierTotal ||
77       detail == kPaymentTestDetailModifierItem) {
78     modifier = BuildPaymentDetailsModifierForTest(
79         detail, data, modification_type, value_to_use);
80   } else {
81     modifier = BuildPaymentDetailsModifierForTest();
82   }
83   DCHECK(modifier);
84 
85   details->setDisplayItems(HeapVector<Member<PaymentItem>>(1, item));
86   details->setShippingOptions(
87       HeapVector<Member<PaymentShippingOption>>(1, shipping_option));
88   details->setModifiers(
89       HeapVector<Member<PaymentDetailsModifier>>(1, modifier));
90 }
91 
92 }  // namespace
93 
BuildPaymentItemForTest(PaymentTestDataToChange data,PaymentTestModificationType modification_type,const String & value_to_use)94 PaymentItem* BuildPaymentItemForTest(
95     PaymentTestDataToChange data,
96     PaymentTestModificationType modification_type,
97     const String& value_to_use) {
98   DCHECK_NE(data, kPaymentTestDataId);
99   PaymentItem* item = PaymentItem::Create();
100   SetValues(item, data, modification_type, value_to_use);
101   return item;
102 }
103 
BuildShippingOptionForTest(PaymentTestDataToChange data,PaymentTestModificationType modification_type,const String & value_to_use)104 PaymentShippingOption* BuildShippingOptionForTest(
105     PaymentTestDataToChange data,
106     PaymentTestModificationType modification_type,
107     const String& value_to_use) {
108   PaymentShippingOption* shipping_option = PaymentShippingOption::Create();
109   if (data == kPaymentTestDataId) {
110     if (modification_type == kPaymentTestOverwriteValue)
111       shipping_option->setId(value_to_use);
112   } else {
113     shipping_option->setId("id" + String::Number(g_unique_id++));
114   }
115   SetValues(shipping_option, data, modification_type, value_to_use);
116   return shipping_option;
117 }
118 
BuildPaymentDetailsModifierForTest(PaymentTestDetailToChange detail,PaymentTestDataToChange data,PaymentTestModificationType modification_type,const String & value_to_use)119 PaymentDetailsModifier* BuildPaymentDetailsModifierForTest(
120     PaymentTestDetailToChange detail,
121     PaymentTestDataToChange data,
122     PaymentTestModificationType modification_type,
123     const String& value_to_use) {
124   PaymentItem* total = nullptr;
125   if (detail == kPaymentTestDetailModifierTotal) {
126     total = BuildPaymentItemForTest(data, modification_type, value_to_use);
127   } else {
128     total = BuildPaymentItemForTest();
129   }
130   DCHECK(total);
131 
132   PaymentItem* item = nullptr;
133   if (detail == kPaymentTestDetailModifierItem) {
134     item = BuildPaymentItemForTest(data, modification_type, value_to_use);
135   } else {
136     item = BuildPaymentItemForTest();
137   }
138   DCHECK(item);
139 
140   PaymentDetailsModifier* modifier = PaymentDetailsModifier::Create();
141   modifier->setSupportedMethod("foo");
142   modifier->setTotal(total);
143   modifier->setAdditionalDisplayItems(HeapVector<Member<PaymentItem>>(1, item));
144   return modifier;
145 }
146 
BuildPaymentDetailsInitForTest(PaymentTestDetailToChange detail,PaymentTestDataToChange data,PaymentTestModificationType modification_type,const String & value_to_use)147 PaymentDetailsInit* BuildPaymentDetailsInitForTest(
148     PaymentTestDetailToChange detail,
149     PaymentTestDataToChange data,
150     PaymentTestModificationType modification_type,
151     const String& value_to_use) {
152   PaymentDetailsInit* details = PaymentDetailsInit::Create();
153   BuildPaymentDetailsBase(detail, data, modification_type, value_to_use,
154                           details);
155 
156   if (detail == kPaymentTestDetailTotal) {
157     details->setTotal(
158         BuildPaymentItemForTest(data, modification_type, value_to_use));
159   } else {
160     details->setTotal(BuildPaymentItemForTest());
161   }
162 
163   return details;
164 }
165 
BuildPaymentDetailsUpdateForTest(PaymentTestDetailToChange detail,PaymentTestDataToChange data,PaymentTestModificationType modification_type,const String & value_to_use)166 PaymentDetailsUpdate* BuildPaymentDetailsUpdateForTest(
167     PaymentTestDetailToChange detail,
168     PaymentTestDataToChange data,
169     PaymentTestModificationType modification_type,
170     const String& value_to_use) {
171   PaymentDetailsUpdate* details = PaymentDetailsUpdate::Create();
172   BuildPaymentDetailsBase(detail, data, modification_type, value_to_use,
173                           details);
174 
175   if (detail == kPaymentTestDetailTotal) {
176     details->setTotal(
177         BuildPaymentItemForTest(data, modification_type, value_to_use));
178   } else {
179     details->setTotal(BuildPaymentItemForTest());
180   }
181 
182   if (detail == kPaymentTestDetailError)
183     details->setError(value_to_use);
184 
185   return details;
186 }
187 
BuildPaymentDetailsErrorMsgForTest(const String & value_to_use)188 PaymentDetailsUpdate* BuildPaymentDetailsErrorMsgForTest(
189     const String& value_to_use) {
190   return BuildPaymentDetailsUpdateForTest(
191       kPaymentTestDetailError, kPaymentTestDataNone, kPaymentTestOverwriteValue,
192       value_to_use);
193 }
194 
BuildPaymentMethodDataForTest()195 HeapVector<Member<PaymentMethodData>> BuildPaymentMethodDataForTest() {
196   HeapVector<Member<PaymentMethodData>> method_data(
197       1, PaymentMethodData::Create());
198   method_data[0]->setSupportedMethod("foo");
199   return method_data;
200 }
201 
BuildPaymentResponseForTest()202 payments::mojom::blink::PaymentResponsePtr BuildPaymentResponseForTest() {
203   payments::mojom::blink::PaymentResponsePtr result =
204       payments::mojom::blink::PaymentResponse::New();
205   result->payer = payments::mojom::blink::PayerDetail::New();
206   return result;
207 }
208 
BuildPaymentAddressForTest()209 payments::mojom::blink::PaymentAddressPtr BuildPaymentAddressForTest() {
210   payments::mojom::blink::PaymentAddressPtr result =
211       payments::mojom::blink::PaymentAddress::New();
212   result->country = "US";
213   return result;
214 }
215 
PaymentRequestV8TestingScope()216 PaymentRequestV8TestingScope::PaymentRequestV8TestingScope()
217     : V8TestingScope(KURL("https://www.example.com/")) {
218   GetDocument().SetSecureContextModeForTesting(
219       SecureContextMode::kSecureContext);
220 }
221 
PaymentRequestMockFunctionScope(ScriptState * script_state)222 PaymentRequestMockFunctionScope::PaymentRequestMockFunctionScope(
223     ScriptState* script_state)
224     : script_state_(script_state) {}
225 
~PaymentRequestMockFunctionScope()226 PaymentRequestMockFunctionScope::~PaymentRequestMockFunctionScope() {
227   v8::MicrotasksScope::PerformCheckpoint(script_state_->GetIsolate());
228   for (MockFunction* mock_function : mock_functions_) {
229     testing::Mock::VerifyAndClearExpectations(mock_function);
230   }
231 }
232 
ExpectCall(String * captor)233 v8::Local<v8::Function> PaymentRequestMockFunctionScope::ExpectCall(
234     String* captor) {
235   mock_functions_.push_back(
236       MakeGarbageCollected<MockFunction>(script_state_, captor));
237   EXPECT_CALL(*mock_functions_.back(), Call(testing::_));
238   return mock_functions_.back()->Bind();
239 }
240 
ExpectCall()241 v8::Local<v8::Function> PaymentRequestMockFunctionScope::ExpectCall() {
242   mock_functions_.push_back(MakeGarbageCollected<MockFunction>(script_state_));
243   EXPECT_CALL(*mock_functions_.back(), Call(testing::_));
244   return mock_functions_.back()->Bind();
245 }
246 
ExpectNoCall()247 v8::Local<v8::Function> PaymentRequestMockFunctionScope::ExpectNoCall() {
248   mock_functions_.push_back(MakeGarbageCollected<MockFunction>(script_state_));
249   EXPECT_CALL(*mock_functions_.back(), Call(testing::_)).Times(0);
250   return mock_functions_.back()->Bind();
251 }
252 
ACTION_P2(SaveValueIn,script_state,captor)253 ACTION_P2(SaveValueIn, script_state, captor) {
254   *captor = ToCoreString(
255       arg0.V8Value()->ToString(script_state->GetContext()).ToLocalChecked());
256 }
257 
MockFunction(ScriptState * script_state)258 PaymentRequestMockFunctionScope::MockFunction::MockFunction(
259     ScriptState* script_state)
260     : ScriptFunction(script_state) {
261   ON_CALL(*this, Call(testing::_)).WillByDefault(testing::ReturnArg<0>());
262 }
263 
MockFunction(ScriptState * script_state,String * captor)264 PaymentRequestMockFunctionScope::MockFunction::MockFunction(
265     ScriptState* script_state,
266     String* captor)
267     : ScriptFunction(script_state), value_(captor) {
268   ON_CALL(*this, Call(testing::_))
269       .WillByDefault(
270           testing::DoAll(SaveValueIn(WrapPersistent(script_state), value_),
271                          testing::ReturnArg<0>()));
272 }
273 
Bind()274 v8::Local<v8::Function> PaymentRequestMockFunctionScope::MockFunction::Bind() {
275   return BindToV8Function();
276 }
277 
278 }  // namespace blink
279