Unphish v2 Docs

Testing Guide

How we test Unphish v2 — frameworks, parity matrix, UAT, and release gates.

This guide covers how we test Unphish v2 end to end. It is for QA engineers, release managers, Unphish staff doing UAT, and engineers who need to know what counts as "tested" before a change ships.

The four layers of testing

Unphish v2 is tested at four layers:

  1. Test types — Unit, integration, route smoke, e2e, and the local-parity smoke harness. What runs, where, and against what data.
  2. V1 parity matrix — The 20-epic, 102-row truth table tracking every v1 capability and its v2 disposition (retained / replaced / merged / retired).
  3. Staff UAT — The 1,540-case user-acceptance test corpus harvested from staff workbooks, mapped onto the parity matrix.
  4. Release gates — What must be green before a deployment promotes to staging or production.

Three principles before you write a test

1. Real cookies, not bypasses

P0 parity rows must be exercised through a real-browser role flow with a real session cookie. DEV_AUTH_BYPASS is for ad-hoc developer debugging, not for signoff. A test that bypasses auth does not exercise the parts of the system that fail in production: route guards, capability checks, audit, source labelling.

2. Source-state assertions are mandatory

Every P0 row must assert the data source state is correct: live, imported, demo, fixture, or unavailable. A test that "passes" because the page rendered fixture data while a customer should be seeing live data is a failed test, not a passing one. Source labelling is the contract; a test that ignores it does not protect the contract.

3. Audit assertions for sensitive flows

Sensitive workflows (impersonation, team delete, provider secret writes, whitelist uploads, scan config changes, enforcement submissions, client approvals) require an audit log assertion. The audit entry is part of the feature; a test that does not check it is incomplete.

What "tested" means in v2

A change is tested when:

  • Unit tests cover its logic in isolation.
  • Integration / route / e2e tests cover the user-visible behavior with real auth and real data.
  • The relevant parity row(s) are green with a real-browser flow, an API assertion, a seeded-data assertion, and a source-state assertion.
  • Audit assertions exist for sensitive flows.
  • Dark mode and responsive QA pass for surfaces that need it (dashboard, threat feed, case detail, client review, partner queue, watchlist, whitelist, scan centre).

Anything less is partial coverage. Partial coverage is fine for in-progress work; it is not fine for promotion to production.

Where to find each thing

WhatWhere
Unit teststests/*.test.mjs, lib/**/*.test.mjs, workers/**/*.test.mjs
Route smokepnpm smoke:routesscripts/smoke-routes.js
Local parity smokepnpm test:local-parity-smokescripts/local-v1-parity-smoke.mjs
Playwright e2epnpm test:e2ee2e/
Migration testspnpm test:migrationscripts/audit-v1-dump.test.js
Worker testspnpm test:worker-config
Workbench testspnpm test:workbench
V1 parity matrixdocs/qa/v1-parity-matrix.md
Staff UAT reviewdocs/qa/staff-uat-functional-spec-gap-review-2026-05-03.md
Local QA runbookdocs/production-readiness-runbook.md
Frontend QA checklistdocs/frontend-hub-team-qa-checklist.md

On this page