[How to] Set up a React app with Vite
Let's start a new SPA project using Vite, React, Typescript, Vitest and react-testing-library
Author: Pob Ch |Created: |Updated: |
Part 1: Vite + React + Typescript
- Initialize the project using
pnpm
pnpm create vite
- Follow the prompts, select
react
andtypescript
template - Start a dev server
pnpm run dev
Part 2: Vitest + react-testing-library(i.e. RTL)
- Install
vitest
, RTL and other necessary packages usingpnpm
pnpm add -D vitest @testing-library/react @testing-library/user-event @testing-library/dom jsdom @testing-library/jest-dom @types/testing-library__jest-dom
- Edit
vite.config.ts
file to be like this
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
test: {
// now we can call test(), expect() in test files without needing to `import` them
globals: true,
// required environment to run RTL
environment: 'jsdom',
// a setup file where we will add more settings
setupFiles: './src/setupTest.ts',
// you might want to disable it, if you don't
// have tests that rely on CSS since parsing CSS is slow
css: true,
},
})
- Create
./src/setupTest.ts
file
import { afterEach, expect } from 'vitest'
import { cleanup } from '@testing-library/react'
import matchers from '@testing-library/jest-dom/matchers'
// enable `expect(...).toBeInTheDocument()`, etc.
expect.extend(matchers)
// unmount all components which are rendered by `render(...)`
afterEach(() => {
cleanup()
})
- The following is an example of a test file (
*.test.tsx
)
// `./src/Button.test.tsx`
import { Button } from './Button'
import { myFunction as mockMyFunction } from './myFunction'
import { render, screen } from '@testing-library/react'
import { vi, beforeEach } from 'vitest'
import userEvent from '@testing-library/user-event'
// how to mock a module using vitest
// assume that this module is used inside <Button/> comp
vi.mock('./myFunction', () => {
return { myFunction: vi.fn(() => 'mock text') }
})
// other options are resetAllMocks(), restoreAllMocks()
beforeEach(() => {
vi.clearAllMocks()
})
test('The first test', async () => {
// how to mock a function using vitest
const mockOnClick = vi.fn()
render(<Button num={5} onClick={mockOnClick} />)
expect(screen.getByText(/Something/)).toBeInTheDocument()
await userEvent.click(screen.getByText(/Something/))
// inspect the mocked module
expect(mockMyFunction).toBeCalledTimes(1)
expect(mockMyFunction).toBeCalledWith(5)
// inspect the mocked function
expect(mockOnClick).toBeCalledTimes(1)
expect(mockOnClick).toBeCalledWith('mock text')
})
- Run all tests
pnpm vitest
- Optionally, add a new field in
scripts
(package.json
file) and run the test withpnpm run test
instead.
"scripts": {
// ...
"test": "vitest"
},