import assert from "node:assert/strict"; import { completedAtFromOnboardingPayload, isValidOnboardingLedgerEvent, normalizeOnboardingEventType, } from "../src/events/onboarding-ledger.js"; const now = "2026-06-28T00:00:00.000Z"; assert.equal(normalizeOnboardingEventType("user_onboarding_completed"), "user.onboarding.completed"); assert.equal( isValidOnboardingLedgerEvent({ type: "onboarding.completed", payload: {}, }), true, "explicit completion event should satisfy onboarding status", ); assert.equal( isValidOnboardingLedgerEvent({ type: "user.onboarding.completed", payload: {}, }), true, "user completion event should satisfy onboarding status", ); assert.equal( isValidOnboardingLedgerEvent({ type: "profile.onboarding.completed", payload: {}, }), true, "profile completion event should satisfy onboarding status", ); assert.equal( isValidOnboardingLedgerEvent({ type: "onboarding.snapshot.saved", payload: { onboarding: { current_step: 2 } }, }), false, "intermediate snapshots must not bypass onboarding", ); assert.equal( isValidOnboardingLedgerEvent({ type: "onboarding.snapshot.saved", payload: { onboarding: { completed_at: now } }, }), true, "completion snapshots should satisfy onboarding status", ); assert.equal( completedAtFromOnboardingPayload({ preferences: { onboarding: { completed_at: now } }, }), now, "completion timestamp should be extracted from preferences snapshot", ); assert.equal( completedAtFromOnboardingPayload({ completedAt: "not-a-date", })?.endsWith("Z"), true, "invalid completion timestamps should normalize to a valid ISO timestamp", ); // ── Regression: underscore completion aliases must be valid (reset deletes them) ── // The reset only reopens the gate if EVERY alias form that isValidOnboardingLedgerEvent // accepts is also in the reset delete scope. Pin both sides agree per alias. for (const underscore of ["onboarding_completed", "user_onboarding_completed", "profile_onboarding_completed"]) { const dotted = normalizeOnboardingEventType(underscore); assert.equal( isValidOnboardingLedgerEvent({ type: underscore, payload: {} }), true, `${underscore} should satisfy onboarding status (normalized to ${dotted})`, ); } // ── Regression: completedAtFromOnboardingPayload paths mirrored by reset SQL ── // resetOnboardingLedger's jsonb predicate checks top-level completed_at/completedAt // and onboarding.completed_at/completedAt. Pin that the JS helper (used for status // validity) agrees a snapshot carrying any of these is a completion snapshot. for (const [label, payload] of [ ["top-level completed_at", { completed_at: now }], ["top-level completedAt", { completedAt: now }], ["onboarding.completed_at", { onboarding: { completed_at: now } }], ["onboarding.completedAt", { onboarding: { completedAt: now } }], ] as const) { assert.equal( completedAtFromOnboardingPayload(payload), now, `completion timestamp extracted from ${label}`, ); assert.equal( isValidOnboardingLedgerEvent({ type: "onboarding.snapshot.saved", payload }), true, `snapshot with ${label} is a completion snapshot`, ); } // ── Regression: intermediate snapshots (no completion marker) stay invalid ── assert.equal( completedAtFromOnboardingPayload({ onboarding: { current_step: 2 } }), undefined, "intermediate snapshot has no completion timestamp", ); console.log("onboarding-ledger tests passed"); process.exit(0);