Files

4.0 KiB

phase, title, status, priority, effort, dependencies
phase title status priority effort dependencies
4 Tests + CI completed P2 2h
2
3

Phase 4: Tests + CI

Overview

Vitest with @cloudflare/vitest-pool-workers for in-Workers-runtime tests. Cover template rendering, fire client behavior (success / non-2xx / network error), token redaction. GitHub Actions CI on push.

Requirements

  • Functional:
    • Tests cover: template substitution, missing-token rendering, fire success path, non-2xx path, fetch throws path.
    • CI runs npm test on push to main and PRs.
  • Non-functional:
    • Coverage report (text summary in CI logs).
    • Tests use mocked fetch — no real network calls (don't burn user's Anthropic quota).
    • Tests written in plain JS with JSDoc, matching production code style.
    • Race-free is N/A on Workers; instead assert console.log output never contains token.

Architecture

Test layout

worker.test.js          # all tests in one file initially (KISS)

Split if exceeds 200 lines.

Test cases (mirror Go daemon's test coverage)

# Case Assertion
1 renderText substitutes {LocalTime}, {Cron}, {ISO} output equals expected string
2 renderText leaves unknown {Foo} tokens intact output contains {Foo}
3 fireRoutine 2xx response logs session_url console captured contains session_url
4 fireRoutine 401 response logs level:error captured log has level:'error', status:401
5 fireRoutine fetch rejects (network) logs error, doesn't throw no thrown exception, error log present
6 Token redaction for cases 3, 4, 5: stringified logs do NOT contain token value
7 Headers correctness mocked fetch receives Authorization: Bearer ${token}, anthropic-version, anthropic-beta
8 Body shape request body parses as { "text": <rendered> }
9 Default template when TEXT_TEMPLATE unset output starts with Scheduled trigger at
10 TZ defaults to UTC when env.TZ unset local time formatting uses UTC

CI workflow

.github/workflows/ci.yml — single job, Node 20, runs test + wrangler dry-run as smoke gate.

  • Create: worker.test.js
  • Create: vitest.config.js (uses @cloudflare/vitest-pool-workers)
  • Create: .github/workflows/ci.yml

Implementation Steps

  1. Install: npm i -D vitest @cloudflare/vitest-pool-workers.
  2. Write vitest.config.js:
    import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config';
    export default defineWorkersConfig({
      test: { poolOptions: { workers: { wrangler: { configPath: './wrangler.toml' } } } },
    });
    
  3. Write worker.test.js covering all 10 cases. Use vi.fn() mock for globalThis.fetch. JSDoc-annotate test helper functions for IDE assist.
  4. Run npm test — all green.
  5. Write .github/workflows/ci.yml:
    name: ci
    on:
      push: { branches: [main] }
      pull_request:
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-node@v4
            with: { node-version: '20', cache: 'npm' }
          - run: npm ci
          - run: npm test
          - run: npx wrangler deploy --dry-run
    
  6. Push to GitHub; verify green CI.

Success Criteria

  • All 10 test cases pass locally
  • npm test exits 0 in CI
  • wrangler deploy --dry-run exits 0 in CI
  • No real HTTP traffic generated by tests (verify by mock spy)
  • Coverage ≥ 80% (track via vitest --coverage; not enforced as blocking gate)

Risk Assessment

  • Workers test pool quirks: @cloudflare/vitest-pool-workers requires wrangler config; ensure wrangler.toml validates first.
  • Mocking fetch inside Workers runtime: verify pattern works — fall back to dependency-injected fetch if not.
  • Beta header pinning in tests: assert exact value to catch accidental edits.

Security Considerations

  • Test fixtures use placeholder token sk-ant-oat01-test-only — never a real value.
  • Test asserts logs don't contain the token (regression guard).