93f49cddae
Tests cover start page, search, and details SEO builders plus Flight/ItemList JSON-LD schema generation for schedule pages.
165 lines
4.9 KiB
TypeScript
165 lines
4.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { Flight, ItemList } from "schema-dts";
|
|
import { buildScheduleFlightJsonLd, buildScheduleFlightListJsonLd } from "./json-ld.js";
|
|
import type { ISimpleFlight } from "./types.js";
|
|
|
|
function makeDirectFlight(overrides: Partial<{
|
|
carrier: string;
|
|
flightNumber: string;
|
|
depCode: string;
|
|
depAirport: string;
|
|
arrCode: string;
|
|
arrAirport: string;
|
|
depTime: string;
|
|
arrTime: string;
|
|
}> = {}): ISimpleFlight {
|
|
return {
|
|
id: "test-schedule-1",
|
|
routeType: "Direct",
|
|
flightId: {
|
|
carrier: overrides.carrier ?? "SU",
|
|
flightNumber: overrides.flightNumber ?? "0012",
|
|
suffix: "",
|
|
date: "20220527",
|
|
},
|
|
flyingTime: "1h 30m",
|
|
operatingBy: {},
|
|
status: "Scheduled",
|
|
leg: {
|
|
index: 0,
|
|
status: "Scheduled",
|
|
flyingTime: "1h 30m",
|
|
updated: "2022-05-27T10:00:00Z",
|
|
dayChange: 0,
|
|
equipment: { name: "Airbus A320", code: "320" },
|
|
flags: { checkinAvailable: false, returnToAirport: false, routeChanged: false },
|
|
operatingBy: {},
|
|
departure: {
|
|
scheduled: {
|
|
airport: overrides.depAirport ?? "Sheremetyevo",
|
|
airportCode: overrides.depCode ?? "SVO",
|
|
city: "Moscow",
|
|
cityCode: "MOW",
|
|
countryCode: "RU",
|
|
},
|
|
checkingStatus: "closed",
|
|
times: {
|
|
scheduledDeparture: {
|
|
dayChange: { value: 0, title: "" },
|
|
local: overrides.depTime ?? "2022-05-27T10:00:00",
|
|
localTime: "10:00",
|
|
tzOffset: 3,
|
|
utc: "2022-05-27T07:00:00Z",
|
|
},
|
|
},
|
|
},
|
|
arrival: {
|
|
scheduled: {
|
|
airport: overrides.arrAirport ?? "Pulkovo",
|
|
airportCode: overrides.arrCode ?? "LED",
|
|
city: "Saint Petersburg",
|
|
cityCode: "LED",
|
|
countryCode: "RU",
|
|
},
|
|
times: {
|
|
scheduledArrival: {
|
|
dayChange: { value: 0, title: "" },
|
|
local: overrides.arrTime ?? "2022-05-27T11:30:00",
|
|
localTime: "11:30",
|
|
tzOffset: 3,
|
|
utc: "2022-05-27T08:30:00Z",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
describe("buildScheduleFlightJsonLd", () => {
|
|
it("returns a Flight schema with correct @type", () => {
|
|
const flight = makeDirectFlight();
|
|
const result = buildScheduleFlightJsonLd(flight);
|
|
|
|
expect(result["@type"]).toBe("Flight");
|
|
});
|
|
|
|
it("sets flightNumber in IATA format", () => {
|
|
const flight = makeDirectFlight({ carrier: "SU", flightNumber: "0012" });
|
|
const result = buildScheduleFlightJsonLd(flight);
|
|
|
|
expect(result.flightNumber).toBe("SU0012");
|
|
});
|
|
|
|
it("maps departure airport", () => {
|
|
const flight = makeDirectFlight({ depCode: "SVO", depAirport: "Sheremetyevo" });
|
|
const result = buildScheduleFlightJsonLd(flight);
|
|
|
|
expect(result.departureAirport).toEqual({
|
|
"@type": "Airport",
|
|
iataCode: "SVO",
|
|
name: "Sheremetyevo",
|
|
});
|
|
});
|
|
|
|
it("maps arrival airport", () => {
|
|
const flight = makeDirectFlight({ arrCode: "LED", arrAirport: "Pulkovo" });
|
|
const result = buildScheduleFlightJsonLd(flight);
|
|
|
|
expect(result.arrivalAirport).toEqual({
|
|
"@type": "Airport",
|
|
iataCode: "LED",
|
|
name: "Pulkovo",
|
|
});
|
|
});
|
|
|
|
it("is type-compatible with schema-dts Flight", () => {
|
|
const flight = makeDirectFlight();
|
|
const result = buildScheduleFlightJsonLd(flight);
|
|
const _typed: Flight = result;
|
|
expect(_typed["@type"]).toBe("Flight");
|
|
});
|
|
});
|
|
|
|
describe("buildScheduleFlightListJsonLd", () => {
|
|
it("returns an ItemList schema", () => {
|
|
const flights = [makeDirectFlight()];
|
|
const result = buildScheduleFlightListJsonLd(flights, "Schedule SVO to LED");
|
|
|
|
expect(result["@type"]).toBe("ItemList");
|
|
});
|
|
|
|
it("sets the description", () => {
|
|
const flights = [makeDirectFlight()];
|
|
const result = buildScheduleFlightListJsonLd(flights, "Schedule SVO to LED");
|
|
|
|
expect(result.description).toBe("Schedule SVO to LED");
|
|
});
|
|
|
|
it("wraps each flight as a ListItem with position", () => {
|
|
const flights = [
|
|
makeDirectFlight({ carrier: "SU", flightNumber: "0012" }),
|
|
makeDirectFlight({ carrier: "SU", flightNumber: "0013" }),
|
|
];
|
|
const result = buildScheduleFlightListJsonLd(flights, "Flights");
|
|
const items = result.itemListElement as unknown as Array<{ position: number }>;
|
|
|
|
expect(Array.isArray(items)).toBe(true);
|
|
expect(items).toHaveLength(2);
|
|
expect(items[0]).toHaveProperty("position", 1);
|
|
expect(items[1]).toHaveProperty("position", 2);
|
|
});
|
|
|
|
it("handles empty flight list", () => {
|
|
const result = buildScheduleFlightListJsonLd([], "No flights");
|
|
|
|
expect(result["@type"]).toBe("ItemList");
|
|
expect(result.itemListElement).toEqual([]);
|
|
});
|
|
|
|
it("is type-compatible with schema-dts ItemList", () => {
|
|
const result = buildScheduleFlightListJsonLd([], "test");
|
|
const _typed: ItemList = result;
|
|
expect(_typed["@type"]).toBe("ItemList");
|
|
});
|
|
});
|