Skip to content

# Testing

Zenith Dashboard ships with Vitest for unit tests and Playwright for end-to-end tests, ready to extend.

## Overview

The testing setup includes two tools that cover different layers of confidence:

- Vitest— Fast unit and component tests running in a jsdom environment. Tests utility functions, mock data integrity, and component rendering.
- Playwright— Browser-based end-to-end tests that verify pages load, navigation works, and interactive features function correctly.

## Test Scripts

Command | Description
--- | ---
`npm run test` | Run Vitest in watch mode (re-runs on file changes)
`npm run test:run` | Run Vitest once and exit (CI-friendly)
`npm run test:e2e` | Run Playwright end-to-end tests
`npm run test:e2e:ui` | Open Playwright interactive UI mode for debugging

## Unit Tests (Vitest)

Vitest is configured in `vitest.config.ts` at the project root. Key settings:

- Environment: jsdom (simulates browser DOM)
- Globals: enabled (`describe`, `it`, `expect` available without imports)
- Path aliases: resolved via vite-tsconfig-paths (`@/*` works in tests)
- Setup file: `src/test/setup.ts` registers @testing-library/jest-dom matchers
- CSS: disabled for faster test execution

### Included Test Files

File | Tests
--- | ---
src/lib/utils.test.ts | cn() utility — class merging, Tailwind conflict resolution, edge cases
src/lib/data/analytics.test.ts | Mock data integrity — field validation, array lengths, traffic sources sum to 100%
src/components/dashboard/stats-cards.test.tsx | StatsCards component — renders all 4 cards with values and trend indicators

## Writing New Unit Tests

Create a file with a `.test.ts` or `.test.tsx` extension alongside the source file:

    // src/lib/my-utils.test.ts
    import { formatCurrency } from "@/lib/my-utils";
    import type { Metadata } from "next";

    export const metadata: Metadata = {
      title: "Testing",
      description:
        "Run unit tests with Vitest and end-to-end tests with Playwright.",
    };

    describe("formatCurrency", () => {
      it("formats USD amounts", () => {
        expect(formatCurrency(1234.5)).toBe("$1,234.50");
      });
    });

For component tests, mock Recharts to avoid SVG rendering issues in jsdom:

    vi.mock("recharts", () => ({
      ResponsiveContainer: ({ children }) => <div>{children}</div>,
      AreaChart: ({ children }) => <div>{children}</div>,
      Area: () => null,
    }));

## E2E Tests (Playwright)

Playwright is configured in `playwright.config.ts` at the project root. It automatically starts the dev server on port 3737 before running tests.

- Browser: Chromium only (add Firefox/WebKit in the config as needed)
- Test directory: `e2e/`
- Traces: captured on first retry for debugging failures

### Included Smoke Tests

The `e2e/smoke.spec.ts` file includes 4 tests:

- Homepage loads with the Dashboard heading
- Sidebar navigation navigates between pages
- Charts page renders all 5 chart cards
- Theme toggle switches between light and dark modes

## Writing New E2E Tests

Create `.spec.ts` files in the `e2e/` directory:

    import { test, expect } from "@playwright/test";

    test("orders page shows data table", async ({ page }) => {
      await page.goto("/orders");
      await expect(page.getByRole("heading", { name: "Orders" })).toBeVisible();
      await expect(page.getByRole("table")).toBeVisible();
    });

Use `npm run test:e2e:ui` for interactive debugging with time-travel, DOM snapshots, and step-through execution.

## CI Integration

For continuous integration, use the single-run commands:

    npm run test:run     # Unit tests (Vitest)
    npm run test:e2e     # E2E tests (Playwright)

Playwright automatically enables retries and single-worker mode when the `CI` environment variable is set.

## Next Steps

See the Deployment guide when you are ready to ship, or check the Changelog for the full release history.