import { describe, expect, it } from "vitest"; import type { FeatureCollection, Geometry } from "geojson"; import { routeFeatureBounds, routeLocksFromFeatures, voyageHarboursFromFeatures } from "../src/voyageHarbours"; describe("voyage harbour feature adapter", () => { it("turns normalized point features into amenity-aware harbour candidates", () => { const collection: FeatureCollection = { type: "FeatureCollection", features: [ { type: "Feature", id: "hamm-marina", geometry: { type: "Point", coordinates: [7.8, 51.68] }, properties: { layer: "harbours", name: "Marina Hamm", leisure: "marina", phone: "+49 2381 123", website: "hamm.example", email: "hafen@hamm.example", vhf: "12", opening_hours: "täglich 08:00-20:00", operator: "Hafen Hamm", "addr:street": "Uferweg", "addr:housenumber": "4", "addr:postcode": "59000", "addr:city": "Hamm", power_supply: "yes", drinking_water: "yes", guest_berths: 8 } }, { type: "Feature", geometry: { type: "LineString", coordinates: [[7, 52], [8, 52]] }, properties: { layer: "harbours", name: "Keine Punktgeometrie" } }, { type: "Feature", geometry: { type: "Point", coordinates: [7.7, 51.7] }, properties: { layer: "locks", name: "Keine Marina" } } ] }; expect(voyageHarboursFromFeatures(collection)).toEqual([ expect.objectContaining({ id: "hamm-marina", name: "Marina Hamm", kind: "marina", coordinate: { lat: 51.68, lon: 7.8 }, email: "hafen@hamm.example", vhf: "12", openingHours: "täglich 08:00-20:00", operator: "Hafen Hamm", address: "Uferweg 4, 59000 Hamm", amenities: expect.objectContaining({ electricity: "available", water: "available", overnight: "available" }) }) ]); }); it("calculates a nautical-mile padded feature request box", () => { const bounds = routeFeatureBounds( { geometry: { type: "LineString", coordinates: [[7, 52], [8, 53]] } }, 6 ); expect(bounds[0]).toBeLessThan(6.84); expect(bounds[1]).toBeCloseTo(51.9, 5); expect(bounds[2]).toBeGreaterThan(8.16); expect(bounds[3]).toBeCloseTo(53.1, 5); }); it("filters and orders route locks while preserving opening hours and phone", () => { const collection: FeatureCollection = { type: "FeatureCollection", features: [ { type: "Feature", id: "lock-late", geometry: { type: "Point", coordinates: [7.8, 52] }, properties: { layer: "locks", name: "Schleuse Ost", openingHours: "Mo-Su 06:00-22:00", phone: "+49 2381 200" } }, { type: "Feature", id: "lock-off-route", geometry: { type: "Point", coordinates: [7.5, 52.02] }, properties: { layer: "locks", name: "Entfernte Schleuse" } }, { type: "Feature", id: "lock-early", geometry: { type: "Point", coordinates: [7.2, 52] }, properties: { layer: "locks", name: "Schleuse West", opening_hours: "nach Anmeldung", phone: "+49 2381 100" } }, { type: "Feature", id: "harbour-on-route", geometry: { type: "Point", coordinates: [7.4, 52] }, properties: { layer: "harbours", name: "Kein Schleusenpunkt" } } ] }; const locks = routeLocksFromFeatures(collection, { geometry: { type: "LineString", coordinates: [[7, 52], [8, 52]] }, distanceNm: 41 }); expect(locks.map((lock) => lock.id)).toEqual(["lock-early", "lock-late"]); expect(locks[0]).toEqual( expect.objectContaining({ name: "Schleuse West", openingHours: "nach Anmeldung", phone: "+49 2381 100", distanceFromRouteNm: 0 }) ); expect(locks[1]).toEqual( expect.objectContaining({ name: "Schleuse Ost", openingHours: "Mo-Su 06:00-22:00", phone: "+49 2381 200", distanceFromRouteNm: 0 }) ); expect(locks[0]!.routeDistanceNm).toBeLessThan(locks[1]!.routeDistanceNm); }); });