Files
cc-ci/tests/plausible/PARITY.md
autonomic-bot 3943cd80e5 feat(2): Q4.7 plausible — §4.3 event-tracking functional tests + PARITY.md; /api/health readiness probe
- functional/test_event_tracking.py: 2 recipe-specific tests (P3) — register site → POST /api/event
  (browser UA) → read back from clickhouse events_v2. test_pageview_event_roundtrip asserts stored
  name/pathname/hostname; test_custom_event_roundtrip asserts a custom-named goal lands under that name.
- test_health_check.py: probe /api/health (200, asserts clickhouse+postgres+sites_cache ready) — fixes
  the broken/unterminated docstring from the prior WIP edit; / is unreliable (500 init / 302 ready).
- recipe_meta.py: HEALTH_PATH=/api/health, HEALTH_OK=(200,); comment corrected.
- PARITY.md: P2 vacuous (no recipe-maintainer corpus); documents P3/P4 coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 18:05:16 +01:00

49 lines
3.4 KiB
Markdown

# plausible — parity & coverage map (Phase 2 Q4.7)
## P2 — Parity port
**No recipe-maintainer corpus exists for plausible** (`/srv/recipe-maintainer/recipe-info/` has no
`plausible/` entry — confirmed: no `recipe-info/plausible/tests/*.py`). P2 (parity) is therefore
**vacuously satisfied** — there are no scripts to port. Coverage is delivered entirely via the generic
lifecycle tiers (install/upgrade/backup/restore) + the recipe-aware backup overlay + the
recipe-specific functional tests below.
## Lifecycle (generic tiers + recipe-aware overlays — Phase 1d/1e)
plausible ships `test_install.py` (generic serving + SPA shell at `/`) and the backup-integrity
overlays (`test_backup.py` / `test_restore.py` / `test_upgrade.py` + `ops.py`). Where an overlay is
present the generic tier still runs alongside it (Phase-1e HC3 invariant).
Readiness probe: `HEALTH_PATH = /api/health`, `HEALTH_OK = (200,)`. plausible's `app` boots before its
ClickHouse events DB is ready and `/` 500s during init (then 302s once ready, so `/` cannot
distinguish not-ready from ready). The dedicated `/api/health` endpoint returns `200` with
`{"clickhouse":"ok","postgres":"ok","sites_cache":"ok"}` **only** once both datastores are reachable —
a true readiness gate. `DEPLOY_TIMEOUT` / `HTTP_TIMEOUT` are widened to 1200s to wait out the cold
ClickHouse + migrations init.
## P3 — Recipe-specific functional tests
- `functional/test_health_check.py`
- `test_plausible_root_serves` — GET `/api/health` → 200, proving ClickHouse + postgres + the
sites_cache are all up (plausible's self-reported backend readiness; not a Traefik fallback).
- `functional/test_event_tracking.py`**§4.3 prescribed "track a test event, query it back"**, the
app's primary object. Both tests register a site row in the metadata postgres (plausible's
`sites_cache` drops events for unregistered domains — empirically confirmed), POST to the public
`/api/event` ingestion endpoint with a browser User-Agent (plausible drops bot/library UAs), then
read the row back out of the ClickHouse `events_v2` table on a poll loop (sites_cache refresh + event
write-buffer flush make the first landing non-instantaneous). Real app-state assertions, not 202-ack
stand-ins:
- `test_pageview_event_roundtrip` — a `pageview` event lands in `events_v2`; asserts the stored
`name`/`pathname`/`hostname` match what was sent.
- `test_custom_event_roundtrip` — a *custom-named* event (a goal/conversion, plausible's distinctive
non-pageview tracking path) lands under that exact name (not coerced to `pageview`).
## P4 — Backup data-integrity (real)
`ops.py` seeds an identifiable `ci_marker` row in the metadata postgres (`db` service), `pre_restore`
drops it, and the restore tier asserts the row survives backup→restore. plausible's recipe backs up
postgres via a real `pg_dump`/`pg_restore` hook (backupbot pre-/post-hooks), so the SQL-level marker
restores cleanly — the recipe-aware data-integrity bar (P4), not a "service is up" stand-in.
## Notes / deferrals
- Reading events back via plausible's **stats API** (rather than ClickHouse directly) requires a
registered user + API key; under `DISABLE_AUTH=true` there is no default user, and creating an API
key adds significant setup with no extra signal over the direct ClickHouse read-back (which is the
authoritative store). The ClickHouse read-back is the stronger, more direct assertion and is used.