mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(roadtrip, journey): six the audit turned up, each one verified before it was touched
**A saved stay left an invisible sheet standing, and the day swipe stayed dead behind it.** The stay sheet reopened 'rtstop' by spreading its own payload, which carries a place id. That sheet is located by day and assignment, so it resolved to nothing and drew nothing, while `shell.sheet` still pointed at it and `menuOpen: !!shell.sheet` kept the day swipe blocked until something else closed it. The row rides along now, both ways, and with no row to go back to the sheet closes rather than opening one that resolves to nothing. **"End the day here" showed off for a day that already ends there, and switching it on deleted that day end.** Two things close a day: the stop's own flag and a manual boundary filed against it. The writer has always known about both; the phone switch read only the flag, so the tap ran through the writer's boundary branch and cleared the boundary. The question is asked once now, in the planner beside that writer, and the desktop reads the same answer it always computed inline. **The road trip chain printed 24-hour clocks at a reader on a twelve-hour one.** The model hands clocks over as HH:MM, which is what the schedule computes in, and the chain, the head card and the up-next card printed it straight. The desktop rail, the day timeline and this tab's own sheets all honour the setting; these go through the same formatter, carried in the row chrome so no two rows can disagree. **The up-next card's navigate button read "places.navigate".** No locale has that key. It is `inspector.navigation`, which is what the stop sheet beside it, the place inspector and the place sheet all use, with the single-target label when there is only one. **Offered roads were invisible on a satellite basemap.** The imagery is anchored under the first layer TREK draws, found by prefix, and the roads offered for a leg are added before the route source so they sit under the current route. That also puts them before the first `trip-` layer, so the raster went straight over them. The prefix list knows them now. **A journal grew a day section for every day Dawarich recorded, all year.** The hook reads every open stay the account has, and the timeline took all of their dates. A week in May therefore sprouted sections from September. Bounded by the journal's own span now, its entries together with the dates of the trips it links, and with no span at all it offers nothing rather than everything.
This commit is contained in:
@@ -169,6 +169,9 @@ export function buildPlanner(overrides: Partial<TripPlanner> = {}): TripPlanner
|
||||
routeProfile: 'driving',
|
||||
setRouteProfile: vi.fn(),
|
||||
routeVias: [],
|
||||
// Whether the day ends at a stop, from the flag and from a manual boundary alike. The
|
||||
// helper answers from the flag; a case about boundaries overrides it.
|
||||
roadtripEndsDayAt: (stop: { endDay?: boolean } | null | undefined) => !!stop?.endDay,
|
||||
fitKey: 0,
|
||||
setFitKey: vi.fn(),
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ import type { TranslationFn } from '../../../../src/types'
|
||||
import type { RefuelSearch } from '../../../../src/components/Roadtrip/useRefuelSearch'
|
||||
import type { RefuelCandidate } from '../../../../src/components/Roadtrip/refuelSuggestion'
|
||||
|
||||
// FE-MOB-RTROW-001 to FE-MOB-RTROW-046
|
||||
// FE-MOB-RTROW-001 to FE-MOB-RTROW-048
|
||||
|
||||
// Same echo strategy as tests/helpers/mobileTrip: assertions stay on keys, not copy.
|
||||
const t: TranslationFn = (key, params) =>
|
||||
params ? `${key}:${Object.values(params).join(',')}` : key
|
||||
|
||||
const chrome: RowChrome = { t, unit: 'metric' }
|
||||
const chrome: RowChrome = { t, unit: 'metric', is12h: false }
|
||||
|
||||
function stopRow(over: Partial<StopRow> = {}): StopRow {
|
||||
return {
|
||||
@@ -214,6 +214,22 @@ describe('RtStopRow', () => {
|
||||
expect(screen.getByText('2')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('FE-MOB-RTROW-047: a clock follows the reader twelve hour setting', () => {
|
||||
// The model hands clocks over as HH:MM, which is the shape the schedule computes in.
|
||||
// Printing that straight to the screen ignored the setting the desktop rail, the day
|
||||
// timeline and this tab's own sheets all honour.
|
||||
render(<RtStopRow row={stopRow({ time: '14:05' })} chrome={{ ...chrome, is12h: true }} onOpen={vi.fn()} />)
|
||||
|
||||
expect(screen.getByText('2:05 PM')).toBeInTheDocument()
|
||||
expect(screen.queryByText('14:05')).toBeNull()
|
||||
})
|
||||
|
||||
it('FE-MOB-RTROW-048: on a twenty four hour clock it stays exactly as the model wrote it', () => {
|
||||
render(<RtStopRow row={stopRow({ time: '14:05' })} chrome={chrome} onOpen={vi.fn()} />)
|
||||
|
||||
expect(screen.getByText('14:05')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('FE-MOB-RTROW-013: writes an overnight warning as a word, since it has no figure', () => {
|
||||
const warning: ScheduleWarning = { index: 1, code: 'overnight' }
|
||||
const { container } = render(<RtStopRow row={stopRow({ warning })} chrome={chrome} onOpen={vi.fn()} />)
|
||||
|
||||
@@ -50,7 +50,7 @@ function makePlanner(overrides: Record<string, unknown> = {}) {
|
||||
|
||||
function makeShell(overrides: Record<string, unknown> = {}) {
|
||||
return buildShell({
|
||||
sheet: { id: 'rtstay', payload: { placeId: 202, minutes: 30, name: 'Bremen Marktplatz' } },
|
||||
sheet: { id: 'rtstay', payload: { placeId: 202, minutes: 30, name: 'Bremen Marktplatz', dayId: 11, assignmentId: 102 } },
|
||||
...overrides,
|
||||
} as unknown as Partial<MTripShellApi>)
|
||||
}
|
||||
@@ -95,7 +95,7 @@ describe('MRtStaySheet', () => {
|
||||
})
|
||||
|
||||
it('FE-MOB-RTSTAY-004: minus stops at zero instead of going negative', () => {
|
||||
renderSheet({}, { sheet: { id: 'rtstay', payload: { placeId: 202, minutes: 3, name: 'Bremen Marktplatz' } } })
|
||||
renderSheet({}, { sheet: { id: 'rtstay', payload: { placeId: 202, minutes: 3, name: 'Bremen Marktplatz', dayId: 11, assignmentId: 102 } } })
|
||||
fireEvent.click(minus())
|
||||
expect(value()).toHaveTextContent('0')
|
||||
expect(minus()).toBeDisabled()
|
||||
@@ -158,7 +158,25 @@ describe('MRtStaySheet', () => {
|
||||
fireEvent.click(plus())
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save' }))
|
||||
await waitFor(() => expect(planner.setRoadtripStay).toHaveBeenCalledWith(202, 35))
|
||||
expect(shell.openSheet).toHaveBeenCalledWith('rtstop', { placeId: 202, minutes: 35, name: 'Bremen Marktplatz' })
|
||||
// Addressed by day and assignment, which is how 'rtstop' locates a row. Spreading this
|
||||
// sheet's own payload left it unable to resolve anything, so it drew nothing while still
|
||||
// counting as open, and the day swipe stayed blocked behind it.
|
||||
expect(shell.openSheet).toHaveBeenCalledWith('rtstop', { dayId: 11, assignmentId: 102 })
|
||||
})
|
||||
|
||||
it('FE-MOB-RTSTAY-019: with no row to go back to it closes rather than opening a sheet that resolves to nothing', async () => {
|
||||
// Every caller sends the row, but a payload without one must not leave `shell.sheet`
|
||||
// pointing at a stop sheet that cannot locate anything: it would draw nothing and still
|
||||
// count as open, and the day swipe reads exactly that to decide it is blocked.
|
||||
const { planner, shell } = renderSheet({}, {
|
||||
sheet: { id: 'rtstay', payload: { placeId: 202, minutes: 30, name: 'Bremen Marktplatz' } },
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save' }))
|
||||
|
||||
await waitFor(() => expect(planner.setRoadtripStay).toHaveBeenCalledWith(202, 30))
|
||||
expect(shell.closeSheet).toHaveBeenCalled()
|
||||
expect(shell.openSheet).not.toHaveBeenCalledWith('rtstop', expect.anything())
|
||||
})
|
||||
|
||||
it('FE-MOB-RTSTAY-013: clearing the stay is a save of zero, not a second write path', async () => {
|
||||
@@ -168,7 +186,7 @@ describe('MRtStaySheet', () => {
|
||||
expect(value()).toHaveTextContent('0')
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save' }))
|
||||
await waitFor(() => expect(planner.setRoadtripStay).toHaveBeenCalledWith(202, 0))
|
||||
expect(shell.openSheet).toHaveBeenCalledWith('rtstop', { placeId: 202, minutes: 0, name: 'Bremen Marktplatz' })
|
||||
expect(shell.openSheet).toHaveBeenCalledWith('rtstop', { dayId: 11, assignmentId: 102 })
|
||||
})
|
||||
|
||||
it('FE-MOB-RTSTAY-014: closing without saving writes nothing and does not reopen the stop', () => {
|
||||
|
||||
@@ -215,10 +215,29 @@ describe('MRtStopSheet', () => {
|
||||
expect(screen.queryByText('Set how full this stop fills')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('FE-MOB-RTSTOP-011: the stay tile hands the stop over to the stay sheet', () => {
|
||||
it('FE-MOB-RTSTOP-011: the stay tile hands the stop over to the stay sheet, row and all', () => {
|
||||
const { shell } = renderSheet()
|
||||
fireEvent.click(screen.getByRole('button', { name: /^Stay/ }))
|
||||
expect(shell.openSheet).toHaveBeenCalledWith('rtstay', { placeId: 203, minutes: 90 })
|
||||
// The day and the assignment ride along because the stay sheet comes back here when it
|
||||
// saves, and this sheet is located by those two rather than by the place. Without them
|
||||
// it reopened on a payload it could not resolve and left an invisible sheet standing.
|
||||
expect(shell.openSheet).toHaveBeenCalledWith('rtstay', {
|
||||
placeId: 203,
|
||||
minutes: 90,
|
||||
name: 'Bremen Marktplatz',
|
||||
dayId: 11,
|
||||
assignmentId: 103,
|
||||
})
|
||||
})
|
||||
|
||||
it('FE-MOB-RTSTOP-036: a day ended by a manual boundary reads as ended, not as off', () => {
|
||||
// Two things can end a day: the stop's own flag and a manual boundary filed against it.
|
||||
// Reading only the flag showed the switch as off for a stop that already ends the day,
|
||||
// and the tap meant to switch it on ran through the writer's boundary branch and
|
||||
// deleted that day end instead.
|
||||
renderSheet({ roadtripEndsDayAt: () => true })
|
||||
|
||||
expect(screen.getByRole('switch', { name: 'End the day here' })).toHaveAttribute('aria-checked', 'true')
|
||||
})
|
||||
|
||||
it('FE-MOB-RTSTOP-012: ending the day here calls the stop-addressed writer with that very stop', async () => {
|
||||
|
||||
Reference in New Issue
Block a user