diff --git a/src/shared/state/crossSectionNavigation.test.ts b/src/shared/state/crossSectionNavigation.test.ts index da943639..a50cc5cc 100644 --- a/src/shared/state/crossSectionNavigation.test.ts +++ b/src/shared/state/crossSectionNavigation.test.ts @@ -186,10 +186,11 @@ describe("4.1.8-R1/R2: projectBoardToSchedule", () => { }); describe("4.1.8-R1/R2: projectScheduleToBoard", () => { - it("carries departure + arrival, sets date=today, clears time", () => { + it("carries departure + arrival, preserves in-window dateFrom, clears time", () => { + // Clock frozen at 2026-05-15. dateFrom = 2026-05-14 (yesterday, within Board window [-1,+14]) const sched: ScheduleFilterSnapshot = { mode: "route", departure: "MOW", arrival: "LED", - dateFrom: "20260511", dateTo: "20260517", + dateFrom: "20260514", dateTo: "20260520", timeFrom: "0600", timeTo: "2200", onlyDirect: true, showReturn: false, searchExecuted: true, @@ -197,12 +198,38 @@ describe("4.1.8-R1/R2: projectScheduleToBoard", () => { const p = projectScheduleToBoard(sched); expect(p.departure).toBe("MOW"); expect(p.arrival).toBe("LED"); - expect(p.date).toBe("20260515"); // today (frozen clock) + expect(p.date).toBe("20260514"); // in-window → preserved expect(p.timeFrom).toBe("0000"); expect(p.timeTo).toBe("2400"); expect(p.searchExecuted).toBe(false); }); + it("4.1.8-R2: preserves dateFrom when schedule dateFrom is today (in-window)", () => { + // Clock frozen at 2026-05-15. dateFrom = today is definitely in window. + const sched: ScheduleFilterSnapshot = { + mode: "route", departure: "MOW", arrival: "LED", + dateFrom: "20260515", dateTo: "20260521", + timeFrom: "0000", timeTo: "2400", + onlyDirect: false, showReturn: false, + searchExecuted: true, + }; + const p = projectScheduleToBoard(sched); + expect(p.date).toBe("20260515"); // in-window → preserved (also equals today) + }); + + it("4.1.8-R2: preserves dateFrom when schedule dateFrom is within +14 days", () => { + // Clock frozen at 2026-05-15. +7 days = 2026-05-22, within the +14 window. + const sched: ScheduleFilterSnapshot = { + mode: "route", departure: "MOW", arrival: "LED", + dateFrom: "20260522", dateTo: "20260528", + timeFrom: "0000", timeTo: "2400", + onlyDirect: false, showReturn: false, + searchExecuted: true, + }; + const p = projectScheduleToBoard(sched); + expect(p.date).toBe("20260522"); // in-window → preserved + }); + it("does not carry optional departure when schedule has only arrival", () => { const p = projectScheduleToBoard({ mode: "route", arrival: "LED", @@ -226,7 +253,7 @@ describe("4.1.8-R1/R2: projectScheduleToBoard", () => { expect(p.mode).toBe("route"); }); - it("4.1.8-R2: projectScheduleToBoard clamps to today when schedule dateFrom is > board window", () => { + it("4.1.8-R2: projectScheduleToBoard clamps to today when schedule dateFrom is outside board window (future)", () => { // Clock frozen at 2026-05-15. Schedule dateFrom = 2026-07-01 (47 days forward, outside board's +14 window) const schedule: ScheduleFilterSnapshot = { mode: "route", @@ -244,8 +271,8 @@ describe("4.1.8-R1/R2: projectScheduleToBoard", () => { expect(projected.date).toBe("20260515"); // clamps to today }); - it("4.1.8-R2: projectScheduleToBoard uses today even when schedule dateFrom is before today-1", () => { - // Schedule dateFrom in the distant past + it("4.1.8-R2: projectScheduleToBoard clamps to today when schedule dateFrom is outside board window (past)", () => { + // Schedule dateFrom in the distant past, outside the -1 day board window const schedule: ScheduleFilterSnapshot = { mode: "route", departure: "MOW", diff --git a/src/shared/state/crossSectionNavigation.ts b/src/shared/state/crossSectionNavigation.ts index e1a83400..05b08f68 100644 --- a/src/shared/state/crossSectionNavigation.ts +++ b/src/shared/state/crossSectionNavigation.ts @@ -6,6 +6,8 @@ * projected from / to Board or Schedule (per TZ §4.1.1 ¶12). */ +import { isInBoardWindow } from "@/shared/dateWindow.js"; + export interface BoardFilterSnapshot { mode: "route" | "flight-number" | "departure" | "arrival"; departure?: string; @@ -97,13 +99,20 @@ export function projectBoardToSchedule(b: BoardFilterSnapshot): ScheduleFilterSn }; } -/** TZ Table 10: Schedule → Board projection. Preserves cities + date=today. */ +/** + * TZ Table 10: Schedule → Board projection. Preserves cities. + * Date: use schedule's dateFrom if it falls within the Board window + * ([-1, +14] days from today); otherwise clamp to today. This preserves + * user intent when the schedule date is near-term but avoids showing a + * date the Board cannot display. + */ export function projectScheduleToBoard(s: ScheduleFilterSnapshot): BoardFilterSnapshot { + const date = isInBoardWindow(s.dateFrom) ? s.dateFrom : todayYyyymmdd(); return { mode: "route", ...(s.departure ? { departure: s.departure } : {}), ...(s.arrival ? { arrival: s.arrival } : {}), - date: todayYyyymmdd(), + date, timeFrom: "0000", timeTo: "2400", searchExecuted: false,