@evervault/react-native 2.6.0 → 2.6.2
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/package.json +3 -2
- package/src/Card/Cvc.test.tsx +41 -0
- package/src/Card/Cvc.tsx +58 -0
- package/src/Card/Expiry.tsx +26 -0
- package/src/Card/Holder.tsx +27 -0
- package/src/Card/Number.test.tsx +76 -0
- package/src/Card/Number.tsx +54 -0
- package/src/Card/Root.test.tsx +341 -0
- package/src/Card/Root.tsx +150 -0
- package/src/Card/index.ts +28 -0
- package/src/Card/schema.ts +41 -0
- package/src/Card/types.ts +57 -0
- package/src/Card/utils.test.ts +271 -0
- package/src/Card/utils.ts +129 -0
- package/src/EvervaultProvider.test.tsx +24 -0
- package/src/EvervaultProvider.tsx +43 -0
- package/src/Input.test.tsx +420 -0
- package/src/Input.tsx +182 -0
- package/src/ThreeDSecure/Frame.test.tsx +87 -0
- package/src/ThreeDSecure/Frame.tsx +50 -0
- package/src/ThreeDSecure/Root.test.tsx +67 -0
- package/src/ThreeDSecure/Root.tsx +23 -0
- package/src/ThreeDSecure/config.ts +3 -0
- package/src/ThreeDSecure/context.ts +6 -0
- package/src/ThreeDSecure/event.ts +19 -0
- package/src/ThreeDSecure/index.ts +17 -0
- package/src/ThreeDSecure/session.test.ts +524 -0
- package/src/ThreeDSecure/session.ts +184 -0
- package/src/ThreeDSecure/types.ts +80 -0
- package/src/ThreeDSecure/useThreeDSecure.test.tsx +244 -0
- package/src/ThreeDSecure/useThreeDSecure.ts +64 -0
- package/src/__mocks__/NativeEvervault.ts +13 -0
- package/src/__mocks__/react-native-webview.tsx +6 -0
- package/src/context.ts +14 -0
- package/src/index.ts +21 -0
- package/src/sdk.test.ts +122 -0
- package/src/sdk.ts +71 -0
- package/src/specs/NativeEvervault.ts +67 -0
- package/src/useEvervault.test.tsx +31 -0
- package/src/useEvervault.ts +14 -0
- package/src/utils.ts +41 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { render } from "@testing-library/react-native";
|
|
2
|
+
import { WebView } from "../__mocks__/react-native-webview";
|
|
3
|
+
import { ThreeDSecureFrame } from "./Frame";
|
|
4
|
+
import { ErrorBoundary } from "../utils";
|
|
5
|
+
import { EvervaultProvider } from "../EvervaultProvider";
|
|
6
|
+
import { ThreeDSecure } from "./Root";
|
|
7
|
+
import { CHALLENGE_DOMAIN_3DS } from "./config";
|
|
8
|
+
|
|
9
|
+
vi.mock("react-native-webview", () => ({ WebView }));
|
|
10
|
+
|
|
11
|
+
it("throws an error if used outside of an EvervaultProvider", () => {
|
|
12
|
+
const onError = vi.fn();
|
|
13
|
+
render(
|
|
14
|
+
<ErrorBoundary onError={onError}>
|
|
15
|
+
<ThreeDSecureFrame />
|
|
16
|
+
</ErrorBoundary>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
expect(onError).toHaveBeenCalledWith(
|
|
20
|
+
new Error("`useEvervault` must be used within an `EvervaultProvider`.")
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("throws an error if used outside of a ThreeDSecure component", () => {
|
|
25
|
+
const onError = vi.fn();
|
|
26
|
+
render(
|
|
27
|
+
<ErrorBoundary onError={onError}>
|
|
28
|
+
<EvervaultProvider teamId="team_123" appId="app_123">
|
|
29
|
+
<ThreeDSecureFrame />
|
|
30
|
+
</EvervaultProvider>
|
|
31
|
+
</ErrorBoundary>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(onError).toHaveBeenCalledWith(
|
|
35
|
+
new Error(
|
|
36
|
+
"`ThreeDSecure.Frame` must be used within a `ThreeDSecure` component."
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("renders null if there is no session", () => {
|
|
42
|
+
const { queryByTestId } = render(
|
|
43
|
+
<EvervaultProvider teamId="team_123" appId="app_123">
|
|
44
|
+
<ThreeDSecure
|
|
45
|
+
state={{
|
|
46
|
+
session: null,
|
|
47
|
+
isVisible: false,
|
|
48
|
+
cancel: vi.fn(),
|
|
49
|
+
start: vi.fn(),
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
<ThreeDSecureFrame />
|
|
53
|
+
</ThreeDSecure>
|
|
54
|
+
</EvervaultProvider>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(queryByTestId("webview")).toBeNull();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("renders a webview with the correct url", () => {
|
|
61
|
+
const { getByTestId } = render(
|
|
62
|
+
<EvervaultProvider teamId="team_123" appId="app_123">
|
|
63
|
+
<ThreeDSecure
|
|
64
|
+
state={{
|
|
65
|
+
session: {
|
|
66
|
+
sessionId: "session_123",
|
|
67
|
+
cancel: vi.fn(),
|
|
68
|
+
get: vi.fn(),
|
|
69
|
+
},
|
|
70
|
+
isVisible: true,
|
|
71
|
+
cancel: vi.fn(),
|
|
72
|
+
start: vi.fn(),
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
<ThreeDSecureFrame />
|
|
76
|
+
</ThreeDSecure>
|
|
77
|
+
</EvervaultProvider>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const webview = getByTestId("webview");
|
|
81
|
+
expect(webview).toBeOnTheScreen();
|
|
82
|
+
expect(webview).toHaveProp("source", {
|
|
83
|
+
uri: `https://${CHALLENGE_DOMAIN_3DS}/?session=session_123&app=app_123&team=team_123`,
|
|
84
|
+
});
|
|
85
|
+
expect(webview).toHaveProp("hideKeyboardAccessoryView", true);
|
|
86
|
+
expect(webview).toHaveProp("overScrollMode", "content");
|
|
87
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useContext, useMemo } from "react";
|
|
2
|
+
import { StyleProp, StyleSheet, ViewStyle } from "react-native";
|
|
3
|
+
import { useEvervault } from "../useEvervault";
|
|
4
|
+
import { WebView } from "react-native-webview";
|
|
5
|
+
import { CHALLENGE_DOMAIN_3DS } from "./config";
|
|
6
|
+
import { ThreeDSecureContext } from "./context";
|
|
7
|
+
|
|
8
|
+
export interface ThreeDSecureFrameProps {
|
|
9
|
+
style?: StyleProp<ViewStyle>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function ThreeDSecureFrame({ style }: ThreeDSecureFrameProps) {
|
|
13
|
+
const evervault = useEvervault();
|
|
14
|
+
|
|
15
|
+
const context = useContext(ThreeDSecureContext);
|
|
16
|
+
if (!context) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"`ThreeDSecure.Frame` must be used within a `ThreeDSecure` component."
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const uri = useMemo(() => {
|
|
23
|
+
if (!context.session) return null;
|
|
24
|
+
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
params.set("session", context.session.sessionId);
|
|
27
|
+
params.set("app", evervault.appId);
|
|
28
|
+
params.set("team", evervault.teamId);
|
|
29
|
+
|
|
30
|
+
return `https://${CHALLENGE_DOMAIN_3DS}/?${params.toString()}`;
|
|
31
|
+
}, [context.session, evervault.appId, evervault.teamId]);
|
|
32
|
+
|
|
33
|
+
if (!uri) return null;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<WebView
|
|
37
|
+
containerStyle={[defaultStyles.webView, style]}
|
|
38
|
+
source={{ uri }}
|
|
39
|
+
hideKeyboardAccessoryView
|
|
40
|
+
overScrollMode="content"
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const defaultStyles = StyleSheet.create({
|
|
46
|
+
webView: {
|
|
47
|
+
flex: 1,
|
|
48
|
+
width: "100%",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { PropsWithChildren } from "react";
|
|
2
|
+
import { EvervaultProvider } from "../EvervaultProvider";
|
|
3
|
+
import { render, screen } from "@testing-library/react-native";
|
|
4
|
+
import { ThreeDSecure } from "./Root";
|
|
5
|
+
import { Text } from "react-native";
|
|
6
|
+
|
|
7
|
+
function wrapper({ children }: PropsWithChildren) {
|
|
8
|
+
return (
|
|
9
|
+
<EvervaultProvider teamId="team_123" appId="app_123">
|
|
10
|
+
{children}
|
|
11
|
+
</EvervaultProvider>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
it("renders null when the session is null", () => {
|
|
16
|
+
render(
|
|
17
|
+
<ThreeDSecure
|
|
18
|
+
state={{
|
|
19
|
+
session: null,
|
|
20
|
+
isVisible: false,
|
|
21
|
+
cancel: vi.fn(),
|
|
22
|
+
start: vi.fn(),
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
<Text testID="child">Hello</Text>
|
|
26
|
+
</ThreeDSecure>,
|
|
27
|
+
{ wrapper }
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
expect(screen.queryByTestId("child")).toBeNull();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("renders null when the session is not visible", () => {
|
|
34
|
+
render(
|
|
35
|
+
<ThreeDSecure
|
|
36
|
+
state={{
|
|
37
|
+
session: { sessionId: "session_123", cancel: vi.fn(), get: vi.fn() },
|
|
38
|
+
isVisible: false,
|
|
39
|
+
cancel: vi.fn(),
|
|
40
|
+
start: vi.fn(),
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
<Text testID="child">Hello</Text>
|
|
44
|
+
</ThreeDSecure>,
|
|
45
|
+
{ wrapper }
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(screen.queryByTestId("child")).toBeNull();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("renders the children when the session defined and visible", () => {
|
|
52
|
+
render(
|
|
53
|
+
<ThreeDSecure
|
|
54
|
+
state={{
|
|
55
|
+
session: { sessionId: "session_123", cancel: vi.fn(), get: vi.fn() },
|
|
56
|
+
isVisible: true,
|
|
57
|
+
cancel: vi.fn(),
|
|
58
|
+
start: vi.fn(),
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<Text testID="child">Hello</Text>
|
|
62
|
+
</ThreeDSecure>,
|
|
63
|
+
{ wrapper }
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
expect(screen.getByTestId("child")).toBeOnTheScreen();
|
|
67
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ThreeDSecureState } from "./types";
|
|
2
|
+
import { useEvervault } from "../useEvervault";
|
|
3
|
+
import { ThreeDSecureContext } from "./context";
|
|
4
|
+
import { PropsWithChildren } from "react";
|
|
5
|
+
|
|
6
|
+
export interface ThreeDSecureProps extends PropsWithChildren {
|
|
7
|
+
/**
|
|
8
|
+
* The 3DS session state returned from the `useThreeDSecure` hook.
|
|
9
|
+
*/
|
|
10
|
+
state: ThreeDSecureState;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ThreeDSecure({ state, children }: ThreeDSecureProps) {
|
|
14
|
+
useEvervault();
|
|
15
|
+
|
|
16
|
+
if (!state.session) return null;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<ThreeDSecureContext.Provider value={state}>
|
|
20
|
+
{state.isVisible && children}
|
|
21
|
+
</ThreeDSecureContext.Provider>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ThreeDSecureSession } from "./types";
|
|
2
|
+
|
|
3
|
+
export type ThreeDSecureEventType = "requestChallenge";
|
|
4
|
+
|
|
5
|
+
export class ThreeDSecureEvent {
|
|
6
|
+
constructor(
|
|
7
|
+
public readonly type: ThreeDSecureEventType,
|
|
8
|
+
public readonly session: ThreeDSecureSession,
|
|
9
|
+
private _defaultPrevented: boolean = false
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
public preventDefault() {
|
|
13
|
+
this._defaultPrevented = true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public get defaultPrevented() {
|
|
17
|
+
return this._defaultPrevented;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ThreeDSecure as ThreeDSecureRoot } from "./Root";
|
|
2
|
+
import { ThreeDSecureFrame } from "./Frame";
|
|
3
|
+
|
|
4
|
+
export const ThreeDSecure = Object.assign(ThreeDSecureRoot, {
|
|
5
|
+
Frame: ThreeDSecureFrame,
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export type { ThreeDSecureProps } from "./Root";
|
|
9
|
+
export type { ThreeDSecureFrameProps } from "./Frame";
|
|
10
|
+
|
|
11
|
+
export type {
|
|
12
|
+
ThreeDSecureState,
|
|
13
|
+
ThreeDSecureSession,
|
|
14
|
+
ThreeDSecureCallbacks,
|
|
15
|
+
} from "./types";
|
|
16
|
+
|
|
17
|
+
export { useThreeDSecure } from "./useThreeDSecure";
|