Files
watermaps/apps/web/tests/voyage-plan.test.tsx
T
2026-07-24 11:29:24 +02:00

143 lines
4.2 KiB
TypeScript

import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen, within } from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";
import type { VoyagePlan as VoyagePlanResult } from "@watermaps/shared";
import { VoyagePlan } from "../src/components/VoyagePlan";
afterEach(() => cleanup());
describe("VoyagePlan", () => {
it("shows daily legs, waypoints, harbour supply and contacts", () => {
render(<VoyagePlan plan={plan()} />);
expect(screen.getByRole("heading", { name: "Etappenplan" })).toBeInTheDocument();
expect(screen.getByText(/2 Tage/)).toHaveTextContent("2 Tage · 72,5 sm · 12 h 05 min");
expect(screen.getByText("Start → Marina Mitte")).toBeInTheDocument();
expect(screen.getByText("Via: Schleuse Eins")).toBeInTheDocument();
const supply = screen.getByRole("list", { name: "Versorgung in Marina Mitte" });
expect(within(supply).getByLabelText("Strom: verfügbar")).toBeInTheDocument();
expect(within(supply).getByLabelText("Treibstoff: nicht verfügbar")).toBeInTheDocument();
expect(within(supply).getByLabelText("Entsorgung: unbekannt")).toBeInTheDocument();
expect(screen.getByRole("link", { name: "Hafen anrufen" })).toHaveAttribute("href", "tel:+4923811234");
expect(screen.getByRole("link", { name: "Website" })).toHaveAttribute("href", "https://hafen.example");
});
it("renders unconfirmed stops and planning warnings clearly", () => {
const result = plan();
result.legs[0] = {
...result.legs[0]!,
end: {
type: "route",
name: "Tagesziel auf der Route",
coordinate: { lat: 52, lon: 7.5 },
routeDistanceNm: 40,
distanceFromRouteNm: 0,
harbour: null
}
};
result.warnings = [
{
code: "NO_SUITABLE_HARBOUR",
severity: "caution",
message: "Kein geeigneter Hafen gefunden.",
day: 1
}
];
render(<VoyagePlan plan={result} />);
expect(screen.getByText("Kein bestätigter Liegeplatz")).toBeInTheDocument();
expect(screen.getByRole("list", { name: "Hinweise zum Etappenplan" })).toHaveTextContent(
"Kein geeigneter Hafen gefunden."
);
});
it("renders nothing until a plan exists", () => {
const { container } = render(<VoyagePlan plan={null} />);
expect(container).toBeEmptyDOMElement();
});
});
function plan(): VoyagePlanResult {
const start = {
type: "start" as const,
name: "Start",
coordinate: { lat: 52, lon: 7 },
routeDistanceNm: 0,
distanceFromRouteNm: 0,
harbour: null
};
const harbour = {
id: "marina-mitte",
name: "Marina Mitte",
kind: "marina" as const,
coordinate: { lat: 52, lon: 7.5 },
phone: "+49 (2381) 1234",
website: "hafen.example",
amenities: {
electricity: "available" as const,
water: "available" as const,
fuel: "unavailable" as const,
waste: "unknown" as const,
overnight: "available" as const
},
routeDistanceNm: 40,
distanceFromRouteNm: 0.25
};
const middle = {
type: "harbour" as const,
name: harbour.name,
coordinate: harbour.coordinate,
routeDistanceNm: harbour.routeDistanceNm,
distanceFromRouteNm: harbour.distanceFromRouteNm,
harbour
};
const destination = {
type: "destination" as const,
name: "Ziel",
coordinate: { lat: 52, lon: 8 },
routeDistanceNm: 72,
distanceFromRouteNm: 0,
harbour: null
};
return {
legs: [
{
day: 1,
start,
end: middle,
routeDistanceNm: 40,
distanceNm: 40.25,
durationHours: 6.708,
waypoints: [
{
id: "lock-one",
name: "Schleuse Eins",
coordinate: { lat: 52, lon: 7.2 },
sequence: 1,
routeDistanceNm: 12,
distanceFromRouteNm: 0
}
]
},
{
day: 2,
start: middle,
end: destination,
routeDistanceNm: 32,
distanceNm: 32.25,
durationHours: 5.375,
waypoints: []
}
],
orderedWaypoints: [],
warnings: [],
requiredAmenities: ["water", "overnight"],
totalRouteDistanceNm: 72,
totalDistanceNm: 72.5,
totalDurationHours: 12.0833,
maxCruisingDistancePerDayNm: 42
};
}