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(); 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(); 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(); 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 }; }