test(tours): the wiring test reads the map stage, the phone timeline test hands the planner its tours

This commit is contained in:
Maurice
2026-10-14 12:05:49 +02:00
parent f463c44d03
commit db531d2bef
2 changed files with 11 additions and 7 deletions
@@ -14,10 +14,13 @@ const pageControllerPath = 'client/src/pages/tripPlanner/useTripPlannerPage.ts'
const pageText = readFileSync(resolve(process.cwd(), 'src/pages/TripPlannerPage.tsx'), 'utf8')
const hookText = readFileSync(resolve(process.cwd(), 'src/pages/tripPlanner/useTripPlanner.ts'), 'utf8')
const pageControllerText = readFileSync(resolve(process.cwd(), 'src/pages/tripPlanner/useTripPlannerPage.ts'), 'utf8')
// The Tours map and its edit gates live in the map stage the page renders.
const mapStageText = readFileSync(resolve(process.cwd(), 'src/pages/tripPlanner/TourPlannerMapStage.tsx'), 'utf8')
const parse = (file: string, text: string) => ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true)
const page = parse(pagePath, pageText)
const hook = parse(hookPath, hookText)
const pageController = parse(pageControllerPath, pageControllerText)
const mapStage = parse('client/src/pages/tripPlanner/TourPlannerMapStage.tsx', mapStageText)
function collect(source: ts.Node, predicate: (node: ts.Node) => boolean): ts.Node[] {
const matches: ts.Node[] = []
@@ -180,10 +183,11 @@ test('B4A desktop page delegates Tours state and permissions to its page hook',
}
}
const mapClickGate = collect(page, node => ts.isJsxAttribute(node)
&& node.name.getText(page) === 'onMapClick'
assert.ok(jsxTags(page, 'TourPlannerMapStage').length === 1)
const mapClickGate = collect(mapStage, node => ts.isJsxAttribute(node)
&& node.name.getText(mapStage) === 'onMapClick'
&& node.initializer && ts.isJsxExpression(node.initializer)
&& !!node.initializer.expression && node.initializer.expression.getText(page).includes('canPlaceEdit'))
&& !!node.initializer.expression && node.initializer.expression.getText(mapStage).includes('canPlaceEdit'))
assert.ok(mapClickGate.length > 0)
})
@@ -191,9 +195,9 @@ test('B4A dedicated desktop controller retains GPX, draft, focus, and saved rail
assert.ok(callNamed(pageController, 'useTourPlanner'))
assert.ok(pageText.includes('const pageState = useTripPlannerPage()'))
assert.ok(pageControllerText.includes("tourPlanner.mode.type === 'view-gpx'"))
for (const mode of ['new-draft', 'edit-saved']) assert.ok(pageText.includes(`tourPlanner.mode.type === '${mode}'`))
for (const mode of ['new-draft', 'edit-saved']) assert.ok(mapStageText.includes(`tourPlanner.mode.type === '${mode}'`))
assert.match(pageControllerText, /readOnlyGpxAnalysis\?\.routeCoordinates/)
assert.match(pageText, /routeProfileFocus=\{tourPlanner\.routeProfileFocus\}/)
assert.match(mapStageText, /routeProfileFocus=\{tourPlanner\.routeProfileFocus\}/)
assert.match(pageText, /tourPlanner\.viewGpxTour\(tour, place\?\.route_geometry \?\? null\)/)
assert.match(pageControllerText, /onSaved:[\s\S]*?upsertTour\(result\.tour\)/)
assert.doesNotMatch(pageText, /setSelectedPlaceId\(result\.tour/)
@@ -365,7 +365,7 @@ describe('MPlanTimeline', () => {
const row: PlanRow = { key: 'pl-91', kind: 'place', item, assignment: tour, linkedReservations: [], invalidTour: true }
it('shows one localized invalid-endpoint warning and selects the Tour through the shared Place path', () => {
const { planner } = renderTimeline({ rows: [row], merged: [item], upNext: null }, { toursEnabled: true })
const { planner } = renderTimeline({ rows: [row], merged: [item], upNext: null }, { toursEnabled: true, tours: [] })
expect(screen.getAllByText('tours.dayRoute.endpointUnknown')).toHaveLength(1)
fireEvent.click(screen.getByText('Assigned Tour'))
@@ -376,7 +376,7 @@ describe('MPlanTimeline', () => {
it('does not show the warning for valid status or with Tours disabled', () => {
const validRow: PlanRow = { ...row, invalidTour: false }
const first = renderTimeline({ rows: [validRow], merged: [item], upNext: null }, { toursEnabled: true })
const first = renderTimeline({ rows: [validRow], merged: [item], upNext: null }, { toursEnabled: true, tours: [] })
expect(screen.queryByText('tours.dayRoute.endpointUnknown')).not.toBeInTheDocument()
first.unmount()