123 lines
3.8 KiB
TypeScript
123 lines
3.8 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
||
import type { RouteResult } from "@watermaps/shared";
|
||
import {
|
||
OFFLINE_VOYAGES_STORAGE_KEY,
|
||
createOfflineVoyageRecord,
|
||
deleteOfflineVoyage,
|
||
listOfflineVoyages,
|
||
loadOfflineVoyage,
|
||
saveOfflineVoyage
|
||
} from "../src/lib/offline-route";
|
||
|
||
beforeEach(() => localStorage.clear());
|
||
|
||
describe("offline voyage storage", () => {
|
||
it("stores and restores a validated route and voyage plan", () => {
|
||
const saved = saveOfflineVoyage(
|
||
{
|
||
route: routeFixture,
|
||
name: "Törn Emden – Hamm",
|
||
plan: {
|
||
vesselProfile: {
|
||
draughtM: 1.4,
|
||
safetyReserveM: 0.5,
|
||
airDraftM: 2.8,
|
||
beamM: 3.2,
|
||
cruiseSpeedKn: 6
|
||
},
|
||
waypoints: [{ lat: 51.65, lon: 7.34 }],
|
||
departureAt: "2026-07-20T06:00:00.000Z",
|
||
notes: "Schleusen vor Abfahrt prüfen"
|
||
}
|
||
},
|
||
localStorage,
|
||
{ id: "voyage-test", savedAt: "2026-07-19T12:00:00.000Z" }
|
||
);
|
||
|
||
expect(saved.plan.start).toEqual({ lat: 53.344167, lon: 7.186111 });
|
||
expect(saved.plan.destination).toEqual({ lat: 51.6814536, lon: 7.8042615 });
|
||
expect(saved.route.departureTime).toBe("2026-07-20T06:00:00.000Z");
|
||
expect(saved.route.durationMinutes).toBe(120);
|
||
expect(saved.route.routeSnaps).toEqual(routeFixture.routeSnaps);
|
||
expect(saved.route.alternatives).toBeUndefined();
|
||
expect(listOfflineVoyages(localStorage)).toHaveLength(1);
|
||
const restored = loadOfflineVoyage("voyage-test", localStorage);
|
||
expect(restored).toEqual(saved);
|
||
expect(restored?.route).toEqual(
|
||
expect.objectContaining({
|
||
departureTime: "2026-07-20T06:00:00.000Z",
|
||
durationMinutes: 120
|
||
})
|
||
);
|
||
expect(deleteOfflineVoyage("voyage-test", localStorage)).toBe(true);
|
||
expect(loadOfflineVoyage("voyage-test", localStorage)).toBeNull();
|
||
});
|
||
|
||
it("ignores corrupted or untrusted persisted values", () => {
|
||
localStorage.setItem(OFFLINE_VOYAGES_STORAGE_KEY, "not-json");
|
||
expect(listOfflineVoyages(localStorage)).toEqual([]);
|
||
|
||
localStorage.setItem(OFFLINE_VOYAGES_STORAGE_KEY, JSON.stringify([{
|
||
schemaVersion: 1,
|
||
id: "bad",
|
||
name: "Bad",
|
||
savedAt: "no date",
|
||
plan: {},
|
||
route: { geometry: { type: "LineString", coordinates: [[999, 0], [0, 0]] } }
|
||
}]));
|
||
expect(listOfflineVoyages(localStorage)).toEqual([]);
|
||
});
|
||
|
||
it("rejects unsafe route coordinates before writing", () => {
|
||
expect(() => createOfflineVoyageRecord({
|
||
route: {
|
||
...routeFixture,
|
||
geometry: { type: "LineString", coordinates: [[7, 53], [Number.NaN, 52]] }
|
||
}
|
||
})).toThrow(/ungültige Koordinaten|Zahlenwert/);
|
||
expect(localStorage.getItem(OFFLINE_VOYAGES_STORAGE_KEY)).toBeNull();
|
||
});
|
||
});
|
||
|
||
const routeFixture: RouteResult = {
|
||
id: "emden-hamm",
|
||
name: "Emden – Hamm",
|
||
geometry: {
|
||
type: "LineString",
|
||
coordinates: [[7.186, 53.344], [7.1, 52.4], [7.8042, 51.6817]]
|
||
},
|
||
distanceNm: 153.69,
|
||
departureTime: "2026-07-20T06:00:00.000Z",
|
||
durationMinutes: 120,
|
||
eta: "2026-07-20T08:00:00.000Z",
|
||
warnings: [{ code: "NOT_OFFICIAL", severity: "caution", message: "Nicht amtlich" }],
|
||
minKnownDepthM: null,
|
||
unknownDepthRatio: 1,
|
||
dataSources: ["OSM"],
|
||
routingMode: "fairway",
|
||
routeSnaps: {
|
||
start: {
|
||
requested: { lat: 53.344167, lon: 7.186111 },
|
||
snapped: { lat: 53.344, lon: 7.186 },
|
||
distanceM: 20
|
||
},
|
||
waypoints: [],
|
||
destination: {
|
||
requested: { lat: 51.6814536, lon: 7.8042615 },
|
||
snapped: { lat: 51.6817, lon: 7.8042 },
|
||
distanceM: 28
|
||
}
|
||
},
|
||
alternatives: [{
|
||
id: "unused",
|
||
name: "Alternative",
|
||
geometry: { type: "LineString", coordinates: [[7, 53], [7.1, 52]] },
|
||
distanceNm: 160,
|
||
eta: null,
|
||
warnings: [],
|
||
minKnownDepthM: null,
|
||
unknownDepthRatio: 1,
|
||
dataSources: ["OSM"]
|
||
}]
|
||
};
|