Skip to content

W0: test foundation - #135

Merged
can3p merged 14 commits into
masterfrom
test/w0-foundation
Sep 26, 2026
Merged

can3p merged 14 commits into
masterfrom
test/w0-foundation

Conversation

@can3p

@can3p can3p commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Wave W0 of the modernization plan: the test infrastructure every later test wave builds on. No production code changes.

  • Test databases: pkg/testutil/testdb.New(t) over gogo v0.0.2's testcontainers/postgres (migrations applied once into a template database, one copy per test). pcom's dockertest copy is deleted.
  • Factories (pkg/testutil/factory): a builder per table, the connection graph, and readers in read.go, with a self-test that builds every entity. It doesn't import testing, so the seed command can use it.
  • Fakes and helpers: Must, fakesender, fakestorage, ginctx, golden.
  • E2E harness (e2e/): runs the real ./cmd/web binary per test against its own database and drives it with a cookie-jar client (CSRF token, htmx headers, goquery). Smoke tests: anonymous home, and a factory user logging in to /feed. A build overlay adds a SIGTERM handler, because a -cover binary writes coverage only on a normal exit; details are in the commit message.
  • Tooling: make test writes coverage.out, make test-short skips E2E, make cover prints merged unit and E2E coverage per package; codecov.yml; docs/testing.md rewritten with worked examples.
  • Plan docs: W0 is marked done, and the wave is recorded in docs/archive/history.md and docs/lessons.md. Q14 (E2E coverage in CI) is open.

New test-only dependency: github.com/PuerkitoBio/goquery (it pulls golang.org/x/net from v0.57.0 to v0.58.0). ory/dockertest is removed.

Please merge with a merge or rebase merge, not a squash: W1–W4 and W6 branch from this one.

🤖 Generated with Claude Code

https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE

can3p and others added 14 commits September 26, 2026 10:27
…from "Owns"

W0 lists each task both as a ### section (the spec) and as a delegation
table row (tier, ownership). The builder took only the row, so subagents
lost the spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
Delete pcom's dockertest-based copy and add pkg/testutil/testdb.New(t),
which resolves pcom's migrations directory and calls gogo's postgres.New.
Migrations are applied once into a template database and each test gets
a copy, dropped on cleanup. Existing DB tests move to testdb.New.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
fakesender records mail and can fail on demand, fakestorage is an
in-memory MediaStorage with injectable errors, ginctx builds a gin
context with a cookie session (optionally logged in, with CSP nonces),
golden compares against testdata with UPDATE_GOLDEN=1, and testutil.Must
unwraps (value, error) pairs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
`make test` writes coverage.out for CI's Codecov upload. `make cover`
collects unit and E2E binary coverage into one directory and prints a
per-package table without the generated pkg/model/core. `make
test-short` skips E2E. codecov.yml ignores pkg/model/core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
One builder per table plus the relationships the domain needs (users and
the connection graph, posts and comments, account, feeds, media, mail),
with defaults that satisfy every constraint and stay unique across a
run, and readers in read.go. The package doesn't import testing, so the
seed command can use it. A self-test builds every entity once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
e2e.Main builds ./cmd/web once with coverage; e2e.Start runs it against
a fresh database in a work dir with a stub asset manifest and waits for
GET / to answer. App.Client is a cookie-jar client that doesn't follow
redirects, sends the scraped CSRF token and exposes htmx headers; HTML
assertions use goquery (new test-only dependency).

The server has no signal handling, so a build overlay adds a SIGTERM
handler to pkg/types (a package without statements, left out of
-coverpkg because the cover tool ignores overlays). A stopped server
then exits normally and writes its coverage where `make cover` merges it.

Smoke tests: anonymous GET / and a factory user logging in to /feed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
Describe testdb, the factories, the fakes, golden files and the E2E
harness as they now exist, with one worked example each of a unit, a DB
and an E2E test. Drop the sections about the removed test container.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
W0's subagents printed whole files 33 times despite AGENTS.md's reading
rules; the task preamble now says it in the task itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
Mark W0 done and delete its wave file, record the wave (what was built,
what turned out wrong, cost) in docs/archive/history.md, start
docs/lessons.md, and add Q14 on E2E coverage in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
The server never reads HX-Request, and HTTP tests that pin HX-* response
headers keep passing when an htmx upgrade breaks the pages. The client
now sends plain requests and Response has no HX-* accessors: behavior that
needs the page's JavaScript is tested in the browser suite. LoginAs
checks that the session can open /feed instead of reading HX-Redirect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UQyTX1ww97bDaWMEBtmuE
@can3p
can3p merged commit af9ff4d into master Sep 26, 2026
5 checks passed
@can3p
can3p deleted the test/w0-foundation branch September 26, 2026 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant