Files
BuTzZ b98ec8bc6f
Test and publish container images / test (push) Successful in 2m27s
Test and publish container images / publish (push) Failing after 4s
Hinweise optimiert
2026-07-27 13:04:32 +02:00

218 lines
11 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { expect, test } from "@playwright/test";
test("renders the iPhone PWA shell without overlapping core controls", async ({ page, context }) => {
await context.grantPermissions(["geolocation"]);
await context.setGeolocation({ latitude: 54.18, longitude: 12.09 });
await page.goto("/");
await page.getByRole("button", { name: "GPS starten" }).click();
await expect(page.getByText("Watermaps")).toBeVisible();
await expect(page.getByTestId("map-container")).toBeVisible();
await expect(page.getByRole("button", { name: "Layer" })).toBeVisible();
await expect(page.getByRole("complementary", { name: "Routenplanung" })).toBeVisible();
await expect(page.getByRole("button", { name: "Start auf Karte setzen" })).toBeVisible();
await expect(page.getByRole("button", { name: "Ziel auf Karte setzen" })).toBeVisible();
await page.getByText("Routenoptionen: Zwischenziele").click();
await expect(page.getByRole("button", { name: "Zwischenziel auf der Karte hinzufügen" })).toBeVisible();
await expect(page.getByLabel("Abfahrt")).toBeVisible();
await page.getByText("Unterwegs: GPX · Offline · Kursalarm").click();
await expect(page.getByRole("region", { name: "Navigation und Offline-Route" })).toBeVisible();
await page.getByRole("button", { name: "Layer" }).click();
await expect(page.getByLabel("Layer Auswahl").getByText("Brücken")).toBeVisible();
await expect(page.getByLabel("Layer Auswahl").getByText("Tiefen")).toBeVisible();
await expect(page.getByLabel("Layer Auswahl").getByText("Schleusen")).toBeVisible();
await expect(page.getByLabel("Layer Auswahl").getByText("Häfen")).toBeVisible();
});
test("sets start and destination only after explicit map picking actions", async ({ page, context }) => {
await context.grantPermissions(["geolocation"]);
await context.setGeolocation({ latitude: 54.18, longitude: 12.09 });
await page.goto("/");
await expect(page.getByText("Start und Ziel setzen")).toBeVisible();
await expect(page.getByRole("button", { name: "Layer" })).toBeVisible();
const mapBox = await page.getByTestId("map-container").boundingBox();
if (!mapBox) {
throw new Error("Map container not visible");
}
const mapTapY = mapBox.y + Math.min(132, mapBox.height * 0.2);
await page.touchscreen.tap(mapBox.x + mapBox.width / 2, mapTapY);
await expect(page.getByText("Start und Ziel setzen")).toBeVisible();
await page.getByRole("button", { name: "Start auf Karte setzen" }).click();
await expect(page.getByText("Startpunkt auf der Karte anklicken")).toBeVisible();
await page.touchscreen.tap(mapBox.x + mapBox.width / 3, mapTapY);
await expect(page.getByText(/^Start \d/)).toBeVisible();
await page.getByRole("button", { name: "Ziel auf Karte setzen" }).click();
await expect(page.getByText("Ziel auf der Karte anklicken")).toBeVisible();
await page.touchscreen.tap(mapBox.x + (mapBox.width * 2) / 3, mapTapY);
await expect(page.getByText(/^Ziel \d/)).toBeVisible();
await expect(page.getByText("Route bereit zur Prüfung")).toBeVisible();
await page.getByText("Routenoptionen: Zwischenziele").click();
await page.getByRole("button", { name: "Zwischenziel auf der Karte hinzufügen" }).click();
await expect(page.getByText("Zwischenziel auf der Karte anklicken")).toBeVisible();
await page.touchscreen.tap(mapBox.x + mapBox.width / 2, mapTapY);
await expect(page.getByText(/^Z1 /)).toBeVisible();
});
test("does not expose Borkum or Hamm as direct route shortcuts", async ({ page }) => {
await page.goto("/");
await expect(page.getByRole("button", { name: /Borkum/i })).toHaveCount(0);
await expect(page.getByRole("button", { name: /Hamm/i })).toHaveCount(0);
await expect(page.getByRole("button", { name: "Start auf Karte setzen" })).toBeVisible();
await expect(page.getByRole("button", { name: "Ziel auf Karte setzen" })).toBeVisible();
});
test("can hide and restore the route planner for a map-only view", async ({ page }) => {
await page.goto("/");
await page.getByRole("button", { name: "Routenfenster ausblenden" }).click();
await expect(page.getByRole("complementary", { name: "Routenplanung" })).toBeHidden();
await expect(page.getByRole("button", { name: "Routenfenster einblenden" })).toBeVisible();
await expect(page.getByRole("button", { name: "Start auf Karte setzen" })).toBeHidden();
await page.getByRole("button", { name: "Routenfenster einblenden" }).click();
await expect(page.getByRole("complementary", { name: "Routenplanung" })).toBeVisible();
await expect(page.getByRole("button", { name: "Start auf Karte setzen" })).toBeVisible();
});
test("cycles the mobile route sheet through half, full, and compact heights", async ({ page }) => {
await page.goto("/");
const routePanel = page.getByRole("complementary", { name: "Routenplanung" });
await expect(routePanel).toHaveAttribute("data-sheet-state", "half");
const halfBox = await routePanel.boundingBox();
await page
.getByRole("button", { name: "Routenfenster auf volle Höhe vergrößern" })
.click();
await expect(routePanel).toHaveAttribute("data-sheet-state", "full");
const fullBox = await routePanel.boundingBox();
expect(fullBox && halfBox && fullBox.height > halfBox.height + 80).toBe(true);
await page
.getByRole("button", { name: "Routenfenster auf kompakte Höhe verkleinern" })
.click();
await expect(routePanel).toHaveAttribute("data-sheet-state", "compact");
const compactBox = await routePanel.boundingBox();
expect(compactBox && halfBox && compactBox.height < halfBox.height - 80).toBe(true);
await expect(page.getByRole("button", { name: "Start auf Karte setzen" })).toBeHidden();
await page.setViewportSize({ width: 900, height: 844 });
await expect(routePanel).toHaveAttribute("data-sheet-state", "half");
await expect(page.getByRole("button", { name: "Start auf Karte setzen" })).toBeVisible();
});
test("starts a visible dynamic course assistant only after route planning", async ({ page, context }) => {
await context.grantPermissions(["geolocation"]);
await context.setGeolocation({ latitude: 54.18, longitude: 12.09 });
await page.route("**/api/routes", async (request) => {
await request.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
id: "guidance-e2e",
name: "Testkurs Ost",
geometry: { type: "LineString", coordinates: [[12.09, 54.18], [12.11, 54.18]] },
distanceNm: 0.7,
eta: null,
warnings: [],
dataSources: ["E2E"],
routingMode: "fairway"
})
});
});
await page.goto("/");
await expect(page.getByRole("button", { name: "Layer" })).toBeVisible();
const mapBox = await page.getByTestId("map-container").boundingBox();
if (!mapBox) throw new Error("Map container not visible");
const tapY = mapBox.y + Math.min(132, mapBox.height * 0.2);
await page.getByRole("button", { name: "Start auf Karte setzen" }).click();
await page.touchscreen.tap(mapBox.x + mapBox.width / 3, tapY);
await page.getByRole("button", { name: "Ziel auf Karte setzen" }).click();
await page.touchscreen.tap(mapBox.x + (mapBox.width * 2) / 3, tapY);
await page.getByRole("button", { name: "Route berechnen" }).click();
const startAssistant = page.getByRole("button", { name: "Navigation starten" });
await expect(startAssistant).toBeVisible();
await startAssistant.click();
const assistant = page.getByRole("complementary", { name: "Kursassistent" });
await expect(assistant).toBeVisible();
await expect(assistant.getByText("SOLL ÜBER GRUND")).toBeVisible();
await expect(assistant.getByRole("button", { name: "Kursassistent stoppen" })).toBeVisible();
await expect(page.getByRole("complementary", { name: "Routenplanung" })).toBeHidden();
const assistantBox = await assistant.boundingBox();
const statusBox = await page.getByLabel("Navigationsstatus").boundingBox();
expect(assistantBox && statusBox && assistantBox.y + assistantBox.height <= statusBox.y + 1).toBe(true);
});
test("sets and arms the anchor watch only through the explicit two-step flow", async ({ page, context }) => {
const now = Date.now();
await context.grantPermissions(["geolocation"]);
await context.setGeolocation({ latitude: 53.2159, longitude: 6.5766 });
await page.route("**/api/tides/nearest?*", async (request) => {
await request.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
station: "Testpegel Emden",
distanceKm: 4.2,
nextHigh: null,
nextLow: null,
waterLevelCurve: [
{ time: new Date(now - 60 * 60_000).toISOString(), predictedM: 1 },
{ time: new Date(now + 6 * 60 * 60_000).toISOString(), predictedM: 2 },
{ time: new Date(now + 30 * 60 * 60_000).toISOString(), predictedM: 0.5 }
],
source: "E2E",
updatedAt: new Date(now).toISOString()
})
});
});
await page.goto("/");
await expect(page.getByRole("complementary", { name: "Ankerwache" })).toHaveCount(0);
await page.getByRole("button", { name: "GPS starten" }).click();
await page.getByRole("button", { name: "Ankerwache öffnen" }).click();
const panel = page.getByRole("complementary", { name: "Ankerwache" });
await expect(panel).toBeVisible();
await expect(panel.getByText(/GPS ±\d+ m/)).toBeVisible();
await expect(page.getByRole("complementary", { name: "Routenplanung" })).toBeHidden();
await panel.getByRole("button", { name: "Anker gefallen Position jetzt setzen" }).click();
await expect(panel.getByText("Ankerpunkt gespeichert")).toBeVisible();
await panel.getByLabel("Tiefe beim Setzen").fill("4");
await panel.getByLabel("Bugrolle über Wasser").fill("1");
await panel.getByLabel("Kette / Leine draußen").fill("40");
await panel.getByLabel("Gewähltes Verhältnis").selectOption("5");
await expect(panel.getByText(/Testpegel Emden · 4\.2 km entfernt/)).toBeVisible();
await expect(panel.getByText(/m Reserve/)).toBeVisible();
await panel.getByRole("button", { name: "Wache starten" }).click();
await expect(panel.getByText("Ankerwache aktiv")).toBeVisible();
await expect(panel.getByText("Im überwachten Schwojkreis")).toBeVisible();
const panelBox = await panel.boundingBox();
const statusBox = await page.getByLabel("Navigationsstatus").boundingBox();
expect(panelBox && statusBox && panelBox.y + panelBox.height <= statusBox.y + 1).toBe(true);
await panel.getByRole("button", { name: "Ankerwache beenden" }).click();
await expect(panel.getByRole("button", { name: "Wirklich beenden" })).toBeVisible();
await panel.getByRole("button", { name: "Wirklich beenden" }).click();
await expect(panel).toBeHidden();
await expect(page.getByRole("complementary", { name: "Routenplanung" })).toBeVisible();
});