Files
watermaps/apps/web/tests/route-deviation.test.ts
2026-07-24 11:29:24 +02:00

50 lines
1.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { distanceToRouteM, evaluateRouteDeviation } from "../src/lib/route-deviation";
describe("route deviation", () => {
it("calculates the cross-track distance to a route segment", () => {
const distance = distanceToRouteM(
{ lat: 0.001, lon: 0.005 },
[[0, 0], [0.01, 0]]
);
expect(distance).toBeGreaterThan(110);
expect(distance).toBeLessThan(112.5);
});
it("uses the endpoint when the nearest point lies beyond the segment", () => {
const distance = distanceToRouteM(
{ lat: 0, lon: 0.02 },
[[0, 0], [0.01, 0]]
);
expect(distance).toBeGreaterThan(1_110);
expect(distance).toBeLessThan(1_113);
});
it("handles a short segment crossing the antimeridian", () => {
const distance = distanceToRouteM(
{ lat: 0.001, lon: 180 },
[[179.9, 0], [-179.9, 0]]
);
expect(distance).toBeGreaterThan(110);
expect(distance).toBeLessThan(113);
});
it("accounts conservatively for GPS accuracy and suppresses unreliable alarms", () => {
const route = [[0, 0], [0.01, 0]] as const;
const near = evaluateRouteDeviation({ lat: 0.001, lon: 0.005 }, route, { thresholdM: 100, accuracyM: 30 });
const away = evaluateRouteDeviation({ lat: 0.002, lon: 0.005 }, route, { thresholdM: 100, accuracyM: 30 });
const inaccurate = evaluateRouteDeviation({ lat: 0.01, lon: 0.005 }, route, { thresholdM: 100, accuracyM: 500 });
expect(near?.isOffRoute).toBe(false);
expect(near?.conservativeDistanceM).toBeLessThan(100);
expect(away?.isOffRoute).toBe(true);
expect(inaccurate?.reliable).toBe(false);
expect(inaccurate?.isOffRoute).toBe(false);
});
it("returns null instead of alarming for invalid or missing route data", () => {
expect(distanceToRouteM({ lat: Number.NaN, lon: 7 }, [[7, 53], [7.1, 53.1]])).toBeNull();
expect(distanceToRouteM({ lat: 53, lon: 7 }, [])).toBeNull();
});
});