Skip to content

Tests

arka-deck uses two test pipelines: Vitest for unit and lightweight integration tests, Playwright for end-to-end UI tests.


Terminal window
npm test
Terminal window
npm run test:watch
Terminal window
npm test -- core/use-cases/projects/build-for-projects.test.ts
Terminal window
npm test -- --grep "purge"
Terminal window
npm test -- --coverage

v8 coverage produced in coverage/. The blocking threshold in CI is set in vitest.config.ts.


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 tests

For HTTP routes, tests live in adapters/inbound/web/server/src/__tests__/.


core/_fakes/ contains reusable outbound port implementations for tests:

  • InMemoryFilesystem
  • InMemoryEventBus (= prod and test impl, no separate fake)
  • InMemoryChatSessionStore
  • FakeClock ({ 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';

Terminal window
npm run e2e:install

(Downloads Chromium and its deps.)

Terminal window
npm run e2e

The test launches the arka-deck server, opens the UI in headless Chromium, and plays scenarios defined in e2e/.

FileScenario
e2e/smoke.spec.tsServer launch + UI load + health check
othersTo add per critical flows

❌ Don’t mock fs or node:fs directly. Use InMemoryFilesystem injected in deps.

❌ Vitest can parallelize. Tests must be isolated (no shared state between tests).

❌ Use FakeClock or vi.useFakeTimers().

❌ Don’t write empty tests just to cover a line. Prefer removing dead code.