Skip to content

Commit 2d1bb7f

Browse files
author
Alejandro Gastelum Flores
committed
Added tests
1 parent 5639540 commit 2d1bb7f

File tree

5 files changed

+589
-11
lines changed

5 files changed

+589
-11
lines changed

packages/react-paypal-js/src/components/cardFields/PayPalCVVField.test.tsx

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import React from "react";
2-
import { render, waitFor } from "@testing-library/react";
2+
import { render, waitFor, screen, fireEvent } from "@testing-library/react";
33
import { ErrorBoundary } from "react-error-boundary";
4-
import { loadScript } from "@paypal/paypal-js";
4+
import {
5+
loadScript,
6+
PayPalCardFieldsIndividualFieldOptions,
7+
} from "@paypal/paypal-js";
58
import { mock } from "jest-mock-extended";
69

710
import { PayPalCVVField } from "./PayPalCVVField";
@@ -134,6 +137,122 @@ describe("PayPalCVVField", () => {
134137
spyConsoleError.mockRestore();
135138
});
136139

140+
test("should not create stale closure when passing callbacks", async () => {
141+
const spyConsoleError = jest
142+
.spyOn(console, "error")
143+
.mockImplementation();
144+
145+
const MOCK_CARDFIELD_ID = "mock-cardfield";
146+
147+
window.paypal = {
148+
CardFields: jest.fn(
149+
() =>
150+
({
151+
isEligible: jest.fn().mockReturnValue(true),
152+
CVVField: jest.fn(
153+
(
154+
options: PayPalCardFieldsIndividualFieldOptions,
155+
) => ({
156+
render: jest.fn(
157+
(element: string | HTMLElement) => {
158+
// Simulate adding element
159+
if (typeof element !== "string") {
160+
const child =
161+
document.createElement("div");
162+
child.setAttribute(
163+
"id",
164+
MOCK_CARDFIELD_ID,
165+
);
166+
child.setAttribute(
167+
"data-testid",
168+
MOCK_CARDFIELD_ID,
169+
);
170+
if (options?.inputEvents?.onFocus) {
171+
child.addEventListener(
172+
"focus",
173+
options.inputEvents
174+
.onFocus as unknown as EventListener,
175+
);
176+
}
177+
element.append(child);
178+
}
179+
return Promise.resolve();
180+
},
181+
),
182+
close: jest.fn(() => Promise.resolve()),
183+
}),
184+
),
185+
}) as unknown as PayPalCardFieldsComponent,
186+
),
187+
version: "",
188+
};
189+
190+
const onFocusFn = jest.fn();
191+
192+
const Wrapper = () => {
193+
const [count, setCount] = React.useState(0);
194+
195+
function onFocus() {
196+
onFocusFn(count);
197+
}
198+
199+
return (
200+
<div>
201+
<button
202+
data-testid="count-button"
203+
onClick={() => setCount(count + 1)}
204+
>
205+
Count: {count}
206+
</button>
207+
<PayPalScriptProvider
208+
options={{
209+
clientId: "test-client",
210+
currency: "USD",
211+
intent: "authorize",
212+
components: "card-fields",
213+
dataClientToken: "test-data-client-token",
214+
}}
215+
>
216+
<PayPalCardFieldsProvider
217+
onApprove={mockOnApprove}
218+
createOrder={mockCreateOrder}
219+
onError={mockOnError}
220+
>
221+
<PayPalCVVField
222+
inputEvents={{
223+
onFocus: onFocus,
224+
}}
225+
/>
226+
</PayPalCardFieldsProvider>
227+
</PayPalScriptProvider>
228+
{wrapper}
229+
</div>
230+
);
231+
};
232+
233+
render(<Wrapper />);
234+
await waitFor(() => expect(onError).toHaveBeenCalledTimes(0));
235+
236+
const countButton = screen.getByTestId("count-button");
237+
const cvvField = screen.getByTestId(MOCK_CARDFIELD_ID);
238+
239+
expect(screen.getByText("Count: 0")).toBeInTheDocument();
240+
fireEvent.focus(cvvField);
241+
expect(onFocusFn).toHaveBeenCalledWith(0);
242+
243+
fireEvent.click(countButton);
244+
expect(await screen.findByText("Count: 1")).toBeInTheDocument();
245+
fireEvent.focus(cvvField);
246+
expect(onFocusFn).toHaveBeenCalledWith(1);
247+
248+
fireEvent.click(countButton);
249+
expect(await screen.findByText("Count: 2")).toBeInTheDocument();
250+
fireEvent.focus(cvvField);
251+
expect(onFocusFn).toHaveBeenCalledWith(2);
252+
253+
spyConsoleError.mockRestore();
254+
});
255+
137256
test("should render component with a specific placeholder", async () => {
138257
const spyConsoleError = jest
139258
.spyOn(console, "error")

packages/react-paypal-js/src/components/cardFields/PayPalCardFieldsProvider.test.tsx

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React from "react";
2-
import { render, waitFor } from "@testing-library/react";
1+
import React, { useState } from "react";
2+
import { render, waitFor, screen, fireEvent } from "@testing-library/react";
33
import { ErrorBoundary } from "react-error-boundary";
44
import { PayPalNamespace, loadScript } from "@paypal/paypal-js";
55
import { mock } from "jest-mock-extended";
@@ -11,7 +11,10 @@ import { PayPalNumberField } from "./PayPalNumberField";
1111
import { PayPalCVVField } from "./PayPalCVVField";
1212
import { PayPalExpiryField } from "./PayPalExpiryField";
1313

14-
import type { PayPalCardFieldsComponent } from "@paypal/paypal-js";
14+
import type {
15+
PayPalCardFieldsComponent,
16+
PayPalCardFieldsComponentOptions,
17+
} from "@paypal/paypal-js";
1518
import type { ReactNode } from "react";
1619

1720
const MOCK_ELEMENT_ID = "mock-element";
@@ -377,4 +380,103 @@ describe("PayPalCardFieldsProvider", () => {
377380

378381
spyConsoleError.mockRestore();
379382
});
383+
384+
test("should not create a stale closure when passing callbacks", async () => {
385+
window.paypal = {
386+
CardFields: jest.fn(
387+
(options?: PayPalCardFieldsComponentOptions) =>
388+
({
389+
isEligible: jest.fn().mockReturnValue(true),
390+
NumberField: jest.fn().mockReturnValue({
391+
render: jest.fn((element: string | HTMLElement) => {
392+
// Simulate adding element
393+
if (typeof element !== "string") {
394+
const child = document.createElement("div");
395+
child.setAttribute("id", MOCK_ELEMENT_ID);
396+
child.setAttribute(
397+
"data-testid",
398+
MOCK_ELEMENT_ID,
399+
);
400+
if (options?.inputEvents?.onFocus) {
401+
child.addEventListener(
402+
"focus",
403+
options.inputEvents
404+
.onFocus as unknown as EventListener,
405+
);
406+
}
407+
element.append(child);
408+
}
409+
return Promise.resolve();
410+
}),
411+
close: jest.fn(() => Promise.resolve()),
412+
}),
413+
}) as unknown as PayPalCardFieldsComponent,
414+
),
415+
version: "",
416+
};
417+
418+
const onFocusFn = jest.fn();
419+
420+
const Wrapper = () => {
421+
const [count, setCount] = useState(0);
422+
423+
function onFocus() {
424+
onFocusFn(count);
425+
}
426+
427+
return (
428+
<div>
429+
<button
430+
data-testid="count-button"
431+
onClick={() => setCount(count + 1)}
432+
>
433+
Count: {count}
434+
</button>
435+
<PayPalScriptProvider
436+
options={{
437+
clientId: "test-client",
438+
currency: "USD",
439+
intent: "authorize",
440+
dataClientToken: "test-data-client-token",
441+
components: "card-fields",
442+
}}
443+
>
444+
<PayPalCardFieldsProvider
445+
onApprove={mockOnApprove}
446+
createOrder={mockCreateOrder}
447+
onError={mockOnError}
448+
inputEvents={{
449+
onFocus,
450+
}}
451+
>
452+
<PayPalNumberField />
453+
</PayPalCardFieldsProvider>
454+
</PayPalScriptProvider>
455+
</div>
456+
);
457+
};
458+
459+
render(<Wrapper />);
460+
461+
await waitFor(() => {
462+
expect(getMockElementsRendered().length).toEqual(1);
463+
});
464+
465+
const countButton = screen.getByTestId("count-button");
466+
const numberField = screen.getByTestId(MOCK_ELEMENT_ID);
467+
468+
expect(screen.getByText("Count: 0")).toBeInTheDocument();
469+
fireEvent.focus(numberField);
470+
expect(onFocusFn).toHaveBeenCalledWith(0);
471+
472+
fireEvent.click(countButton);
473+
expect(await screen.findByText("Count: 1")).toBeInTheDocument();
474+
fireEvent.focus(numberField);
475+
expect(onFocusFn).toHaveBeenCalledWith(1);
476+
477+
fireEvent.click(countButton);
478+
expect(await screen.findByText("Count: 2")).toBeInTheDocument();
479+
fireEvent.focus(numberField);
480+
expect(onFocusFn).toHaveBeenCalledWith(2);
481+
});
380482
});

packages/react-paypal-js/src/components/cardFields/PayPalExpiryField.test.tsx

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import React from "react";
2-
import { render, waitFor } from "@testing-library/react";
2+
import { fireEvent, render, waitFor, screen } from "@testing-library/react";
33
import { ErrorBoundary } from "react-error-boundary";
4-
import { loadScript } from "@paypal/paypal-js";
4+
import {
5+
loadScript,
6+
PayPalCardFieldsIndividualFieldOptions,
7+
} from "@paypal/paypal-js";
58
import { mock } from "jest-mock-extended";
69

710
import { PayPalExpiryField } from "./PayPalExpiryField";
@@ -134,6 +137,122 @@ describe("PayPalExpiryField", () => {
134137
spyConsoleError.mockRestore();
135138
});
136139

140+
test("should not create stale closure when passing callbacks", async () => {
141+
const spyConsoleError = jest
142+
.spyOn(console, "error")
143+
.mockImplementation();
144+
145+
const MOCK_CARDFIELD_ID = "mock-cardfield";
146+
147+
window.paypal = {
148+
CardFields: jest.fn(
149+
() =>
150+
({
151+
isEligible: jest.fn().mockReturnValue(true),
152+
ExpiryField: jest.fn(
153+
(
154+
options: PayPalCardFieldsIndividualFieldOptions,
155+
) => ({
156+
render: jest.fn(
157+
(element: string | HTMLElement) => {
158+
// Simulate adding element
159+
if (typeof element !== "string") {
160+
const child =
161+
document.createElement("div");
162+
child.setAttribute(
163+
"id",
164+
MOCK_CARDFIELD_ID,
165+
);
166+
child.setAttribute(
167+
"data-testid",
168+
MOCK_CARDFIELD_ID,
169+
);
170+
if (options?.inputEvents?.onFocus) {
171+
child.addEventListener(
172+
"focus",
173+
options.inputEvents
174+
.onFocus as unknown as EventListener,
175+
);
176+
}
177+
element.append(child);
178+
}
179+
return Promise.resolve();
180+
},
181+
),
182+
close: jest.fn(() => Promise.resolve()),
183+
}),
184+
),
185+
}) as unknown as PayPalCardFieldsComponent,
186+
),
187+
version: "",
188+
};
189+
190+
const onFocusFn = jest.fn();
191+
192+
const Wrapper = () => {
193+
const [count, setCount] = React.useState(0);
194+
195+
function onFocus() {
196+
onFocusFn(count);
197+
}
198+
199+
return (
200+
<div>
201+
<button
202+
data-testid="count-button"
203+
onClick={() => setCount(count + 1)}
204+
>
205+
Count: {count}
206+
</button>
207+
<PayPalScriptProvider
208+
options={{
209+
clientId: "test-client",
210+
currency: "USD",
211+
intent: "authorize",
212+
components: "card-fields",
213+
dataClientToken: "test-data-client-token",
214+
}}
215+
>
216+
<PayPalCardFieldsProvider
217+
onApprove={mockOnApprove}
218+
createOrder={mockCreateOrder}
219+
onError={mockOnError}
220+
>
221+
<PayPalExpiryField
222+
inputEvents={{
223+
onFocus: onFocus,
224+
}}
225+
/>
226+
</PayPalCardFieldsProvider>
227+
</PayPalScriptProvider>
228+
{wrapper}
229+
</div>
230+
);
231+
};
232+
233+
render(<Wrapper />);
234+
await waitFor(() => expect(onError).toHaveBeenCalledTimes(0));
235+
236+
const countButton = screen.getByTestId("count-button");
237+
const expiryField = screen.getByTestId(MOCK_CARDFIELD_ID);
238+
239+
expect(screen.getByText("Count: 0")).toBeInTheDocument();
240+
fireEvent.focus(expiryField);
241+
expect(onFocusFn).toHaveBeenCalledWith(0);
242+
243+
fireEvent.click(countButton);
244+
expect(await screen.findByText("Count: 1")).toBeInTheDocument();
245+
fireEvent.focus(expiryField);
246+
expect(onFocusFn).toHaveBeenCalledWith(1);
247+
248+
fireEvent.click(countButton);
249+
expect(await screen.findByText("Count: 2")).toBeInTheDocument();
250+
fireEvent.focus(expiryField);
251+
expect(onFocusFn).toHaveBeenCalledWith(2);
252+
253+
spyConsoleError.mockRestore();
254+
});
255+
137256
test("should render component with a specific placeholder", async () => {
138257
const spyConsoleError = jest
139258
.spyOn(console, "error")

0 commit comments

Comments
 (0)