fix(time-tracking): cap smart-fill start at now so the range is never inverted

Smart-fill set the From time to the configured default start (09:00) when there
was no recent entry to continue from. Before that time of day the default lands
in the future, after the To time of now, producing an inverted range the backend
rejects (end_time before start_time). The save then failed silently and the
entry never appeared.

This surfaced as a flaky time-tracking e2e suite: the smart-fill specs failed
only when CI happened to run before 09:00 UTC.
This commit is contained in:
kolaente 2026-06-10 11:00:20 +02:00
parent 6d505e360b
commit e16d120236
2 changed files with 16 additions and 2 deletions

View File

@ -44,4 +44,14 @@ describe('smartFillStart', () => {
it('falls back to 09:00 when no default is configured', () => {
expect(smartFillStart([], '', now)).toEqual(new Date('2026-06-07T09:00:00'))
})
it('caps the default start at now when it would be in the future (before 09:00)', () => {
const beforeNine = new Date('2026-06-07T07:30:00')
expect(smartFillStart([], '09:00', beforeNine)).toEqual(beforeNine)
})
it('caps a future last-entry end at now', () => {
const entries = [entry(new Date('2026-06-07T16:00:00'), new Date('2026-06-07T17:00:00'))]
expect(smartFillStart(entries, '09:00', now)).toEqual(now)
})
})

View File

@ -5,16 +5,20 @@ import type {ITimeEntry} from '@/modelTypes/ITimeEntry'
// continue from, fall back to the user's configured default start (HH:MM) on
// the given day.
export function smartFillStart(recentEntries: ITimeEntry[], defaultStart: string, now: Date): Date {
// The filled range ends at now, so a start after now would be inverted (and
// rejected on save). Cap at now — e.g. the 09:00 fallback before 9am.
const cap = (start: Date) => (start.getTime() > now.getTime() ? new Date(now) : start)
const lastEnd = recentEntries
.map(entry => entry.endTime)
.filter((end): end is Date => end !== null)
.sort((a, b) => b.getTime() - a.getTime())[0]
if (lastEnd !== undefined) {
return new Date(lastEnd)
return cap(new Date(lastEnd))
}
const [hours, minutes] = (defaultStart || '09:00').split(':').map(Number)
const start = new Date(now)
start.setHours(hours || 0, minutes || 0, 0, 0)
return start
return cap(start)
}