End-to-end tests for the agentage Memory product — landing, backend, dashboard, Obsidian plugin, MCP endpoint. Whole-product e2e only; module-level tests live with the code they cover.
This repo exists to give delivery quality with minimal effort:
- Fast sense-check for a small change →
npm run smoke(seconds). - Gate the dev→prod promotion on the P0s →
npm run gate(and thelanding-gateCI job; promotion only fires when it's green). - Surface the other required fixes →
KNOWN-ISSUES.md(visible, tracked — not tribal).
Full model in TEST-STRATEGY.md.
PR (changed tests) ──────► smoke ───────────────────────────► merge if green
deploy → dev ────────────► smoke (dev)
nightly (schedule) ──────► full (dev) ──► P0 green? ──yes──► promote dev → prod ──► full (prod)
│
└──no──► blocked + issue filed
Two lanes: a fast lane (PR / dev deploy → smoke) for quick confidence, and a scheduled lane (nightly full on dev → the P0 gate → promote → full on prod). Wired today: PR smoke (changed files), nightly full → landing-gate → promote, prod gate via verify-prod. Pending: a dev-deploy smoke hook, and full (vs the gate) on prod.
npm run e2e -- <surface> <level> # order-free positional, or --surface/--level
npm run smoke # = e2e all smoke (fast sense-check)
npm run gate # = e2e landing gate (the promotion gate)
npm run e2e -- landing gate # landing smoke + P0
npm run e2e -- all p0 # every surface, P0 only
npm run e2e -- backend smoke --headed # extra flags pass through to Playwright| Dial | Values | Maps to |
|---|---|---|
| surface | all · landing · backend · dashboard · obsidian · mcp · integration |
Playwright project |
| level | smoke · p0 · gate (=smoke+p0) · full (=every tag) |
test tag |
Pick the target with LANDING_ENV / SITE_ENV (dev | prod, default dev) or explicit LANDING_URL / SITE_URL.
On demand in CI: the E2E (on demand) workflow (Actions tab → Run workflow) takes the same surface + level + target and runs them against the deployed site.
Always-on — deployed-site. No secret needed; targets a live URL, so the nightly is never vacuous.
| Project | Target | Covers |
|---|---|---|
landing |
landingUrl() |
@smoke liveness · @p0 SEO/OG/icons/disclosure/robots/sitemap/blog/mobile · @full signal |
backend |
siteUrl() + /api |
@smoke /api/health envelope |
dashboard |
siteUrl() |
@smoke /dashboard + login form (cold-start-resilient) |
Gated — needs a backing service. Skips via test.skip(!gates.X, '...') when the env var is absent, so verify and the nightly still run everywhere.
| Project | Gate (env var) | Covers |
|---|---|---|
obsidian |
OBSIDIAN_BIN (+ COUCHDB_URL) |
Plugin loads + push/pull/status round-trip |
mcp |
MCP_URL |
memory__* tools over Streamable HTTP + OAuth/PKCE |
integration |
all of the above + DASHBOARD_URL |
Golden-path: write anywhere → read everywhere |
nightly.yml → landing-gate job runs landing @smoke+@p0 + backend health + dashboard smoke. Only green fires the dev→prod promote dispatch. The full suite (e2e job) is the nightly signal and gates the plugin release. A landing regression blocks promotion; an obsidian/full-suite flake does not.
After a promote, verify-prod.yml re-runs the gate against prod (agentage.io) — by hand (workflow_dispatch) or fired from web's deploy.yml on a successful prod deploy (repository_dispatch: verify-prod). This exercises the prod-only robots/canonical/indexable branch, so a promotion is confirmed on the real URL, not assumed from dev.
Needs the Obsidian .deb (or an extracted AppImage; snap won't work), a checkout of agentage/obsidian-memory with the plugin built, and an X display.
npm install
./scripts/e2e/install-obsidian.sh # Obsidian + window manager + Xvfb
./scripts/e2e/start-display.sh
( cd ../obsidian-memory && npm ci && npm run build )
PLUGIN_ROOT=$(pwd)/../obsidian-memory ./scripts/e2e/setup-vault.sh
OBSIDIAN_BIN=/opt/Obsidian/obsidian OBSIDIAN_VAULT=/tmp/obsidian-test-vault DISPLAY=:99 \
npm run test:obsidiannpm run verify # type-check + lint + format:checkRoot CLAUDE.md. Memory product spec: ~/agentage-memory/onepager.md.