-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTestAsyncThunk.ts
89 lines (73 loc) · 2.12 KB
/
TestAsyncThunk.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import type { AsyncThunkAction, Dispatch } from '@reduxjs/toolkit'
import type { AxiosStatic } from 'axios'
import axios from 'axios'
import type { StateSchema } from '@/app/providers/StoreProvider'
type ActionCreator<Return, Arg, RejectValue> = (
arg: Arg
) => AsyncThunkAction<Return, Arg, { rejectValue: RejectValue }>
jest.mock('axios')
const mockedAxios = jest.mocked(axios)
/**
* This class is used to test async thunks.
* It mocks dispatch, getState and thunk extra arguments.
*
* Usage:
* ```ts
// defines mocked state for the test
const state = {
articleDetails: {
data: {
id: 1,
},
},
user: {
authData: {
id: 1,
},
},
}
// creates a new instance of TestAsyncThunk. First argument is the thunk to test, second is the mocked state
const thunk = new TestAsyncThunk(sendArticleComment, state)
// defines the expected result
const newComment = {
body: 'new comment body',
id: 4,
}
// mocks axios.post
thunk.api.post.mockReturnValue(
Promise.resolve({
data: newComment,
})
)
// calls the mocked thunk
const result = await thunk.call('new comment body')
// asserts the result
expect(result.payload).toEqual(newComment)
expect(thunk.api.post).toHaveBeenCalled()
expect(result.meta.requestStatus).toEqual('fulfilled')
* ```
*/
export class TestAsyncThunk<Return, Arg, RejectValue> {
dispatch: jest.MockedFunction<Dispatch>
getState: () => StateSchema
actionCreator: ActionCreator<Return, Arg, RejectValue>
api: jest.MockedFunctionDeep<AxiosStatic>
constructor(
actionCreator: ActionCreator<Return, Arg, RejectValue>,
state?: DeepPartial<StateSchema>
) {
this.actionCreator = actionCreator
this.dispatch = jest.fn()
this.getState = jest.fn(() => state as StateSchema)
this.api = mockedAxios
}
async call(arg: Arg) {
// we create an action that we normally put into dispatch
const action = this.actionCreator(arg)
// normally this is passed by redux-thunk middleware
const result = await action(this.dispatch, this.getState, {
api: this.api,
})
return result
}
}