Testing¶
Strategy¶
Three layers, matching the proxy's architecture:
- Unit tests — Pure logic: key selection, auth hashing, rate limit math, circuit breaker state
- Integration tests — Worker running locally via
wrangler dev, hitting real D1/KV (local miniflare) - E2E smoke tests — Hit the deployed Worker with real team tokens, verify proxy works against upstream APIs
Running Tests¶
# Unit tests (fast, no network)
pnpm test
# Integration tests (starts local worker, needs wrangler)
pnpm test:integration
# E2E smoke (hits deployed worker)
KEYPOOL_URL=https://keypool.yourdomain.com TEAM_TOKEN=xxx pnpm test:e2e
Unit Tests¶
Use vitest (already compatible with Workers types). Test pure functions without Worker runtime:
// tests/unit/key-selector.test.ts
import { describe, it, expect } from 'vitest'
describe('key selection', () => {
it('round-robin cycles through available keys', () => {
// Test the selection logic with mock D1 results
})
it('skips keys with active circuit breakers', () => {
// Verify circuit-broken keys are filtered
})
it('respects daily limits', () => {
// Key at daily_limit should be skipped
})
})
// tests/unit/auth.test.ts
describe('auth', () => {
it('hashes tokens deterministically', async () => {
// Verify SHA-256 hash matches expected output
})
it('extracts token from Bearer header', () => {
// Test header parsing
})
it('extracts token from x-api-key header', () => {
// Test header parsing
})
it('extracts token from xi-api-key header', () => {
// Test header parsing
})
})
Integration Tests¶
Use unstable_dev from wrangler to spin up a local Worker with real D1/KV bindings:
// tests/integration/proxy.test.ts
import { unstable_dev } from 'wrangler'
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
describe('proxy integration', () => {
let worker: Awaited<ReturnType<typeof unstable_dev>>
beforeAll(async () => {
worker = await unstable_dev('src/index.ts', {
experimental: { disableExperimentalWarning: true },
})
// Seed local D1 with test data
})
afterAll(async () => {
await worker.stop()
})
it('returns 401 without token', async () => {
const res = await worker.fetch('/v1/exa/search', { method: 'POST' })
expect(res.status).toBe(401)
})
it('returns 404 for unknown service', async () => {
const res = await worker.fetch('/v1/nonexistent/test', {
headers: { Authorization: 'Bearer test-token' },
})
expect(res.status).toBe(404) // or 503 if service not found
})
it('health endpoint works without auth', async () => {
const res = await worker.fetch('/health')
expect(res.status).toBe(200)
const body = await res.json()
expect(body.status).toBe('ok')
})
it('admin requires ADMIN_TOKEN', async () => {
const res = await worker.fetch('/admin/status')
expect(res.status).toBe(401)
})
})
E2E Smoke Tests¶
Run against the deployed Worker with a real team token. These verify the full proxy path including upstream API calls:
// tests/e2e/smoke.test.ts
const KEYPOOL_URL = process.env.KEYPOOL_URL!
const TEAM_TOKEN = process.env.TEAM_TOKEN!
describe('e2e smoke', () => {
it('proxies Exa search', async () => {
const res = await fetch(`${KEYPOOL_URL}/v1/exa/search`, {
method: 'POST',
headers: {
Authorization: `Bearer ${TEAM_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: 'test query',
num_results: 1,
}),
})
expect(res.status).toBe(200)
const body = await res.json()
expect(body.results).toBeDefined()
// Verify KeyPool headers are present
expect(res.headers.get('X-KeyPool-Key-Id')).toBeTruthy()
})
it('proxies Firecrawl scrape', async () => {
const res = await fetch(`${KEYPOOL_URL}/v1/firecrawl/v1/scrape`, {
method: 'POST',
headers: {
Authorization: `Bearer ${TEAM_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://example.com',
formats: ['markdown'],
}),
})
expect(res.status).toBe(200)
})
it('rate limits excessive requests', async () => {
// Fire requests rapidly to trigger rate limit
const promises = Array.from({ length: 100 }, () =>
fetch(`${KEYPOOL_URL}/v1/exa/search`, {
method: 'POST',
headers: {
Authorization: `Bearer ${TEAM_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query: 'test', num_results: 1 }),
})
)
const responses = await Promise.all(promises)
const rateLimited = responses.filter((r) => r.status === 429)
expect(rateLimited.length).toBeGreaterThan(0)
})
})
Quick Manual Smoke Test¶
After deploy, run this to verify the proxy works:
# 1. Create a team token
curl -X POST https://keypool.yourdomain.com/admin/tokens \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"member_name": "test-user"}' | jq .
# 2. Save the returned token, then test proxy
curl -X POST https://keypool.yourdomain.com/v1/exa/search \
-H "Authorization: Bearer TEAM_TOKEN_FROM_STEP_1" \
-H "Content-Type: application/json" \
-d '{"query": "cloudflare workers", "num_results": 1}' | jq .
# 3. Check admin status
curl https://keypool.yourdomain.com/admin/status \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" | jq .
# 4. Check usage
curl "https://keypool.yourdomain.com/admin/usage?days=1" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" | jq .