Tests
arka-deck uses two test pipelines: Vitest for unit and lightweight integration tests, Playwright for end-to-end UI tests.
Vitest — unit + integration
Section titled “Vitest — unit + integration”Run all tests
Section titled “Run all tests”npm testWatch mode
Section titled “Watch mode”npm run test:watchTarget a file
Section titled “Target a file”npm test -- core/use-cases/projects/build-for-projects.test.tsTarget a pattern
Section titled “Target a pattern”npm test -- --grep "purge"Coverage
Section titled “Coverage”npm test -- --coveragev8 coverage produced in coverage/. The blocking threshold in CI is set in vitest.config.ts.
Placement convention
Section titled “Placement convention”Tests live next to the tested code:
core/use-cases/projects/├── build-for-projects.ts├── build-for-projects.test.ts ← unit tests└── build-for-projects.integration.test.ts ← integration tests (optional)
adapters/inbound/web/server/src/__tests__/└── projects-routes.test.ts ← server testsFor HTTP routes, tests live in adapters/inbound/web/server/src/__tests__/.
Fakes and test doubles
Section titled “Fakes and test doubles”core/_fakes/ contains reusable outbound port implementations for tests:
InMemoryFilesystemInMemoryEventBus(= prod and test impl, no separate fake)InMemoryChatSessionStoreFakeClock({ now: () => new Date('2026-01-01T00:00:00Z') })FakeIdGenerator({ next: () => 'test-id-N' })- etc.
Import from tests:
import { InMemoryFilesystem } from '../../../core/_fakes/in-memory-filesystem.js';Playwright — E2E
Section titled “Playwright — E2E”Install Playwright
Section titled “Install Playwright”npm run e2e:install(Downloads Chromium and its deps.)
Run E2E
Section titled “Run E2E”npm run e2eThe test launches the arka-deck server, opens the UI in headless Chromium, and plays scenarios defined in e2e/.
Available E2E tests
Section titled “Available E2E tests”| File | Scenario |
|---|---|
e2e/smoke.spec.ts | Server launch + UI load + health check |
| others | To add per critical flows |
Anti-patterns to avoid
Section titled “Anti-patterns to avoid”Global fs mocking
Section titled “Global fs mocking”❌ Don’t mock fs or node:fs directly. Use InMemoryFilesystem injected in deps.
Order-dependent test
Section titled “Order-dependent test”❌ Vitest can parallelize. Tests must be isolated (no shared state between tests).
Real-clock-dependent test
Section titled “Real-clock-dependent test”❌ Use FakeClock or vi.useFakeTimers().
Artificial coverage
Section titled “Artificial coverage”❌ Don’t write empty tests just to cover a line. Prefer removing dead code.
See also
Section titled “See also”- Hexagonal architecture (ADR 0001): ../../adr/0001-architecture-hexagonale.md
- Contribution conventions: ./conventions (coming)
- CI gates: ./ci-gates (coming)