Bootssymbol hinzugefügt
Test and publish container images / test (push) Successful in 2m20s
Test and publish container images / publish (push) Failing after 4s

This commit is contained in:
BuTzZ
2026-07-26 12:31:49 +02:00
parent c9a20aacd7
commit 55ce94066e
19 changed files with 1969 additions and 122 deletions
+164
View File
@@ -0,0 +1,164 @@
import "@testing-library/jest-dom/vitest";
import { cleanup, fireEvent, render, screen, within } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { BoatProfile } from "@watermaps/shared";
import { BoatProfilePanel } from "../src/components/BoatProfilePanel";
afterEach(cleanup);
describe("BoatProfilePanel", () => {
it("shows the current profile, all routing-relevant fields and cookie information", () => {
renderPanel();
expect(screen.getByRole("heading", { name: "Aktuelles Boot" })).toBeVisible();
expect(screen.getByLabelText("Name des Bootes")).toHaveValue("Seestern");
expect(screen.getByLabelText("Kategorie")).toHaveValue("sailboat");
expect(screen.getByLabelText("Länge über alles")).toHaveValue(10.4);
expect(screen.getByLabelText("Breite")).toHaveValue(3.3);
expect(
screen.getByLabelText("Durchfahrtshöhe ab Wasserlinie")
).toHaveValue(14.2);
expect(screen.getByLabelText("Tiefgang")).toHaveValue(1.8);
expect(screen.getByLabelText("Sicherheitsreserve")).toHaveValue(0.5);
expect(screen.getByLabelText("Reisegeschwindigkeit")).toHaveValue(6);
expect(screen.getByLabelText("Bugrolle über Wasserlinie")).toHaveValue(1.1);
expect(
screen.getByRole("group", { name: "Ankern" })
).toHaveTextContent("von der Durchfahrtshöhe getrennt");
expect(screen.getByText(/in einem Cookie dieses Browsers gespeichert/)).toBeVisible();
});
it("validates, normalizes and saves the edited profile", () => {
const onSave = vi.fn(() => true);
renderPanel({ onSave, hasActiveRoute: true });
expect(screen.getByText(/Beim Speichern wird sie verworfen/)).toBeVisible();
fireEvent.change(screen.getByLabelText("Name des Bootes"), {
target: { value: " Kleine Möwe " }
});
fireEvent.change(screen.getByLabelText("Kategorie"), {
target: { value: "motor-sailer" }
});
fireEvent.change(screen.getByLabelText("Breite"), {
target: { value: "3.6" }
});
fireEvent.change(screen.getByLabelText("Bugrolle über Wasserlinie"), {
target: { value: "1.25" }
});
fireEvent.click(
screen.getByRole("button", { name: "Bootsdaten speichern" })
);
expect(onSave).toHaveBeenCalledWith({
...PROFILE,
name: "Kleine Möwe",
category: "motor-sailer",
beamM: 3.6,
bowRollerHeightM: 1.25
});
expect(screen.getByRole("status")).toHaveTextContent(
"Die Bootsdaten wurden in diesem Browser gespeichert."
);
});
it("reports invalid values without calling the persistence callback", () => {
const onSave = vi.fn(() => true);
renderPanel({ onSave });
fireEvent.change(screen.getByLabelText("Reisegeschwindigkeit"), {
target: { value: "81" }
});
fireEvent.submit(
screen.getByRole("button", { name: "Bootsdaten speichern" }).closest("form")!
);
expect(onSave).not.toHaveBeenCalled();
expect(screen.getByRole("alert")).toHaveTextContent(
"Reisegeschwindigkeit muss zwischen mehr als 0 und 80 liegen."
);
});
it("explains when the browser refuses to save the cookie", () => {
renderPanel({ onSave: vi.fn(() => false) });
fireEvent.click(
screen.getByRole("button", { name: "Bootsdaten speichern" })
);
expect(screen.getByRole("alert")).toHaveTextContent(
"nicht im Cookie gespeichert"
);
});
it("only offers deletion for stored data and requires inline confirmation", () => {
const onDelete = vi.fn(() => true);
const { rerender } = renderPanel({ stored: false, onDelete });
expect(
screen.queryByRole("button", { name: "Bootsdaten löschen" })
).not.toBeInTheDocument();
rerender(
<BoatProfilePanel
profile={PROFILE}
stored
onSave={vi.fn(() => true)}
onDelete={onDelete}
/>
);
fireEvent.click(
screen.getByRole("button", { name: "Bootsdaten löschen" })
);
const confirmation = screen.getByRole("group", {
name: "Löschen der Bootsdaten bestätigen"
});
expect(onDelete).not.toHaveBeenCalled();
fireEvent.click(
within(confirmation).getByRole("button", { name: "Abbrechen" })
);
expect(
screen.queryByRole("group", {
name: "Löschen der Bootsdaten bestätigen"
})
).not.toBeInTheDocument();
fireEvent.click(
screen.getByRole("button", { name: "Bootsdaten löschen" })
);
fireEvent.click(
screen.getByRole("button", { name: "Endgültig löschen" })
);
expect(onDelete).toHaveBeenCalledTimes(1);
expect(screen.getByRole("status")).toHaveTextContent(
"aus diesem Browser gelöscht"
);
});
});
const PROFILE: BoatProfile = {
name: "Seestern",
category: "sailboat",
lengthM: 10.4,
beamM: 3.3,
draughtM: 1.8,
airDraftM: 14.2,
safetyReserveM: 0.5,
cruiseSpeedKn: 6,
bowRollerHeightM: 1.1
};
function renderPanel(
overrides: Partial<Parameters<typeof BoatProfilePanel>[0]> = {}
) {
const props: Parameters<typeof BoatProfilePanel>[0] = {
profile: PROFILE,
stored: true,
onSave: vi.fn(() => true),
onDelete: vi.fn(() => true),
...overrides
};
return render(<BoatProfilePanel {...props} />);
}