Test types and frameworks
Unit, integration, route smoke, e2e, and parity smoke — what each is for.
Unphish v2 uses a deliberately small number of testing frameworks. The goal is for any contributor to understand what a given test is doing without consulting a separate guide.
Unit tests
Tool: Node's built-in node --test runner.
Where: tests/*.test.mjs, plus colocated *.test.mjs files in lib/, workers/, and scripts/.
Run: pnpm test
Unit tests cover pure logic: role normalization, OIDC config parsing, provider adapter shape, classification scoring math, agent activity normalization. They are fast and exhaustive within their scope.
Unit tests do not start a browser, do not hit a database, and do not call providers. If your test needs any of those, it belongs in a different layer.
Provider adapter and worker tests
Tool: node --test against the worker code.
Where: workers/temporal/**/*.test.mjs.
Run: pnpm test:worker-config
Covers Temporal worker configuration, provider adapter contracts (URLScan, WhoisXML, NothingPhishy, CleanDNS, WhoisFreaks), and enforcement activity behavior. Includes the contract that every provider request must carry organization_id, client_id where applicable, environment, idempotency key, and source/timestamp metadata.
Workbench tests
Run: pnpm test:workbench
Covers the workbench shared pipeline: ingestion, classification, workflow stepping. The workbench shares contracts with production, so workbench tests double as production-contract regression tests.
Migration tests
Run: pnpm test:migration
Covers the v1 dump audit script: row count assertions, schema-drift checks against the v1 snapshot, distinct-value extraction for status / activity / role / report-type / issue-type / platform / quota fields. These run automatically in CI when a v1 dump is available.
Route smoke
Tool: pnpm smoke:routes → scripts/smoke-routes.js
Hits public and authenticated routes against a target URL (local dev or a Vercel preview), checking:
- Public routes return 200 and the expected build artifact.
- Authenticated routes redirect unauthenticated requests to
/signin. - Root layouts, error boundaries, and not-found pages render.
Route smoke is fast and catches build / routing regressions. It is not a substitute for parity testing.
Local parity smoke
Tool: pnpm test:local-parity-smoke → scripts/local-v1-parity-smoke.mjs
Uses the seeded qa_v1_parity fixture set and persona cookies to exercise role-specific flows:
- Hub team management for
staff/admin. - Dashboard data loading with source labels for
analyst. - Client review queue for
client_approver. - Partner portfolio for partner
admin/analyst.
Local parity smoke is the fastest way to confirm a change has not broken role-scoped data flow. It is not a substitute for full Playwright e2e but catches most regressions.
Playwright end-to-end
Tool: pnpm test:e2e (headed: pnpm test:e2e:headed) → e2e/
Real-browser flows for the highest-value journeys:
- Sign-in via Authentik (or the staging Authentik clone).
- Invite acceptance for new and existing users.
- Threat feed triage to enforcement submission.
- Client approval round-trip.
- Watchlist update → case promotion.
- Verification cycle with scheduled checks.
Playwright runs against a configured base URL: typically a local dev server with the seeded fixture set, or a Vercel preview environment.
Manual QA: frontend hub & team checklist
The frontend hub & team QA checklist at docs/frontend-hub-team-qa-checklist.md is a smoke checklist for high-velocity surfaces. Run it whenever any of these touch a PR:
- Hub team invite / resend / revoke / role normalization.
- Dashboard team counts, role/access edit, removal flow.
- Invitation acceptance (valid, expired, mismatched, reused).
- Dashboard source labels (live / imported / unavailable) and absence of fixture fallback on production surfaces.
- API/auth:
/api/teaminvite status,/api/statssource attribution,/api/org/statusdata source claim.
CI
pnpm ci runs lint, typecheck, and build sequentially. CI on pull requests adds:
- Vercel preview deployment.
- Route smoke against the preview.
- v1 dump audit when dump files are available.
- Provider adapter tests.
Production promotion requires CI green plus the gates in Release gates.
What does not count as testing
These have value but do not satisfy signoff on their own:
- TypeScript compile — verifies code shape, not behavior.
- Lint — verifies style and obvious bugs, not behavior.
- Manual click-through with
DEV_AUTH_BYPASS— bypasses the parts of the system that matter (auth, capability, audit, source labels). - A test that mocks the database — integration tests must hit a real database. A mocked database hides migration breakage.