Home
Getting Started
Features
Testing Guide
This project uses **Vitest** with **React Testing Library** for comprehensive unit testing.
This project uses Vitest with React Testing Library for comprehensive unit testing.
Testing Stack
- Vitest - Fast unit testing framework
- React Testing Library - Component testing
- jsdom - DOM implementation for Node.js
- @vitest/coverage-v8 - Code coverage
Running Tests
bun run test # Watch mode
bun run test:run # Run once
bun run test:watch # Watch mode
bun run test:coverage # Coverage reportTest Configuration
Vitest Config (vitest.config.ts)
- Environment: jsdom
- Setup Files: Global mocks and utilities in
src/__tests__/setup.ts - Coverage: v8 provider
- Path Aliases: Same as production (
@/→src/)
Global Setup (src/__tests__/setup.ts)
Automatically mocks:
- Next.js Router - Navigation hooks
- Next.js Image - Renders as
<img> - Framer Motion - Renders as plain elements
- Browser APIs - IntersectionObserver, ResizeObserver, matchMedia
- fetch - Global mock
- localStorage - In-memory mock
Custom Render (src/__tests__/utils.tsx)
Wraps components in ThemeProvider:
import { render } from "@/__tests__/utils";
render(<MyComponent />); // Wrapped in ThemeProviderTest Structure
src/__tests__/
├── setup.ts # Global mocks
├── utils.tsx # Custom render
├── lib/ # Utility tests
├── hooks/ # Hook tests
├── components/ # Component tests
└── app/api/og/ # OG API testsCoverage Goals
- Statements: > 80%
- Branches: > 80%
- Functions: > 80%
- Lines: > 80%
Current coverage: 93% statements, 81% branches, 98% functions, 96% lines.
Common Patterns
Component Test
import { render, screen } from "@/__tests__/utils";
import MyComponent from "@/components/MyComponent";
it("renders", () => {
render(<MyComponent />);
expect(screen.getByText("Hello")).toBeDefined();
});Hook Test
import { renderHook, waitFor } from "@testing-library/react";
import { useMyHook } from "@/hooks/use-my-hook";
it("fetches data", async () => {
vi.mocked(global.fetch).mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({ data: [] }),
} as Response);
const { result } = renderHook(() => useMyHook());
await waitFor(() => expect(result.current.loading).toBe(false));
});
Nicholas Adamou