Files
TREK/client/tests/helpers/tourPlannerStub.ts
T
Maurice c83eb42730 feat(tours): plan a run at your own pace
RUN-01. Run joins the tour types in the planner, with Running as its first
profile, chosen on purpose like a bike tour's. A run is routed on foot for
runnable, mostly paved ways: tracks and ferries only where there is no other
way (use_tracks 0, use_ferry 0, measured against the public Valhalla), no
hiking limit and no via ferrata. The runner types a pace in min/km; the
running time is the distance at that pace and nothing else, shown under the
field as badges (8 km x 6:00 /km = 48 min). TREK suggests no pace: without
one the time stays unknown and Save waits, text that is no pace or a pace
outside 2:00 to 20:00 is marked. The info dot, the overview and the head say
climbs, descents and difficulty are not in the time, and the time reads as
planned everywhere, so it never passes for a recorded one; the heights are
shown as for any tour on land.

Type, profile, pace and route come back on opening, survive a draft reload,
an undo of the type, a copy and a take-over; switching to another type drops
profile and pace. Day assignment, the 3D terrain view (with topo and
satellite, no ferratas) and a routing failure keeping the last route work as
for every tour. A GPX file can be imported as a run with its profile and no
pace, and planned over as a run. Runs export to GPX as running and get their
own places along the way (water, toilets, parks, viewpoints).

The server keeps tours.run_profile (CHECK list, already holding trail for
RUN-02, since SQLite cannot widen a CHECK in place) and
tours.run_pace_seconds_per_km (120 to 1200), switches the run type on,
refuses a run without a profile and run fields on any other type, and
list_tours names both with what the planned time does not include.
2026-10-20 15:05:38 +02:00

80 lines
2.3 KiB
TypeScript

import { vi } from 'vitest';
/**
* What a stubbed tour planner needs beyond the fields a test sets: a hike, no
* boat, no loop and the route tools as spies. Spread first, so a test's own
* fields win.
*/
export function hikePlannerDefaults() {
return {
tourType: 'hike' as const,
setTourType: vi.fn(),
isPaddle: false,
isBike: false,
bikeProfile: 'touring' as const,
setBikeProfile: vi.fn(),
// HIK-01: a hike without a winter label, as every hike starts.
winterActivity: null,
setWinterActivity: vi.fn(),
// RUN-01: no run, so no pace asked for.
isRun: false,
runProfile: 'running' as const,
setRunProfile: vi.fn(),
runPace: { paceSecondsPerKm: null, setPace: vi.fn(), load: vi.fn() },
runPaceMissing: false,
runPaceInvalid: false,
unreachable: null,
paddle: {
boatType: null,
waterContext: null,
speedKmh: null,
portageSpeedKmh: null,
lakeStyle: 'direct' as const,
recommendedSpeedKmh: null,
effectiveSpeedKmh: null,
setBoatType: vi.fn(),
setWaterContext: vi.fn(),
setSpeedKmh: vi.fn(),
setPortageSpeedKmh: vi.fn(),
setLakeStyle: vi.fn(),
adoptRecommendedSpeed: vi.fn(),
load: vi.fn(),
},
paddleSpeedInvalid: false,
paddleIncomplete: false,
paddleEstimate: null,
editPaddlePoints: vi.fn(),
amendWaypoints: vi.fn(),
isLoop: false,
reverse: vi.fn(),
returnToStart: vi.fn(),
toggleWaypointFreeLeg: vi.fn(),
insertShapingPoint: vi.fn(() => null),
setWaypointShaping: vi.fn(),
recomputeLeg: vi.fn(),
routeDrawnLegsOnWater: vi.fn(),
paddleRoute: null,
routeCurrent: false,
routeParts: null,
mapOverlays: new Set<string>(),
toggleMapOverlay: vi.fn(),
tripId: 1,
editWaypoints: vi.fn(),
// CW-07: a draft planned in TREK, not read from a Google Maps walk.
draftSource: null,
// P2C-03: a tour opened at its first revision, with nothing known about others.
revision: {
base: null,
baseRef: { current: null },
conflict: null,
remote: null,
adopt: vi.fn(),
notice: vi.fn(() => false),
refuse: vi.fn(() => false),
takeOver: vi.fn(),
dismissConflict: vi.fn(),
dismissRemote: vi.fn(),
},
};
}