import { describe, it, expect } from "vitest"; import { parseScheduleRouteParams, buildScheduleRouteParams, parseScheduleUrl, buildScheduleUrl, type ScheduleParams, } from "./url"; // --------------------------------------------------------------------------- // parseScheduleRouteParams // --------------------------------------------------------------------------- describe("parseScheduleRouteParams", () => { it("parses route without time range or connections", () => { expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501")).toEqual({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", }); }); it("parses route with time range", () => { expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-06002200")).toEqual({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", }); }); it("parses route with connections only", () => { expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-C1")).toEqual({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 1, }); }); it("parses route with connections=0", () => { expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-C0")).toEqual({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 0, }); }); it("parses route with time range and connections", () => { expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-06002200-C0")).toEqual({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0, }); }); it("returns null for empty string", () => { expect(parseScheduleRouteParams("")).toBeNull(); }); it("returns null for insufficient segments", () => { expect(parseScheduleRouteParams("MOW-KUF-20220425")).toBeNull(); }); it("returns null for invalid dateFrom", () => { expect(parseScheduleRouteParams("MOW-KUF-2022-20220501")).toBeNull(); }); it("returns null for invalid dateTo", () => { expect(parseScheduleRouteParams("MOW-KUF-20220425-2022")).toBeNull(); }); }); // --------------------------------------------------------------------------- // buildScheduleRouteParams // --------------------------------------------------------------------------- describe("buildScheduleRouteParams", () => { it("builds route without time range or connections", () => { expect(buildScheduleRouteParams({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", })).toBe("MOW-KUF-20220425-20220501"); }); it("builds route with time range", () => { expect(buildScheduleRouteParams({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", })).toBe("MOW-KUF-20220425-20220501-06002200"); }); it("builds route with connections", () => { expect(buildScheduleRouteParams({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 1, })).toBe("MOW-KUF-20220425-20220501-C1"); }); it("builds route with connections=0", () => { expect(buildScheduleRouteParams({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 0, })).toBe("MOW-KUF-20220425-20220501-C0"); }); it("builds route with time range and connections", () => { expect(buildScheduleRouteParams({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0, })).toBe("MOW-KUF-20220425-20220501-06002200-C0"); }); it("omits time range when only timeFrom is provided", () => { expect(buildScheduleRouteParams({ departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", })).toBe("MOW-KUF-20220425-20220501"); }); }); // --------------------------------------------------------------------------- // parseScheduleUrl // --------------------------------------------------------------------------- describe("parseScheduleUrl", () => { it("parses start page (no trailing slash)", () => { expect(parseScheduleUrl("/schedule")).toEqual({ type: "start" }); }); it("parses start page (with trailing slash)", () => { expect(parseScheduleUrl("/schedule/")).toEqual({ type: "start" }); }); it("parses one-way route search", () => { expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501")).toEqual({ type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", }, }); }); it("parses one-way route with time range", () => { expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-06002200")).toEqual({ type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", }, }); }); it("parses one-way route with connections", () => { expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-C1")).toEqual({ type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 1, }, }); }); it("parses round-trip route search", () => { expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501/KUF-MOW-20220502-20220508")).toEqual({ type: "roundtrip", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", }, inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508", }, }); }); it("parses round-trip with time ranges", () => { expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-06002200/KUF-MOW-20220502-20220508-06002200")).toEqual({ type: "roundtrip", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", }, inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508", timeFrom: "0600", timeTo: "2200", }, }); }); it("parses round-trip with connections", () => { expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-C0/KUF-MOW-20220502-20220508-C0")).toEqual({ type: "roundtrip", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 0, }, inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508", connections: 0, }, }); }); it("parses single-flight details", () => { expect(parseScheduleUrl("/schedule/SU0012-20220527")).toEqual({ type: "details", flights: [ { carrier: "SU", flightNumber: "0012", date: "20220527" }, ], }); }); it("parses multi-flight details (connecting)", () => { expect(parseScheduleUrl("/schedule/SU0012-20220501/SU0013-20220507")).toEqual({ type: "details", flights: [ { carrier: "SU", flightNumber: "0012", date: "20220501" }, { carrier: "SU", flightNumber: "0013", date: "20220507" }, ], }); }); it("parses details with airport codes interleaved", () => { // Format: /{depCode}/{flight-date}/{arrCode}/{depCode2}/{flight2-date}/{arrCode2} // Airport codes (3-letter) are skipped, flight segments are parsed expect(parseScheduleUrl("/schedule/SVO/SU0012-20220501/LED/LED/SU0013-20220507/SVO")).toEqual({ type: "details", flights: [ { carrier: "SU", flightNumber: "0012", date: "20220501" }, { carrier: "SU", flightNumber: "0013", date: "20220507" }, ], }); }); it("returns null for empty string", () => { expect(parseScheduleUrl("")).toBeNull(); }); it("returns null for non-schedule path", () => { expect(parseScheduleUrl("/some/other/path")).toBeNull(); }); it("returns null for invalid route params", () => { expect(parseScheduleUrl("/schedule/route/")).toBeNull(); }); it("handles path without leading slash", () => { expect(parseScheduleUrl("schedule")).toEqual({ type: "start" }); }); it("handles path without leading slash for route", () => { expect(parseScheduleUrl("schedule/route/MOW-KUF-20220425-20220501")).toEqual({ type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", }, }); }); }); // --------------------------------------------------------------------------- // buildScheduleUrl // --------------------------------------------------------------------------- describe("buildScheduleUrl", () => { it("builds start page URL", () => { expect(buildScheduleUrl({ type: "start" })).toBe("schedule"); }); it("builds one-way route URL", () => { expect(buildScheduleUrl({ type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", }, })).toBe("schedule/route/MOW-KUF-20220425-20220501"); }); it("builds one-way route with time range and connections", () => { expect(buildScheduleUrl({ type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0, }, })).toBe("schedule/route/MOW-KUF-20220425-20220501-06002200-C0"); }); it("builds round-trip route URL", () => { expect(buildScheduleUrl({ type: "roundtrip", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", }, inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508", }, })).toBe("schedule/route/MOW-KUF-20220425-20220501/KUF-MOW-20220502-20220508"); }); it("builds round-trip with time ranges and connections", () => { expect(buildScheduleUrl({ type: "roundtrip", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0, }, inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508", timeFrom: "0600", timeTo: "2200", connections: 0, }, })).toBe("schedule/route/MOW-KUF-20220425-20220501-06002200-C0/KUF-MOW-20220502-20220508-06002200-C0"); }); it("builds single-flight details URL", () => { expect(buildScheduleUrl({ type: "details", flights: [ { carrier: "SU", flightNumber: "0012", date: "20220527" }, ], })).toBe("schedule/SU0012-20220527"); }); it("builds multi-flight details URL", () => { expect(buildScheduleUrl({ type: "details", flights: [ { carrier: "SU", flightNumber: "0012", date: "20220501" }, { carrier: "SU", flightNumber: "0013", date: "20220507" }, ], })).toBe("schedule/SU0012-20220501/SU0013-20220507"); }); }); // --------------------------------------------------------------------------- // Roundtrip tests: build -> parse -> build // --------------------------------------------------------------------------- describe("roundtrip: build -> parse -> build", () => { const cases: Array<{ name: string; params: ScheduleParams }> = [ { name: "start", params: { type: "start" } }, { name: "one-way route without extras", params: { type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501" }, }, }, { name: "one-way route with time range", params: { type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200" }, }, }, { name: "one-way route with connections", params: { type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 1 }, }, }, { name: "one-way route with time range and connections", params: { type: "route", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0 }, }, }, { name: "round-trip without extras", params: { type: "roundtrip", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501" }, inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508" }, }, }, { name: "round-trip with time range and connections", params: { type: "roundtrip", outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0 }, inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508", timeFrom: "0600", timeTo: "2200", connections: 0 }, }, }, { name: "single-flight details", params: { type: "details", flights: [{ carrier: "SU", flightNumber: "0012", date: "20220527" }], }, }, { name: "multi-flight details", params: { type: "details", flights: [ { carrier: "SU", flightNumber: "0012", date: "20220501" }, { carrier: "SU", flightNumber: "0013", date: "20220507" }, ], }, }, ]; for (const { name, params } of cases) { it(`roundtrips ${name}`, () => { const url = buildScheduleUrl(params); const parsed = parseScheduleUrl(url); expect(parsed).not.toBeNull(); if (parsed === null) return; const rebuilt = buildScheduleUrl(parsed); expect(rebuilt).toBe(url); }); } });