This document describes the testing setup for the Patch monorepo. For contribution workflow and pre-commit checks, see CONTRIBUTING.md.
There are two kinds of tests:
- Unit tests – Vitest, multi-project config at the repo root. Fast, no browser, mock dependencies. Backend, extension, and shared packages each have their own project.
- E2E tests – Separate
e2e/package. Puppeteer + Vitest, real headless Chrome with the built extension and a mock backend. Slower, full integration.
Unit tests use Vitest with a multi-project configuration. The root vitest.config.ts defines three projects:
- backend – Express API, middleware, and services
- extension – Chrome extension UI and logic
- shared – Schemas, types, and utilities
From the project root, pnpm test runs all three unit-test projects; individual projects can be run with pnpm test:backend, pnpm test:extension, or pnpm test:shared.
| Command | Description |
|---|---|
pnpm test |
Run all unit tests once |
pnpm test:backend |
Run backend unit tests only |
pnpm test:extension |
Run extension unit tests only |
pnpm test:shared |
Run shared unit tests only |
pnpm test:watch |
Run unit tests in watch mode (interactive) |
pnpm test:coverage |
Run all unit tests with coverage report |
E2E tests live in the e2e package (e2e/) and use Puppeteer with Vitest to run the built Chrome extension in a real (headless) browser against a mock backend. They are run only via pnpm test:e2e (or pnpm test from inside e2e/).
- Extension must be built before running E2E tests: run
pnpm build:extensionfrom the repo root (or build the extension package). The tests side-loadextension/dist. - Chrome is required; Puppeteer uses the system Chrome or its bundled Chromium.
| Command | Description |
|---|---|
pnpm test:e2e |
Run E2E tests (from repo root) |
From the project root:
pnpm test:e2eFrom the e2e directory:
cd e2e && pnpm testUse pnpm test:watch in e2e/ for watch mode.
-
Global setup (
e2e/globalSetup.ts) runs once before all tests:- Starts a lightweight mock backend HTTP server (deterministic responses, no LLM).
- Launches a headless Chrome instance with the built extension loaded via
--load-extension. - Exposes the browser’s WebSocket endpoint via
process.env.PUPPETEER_WS_ENDPOINTso test files can connect.
-
Each test file uses
connectBrowser()frome2e/helpersto attach to that shared browser viapuppeteer.connect(), then opens pages (includingfile://demo pages underdemo/), interacts with the overlay/popup, and asserts on the DOM or network. -
Teardown closes the browser and mock server after all tests finish.
Tests run serially (maxWorkers: 1) and use 30s test/hook timeouts to allow for browser and extension startup.
The following applies to unit tests (backend, extension, shared) only. E2E tests live in e2e/ and follow the E2E layout and conventions described above.
- Unit test files must match
**/*.{test,spec}.{ts,tsx}under each project’stests/directory. - Use Vitest globals (
describe,it,expect,vi) without importing them whenglobals: trueis set. - Use
vi.mock()to mock modules; for example, the backend service tests mock the LLM client and generated prompt.
In backend and shared, the @/* alias is defined only in tsconfig.test.json and Vitest’s resolve config. Do not use @/* in src/—tsc does not rewrite path aliases, so compiled output would fail at runtime. Use @/* only in test files.
| Path | Purpose |
|---|---|
e2e/tests/*.test.ts |
Test files (e.g. overlay, popup, domain toggle) |
e2e/helpers/ |
Shared utilities: connectBrowser, openDemoPageWithOverlay, getExtensionId, shadow-DOM helpers, mock backend |
e2e/globalSetup.ts |
Vitest global setup/teardown (mock server + Chrome) |
demo/ (repo root) |
Demo HTML pages used as file:// targets in tests |
- Use Vitest’s
describe/it/beforeAll/afterAll.- In
beforeAll, callconnectBrowser()and store theBrowser - In
afterAll, callbrowser.disconnect()
- In
- Use helpers from
../helpers(ore2e/helpers) to open demo pages, click inside shadow roots, and wait for the overlay. The mock backend is already running; point the extension at it via the configured mock port (seee2e/helpers/mockBackend.ts). - Test files must match
e2e/tests/**/*.test.ts(seee2e/vitest.config.ts).