Smoke tests
Smoke tests cover the service-reachability and end-to-end-pipeline layer: every service responds to /health, the gateway can accept and route orders, OAuth flows succeed, and core data paths return expected shapes. The platform has two distinct smoke surfaces: backend smoke (run in CI against a testcontainers stack) and frontend deploy-gate smoke (run in CI against a deployed Vite build).
Smoke does not assert correctness of business logic; that is the job of unit and integration tests. It asserts only that requests reach handlers and return well-formed responses.
Backend smoke
Section titled “Backend smoke”File: backend/src/tests/smoke.full.tc.test.ts (full suite) and backend/src/tests/smoke.tc.test.ts (fast critical-path subset)
Run: deno task test:testcontainers
Checks: 11 critical-path checks (fast subset), plus 65 end-to-end checks across the full suite
The full backend smoke (smoke.full.tc.test.ts) groups its 62 checks into three top-level Deno.test blocks so each block can boot the minimum service set it needs:
| Block | Services booted | Checks | | --- | --- | --- | | Service health and version | All 29 services | 3 | | Core trading flows | 9 core services, all 9 algo strategies | 41 | | Peripheral services | 4 core services, 12 peripheral services | 18 |
- Core trading flows boots: market-sim, EMS, OMS, user-service, journal, gateway, fix-archive, observability, risk-engine.
- Peripheral services boots: market-sim, journal, user-service, gateway, plus news, analytics, recommendation, feature, signal, scenario, llm-advisory, replay, rfq, dark-pool, ccp, market-data.
Every block is gated on RUN_TESTCONTAINERS=1, runs inside scripts/run-testcontainers.sh, and wraps its body in try { ... } finally { await stack.teardown() }.
Where it runs
Section titled “Where it runs”- CI (
test:testcontainerstask): runs on every push and PR.scripts/run-testcontainers.shsetsRUN_TESTCONTAINERS=1and brings up an ephemeral Postgres + Redpanda per Deno.test block. - Local development:
deno task test:testcontainersworks in the dev container with Docker available. The full smoke suite (smoke.full.tc.test.ts) takes 90 to 150 seconds depending on how many services each block boots. - Pre-commit: testcontainers smoke is not run by the pre-commit hook because the hook stays fast for tight edit loops. Pre-commit covers unit tests + integration tests (the latter auto-skipped if the local stack is offline).
Why two files
Section titled “Why two files”smoke.tc.test.ts is a curated 11-check subset that boots a small 8-service stack and runs in around 30 seconds. It catches the most common deployment-class bugs quickly. smoke.full.tc.test.ts is the comprehensive 62-check port; it boots larger stacks and takes longer, but covers every check the legacy smoke.test.ts used to assert.
Both files use the same testcontainers helpers (startStack, login from ./testcontainers/auth.ts) and the same RUN_TESTCONTAINERS=1 gate.
Frontend deploy-gate smoke
Section titled “Frontend deploy-gate smoke”File: frontend/tests/gate/smoke.spec.ts
Run: cd frontend && npx playwright test --config playwright.gate.config.ts
Checks: 5 end-user-flow assertions
The frontend smoke is a small Playwright suite that runs against a deployed environment, not the dev stack. It verifies the user-visible surface is wired up:
- Login page renders (homepage is reachable, no 502).
/sessions/mereturns 401 for an anonymous request (the user-service is routable through the gateway and is gating on auth).- After OAuth login, the dashboard mounts and the gateway-proxied market-sim
/pricesendpoint returns price data within 30s (the full happy path works). - A WebSocket to the gateway emits at least one
marketUpdateframe within 10s (real-time data is flowing).
This is the gate that decides whether a deploy is good. If the backend smoke passes but this fails, the deployment's plumbing (Traefik routes, OAuth client config, WebSocket upgrade headers) is wrong: the services are up but the user-facing path is broken.
What smoke is not
Section titled “What smoke is not”Smoke does not verify trading logic, P&L maths, FIX message shapes, or any business behaviour. Those are covered by unit and integration tests. Smoke is the layer that verifies delivery: that the unit-tested code is reachable from a fresh stack boot, with services correctly wired to Postgres and Redpanda, and that the gateway can authenticate users and route orders.
A smoke failure means a routing, wiring, or auth path is broken. A unit or integration failure means the code logic is broken. The runbooks for these two are different.
History
Section titled “History”The legacy smoke.test.ts (now removed) ran against localhost or a remote VETA_BASE_URL and contained 62 checks. It was originally written as a manual post-deploy gate, but in practice ran nowhere: the pre-commit hook auto-skipped it when local services were offline, CI did not invoke it, and the production deploy script uses container healthchecks rather than this suite. The 62 checks were ported to smoke.full.tc.test.ts (which runs in CI via the testcontainers gate) and the legacy file was removed.