Wiring up #vitest and #rr7 for tests is not obvious.

  • Requires a separate vitest.config.ts
  • Requires createRoutesStub

discord

vitest.config.ts: #

We need a separate vite.config that omits @react-router/dev/vite, and then configures the typical test features.

import react from "@vitejs/plugin-react"
import autoprefixer from "autoprefixer"
import tailwindcss from "tailwindcss"
import { defineConfig, loadEnv } from "vite"
import tsconfigPaths from "vite-tsconfig-paths"

// -----------------------------------------------------------------------------

export default defineConfig({
  css: {
    postcss: {
      plugins: [tailwindcss, autoprefixer],
    },
  },

  // using `@vitejs/plugin-react` instead of `@react-router/dev/vite`
  plugins: [react(), tsconfigPaths()],

  test: {
    env: loadEnv("test", process.cwd(), ""),
    environment: "happy-dom",
    // @NOTE: https://testing-library.com/docs/react-testing-library/setup#auto-cleanup-in-vitest
    setupFiles: ["./vite.cleanup.ts"],
  },
})

A test: #

Now, we need to use createRoutesStub anywhere a component renders anything to do with #reactrouter. Alternatively, we could build a "wrapper" utility, similar to mocking a redux provider, but in practice we'll be passing createRoutesStub to a wrapper utility anyways.

import userEvent from "@testing-library/user-event"
import { Link } from "react-router"
import { createRoutesStub } from "react-router"
import { render, screen, waitFor } from "@testing-library/react"
import { test } from "vitest"

// -----------------------------------------------------------------------------

const Welcome: React.FC = () => {
  return <Link to="/login">Log In</Link>
}

const Success: React.FC = () => {
  return <>you did it!</>
}

test("Welcome screen navigates to /login", async () => {
  const Stub = createRoutesStub([
    { Component: Welcome, path: "/" },
    { Component: Success, path: "/login" },
  ])

  render(<Stub />)

  await userEvent.click(screen.getByText("Log In"))
  await waitFor(() => screen.findByText("you did it!"))
})