docs(agents): the doctrine — tests never run against a real server
Codify the standing rule at the top of the Tests section: the dev DB is the test environment, and the invariant every test must uphold is the testuser experience — its settings, scans, and reading data must be exactly as the suite found them. The helpers exist to enforce this; when a test needs protection the helpers don't provide, expand the helpers rather than hand-rolling. New known-gotchas from the 2026-10-21 incident cluster: 7. scanner re-extraction is write-after-success — audio_metadata is guarded on both writers; new scan-owned column writes need the same guard. 8. templ double-escapes style attribute values (sanitizer + EscapeString) — emit quote-free CSS via unquoted url() tokens through SafeCSS. 9. vp test runs the vite config — build-hook plugins fire in the test context too; outDir-mutating plugins need an "am I a build?" guard.
This commit is contained in:
1 parent
3ed852515b
commit
6508abc00f
1 file changed
+32
@@ -71,6 +71,16 @@ were name-only across ALL libraries. Fixed; do not regress.
|
||||
|
||||
## Tests
|
||||
|
||||
- **THE DOCTRINE — tests are never run against a real/production
|
||||
server.** The dev DB is the test environment, and the invariant every
|
||||
test must uphold is: **leave the testuser experience alone** — its
|
||||
settings, scans, and reading data must be exactly as the suite found
|
||||
them. The helpers exist to enforce this; if a test needs protection
|
||||
the helpers don't provide, EXPAND THE HELPERS rather than hand-rolling
|
||||
(2026-10-21: `setSystemSettingRestored` — snapshot-and-restore for
|
||||
system_settings — exists because a hardcoded ev restore could clobber
|
||||
a deliberate dev bump, and the live dev server obeys that setting on
|
||||
its next poll).
|
||||
- Use `setupTestServer()` from `cmd/server/tests/test_helpers_test.go`
|
||||
(see the Conventions section below for the pool/cleanup rules).
|
||||
- Integration tests run against the SHARED dev database: never write
|
||||
@@ -223,3 +233,25 @@ of a server bug: stop and flag the user.
|
||||
test pools use `max_conns=1`; never create a `pgxpool` per subtest
|
||||
(connection exhaustion); use `t.Cleanup()`-based helpers; table-driven
|
||||
subtests over duplicate functions.
|
||||
7. **Scanner re-extraction is write-after-success** — a failed/empty
|
||||
extraction must NEVER clear scan-derived columns. `updateMediaItem`
|
||||
(generic full-row path) preserves `existing.AudioMetadata` when the
|
||||
new extraction carries no audio payload, and `updateAudioBookItem`
|
||||
refuses empty payloads over populated rows (both guarded 2026-10-21
|
||||
after an ev-gated re-extract NULLed every multi-file audiobook's
|
||||
audio_metadata — books displayed as 1 second long and lost their
|
||||
track manifests). New scan-owned column writes need the same guard.
|
||||
8. **templ double-escapes style attribute values** — the codegen wraps
|
||||
style exprs in a sanitizer AND `templ.EscapeString`, so ANY quote
|
||||
character (even inside `templ.SafeCSS`) reaches the DOM as literal
|
||||
`'` text and the CSS never parses (2026-10-21: every book-detail
|
||||
hero backdrop broken + Firefox fetched `/media/&` → 500 spam).
|
||||
Emit quote-free CSS: unquoted `url(...)` tokens via `SafeCSS` +
|
||||
`cssURL()` in book_detail.templ.
|
||||
9. **`vp test` runs the vite config** — plugins with build hooks fire
|
||||
in the test context too. `cleanStaleChunks` guards on
|
||||
`produced.size === 0` precisely because a bare sweep deleted every
|
||||
hashed chunk in `web/static` when run under vitest (2026-10-21:
|
||||
`npm run test` gutted the build; every page 404'd its imports).
|
||||
Any future outDir-mutating plugin needs the same "am I a build?"
|
||||
guard.
|
||||
Reference in new issue
Block a user