What you will learn
- The four test categories and what each covers
- How to run tests by category and in watch mode
- Where test files and fixtures live
- How Docker and Anvil dependencies are handled
- Guidelines for writing new tests
Test categories
Clavion uses vitest as its test runner. Tests are organized into four categories by scope and requirements.| Category | Count | Requirements | What It Covers |
|---|---|---|---|
| Unit | ~300+ | None | Schemas, policy engine, builders, risk scorer, keystore, wallet service, approval tokens, manifest validation, scanner, ISCLClient, intent builder |
| Integration | ~30+ | None | HTTP API routes, adapter client against real Fastify, skill wrappers end-to-end, rate limiting |
| Security | ~28 | Docker (some tests) | Domain A isolation, Domain B integrity, Domain C sandbox enforcement, tampered package detection |
| E2E | ~6 | Anvil + BASE_RPC_URL | Full pipeline on Anvil Base fork: build -> preflight -> approve -> sign -> broadcast |
Running tests
E2E tests require both Anvil (from the Foundry toolchain) and a Base RPC endpoint. Set
BASE_RPC_URL before running.Test directory structure
Fixtures
Test fixtures live intools/fixtures/:
| Fixture File | Contents |
|---|---|
valid-intents.ts | One valid TxIntent per action type (transfer, transfer_native, approve, swap_exact_in, swap_exact_out) |
invalid-intents.ts | Malformed and edge-case intents for rejection testing |
skill-manifests.ts | Valid and invalid SkillManifest examples |
hash-fixtures.ts | Pre-computed canonicalization hashes for determinism verification |
Skipping tests
Tests that require external infrastructure skip gracefully when dependencies are unavailable:- Docker Tests
- E2E Tests
- Security Tests
Use
describe.skipIf(!dockerAvailable). Skipped when Docker is not running. Affects sandbox isolation tests in tests/security/.CI pipeline
The GitHub Actions workflow (.github/workflows/ci.yml) runs on push to main/develop and on pull requests:
Security and E2E tests require Docker/Anvil and are not run in CI by default. Run them locally before submitting PRs that touch Domain B code.
Writing new tests
Unit tests
Unit tests
Import the module directly and mock external dependencies (RPC, filesystem). Unit tests live in Key rules:
packages/*/test/ alongside the package they test.- Mock RPC clients, never make real network calls
- Mock the filesystem for file-dependent tests
- Use fixtures from
tools/fixtures/for TxIntents and SkillManifests
Integration tests
Integration tests
Use Key rules:
buildApp() to create an ephemeral Fastify server on port 0, then test via real HTTP requests. Integration tests live in tests/integration/.- Always close the Fastify instance after the test
- Use port 0 to avoid conflicts
- Test the full HTTP request/response cycle
Security tests
Security tests
Test against the threat model scenarios (A1-A4, B1-B4, C1-C4). Security tests live in
tests/security/.Key rules:- Verify Domain A code cannot access keys or sign transactions
- Verify Domain B enforces policy and approval on every path
- Verify Domain C sandbox restrictions are enforced
- Flag changes to signing, key management, or approval flow for extra review
Mock RPC factories
Mock RPC factories
All mock RPC factories must include every
RpcClient interface method, including readNativeBalance. Incomplete mocks cause runtime failures in unrelated tests.Testing requirements for PRs
All pull requests must satisfy these rules:npm testpasses — this runs unit and integration tests.- New features include unit tests. If you add a builder, service, route, or adapter method, add corresponding tests.
- Fund-affecting features include security tests. Changes to signing, policy enforcement, approval flow, or key management must include tests that verify Domain B integrity.
- Mock RPC factories implement all
RpcClientmethods, includingreadNativeBalance. - Test fixtures stay in sync. New valid fixtures require corresponding hash entries.
Next steps
- Contributing Guide — PR process and coding standards
- Sandbox Security — Container isolation testing
- Trust Domains — Understanding the three trust domains