156 lines
4.5 KiB
TypeScript
156 lines
4.5 KiB
TypeScript
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<Geometry> = {
|
|
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<Geometry> = {
|
|
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);
|
|
});
|
|
});
|