143 lines
4.2 KiB
TypeScript
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
|
|
};
|
|
}
|