End-to-end test harness for the mx-space CLI ↔ server contract. Boots a real in-process NestJS core server backed by throwaway PostgreSQL and Redis containers, seeds an owner, then drives the real mxs CLI binary as a subprocess against it.
Each test file follows the same lifecycle:
- Containers —
createE2EBackend()starts apostgres:17-alpinetestcontainer (per-worker isolated database, migrated fromapps/core/src/database/migrations) and a per-backendredis:7-alpinetestcontainer. - Env seeding —
PG_*/REDIS_*/MIGRATIONS_DIR/JWT_SECRETare written intoprocess.envbeforeapps/core'sAppModuleis dynamically imported, so no frozen config defaults leak in. - Server —
@nestjs/testingcompilesAppModule; Fastify listens on an ephemeral loopback port in dev mode (no/api/vNprefix). - Auth — an owner is inserted directly into PostgreSQL (Better Auth credential rows), a bearer token is minted via
signInUsername, and a CLI profile is written under a temporary$XDG_CONFIG_HOME. - CLI — tests spawn
packages/cli/src/bin/mxs.tsviatsxwith mode flags and assert on the parsed{ ok, data }envelope.runAcrossModes()walks all five output modes (json,pretty-json,readable,llm,xml).
# From the repo root
pnpm e2e
# Or from this package
pnpm -C packages/e2e run testRequires Docker (testcontainers). No environment variables are strictly required — all are seeded with ??= defaults. Set PG_VERIFY_URL to reuse an external PostgreSQL instead of starting a container.
Note
Hook and test timeouts are 120s; CI runs with 2 retries and 2 workers.
src/
├── helpers/ # backend boot, PG/Redis containers, CLI subprocess, auth seeding, fixtures
└── fixtures/ # canonical owner credentials
test/
├── auth-device-flow.test.ts, auth-login-state.test.ts, post-crud.test.ts, profile-switch.test.ts
├── ai/ # AI artifact management
├── file/ # upload flow
├── help/ # help output contracts
├── output/ # output-mode format matrix
├── resources/ # category / comment / config / note / page / project / snippet / topic CRUD
└── skill/ # skill list / get / search output