Archive milestone artifacts (roadmap, requirements, audit, phase directories) to .planning/milestones/. Evolve PROJECT.md with validated requirements and decision outcomes. Create MILESTONES.md and RETROSPECTIVE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
125 lines
5.9 KiB
Markdown
125 lines
5.9 KiB
Markdown
---
|
|
phase: 01-data-foundation
|
|
plan: 02
|
|
subsystem: testing
|
|
tags: [vitest, supabase, mocking, unit-tests, health-checks, alert-events]
|
|
|
|
# Dependency graph
|
|
requires:
|
|
- phase: 01-data-foundation/01-01
|
|
provides: HealthCheckModel and AlertEventModel classes with getSupabaseServiceClient usage
|
|
|
|
provides:
|
|
- Unit tests for HealthCheckModel covering all CRUD methods and input validation
|
|
- Unit tests for AlertEventModel covering all CRUD methods, status transitions, and input validation
|
|
- Supabase chainable mock pattern for future model tests
|
|
- INFR-04 compliance verification (models call getSupabaseServiceClient per invocation)
|
|
|
|
affects:
|
|
- 02-monitoring-services
|
|
- future model tests
|
|
|
|
# Tech tracking
|
|
tech-stack:
|
|
added: []
|
|
patterns:
|
|
- "Supabase chainable mock: makeSupabaseChain() helper with fluent vi.fn() returns and thenability for awaitable queries"
|
|
- "vi.mock hoisting: factory functions use only inline vi.fn() to avoid temporal dead zone errors"
|
|
- "vi.mocked() for typed access to mocked module exports after import"
|
|
|
|
key-files:
|
|
created:
|
|
- backend/src/__tests__/models/HealthCheckModel.test.ts
|
|
- backend/src/__tests__/models/AlertEventModel.test.ts
|
|
modified: []
|
|
|
|
key-decisions:
|
|
- "Supabase mock uses thenability (chain.then) so both .single() and direct await patterns work without duplicating mocks"
|
|
- "makeSupabaseChain() factory encapsulates mock setup — one call per test, no shared state between tests"
|
|
- "vi.mock() factories use only inline vi.fn() — no top-level variable references to avoid hoisting TDZ errors"
|
|
|
|
patterns-established:
|
|
- "Model test pattern: vi.mock both supabase and logger, import vi.mocked() typed refs, makeSupabaseChain() per test, clearAllMocks in beforeEach"
|
|
- "Validation test pattern: verify getSupabaseServiceClient not called when validation throws (confirms no DB hit)"
|
|
- "PGRST116 null return: mock error.code = 'PGRST116' to test no-rows path that returns null instead of throwing"
|
|
|
|
requirements-completed: [INFR-01, INFR-04]
|
|
|
|
# Metrics
|
|
duration: 26min
|
|
completed: 2026-02-24
|
|
---
|
|
|
|
# Phase 01 Plan 02: Model Unit Tests Summary
|
|
|
|
**33 unit tests for HealthCheckModel and AlertEventModel with Vitest + Supabase chainable mock pattern**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** 26 min
|
|
- **Started:** 2026-02-24T16:46:26Z
|
|
- **Completed:** 2026-02-24T17:13:22Z
|
|
- **Tasks:** 2
|
|
- **Files modified:** 2
|
|
|
|
## Accomplishments
|
|
|
|
- HealthCheckModel: 14 tests covering create (valid/minimal/probe_details), 2 validation error paths, Supabase error + error logging, findLatestByService (found/null PGRST116), findAll (default limit/filtered/custom limit), deleteOlderThan (date calculation/count)
|
|
- AlertEventModel: 19 tests covering create (valid/default status/explicit status/details JSONB), 3 validation error paths, Supabase error, findActive (all/filtered/empty), acknowledge/resolve (success + PGRST116 not-found), findRecentByService (found/null), deleteOlderThan
|
|
- Established `makeSupabaseChain()` helper pattern for all future model tests — single source for mock client setup with fluent chain and thenable resolution
|
|
- Full test suite (41 tests) passes with no regressions
|
|
|
|
## Task Commits
|
|
|
|
Each task was committed atomically:
|
|
|
|
1. **Task 1: Create HealthCheckModel unit tests** - `99c6dcb` (test)
|
|
2. **Task 2: Create AlertEventModel unit tests** - `a3cd82b` (test)
|
|
|
|
**Plan metadata:** (docs commit to follow)
|
|
|
|
## Files Created/Modified
|
|
|
|
- `backend/src/__tests__/models/HealthCheckModel.test.ts` - 14 unit tests for HealthCheckModel CRUD, validation, and error handling
|
|
- `backend/src/__tests__/models/AlertEventModel.test.ts` - 19 unit tests for AlertEventModel CRUD, status transitions, validation, and error handling
|
|
|
|
## Decisions Made
|
|
|
|
- Supabase mock uses `chain.then` (thenability) so both `.single()` and direct `await query` patterns work from the same mock object — no need to bifurcate mocks for the two query termination patterns the models use.
|
|
- `makeSupabaseChain(resolvedValue)` factory creates a fresh mock per test — avoids state leakage between tests that would occur with a shared top-level mock object.
|
|
- `vi.mock()` factories use only inline `vi.fn()` — top-level variable references are in temporal dead zone when hoisted factories execute.
|
|
|
|
## Deviations from Plan
|
|
|
|
**1. [Rule 1 - Bug] Fixed Vitest hoisting TDZ error in initial mock approach**
|
|
- **Found during:** Task 1 (first test run)
|
|
- **Issue:** Initial approach created top-level mock variables, then referenced them inside `vi.mock()` factory — Vitest hoists `vi.mock` before variable initialization, causing `ReferenceError: Cannot access 'mockGetSupabaseServiceClient' before initialization`
|
|
- **Fix:** Rewrote mock factories to use only inline `vi.fn()`, then used `vi.mocked()` after imports to get typed references
|
|
- **Files modified:** `backend/src/__tests__/models/HealthCheckModel.test.ts`
|
|
- **Verification:** Tests ran successfully on second attempt; this pattern used for AlertEventModel from the start
|
|
- **Committed in:** 99c6dcb (Task 1 commit, updated file)
|
|
|
|
---
|
|
|
|
**Total deviations:** 1 auto-fixed (Rule 1 — runtime error in test infrastructure)
|
|
**Impact on plan:** Fix was required for tests to run. Resulted in a cleaner, idiomatic Vitest mock pattern.
|
|
|
|
## Issues Encountered
|
|
|
|
- Vitest mock hoisting TDZ: the correct pattern is `vi.mock()` factory uses only `vi.fn()` inline, with `vi.mocked()` used post-import for typed access. Documented in patterns-established for all future test authors.
|
|
|
|
## User Setup Required
|
|
|
|
None - no external service configuration required.
|
|
|
|
## Next Phase Readiness
|
|
|
|
- Both model classes verified correct through unit tests
|
|
- Supabase mock pattern established — Phase 2 service tests can reuse `makeSupabaseChain()` helper
|
|
- INFR-04 compliance confirmed: tests verify `getSupabaseServiceClient` is called per-method invocation
|
|
- Ready for Phase 2: monitoring services that depend on HealthCheckModel and AlertEventModel
|
|
|
|
---
|
|
*Phase: 01-data-foundation*
|
|
*Completed: 2026-02-24*
|