Files
TREK/client/tests/helpers/tourPlannerStub.ts
T
Maurice 2449616ee9 feat(tours): plan a multi-day tour as one route split into stages
A hut-to-hut hike or a paddle trip over several days is now planned in the
Tours planner as one tour: the whole route is planned as before, and stops
along it are marked as stage ends (MDT-01). The stages are read off that one
route in its order, never kept as copies, so a change inside a stage changes
the whole tour and every figure on it.

- A Day tour / Multi-day tour switch beside the tour type; a stop's menu
  ends a stage there or lets it go on. Back to a day tour removes every stage
  end after a confirmation, as one step undo brings back.
- The list of points is headed per stage with its distance and moving time;
  a stop that ends a stage carries a moon at its number, on the map too.
- The overview lists the stages from stop to stop with distance, climb,
  descent and time (hiking rule per stage, paddle estimate per stage, the
  router's time shared by distance otherwise), marks where each ends across
  the elevation profile, and a stage of more than a day on the move warns.
- A stage end a change cannot keep (its stop removed, moved to an end or
  made a shaping point) is dropped and said so, with undo, never moved
  to another point.
- A multi-day tour may take a day a stage, so its time limit grows with its
  stages; the tour keeps its one type, portages included.
- The list and the MCP tools show the stage count and where stages end.

Stage ends are a flag on the waypoint (migration 046000); a tour without one
is a day tour, as every tour saved before.
2026-10-20 15:26:18 +02:00

130 lines
3.5 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,
isHorse: 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(),
winterActivityChoice: 'winter_hike' as const,
// 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),
insertShapingPoints: vi.fn(() => null),
setWaypointShaping: vi.fn(),
recomputeLeg: vi.fn(),
routeDrawnLegsOnWater: vi.fn(),
legVariants: idleLegVariants(),
roundHikes: idleRoundHikes(),
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,
// MDT-01: a day tour, no stage set and none that may be.
stages: {
multiDay: false,
stages: [],
endCount: 0,
lost: 0,
setMultiDay: vi.fn(),
toggleStageEnd: vi.fn(),
canEnd: vi.fn(() => false),
},
// 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(),
},
};
}
/** RTE-02: a planner comparing no section, with its actions as spies. */
export function idleLegVariants() {
return {
comparison: null,
focus: null,
canCompare: vi.fn(() => false),
compare: vi.fn(),
select: vi.fn(),
hover: vi.fn(),
apply: vi.fn(),
close: vi.fn(),
appliedHint: { shown: false, key: null, undo: vi.fn(), hold: vi.fn() },
};
}
/** RTE-03: a planner offering no round hike, with its actions as spies. */
export function idleRoundHikes() {
return {
view: null,
focus: null,
frame: null,
canStart: vi.fn(() => false),
open: vi.fn(),
find: vi.fn(),
back: vi.fn(),
select: vi.fn(),
hover: vi.fn(),
apply: vi.fn(),
confirm: vi.fn(),
cancelConfirm: vi.fn(),
close: vi.fn(),
appliedHint: { shown: false, key: null, undo: vi.fn(), hold: vi.fn() },
};
}