Skip to content

0042 — Manual Testing Tool Suite ​

Status: Accepted

Date: 2026-06-24

ADO work item: AB#4415

Deciders: Kristopher Turner


Context ​

The Heritage Community Hub codebase spans a Node.js/Fastify API, a React web app, shared TypeScript packages, Bicep infrastructure-as-code, and PowerShell automation scripts. Before any deployment goes live, the team needs confidence that every layer of the stack is correct — from infrastructure templates to UI components to API service logic.

The project runs on a single production environment. There is no automated gate that blocks a bad deployment; the developer is responsible for running the appropriate tools before pushing code live. The goal is a well-defined suite of purpose-built tools — one per layer — that can each be run independently and manually to verify correctness and catch problems before they reach users.

This ADR defines that suite: what tool covers what layer, why it was chosen, and how it is used.

Decision ​

We will maintain a suite of purpose-built testing tools — one per layer of the stack — each run manually before deployment. No single tool covers everything. Each tool is chosen because it is the best fit for its specific layer.

The suite covers the following layers:

Infrastructure (Bicep / Azure) ​

Tool: PSRule for Azure (Az.Test ruleset)

PSRule for Azure validates Bicep templates against the Azure Well-Architected Framework and Microsoft best-practice rules before deployment. It runs entirely offline against the template files — no Azure subscription required.

powershell
Invoke-PSRule -InputPath infrastructure/ -Module 'PSRule.Rules.Azure'

Tool: ARM Template Toolkit (arm-ttk)

arm-ttk validates the ARM JSON that Bicep compiles to, catching structural errors, naming violations, and parameter issues.

powershell
Test-AzTemplate -TemplatePath infrastructure/

API — Unit and Integration ​

Tool: Vitest

Vitest is the unit and integration test runner for the Node.js/Fastify API. Each service class is tested in isolation with a mocked Prisma client. Integration tests use Fastify's app.inject() to exercise the full middleware stack — auth guards, error envelopes, route registration — without a live database or Clerk connection.

Tests live in apps/api/src/ alongside the source files they cover. The shared Prisma mock is in apps/api/src/test/setup.ts.

Run from bld-01 or WSL:

bash
pnpm --filter @hch/api test

API — Live Endpoint Testing ​

Tool: Bruno (or VS Code REST Client .http files)

Bruno is an open-source API client (no cloud sync, no account required) for manually testing live API endpoints. Request collections live in apps/api/requests/ and cover every route — authenticated and unauthenticated — with example payloads and expected responses documented inline.

VS Code REST Client .http files are an alternative for developers who prefer to stay in the editor.

Web — Component and Page Tests ​

Tool: Vitest + React Testing Library

React Testing Library tests verify that key pages and components render correctly, respond to user interaction, and handle conditional UI logic (auth state, role-based visibility, empty/loading/error states).

Run from bld-01 or WSL:

bash
pnpm --filter @hch/web test

Web — Browser-Level ​

Tool: Playwright

Playwright smoke tests verify critical user flows in a real browser — sign-in redirect, authenticated page access, API health — against the live deployed environment. Tests live in e2e/.

bash
pnpm exec playwright test

Shared TypeScript Packages ​

Tool: Vitest

Lightweight smoke tests for @hch/shared-config (featureRegistry logic, role filtering) and @hch/shared-types (ROLE_LEVEL shape, FEATURE_ROLES set).

bash
pnpm --filter @hch/shared-config test
pnpm --filter @hch/shared-types test

PowerShell Scripts ​

Tool: Pester 5

Pester is the standard PowerShell testing framework. Any PowerShell automation scripts in this repo (infrastructure helpers, seed scripts, tooling) have corresponding .Tests.ps1 files that verify their behavior.

powershell
Invoke-Pester ./scripts/

Dependency and Secret Scanning ​

Tool: Snyk

Snyk scans all npm packages for known vulnerabilities.

bash
npx snyk test --severity-threshold=high

Tool: Gitleaks

Gitleaks scans the full git history for accidentally committed secrets or credentials.

bash
gitleaks detect --source . --verbose --redact

Static Analysis / Lint ​

Tool: ESLint + TypeScript compiler

The TypeScript compiler (tsc --noEmit) and ESLint catch type errors, unsafe patterns, and style violations across all packages before a build.

bash
pnpm turbo lint

Alternatives considered ​

LayerChosenAlternatives consideredWhy not chosen
InfrastructurePSRule for Azure + arm-ttkManual az deployment validate onlyaz validate catches syntax errors only; PSRule enforces best practices
API unit/integrationVitestJestJest requires additional Babel/ESM config; Vitest is already in the workspace
API live endpointsBrunoPostman, InsomniaPostman requires cloud account; Bruno is open-source and offline-first
Web componentsVitest + RTLCypress component testingCypress adds significant overhead for component tests; RTL is lighter
Browser-levelPlaywrightCypress E2EPlaywright is faster, cross-browser, and has better TypeScript support
PowerShellPester 5Manual execution onlyPester is the PowerShell standard; manual-only provides no repeatability
SecretsGitleakstruffleHogBoth are good; Gitleaks is already integrated

Consequences ​

Positive ​

  • Every layer of the stack has a purpose-built tool that understands its language, format, and failure modes.
  • Tools are independent — a developer can run only the layer relevant to what they changed.
  • No single monolithic test run; faster feedback for targeted changes.
  • Bruno collections serve as living API documentation alongside the tests.
  • PSRule catches infrastructure drift from Azure best practices before it costs money or causes incidents.

Negative / trade-offs ​

  • Multiple tools to install and maintain across the suite.
  • Requires developer discipline — no automatic gate enforces that all tools are run before deployment.
  • Bruno collections must be kept in sync with API route changes.

Risks ​

  • Tool not run before deploy — mitigated by a pre-deployment checklist in the operations runbook that maps each change type to the tools that must pass.
  • Mock drift in Vitest — if the Prisma schema changes and setup.ts is not updated, unit tests pass against a stale mock. Mitigated by updating setup.ts as part of every schema migration.
  • PSRule false positives — some rules may not apply to this project's scale. A .ps-rule/ suppression file will be maintained to document intentional rule suppressions.

References ​

  • AB#4415 — Build comprehensive automated test suite
  • AB#4416 — API service unit tests (220+ tests, completed)
  • AB#4417 — API controller/route tests
  • AB#4418 — API integration tests
  • AB#4419 — Web component tests
  • AB#4420 — Shared package tests
  • AB#4421 — E2E smoke tests (Playwright)
  • ADR 0029 — CI/CD pipeline

Heritage Community Hub — Internal. Access restricted via Cloudflare Access + Entra ID.