Skip to content

Commit 62268b6

Browse files
committed
extract PreloadedState properly
1 parent 435b43a commit 62268b6

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

docs/usage/WritingTests.mdx

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ See these resources for typical test runner configuration instructions:
5757

5858
### UI and Network Testing Tools
5959

60-
**The Redux team recommends using [React Testing Library (RTL)](https://testing-library.com/docs/react-testing-library/intro) to test React components that connect to Redux**. React Testing Library is a simple and complete React DOM testing utility that encourages good testing practices. It uses ReactDOM's `render` function and `act` from react-dom/tests-utils. (The Testing Library family of tools also includes [adapters for many other popular frameworks as well](https://testing-library.com/docs/dom-testing-library/intro).)
60+
**The Redux team recommends using [React Testing Library (RTL)](https://testing-library.com/docs/react-testing-library/intro) to test React components that connect to Redux without a browser**. React Testing Library is a simple and complete React DOM testing utility that encourages good testing practices. It uses ReactDOM's `render` function and `act` from react-dom/tests-utils. (The Testing Library family of tools also includes [adapters for many other popular frameworks as well](https://testing-library.com/docs/dom-testing-library/intro).)
6161

6262
We also **recommend using [Mock Service Worker (MSW)](https://mswjs.io/) to mock network requests**, as this means your application logic does not need to be changed or mocked when writing tests.
6363

@@ -146,16 +146,17 @@ export default userSlice.reducer
146146
// file: app/store.ts
147147
import { combineReducers, configureStore } from '@reduxjs/toolkit'
148148
import userReducer from '../features/users/userSlice'
149-
// Create the root reducer independently to obtain the RootState type
149+
// Create the root reducer independently to obtain the RootState and PreloadedState type
150150
const rootReducer = combineReducers({
151151
user: userReducer
152152
})
153-
export function setupStore(preloadedState?: Partial<RootState>) {
153+
export function setupStore(preloadedState?: PreloadedState) {
154154
return configureStore({
155155
reducer: rootReducer,
156156
preloadedState
157157
})
158158
}
159+
export type PreloadedState = Parameters<typeof rootReducer>[0]
159160
export type RootState = ReturnType<typeof rootReducer>
160161
export type AppStore = ReturnType<typeof setupStore>
161162
export type AppDispatch = AppStore['dispatch']
@@ -179,12 +180,13 @@ import userReducer from '../features/users/userSlice'
179180
const rootReducer = combineReducers({
180181
user: userReducer
181182
})
182-
export function setupStore(preloadedState?: Partial<RootState>) {
183+
export function setupStore(preloadedState?: PreloadedState) {
183184
return configureStore({
184185
reducer: rootReducer,
185186
preloadedState
186187
})
187188
}
189+
export type PreloadedState = Parameters<typeof rootReducer>[0]
188190
export type RootState = ReturnType<typeof rootReducer>
189191
export type AppStore = ReturnType<typeof setupStore>
190192
export type AppDispatch = AppStore['dispatch']
@@ -210,12 +212,13 @@ import userReducer from '../features/users/userSlice'
210212
const rootReducer = combineReducers({
211213
user: userReducer
212214
})
213-
export function setupStore(preloadedState?: Partial<RootState>) {
215+
export function setupStore(preloadedState?: PreloadedState) {
214216
return configureStore({
215217
reducer: rootReducer,
216218
preloadedState
217219
})
218220
}
221+
export type PreloadedState = Parameters<typeof rootReducer>[0]
219222
export type RootState = ReturnType<typeof rootReducer>
220223
export type AppStore = ReturnType<typeof setupStore>
221224
export type AppDispatch = AppStore['dispatch']
@@ -324,29 +327,29 @@ import userReducer from '../features/users/userSlice'
324327
const rootReducer = combineReducers({
325328
user: userReducer
326329
})
327-
export function setupStore(preloadedState?: Partial<RootState>) {
330+
export function setupStore(preloadedState?: PreloadedState) {
328331
return configureStore({
329332
reducer: rootReducer,
330333
preloadedState
331334
})
332335
}
336+
export type PreloadedState = Parameters<typeof rootReducer>[0]
333337
export type RootState = ReturnType<typeof rootReducer>
334338
export type AppStore = ReturnType<typeof setupStore>
335339
// file: utils/test-utils.tsx
336340
import React, { PropsWithChildren } from 'react'
337341
import { render } from '@testing-library/react'
338342
import type { RenderOptions } from '@testing-library/react'
339343
import { userEvent } from '@testing-library/user-event'
340-
import { configureStore } from '@reduxjs/toolkit'
341344
import { Provider } from 'react-redux'
342345

343-
import type { AppStore, RootState } from '../app/store'
346+
import type { AppStore, RootState, PreloadedState } from '../app/store'
344347
import { setupStore } from '../app/store'
345348

346349
// This type interface extends the default options for render from RTL, as well
347350
// as allows the user to specify other things such as initialState, store.
348351
interface ExtendedRenderOptions extends Omit<RenderOptions, 'queries'> {
349-
preloadedState?: Partial<RootState>
352+
preloadedState?: PreloadedState
350353
store?: AppStore
351354
}
352355

@@ -406,13 +409,14 @@ const rootReducer = combineReducers({
406409
user: userReducer
407410
})
408411

409-
export const setupStore = (preloadedState?: Partial<RootState>) => {
412+
export const setupStore = (preloadedState?: PreloadedState) => {
410413
return configureStore({
411414
reducer: rootReducer,
412415
preloadedState
413416
})
414417
}
415418

419+
export type PreloadedState = Parameters<typeof rootReducer>[0]
416420
export type RootState = ReturnType<typeof rootReducer>
417421
export type AppStore = ReturnType<typeof setupStore>
418422
export type AppDispatch = AppStore['dispatch']
@@ -424,10 +428,10 @@ import { userEvent } from '@testing-library/user-event'
424428
import { Provider } from 'react-redux'
425429

426430
import { setupStore } from '../app/store'
427-
import type { AppStore, RootState } from '../app/store'
431+
import type { AppStore, RootState, PreloadedState } from '../app/store'
428432

429433
interface ExtendedRenderOptions extends Omit<RenderOptions, 'queries'> {
430-
preloadedState?: Partial<RootState>
434+
preloadedState?: PreloadedState
431435
store?: AppStore
432436
}
433437

@@ -566,7 +570,7 @@ While we recommend using integration tests by default, since they exercise all t
566570

567571
Reducers are pure functions that return the new state after applying the action to the previous state. In the majority of cases, the reducer is an implementation detail that does not need explicit tests. However, if your reducer contains particularly complex logic that you would like the confidence of having unit tests for, reducers can be easily tested.
568572

569-
Because reducers are pure functions, so testing them should be straightforward. Call the reducer with a specific input `state` and `action`, and assert that the result state matches expectations.
573+
Because reducers are pure functions, testing them should be straightforward. Call the reducer with a specific input `state` and `action`, and assert that the result state matches expectations.
570574

571575
#### Example
572576

0 commit comments

Comments
 (0)