Testing
Aero2 uses Vitest with the Cloudflare Workers test pool for unit and integration tests, and Playwright for end-to-end tests.
Test Framework
| Tool | Purpose |
|---|---|
| Vitest | Unit and integration tests |
| @cloudflare/vitest-pool-workers | Workers-compatible test execution environment |
| Playwright | End-to-end browser tests |
Running Tests
# Run all unit/integration tests once
npm test
# Run tests in watch mode (re-runs on file changes)
npm run test:watch
# Run end-to-end tests (requires QA environment)
npm run test:e2e
# Run API integration tests
npm run test:apiTest Configuration
The Vitest configuration is in vitest.config.ts:
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: "./wrangler.json" },
},
},
},
});This configuration runs tests inside a simulated Workers runtime with access to D1, Durable Objects, and all other bindings defined in wrangler.json.
Test Structure
Tests are located in the tests/ directory and use describe/it blocks:
import { env, createExecutionContext, waitOnExecutionContext } from "cloudflare:test";
import { describe, it, expect } from "vitest";
import worker from "../src/backend/index";
describe("Health endpoint", () => {
it("returns 200 with healthy status", async () => {
const request = new Request("http://localhost/health");
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
await waitOnExecutionContext(ctx);
expect(response.status).toBe(200);
const body = await response.json();
expect(body.status).toBe("healthy");
});
});Key Test Helpers
| Import | Purpose |
|---|---|
env | The Worker environment bindings (DB, JWKS_MANAGER, etc.) |
createExecutionContext() | Creates a mock execution context |
waitOnExecutionContext(ctx) | Waits for all async operations to complete |
SELF | Integration test helper for making requests to the Worker |
Integration Tests with SELF
For integration tests that exercise the full middleware chain:
import { SELF } from "cloudflare:test";
describe("API integration", () => {
it("requires authentication for protected endpoints", async () => {
const response = await SELF.fetch("http://localhost/api/users");
expect(response.status).toBe(401);
});
});Test Categories
Unit Tests
Test individual functions and utilities in isolation:
- Token signing and verification
- Password hashing and verification
- CSRF validation logic
- Input validation schemas
- URL validation and redirect prevention
Integration Tests
Test the full request/response cycle through the Worker:
- Authentication flows (login, callback, session creation)
- API endpoint authorization (admin vs user vs unauthenticated)
- OIDC Provider flows (authorize, token exchange)
- RBAC permission enforcement
- Cross-app isolation (verify app A cannot access app B data)
End-to-End Tests
Playwright tests that run in a real browser against the live QA environment:
- Full login flow (navigate to login, click IdP button, complete OAuth, verify dashboard)
- Admin management (create client, configure IdP, manage users)
- Session management (view sessions, revoke session)
Test Data Generation
For populating test environments with sample data:
node scripts/generate-test-data.mjsThis script creates sample users, clients, IdPs, and other test data in the local D1 database.
Writing New Tests
When adding a new feature, include tests that cover:
- Success cases -- The happy path works as expected
- Failure cases -- Invalid input returns appropriate errors
- Authentication -- Protected endpoints reject unauthenticated requests
- Authorization -- Admin endpoints reject non-admin users
- Edge cases -- Boundary conditions, empty inputs, maximum lengths
Naming Convention
Test files are named after the module they test:
tests/op.test.ts-- Tests for OIDC Providertests/rp.test.ts-- Tests for Relying Partytests/auth.test.ts-- Tests for authentication middlewaretests/users.test.ts-- Tests for user management API
Current Test Coverage
The project has 128+ tests passing, covering:
- OIDC Provider (authorization, token exchange, refresh, revocation)
- Relying Party (OAuth flow, state validation, user creation)
- Authentication middleware (token verification, session validation)
- RBAC (permission checks, role assignment)
- Security controls (CSRF, SSRF prevention, redirect validation)
- API endpoints (users, clients, IdPs, roles, sessions, audit)