frames-react-native 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/cd.yml +36 -36
- package/README.md +36 -2
- package/__tests__/CardUtils.test.tsx +43 -0
- package/__tests__/FramesContextGuards.test.tsx +30 -0
- package/__tests__/HttpAndLogger.test.tsx +204 -0
- package/__tests__/Integration.test.tsx +99 -4
- package/__tests__/Unit.test.tsx +1 -1
- package/dist/Frames.d.ts +2 -2
- package/dist/Frames.js +6 -3
- package/dist/Frames.js.map +1 -1
- package/dist/components/CardNumber.js +6 -5
- package/dist/components/CardNumber.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/types/types.d.ts +7 -3
- package/dist/utils/http.js +9 -4
- package/dist/utils/http.js.map +1 -1
- package/package.json +1 -1
package/.github/workflows/cd.yml
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
name: Test and Deploy
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
10
|
|
|
11
11
|
jobs:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
verbose: true
|
|
12
|
+
test-and-coverage:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: 21
|
|
19
|
+
- run: npm ci
|
|
20
|
+
- run: npm test
|
|
21
|
+
- name: Upload coverage to Codecov
|
|
22
|
+
uses: codecov/codecov-action@v1
|
|
23
|
+
with:
|
|
24
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
25
|
+
verbose: true
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
27
|
+
publish-npm:
|
|
28
|
+
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
|
29
|
+
needs: test-and-coverage
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: actions/setup-node@v4
|
|
34
|
+
with:
|
|
35
|
+
node-version: 21
|
|
36
|
+
registry-url: https://registry.npmjs.org/
|
|
37
|
+
- run: npm ci
|
|
38
|
+
- run: npm run build
|
|
39
|
+
- run: cp -R src/icons dist/
|
|
40
|
+
- run: npm publish
|
|
41
|
+
env:
|
|
42
|
+
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
|
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ export default function App() {
|
|
|
57
57
|
<Frames
|
|
58
58
|
config={{
|
|
59
59
|
debug: true,
|
|
60
|
-
publicKey: "
|
|
60
|
+
publicKey: "pk_sbox_eo3yb3urja2ozf6ycgn5kuy7ke#",
|
|
61
61
|
}}
|
|
62
62
|
cardTokenized={(e) => {
|
|
63
63
|
alert(e.token);
|
|
@@ -144,7 +144,41 @@ const styles = StyleSheet.create({
|
|
|
144
144
|
|
|
145
145
|
## Trigger tokenization
|
|
146
146
|
|
|
147
|
-
The tokenization is triggered when the SubmitButton is pressed
|
|
147
|
+
The tokenization is triggered when the `SubmitButton` is pressed, or programmatically via a ref on `Frames`.
|
|
148
|
+
|
|
149
|
+
### Programmatic submit via ref
|
|
150
|
+
|
|
151
|
+
You can attach a ref to `Frames` and call `submitCard()` imperatively:
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import React, { useRef } from "react";
|
|
155
|
+
import { Frames, CardNumber, ExpiryDate, Cvv } from "frames-react-native";
|
|
156
|
+
import type { FramesRef } from "frames-react-native";
|
|
157
|
+
|
|
158
|
+
export const Example = () => {
|
|
159
|
+
const framesRef = useRef<FramesRef>(null);
|
|
160
|
+
|
|
161
|
+
const onCustomPress = () => {
|
|
162
|
+
framesRef.current?.submitCard();
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<Frames
|
|
167
|
+
ref={framesRef}
|
|
168
|
+
config={{ debug: true, publicKey: "pk_test_..." }}
|
|
169
|
+
cardTokenized={(e) => console.log(e.token)}
|
|
170
|
+
>
|
|
171
|
+
<CardNumber />
|
|
172
|
+
<ExpiryDate />
|
|
173
|
+
<Cvv />
|
|
174
|
+
{/* Use your own button UI */}
|
|
175
|
+
<MyCustomButton onPress={onCustomPress} />
|
|
176
|
+
</Frames>
|
|
177
|
+
);
|
|
178
|
+
};
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The process of getting the token is async, so the outcome of the tokenization will be shared in the `cardTokenized` or `cardTokenizationFailed` handlers.
|
|
148
182
|
|
|
149
183
|
## The `props` for the Frames wrapper component
|
|
150
184
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatCard,
|
|
3
|
+
getCardType,
|
|
4
|
+
getIcon,
|
|
5
|
+
isValidCard,
|
|
6
|
+
cvvLength,
|
|
7
|
+
isValidCvv,
|
|
8
|
+
isValidDate,
|
|
9
|
+
} from "../src/utils/card";
|
|
10
|
+
|
|
11
|
+
describe("card utils", () => {
|
|
12
|
+
it("formats and validates card number", () => {
|
|
13
|
+
expect(formatCard("4242424242424242")).toBe("4242 4242 4242 4242");
|
|
14
|
+
expect(isValidCard("4242 4242 4242 4242")).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("detects card type including extended whitelist (Discover)", () => {
|
|
18
|
+
expect(getCardType("6011111111111117")).toBe("Discover");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("cvvLength varies by type (Amex -> 4)", () => {
|
|
22
|
+
// Amex test number
|
|
23
|
+
const amex = "378282246310005";
|
|
24
|
+
expect(cvvLength(amex)).toBe(4);
|
|
25
|
+
expect(cvvLength("4242 4242 4242 4242")).toBe(3);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("validates cvv by inferred type", () => {
|
|
29
|
+
// Amex 4-digit CVC (It's an AMEX Test card number)
|
|
30
|
+
expect(isValidCvv("1234", "345678901234564")).toBe(true);
|
|
31
|
+
// Visa 3-digit CVC
|
|
32
|
+
expect(isValidCvv("123", "4242 4242 4242 4242")).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("getIcon returns undefined for unknown type", () => {
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
expect(getIcon("UnknownBrand")).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("isValidDate rejects incomplete or past dates", () => {
|
|
41
|
+
expect(isValidDate("06/")).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@testing-library/react-native";
|
|
3
|
+
|
|
4
|
+
import { CardNumber, ExpiryDate, Cvv, SubmitButton } from "../src/index";
|
|
5
|
+
|
|
6
|
+
describe("Component context guards", () => {
|
|
7
|
+
it("throws when CardNumber is rendered outside Frames", () => {
|
|
8
|
+
expect(() => render(<CardNumber />)).toThrow(
|
|
9
|
+
"It looks like you are trying to render the CardNumber outside of the Frames Component."
|
|
10
|
+
);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("throws when ExpiryDate is rendered outside Frames", () => {
|
|
14
|
+
expect(() => render(<ExpiryDate />)).toThrow(
|
|
15
|
+
"It looks like you are trying to render the ExpiryDate outside of the Frames Component."
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("throws when Cvv is rendered outside Frames", () => {
|
|
20
|
+
expect(() => render(<Cvv />)).toThrow(
|
|
21
|
+
"It looks like you are trying to render the Cvv outside of the Frames Component."
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("throws when SubmitButton is rendered outside Frames", () => {
|
|
26
|
+
expect(() => render(<SubmitButton title="Pay" />)).toThrow(
|
|
27
|
+
"It looks like you are trying to render the SubmitButton outside of the Frames Component."
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, fireEvent, waitFor } from "@testing-library/react-native";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
Frames,
|
|
6
|
+
CardNumber,
|
|
7
|
+
ExpiryDate,
|
|
8
|
+
Cvv,
|
|
9
|
+
SubmitButton,
|
|
10
|
+
} from "../src/index";
|
|
11
|
+
|
|
12
|
+
import { SANDBOX_LOGGER, LIVE_LOGGER } from "../src/utils/constants";
|
|
13
|
+
|
|
14
|
+
describe("http.tokenize and helpers", () => {
|
|
15
|
+
const { tokenize, formatDataForTokenization, getEnvironment } =
|
|
16
|
+
jest.requireActual("../src/utils/http");
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
global.fetch = jest.fn();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("tokenize returns json when response ok", async () => {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
global.fetch.mockResolvedValueOnce({
|
|
26
|
+
ok: true,
|
|
27
|
+
json: jest.fn().mockResolvedValue({ ok: true }),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const res = await tokenize({
|
|
31
|
+
key: "pk_sbox_dummy",
|
|
32
|
+
body: {
|
|
33
|
+
type: "card",
|
|
34
|
+
number: "4242424242424242",
|
|
35
|
+
expiry_month: "12",
|
|
36
|
+
expiry_year: "2030",
|
|
37
|
+
cvv: "123",
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(res).toEqual({ ok: true });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("tokenize throws json when response not ok", async () => {
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
global.fetch.mockResolvedValueOnce({
|
|
47
|
+
ok: false,
|
|
48
|
+
json: jest.fn().mockResolvedValue({ error: "bad" }),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await expect(
|
|
52
|
+
tokenize({
|
|
53
|
+
key: "pk_sbox_dummy",
|
|
54
|
+
body: {
|
|
55
|
+
type: "card",
|
|
56
|
+
number: "4242424242424242",
|
|
57
|
+
expiry_month: "12",
|
|
58
|
+
expiry_year: "2030",
|
|
59
|
+
cvv: "123",
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
).rejects.toEqual({ error: "bad" });
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("formatDataForTokenization maps fields and billing address including addressLine2", () => {
|
|
66
|
+
const { EXPIRY_DATE_DELIMITER } = require("../src/utils/constants");
|
|
67
|
+
const state = {
|
|
68
|
+
cardNumber: "4242 4242 4242 4242",
|
|
69
|
+
cardBin: { bin: null, scheme: null },
|
|
70
|
+
cardIcon: undefined,
|
|
71
|
+
cardType: null,
|
|
72
|
+
expiryDate: `12${EXPIRY_DATE_DELIMITER}30`,
|
|
73
|
+
cvv: "123",
|
|
74
|
+
cvvLength: 3,
|
|
75
|
+
validation: { cardNumber: true, expiryDate: true, cvv: true, card: true },
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const config = {
|
|
79
|
+
publicKey: "pk_sbox_dummy",
|
|
80
|
+
cardholder: {
|
|
81
|
+
name: "John Doe",
|
|
82
|
+
phone: "+1234567890",
|
|
83
|
+
billingAddress: {
|
|
84
|
+
addressLine1: "Line 1",
|
|
85
|
+
addressLine2: "Line 2",
|
|
86
|
+
city: "City",
|
|
87
|
+
state: "ST",
|
|
88
|
+
zip: "12345",
|
|
89
|
+
country: "US",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const params = formatDataForTokenization(state, config);
|
|
95
|
+
expect(params.key).toBe(config.publicKey);
|
|
96
|
+
expect(params.body.number).toBe("4242424242424242");
|
|
97
|
+
expect(params.body.expiry_month).toBe("12");
|
|
98
|
+
expect(params.body.expiry_year).toMatch(/^20\d{2}$/);
|
|
99
|
+
expect(params.body.cvv).toBe("123");
|
|
100
|
+
expect(params.body.name).toBe("John Doe");
|
|
101
|
+
expect(params.body.billing_address).toEqual({
|
|
102
|
+
address_line1: "Line 1",
|
|
103
|
+
address_line2: "Line 2",
|
|
104
|
+
city: "City",
|
|
105
|
+
state: "ST",
|
|
106
|
+
zip: "12345",
|
|
107
|
+
country: "US",
|
|
108
|
+
});
|
|
109
|
+
expect(params.body.phone).toEqual({ number: "+1234567890" });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("formatDataForTokenization sets billing_address to null when not provided", () => {
|
|
113
|
+
const state = {
|
|
114
|
+
cardNumber: "4242 4242 4242 4242",
|
|
115
|
+
cardBin: { bin: null, scheme: null },
|
|
116
|
+
cardIcon: undefined,
|
|
117
|
+
cardType: null,
|
|
118
|
+
expiryDate: "12/30",
|
|
119
|
+
cvv: "123",
|
|
120
|
+
cvvLength: 3,
|
|
121
|
+
validation: { cardNumber: true, expiryDate: true, cvv: true, card: true },
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const config = {
|
|
125
|
+
publicKey: "pk_sbox_dummy",
|
|
126
|
+
cardholder: { name: "John Doe" },
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const params = formatDataForTokenization(state, config);
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
expect(params.body.billing_address).toBeNull();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("getEnvironment returns expected token URL", () => {
|
|
135
|
+
expect(getEnvironment("pk_sbox_dummy")).toBe(
|
|
136
|
+
"https://api.sandbox.checkout.com/tokens"
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe("logger.log", () => {
|
|
142
|
+
const { log, getEnvironment } = require("../src/utils/logger");
|
|
143
|
+
|
|
144
|
+
beforeEach(() => {
|
|
145
|
+
// @ts-ignore
|
|
146
|
+
global.fetch = jest.fn().mockResolvedValue({});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("posts to sandbox logger with structured body", async () => {
|
|
150
|
+
await log("info", "type_event", { publicKey: "pk_sbox_dummy" }, { a: 1 });
|
|
151
|
+
|
|
152
|
+
expect(global.fetch).toHaveBeenCalledWith(
|
|
153
|
+
SANDBOX_LOGGER,
|
|
154
|
+
expect.anything()
|
|
155
|
+
);
|
|
156
|
+
const [, options] = (global.fetch as jest.Mock).mock.calls[0];
|
|
157
|
+
const body = JSON.parse(options.body);
|
|
158
|
+
expect(body.specversion).toBe("1.0");
|
|
159
|
+
expect(body.type).toBe("type_event");
|
|
160
|
+
expect(body.data.environment).toBe("sandbox");
|
|
161
|
+
expect(body.cko.loglevel).toBe("info");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("getEnvironment returns live logger for prod keys", () => {
|
|
165
|
+
expect(getEnvironment("pk_4296fd52-efba-4a38-b6ce-cf0d93639d8a")).toBe(
|
|
166
|
+
LIVE_LOGGER
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe("Frames error path on tokenization failure", () => {
|
|
172
|
+
it("emits cardTokenizationFailed when tokenization rejects", async () => {
|
|
173
|
+
const httpMod = require("../src/utils/http");
|
|
174
|
+
jest.spyOn(httpMod, "tokenize").mockRejectedValueOnce({ error: "failure" });
|
|
175
|
+
|
|
176
|
+
const { Frames } = require("../src/index");
|
|
177
|
+
|
|
178
|
+
const cardTokenizationFailed = jest.fn();
|
|
179
|
+
|
|
180
|
+
const screen = render(
|
|
181
|
+
<Frames
|
|
182
|
+
config={{ publicKey: "pk_sbox_dummy", debug: true }}
|
|
183
|
+
cardTokenizationFailed={cardTokenizationFailed}
|
|
184
|
+
>
|
|
185
|
+
<CardNumber />
|
|
186
|
+
<ExpiryDate />
|
|
187
|
+
<Cvv />
|
|
188
|
+
<SubmitButton title="Pay" />
|
|
189
|
+
</Frames>
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
fireEvent.changeText(
|
|
193
|
+
screen.getByPlaceholderText("•••• •••• •••• ••••"),
|
|
194
|
+
"4242 4242 4242 4242"
|
|
195
|
+
);
|
|
196
|
+
fireEvent.changeText(screen.getByPlaceholderText("MM/YY"), "12/30");
|
|
197
|
+
fireEvent.changeText(screen.getByPlaceholderText("•••"), "123");
|
|
198
|
+
|
|
199
|
+
fireEvent.press(screen.getByText("Pay"));
|
|
200
|
+
|
|
201
|
+
await waitFor(() => expect(cardTokenizationFailed).toHaveBeenCalled());
|
|
202
|
+
expect(cardTokenizationFailed).toHaveBeenCalledWith({ error: "failure" });
|
|
203
|
+
});
|
|
204
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { createRef } from "react";
|
|
2
2
|
import { render, fireEvent, waitFor } from "@testing-library/react-native";
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Cvv,
|
|
9
9
|
SubmitButton,
|
|
10
10
|
} from "../src/index";
|
|
11
|
+
import type { FramesRef } from "../src/index";
|
|
11
12
|
|
|
12
13
|
// Mock network-dependent modules to avoid real HTTP requests
|
|
13
14
|
jest.mock("../src/utils/http", () => {
|
|
@@ -32,7 +33,7 @@ describe("Frames integration", () => {
|
|
|
32
33
|
const validCvv = "123";
|
|
33
34
|
|
|
34
35
|
const config = {
|
|
35
|
-
publicKey: "
|
|
36
|
+
publicKey: "pk_sbox_eo3yb3urja2ozf6ycgn5kuy7ke#",
|
|
36
37
|
debug: true,
|
|
37
38
|
cardholder: {
|
|
38
39
|
name: "John Doe",
|
|
@@ -47,6 +48,10 @@ describe("Frames integration", () => {
|
|
|
47
48
|
},
|
|
48
49
|
};
|
|
49
50
|
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
jest.clearAllMocks();
|
|
53
|
+
});
|
|
54
|
+
|
|
50
55
|
it("emits validation and bin events, and tokenizes on submit", async () => {
|
|
51
56
|
const { tokenize } = require("../src/utils/http");
|
|
52
57
|
|
|
@@ -54,8 +59,8 @@ describe("Frames integration", () => {
|
|
|
54
59
|
type: "card",
|
|
55
60
|
token: "tok_test_123",
|
|
56
61
|
expires_on: "2030-12-31T23:59:59Z",
|
|
57
|
-
expiry_month:
|
|
58
|
-
expiry_year:
|
|
62
|
+
expiry_month: 12,
|
|
63
|
+
expiry_year: 2030,
|
|
59
64
|
scheme: "Visa",
|
|
60
65
|
last4: "4242",
|
|
61
66
|
bin: "424242",
|
|
@@ -134,4 +139,94 @@ describe("Frames integration", () => {
|
|
|
134
139
|
expect(cardTokenized).toHaveBeenCalledWith(mockTokenResponse);
|
|
135
140
|
expect(cardTokenizationFailed).not.toHaveBeenCalled();
|
|
136
141
|
});
|
|
142
|
+
|
|
143
|
+
it("allows submitting via Frames ref submitCard()", async () => {
|
|
144
|
+
const { tokenize } = require("../src/utils/http");
|
|
145
|
+
|
|
146
|
+
const mockTokenResponse = {
|
|
147
|
+
type: "card",
|
|
148
|
+
token: "tok_test_ref_123",
|
|
149
|
+
expires_on: "2030-12-31T23:59:59Z",
|
|
150
|
+
expiry_month: 12,
|
|
151
|
+
expiry_year: 2030,
|
|
152
|
+
scheme: "Visa",
|
|
153
|
+
last4: "4242",
|
|
154
|
+
bin: "424242",
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
tokenize.mockResolvedValueOnce(mockTokenResponse);
|
|
158
|
+
|
|
159
|
+
const cardTokenized = jest.fn();
|
|
160
|
+
|
|
161
|
+
const ref = createRef<FramesRef>();
|
|
162
|
+
|
|
163
|
+
const screen = render(
|
|
164
|
+
<Frames config={config} cardTokenized={cardTokenized} ref={ref}>
|
|
165
|
+
<CardNumber />
|
|
166
|
+
<ExpiryDate />
|
|
167
|
+
<Cvv />
|
|
168
|
+
</Frames>
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
const cardNumberInput = screen.getByPlaceholderText("•••• •••• •••• ••••");
|
|
172
|
+
const expiryInput = screen.getByPlaceholderText("MM/YY");
|
|
173
|
+
const cvvInput = screen.getByPlaceholderText("•••");
|
|
174
|
+
|
|
175
|
+
// Fill valid data
|
|
176
|
+
fireEvent.changeText(cardNumberInput, validVisa);
|
|
177
|
+
fireEvent.changeText(expiryInput, validExpiry);
|
|
178
|
+
fireEvent.changeText(cvvInput, validCvv);
|
|
179
|
+
|
|
180
|
+
// Call submit via ref
|
|
181
|
+
await waitFor(async () => {
|
|
182
|
+
expect(ref.current).not.toBeNull();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
await ref.current!.submitCard();
|
|
186
|
+
|
|
187
|
+
await waitFor(() => expect(tokenize).toHaveBeenCalledTimes(1));
|
|
188
|
+
expect(cardTokenized).toHaveBeenCalledWith(mockTokenResponse);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("SubmitButton triggers submitCard and forwards onPress to consumer", async () => {
|
|
192
|
+
const { tokenize } = require("../src/utils/http");
|
|
193
|
+
|
|
194
|
+
const mockTokenResponse = {
|
|
195
|
+
type: "card",
|
|
196
|
+
token: "tok_test_press_123",
|
|
197
|
+
expires_on: "2030-12-31T23:59:59Z",
|
|
198
|
+
expiry_month: 12,
|
|
199
|
+
expiry_year: 2030,
|
|
200
|
+
scheme: "Visa",
|
|
201
|
+
last4: "4242",
|
|
202
|
+
bin: "424242",
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
tokenize.mockResolvedValueOnce(mockTokenResponse);
|
|
206
|
+
|
|
207
|
+
const onPressSpy = jest.fn();
|
|
208
|
+
const cardTokenized = jest.fn();
|
|
209
|
+
|
|
210
|
+
const screen = render(
|
|
211
|
+
<Frames config={config} cardTokenized={cardTokenized}>
|
|
212
|
+
<CardNumber />
|
|
213
|
+
<ExpiryDate />
|
|
214
|
+
<Cvv />
|
|
215
|
+
<SubmitButton title="Pay" onPress={onPressSpy} />
|
|
216
|
+
</Frames>
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
fireEvent.changeText(
|
|
220
|
+
screen.getByPlaceholderText("•••• •••• •••• ••••"),
|
|
221
|
+
validVisa
|
|
222
|
+
);
|
|
223
|
+
fireEvent.changeText(screen.getByPlaceholderText("MM/YY"), validExpiry);
|
|
224
|
+
fireEvent.changeText(screen.getByPlaceholderText("•••"), validCvv);
|
|
225
|
+
|
|
226
|
+
fireEvent.press(screen.getByText("Pay"));
|
|
227
|
+
|
|
228
|
+
await waitFor(() => expect(tokenize).toHaveBeenCalledTimes(1));
|
|
229
|
+
expect(cardTokenized).toHaveBeenCalledWith(mockTokenResponse);
|
|
230
|
+
expect(onPressSpy).toHaveBeenCalledTimes(1);
|
|
231
|
+
});
|
|
137
232
|
});
|
package/__tests__/Unit.test.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { getFormattedDate } from "../src/utils/date";
|
|
|
3
3
|
import { getEnvironment } from "../src/utils/http";
|
|
4
4
|
import { getEnvironment as loggerGetEnvironment } from "../src/utils/logger";
|
|
5
5
|
|
|
6
|
-
const PK_SB = "
|
|
6
|
+
const PK_SB = "pk_sbox_eo3yb3urja2ozf6ycgn5kuy7ke#";
|
|
7
7
|
const PK_PROD = "pk_4296fd52-efba-4a38-b6ce-cf0d93639d8a"; // fake key
|
|
8
8
|
|
|
9
9
|
describe("Date", () => {
|
package/dist/Frames.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { FramesContextType, FramesProps } from "./types/types";
|
|
2
|
+
import { FramesContextType, FramesProps, FramesRef } from "./types/types";
|
|
3
3
|
export declare const FramesContext: React.Context<FramesContextType>;
|
|
4
|
-
declare const Frames:
|
|
4
|
+
declare const Frames: React.ForwardRefExoticComponent<FramesProps & React.RefAttributes<FramesRef>>;
|
|
5
5
|
export default Frames;
|
|
6
6
|
export declare const FramesConsumer: React.Consumer<FramesContextType>;
|
|
7
7
|
export declare const FramesProvider: React.Provider<FramesContextType>;
|
package/dist/Frames.js
CHANGED
|
@@ -34,13 +34,13 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
34
34
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
import React, { useEffect } from "react";
|
|
37
|
+
import React, { useEffect, useImperativeHandle } from "react";
|
|
38
38
|
import { View, StyleSheet } from "react-native";
|
|
39
39
|
import { framesReducer } from "./utils/reducer";
|
|
40
40
|
import { log } from "./utils/logger";
|
|
41
41
|
import { tokenize, formatDataForTokenization } from "./utils/http";
|
|
42
42
|
export var FramesContext = React.createContext({});
|
|
43
|
-
var Frames = function (props) {
|
|
43
|
+
var Frames = React.forwardRef(function (props, ref) {
|
|
44
44
|
var initialState = {
|
|
45
45
|
cardNumber: null,
|
|
46
46
|
cardBin: {
|
|
@@ -88,6 +88,9 @@ var Frames = function (props) {
|
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
90
|
}); };
|
|
91
|
+
useImperativeHandle(ref, function () { return ({
|
|
92
|
+
submitCard: submitCard,
|
|
93
|
+
}); }, [submitCard]);
|
|
91
94
|
useEffect(function () {
|
|
92
95
|
if (state.cardBin.bin !== null) {
|
|
93
96
|
if (props.config.debug)
|
|
@@ -170,7 +173,7 @@ var Frames = function (props) {
|
|
|
170
173
|
{props.children}
|
|
171
174
|
</FramesContext.Provider>
|
|
172
175
|
</View>);
|
|
173
|
-
};
|
|
176
|
+
});
|
|
174
177
|
export default Frames;
|
|
175
178
|
export var FramesConsumer = FramesContext.Consumer;
|
|
176
179
|
export var FramesProvider = FramesContext.Provider;
|
package/dist/Frames.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Frames.js","sourceRoot":"","sources":["../src/Frames.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Frames.js","sourceRoot":"","sources":["../src/Frames.tsx"],"names":[],"mappings":"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"}
|
|
@@ -13,13 +13,14 @@ var CardNumber = function (props) {
|
|
|
13
13
|
}
|
|
14
14
|
return (<View style={styles.wrapper}>
|
|
15
15
|
<TextInput autoComplete="cc-number" keyboardType="number-pad" returnKeyType="done" placeholder={DEFAULT_CARD_NUMBER_PLACEHOLDER} {...props} value={(_b = state.cardNumber) !== null && _b !== void 0 ? _b : ""} style={[styles.cardNumber, props.style]} onChangeText={function (val) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
var safeValue = val !== null && val !== void 0 ? val : "";
|
|
17
|
+
dispatch({ type: CARD_CHANGE, payload: safeValue });
|
|
18
|
+
var digits = safeValue.replace(/[^0-9]/g, "");
|
|
19
|
+
if (digits.length >= 8 &&
|
|
20
|
+
digits.substring(0, 8) !== state.cardBin.bin) {
|
|
20
21
|
dispatch({
|
|
21
22
|
type: BIN_CHANGE,
|
|
22
|
-
payload:
|
|
23
|
+
payload: digits.substring(0, 8),
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
26
|
}}/>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CardNumber.js","sourceRoot":"","sources":["../../src/components/CardNumber.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AAErE,IAAM,UAAU,GAAmC,UAAC,KAAK;IACvD,OAAO,CACL,CAAC,cAAc,CACb;MAAA,CAAC,UAAC,EAAmB;;gBAAjB,KAAK,WAAA,EAAE,QAAQ,cAAA;YACjB,IAAI,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,MAAK,SAAS,EAAE,CAAC;gBACpC,MAAM,wFAAwF,CAAC;YACjG,CAAC;YACD,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAC1B;YAAA,CAAC,SAAS,CACR,YAAY,CAAC,WAAW,CACxB,YAAY,CAAC,YAAY,CACzB,aAAa,CAAC,MAAM,CACpB,WAAW,CAAC,CAAC,+BAA+B,CAAC,CAC7C,IAAI,KAAK,CAAC,CACV,KAAK,CAAC,CAAC,MAAA,KAAK,CAAC,UAAU,mCAAI,EAAE,CAAC,CAC9B,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CACxC,YAAY,CAAC,CAAC,UAAC,GAAW;oBACxB,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"CardNumber.js","sourceRoot":"","sources":["../../src/components/CardNumber.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export { default as ExpiryDate } from "./components/ExpiryDate";
|
|
|
4
4
|
export { default as Cvv } from "./components/Cvv";
|
|
5
5
|
export { default as SubmitButton } from "./components/SubmitButton";
|
|
6
6
|
export { default as FramesConsumer } from "./Frames";
|
|
7
|
+
export type { FramesRef } from "./types/types";
|
package/dist/types/types.d.ts
CHANGED
|
@@ -88,8 +88,11 @@ interface ValidationChange {
|
|
|
88
88
|
export type FramesContextType = {
|
|
89
89
|
state: FramesState;
|
|
90
90
|
dispatch: FramesDispatch;
|
|
91
|
-
submitCard: () => void
|
|
91
|
+
submitCard: () => Promise<void>;
|
|
92
92
|
};
|
|
93
|
+
export interface FramesRef {
|
|
94
|
+
submitCard: () => Promise<void>;
|
|
95
|
+
}
|
|
93
96
|
export interface TokenizationParams {
|
|
94
97
|
key: string;
|
|
95
98
|
body: TokenizationBody;
|
|
@@ -125,9 +128,10 @@ export interface FrameCardTokenizedEvent {
|
|
|
125
128
|
type: string;
|
|
126
129
|
token: string;
|
|
127
130
|
expires_on: string;
|
|
128
|
-
expiry_month:
|
|
129
|
-
expiry_year:
|
|
131
|
+
expiry_month: number;
|
|
132
|
+
expiry_year: number;
|
|
130
133
|
scheme?: Scheme;
|
|
134
|
+
scheme_local?: string;
|
|
131
135
|
last4: string;
|
|
132
136
|
bin: string;
|
|
133
137
|
card_type?: CardType;
|
package/dist/utils/http.js
CHANGED
|
@@ -73,9 +73,14 @@ export var tokenize = function (e) { return __awaiter(void 0, void 0, void 0, fu
|
|
|
73
73
|
}); };
|
|
74
74
|
export var formatDataForTokenization = function (state, config) {
|
|
75
75
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
76
|
-
var
|
|
77
|
-
var
|
|
78
|
-
var
|
|
76
|
+
var rawNumber = state.cardNumber || "";
|
|
77
|
+
var number = rawNumber.replace(/[^A-Z0-9]+/gi, "");
|
|
78
|
+
var rawExpiry = state.expiryDate || "";
|
|
79
|
+
var _h = rawExpiry.split(EXPIRY_DATE_DELIMITER), _j = _h[0], expiry_month = _j === void 0 ? "" : _j, expiryYearSuffix = _h[1];
|
|
80
|
+
var currentCentury = new Date().getFullYear().toString().substring(0, 2);
|
|
81
|
+
var expiry_year = expiryYearSuffix
|
|
82
|
+
? "".concat(currentCentury).concat(expiryYearSuffix)
|
|
83
|
+
: "";
|
|
79
84
|
var billing_address = {
|
|
80
85
|
address_line1: "",
|
|
81
86
|
address_line2: "",
|
|
@@ -109,7 +114,7 @@ export var formatDataForTokenization = function (state, config) {
|
|
|
109
114
|
number: number,
|
|
110
115
|
expiry_month: expiry_month,
|
|
111
116
|
expiry_year: expiry_year,
|
|
112
|
-
cvv: state.cvv,
|
|
117
|
+
cvv: state.cvv || "",
|
|
113
118
|
name: (_f = config.cardholder) === null || _f === void 0 ? void 0 : _f.name,
|
|
114
119
|
billing_address: billing_address,
|
|
115
120
|
phone: {
|
package/dist/utils/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/utils/http.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,IAAM,QAAQ,GAAG,UAAO,CAAqB;;;;;;gBAE1C,KAAK,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;gBAC7B,qBAAM,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;wBAChD,MAAM,EAAE,MAAM;wBACd,OAAO,EAAE;4BACP,MAAM,EAAE,kBAAkB;4BAC1B,cAAc,EAAE,kBAAkB;4BAClC,YAAY,EAAE,8BAAuB,KAAK,CAAC,OAAO,CAAE;4BACpD,aAAa,EAAE,CAAC,CAAC,GAAG;yBACrB;wBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;qBAC7B,CAAC,EAAA;;gBATE,QAAQ,GAAG,SASb;gBAES,qBAAM,QAAQ,CAAC,IAAI,EAAE,EAAA;;gBAA5B,IAAI,GAAG,SAAqB;gBAEhC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;oBAChB,sBAAO,IAAI,EAAC;gBACd,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,CAAC;gBACb,CAAC;;;;gBAED,MAAM,OAAK,CAAC;;;;KAEf,CAAC;AAEF,MAAM,CAAC,IAAM,yBAAyB,GAAG,UACvC,KAAkB,EAClB,MAAoB;;IAEpB,
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/utils/http.tsx"],"names":[],"mappings":"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"}
|