Bootssymbol hinzugefügt
This commit is contained in:
@@ -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} />);
|
||||
}
|
||||
Reference in New Issue
Block a user