import { describe, expect, it } from "vitest"; import { activationLineDocumentY, deriveSectionState, isAtDocumentEnd, selectActiveSection, type SectionHeadingGeometry, } from "@/journey/section-controller"; const headings: readonly SectionHeadingGeometry[] = [ { id: "start", top: 100 }, { id: "profile", top: 350 }, { id: "experience", top: 700 }, { id: "infrastructure", top: 1100 }, { id: "selected-builds", top: 1500 }, { id: "additional-work", top: 1900 }, { id: "toolkit", top: 2300 }, { id: "contact", top: 2700 }, ]; describe("active section selection", () => { it("places the activation line at a literal 35 percent of the visual viewport", () => { expect( activationLineDocumentY({ scrollY: 200, visualViewportOffsetTop: 25, visualViewportHeight: 1000, }), ).toBe(575); }); it("forces document end within exactly two CSS pixels using current geometry", () => { expect( isAtDocumentEnd({ scrollY: 498, scrollHeight: 1000, visualViewportHeight: 500, }), ).toBe(true); expect( isAtDocumentEnd({ scrollY: 497.999, scrollHeight: 1000, visualViewportHeight: 500, }), ).toBe(false); expect( isAtDocumentEnd({ scrollY: 498, scrollHeight: 1200, visualViewportHeight: 500, }), ).toBe(false); }); it("keeps the first section before any heading reaches the activation line", () => { expect( selectActiveSection({ headings, activationY: 99, atDocumentEnd: false }), ).toBe("start"); }); it("selects the last heading at or above the literal 35 percent activation line", () => { expect( selectActiveSection({ headings, activationY: 699.999, atDocumentEnd: false, }), ).toBe("profile"); expect( selectActiveSection({ headings, activationY: 700, atDocumentEnd: false }), ).toBe("experience"); }); it("lets later document order win when heading positions are identical", () => { expect( selectActiveSection({ headings: [ { id: "start", top: 0 }, { id: "profile", top: 350 }, { id: "experience", top: 350 }, ], activationY: 350, atDocumentEnd: false, }), ).toBe("experience"); }); it("forces the final canonical section at document end", () => { expect( selectActiveSection({ headings, activationY: 1400, atDocumentEnd: true }), ).toBe("contact"); }); it("uses fresh late-growth geometry on every selection", () => { const grown = headings.map((heading) => heading.id === "experience" ? { ...heading, top: 900 } : heading, ); expect( selectActiveSection({ headings, activationY: 750, atDocumentEnd: false }), ).toBe("experience"); expect( selectActiveSection({ headings: grown, activationY: 750, atDocumentEnd: false, }), ).toBe("profile"); }); it("maps every canonical section to its chapter and arrival state", () => { expect([ deriveSectionState("start"), deriveSectionState("profile"), deriveSectionState("experience"), deriveSectionState("infrastructure"), deriveSectionState("selected-builds"), deriveSectionState("additional-work"), deriveSectionState("toolkit"), deriveSectionState("contact"), ]).toEqual([ { activeSectionId: "start", chapter: "deep-night", arrived: false }, { activeSectionId: "profile", chapter: "deep-night", arrived: false }, { activeSectionId: "experience", chapter: "systems", arrived: false }, { activeSectionId: "infrastructure", chapter: "infrastructure", arrived: false, }, { activeSectionId: "selected-builds", chapter: "builds", arrived: false }, { activeSectionId: "additional-work", chapter: "builds", arrived: false }, { activeSectionId: "toolkit", chapter: "pre-dawn", arrived: false }, { activeSectionId: "contact", chapter: "destination", arrived: true }, ]); }); });