1 | import { configureStore } from './configureStore'
|
2 | import * as redux from 'redux'
|
3 | import * as devtools from './devtoolsExtension'
|
4 | import { StoreEnhancer, StoreEnhancerStoreCreator } from 'redux'
|
5 |
|
6 | describe('configureStore', () => {
|
7 | jest.spyOn(redux, 'applyMiddleware')
|
8 | jest.spyOn(redux, 'combineReducers')
|
9 | jest.spyOn(redux, 'compose')
|
10 | jest.spyOn(redux, 'createStore')
|
11 | jest.spyOn(devtools, 'composeWithDevTools')
|
12 |
|
13 | const reducer: redux.Reducer = (state = {}, _action) => state
|
14 |
|
15 | beforeEach(() => jest.clearAllMocks())
|
16 |
|
17 | describe('given a function reducer', () => {
|
18 | it('calls createStore with the reducer', () => {
|
19 | configureStore({ reducer })
|
20 | expect(configureStore({ reducer })).toBeInstanceOf(Object)
|
21 | expect(redux.applyMiddleware).toHaveBeenCalled()
|
22 | expect(devtools.composeWithDevTools).toHaveBeenCalled()
|
23 | expect(redux.createStore).toHaveBeenCalledWith(
|
24 | reducer,
|
25 | undefined,
|
26 | expect.any(Function)
|
27 | )
|
28 | })
|
29 | })
|
30 |
|
31 | describe('given an object of reducers', () => {
|
32 | it('calls createStore with the combined reducers', () => {
|
33 | const reducer = {
|
34 | reducer() {
|
35 | return true
|
36 | }
|
37 | }
|
38 | expect(configureStore({ reducer })).toBeInstanceOf(Object)
|
39 | expect(redux.combineReducers).toHaveBeenCalledWith(reducer)
|
40 | expect(redux.applyMiddleware).toHaveBeenCalled()
|
41 | expect(devtools.composeWithDevTools).toHaveBeenCalled()
|
42 | expect(redux.createStore).toHaveBeenCalledWith(
|
43 | expect.any(Function),
|
44 | undefined,
|
45 | expect.any(Function)
|
46 | )
|
47 | })
|
48 | })
|
49 |
|
50 | describe('given no reducer', () => {
|
51 | it('throws', () => {
|
52 | expect(configureStore).toThrow(
|
53 | '"reducer" is a required argument, and must be a function or an object of functions that can be passed to combineReducers'
|
54 | )
|
55 | })
|
56 | })
|
57 |
|
58 | describe('given no middleware', () => {
|
59 | it('calls createStore without any middleware', () => {
|
60 | expect(configureStore({ middleware: [], reducer })).toBeInstanceOf(Object)
|
61 | expect(redux.applyMiddleware).toHaveBeenCalledWith()
|
62 | expect(devtools.composeWithDevTools).toHaveBeenCalled()
|
63 | expect(redux.createStore).toHaveBeenCalledWith(
|
64 | reducer,
|
65 | undefined,
|
66 | expect.any(Function)
|
67 | )
|
68 | })
|
69 | })
|
70 |
|
71 | describe('given custom middleware', () => {
|
72 | it('calls createStore with custom middleware and without default middleware', () => {
|
73 | const thank: redux.Middleware = _store => next => action => next(action)
|
74 | expect(configureStore({ middleware: [thank], reducer })).toBeInstanceOf(
|
75 | Object
|
76 | )
|
77 | expect(redux.applyMiddleware).toHaveBeenCalledWith(thank)
|
78 | expect(devtools.composeWithDevTools).toHaveBeenCalled()
|
79 | expect(redux.createStore).toHaveBeenCalledWith(
|
80 | reducer,
|
81 | undefined,
|
82 | expect.any(Function)
|
83 | )
|
84 | })
|
85 | })
|
86 |
|
87 | describe('middleware builder notation', () => {
|
88 | it('calls builder, passes getDefaultMiddleware and uses returned middlewares', () => {
|
89 | const thank = jest.fn((_store => next => action =>
|
90 | 'foobar') as redux.Middleware)
|
91 |
|
92 | const builder = jest.fn(getDefaultMiddleware => {
|
93 | expect(getDefaultMiddleware).toEqual(expect.any(Function))
|
94 | expect(getDefaultMiddleware()).toEqual(expect.any(Array))
|
95 |
|
96 | return [thank]
|
97 | })
|
98 |
|
99 | const store = configureStore({ middleware: builder, reducer })
|
100 |
|
101 | expect(builder).toHaveBeenCalled()
|
102 |
|
103 | expect(store.dispatch({ type: 'test' })).toBe('foobar')
|
104 | })
|
105 | })
|
106 |
|
107 | describe('with devTools disabled', () => {
|
108 | it('calls createStore without devTools enhancer', () => {
|
109 | expect(configureStore({ devTools: false, reducer })).toBeInstanceOf(
|
110 | Object
|
111 | )
|
112 | expect(redux.applyMiddleware).toHaveBeenCalled()
|
113 | expect(redux.compose).toHaveBeenCalled()
|
114 | expect(redux.createStore).toHaveBeenCalledWith(
|
115 | reducer,
|
116 | undefined,
|
117 | expect.any(Function)
|
118 | )
|
119 | })
|
120 | })
|
121 |
|
122 | describe('with devTools options', () => {
|
123 | it('calls createStore with devTools enhancer and option', () => {
|
124 | const options = {
|
125 | name: 'myApp',
|
126 | trace: true
|
127 | }
|
128 | expect(configureStore({ devTools: options, reducer })).toBeInstanceOf(
|
129 | Object
|
130 | )
|
131 | expect(redux.applyMiddleware).toHaveBeenCalled()
|
132 | expect(devtools.composeWithDevTools).toHaveBeenCalledWith(options)
|
133 | expect(redux.createStore).toHaveBeenCalledWith(
|
134 | reducer,
|
135 | undefined,
|
136 | expect.any(Function)
|
137 | )
|
138 | })
|
139 | })
|
140 |
|
141 | describe('given preloadedState', () => {
|
142 | it('calls createStore with preloadedState', () => {
|
143 | expect(configureStore({ reducer })).toBeInstanceOf(Object)
|
144 | expect(redux.applyMiddleware).toHaveBeenCalled()
|
145 | expect(devtools.composeWithDevTools).toHaveBeenCalled()
|
146 | expect(redux.createStore).toHaveBeenCalledWith(
|
147 | reducer,
|
148 | undefined,
|
149 | expect.any(Function)
|
150 | )
|
151 | })
|
152 | })
|
153 |
|
154 | describe('given enhancers', () => {
|
155 | it('calls createStore with enhancers', () => {
|
156 | const enhancer: redux.StoreEnhancer = next => next
|
157 | expect(configureStore({ enhancers: [enhancer], reducer })).toBeInstanceOf(
|
158 | Object
|
159 | )
|
160 | expect(redux.applyMiddleware).toHaveBeenCalled()
|
161 | expect(devtools.composeWithDevTools).toHaveBeenCalled()
|
162 | expect(redux.createStore).toHaveBeenCalledWith(
|
163 | reducer,
|
164 | undefined,
|
165 | expect.any(Function)
|
166 | )
|
167 | })
|
168 |
|
169 | it('accepts a callback for customizing enhancers', () => {
|
170 | let dummyEnhancerCalled = false
|
171 |
|
172 | const dummyEnhancer: StoreEnhancer = (
|
173 | createStore: StoreEnhancerStoreCreator
|
174 | ) => (reducer, ...args: any[]) => {
|
175 | dummyEnhancerCalled = true
|
176 |
|
177 | return createStore(reducer, ...args)
|
178 | }
|
179 |
|
180 | const reducer = () => ({})
|
181 |
|
182 | const store = configureStore({
|
183 | reducer,
|
184 | enhancers: defaultEnhancers => {
|
185 | return [...defaultEnhancers, dummyEnhancer]
|
186 | }
|
187 | })
|
188 |
|
189 | expect(dummyEnhancerCalled).toBe(true)
|
190 | })
|
191 | })
|
192 | })
|