gopeeker 0.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of gopeeker might be problematic. Click here for more details.

@@ -0,0 +1,326 @@
1
+ import React from 'react'
2
+ import { render } from '@testing-library/react'
3
+ import { act } from '@testing-library/react-hooks'
4
+ import { createStore } from '../src/index'
5
+ import { counter, counter2 } from './helper/model'
6
+ import { createHook } from './helper/createHook'
7
+ import { CounterWithRef } from './helper/CountFunctionComponent'
8
+ import { Counter } from './helper/CountClassComponent'
9
+ import {
10
+ CounterWithContextName,
11
+ CounterWithDefault,
12
+ CounterWithSameContextName,
13
+ CounterWithOtherContextName,
14
+ } from './helper/MultiCountClassComponent'
15
+
16
+ describe('Provider test', () => {
17
+ it('should render correct when use provider in component', () => {
18
+ const store = createStore({
19
+ counter,
20
+ })
21
+ const { Provider, withProvider } = store
22
+
23
+ const Component: React.FC = () => <div></div>
24
+
25
+ expect(() => {
26
+ render(
27
+ <Provider>
28
+ <Component />
29
+ </Provider>
30
+ )
31
+ }).not.toThrow()
32
+
33
+ const WithProvider = withProvider(Component)
34
+
35
+ expect(() => {
36
+ render(<WithProvider />)
37
+ }).not.toThrow()
38
+ })
39
+
40
+ it('should throw error when call useModel without Provider wrapper', () => {
41
+ const originalError = console.error
42
+ console.error = jest.fn()
43
+
44
+ const store = createStore({
45
+ counter,
46
+ })
47
+ const { useModel } = store
48
+
49
+ const ErrorCounter: React.FC = () => {
50
+ const { state } = useModel('counter')
51
+ return <div>{state.count}</div>
52
+ }
53
+
54
+ expect(() => render(<ErrorCounter />)).toThrow()
55
+
56
+ console.error = originalError
57
+ })
58
+
59
+ it('support pass ref use withProviderForwardRef', () => {
60
+ let ref: any
61
+ render(<CounterWithRef ref={r => (ref = r)} />)
62
+
63
+ expect(ref.methodFromUseImperativeHandle).toBeDefined()
64
+ })
65
+
66
+ it('should add the store to function component context', () => {
67
+ const store = createStore({
68
+ counter,
69
+ })
70
+ const { Provider, useModel } = store
71
+
72
+ const {
73
+ result: { current },
74
+ } = createHook(Provider, useModel, 'counter')
75
+
76
+ expect(current.state.count).toBe(0)
77
+ expect(current.reducers).toBeDefined()
78
+ expect(current.effects).toBeDefined()
79
+ })
80
+
81
+ it('should add the store to class component context', () => {
82
+ const originalWarn = console.warn
83
+ console.warn = jest.fn()
84
+
85
+ const store = createStore({
86
+ counter,
87
+ })
88
+ const { Provider, withModel } = store
89
+
90
+ const Component = withModel('counter')(Counter)
91
+
92
+ const wrapper = render(
93
+ <Provider>
94
+ <Component />
95
+ </Provider>
96
+ )
97
+
98
+ expect(wrapper.getByTestId('count').innerHTML).toBe('0')
99
+
100
+ const Component2 = withModel('counter', undefined, 'models')(CounterWithSameContextName)
101
+ const wrapper2 = render(
102
+ <Provider>
103
+ {/* @ts-ignore */}
104
+ <Component2 models="what ever" />
105
+ </Provider>
106
+ )
107
+ expect(console.warn).toHaveBeenCalledWith(
108
+ 'IMPORT MODEL FAILED: The component wrapped by [withModel] already has "models" in its props.'
109
+ )
110
+ expect(wrapper2.getByTestId('show-models').innerHTML).toBe('what ever')
111
+
112
+ const Component3 = withModel('counter')(Counter)
113
+
114
+ render(
115
+ <Provider>
116
+ {/* @ts-ignore */}
117
+ <Component3 state="1" reducers="2" effects="3" />
118
+ </Provider>
119
+ )
120
+ expect(console.warn).toHaveBeenCalledWith(
121
+ 'IMPORT MODEL FAILED: The component wrapped by [withModel] already has "state" in its props.'
122
+ )
123
+ expect(console.warn).toHaveBeenCalledWith(
124
+ 'IMPORT MODEL FAILED: The component wrapped by [withModel] already has "reducers" in its props.'
125
+ )
126
+ expect(console.warn).toHaveBeenCalledWith(
127
+ 'IMPORT MODEL FAILED: The component wrapped by [withModel] already has "effects" in its props.'
128
+ )
129
+
130
+ const Component4 = withModel('counter', undefined, 'myModel')(CounterWithOtherContextName)
131
+ const wrapper4 = render(
132
+ <Provider>
133
+ {/* @ts-ignore */}
134
+ <Component4 myProp="what ever" />
135
+ </Provider>
136
+ )
137
+ expect(wrapper4.getByTestId('show-myProp').innerHTML).toBe('what ever')
138
+ expect(wrapper4.getByTestId('show-myModel').innerHTML).toBe('0')
139
+
140
+ console.warn = originalWarn
141
+ })
142
+
143
+ it('should warning when props override', () => {
144
+ const originalWarn = console.warn
145
+ console.warn = jest.fn()
146
+
147
+ const store = createStore({
148
+ counter,
149
+ })
150
+ const { Provider, withModel } = store
151
+
152
+ const Component = withModel('counter')(Counter)
153
+
154
+ const wrapper = render(
155
+ <Provider>
156
+ <Component />
157
+ </Provider>
158
+ )
159
+
160
+ expect(wrapper.getByTestId('count').innerHTML).toBe('0')
161
+
162
+ const Component2 = withModel('counter', undefined, 'models')(CounterWithSameContextName)
163
+ const wrapper2 = render(
164
+ <Provider>
165
+ {/* @ts-ignore */}
166
+ <Component2 models="what ever" />
167
+ </Provider>
168
+ )
169
+ expect(console.warn).toHaveBeenCalledWith(
170
+ 'IMPORT MODEL FAILED: The component wrapped by [withModel] already has "models" in its props.'
171
+ )
172
+ expect(wrapper2.getByTestId('show-models').innerHTML).toBe('what ever')
173
+
174
+ const Component3 = withModel('counter', undefined, 'myModel')(CounterWithOtherContextName)
175
+ const wrapper3 = render(
176
+ <Provider>
177
+ {/* @ts-ignore */}
178
+ <Component3 myProp="what ever" />
179
+ </Provider>
180
+ )
181
+ expect(wrapper3.getByTestId('show-myProp').innerHTML).toBe('what ever')
182
+ expect(wrapper3.getByTestId('show-myModel').innerHTML).toBe('0')
183
+
184
+ console.warn = originalWarn
185
+ })
186
+
187
+ it('should add specific stores to class component context', () => {
188
+ const store = createStore({
189
+ counter,
190
+ counter2,
191
+ })
192
+ const { Provider, withModels } = store
193
+
194
+ const Component2 = withModels(['counter', 'counter2'])(CounterWithDefault)
195
+
196
+ const wrapper2 = render(
197
+ <Provider>
198
+ <Component2 />
199
+ </Provider>
200
+ )
201
+ expect(wrapper2.getByTestId('count-1').innerHTML).toBe('0')
202
+ expect(wrapper2.getByTestId('count-2').innerHTML).toBe('0')
203
+ })
204
+
205
+ it('should add specific stores to class component context with custom property', () => {
206
+ const originalWarn = console.warn
207
+ console.warn = jest.fn()
208
+
209
+ const store = createStore({
210
+ counter,
211
+ counter2,
212
+ })
213
+ const { Provider, withModels } = store
214
+
215
+ const Component = withModels(
216
+ ['counter', 'counter2'],
217
+ {
218
+ counter: state => ({
219
+ count: state.count,
220
+ }),
221
+ },
222
+ 'forDobux'
223
+ )(CounterWithContextName)
224
+
225
+ const wrapper = render(
226
+ <Provider>
227
+ <Component />
228
+ </Provider>
229
+ )
230
+ expect(wrapper.getByTestId('count-1').innerHTML).toBe('0')
231
+ expect(wrapper.getByTestId('count-2').innerHTML).toBe('0')
232
+
233
+ const Component2 = withModels(['counter', 'counter2'])(CounterWithSameContextName)
234
+
235
+ const wrapper2 = render(
236
+ <Provider>
237
+ {/* @ts-ignore */}
238
+ <Component2 models="correct answer" />
239
+ </Provider>
240
+ )
241
+
242
+ expect(console.warn).toHaveBeenCalledWith(
243
+ 'IMPORT MODELS FAILED: The component wrapped by [withModels] already has "models" in its props.'
244
+ )
245
+ expect(wrapper2.getByTestId('show-models').innerHTML).toBe('correct answer')
246
+
247
+ console.warn = originalWarn
248
+ })
249
+
250
+ it('should not reset store when component unmount', async () => {
251
+ const store = createStore({
252
+ counter,
253
+ })
254
+ const { Provider, useModel } = store
255
+ const { result, unmount } = createHook(Provider, useModel, 'counter')
256
+
257
+ act(() => {
258
+ expect(result.current.state.count).toBe(0)
259
+ result.current.reducers.increase()
260
+ })
261
+
262
+ expect(result.current.state.count).toBe(1)
263
+
264
+ unmount()
265
+
266
+ const {
267
+ result: { current },
268
+ } = createHook(Provider, useModel, 'counter')
269
+
270
+ expect(current.state.count).toBe(1)
271
+ })
272
+
273
+ it('setting autoReset to true, model should be reset when the component unmount', async () => {
274
+ const store = createStore(
275
+ {
276
+ counter,
277
+ },
278
+ {
279
+ autoReset: true,
280
+ }
281
+ )
282
+ const { Provider, useModel } = store
283
+ const { result, unmount } = createHook(Provider, useModel, 'counter')
284
+
285
+ act(() => {
286
+ expect(result.current.state.count).toBe(0)
287
+ result.current.reducers.increase()
288
+ })
289
+
290
+ expect(result.current.state.count).toBe(1)
291
+
292
+ unmount()
293
+
294
+ const {
295
+ result: { current },
296
+ } = createHook(Provider, useModel, 'counter')
297
+
298
+ expect(current.state.count).toBe(0)
299
+ })
300
+
301
+ it('setting autoReset to specify model, should be reset when the component unmount', async () => {
302
+ const store = createStore(
303
+ {
304
+ counter,
305
+ },
306
+ {
307
+ autoReset: ['counter'],
308
+ }
309
+ )
310
+ const { Provider, useModel } = store
311
+ const { result, unmount } = createHook(Provider, useModel, 'counter')
312
+
313
+ act(() => {
314
+ expect(result.current.state.count).toBe(0)
315
+ result.current.reducers.increase()
316
+ })
317
+
318
+ expect(result.current.state.count).toBe(1)
319
+
320
+ unmount()
321
+
322
+ const hook = createHook(Provider, useModel, 'counter')
323
+
324
+ expect(hook.result.current.state.count).toBe(0)
325
+ })
326
+ })
@@ -0,0 +1,270 @@
1
+ import { act } from '@testing-library/react-hooks'
2
+ import { createStore } from '../src/index'
3
+ import { counter } from './helper/model'
4
+ import { createHook } from './helper/createHook'
5
+
6
+ describe('reducer test', () => {
7
+ it('customize reducers execution results should be as expected', () => {
8
+ const store = createStore({
9
+ counter,
10
+ })
11
+ const { Provider, useModel } = store
12
+
13
+ const { result } = createHook(Provider, useModel, 'counter')
14
+
15
+ const increase = result.current.reducers.increase
16
+ const decrease = result.current.reducers.decrease
17
+
18
+ expect(increase.length).toBe(0)
19
+
20
+ act(() => {
21
+ increase()
22
+ })
23
+ expect(result.current.state.count).toBe(1)
24
+
25
+ act(() => {
26
+ decrease()
27
+ })
28
+ expect(result.current.state.count).toBe(0)
29
+ })
30
+
31
+ it('should not rerender when the value of mapStateToProps returned not modified', () => {
32
+ const store = createStore({
33
+ counter,
34
+ })
35
+ const { Provider, useModel } = store
36
+
37
+ const { result } = createHook(Provider, useModel, 'counter', (state: any) => {
38
+ return {
39
+ count: state.count,
40
+ }
41
+ })
42
+
43
+ const increase = result.current.reducers.increase
44
+ const decrease = result.current.reducers.decrease
45
+
46
+ expect(result.current.state.count).toBe(0)
47
+ expect(result.current.state.data).toBeUndefined()
48
+ expect(increase.length).toBe(0)
49
+
50
+ act(() => {
51
+ increase()
52
+ })
53
+ expect(result.current.state.count).toBe(1)
54
+
55
+ act(() => {
56
+ decrease()
57
+ })
58
+ expect(result.current.state.count).toBe(0)
59
+
60
+ act(() => {
61
+ result.current.reducers.setValue('data', 1)
62
+ })
63
+
64
+ expect(result.current.state.data).toBeUndefined()
65
+ })
66
+
67
+ it('should provider build-in reducers when no customize passed', () => {
68
+ const store = createStore({
69
+ counter,
70
+ })
71
+ const { Provider, useModel } = store
72
+
73
+ const { result } = createHook(Provider, useModel, 'counter')
74
+
75
+ const setValue = result.current.reducers.setValue
76
+ const setValues = result.current.reducers.setValues
77
+ const reset = result.current.reducers.reset
78
+
79
+ expect(setValue.length).toBe(2)
80
+ act(() => {
81
+ setValue('count', 1)
82
+ })
83
+ expect(result.current.state.count).toBe(1)
84
+
85
+ act(() => {
86
+ setValue('count', (prevState: number) => {
87
+ return prevState - 1
88
+ })
89
+ })
90
+ expect(result.current.state.count).toBe(0)
91
+
92
+ act(() => {
93
+ setValue('data', (draft: any) => {
94
+ draft.a = 2
95
+ draft.b = '3'
96
+ })
97
+ })
98
+ expect(result.current.state.data).toEqual({
99
+ a: 2,
100
+ b: '3',
101
+ })
102
+
103
+ expect(setValues.length).toBe(1)
104
+ act(() => {
105
+ setValues({
106
+ count: 10,
107
+ })
108
+ })
109
+ expect(result.current.state.count).toBe(10)
110
+
111
+ act(() => {
112
+ setValues((prevState: Record<string, any>) => {
113
+ prevState.count = prevState.count - 10
114
+ })
115
+ })
116
+ expect(result.current.state.count).toBe(0)
117
+
118
+ act(() => {
119
+ setValues((prevState: Record<string, any>) => {
120
+ return {
121
+ count: prevState.count + 1,
122
+ }
123
+ })
124
+ })
125
+ expect(result.current.state.count).toBe(1)
126
+
127
+ expect(reset.length).toBe(1)
128
+ act(() => {
129
+ reset('count')
130
+ })
131
+ expect(result.current.state.count).toBe(0)
132
+
133
+ act(() => {
134
+ setValues({
135
+ data: 1,
136
+ count: 10,
137
+ })
138
+ })
139
+
140
+ expect(result.current.state.count).toBe(10)
141
+ expect(result.current.state.data).toBe(1)
142
+
143
+ act(() => {
144
+ reset()
145
+ })
146
+
147
+ expect(result.current.state.count).toBe(0)
148
+ expect(result.current.state.data).toEqual({
149
+ a: 1,
150
+ b: '2',
151
+ })
152
+ })
153
+
154
+ it('should provider build-in reducers when no customize passed', () => {
155
+ const store = createStore({
156
+ counter,
157
+ })
158
+ const { Provider, useModel } = store
159
+
160
+ const { result } = createHook(Provider, useModel, 'counter')
161
+
162
+ const setValue = result.current.reducers.setValue
163
+ const setValues = result.current.reducers.setValues
164
+ const reset = result.current.reducers.reset
165
+
166
+ expect(setValue.length).toBe(2)
167
+ act(() => {
168
+ setValue('count', 1)
169
+ })
170
+ expect(result.current.state.count).toBe(1)
171
+
172
+ act(() => {
173
+ setValue('count', (prevState: number) => {
174
+ return prevState - 1
175
+ })
176
+ })
177
+ expect(result.current.state.count).toBe(0)
178
+
179
+ expect(setValues.length).toBe(1)
180
+ act(() => {
181
+ setValues({
182
+ count: 10,
183
+ })
184
+ })
185
+ expect(result.current.state.count).toBe(10)
186
+
187
+ act(() => {
188
+ setValues((prevState: Record<string, any>) => {
189
+ prevState.count = prevState.count - 10
190
+ })
191
+ })
192
+ expect(result.current.state.count).toBe(0)
193
+
194
+ expect(reset.length).toBe(1)
195
+ act(() => {
196
+ reset('count')
197
+ })
198
+ expect(result.current.state.count).toBe(0)
199
+
200
+ act(() => {
201
+ setValues({
202
+ data: 1,
203
+ count: 10,
204
+ })
205
+ })
206
+
207
+ expect(result.current.state.count).toBe(10)
208
+ expect(result.current.state.data).toBe(1)
209
+
210
+ act(() => {
211
+ reset()
212
+ })
213
+
214
+ expect(result.current.state.count).toBe(0)
215
+ expect(result.current.state.data).toEqual({
216
+ a: 1,
217
+ b: '2',
218
+ })
219
+ })
220
+
221
+ it('should overwrite build-in reducers when customize passed', () => {
222
+ const store = createStore({
223
+ counter: {
224
+ state: {
225
+ count: 10,
226
+ },
227
+ reducers: {
228
+ setValue(state, payload) {
229
+ state.count = payload + 1
230
+ },
231
+
232
+ setValues(state, partialState) {
233
+ Object.keys(partialState).forEach(key => {
234
+ state[key] = partialState[key] + 1
235
+ })
236
+ },
237
+
238
+ reset(state) {
239
+ state.count = 10
240
+ },
241
+ },
242
+ effects: () => ({}),
243
+ },
244
+ })
245
+ const { Provider, useModel } = store
246
+
247
+ const { result } = createHook(Provider, useModel, 'counter')
248
+
249
+ const setValue = result.current.reducers.setValue
250
+ const setValues = result.current.reducers.setValues
251
+ const reset = result.current.reducers.reset
252
+
253
+ act(() => {
254
+ setValue(1)
255
+ })
256
+ expect(result.current.state.count).toBe(2)
257
+
258
+ act(() => {
259
+ setValues({
260
+ count: 10,
261
+ })
262
+ })
263
+ expect(result.current.state.count).toBe(11)
264
+
265
+ act(() => {
266
+ reset()
267
+ })
268
+ expect(result.current.state.count).toBe(10)
269
+ })
270
+ })
@@ -0,0 +1,113 @@
1
+ import { act } from '@testing-library/react-hooks'
2
+ import { createModel } from '../src'
3
+ import { Store } from '../src/core/Store'
4
+ import { createHook } from './helper/createHook'
5
+ import { defaultStoreOptions } from './helper/shared'
6
+
7
+ const store = new Store(
8
+ {
9
+ test: createModel()({
10
+ state: {
11
+ count: 1,
12
+ },
13
+ }),
14
+ },
15
+ defaultStoreOptions
16
+ )
17
+
18
+ describe('Store test', () => {
19
+ it('Store should be defined', () => {
20
+ expect(Store).toBeDefined()
21
+ expect(Store.prototype.constructor).toBe(Store)
22
+ })
23
+
24
+ it('should have valid api', () => {
25
+ const methods = Object.keys(store)
26
+
27
+ expect(methods).toContain('Provider')
28
+ expect(methods).toContain('withProvider')
29
+ expect(methods).toContain('withProviderForwardRef')
30
+ expect(methods).toContain('useModel')
31
+ expect(methods).toContain('withModel')
32
+ expect(methods).toContain('withModels')
33
+ expect(methods).toContain('getState')
34
+ expect(methods).toContain('getReducers')
35
+ })
36
+
37
+ it('state can be primitive value', () => {
38
+ const { Provider, useModel } = new Store(
39
+ {
40
+ counter: {
41
+ state: 1,
42
+ reducers: {
43
+ increase() {
44
+ return 2
45
+ },
46
+ },
47
+ effects: () => ({}),
48
+ },
49
+ },
50
+ defaultStoreOptions
51
+ )
52
+
53
+ const { result } = createHook(Provider, useModel, 'counter')
54
+
55
+ expect(result.current.state).toBe(1)
56
+
57
+ act(() => {
58
+ result.current.reducers.increase()
59
+ })
60
+
61
+ expect(result.current.state).toBe(2)
62
+ })
63
+
64
+ it('state can be array', () => {
65
+ const { Provider, useModel } = new Store(
66
+ {
67
+ counter: {
68
+ state: [1, 2, 3],
69
+ reducers: {
70
+ increase() {
71
+ return 2
72
+ },
73
+ },
74
+ effects: () => ({}),
75
+ },
76
+ },
77
+ defaultStoreOptions
78
+ )
79
+
80
+ const { result } = createHook(Provider, useModel, 'counter')
81
+
82
+ expect(result.current.state).toEqual([1, 2, 3])
83
+ })
84
+
85
+ it('state can be object', () => {
86
+ const { Provider, useModel } = new Store(
87
+ {
88
+ counter: {
89
+ state: {
90
+ count: 1,
91
+ },
92
+ reducers: {
93
+ increase(state) {
94
+ state.count += 1
95
+ },
96
+ },
97
+ effects: () => ({}),
98
+ },
99
+ },
100
+ defaultStoreOptions
101
+ )
102
+
103
+ const { result } = createHook(Provider, useModel, 'counter')
104
+
105
+ expect(result.current.state.count).toBe(1)
106
+
107
+ act(() => {
108
+ result.current.reducers.increase()
109
+ })
110
+
111
+ expect(result.current.state.count).toBe(2)
112
+ })
113
+ })