|
|
|
@@ -471,3 +471,185 @@ describe("4.1.13.3 — Collapsed row state", () => {
|
|
|
|
|
expect(document.querySelector("[data-testid='flight-card-expanded']")).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// §4.1.13.4 — Expanded representation (Table 25 / §4.1.13.4.3)
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function makeTransitionItem(status: "InProgress" | "Finished" | "Expected" = "InProgress") {
|
|
|
|
|
return {
|
|
|
|
|
start: {
|
|
|
|
|
dayChange: { value: 0, title: "" },
|
|
|
|
|
local: "2026-04-15T09:00:00+03:00",
|
|
|
|
|
localTime: "09:00",
|
|
|
|
|
tzOffset: 3,
|
|
|
|
|
utc: "2026-04-15T06:00:00Z",
|
|
|
|
|
},
|
|
|
|
|
end: {
|
|
|
|
|
dayChange: { value: 0, title: "" },
|
|
|
|
|
local: "2026-04-15T09:30:00+03:00",
|
|
|
|
|
localTime: "09:30",
|
|
|
|
|
tzOffset: 3,
|
|
|
|
|
utc: "2026-04-15T06:30:00Z",
|
|
|
|
|
},
|
|
|
|
|
status,
|
|
|
|
|
isActual: true,
|
|
|
|
|
} as const;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Build a full ISimpleFlight with boarding transition + gate/dispatch override.
|
|
|
|
|
*/
|
|
|
|
|
function makeFlightWithBoarding(opts: {
|
|
|
|
|
gate?: string;
|
|
|
|
|
dispatch?: string;
|
|
|
|
|
bagBelt?: string;
|
|
|
|
|
direction?: "departure" | "arrival";
|
|
|
|
|
}): ISimpleFlight {
|
|
|
|
|
const base = makeFlight({});
|
|
|
|
|
const transition = makeTransitionItem();
|
|
|
|
|
// `makeFlight` always returns a Direct flight so `leg` is safe to access
|
|
|
|
|
const baseLeg = (base as ReturnType<typeof makeFlight> & { leg: ReturnType<typeof makeLeg> }).leg;
|
|
|
|
|
return {
|
|
|
|
|
...base,
|
|
|
|
|
leg: {
|
|
|
|
|
...baseLeg,
|
|
|
|
|
transition: {
|
|
|
|
|
boarding: transition,
|
|
|
|
|
deboarding: transition,
|
|
|
|
|
},
|
|
|
|
|
departure: {
|
|
|
|
|
...baseLeg.departure,
|
|
|
|
|
gate: opts.gate,
|
|
|
|
|
dispatch: opts.dispatch,
|
|
|
|
|
},
|
|
|
|
|
arrival: {
|
|
|
|
|
...baseLeg.arrival,
|
|
|
|
|
gate: opts.gate,
|
|
|
|
|
bagBelt: opts.bagBelt,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
} as unknown as ISimpleFlight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
describe("4.1.13.4 — Expanded row content (TZ §4.1.13.4.3)", () => {
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: expanded row shows scheduled departure time with label", () => {
|
|
|
|
|
const flight = makeFlight({ depLocal: "2026-04-15T10:00:00+03:00" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} />);
|
|
|
|
|
const expanded = screen.getByTestId("flight-card-expanded");
|
|
|
|
|
// Scheduled time in expanded body
|
|
|
|
|
const text = expanded.textContent ?? "";
|
|
|
|
|
expect(text).toContain("10:00");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: expanded row shows scheduled arrival time with label", () => {
|
|
|
|
|
const flight = makeFlight({ arrLocal: "2026-04-15T12:30:00+03:00" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} />);
|
|
|
|
|
const expanded = screen.getByTestId("flight-card-expanded");
|
|
|
|
|
expect(expanded.textContent).toContain("12:30");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: expanded row shows actual departure time when available with SHARED.ACTUAL caption", () => {
|
|
|
|
|
const flight = makeFlight({
|
|
|
|
|
depLocal: "2026-04-15T10:00:00+03:00",
|
|
|
|
|
depActualLocal: "2026-04-15T11:15:00+03:00",
|
|
|
|
|
});
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} />);
|
|
|
|
|
const expanded = screen.getByTestId("flight-card-expanded");
|
|
|
|
|
// Actual time and caption key
|
|
|
|
|
expect(expanded.textContent).toContain("11:15");
|
|
|
|
|
expect(expanded.textContent).toContain("SHARED.ACTUAL");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: boarding row shows status + start + end times when transition present", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({});
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="departure" />);
|
|
|
|
|
const expanded = screen.getByTestId("flight-card-expanded");
|
|
|
|
|
// Label key
|
|
|
|
|
expect(expanded.textContent).toContain("DETAILS.BOARDING");
|
|
|
|
|
// Status key
|
|
|
|
|
expect(expanded.textContent).toContain("BOARDING-STATUSES.InProgress");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: deboarding row shown on arrival direction", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({});
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="arrival" />);
|
|
|
|
|
const expanded = screen.getByTestId("flight-card-expanded");
|
|
|
|
|
expect(expanded.textContent).toContain("DETAILS.DEBOARDING");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: boarding gate rendered when departure.gate is set (§4.1.13.4.3 Table 29)", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({ gate: "B12", direction: "departure" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="departure" />);
|
|
|
|
|
expect(screen.getByTestId("transition-gate")).toBeTruthy();
|
|
|
|
|
expect(screen.getByTestId("transition-gate").textContent).toContain("B12");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: gate is NOT rendered when gate is absent", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({});
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="departure" />);
|
|
|
|
|
expect(document.querySelector("[data-testid='transition-gate']")).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: dispatch (трап/автобус) rendered when departure.dispatch is set (§4.1.13.4.3 Table 29)", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({ dispatch: "Bridge" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="departure" />);
|
|
|
|
|
expect(screen.getByTestId("transition-dispatch")).toBeTruthy();
|
|
|
|
|
// The dispatch value goes through t("DISPATCH.Bridge") which returns "DISPATCH.Bridge" in mock
|
|
|
|
|
expect(screen.getByTestId("transition-dispatch").textContent).toContain("Bridge");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: dispatch NOT rendered when departure.dispatch absent", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({});
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="departure" />);
|
|
|
|
|
expect(document.querySelector("[data-testid='transition-dispatch']")).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: baggage belt rendered for deboarding (arrival) when arrival.bagBelt is set (§4.1.13.4.3 Table 30)", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({ bagBelt: "3", direction: "arrival" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="arrival" />);
|
|
|
|
|
expect(screen.getByTestId("transition-bag-belt")).toBeTruthy();
|
|
|
|
|
expect(screen.getByTestId("transition-bag-belt").textContent).toContain("3");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: baggage belt NOT rendered for departure direction", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({ bagBelt: "3" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="departure" />);
|
|
|
|
|
expect(document.querySelector("[data-testid='transition-bag-belt']")).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: arrival gate rendered in deboarding row when arrival.gate is set", () => {
|
|
|
|
|
const flight = makeFlightWithBoarding({ gate: "C7" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} direction="arrival" />);
|
|
|
|
|
expect(screen.getByTestId("transition-gate")).toBeTruthy();
|
|
|
|
|
expect(screen.getByTestId("transition-gate").textContent).toContain("C7");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: share button always present in expanded actions row", () => {
|
|
|
|
|
render(<FlightCard flight={makeFlight({})} expandable initialExpanded onViewDetails={() => {}} />);
|
|
|
|
|
expect(screen.getByTestId("flight-share-button")).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: Details button present in expanded actions row", () => {
|
|
|
|
|
render(<FlightCard flight={makeFlight({})} expandable initialExpanded onViewDetails={() => {}} />);
|
|
|
|
|
expect(screen.getByTestId("flight-details-button")).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: aircraft type shown under operator column when expanded (TZ Table 25 C3)", () => {
|
|
|
|
|
const flight = makeFlight({ aircraftTitle: "Airbus A320" });
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} />);
|
|
|
|
|
const number = screen.getByTestId("flight-carrier-number");
|
|
|
|
|
// Aircraft name rendered inside the number/header column when expanded
|
|
|
|
|
expect(number.textContent).toContain("Airbus A320");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("4.1.13.4-R: no transition row shown when no transition data", () => {
|
|
|
|
|
const flight = makeFlight({});
|
|
|
|
|
render(<FlightCard flight={flight} expandable initialExpanded onViewDetails={() => {}} />);
|
|
|
|
|
const expanded = screen.getByTestId("flight-card-expanded");
|
|
|
|
|
// Neither boarding nor deboarding label should appear when transition is absent
|
|
|
|
|
expect(expanded.textContent).not.toContain("DETAILS.BOARDING");
|
|
|
|
|
expect(expanded.textContent).not.toContain("DETAILS.DEBOARDING");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|