# Testing and verification

Verify domain behavior against real Postgres and the deployed runtime shape.

## Fast gates [#fast-gates]

```sh
pnpm install --frozen-lockfile
pnpm check-types
pnpm lint
pnpm exec oxlint
FORMAT_BASE_REF=origin/main pnpm format:check
pnpm test
pnpm --filter mobile exec tsc --noEmit
```

Type checks do not validate Worker bundling or database behavior. The format check compares changed files to its base reference; use the intended review base.

## Isolated Postgres [#isolated-postgres]

```sh
node scripts/test-local-postgres.mjs exec pnpm test:integration
node scripts/test-local-postgres.mjs exec node scripts/test-local-jobs.mjs
```

The wrapper creates a disposable local cluster, exports the owned test database variables, applies migrations and stops its cluster when the child finishes. It refuses unsafe assumptions about a remote/shared test database. The jobs harness runs the built Worker with controlled provider fixtures and exercises persisted outcomes, timeouts, leases and repeated ticks.

Effect timeout unit tests use `@effect/vitest` with `TestClock` and production durations. Queue persistence changes additionally require the fault gate in [ADR-0006](/docs/adr/0006-effect-persisted-queue).

## What to test [#what-to-test]

Test the decisions your change makes, not the framework, the ORM or a getter. Database tests run against the disposable cluster above.

**Every procedure:**

- one success with the documented output;
- one `INPUT_VALIDATION` rejection (HTTP 400 on the wire; `BAD_REQUEST` through an in-process `createRouterClient`);
- a caller who is not a Member of the Active Organization gets `FORBIDDEN`;
- another Organization's row is a `NOT_FOUND`, never a result (use the `two-tenants` fixture in `packages/api/src/testing/two-tenants.ts`);
- each tagged error the service can raise, asserting the code and message the client sees (the pilots pin theirs through the real RPC handler in `packages/api/src/testing/characterization/`);
- an audited write records its Audit Event in the same transaction.

**Every new table or tenant path:** the RLS catalog test passes, and the change is proved on every role profile with `pnpm --filter @template-cloudflare/db test:rls-matrix`.

**Every job:** a replay of the same work is a no-op, a lease held by another consumer is not overwritten, and a deadline uses the production value with `TestClock`.

**Every list:** the order is stable with equal sort values, the limit is capped, and a malformed cursor is rejected as input.

## Built Worker [#built-worker]

```sh
pnpm --filter web build
# Run from apps/web in an isolated local test environment:
pnpm exec wrangler dev -c dist/server/wrangler.json --local --port 8790
```

Provide the Hyperdrive local override for the configured binding ID with a password-bearing URL such as `postgresql://template_owner:local@127.0.0.1:PORT/template_test` (the table owner `pnpm test:integration` creates). The exact variable name comes from the Wrangler binding. Keep local tests local; do not deploy to discover a bundling failure.

The build checks that client assets contain no server-only markers and that production AI code does not gain the server-function manifest dependency. Runtime smoke checks should include a public page, the changed API, auth refusal paths and discovery endpoints.

## Docs checks [#docs-checks]

The web unit suite loads compiled MDX, validates metadata and links, orders releases, and checks Markdown/discovery output. Browser review covers light/dark, desktop/mobile, keyboard focus, local diagram scrolling, code blocks and the command palette. Bundle reports separate total client assets from the initial route graph.

## Key files [#key-files]

- [`scripts/test-local-postgres.mjs`](https://github.com/CarlosZiegler/template-cloudflare/blob/main/scripts/test-local-postgres.mjs)
- [`scripts/test-local-jobs.mjs`](https://github.com/CarlosZiegler/template-cloudflare/blob/main/scripts/test-local-jobs.mjs)
- [`apps/web/scripts/assert-client-bundle-clean.mjs`](https://github.com/CarlosZiegler/template-cloudflare/blob/main/apps/web/scripts/assert-client-bundle-clean.mjs)

