@frak-labs/react-sdk 0.1.1 → 0.2.0-beta.7898df5b
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/README.md +25 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +29 -68
- package/dist/index.d.ts +28 -67
- package/dist/index.js +1 -1
- package/package.json +17 -16
- package/src/hook/helper/useReferralInteraction.test.ts +309 -0
- package/src/hook/helper/useReferralInteraction.ts +73 -0
- package/src/hook/index.ts +10 -0
- package/src/hook/useDisplayModal.test.ts +275 -0
- package/src/hook/useDisplayModal.ts +68 -0
- package/src/hook/useFrakClient.test.ts +119 -0
- package/src/hook/useFrakClient.ts +11 -0
- package/src/hook/useFrakConfig.test.ts +184 -0
- package/src/hook/useFrakConfig.ts +22 -0
- package/src/hook/useGetMerchantInformation.ts +56 -0
- package/src/hook/useOpenSso.test.ts +202 -0
- package/src/hook/useOpenSso.ts +51 -0
- package/src/hook/usePrepareSso.test.ts +197 -0
- package/src/hook/usePrepareSso.ts +55 -0
- package/src/hook/useSendTransaction.test.ts +218 -0
- package/src/hook/useSendTransaction.ts +62 -0
- package/src/hook/useSiweAuthenticate.test.ts +258 -0
- package/src/hook/useSiweAuthenticate.ts +66 -0
- package/src/hook/useWalletStatus.test.ts +112 -0
- package/src/hook/useWalletStatus.ts +55 -0
- package/src/hook/utils/useFrakContext.test.ts +157 -0
- package/src/hook/utils/useFrakContext.ts +42 -0
- package/src/hook/utils/useMounted.test.ts +70 -0
- package/src/hook/utils/useMounted.ts +12 -0
- package/src/hook/utils/useWindowLocation.test.ts +54 -0
- package/src/hook/utils/useWindowLocation.ts +40 -0
- package/src/index.ts +25 -0
- package/src/provider/FrakConfigProvider.test.ts +246 -0
- package/src/provider/FrakConfigProvider.ts +54 -0
- package/src/provider/FrakIFrameClientProvider.test.tsx +209 -0
- package/src/provider/FrakIFrameClientProvider.ts +86 -0
- package/src/provider/index.ts +7 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for useReferralInteraction hook
|
|
3
|
+
* Tests automatic referral interaction submission
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { vi } from "vitest";
|
|
7
|
+
|
|
8
|
+
vi.mock("@frak-labs/core-sdk/actions");
|
|
9
|
+
vi.mock("../useFrakClient");
|
|
10
|
+
vi.mock("../useWalletStatus");
|
|
11
|
+
vi.mock("../utils/useFrakContext");
|
|
12
|
+
|
|
13
|
+
import type { FrakContext, WalletStatusReturnType } from "@frak-labs/core-sdk";
|
|
14
|
+
import { processReferral } from "@frak-labs/core-sdk/actions";
|
|
15
|
+
import { ClientNotFound } from "@frak-labs/frame-connector";
|
|
16
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
|
17
|
+
import { describe, expect, test } from "../../../tests/vitest-fixtures";
|
|
18
|
+
import { useFrakClient } from "../useFrakClient";
|
|
19
|
+
import { useWalletStatus } from "../useWalletStatus";
|
|
20
|
+
import { useFrakContext } from "../utils/useFrakContext";
|
|
21
|
+
import { useReferralInteraction } from "./useReferralInteraction";
|
|
22
|
+
|
|
23
|
+
describe("useReferralInteraction", () => {
|
|
24
|
+
test("should return processing when wallet status is not available", ({
|
|
25
|
+
queryWrapper,
|
|
26
|
+
mockFrakClient,
|
|
27
|
+
}) => {
|
|
28
|
+
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
29
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
30
|
+
frakContext: null,
|
|
31
|
+
updateContext: vi.fn(),
|
|
32
|
+
});
|
|
33
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
34
|
+
data: undefined,
|
|
35
|
+
isSuccess: false,
|
|
36
|
+
isPending: true,
|
|
37
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
38
|
+
|
|
39
|
+
const { result } = renderHook(() => useReferralInteraction(), {
|
|
40
|
+
wrapper: queryWrapper.wrapper,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Query is disabled when wallet status is not available, status remains pending
|
|
44
|
+
expect(result.current).toBe("processing");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("should process referral successfully", async ({
|
|
48
|
+
queryWrapper,
|
|
49
|
+
mockFrakClient,
|
|
50
|
+
}) => {
|
|
51
|
+
const mockReferralState = "success";
|
|
52
|
+
|
|
53
|
+
const mockWalletStatus: WalletStatusReturnType = {
|
|
54
|
+
key: "connected",
|
|
55
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const mockFrakContext: FrakContext = {
|
|
59
|
+
r: "0x1234567890123456789012345678901234567890",
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
63
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
64
|
+
frakContext: mockFrakContext,
|
|
65
|
+
updateContext: vi.fn(),
|
|
66
|
+
});
|
|
67
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
68
|
+
data: mockWalletStatus,
|
|
69
|
+
isSuccess: true,
|
|
70
|
+
isPending: false,
|
|
71
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
72
|
+
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
73
|
+
|
|
74
|
+
const { result } = renderHook(() => useReferralInteraction(), {
|
|
75
|
+
wrapper: queryWrapper.wrapper,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await waitFor(() => {
|
|
79
|
+
expect(result.current).toEqual(mockReferralState);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(processReferral).toHaveBeenCalledWith(mockFrakClient, {
|
|
83
|
+
walletStatus: mockWalletStatus,
|
|
84
|
+
frakContext: mockFrakContext,
|
|
85
|
+
options: undefined,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("should process referral with options", async ({
|
|
90
|
+
queryWrapper,
|
|
91
|
+
mockFrakClient,
|
|
92
|
+
}) => {
|
|
93
|
+
const mockReferralState = "success";
|
|
94
|
+
|
|
95
|
+
const options = {
|
|
96
|
+
alwaysAppendUrl: true,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const mockWalletStatus: WalletStatusReturnType = {
|
|
100
|
+
key: "connected",
|
|
101
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
105
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
106
|
+
frakContext: { r: "0x7890123456789012345678901234567890123456" },
|
|
107
|
+
updateContext: vi.fn(),
|
|
108
|
+
});
|
|
109
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
110
|
+
data: mockWalletStatus,
|
|
111
|
+
isSuccess: true,
|
|
112
|
+
isPending: false,
|
|
113
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
114
|
+
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
115
|
+
|
|
116
|
+
const { result } = renderHook(
|
|
117
|
+
() => useReferralInteraction({ options }),
|
|
118
|
+
{
|
|
119
|
+
wrapper: queryWrapper.wrapper,
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
await waitFor(() => {
|
|
124
|
+
expect(result.current).toEqual(mockReferralState);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
expect(processReferral).toHaveBeenCalledWith(
|
|
128
|
+
mockFrakClient,
|
|
129
|
+
expect.objectContaining({
|
|
130
|
+
options,
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("should handle processing state", ({
|
|
136
|
+
queryWrapper,
|
|
137
|
+
mockFrakClient,
|
|
138
|
+
}) => {
|
|
139
|
+
const mockWalletStatus: WalletStatusReturnType = {
|
|
140
|
+
key: "connected",
|
|
141
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
145
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
146
|
+
frakContext: { r: "0x9999999999999999999999999999999999999999" },
|
|
147
|
+
updateContext: vi.fn(),
|
|
148
|
+
});
|
|
149
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
150
|
+
data: mockWalletStatus,
|
|
151
|
+
isSuccess: true,
|
|
152
|
+
isPending: false,
|
|
153
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
154
|
+
|
|
155
|
+
// Mock processReferral to never resolve (simulate pending)
|
|
156
|
+
vi.mocked(processReferral).mockImplementation(
|
|
157
|
+
() => new Promise(() => {})
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const { result } = renderHook(() => useReferralInteraction(), {
|
|
161
|
+
wrapper: queryWrapper.wrapper,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(result.current).toBe("processing");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("should handle errors", async ({ queryWrapper, mockFrakClient }) => {
|
|
168
|
+
const error = new Error("Referral processing failed");
|
|
169
|
+
|
|
170
|
+
const mockWalletStatus: WalletStatusReturnType = {
|
|
171
|
+
key: "connected",
|
|
172
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
176
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
177
|
+
frakContext: { r: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" },
|
|
178
|
+
updateContext: vi.fn(),
|
|
179
|
+
});
|
|
180
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
181
|
+
data: mockWalletStatus,
|
|
182
|
+
isSuccess: true,
|
|
183
|
+
isPending: false,
|
|
184
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
185
|
+
vi.mocked(processReferral).mockRejectedValue(error);
|
|
186
|
+
|
|
187
|
+
const { result } = renderHook(() => useReferralInteraction(), {
|
|
188
|
+
wrapper: queryWrapper.wrapper,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
await waitFor(() => {
|
|
192
|
+
expect(result.current).toEqual(error);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("should throw ClientNotFound when client is not available", async ({
|
|
197
|
+
queryWrapper,
|
|
198
|
+
}) => {
|
|
199
|
+
const mockWalletStatus: WalletStatusReturnType = {
|
|
200
|
+
key: "connected",
|
|
201
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
vi.mocked(useFrakClient).mockReturnValue(undefined);
|
|
205
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
206
|
+
frakContext: { r: "0xcccccccccccccccccccccccccccccccccccccccc" },
|
|
207
|
+
updateContext: vi.fn(),
|
|
208
|
+
});
|
|
209
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
210
|
+
data: mockWalletStatus,
|
|
211
|
+
isSuccess: true,
|
|
212
|
+
isPending: false,
|
|
213
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
214
|
+
|
|
215
|
+
const { result } = renderHook(() => useReferralInteraction(), {
|
|
216
|
+
wrapper: queryWrapper.wrapper,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
await waitFor(() => {
|
|
220
|
+
expect(result.current).toBeInstanceOf(ClientNotFound);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("should update query key when referrer changes", async ({
|
|
225
|
+
queryWrapper,
|
|
226
|
+
mockFrakClient,
|
|
227
|
+
}) => {
|
|
228
|
+
const mockReferralState = "success";
|
|
229
|
+
|
|
230
|
+
const mockWalletStatus: WalletStatusReturnType = {
|
|
231
|
+
key: "connected",
|
|
232
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
236
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
237
|
+
data: mockWalletStatus,
|
|
238
|
+
isSuccess: true,
|
|
239
|
+
isPending: false,
|
|
240
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
241
|
+
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
242
|
+
|
|
243
|
+
// Start with one referrer
|
|
244
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
245
|
+
frakContext: { r: "0x1111111111111111111111111111111111111111" },
|
|
246
|
+
updateContext: vi.fn(),
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
const { rerender } = renderHook(() => useReferralInteraction(), {
|
|
250
|
+
wrapper: queryWrapper.wrapper,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
await waitFor(() => {
|
|
254
|
+
expect(processReferral).toHaveBeenCalledTimes(1);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Change referrer
|
|
258
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
259
|
+
frakContext: { r: "0x2222222222222222222222222222222222222222" },
|
|
260
|
+
updateContext: vi.fn(),
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
rerender();
|
|
264
|
+
|
|
265
|
+
// Query should re-run with new referrer
|
|
266
|
+
await waitFor(() => {
|
|
267
|
+
expect(processReferral).toHaveBeenCalledTimes(2);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test("should handle no referrer in context", async ({
|
|
272
|
+
queryWrapper,
|
|
273
|
+
mockFrakClient,
|
|
274
|
+
}) => {
|
|
275
|
+
const mockReferralState = "success";
|
|
276
|
+
|
|
277
|
+
const mockWalletStatus: WalletStatusReturnType = {
|
|
278
|
+
key: "connected",
|
|
279
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
283
|
+
vi.mocked(useFrakContext).mockReturnValue({
|
|
284
|
+
frakContext: null, // No referrer
|
|
285
|
+
updateContext: vi.fn(),
|
|
286
|
+
});
|
|
287
|
+
vi.mocked(useWalletStatus).mockReturnValue({
|
|
288
|
+
data: mockWalletStatus,
|
|
289
|
+
isSuccess: true,
|
|
290
|
+
isPending: false,
|
|
291
|
+
} as ReturnType<typeof useWalletStatus>);
|
|
292
|
+
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
293
|
+
|
|
294
|
+
const { result } = renderHook(() => useReferralInteraction(), {
|
|
295
|
+
wrapper: queryWrapper.wrapper,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
await waitFor(() => {
|
|
299
|
+
expect(result.current).toEqual(mockReferralState);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
expect(processReferral).toHaveBeenCalledWith(
|
|
303
|
+
mockFrakClient,
|
|
304
|
+
expect.objectContaining({
|
|
305
|
+
frakContext: null,
|
|
306
|
+
})
|
|
307
|
+
);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ProcessReferralOptions,
|
|
3
|
+
processReferral,
|
|
4
|
+
} from "@frak-labs/core-sdk/actions";
|
|
5
|
+
import { ClientNotFound } from "@frak-labs/frame-connector";
|
|
6
|
+
import { useQuery } from "@tanstack/react-query";
|
|
7
|
+
import { useMemo } from "react";
|
|
8
|
+
import { useFrakClient } from "../useFrakClient";
|
|
9
|
+
import { useWalletStatus } from "../useWalletStatus";
|
|
10
|
+
import { useFrakContext } from "../utils/useFrakContext";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Helper hook to automatically submit a referral interaction when detected
|
|
14
|
+
*
|
|
15
|
+
* @group hooks
|
|
16
|
+
*
|
|
17
|
+
* @param args
|
|
18
|
+
* @param args.options - Some options for the referral interaction
|
|
19
|
+
*
|
|
20
|
+
* @returns The resulting referral state, or a potential error
|
|
21
|
+
*
|
|
22
|
+
* @description This function will automatically handle the referral interaction process
|
|
23
|
+
*
|
|
24
|
+
* @see {@link @frak-labs/core-sdk!actions.processReferral | `processReferral()`} for more details on the automatic referral handling process
|
|
25
|
+
*/
|
|
26
|
+
export function useReferralInteraction({
|
|
27
|
+
options,
|
|
28
|
+
}: {
|
|
29
|
+
options?: ProcessReferralOptions;
|
|
30
|
+
} = {}) {
|
|
31
|
+
// Get the frak client
|
|
32
|
+
const client = useFrakClient();
|
|
33
|
+
|
|
34
|
+
// Get the current frak context
|
|
35
|
+
const { frakContext } = useFrakContext();
|
|
36
|
+
|
|
37
|
+
// Get the wallet status
|
|
38
|
+
const { data: walletStatus } = useWalletStatus();
|
|
39
|
+
|
|
40
|
+
// Setup the query that will transmit the referral interaction
|
|
41
|
+
const {
|
|
42
|
+
data: referralState,
|
|
43
|
+
error,
|
|
44
|
+
status,
|
|
45
|
+
} = useQuery({
|
|
46
|
+
gcTime: 0,
|
|
47
|
+
staleTime: 0,
|
|
48
|
+
queryKey: [
|
|
49
|
+
"frak-sdk",
|
|
50
|
+
"auto-referral-interaction",
|
|
51
|
+
frakContext?.r ?? "no-referrer",
|
|
52
|
+
walletStatus?.key ?? "no-wallet-status",
|
|
53
|
+
],
|
|
54
|
+
queryFn: () => {
|
|
55
|
+
if (!client) {
|
|
56
|
+
throw new ClientNotFound();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return processReferral(client, {
|
|
60
|
+
walletStatus,
|
|
61
|
+
frakContext,
|
|
62
|
+
options,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
enabled: !!walletStatus,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return useMemo(() => {
|
|
69
|
+
if (status === "pending") return "processing";
|
|
70
|
+
if (status === "error") return error;
|
|
71
|
+
return referralState || "idle";
|
|
72
|
+
}, [referralState, status, error]);
|
|
73
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { useReferralInteraction } from "./helper/useReferralInteraction";
|
|
2
|
+
export { useDisplayModal } from "./useDisplayModal";
|
|
3
|
+
export { useFrakClient } from "./useFrakClient";
|
|
4
|
+
export { useFrakConfig } from "./useFrakConfig";
|
|
5
|
+
export { useGetMerchantInformation } from "./useGetMerchantInformation";
|
|
6
|
+
export { useOpenSso } from "./useOpenSso";
|
|
7
|
+
export { usePrepareSso } from "./usePrepareSso";
|
|
8
|
+
export { useSendTransactionAction } from "./useSendTransaction";
|
|
9
|
+
export { useSiweAuthenticate } from "./useSiweAuthenticate";
|
|
10
|
+
export { useWalletStatus } from "./useWalletStatus";
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for useDisplayModal hook
|
|
3
|
+
* Tests TanStack Mutation wrapper for displaying modals
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { vi } from "vitest";
|
|
7
|
+
|
|
8
|
+
vi.mock("@frak-labs/core-sdk/actions");
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
LoginModalStepType,
|
|
12
|
+
ModalRpcStepsResultType,
|
|
13
|
+
SendTransactionModalStepType,
|
|
14
|
+
} from "@frak-labs/core-sdk";
|
|
15
|
+
import { displayModal } from "@frak-labs/core-sdk/actions";
|
|
16
|
+
import { ClientNotFound } from "@frak-labs/frame-connector";
|
|
17
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
|
18
|
+
import { describe, expect, test } from "../../tests/vitest-fixtures";
|
|
19
|
+
import { useDisplayModal } from "./useDisplayModal";
|
|
20
|
+
|
|
21
|
+
describe("useDisplayModal", () => {
|
|
22
|
+
test("should throw ClientNotFound when client is not available", async ({
|
|
23
|
+
queryWrapper,
|
|
24
|
+
}) => {
|
|
25
|
+
const { result } = renderHook(() => useDisplayModal(), {
|
|
26
|
+
wrapper: queryWrapper.wrapper,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
await waitFor(() => {
|
|
30
|
+
expect(result.current.mutate).toBeDefined();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
result.current.mutate({
|
|
34
|
+
steps: {
|
|
35
|
+
login: {},
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
await waitFor(() => {
|
|
40
|
+
expect(result.current.isError).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
expect(result.current.error).toBeInstanceOf(ClientNotFound);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("should display modal with login step", async ({
|
|
47
|
+
mockFrakProviders,
|
|
48
|
+
}) => {
|
|
49
|
+
const mockResult: ModalRpcStepsResultType<[LoginModalStepType]> = {
|
|
50
|
+
login: {
|
|
51
|
+
wallet: "0x1234567890123456789012345678901234567890",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
vi.mocked(displayModal).mockResolvedValue(mockResult as any);
|
|
56
|
+
|
|
57
|
+
const { result } = renderHook(
|
|
58
|
+
() => useDisplayModal<[LoginModalStepType]>(),
|
|
59
|
+
{
|
|
60
|
+
wrapper: mockFrakProviders,
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
result.current.mutate({
|
|
65
|
+
steps: {
|
|
66
|
+
login: {},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await waitFor(() => {
|
|
71
|
+
expect(result.current.isSuccess).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(result.current.data).toEqual(mockResult);
|
|
75
|
+
expect(displayModal).toHaveBeenCalledTimes(1);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("should display modal with sendTransaction step", async ({
|
|
79
|
+
mockFrakProviders,
|
|
80
|
+
}) => {
|
|
81
|
+
const mockResult: ModalRpcStepsResultType<
|
|
82
|
+
[SendTransactionModalStepType]
|
|
83
|
+
> = {
|
|
84
|
+
sendTransaction: {
|
|
85
|
+
hash: "0x1234567890123456789012345678901234567890123456789012345678901234",
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
vi.mocked(displayModal).mockResolvedValue(mockResult as any);
|
|
90
|
+
|
|
91
|
+
const { result } = renderHook(
|
|
92
|
+
() => useDisplayModal<[SendTransactionModalStepType]>(),
|
|
93
|
+
{
|
|
94
|
+
wrapper: mockFrakProviders,
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
result.current.mutate({
|
|
99
|
+
steps: {
|
|
100
|
+
sendTransaction: {
|
|
101
|
+
tx: {
|
|
102
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
103
|
+
data: "0x",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
await waitFor(() => {
|
|
110
|
+
expect(result.current.isSuccess).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(result.current.data).toEqual(mockResult);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("should display modal with custom metadata", async ({
|
|
117
|
+
mockFrakProviders,
|
|
118
|
+
}) => {
|
|
119
|
+
const mockResult: ModalRpcStepsResultType<[LoginModalStepType]> = {
|
|
120
|
+
login: { wallet: "0x1234567890123456789012345678901234567890" },
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
vi.mocked(displayModal).mockResolvedValue(mockResult as any);
|
|
124
|
+
|
|
125
|
+
const { result } = renderHook(
|
|
126
|
+
() => useDisplayModal<[LoginModalStepType]>(),
|
|
127
|
+
{
|
|
128
|
+
wrapper: mockFrakProviders,
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
result.current.mutate({
|
|
133
|
+
steps: {
|
|
134
|
+
login: {},
|
|
135
|
+
},
|
|
136
|
+
metadata: {
|
|
137
|
+
header: {
|
|
138
|
+
title: "Custom Login",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
await waitFor(() => {
|
|
144
|
+
expect(result.current.isSuccess).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
expect(displayModal).toHaveBeenCalledWith(
|
|
148
|
+
expect.anything(),
|
|
149
|
+
expect.objectContaining({
|
|
150
|
+
metadata: expect.objectContaining({
|
|
151
|
+
header: {
|
|
152
|
+
title: "Custom Login",
|
|
153
|
+
},
|
|
154
|
+
}),
|
|
155
|
+
})
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("should handle mutateAsync", async ({ mockFrakProviders }) => {
|
|
160
|
+
const mockResult: ModalRpcStepsResultType<[LoginModalStepType]> = {
|
|
161
|
+
login: { wallet: "0x1234567890123456789012345678901234567890" },
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
vi.mocked(displayModal).mockResolvedValue(mockResult as any);
|
|
165
|
+
|
|
166
|
+
const { result } = renderHook(
|
|
167
|
+
() => useDisplayModal<[LoginModalStepType]>(),
|
|
168
|
+
{
|
|
169
|
+
wrapper: mockFrakProviders,
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const response = await result.current.mutateAsync({
|
|
174
|
+
steps: {
|
|
175
|
+
login: {},
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
expect(response).toEqual(mockResult);
|
|
180
|
+
|
|
181
|
+
await waitFor(() => {
|
|
182
|
+
expect(result.current.isSuccess).toBe(true);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("should handle RPC errors", async ({ mockFrakProviders }) => {
|
|
187
|
+
const error = new Error("Modal display failed");
|
|
188
|
+
vi.mocked(displayModal).mockRejectedValue(error);
|
|
189
|
+
|
|
190
|
+
const { result } = renderHook(() => useDisplayModal(), {
|
|
191
|
+
wrapper: mockFrakProviders,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
result.current.mutate({
|
|
195
|
+
steps: {
|
|
196
|
+
login: {},
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
await waitFor(() => {
|
|
201
|
+
expect(result.current.isError).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
expect(result.current.error).toEqual(error);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("should handle mutation options", async ({ mockFrakProviders }) => {
|
|
208
|
+
const mockResult: ModalRpcStepsResultType<[LoginModalStepType]> = {
|
|
209
|
+
login: { wallet: "0x1234567890123456789012345678901234567890" },
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
vi.mocked(displayModal).mockResolvedValue(mockResult as any);
|
|
213
|
+
|
|
214
|
+
const onSuccess = vi.fn();
|
|
215
|
+
const onError = vi.fn();
|
|
216
|
+
|
|
217
|
+
const { result } = renderHook(
|
|
218
|
+
() =>
|
|
219
|
+
useDisplayModal<[LoginModalStepType]>({
|
|
220
|
+
mutations: {
|
|
221
|
+
onSuccess,
|
|
222
|
+
onError,
|
|
223
|
+
},
|
|
224
|
+
}),
|
|
225
|
+
{
|
|
226
|
+
wrapper: mockFrakProviders,
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
result.current.mutate({
|
|
231
|
+
steps: {
|
|
232
|
+
login: {},
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
await waitFor(() => {
|
|
237
|
+
expect(result.current.isSuccess).toBe(true);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
expect(onSuccess).toHaveBeenCalled();
|
|
241
|
+
expect(onError).not.toHaveBeenCalled();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("should reset mutation state", async ({ mockFrakProviders }) => {
|
|
245
|
+
const mockResult: ModalRpcStepsResultType<[LoginModalStepType]> = {
|
|
246
|
+
login: { wallet: "0x1234567890123456789012345678901234567890" },
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
vi.mocked(displayModal).mockResolvedValue(mockResult as any);
|
|
250
|
+
|
|
251
|
+
const { result } = renderHook(
|
|
252
|
+
() => useDisplayModal<[LoginModalStepType]>(),
|
|
253
|
+
{
|
|
254
|
+
wrapper: mockFrakProviders,
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
result.current.mutate({
|
|
259
|
+
steps: {
|
|
260
|
+
login: {},
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
await waitFor(() => {
|
|
265
|
+
expect(result.current.isSuccess).toBe(true);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
result.current.reset();
|
|
269
|
+
|
|
270
|
+
await waitFor(() => {
|
|
271
|
+
expect(result.current.data).toBeUndefined();
|
|
272
|
+
expect(result.current.isIdle).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|