Skip to content

Commit 6cf1fd8

Browse files
authored
test(react, vue): use-mutation hook and composable (#735)
1 parent b847f5b commit 6cf1fd8

2 files changed

Lines changed: 232 additions & 0 deletions

File tree

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { ChainProvider } from "../contexts/chain.js";
2+
import { ReactiveDotProvider } from "../contexts/provider.js";
3+
import { SignerProvider } from "../contexts/signer.js";
4+
import { useMutation } from "./use-mutation.js";
5+
import { defineConfig, idle, pending } from "@reactive-dot/core";
6+
import { act, renderHook } from "@testing-library/react";
7+
import { atom } from "jotai";
8+
import type { PolkadotSigner, TxEvent } from "polkadot-api";
9+
import { from, of, throwError } from "rxjs";
10+
import { concatMap, delay } from "rxjs/operators";
11+
import { afterEach, beforeEach, expect, it, vi } from "vitest";
12+
13+
const mockSignSubmitAndWatch = vi.fn();
14+
15+
vi.mock("./use-typed-api.js", () => ({
16+
typedApiAtom: vi.fn(() =>
17+
atom({
18+
tx: {
19+
TestPallet: {
20+
testCall: vi.fn().mockReturnValue({
21+
signSubmitAndWatch: mockSignSubmitAndWatch,
22+
}),
23+
},
24+
},
25+
}),
26+
),
27+
}));
28+
29+
vi.useFakeTimers();
30+
31+
beforeEach(() =>
32+
mockSignSubmitAndWatch.mockReturnValue(
33+
from<Partial<TxEvent>[]>([
34+
{ type: "signed" },
35+
{ type: "broadcasted" },
36+
{ type: "txBestBlocksState" },
37+
{ type: "finalized" },
38+
]).pipe(concatMap((item) => of(item).pipe(delay(1000)))),
39+
),
40+
);
41+
42+
afterEach(() => {
43+
vi.restoreAllMocks();
44+
});
45+
46+
it("sign submit and watch", async () => {
47+
const { result } = await act(() =>
48+
renderHook(
49+
() =>
50+
useMutation((tx) =>
51+
// @ts-expect-error mocked call
52+
tx.TestPallet!.testCall("test-value"),
53+
),
54+
{
55+
wrapper: ({ children }) => (
56+
<ReactiveDotProvider config={defineConfig({ chains: {} })}>
57+
<ChainProvider chainId="test_chain">
58+
<SignerProvider signer={{} as PolkadotSigner}>
59+
{children}
60+
</SignerProvider>
61+
</ChainProvider>
62+
</ReactiveDotProvider>
63+
),
64+
},
65+
),
66+
);
67+
68+
expect(result.current[0]).toBe(idle);
69+
70+
await act(() => result.current[1]());
71+
72+
expect(result.current[0]).toBe(pending);
73+
74+
await act(() => vi.advanceTimersByTime(1000));
75+
76+
expect(result.current[0]).toMatchObject({ type: "signed" });
77+
78+
await act(() => vi.advanceTimersByTime(1000));
79+
80+
expect(result.current[0]).toMatchObject({ type: "broadcasted" });
81+
82+
await act(() => vi.advanceTimersByTime(1000));
83+
84+
expect(result.current[0]).toMatchObject({ type: "txBestBlocksState" });
85+
86+
await act(() => vi.advanceTimersByTime(1000));
87+
88+
expect(result.current[0]).toMatchObject({ type: "finalized" });
89+
});
90+
91+
it("catches error", async () => {
92+
const { result } = await act(() =>
93+
renderHook(
94+
() =>
95+
useMutation((tx) =>
96+
// @ts-expect-error mocked call
97+
tx.TestPallet!.testCall("test-value"),
98+
),
99+
{
100+
wrapper: ({ children }) => (
101+
<ReactiveDotProvider config={defineConfig({ chains: {} })}>
102+
<ChainProvider chainId="test_chain">
103+
<SignerProvider signer={{} as PolkadotSigner}>
104+
{children}
105+
</SignerProvider>
106+
</ChainProvider>
107+
</ReactiveDotProvider>
108+
),
109+
},
110+
),
111+
);
112+
113+
mockSignSubmitAndWatch.mockReturnValue(throwError(() => new Error("test")));
114+
115+
expect(result.current[0]).toBe(idle);
116+
117+
await act(() => result.current[1]());
118+
119+
expect(result.current[0]).toBeInstanceOf(Error);
120+
});
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { chainIdKey, configKey, signerKey } from "../keys.js";
2+
import { withSetup } from "../test-utils.js";
3+
import { useMutation } from "./use-mutation.js";
4+
import { defineConfig } from "@reactive-dot/core";
5+
import type { TxEvent } from "polkadot-api";
6+
import { from, of, throwError } from "rxjs";
7+
import { concatMap, delay } from "rxjs/operators";
8+
import { afterEach, beforeEach, expect, it, vi } from "vitest";
9+
import { computed } from "vue";
10+
11+
const mockSignSubmitAndWatch = vi.fn();
12+
13+
vi.mock("./use-typed-api.js", () => ({
14+
useTypedApiPromise: vi.fn(() =>
15+
computed(() =>
16+
Promise.resolve({
17+
tx: {
18+
TestPallet: {
19+
testCall: vi.fn(() => ({
20+
signSubmitAndWatch: mockSignSubmitAndWatch,
21+
})),
22+
},
23+
},
24+
}),
25+
),
26+
),
27+
}));
28+
29+
vi.useFakeTimers();
30+
31+
beforeEach(() =>
32+
mockSignSubmitAndWatch.mockReturnValue(
33+
from<Partial<TxEvent>[]>([
34+
{ type: "signed" },
35+
{ type: "broadcasted" },
36+
{ type: "txBestBlocksState" },
37+
{ type: "finalized" },
38+
]).pipe(concatMap((item) => of(item).pipe(delay(1000)))),
39+
),
40+
);
41+
42+
afterEach(() => {
43+
vi.restoreAllMocks();
44+
});
45+
46+
it("sign submit and watch", async () => {
47+
const { result } = withSetup(
48+
() =>
49+
useMutation((tx) =>
50+
// @ts-expect-error mocked call
51+
tx.TestPallet!.testCall("test-value"),
52+
),
53+
{
54+
[configKey]: defineConfig({ chains: {} }),
55+
[chainIdKey]: "test_chain",
56+
[signerKey]: {},
57+
},
58+
);
59+
60+
expect(result.status.value).toBe("idle");
61+
62+
result.execute();
63+
64+
expect(result.status.value).toBe("pending");
65+
66+
vi.advanceTimersByTime(1000);
67+
68+
await vi.waitUntil(() => result.status.value === "success", {
69+
timeout: 3000,
70+
});
71+
72+
expect(result.data.value).toMatchObject({ type: "signed" });
73+
74+
vi.advanceTimersByTime(1000);
75+
76+
expect(result.data.value).toMatchObject({ type: "broadcasted" });
77+
78+
vi.advanceTimersByTime(1000);
79+
80+
expect(result.data.value).toMatchObject({ type: "txBestBlocksState" });
81+
82+
vi.advanceTimersByTime(1000);
83+
84+
expect(result.data.value).toMatchObject({ type: "finalized" });
85+
});
86+
87+
it("catches error", async () => {
88+
const { result } = withSetup(
89+
() =>
90+
useMutation((tx) =>
91+
// @ts-expect-error mocked call
92+
tx.TestPallet!.testCall("test-value"),
93+
),
94+
{
95+
[configKey]: defineConfig({ chains: {} }),
96+
[chainIdKey]: "test_chain",
97+
[signerKey]: {},
98+
},
99+
);
100+
101+
mockSignSubmitAndWatch.mockReturnValue(throwError(() => new Error("test")));
102+
103+
expect(result.status.value).toBe("idle");
104+
105+
result.execute();
106+
107+
await vi.waitUntil(() => result.status.value === "error", {
108+
timeout: 3000,
109+
});
110+
111+
expect(result.error.value).toBeInstanceOf(Error);
112+
});

0 commit comments

Comments
 (0)