Initial Watermaps import
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import { act, cleanup, renderHook } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { RouteResult } from "@watermaps/shared";
|
||||
import { useCourseAssistant, type CourseAssistantInput } from "../src/hooks/useCourseAssistant";
|
||||
|
||||
const originalVibrate = Object.getOwnPropertyDescriptor(navigator, "vibrate");
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.useRealTimers();
|
||||
if (originalVibrate) Object.defineProperty(navigator, "vibrate", originalVibrate);
|
||||
else Reflect.deleteProperty(navigator, "vibrate");
|
||||
});
|
||||
|
||||
describe("useCourseAssistant", () => {
|
||||
it("never starts automatically and calculates only after an explicit start", () => {
|
||||
const { result } = renderHook(() => useCourseAssistant(input()));
|
||||
|
||||
expect(result.current.active).toBe(false);
|
||||
expect(result.current.guidance).toBeNull();
|
||||
|
||||
act(() => result.current.start());
|
||||
|
||||
expect(result.current.active).toBe(true);
|
||||
expect(result.current.guidance?.status).toBe("on-route");
|
||||
expect(result.current.guidance?.desiredCourseDeg).toBeCloseTo(90, 0);
|
||||
});
|
||||
|
||||
it("stops deliberately when a different route is selected", () => {
|
||||
const first = route("first", [[0, 0], [0.02, 0]]);
|
||||
const second = route("second", [[0, 0], [0, 0.02]]);
|
||||
const { result, rerender } = renderHook(
|
||||
({ currentRoute }) => useCourseAssistant(input(currentRoute)),
|
||||
{ initialProps: { currentRoute: first } }
|
||||
);
|
||||
act(() => result.current.start());
|
||||
expect(result.current.active).toBe(true);
|
||||
|
||||
rerender({ currentRoute: second });
|
||||
|
||||
expect(result.current.active).toBe(false);
|
||||
expect(result.current.guidance).toBeNull();
|
||||
});
|
||||
|
||||
it("pauses guidance when no fresh GPS fix arrives", () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-07-20T10:00:00.000Z"));
|
||||
const fixTimestampMs = Date.now();
|
||||
const { result } = renderHook(() => useCourseAssistant(input(routeFixture, fixTimestampMs)));
|
||||
act(() => result.current.start());
|
||||
expect(result.current.guidance).not.toBeNull();
|
||||
|
||||
act(() => vi.advanceTimersByTime(20_000));
|
||||
|
||||
expect(result.current.fixStale).toBe(true);
|
||||
expect(result.current.guidance).toBeNull();
|
||||
});
|
||||
|
||||
it("vibrates once when crossing into the off-route state", () => {
|
||||
const vibrate = vi.fn();
|
||||
Object.defineProperty(navigator, "vibrate", { configurable: true, value: vibrate });
|
||||
const { result, rerender } = renderHook(
|
||||
({ lat }) => useCourseAssistant(input(routeFixture, Date.now(), lat)),
|
||||
{ initialProps: { lat: 0 } }
|
||||
);
|
||||
act(() => result.current.start());
|
||||
expect(vibrate).not.toHaveBeenCalled();
|
||||
|
||||
rerender({ lat: 0.003 });
|
||||
expect(result.current.guidance?.status).toBe("off-route");
|
||||
expect(vibrate).toHaveBeenCalledTimes(1);
|
||||
|
||||
rerender({ lat: 0.0031 });
|
||||
expect(vibrate).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
function input(
|
||||
currentRoute: RouteResult = routeFixture,
|
||||
fixTimestampMs = Date.now(),
|
||||
lat = 0
|
||||
): CourseAssistantInput {
|
||||
return {
|
||||
route: currentRoute,
|
||||
position: { lon: 0.001, lat },
|
||||
accuracyM: 5,
|
||||
speedKn: 6,
|
||||
headingDeg: 90,
|
||||
fixTimestampMs
|
||||
};
|
||||
}
|
||||
|
||||
function route(id: string, coordinates: [number, number][]): RouteResult {
|
||||
return {
|
||||
id,
|
||||
name: id,
|
||||
geometry: { type: "LineString", coordinates },
|
||||
distanceNm: 1,
|
||||
eta: null,
|
||||
warnings: [],
|
||||
minKnownDepthM: null,
|
||||
unknownDepthRatio: 1,
|
||||
dataSources: ["Test"],
|
||||
routingMode: "fairway"
|
||||
};
|
||||
}
|
||||
|
||||
const routeFixture = route("test-route", [[0, 0], [0.02, 0]]);
|
||||
Reference in New Issue
Block a user