/* Unit tests for eligibilitypbt — eligibility.pbt covering its documented public contract and regression-sensitive edge cases. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1311: Compass header sweep — declares the eligibility.pbt suite's contract for test-file scaffold coverage. */ import { test, expect } from "vitest"; import fc from "fast-check"; import { normalizeSegment, matchesRecord, countMatching, buildRecordIndex, countMatchingIndexed, pathKey, enumerateCandidateTuples, buildEligibilityMatrix, type AxisFieldMap, } from "../eligibility.ts"; import type { SurfaceAxis, SurfaceRecord, EligibilityPolicy } from "../types.ts"; const SEGMENT_PATTERN = /^[a-z0-9-]+$/; const defaultPolicy: EligibilityPolicy = { minRecordsPerDepth: { 0: 1, 1: 1, 2: 1 }, noindexBelowPerDepth: {}, redirectPolicy: "nearest-ancestor", trailingSlash: true, segmentPattern: SEGMENT_PATTERN, }; test("PBT: normalizeSegment is idempotent", () => { fc.assert( fc.property( fc.stringMatching(SEGMENT_PATTERN).map((s) => s.replace(/_/g, "-")), (s) => { const once = normalizeSegment(s, SEGMENT_PATTERN); const twice = normalizeSegment(once, SEGMENT_PATTERN); expect(twice).toBe(once); }, ), ); }); test("PBT: countMatchingIndexed matches countMatching for any tuple", () => { const _axes: SurfaceAxis[] = [ { id: "trade", universe: ["elektriker", "friseur", "baker"] }, { id: "region", universe: ["berlin", "hamburg", "munich"] }, ]; const axisFieldMap: AxisFieldMap = { trade: "trade", region: "region" }; const records: SurfaceRecord[] = [ { trade: "elektriker", region: "berlin", status: "active" }, { trade: "elektriker", region: "hamburg", status: "active" }, { trade: "friseur", region: "berlin", status: "active" }, { trade: "friseur", region: "hamburg", status: "archived" }, { trade: "baker", region: "munich", status: "active" }, ]; const index = buildRecordIndex(records, axisFieldMap); const tupleArb = fc.record({ trade: fc.constantFrom("elektriker", "friseur", "baker", undefined), region: fc.constantFrom("berlin", "hamburg", "munich", undefined), }); fc.assert( fc.property(tupleArb, (tuple) => { const linear = countMatching(records, tuple, axisFieldMap); const indexed = countMatchingIndexed(tuple, axisFieldMap, index); expect(indexed).toBe(linear); }), ); }); test("PBT: pathKey is deterministic for the same input", () => { const axisOrder = ["a", "b", "c"]; const tupleArb = fc.record({ a: fc.constantFrom("x", "y", undefined), b: fc.constantFrom("z", "w", undefined), c: fc.constantFrom("q", "r", undefined), }); const depthArb = fc.integer({ min: 0, max: 3 }); fc.assert( fc.property(tupleArb, depthArb, (tuple, depth) => { const k1 = pathKey(depth, tuple, axisOrder); const k2 = pathKey(depth, tuple, axisOrder); expect(k1).toBe(k2); }), ); }); test("PBT: enumerateCandidateTuples count equals product of universe sizes", () => { const universeArb = fc.array(fc.stringMatching(SEGMENT_PATTERN), { minLength: 1, maxLength: 5 }); const axesArb = fc.array( fc.record({ id: fc.stringMatching(SEGMENT_PATTERN), universe: universeArb }), { minLength: 1, maxLength: 3 }, ); fc.assert( fc.property(axesArb, (axes) => { const depth = axes.length; const tuples = [...enumerateCandidateTuples(axes, depth)]; const expected = axes.reduce((acc, a) => acc * a.universe.length, 1); expect(tuples).toHaveLength(expected); }), ); }); test("PBT: buildEligibilityMatrix entries are ordered by depth", () => { const axes: SurfaceAxis[] = [ { id: "trade", universe: ["elektriker", "friseur"] }, { id: "region", universe: ["berlin", "hamburg"] }, ]; const axisFieldMap: AxisFieldMap = { trade: "trade", region: "region" }; const records: SurfaceRecord[] = [ { trade: "elektriker", region: "berlin", status: "active" }, { trade: "friseur", region: "hamburg", status: "active" }, ]; fc.assert( fc.property(fc.boolean(), (forceGate) => { const matrix = buildEligibilityMatrix(axes, axisFieldMap, records, defaultPolicy, { forceNonIndexableDepths: forceGate ? [2] : [], }); for (let i = 1; i < matrix.entries.length; i++) { expect(matrix.entries[i]!.depth).toBeGreaterThanOrEqual(matrix.entries[i - 1]!.depth); } }), ); }); test("PBT: matchesRecord with empty tuple always returns true", () => { const recordArb: fc.Arbitrary = fc.record({ field: fc.string(), status: fc.constantFrom("active", "archived"), }); fc.assert( fc.property(recordArb, (record) => { expect(matchesRecord(record, {}, {})).toBe(true); }), ); });