Migrating from Jest to Vitest

Migrating from Jest to Vitest

In this tutorial, we'll guide you through the process of migrating your test suite from Jest to Vitest. We'll cover the key differences, necessary configuration changes, and how to update your tests for compatibility with Vitest.

Why migrate to Vitest?

Jest has been a solid choice of testing framework for many years; it's popular, well-documented, and has plenty of plugins to pick from. However, as the modern Javascript stack continues to evolve, Jest's poor support for modern features such as ESM and Typescript can make for a frustrating experience.

Thankfully, a new player has emerged - Vitest. Vitest is a next-generation testing framework designed to be faster and more developer-friendly than Jest. It's built on top of Vite, which provides lightning-fast HMR (Hot Module Replacement) and native ESM & Typescript support.

Installing Vitest

First, let's install Vitest and remove Jest:

npm uninstall jest @types/jest
npm install -D vitest
# or if you prefer yarn
yarn remove jest @types/jest
yarn add -D vitest

Updating configuration

Replace your jest.config.js with a vitest.config.ts (or vitest.config.js if you're not using TypeScript):

import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    // Jest-like globals
    globals: true,
    // Environment
    environment: 'jsdom',
    // Include below if you want code coverage
    coverage: {
      provider: 'v8', // or 'istanbul'
      reporter: ['text', 'json', 'html'],
    },
  },
})

Updating your tests

Most Jest tests will work in Vitest with minimal changes. Here are some key differences:

  1. Import statements: Replace import { ... } from '@jest/globals' with import { ... } from 'vitest'.

  2. Test file naming: Vitest supports .test.ts, .spec.ts, and .test.js file extensions by default.

  3. Mocking: Use vi instead of jest for mocking functions. For example:

// Before (Jest)
jest.fn()
jest.spyOn()

// After (Vitest)
vi.fn()
vi.spyOn()
  1. Timers: Replace jest.useFakeTimers() with vi.useFakeTimers().

Here's an example of updating a test:

// Before (Jest)
import { describe, it, expect } from '@jest/globals';

// After (Vitest)
import { describe, it, expect } from 'vitest';

describe('My test suite', () => {
  it('should work the same in Vitest', () => {
    expect(true).toBe(true);
  });
});

Puppeteer

Vitest has experimental support for running your tests directly in a browser so you may not need to use Puppeteer any more. Otherwise, if you're using the popular jest-puppeteer preset, you can use our vitest port - vitest-puppeteer.

Updating your package.json

Update your test scripts in package.json:

{
  "scripts": {
    "test": "vitest run",
    "test:watch": "vitest watch",
    "test:coverage": "vitest run --coverage"
  }
}

Running your tests

Now you can run your tests using the updated scripts:

npm run test
# or
yarn test

Any missing dependencies will be installed automatically by vitest.

Troubleshooting common issues

  1. ESM imports: If you're using CommonJS modules, you might need to update your imports to use ESM syntax.

  2. TypeScript configuration: Ensure your tsconfig.json is compatible with Vitest. You might need to add "types": ["vitest/globals"] to your compilerOptions.

  3. Environment-specific code: If your tests rely on Node.js-specific APIs, you might need to adjust your Vitest configuration or mock these APIs.

Conclusion

Migrating from Jest to Vitest can significantly improve your testing experience and performance. While there might be some initial work involved in the migration, the benefits in terms of speed and developer experience are often worth it.

Remember to check the official Vitest documentation for more detailed information and advanced configuration options.