How to use Jest matchers with Vitest
A while ago I migrated a test suite from Jest to Vitest. Every thing went fine except that I needed to find out how we could continue to use jest-dom with Vitest. Jest-dom is useful when writing tests for DOM elements with testing-library. It provides handy assertions like for example expect(someButton).toBeDisabled()
.
Luckily Vitest is largely compatible with Jest and so Jest matchers can be used as is.
First we need to create a setup file. I use the name vitest-setup.mjs
but it can be anything you like. Just make sure it matches the configuration below.
// vitest-setup.mjs
import { expect } from "vitest";
import * as matchers from "@testing-library/jest-dom/matchers";
expect.extend(matchers);
Next we add the setup file to the configuration.
// vitest.config.mjs
import { defineConfig } from "vitest/dist/config";
export default defineConfig({
test: {
setupFiles: ["./vitest-setup.mjs"],
},
});
In case we are using TypeScript we need to add the additional matchers to Vitest’s types.
// vitest-testing-library-matchers.d.ts
import "vitest";
import type { TestingLibraryMatchers } from "@testing-library/jest-dom/types/matchers";
declare module "vitest" {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface Assertion<T = any> extends TestingLibraryMatchers<T, void> {}
}
Ensure that TypeScript picks up this declaration file.
// tsconfig.json
{
"include": ["*.d.ts", …],
…
}
Now we can write tests that make use of Jest-dom. 🎉
// greeting.spec.tsx
import { describe, expect, it } from "vitest";
import { render, screen } from "@testing-library/react";
import { Greeting } from "./greeting";
describe("<Greeting>", () => {
it("should say Hello", () => {
render(<Greeting name="Vitest" />);
const heading = screen.getByRole("heading");
expect(heading).toHaveTextContent("Hello, Vitest!");
});
});