-
Notifications
You must be signed in to change notification settings - Fork 0
/
withActions.test.tsx
140 lines (114 loc) · 4.31 KB
/
withActions.test.tsx
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import { shallow } from 'enzyme'
import * as React from 'react'
import { withActions, ActionDef } from './withActions'
const setupComponent = (mockActionImpl?: (token: any, arg: any) => void) => {
const Component = jest.fn(() => null)
const mockAction = jest.fn(mockActionImpl)
const actions = { mock: [mockAction, { someOption: true }] as ActionDef<any> }
const WrappedComponent = withActions(actions)(Component)
const wrapper = shallow(<WrappedComponent id={1} />)
wrapper.render()
return { wrapper, Component, mockAction, mockProps: Component.mock.calls }
}
const setupWithResolveAndReject = () => {
let resolveCallback: (arg?: any) => void
let rejectCallback: (error?: Error) => void
const promise = new Promise((resolve, reject) => {
resolveCallback = resolve
rejectCallback = reject
})
return {
...setupComponent(() => promise),
// TS cannot know it is already assigned
// @ts-ignore
resolve: resolveCallback,
// @ts-ignore
reject: rejectCallback,
}
}
// As withActions resolve the callbacks as promises it is not immediate
// we can hook into componentDidUpdate of our mock or just wait for next loop.
const wait = () => {
return new Promise((resolve) => {
setTimeout(() => resolve(), 0)
})
}
describe('withActions', () => {
it('Supplies component with correct ActionProp', () => {
const { mockProps } = setupComponent()
expect(mockProps[0][0].id).toBe(1)
expect(Object.keys(mockProps[0][0].mock)).toEqual(['run'])
expect(typeof mockProps[0][0].mock.run).toBe('function')
})
it('It calls supplied action callback after calling run()', async () => {
const { mockAction, mockProps } = setupComponent()
mockProps[0][0].mock.run(1)
// This should be a cancelToken
// TODO better check
expect(typeof mockAction.mock.calls[0][0].cancelToken).toBe('object')
expect(mockAction.mock.calls[0][0].params).toBe(1)
})
it('Updates isLoading state after calling run()', async () => {
expect.assertions(2)
const { wrapper, mockProps, resolve } = setupWithResolveAndReject()
mockProps[0][0].mock.run(1)
wrapper.render()
// We run the action which is not resolved yet, we expect to have
// rendered with isLoading == true
expect(mockProps[1][0].mock.isLoading).toBe(true)
resolve()
await wait()
wrapper.render()
// After resolving the promise we should no longer be loading
expect(mockProps[2][0].mock.isLoading).toBe(false)
})
it('Updates result of ActionProp after resolving callback ', async () => {
expect.assertions(1)
const { wrapper, mockProps, resolve } = setupWithResolveAndReject()
mockProps[0][0].mock.run(1)
wrapper.render()
resolve(2)
await wait()
wrapper.render()
expect(mockProps[2][0].mock.response).toBe(2)
})
it('Updates ActionProp with error, when action callback throws, ', async () => {
expect.assertions(2)
const { wrapper, mockProps, reject } = setupWithResolveAndReject()
mockProps[0][0].mock.run(1)
wrapper.render()
reject(new Error('reject test'))
await wait()
wrapper.render()
expect(mockProps[2][0].mock.error instanceof Error).toBe(true)
expect(mockProps[2][0].mock.error.message).toBe('reject test')
})
it('Calls custom errorHandler when action callback throws', async () => {
expect.assertions(4)
const { wrapper, mockProps, reject } = setupWithResolveAndReject()
const errorHandler = jest.fn()
withActions.config.errorHandler = errorHandler
mockProps[0][0].mock.run(1)
wrapper.render()
reject(new Error('reject test'))
await wait()
expect(errorHandler.mock.calls[0][0]).toBe('mock')
expect(errorHandler.mock.calls[0][1].message).toBe('reject test')
expect(errorHandler.mock.calls[0][2]).toEqual({ someOption: true })
expect(typeof errorHandler.mock.calls[0][3]).toBe('function')
})
it('Cancels token on unmount', async () => {
expect.assertions(2)
const errorHandler = jest.fn()
withActions.config.errorHandler = errorHandler
const { wrapper, Component } = setupComponent(async ({ cancelToken }) => {
await wait()
expect(cancelToken.reason).toBeTruthy()
cancelToken.throwIfRequested()
})
Component.mock.calls[0][0].mock.run(1)
wrapper.unmount()
await wait()
expect(errorHandler.mock.calls.length).toBe(0)
})
})