1
1
import { vi } from 'vitest'
2
2
import type { StoreEnhancer , StoreEnhancerStoreCreator } from '@reduxjs/toolkit'
3
- import { configureStore } from '@reduxjs/toolkit'
4
- import * as RTK from '@reduxjs/toolkit'
5
- import * as redux from 'redux'
6
- import * as devtools from '@internal/devtoolsExtension'
3
+ import type * as Redux from 'redux'
4
+ import type * as DevTools from '@internal/devtoolsExtension'
5
+
6
+ vi . doMock ( 'redux' , async ( ) => {
7
+ const redux : any = await vi . importActual ( 'redux' )
7
8
8
- describe ( 'configureStore' , ( ) => {
9
9
vi . spyOn ( redux , 'applyMiddleware' )
10
10
vi . spyOn ( redux , 'combineReducers' )
11
11
vi . spyOn ( redux , 'compose' )
12
12
vi . spyOn ( redux , 'createStore' )
13
+
14
+ return redux
15
+ } )
16
+
17
+ vi . doMock ( '@internal/devtoolsExtension' , async ( ) => {
18
+ const devtools : typeof DevTools = await vi . importActual (
19
+ '@internal/devtoolsExtension'
20
+ )
13
21
vi . spyOn ( devtools , 'composeWithDevTools' ) // @remap -prod-remove-line
22
+ return devtools
23
+ } )
24
+
25
+ function originalReduxCompose ( ...funcs : Function [ ] ) {
26
+ if ( funcs . length === 0 ) {
27
+ // infer the argument type so it is usable in inference down the line
28
+ return < T > ( arg : T ) => arg
29
+ }
30
+
31
+ if ( funcs . length === 1 ) {
32
+ return funcs [ 0 ]
33
+ }
34
+
35
+ return funcs . reduce (
36
+ ( a , b ) =>
37
+ ( ...args : any ) =>
38
+ a ( b ( ...args ) )
39
+ )
40
+ }
14
41
15
- const reducer : redux . Reducer = ( state = { } , _action ) => state
42
+ function originalComposeWithDevtools ( ) {
43
+ if ( arguments . length === 0 ) return undefined
44
+ if ( typeof arguments [ 0 ] === 'object' ) return originalReduxCompose
45
+ return originalReduxCompose . apply ( null , arguments as any as Function [ ] )
46
+ }
47
+
48
+ describe ( 'configureStore' , async ( ) => {
49
+ // RTK's internal `composeWithDevtools` function isn't publicly exported,
50
+ // so we can't mock it. However, it _does_ try to access the global extension method
51
+ // attached to `window`. So, if we mock _that_, we'll know if the enhancer ran.
52
+ const mockDevtoolsCompose = vi
53
+ . fn ( )
54
+ . mockImplementation ( originalComposeWithDevtools )
55
+ ; ( window as any ) . __REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = mockDevtoolsCompose
56
+
57
+ const redux = await import ( 'redux' )
58
+
59
+ const { configureStore } = await import ( '@reduxjs/toolkit' )
60
+
61
+ const reducer : Redux . Reducer = ( state = { } , _action ) => state
16
62
17
63
beforeEach ( ( ) => {
18
64
vi . clearAllMocks ( )
@@ -22,13 +68,14 @@ describe('configureStore', () => {
22
68
it ( 'calls createStore with the reducer' , ( ) => {
23
69
configureStore ( { reducer } )
24
70
expect ( configureStore ( { reducer } ) ) . toBeInstanceOf ( Object )
25
- expect ( redux . applyMiddleware ) . toHaveBeenCalled ( )
26
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalled ( ) // @remap -prod-remove-line
71
+
27
72
expect ( redux . createStore ) . toHaveBeenCalledWith (
28
73
reducer ,
29
74
undefined ,
30
75
expect . any ( Function )
31
76
)
77
+ expect ( redux . applyMiddleware ) . toHaveBeenCalled ( )
78
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalled ( ) // @remap -prod-remove-line
32
79
} )
33
80
} )
34
81
@@ -42,7 +89,7 @@ describe('configureStore', () => {
42
89
expect ( configureStore ( { reducer } ) ) . toBeInstanceOf ( Object )
43
90
expect ( redux . combineReducers ) . toHaveBeenCalledWith ( reducer )
44
91
expect ( redux . applyMiddleware ) . toHaveBeenCalled ( )
45
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
92
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
46
93
expect ( redux . createStore ) . toHaveBeenCalledWith (
47
94
expect . any ( Function ) ,
48
95
undefined ,
@@ -63,7 +110,7 @@ describe('configureStore', () => {
63
110
it ( 'calls createStore without any middleware' , ( ) => {
64
111
expect ( configureStore ( { middleware : [ ] , reducer } ) ) . toBeInstanceOf ( Object )
65
112
expect ( redux . applyMiddleware ) . toHaveBeenCalledWith ( )
66
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
113
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
67
114
expect ( redux . createStore ) . toHaveBeenCalledWith (
68
115
reducer ,
69
116
undefined ,
@@ -82,7 +129,7 @@ describe('configureStore', () => {
82
129
expect . any ( Function ) , // immutableCheck
83
130
expect . any ( Function ) // serializableCheck
84
131
)
85
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
132
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
86
133
expect ( redux . createStore ) . toHaveBeenCalledWith (
87
134
reducer ,
88
135
undefined ,
@@ -121,13 +168,13 @@ describe('configureStore', () => {
121
168
122
169
describe ( 'given custom middleware' , ( ) => {
123
170
it ( 'calls createStore with custom middleware and without default middleware' , ( ) => {
124
- const thank : redux . Middleware = ( _store ) => ( next ) => ( action ) =>
171
+ const thank : Redux . Middleware = ( _store ) => ( next ) => ( action ) =>
125
172
next ( action )
126
173
expect ( configureStore ( { middleware : [ thank ] , reducer } ) ) . toBeInstanceOf (
127
174
Object
128
175
)
129
176
expect ( redux . applyMiddleware ) . toHaveBeenCalledWith ( thank )
130
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
177
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalled ( ) // @remap -prod-remove-line-line
131
178
expect ( redux . createStore ) . toHaveBeenCalledWith (
132
179
reducer ,
133
180
undefined ,
@@ -139,7 +186,7 @@ describe('configureStore', () => {
139
186
describe ( 'middleware builder notation' , ( ) => {
140
187
it ( 'calls builder, passes getDefaultMiddleware and uses returned middlewares' , ( ) => {
141
188
const thank = vi . fn (
142
- ( ( _store ) => ( next ) => ( action ) => 'foobar' ) as redux . Middleware
189
+ ( ( _store ) => ( next ) => ( action ) => 'foobar' ) as Redux . Middleware
143
190
)
144
191
145
192
const builder = vi . fn ( ( getDefaultMiddleware ) => {
@@ -182,7 +229,7 @@ describe('configureStore', () => {
182
229
Object
183
230
)
184
231
expect ( redux . applyMiddleware ) . toHaveBeenCalled ( )
185
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalledWith ( options ) // @remap -prod-remove-line
232
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalledWith ( options ) // @remap -prod-remove-line
186
233
expect ( redux . createStore ) . toHaveBeenCalledWith (
187
234
reducer ,
188
235
undefined ,
@@ -195,7 +242,7 @@ describe('configureStore', () => {
195
242
it ( 'calls createStore with preloadedState' , ( ) => {
196
243
expect ( configureStore ( { reducer } ) ) . toBeInstanceOf ( Object )
197
244
expect ( redux . applyMiddleware ) . toHaveBeenCalled ( )
198
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalled ( ) // @remap -prod-remove-line
245
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalled ( ) // @remap -prod-remove-line
199
246
expect ( redux . createStore ) . toHaveBeenCalledWith (
200
247
reducer ,
201
248
undefined ,
@@ -206,12 +253,12 @@ describe('configureStore', () => {
206
253
207
254
describe ( 'given enhancers' , ( ) => {
208
255
it ( 'calls createStore with enhancers' , ( ) => {
209
- const enhancer : redux . StoreEnhancer = ( next ) => next
256
+ const enhancer : Redux . StoreEnhancer = ( next ) => next
210
257
expect ( configureStore ( { enhancers : [ enhancer ] , reducer } ) ) . toBeInstanceOf (
211
258
Object
212
259
)
213
260
expect ( redux . applyMiddleware ) . toHaveBeenCalled ( )
214
- expect ( devtools . composeWithDevTools ) . toHaveBeenCalled ( ) // @remap -prod-remove-line
261
+ expect ( mockDevtoolsCompose ) . toHaveBeenCalled ( ) // @remap -prod-remove-line
215
262
expect ( redux . createStore ) . toHaveBeenCalledWith (
216
263
reducer ,
217
264
undefined ,
0 commit comments