How to set up Vite React TS project with Vitest
Tags: vite, react, testing, vitest
Published: 2022-08-24 17:03:44

This tutorials will work for self-generated vite react-ts projects. Please also refer to the following two repos if you have different requirements:

- https://github.com/nickmccurdy/vite-react-testing-ts
- https://stackblitz.com/edit/vitest-dev-vitest-iaqfk8?file=src%2FApp.test.tsx&initialPath=__vitest__

I personally ran into quite some TS errors and after some hours of digging I found the following settings worked for me. Hence I'd like to write it down and hope it will benefit anyone who has encountered the same issue.

---

## 1. Install packages. You will need those following:

```
@testing-library/dom
@testing-library/jest-dom
@testing-library/react
@testing-library/user-event
@types/testing-library__jest-dom
@vitest/ui
vitest
```

## 2. Add scripts:

```
"test": "vitest",
"test:ui": "vitest --ui",
"coverage": "vitest run --coverage",
```

## 3. In your `vite.config.ts` add, note the triple slash reference types are important to include here:

```
/// <reference types="vitest" />
/// <reference types="vite/client" />

import {defineConfig} from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],

  ...bla bla bla

  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/setupTests.ts',
    // you might want to disable it, if you don't have tests that rely on CSS
    // since parsing CSS is slow
    css: true,
  },
});
```

## 4. In your `tsconfig.json` include:

```
 "include": ["src", "@testing-library/jest-dom"],
```

## 5. In your root directory, have a file named `setupTests.ts` and include those:
```
/// <reference types="vitest/globals" />
import '@testing-library/jest-dom';
import "@testing-library/jest-dom/extend-expect";
```

## 6. Make a utils folder and include a `test-utils.tsx` file and put those in the code:

```
/* eslint-disable import/export */
import { cleanup, render } from '@testing-library/react'
import { afterEach } from 'vitest'

afterEach(() => {
  cleanup()
})

const customRender = (ui: React.ReactElement, options = {}) =>
  render(ui, {
    // wrap provider(s) here if needed
    wrapper: ({ children }) => children,
    ...options,
  })

export * from '@testing-library/react'
export { default as userEvent } from '@testing-library/user-event'
// override render export
export { customRender as render }
```

## 7. Finally, try writing a test, such as `App.test.tsx`

```
import {describe, expect, it} from 'vitest';
import App from './App';
import { render, screen, userEvent } from './utils/test-utils'


describe('Simple working test', () => {
  it('the title is visible', () => {
    render(<App />);
    expect(screen.getByText(/Ellida Admin/i)).toBeInTheDocument();
  });
``
  it('should increment count on click', async () => {
    render(<App />)
    userEvent.click(screen.getByRole('button'))
    expect(await screen.findByText(/count is: 1/i)).toBeInTheDocument()
  })

  it('uses flexbox in app header', async () => {
    render(<App />)
    const element = screen.getByRole('banner')
    expect(element.className).toEqual('App-header')
    expect(getComputedStyle(element).display).toEqual('flex')
  })
});
```

Then type in command line either `pnpm test` if you just want it to run in the terminal or `pnpm test:ui` if you want to see the nice UI part. `npm` or `yarn` would work similar.