diff --git a/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.test.tsx b/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.test.tsx index 7240686a..dc72b72a 100644 --- a/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.test.tsx +++ b/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.test.tsx @@ -9,13 +9,17 @@ vi.mock("@/i18n/provider.js", () => ({ describe("DaysOfWeekStrip", () => { it("renders 7 day boxes", () => { - render(); + render(); const boxes = screen.getAllByTestId(/^day-of-week-\d$/); expect(boxes).toHaveLength(7); }); - it("marks first 3 active, last 4 inactive for '1110000'", () => { - render(); + // Real API shape: `daysOfWeek.flight` is a STRING OF DIGITS where each + // character is the ISO weekday number of an active day (1=Mon..7=Sun). + // E.g. "156" means Mon + Fri + Sat are operating; "1234567" = every day. + + it("marks Mon/Tue/Wed active, Thu-Sun inactive for '123'", () => { + render(); expect(screen.getByTestId("day-of-week-0").className).not.toMatch(/--inactive/); expect(screen.getByTestId("day-of-week-1").className).not.toMatch(/--inactive/); expect(screen.getByTestId("day-of-week-2").className).not.toMatch(/--inactive/); @@ -23,57 +27,52 @@ describe("DaysOfWeekStrip", () => { expect(screen.getByTestId("day-of-week-6").className).toMatch(/--inactive/); }); - it("marks all active for '1111111'", () => { - render(); + it("marks all active for '1234567'", () => { + render(); for (let i = 0; i < 7; i++) { expect(screen.getByTestId(`day-of-week-${i}`).className).not.toMatch(/--inactive/); } }); - it("marks all inactive for '0000000'", () => { - render(); + it("marks all inactive for ''", () => { + render(); for (let i = 0; i < 7; i++) { expect(screen.getByTestId(`day-of-week-${i}`).className).toMatch(/--inactive/); } }); it("renders DAYS.1 through DAYS.7 labels in order", () => { - render(); + render(); expect(screen.getByTestId("day-of-week-0").textContent).toContain("DAYS.1"); expect(screen.getByTestId("day-of-week-6").textContent).toContain("DAYS.7"); }); - // TZ §4.1.16.8: position 0 = Monday (first ISO weekday), position 6 = Sunday - // Verify the Mon/Wed/Fri pattern used by typical schedule flights ("Пн Ср Пт" = "1010100") - it("Mon/Wed/Fri pattern: positions 0,2,4 active; 1,3,5,6 inactive", () => { - render(); - // Active: Mon(0), Wed(2), Fri(4) + // Real-world: SU 6188 returns "156" → Mon, Fri, Sat operating. + it("Mon/Fri/Sat pattern '156': positions 0,4,5 active; 1,2,3,6 inactive", () => { + render(); expect(screen.getByTestId("day-of-week-0").className).not.toMatch(/--inactive/); - expect(screen.getByTestId("day-of-week-2").className).not.toMatch(/--inactive/); expect(screen.getByTestId("day-of-week-4").className).not.toMatch(/--inactive/); - // Inactive: Tue(1), Thu(3), Sat(5), Sun(6) + expect(screen.getByTestId("day-of-week-5").className).not.toMatch(/--inactive/); expect(screen.getByTestId("day-of-week-1").className).toMatch(/--inactive/); + expect(screen.getByTestId("day-of-week-2").className).toMatch(/--inactive/); expect(screen.getByTestId("day-of-week-3").className).toMatch(/--inactive/); - expect(screen.getByTestId("day-of-week-5").className).toMatch(/--inactive/); expect(screen.getByTestId("day-of-week-6").className).toMatch(/--inactive/); }); - // TZ §4.1.16.8: Sat/Sun only ("0000011") - it("weekend-only pattern: positions 5,6 active; 0-4 inactive", () => { - render(); - for (let i = 0; i < 5; i++) { - expect(screen.getByTestId(`day-of-week-${i}`).className).toMatch(/--inactive/); - } - expect(screen.getByTestId("day-of-week-5").className).not.toMatch(/--inactive/); - expect(screen.getByTestId("day-of-week-6").className).not.toMatch(/--inactive/); - }); - - // TZ §4.1.16.8: single-day operation (Tuesday only = "0100000") - it("Tuesday-only pattern: position 1 active; all others inactive", () => { - render(); + it("Tue-only '2': position 1 active; all others inactive", () => { + render(); expect(screen.getByTestId("day-of-week-1").className).not.toMatch(/--inactive/); for (const i of [0, 2, 3, 4, 5, 6]) { expect(screen.getByTestId(`day-of-week-${i}`).className).toMatch(/--inactive/); } }); + + it("ignores non-digit characters and out-of-range digits", () => { + render(); + expect(screen.getByTestId("day-of-week-0").className).not.toMatch(/--inactive/); + expect(screen.getByTestId("day-of-week-6").className).not.toMatch(/--inactive/); + for (const i of [1, 2, 3, 4, 5]) { + expect(screen.getByTestId(`day-of-week-${i}`).className).toMatch(/--inactive/); + } + }); }); diff --git a/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.tsx b/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.tsx index 78f109ea..5707fb95 100644 --- a/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.tsx +++ b/src/features/online-board/components/FlightSchedule/DaysOfWeekStrip.tsx @@ -2,6 +2,14 @@ import type { FC } from "react"; import { useTranslation } from "@/i18n/provider.js"; export interface DaysOfWeekStripProps { + /** + * Operating-days indicator from the API. The `daysOfWeek.flight` field + * is a STRING OF DIGITS (1=Mon..7=Sun), one digit per active day — + * NOT a 7-char bitmask. Examples: `"156"` = Mon/Fri/Sat; + * `"1234567"` = every day; `""` = none. Anything else (alternative + * shape, missing field) falls through to "all inactive" so the badge + * row still renders without crashing. + */ flightBitString: string; } @@ -9,11 +17,19 @@ const DAY_INDEXES = [0, 1, 2, 3, 4, 5, 6] as const; export const DaysOfWeekStrip: FC = ({ flightBitString }) => { const { t } = useTranslation(); + // Build a Set from the API string. Each character is a + // 1-based ISO weekday digit ("1" → Mon, …, "7" → Sun). + const activeDays = new Set(); + for (const ch of flightBitString) { + const n = Number(ch); + if (Number.isInteger(n) && n >= 1 && n <= 7) activeDays.add(n); + } return (
{DAY_INDEXES.map((i) => { - const isActive = flightBitString[i] === "1"; + const dayNumber = i + 1; + const isActive = activeDays.has(dayNumber); const className = isActive ? "day" : "day day--inactive"; return ( = ({ flightBitString }) = className={className} data-testid={`day-of-week-${i}`} > - {t(`DAYS.${i + 1}`)} + {t(`DAYS.${dayNumber}`)} ); })} diff --git a/src/features/online-board/components/FlightSchedule/FlightSchedule.test.tsx b/src/features/online-board/components/FlightSchedule/FlightSchedule.test.tsx index db547156..b2befc3f 100644 --- a/src/features/online-board/components/FlightSchedule/FlightSchedule.test.tsx +++ b/src/features/online-board/components/FlightSchedule/FlightSchedule.test.tsx @@ -159,10 +159,10 @@ describe("FlightSchedule", () => { }); // TZ §4.1.16.8: uses daysOfWeek.flight (schedule days), not .current (today's active day) - it("uses daysOfWeek.flight bitstring for active days, not .current", () => { - // current = daily, flight = Mon/Wed/Fri only ("1010100") + it("uses daysOfWeek.flight digit-list for active days, not .current", () => { + // current = daily ("1234567"), flight = Mon/Wed/Fri only ("135") const flight = makeFlight({ - daysOfWeek: { current: "1111111", flight: "1010100" }, + daysOfWeek: { current: "1234567", flight: "135" }, }); render(); // Mon(0), Wed(2), Fri(4) should be active