Testing
Two tiers, declared rather than implied. See also Conventions.
| Tier | Where | Needs |
|---|---|---|
| Unit | tests/unit/ | Markup only — no Postgres |
| Full | tests/ | Real Postgres |
bun run test:unit # SKIP_MIGRATIONS=true bun test tests/unitbun run test:db # db:apply, then the full suitebun run ok # check + test:unitIf a “unit” test hits the database it fails with no service — that keeps the split honest.
Contract and post-swap asserts
Section titled “Contract and post-swap asserts”tests/contract.test.ts walks pages through htmx-contract
(checkDocument). Every resource under src/routes/ must be enrolled; a
meta-test fails when one is missing. Sign-in is checked separately.
For interactions, assert on the DOM after the swap with swapAndCheck — see
tests/tasks.test.ts and Usage. The response body is
not what the user ends up looking at.
Helpers pull CSRF from markup (attributeOf / hx-headers), not with a regex.
Posts without CSRF only test middleware.
CI in a generated app
Section titled “CI in a generated app”templates/app/.github/workflows/ci.yml
ships two jobs:
- fast —
check+test:unit, no Postgres service - full — Postgres service +
test:db
That is what keeps the separation honest in CI as well as locally.