1 import { render } from '@testing-library/react';
2 import userEvent from '@testing-library/user-event';
4 import { useCard } from '@proton/components/payments/react-extensions/useCard';
5 import { apiMock } from '@proton/testing';
7 import type { Props } from './CreditCard';
8 import CreditCard from './CreditCard';
14 const TestComponent = (rest?: Partial<Props>) => {
15 const cardHook = useCard(
24 verifyPayment: jest.fn(),
31 errors={cardHook.errors}
32 fieldsStatus={cardHook.fieldsStatus}
33 setCardProperty={cardHook.setCardProperty}
39 it('should render', () => {
40 const { container } = render(<TestComponent />);
41 expect(container).not.toBeEmptyDOMElement();
44 it('should be not narrow by default', () => {
45 const { queryByTestId } = render(<TestComponent />);
47 expect(queryByTestId('credit-card-form-container')).toHaveClass('field-two-container');
48 expect(queryByTestId('credit-card-form-container')).not.toHaveClass('credit-card-form--narrow');
51 it('should render narrow', () => {
52 const { queryByTestId } = render(<TestComponent forceNarrow />);
54 expect(queryByTestId('credit-card-form-container')).toHaveClass('field-two-container');
55 expect(queryByTestId('credit-card-form-container')).toHaveClass('credit-card-form--narrow');
58 it('should not accept invalid CVC input', async () => {
59 const { queryByTestId } = render(<TestComponent />);
60 const cvcInput = queryByTestId('cvc') as HTMLInputElement;
62 await userEvent.type(cvcInput, 'abc');
64 expect(cvcInput.value).toBe('');
67 describe('autoadvancer', () => {
68 it('should move the cursor to the expiration date when credit card number is entered', async () => {
69 const { queryByTestId } = render(<TestComponent />);
70 const ccNumber = queryByTestId('ccnumber') as HTMLInputElement;
72 await userEvent.type(ccNumber, '4242424242424242');
74 const expInput = queryByTestId('exp') as HTMLInputElement;
76 expect(expInput).toHaveFocus();
79 it('should move the cursor to the cvc when expiration date is entered', async () => {
80 const { queryByTestId } = render(<TestComponent />);
81 const expInput = queryByTestId('exp') as HTMLInputElement;
83 await userEvent.type(expInput, '1232');
85 const cvcInput = queryByTestId('cvc') as HTMLInputElement;
87 expect(cvcInput).toHaveFocus();
90 it('should move the cursor to the zip when cvc is entered', async () => {
91 const { queryByTestId } = render(<TestComponent />);
92 const cvcInput = queryByTestId('cvc') as HTMLInputElement;
94 await userEvent.type(cvcInput, '123');
96 const zipInput = queryByTestId('postalCode') as HTMLInputElement;
98 expect(zipInput).toHaveFocus();
101 it('narrow - should move the cursor to the expiration date when credit card number is entered', async () => {
102 const { queryByTestId } = render(<TestComponent forceNarrow />);
103 const ccNumber = queryByTestId('ccnumber') as HTMLInputElement;
105 await userEvent.type(ccNumber, '4242424242424242');
107 const expInput = queryByTestId('exp') as HTMLInputElement;
109 expect(expInput).toHaveFocus();
112 it('narrow should move the cursor to the cvc when expiration date is entered', async () => {
113 const { queryByTestId } = render(<TestComponent forceNarrow />);
114 const expInput = queryByTestId('exp') as HTMLInputElement;
116 await userEvent.type(expInput, '1232');
118 const cvcInput = queryByTestId('cvc') as HTMLInputElement;
120 expect(cvcInput).toHaveFocus();
123 it('narrow should move the cursor to the zip when cvc is entered', async () => {
124 const { queryByTestId } = render(<TestComponent forceNarrow />);
125 const cvcInput = queryByTestId('cvc') as HTMLInputElement;
127 await userEvent.type(cvcInput, '123');
129 const zipInput = queryByTestId('postalCode') as HTMLInputElement;
131 expect(zipInput).toHaveFocus();
134 it('should not move cursor the second time, if user decides to edit the field', async () => {
135 const { queryByTestId } = render(<TestComponent />);
136 const ccNumber = queryByTestId('ccnumber') as HTMLInputElement;
138 await userEvent.type(ccNumber, '4242424242424242');
139 expect(ccNumber.value).toBe('4242 4242 4242 4242'); // formatted
141 const expInput = queryByTestId('exp') as HTMLInputElement;
142 expect(expInput).toHaveFocus();
144 await userEvent.click(ccNumber);
145 await userEvent.type(ccNumber, '4242424242424242');
146 expect(ccNumber).toHaveFocus();
149 it('should not move the cursor if the credit card number is invalid', async () => {
150 const { queryByTestId } = render(<TestComponent />);
151 const ccNumber = queryByTestId('ccnumber') as HTMLInputElement;
153 await userEvent.type(ccNumber, '4000000000000000');
154 expect(ccNumber.value).toBe('4000 0000 0000 0000'); // formatted
156 expect(ccNumber).toHaveFocus();
159 it('should not move the cursor if the expiration date is invalid', async () => {
160 const { queryByTestId } = render(<TestComponent />);
161 const expInput = queryByTestId('exp') as HTMLInputElement;
163 await userEvent.type(expInput, '1211');
164 expect(expInput.value).toBe('12/11');
166 expect(expInput).toHaveFocus();
169 it('should not move the cursor if the cvc is invalid', async () => {
170 const { queryByTestId } = render(<TestComponent />);
171 const cvcInput = queryByTestId('cvc') as HTMLInputElement;
173 await userEvent.type(cvcInput, '12');
175 expect(cvcInput).toHaveFocus();
178 it('should move the cursor when user enter correct AmEx card number', async () => {
179 const { queryByTestId } = render(<TestComponent />);
180 const ccNumber = queryByTestId('ccnumber') as HTMLInputElement;
182 const num = '374245455400126';
183 expect(num.length).toBe(15); // not 16 as for Visa
185 await userEvent.type(ccNumber, num);
186 expect(ccNumber.value).toBe('3742 454554 00126'); // formatted
188 const expInput = queryByTestId('exp') as HTMLInputElement;
189 expect(expInput).toHaveFocus();
192 it('should move the cursor to ZIP when user enter correct AmEx card number and 4-digit security code', async () => {
193 const { queryByTestId } = render(<TestComponent />);
194 const ccNumber = queryByTestId('ccnumber') as HTMLInputElement;
196 const num = '374245455400126';
197 expect(num.length).toBe(15); // not 16 as for Visa
199 await userEvent.type(ccNumber, num);
201 const expInput = queryByTestId('exp') as HTMLInputElement;
202 expect(expInput).toHaveFocus();
203 await userEvent.type(expInput, '1232');
205 const cvcInput = queryByTestId('cvc') as HTMLInputElement;
206 expect(cvcInput).toHaveFocus();
208 await userEvent.type(cvcInput, '1234');
210 const zipInput = queryByTestId('postalCode') as HTMLInputElement;
211 expect(zipInput).toHaveFocus();
212 expect(cvcInput.value).toBe('1234');