Skip to main content

Smart contract tests

177 Foundry tests across 4 files, organized by domain:

Test structure

All test contracts inherit from BaseTest.sol, which sets up a fork-like environment with a mock USDC token, deploys the factory via UUPS proxy, and provides shared helpers (_createPvPBet, _createOpenBet, _opponentDeposit, _resolve, etc.).

Coverage

Branch coverage numbers appear low (~47% / ~12%) but this is an artifact of --ir-minimum generating imprecise source mappings. The --ir-minimum flag is required because the contracts hit “stack too deep” errors with standard coverage compilation.

Backend tests

The backend uses integration tests that exercise the full HTTP request lifecycle: routing, middleware, input validation, permission checks, state transitions, and database queries. Tests run against the real PostgreSQL database — only external services that cannot be automated (Privy OAuth, Base blockchain) are mocked.
56 tests across 4 files. Runs in ~60 seconds.

What the tests cover

Auth (auth.test.ts — 11 tests)

Bets (bets.test.ts — 33 tests)

Users (users.test.ts — 8 tests)

Leaderboard (leaderboard.test.ts — 4 tests)

What is mocked

External services that require real credentials, OAuth flows, or cost real money are replaced with mock functions: Mocks are defined in src/__tests__/setup.ts and reset before each test via vi.clearAllMocks().

What is real

  • PostgreSQL database — all INSERT, SELECT, UPDATE, DELETE queries hit the real Neon DB
  • Hono app — full middleware chain (CORS, logger, auth middleware)
  • Route handlers — all validation logic, permission checks, SQL queries, state transitions
  • Drizzle ORM — real query building and execution

What the tests do NOT cover

How test data is isolated

Tests never delete existing data. Each test helper (createTestUser, createTestBet, createTestActivity) tracks the IDs of records it creates. At the end of each test file, cleanupTestData() deletes only those tracked records:
Test files run sequentially (fileParallelism: false) to avoid race conditions on the shared database.

File structure

The app.ts / index.ts split exists specifically for testing. app.ts exports the Hono app without calling serve() or starting cron jobs, so tests can import it cleanly via app.request().