1 import { render, waitFor } from '@testing-library/react';
3 import type { ViewPaymentMethod } from '@proton/components/payments/client-extensions';
4 import type { CardFieldStatus } from '@proton/components/payments/react-extensions/useCard';
5 import type { CardModel, SavedPaymentMethod, SavedPaymentMethodInternal } from '@proton/payments';
6 import { MethodStorage, PAYMENT_METHOD_TYPES } from '@proton/payments';
7 import { ChargebeeEnabled } from '@proton/shared/lib/interfaces';
8 import { applyHOCs, withApi, withCache, withConfig } from '@proton/testing';
10 import { PaymentsNoApi } from './Payment';
12 let apiMock: jest.Mock;
13 jest.mock('../../hooks/useApi', () => {
23 const defaultCard: CardModel = {
32 const cardFieldStatus: CardFieldStatus = {
41 let paymentMethods: SavedPaymentMethod[];
44 let lastUsedMethod: ViewPaymentMethod;
46 let allMethods: ViewPaymentMethod[];
48 const PaymentContext = applyHOCs(withApi(), withConfig(), withCache())(PaymentsNoApi);
54 Type: PAYMENT_METHOD_TYPES.CARD,
62 Name: 'Arthur Morgan',
66 External: MethodStorage.INTERNAL,
70 Type: PAYMENT_METHOD_TYPES.PAYPAL,
73 BillingAgreementID: 'Billing1',
75 Payer: 'buyer@example.com',
77 External: MethodStorage.INTERNAL,
81 Type: PAYMENT_METHOD_TYPES.CARD,
89 Name: 'Arthur Morgan',
93 External: MethodStorage.INTERNAL,
101 text: 'Visa ending in 4242',
102 // some plausible value
108 icon: 'brand-paypal',
109 text: 'PayPal - someId',
116 text: 'Visa ending in 3220',
121 ] as ViewPaymentMethod[],
126 text: 'New credit/debit card',
133 ] as ViewPaymentMethod[],
136 lastUsedMethod = options.usedMethods[options.usedMethods.length - 1];
137 allMethods = [...options.usedMethods, ...options.methods];
140 describe('Payment', () => {
145 it('should render', () => {
146 const method = PAYMENT_METHOD_TYPES.CARD;
147 const savedMethodInternal = paymentMethods.find(({ ID }) => method === ID) as SavedPaymentMethodInternal;
160 cardFieldStatus={cardFieldStatus}
161 isAuthenticated={true}
162 lastUsedMethod={lastUsedMethod}
163 allMethods={allMethods}
164 savedMethodInternal={savedMethodInternal}
167 iframeHandles={null as any}
168 chargebeeCard={null as any}
169 chargebeePaypal={null as any}
170 bitcoinInhouse={null as any}
171 bitcoinChargebee={null as any}
172 hasSomeVpnPlan={false}
173 paymentComponentLoaded={jest.fn()}
174 isChargebeeEnabled={() => ChargebeeEnabled.INHOUSE_FORCED}
176 paymentStatus={undefined}
180 bankAccount: {} as any,
187 it('should render <Alert3DS> if the payment method is card', async () => {
188 let { container } = render(
192 method={PAYMENT_METHOD_TYPES.CARD}
199 cardFieldStatus={cardFieldStatus}
200 isAuthenticated={true}
201 lastUsedMethod={lastUsedMethod}
202 allMethods={allMethods}
203 savedMethodInternal={undefined}
206 iframeHandles={null as any}
207 chargebeeCard={null as any}
208 chargebeePaypal={null as any}
209 bitcoinInhouse={null as any}
210 bitcoinChargebee={null as any}
211 hasSomeVpnPlan={false}
212 paymentComponentLoaded={jest.fn()}
213 isChargebeeEnabled={() => ChargebeeEnabled.INHOUSE_FORCED}
215 paymentStatus={undefined}
219 bankAccount: {} as any,
225 await waitFor(() => {
226 expect(container).toHaveTextContent('We use 3-D Secure to protect your payments');
230 it('should not render <Alert3DS> if flow type is "signup"', async () => {
231 let { container } = render(
235 method={PAYMENT_METHOD_TYPES.CARD}
242 cardFieldStatus={cardFieldStatus}
243 isAuthenticated={true}
244 lastUsedMethod={lastUsedMethod}
245 allMethods={allMethods}
246 savedMethodInternal={undefined}
249 iframeHandles={null as any}
250 chargebeeCard={null as any}
251 chargebeePaypal={null as any}
252 bitcoinInhouse={null as any}
253 bitcoinChargebee={null as any}
254 hasSomeVpnPlan={false}
255 paymentComponentLoaded={jest.fn()}
256 isChargebeeEnabled={() => ChargebeeEnabled.INHOUSE_FORCED}
258 paymentStatus={undefined}
262 bankAccount: {} as any,
268 await waitFor(() => {
269 expect(container).not.toHaveTextContent('We use 3-D Secure to protect your payments');
273 it('should render <Alert3DS> if user selected a perviously used credit card (customPaymentMethod)', async () => {
274 apiMock.mockImplementation((query) => {
275 if (query.url === 'payments/v4/methods') {
279 ID: 'my-custom-method-123',
280 Type: PAYMENT_METHOD_TYPES.CARD,
291 ID: 'my-custom-method-123',
292 Type: PAYMENT_METHOD_TYPES.CARD,
300 Name: 'Arthur Morgan',
304 External: MethodStorage.INTERNAL,
308 let savedMethodInternal = paymentMethods[0] as SavedPaymentMethodInternal;
310 let { container } = render(
314 method="my-custom-method-123"
321 cardFieldStatus={cardFieldStatus}
322 isAuthenticated={true}
323 lastUsedMethod={lastUsedMethod}
324 allMethods={allMethods}
325 savedMethodInternal={savedMethodInternal}
328 iframeHandles={{} as any}
329 chargebeeCard={null as any}
330 chargebeePaypal={null as any}
331 bitcoinInhouse={null as any}
332 bitcoinChargebee={null as any}
333 hasSomeVpnPlan={false}
334 paymentComponentLoaded={jest.fn()}
335 isChargebeeEnabled={() => ChargebeeEnabled.INHOUSE_FORCED}
337 paymentStatus={undefined}
341 bankAccount: {} as any,
347 await waitFor(() => {
348 expect(container).toHaveTextContent('We use 3-D Secure to protect your payments');
352 it('should not render <Alert3DS> if user selected a perviously used method which is not a credit card', async () => {
353 apiMock.mockImplementation((query) => {
354 if (query.url === 'payments/v4/methods') {
358 ID: 'my-custom-method-123',
359 Type: PAYMENT_METHOD_TYPES.PAYPAL,
370 ID: 'my-custom-method-123',
371 Type: PAYMENT_METHOD_TYPES.PAYPAL,
374 BillingAgreementID: 'Billing1',
378 External: MethodStorage.INTERNAL,
382 let savedMethodInternal: SavedPaymentMethodInternal = paymentMethods[0] as SavedPaymentMethodInternal;
384 let { container } = render(
388 method="my-custom-method-123"
395 cardFieldStatus={cardFieldStatus}
396 isAuthenticated={true}
397 lastUsedMethod={lastUsedMethod}
398 allMethods={allMethods}
399 savedMethodInternal={savedMethodInternal}
402 iframeHandles={null as any}
403 chargebeeCard={null as any}
404 chargebeePaypal={null as any}
405 bitcoinInhouse={null as any}
406 bitcoinChargebee={null as any}
407 hasSomeVpnPlan={false}
408 paymentComponentLoaded={jest.fn()}
409 isChargebeeEnabled={() => ChargebeeEnabled.INHOUSE_FORCED}
411 paymentStatus={undefined}
415 bankAccount: {} as any,
421 await waitFor(() => {
422 expect(container).not.toHaveTextContent('We use 3-D Secure to protect your payments');