@@ -20,28 +20,36 @@ afterEach(() => {
20
20
restore ( )
21
21
} )
22
22
23
+ const baseUrl = 'http://example.com'
24
+
23
25
function createApis ( ) {
24
26
const api1 = createApi ( {
25
- reducerPath : 'api1' ,
26
- baseQuery : fetchBaseQuery ( { } ) ,
27
+ baseQuery : fetchBaseQuery ( { baseUrl } ) ,
28
+ endpoints : ( builder ) => ( {
29
+ q1 : builder . query ( { query : ( ) => '/success' } ) ,
30
+ } ) ,
31
+ } )
32
+
33
+ const api1_2 = createApi ( {
34
+ baseQuery : fetchBaseQuery ( { baseUrl} ) ,
27
35
endpoints : ( builder ) => ( {
28
36
q1 : builder . query ( { query : ( ) => '/success' } ) ,
29
37
} ) ,
30
38
} )
31
39
32
40
const api2 = createApi ( {
33
41
reducerPath : 'api2' ,
34
- baseQuery : fetchBaseQuery ( { } ) ,
42
+ baseQuery : fetchBaseQuery ( { baseUrl } ) ,
35
43
endpoints : ( builder ) => ( {
36
44
q1 : builder . query ( { query : ( ) => '/success' } ) ,
37
45
} ) ,
38
46
} )
39
- return [ api1 , api2 ] as const
47
+ return [ api1 , api1_2 , api2 ] as const
40
48
}
41
49
42
- let [ api1 , api2 ] = createApis ( )
50
+ let [ api1 , api1_2 , api2 ] = createApis ( )
43
51
beforeEach ( ( ) => {
44
- ; [ api1 , api2 ] = createApis ( )
52
+ ; [ api1 , api1_2 , api2 ] = createApis ( )
45
53
} )
46
54
47
55
describe ( 'missing middleware' , ( ) => {
@@ -50,42 +58,49 @@ describe('missing middleware', () => {
50
58
[ 'production' , false ] ,
51
59
] ) ( '%s warns if middleware is missing: %s' , ( [ env , shouldWarn ] ) => {
52
60
; ( process . env as any ) . NODE_ENV = env
53
- const store = configureStore ( { reducer : { api1 : api1 . reducer } } )
61
+ const store = configureStore ( {
62
+ reducer : { [ api1 . reducerPath ] : api1 . reducer } ,
63
+ } )
54
64
store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
55
65
expect ( getLog ( ) . log ) . toBe (
56
66
shouldWarn
57
- ? `Warning: Middleware for RTK-Query API at reducerPath "api1 " has not been added to the store.
67
+ ? `Warning: Middleware for RTK-Query API at reducerPath "api " has not been added to the store.
58
68
Features like automatic cache collection, automatic refetching etc. will not be available.`
59
69
: ''
60
70
)
61
71
} )
62
72
63
73
test ( 'does not warn if middleware is not missing' , ( ) => {
64
74
const store = configureStore ( {
65
- reducer : { api1 : api1 . reducer } ,
75
+ reducer : { [ api1 . reducerPath ] : api1 . reducer } ,
66
76
middleware : ( gdm ) => gdm ( ) . concat ( api1 . middleware ) ,
67
77
} )
68
78
store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
69
79
expect ( getLog ( ) . log ) . toBe ( `` )
70
80
} )
71
81
72
82
test ( 'warns only once per api' , ( ) => {
73
- const store = configureStore ( { reducer : { api1 : api1 . reducer } } )
83
+ const store = configureStore ( {
84
+ reducer : { [ api1 . reducerPath ] : api1 . reducer } ,
85
+ } )
74
86
store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
75
87
store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
76
88
expect ( getLog ( ) . log )
77
- . toBe ( `Warning: Middleware for RTK-Query API at reducerPath "api1 " has not been added to the store.
89
+ . toBe ( `Warning: Middleware for RTK-Query API at reducerPath "api " has not been added to the store.
78
90
Features like automatic cache collection, automatic refetching etc. will not be available.` )
79
91
} )
80
92
81
93
test ( 'warns multiple times for multiple apis' , ( ) => {
82
94
const store = configureStore ( {
83
- reducer : { api1 : api1 . reducer , api2 : api2 . reducer } ,
95
+ reducer : {
96
+ [ api1 . reducerPath ] : api1 . reducer ,
97
+ [ api2 . reducerPath ] : api2 . reducer ,
98
+ } ,
84
99
} )
85
100
store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
86
101
store . dispatch ( api2 . endpoints . q1 . initiate ( undefined ) )
87
102
expect ( getLog ( ) . log )
88
- . toBe ( `Warning: Middleware for RTK-Query API at reducerPath "api1 " has not been added to the store.
103
+ . toBe ( `Warning: Middleware for RTK-Query API at reducerPath "api " has not been added to the store.
89
104
Features like automatic cache collection, automatic refetching etc. will not be available.
90
105
Warning: Middleware for RTK-Query API at reducerPath "api2" has not been added to the store.
91
106
Features like automatic cache collection, automatic refetching etc. will not be available.` )
@@ -117,15 +132,15 @@ describe('missing reducer', () => {
117
132
api1 . endpoints . q1 . select ( undefined ) ( store . getState ( ) )
118
133
expect ( getLog ( ) . log ) . toBe (
119
134
shouldWarn
120
- ? 'Error: No data found at `state.api1 `. Did you forget to add the reducer to the store?'
135
+ ? 'Error: No data found at `state.api `. Did you forget to add the reducer to the store?'
121
136
: ''
122
137
)
123
138
} )
124
139
} )
125
140
126
141
test ( 'does not warn if reducer is not missing' , ( ) => {
127
142
const store = configureStore ( {
128
- reducer : { api1 : api1 . reducer } ,
143
+ reducer : { [ api1 . reducerPath ] : api1 . reducer } ,
129
144
middleware : ( gdm ) => gdm ( ) . concat ( api1 . middleware ) ,
130
145
} )
131
146
api1 . endpoints . q1 . select ( undefined ) ( store . getState ( ) )
@@ -143,7 +158,7 @@ describe('missing reducer', () => {
143
158
// @ts -expect-error
144
159
api1 . endpoints . q1 . select ( undefined ) ( store . getState ( ) )
145
160
expect ( getLog ( ) . log ) . toBe (
146
- 'Error: No data found at `state.api1 `. Did you forget to add the reducer to the store?'
161
+ 'Error: No data found at `state.api `. Did you forget to add the reducer to the store?'
147
162
)
148
163
} )
149
164
@@ -158,7 +173,7 @@ describe('missing reducer', () => {
158
173
// @ts -expect-error
159
174
api2 . endpoints . q1 . select ( undefined ) ( store . getState ( ) )
160
175
expect ( getLog ( ) . log ) . toBe (
161
- 'Error: No data found at `state.api1 `. Did you forget to add the reducer to the store?\nError: No data found at `state.api2`. Did you forget to add the reducer to the store?'
176
+ 'Error: No data found at `state.api `. Did you forget to add the reducer to the store?\nError: No data found at `state.api2`. Did you forget to add the reducer to the store?'
162
177
)
163
178
} )
164
179
} )
@@ -171,10 +186,91 @@ test('warns only for reducer if everything is missing', async () => {
171
186
api1 . endpoints . q1 . select ( undefined ) ( store . getState ( ) )
172
187
await store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
173
188
expect ( getLog ( ) . log ) . toBe (
174
- 'Error: No data found at `state.api1 `. Did you forget to add the reducer to the store?'
189
+ 'Error: No data found at `state.api `. Did you forget to add the reducer to the store?'
175
190
)
176
191
} )
177
192
193
+ describe ( 'warns on multiple apis using the same `reducerPath`' , ( ) => {
194
+ test ( 'common: two apis, same order' , async ( ) => {
195
+ const store = configureStore ( {
196
+ reducer : {
197
+ [ api1 . reducerPath ] : api1 . reducer ,
198
+ [ api1_2 . reducerPath ] : api1_2 . reducer ,
199
+ } ,
200
+ middleware : ( gDM ) => gDM ( ) . concat ( api1 . middleware , api1_2 . middleware ) ,
201
+ } )
202
+ await store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
203
+ // only second api prints
204
+ expect ( getLog ( ) . log ) . toBe (
205
+ `There is a mismatch between slice and middleware for the reducerPath "api".
206
+ You can only have one api per reducer path, this will lead to crashes in various situations!
207
+ If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`
208
+ )
209
+ } )
210
+
211
+ test ( 'common: two apis, opposing order' , async ( ) => {
212
+ const store = configureStore ( {
213
+ reducer : {
214
+ [ api1 . reducerPath ] : api1 . reducer ,
215
+ [ api1_2 . reducerPath ] : api1_2 . reducer ,
216
+ } ,
217
+ middleware : ( gDM ) => gDM ( ) . concat ( api1_2 . middleware , api1 . middleware ) ,
218
+ } )
219
+ await store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
220
+ // both apis print
221
+ expect ( getLog ( ) . log ) . toBe (
222
+ `There is a mismatch between slice and middleware for the reducerPath "api".
223
+ You can only have one api per reducer path, this will lead to crashes in various situations!
224
+ If you have multiple apis, you *have* to specify the reducerPath option when using createApi!
225
+ There is a mismatch between slice and middleware for the reducerPath "api".
226
+ You can only have one api per reducer path, this will lead to crashes in various situations!
227
+ If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`
228
+ )
229
+ } )
230
+
231
+ test ( 'common: two apis, only first middleware' , async ( ) => {
232
+ const store = configureStore ( {
233
+ reducer : {
234
+ [ api1 . reducerPath ] : api1 . reducer ,
235
+ [ api1_2 . reducerPath ] : api1_2 . reducer ,
236
+ } ,
237
+ middleware : ( gDM ) => gDM ( ) . concat ( api1 . middleware ) ,
238
+ } )
239
+ await store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
240
+
241
+ expect ( getLog ( ) . log ) . toBe (
242
+ `There is a mismatch between slice and middleware for the reducerPath "api".
243
+ You can only have one api per reducer path, this will lead to crashes in various situations!
244
+ If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`
245
+ )
246
+ } )
247
+
248
+ /**
249
+ * This is the one edge case that we currently cannot detect:
250
+ * Multiple apis with the same reducer key and only the middleware of the last api is being used.
251
+ *
252
+ * It would be great to support this case as well, but for now:
253
+ * "It is what it is."
254
+ */
255
+ test . skip ( 'common: two apis, only second middleware' , async ( ) => {
256
+ const store = configureStore ( {
257
+ reducer : {
258
+ [ api1 . reducerPath ] : api1 . reducer ,
259
+ [ api1_2 . reducerPath ] : api1_2 . reducer ,
260
+ } ,
261
+ middleware : ( gDM ) => gDM ( ) . concat ( api1_2 . middleware ) ,
262
+ } )
263
+ await store . dispatch ( api1 . endpoints . q1 . initiate ( undefined ) )
264
+
265
+ expect ( getLog ( ) . log ) . toBe (
266
+ `There is a mismatch between slice and middleware for the reducerPath "api".
267
+ You can only have one api per reducer path, this will lead to crashes in various situations!
268
+ If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`
269
+ )
270
+ } )
271
+ } )
272
+
273
+
178
274
describe ( '`console.error` on unhandled errors during `initiate`' , ( ) => {
179
275
test ( 'error thrown in `baseQuery`' , async ( ) => {
180
276
const api = createApi ( {
@@ -248,7 +344,7 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".
248
344
test ( '`fetchBaseQuery`: error thrown in `prepareHeaders`' , async ( ) => {
249
345
const api = createApi ( {
250
346
baseQuery : fetchBaseQuery ( {
251
- baseUrl : 'http://example.com' ,
347
+ baseUrl,
252
348
prepareHeaders ( ) {
253
349
throw new Error ( 'this was kinda expected' )
254
350
} ,
@@ -275,7 +371,7 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".
275
371
test ( '`fetchBaseQuery`: error thrown in `validateStatus`' , async ( ) => {
276
372
const api = createApi ( {
277
373
baseQuery : fetchBaseQuery ( {
278
- baseUrl : 'http://example.com' ,
374
+ baseUrl
279
375
} ) ,
280
376
endpoints : ( build ) => ( {
281
377
val : build . query < any , void > ( {
0 commit comments