Skip to content

Commit f650971

Browse files
committed
make testing section vitest-first
1 parent 9adc267 commit f650971

File tree

3 files changed

+922
-1572
lines changed

3 files changed

+922
-1572
lines changed

docs/usage/WritingTests.mdx

Lines changed: 9 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,20 @@ For background on why we recommend integration-style tests, see:
4040

4141
### Test Runners
4242

43-
**Redux can be tested with any test runner**, since it's just plain JavaScript. One common option is [Jest](https://jestjs.io/), a widely used test runner that comes with Create-React-App, and is used by the Redux library repos. If you're using [Vite](https://vitejs.dev/) to build your project, you may be using [Vitest](https://vitest.dev/) as your test runner.
43+
**Redux can be tested with any test runner**, since it's just plain JavaScript. An increasingly common choice is [Vitest](https://vitest.dev/) (used by the Redux library repos), though [Jest](https://jestjs.io/) is still used widely.
4444

45-
Typically, your test runner needs to be configured to compile JavaScript/TypeScript syntax. If you're going to be testing UI components, you will likely need to configure the test runner to use [JSDOM](https://github.com/jsdom/jsdom) to provide a mock DOM environment.
45+
Typically, your test runner needs to be configured to compile JavaScript/TypeScript syntax. If you're going to be testing UI components **without a browser**, you will likely need to configure the test runner to use [JSDOM](https://github.com/jsdom/jsdom) to provide a mock DOM environment.
4646

47-
The examples in this page will assume you're using Jest, but the same patterns apply no matter what test runner you're using.
47+
The examples in this page will assume you're using Vitest, but the same patterns apply no matter what test runner you're using.
4848

4949
See these resources for typical test runner configuration instructions:
5050

51-
- **Jest**:
52-
- [Jest: Getting Started](https://jestjs.io/docs/getting-started)
53-
- [Jest: Configuration - Test Environment](https://jestjs.io/docs/configuration#testenvironment-string)
5451
- **Vitest**
5552
- [Vitest: Getting Started](https://vitest.dev/guide/)
5653
- [Vitest: Configuration - Test Environment](https://vitest.dev/config/#environment)
54+
- **Jest**:
55+
- [Jest: Getting Started](https://jestjs.io/docs/getting-started)
56+
- [Jest: Configuration - Test Environment](https://jestjs.io/docs/configuration#testenvironment-string)
5757

5858
### UI and Network Testing Tools
5959

@@ -339,8 +339,6 @@ import { Provider } from 'react-redux'
339339

340340
import type { AppStore, RootState } from '../app/store'
341341
import { setupStore } from '../app/store'
342-
// As a basic setup, import your same slice reducers
343-
import userReducer from '../features/users/userSlice'
344342

345343
// This type interface extends the default options for render from RTL, as well
346344
// as allows the user to specify other things such as initialState, store.
@@ -372,113 +370,12 @@ export function renderWithProviders(
372370
}
373371
```
374372

375-
In this example, we're directly importing the same slice reducers that the real app uses to create the store. It may be helpful to create a reusable `setupStore` function that does the actual store creation with the right options and configuration, and use that in the custom render function instead.
376-
377-
```ts title="app/store.ts"
378-
// file: features/users/userSlice.ts noEmit
379-
import { createSlice } from '@reduxjs/toolkit'
380-
const userSlice = createSlice({
381-
name: 'user',
382-
initialState: {
383-
name: 'No user',
384-
status: 'idle'
385-
},
386-
reducers: {}
387-
})
388-
export default userSlice.reducer
389-
// file: app/store.ts
390-
import { combineReducers, configureStore } from '@reduxjs/toolkit'
391-
392-
import userReducer from '../features/users/userSlice'
393-
394-
// Create the root reducer separately so we can extract the RootState type
395-
const rootReducer = combineReducers({
396-
user: userReducer
397-
})
398-
399-
export const setupStore = (preloadedState?: Partial<RootState>) => {
400-
return configureStore({
401-
reducer: rootReducer,
402-
preloadedState
403-
})
404-
}
405-
406-
export type RootState = ReturnType<typeof rootReducer>
407-
export type AppStore = ReturnType<typeof setupStore>
408-
export type AppDispatch = AppStore['dispatch']
409-
```
410-
411-
Then, use `setupStore` in the test utils file instead of calling `configureStore` again:
412-
413-
```tsx
414-
// file: features/users/userSlice.ts noEmit
415-
import { createSlice } from '@reduxjs/toolkit'
416-
const userSlice = createSlice({
417-
name: 'user',
418-
initialState: {
419-
name: 'No user',
420-
status: 'idle'
421-
},
422-
reducers: {}
423-
})
424-
export default userSlice.reducer
425-
// file: app/store.ts noEmit
426-
import { combineReducers, configureStore } from '@reduxjs/toolkit'
427-
428-
import userReducer from '../features/users/userSlice'
429-
430-
const rootReducer = combineReducers({
431-
user: userReducer
432-
})
433-
434-
export const setupStore = (preloadedState?: Partial<RootState>) => {
435-
return configureStore({
436-
reducer: rootReducer,
437-
preloadedState
438-
})
439-
}
440-
441-
export type RootState = ReturnType<typeof rootReducer>
442-
export type AppStore = ReturnType<typeof setupStore>
443-
export type AppDispatch = AppStore['dispatch']
444-
// file: utils/test-utils.tsx
445-
import React, { PropsWithChildren } from 'react'
446-
import { render } from '@testing-library/react'
447-
import type { RenderOptions } from '@testing-library/react'
448-
import { Provider } from 'react-redux'
449-
450-
import { setupStore } from '../app/store'
451-
import type { AppStore, RootState } from '../app/store'
452-
453-
// This type interface extends the default options for render from RTL, as well
454-
// as allows the user to specify other things such as initialState, store.
455-
interface ExtendedRenderOptions extends Omit<RenderOptions, 'queries'> {
456-
preloadedState?: Partial<RootState>
457-
store?: AppStore
458-
}
459-
460-
export function renderWithProviders(
461-
ui: React.ReactElement,
462-
{
463-
preloadedState = {},
464-
// Automatically create a store instance if no store was passed in
465-
store = setupStore(preloadedState),
466-
...renderOptions
467-
}: ExtendedRenderOptions = {}
468-
) {
469-
function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element {
470-
return <Provider store={store}>{children}</Provider>
471-
}
472-
return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) }
473-
}
474-
```
475-
476373
### Writing Integration Tests With Components
477374

478375
The actual test files should use the custom `render` function to actually render our Redux-connected components. If the code that we're testing involves making network requests, we should also configure MSW to mock the expected requests with appropriate test data.
479376

480377
```tsx title="features/users/tests/UserDisplay.test.tsx"
481-
// file: jest-setup.ts noEmit
378+
// file: setup.ts noEmit
482379
import '@testing-library/jest-dom'
483380

484381
// file: features/users/userSlice.ts noEmit
@@ -571,6 +468,7 @@ export default function UserDisplay() {
571468
}
572469
// file: features/users/tests/UserDisplay.test.tsx
573470
import React from 'react'
471+
import { beforeAll, afterEach, afterAll, test, expect } from 'vitest'
574472
import { http, HttpResponse, delay } from 'msw'
575473
import { setupServer } from 'msw/node'
576474
import { fireEvent, screen } from '@testing-library/react'
@@ -727,7 +625,7 @@ export const { todoAdded } = todosSlice.actions
727625
export default todosSlice.reducer
728626

729627
// file: todosSlice.test.ts
730-
628+
import { test, expect } from 'vitest'
731629
import reducer, { todoAdded, Todo } from './todosSlice'
732630

733631
test('should return the initial state', () => {

website/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@
2323
"@testing-library/jest-dom": "^6.2.0",
2424
"@testing-library/react": "^14.1.2",
2525
"@testing-library/user-event": "^14.5.2",
26-
"@types/jest": "^29.5.11",
2726
"@types/node": "^20.11.0",
2827
"@types/react": "^18.2.47",
29-
"jest": "^29.7.0",
3028
"msw": "^2.0.0",
3129
"netlify-plugin-cache": "^1.0.3",
32-
"react-redux": "^9.1.0"
30+
"react-redux": "^9.1.0",
31+
"vitest": "^2.0.5"
3332
},
3433
"browserslist": {
3534
"production": [

0 commit comments

Comments
 (0)