Running tests
Every command, every flag, every gotcha.
Marketplace root suite
cd /Users/.../marketplace
# Full suite (excludes e2e smoke files)
npm test
# Single file
npx vitest run tests/seller-bid-lifecycle.test.ts
# Pattern match
npx vitest run --grep "BUG-007"
# All files in a directory
npx vitest run tests/components/
# Watch mode (re-runs on file change — good for active development)
npx vitest
# E2E smoke only (the hourly cron's tests)
npm run test:smoke
Common flags
| Flag | What it does |
|---|---|
--reporter=verbose | Print every test name as it runs |
--coverage | Generate coverage report (slow, ~3x runtime) |
--run | One-shot run (default npm test already includes this) |
--bail=1 | Stop after first failure (useful when triaging) |
--grep "pattern" | Only tests whose name matches |
Mobile suites
Each app has its own Jest harness with its own deps.
# Consumer mobile
cd mobile && npm test
# Seller mobile
cd mobile-seller && npm test
# Doctor mobile (rarely run)
cd mobile-doctor && npm test
Single file
cd mobile && npm test -- __tests__/components/NegotiationCard.test.tsx
Watch mode
cd mobile && npm test -- --watch
CI behavior
npm test in marketplace root runs in .github/workflows/deploy.yml automatically on every push to main. A test failure aborts the Cloud Run deploy.
Mobile suites do NOT run in CI today — they run on the developer machine before commit.
Environment requirements
| Test layer | Needs |
|---|---|
| File-shape (Vitest, node) | Just node + npm install. No DB, no env vars. |
| jsdom integration | Same as above. The tests/setup.dom.ts provides DOM mocks. |
| API integration (some) | DATABASE_URL if the test queries real prod. Most are mocked. |
| Mobile Jest | cd mobile && npm install per app. Each app has its own node_modules. |
| Live verification | gcloud auth + psql + node (for JWT signing). See Live verification. |
Output interpretation
A successful Vitest run looks like:
Test Files 70 passed | 4 skipped (74)
Tests 2668 passed | 231 skipped (2899)
Start at 19:08:23
Duration 2.73s
The skipped tests are deliberate:
- Eats integration tests (
/api/restaurants) — decommissioned 2026-04-17 but tests not yet deleted - Some flaky integration tests waiting on a fix
- Doctor-flow tests (
project_prescription_deprioritized.md)
A failure looks like:
FAIL tests/seller-bid-lifecycle.test.ts > Counter offer sheet (BUG-006d) > Send button always visible
AssertionError: expected '...' to match /flex:\s*2[\s\S]+?Send/
The first line tells you which test class + which describe + which it. The second line shows the assertion. Click the file path in your terminal to jump to the line.
Speed
| Suite | Typical runtime | Notes |
|---|---|---|
| Marketplace root | ~3-5s for 2668 tests | Vitest parallelizes; node tests are sub-millisecond each |
| jsdom component tests | ~1s per test | DOM setup is the slow part |
| mobile Jest | ~5-30s | Slow because of native module mocks; first run includes Babel transform cache build |
| e2e smoke | ~30-60s | Real HTTP calls to prod; rate-limited |
If your test takes more than ~2 seconds, it's probably hitting the network or doing real DB work. Mock those.
Debugging a flaky test
- Run the file alone:
npx vitest run tests/foo.test.ts - Run it 5x in a row:
for i in {1..5}; do npx vitest run tests/foo.test.ts || break; done - If still flaky, suspect: shared state, async race, real network call, time-of-day dependency
- Fix by: isolating state via
beforeEach, awaiting all async, mocking time/network - Don't quarantine — pin the regression in a comment so the next person knows the historical reason