Skip to content

Latest commit

 

History

History
106 lines (69 loc) · 5.5 KB

File metadata and controls

106 lines (69 loc) · 5.5 KB

Testing

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

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.

Unit test commands

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

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/).

Prerequisites

  • Extension must be built before running E2E tests: run pnpm build:extension from the repo root (or build the extension package). The tests side-load extension/dist.
  • Chrome is required; Puppeteer uses the system Chrome or its bundled Chromium.

E2E commands

Command Description
pnpm test:e2e Run E2E tests (from repo root)

Running E2E tests

From the project root:

pnpm test:e2e

From the e2e directory:

cd e2e && pnpm test

Use pnpm test:watch in e2e/ for watch mode.

How it works

  1. 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_ENDPOINT so test files can connect.
  2. Each test file uses connectBrowser() from e2e/helpers to attach to that shared browser via puppeteer.connect(), then opens pages (including file:// demo pages under demo/), interacts with the overlay/popup, and asserts on the DOM or network.

  3. 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.


Writing unit tests

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’s tests/ directory.
  • Use Vitest globals (describe, it, expect, vi) without importing them when globals: true is set.
  • Use vi.mock() to mock modules; for example, the backend service tests mock the LLM client and generated prompt.

Path alias @/* (backend and shared)

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

Writing E2E tests

  • Use Vitest’s describe / it / beforeAll / afterAll.
    • In beforeAll, call connectBrowser() and store the Browser
    • In afterAll, call browser.disconnect()
  • Use helpers from ../helpers (or e2e/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 (see e2e/helpers/mockBackend.ts).
  • Test files must match e2e/tests/**/*.test.ts (see e2e/vitest.config.ts).