Skip to content

Commit cb69862

Browse files
authored
test(hooks): add specs for useTransaction() (#178) (#295)
1 parent 29281c6 commit cb69862

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { renderHook, act } from '@testing-library/react-hooks';
2+
import { useTransaction } from './useTransaction';
3+
4+
describe('useTransaction', () => {
5+
let getMockMethod: (withError?: boolean) => jest.Mock<any, any>;
6+
const tx = {
7+
chainId: 0,
8+
confirmations: 0,
9+
from: '0xd9f96E9bDb294Fc0819e88fc51FE3C7907173493',
10+
hash: '0xd268efc2a51973df6012357e05739e8e44258a4ee6e32fe9d8810cbc5c32b8ac',
11+
};
12+
const txReceipt = { ...tx, confirmations: 2 };
13+
const txResponse = {
14+
...tx,
15+
wait: () => new Promise((res) => setTimeout(() => res(txReceipt))),
16+
};
17+
const txError = {
18+
code: 4001,
19+
message: 'MetaMask Tx Signature: User denied transaction signature.',
20+
};
21+
22+
beforeEach(() => {
23+
getMockMethod = (withError = false) =>
24+
jest.fn(() => {
25+
// Do async work to simulate a transaction
26+
return new Promise((res, rej) => {
27+
setTimeout(() => {
28+
withError ? rej(txError) : res(txResponse);
29+
});
30+
});
31+
});
32+
});
33+
34+
test('has correct API', () => {
35+
const mockMethod = getMockMethod();
36+
const { result } = renderHook(() => useTransaction(mockMethod));
37+
const [execute, loading, error] = result.current;
38+
39+
expect(typeof execute).toBe('function');
40+
expect(typeof loading).toBe('boolean');
41+
expect(typeof error).not.toBe('undefined');
42+
});
43+
44+
test('execute() calls given method with correct args', async () => {
45+
const mockMethod = getMockMethod();
46+
const { result } = renderHook(() => useTransaction(mockMethod));
47+
const execute = result.current[0];
48+
const args = ['Hello World', 1, true];
49+
50+
await act(async () => {
51+
await execute(args);
52+
});
53+
54+
expect(mockMethod.mock.calls[0]).toEqual([args]);
55+
});
56+
57+
test('execute() sets loading back to false after transaction has finished', async () => {
58+
const mockMethod = getMockMethod();
59+
const { result } = renderHook(() => useTransaction(mockMethod));
60+
61+
expect(result.current[1]).toBe(false);
62+
await act(async () => {
63+
// await the method call and confirmation
64+
await result.current[0]([]);
65+
expect(result.current[1]).toBe(false);
66+
});
67+
});
68+
69+
test('execute() returns the transaction response if successful', async () => {
70+
const mockMethod = getMockMethod();
71+
const { result } = renderHook(() => useTransaction(mockMethod));
72+
73+
await act(async () => {
74+
const returnVal = await result.current[0]([]);
75+
expect(returnVal).toBe(txResponse);
76+
});
77+
});
78+
79+
test('execute() sets error if unsuccessful', async () => {
80+
const mockMethod = getMockMethod(true); // withError = true
81+
const { result } = renderHook(() => useTransaction(mockMethod));
82+
83+
expect(result.current[2]).toBe(null);
84+
await act(async () => {
85+
await result.current[0]([]);
86+
expect(result.current[2]).toBe(txError);
87+
});
88+
});
89+
90+
test('execute() returns error if unsuccessful', async () => {
91+
const mockMethod = getMockMethod(true); // withError = true
92+
const { result } = renderHook(() => useTransaction(mockMethod));
93+
94+
expect(result.current[2]).toBe(null);
95+
await act(async () => {
96+
const response = await result.current[0]([]);
97+
expect(response).toBe(txError);
98+
});
99+
});
100+
101+
test('execute() sets loading to true', async () => {
102+
const mockMethod = getMockMethod();
103+
const { result, waitFor } = renderHook(() => useTransaction(mockMethod));
104+
105+
expect(result.current[1]).toBe(false);
106+
await act(async () => {
107+
await waitFor(() => {
108+
result.current[0]([]);
109+
110+
// while waiting for the transaction to be confirmed...
111+
expect(result.current[1]).toBe(true);
112+
});
113+
});
114+
});
115+
});

0 commit comments

Comments
 (0)