@evervault/react-native 2.1.0 → 2.2.1

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.
@@ -7105,6 +7105,8 @@ function areValuesComplete(values) {
7105
7105
  function isAcceptedBrand(acceptedBrands, cardNumberValidationResult) {
7106
7106
  if (!acceptedBrands?.length)
7107
7107
  return true;
7108
+ if (!cardNumberValidationResult.isValid)
7109
+ return false;
7108
7110
  const { brand, localBrands } = cardNumberValidationResult;
7109
7111
  const acceptedBrandsSet = new Set(acceptedBrands);
7110
7112
  const isBrandAccepted = brand !== null && acceptedBrandsSet.has(brand);
@@ -7123,15 +7125,15 @@ function formatExpiry(expiry) {
7123
7125
  }
7124
7126
 
7125
7127
  function getCardFormSchema(acceptedBrands) {
7126
- return z
7127
- .object({
7128
+ return z.object({
7128
7129
  name: z.string().min(1, "Missing name"),
7129
7130
  number: z
7130
7131
  .string()
7131
7132
  .min(1, "Required")
7132
7133
  .refine((value) => f(value).isValid, {
7133
7134
  message: "Invalid card number",
7134
- }),
7135
+ })
7136
+ .refine((value) => isAcceptedBrand(acceptedBrands, f(value)), { message: "Brand not accepted" }),
7135
7137
  expiry: z
7136
7138
  .string()
7137
7139
  .min(1, "Required")
@@ -7144,19 +7146,6 @@ function getCardFormSchema(acceptedBrands) {
7144
7146
  .refine((value) => C(value).isValid, {
7145
7147
  message: "Invalid CVC",
7146
7148
  }),
7147
- })
7148
- .superRefine((value, ctx) => {
7149
- const validation = f(value.number);
7150
- if (!validation.isValid)
7151
- return;
7152
- const isAccepted = isAcceptedBrand(acceptedBrands, validation);
7153
- if (!isAccepted) {
7154
- ctx.addIssue({
7155
- code: z.ZodIssueCode.custom,
7156
- message: "Brand not accepted",
7157
- path: ["number"],
7158
- });
7159
- }
7160
7149
  });
7161
7150
  }
7162
7151
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@evervault/react-native",
3
3
  "description": "Evervault SDK for React Native",
4
- "version": "2.1.0",
4
+ "version": "2.2.1",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./build/index.cjs.js",
7
7
  "module": "./build/index.esm.js",
@@ -258,3 +258,84 @@ it("adds Invalid error when input is blurred with an invalid value", async () =>
258
258
  });
259
259
  });
260
260
  });
261
+
262
+ it("adds 'Brand not accepted' error when brand is not accepted", async () => {
263
+ const onChange = vi.fn();
264
+ const { getByTestId } = render(
265
+ <Card onChange={onChange} acceptedBrands={["american-express"]}>
266
+ <CardNumber testID="number" />
267
+ </Card>,
268
+ { wrapper }
269
+ );
270
+
271
+ const number = getByTestId("number");
272
+
273
+ const user = userEvent.setup();
274
+ await user.type(number, "4242");
275
+ fireEvent(number, "blur");
276
+
277
+ await waitFor(() => {
278
+ expect(onChange).toHaveBeenLastCalledWith({
279
+ card: {
280
+ name: null,
281
+ brand: "visa",
282
+ localBrands: [],
283
+ number: null,
284
+ lastFour: null,
285
+ bin: null,
286
+ expiry: null,
287
+ cvc: null,
288
+ },
289
+ isValid: false,
290
+ isComplete: false,
291
+ errors: {
292
+ number: "Invalid card number",
293
+ },
294
+ });
295
+ });
296
+
297
+ await user.type(number, "4242 4242 4242");
298
+ fireEvent(number, "blur");
299
+
300
+ await waitFor(() => {
301
+ expect(onChange).toHaveBeenLastCalledWith({
302
+ card: {
303
+ name: null,
304
+ brand: "visa",
305
+ localBrands: [],
306
+ number: expect.any(String),
307
+ lastFour: "4242",
308
+ bin: "42424242",
309
+ expiry: null,
310
+ cvc: null,
311
+ },
312
+ isValid: false,
313
+ isComplete: true,
314
+ errors: {
315
+ number: "Brand not accepted",
316
+ },
317
+ });
318
+ });
319
+
320
+ await user.clear(number);
321
+ await user.type(number, "3782 822463 10005");
322
+ fireEvent(number, "blur");
323
+
324
+ await waitFor(() => {
325
+ expect(onChange).toHaveBeenLastCalledWith({
326
+ card: {
327
+ name: null,
328
+ brand: "american-express",
329
+ localBrands: [],
330
+ number: expect.any(String),
331
+ lastFour: "0005",
332
+ bin: "378282",
333
+ expiry: null,
334
+ cvc: null,
335
+ },
336
+ isValid: true,
337
+ isComplete: true,
338
+ errors: {},
339
+ });
340
+ });
341
+ });
@@ -8,44 +8,34 @@ import { CardBrandName } from "./types";
8
8
  import { isAcceptedBrand } from "./utils";
9
9
 
10
10
  export function getCardFormSchema(acceptedBrands: CardBrandName[]) {
11
- return z
12
- .object({
13
- name: z.string().min(1, "Missing name"),
11
+ return z.object({
12
+ name: z.string().min(1, "Missing name"),
14
13
 
15
- number: z
16
- .string()
17
- .min(1, "Required")
18
- .refine((value) => validateNumber(value).isValid, {
19
- message: "Invalid card number",
20
- }),
14
+ number: z
15
+ .string()
16
+ .min(1, "Required")
17
+ .refine((value) => validateNumber(value).isValid, {
18
+ message: "Invalid card number",
19
+ })
20
+ .refine(
21
+ (value) => isAcceptedBrand(acceptedBrands, validateNumber(value)),
22
+ { message: "Brand not accepted" }
23
+ ),
21
24
 
22
- expiry: z
23
- .string()
24
- .min(1, "Required")
25
- .refine((value) => validateExpiry(value).isValid, {
26
- message: "Invalid expiry",
27
- }),
25
+ expiry: z
26
+ .string()
27
+ .min(1, "Required")
28
+ .refine((value) => validateExpiry(value).isValid, {
29
+ message: "Invalid expiry",
30
+ }),
28
31
 
29
- cvc: z
30
- .string()
31
- .min(1, "Required")
32
- .refine((value) => validateCVC(value).isValid, {
33
- message: "Invalid CVC",
34
- }),
35
- })
36
- .superRefine((value, ctx) => {
37
- const validation = validateNumber(value.number);
38
- if (!validation.isValid) return;
39
-
40
- const isAccepted = isAcceptedBrand(acceptedBrands, validation);
41
- if (!isAccepted) {
42
- ctx.addIssue({
43
- code: z.ZodIssueCode.custom,
44
- message: "Brand not accepted",
45
- path: ["number"],
46
- });
47
- }
48
- });
32
+ cvc: z
33
+ .string()
34
+ .min(1, "Required")
35
+ .refine((value) => validateCVC(value).isValid, {
36
+ message: "Invalid CVC",
37
+ }),
38
+ });
49
39
  }
50
40
 
51
41
  export type CardFormValues = z.infer<ReturnType<typeof getCardFormSchema>>;
package/src/Card/types.ts CHANGED
@@ -18,6 +18,12 @@ export const CARD_BRAND_NAMES = [
18
18
  export type CardBrandName = (typeof CARD_BRAND_NAMES)[number];
19
19
 
20
20
  export interface CardConfig {
21
+ /**
22
+ * The brands that are accepted by the card form.
23
+ * Pass an empty array to accept all brands.
24
+ *
25
+ * @default []
26
+ */
21
27
  acceptedBrands?: CardBrandName[];
22
28
  }
23
29
 
package/src/Card/utils.ts CHANGED
@@ -101,6 +101,8 @@ export function isAcceptedBrand(
101
101
  cardNumberValidationResult: CardNumberValidationResult
102
102
  ): boolean {
103
103
  if (!acceptedBrands?.length) return true;
104
+
105
+ if (!cardNumberValidationResult.isValid) return false;
104
106
  const { brand, localBrands } = cardNumberValidationResult;
105
107
 
106
108
  const acceptedBrandsSet = new Set(acceptedBrands);