fix(03): WR-01/WR-02/IN-02 recurrence-edit helper text, all-day toggle clamp, edit-mode parse-failure guard
This commit is contained in:
@@ -262,6 +262,36 @@ describe('EventForm', () => {
|
||||
expect(timeInputs.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
// WR-02 (iteration 2): toggling all-day ON deterministically clamps endDate to
|
||||
// max(startDate, endDate). When the end day is BEHIND the start day, it snaps forward
|
||||
// to a single-day event rather than validating as an inconsistent span, and any stale
|
||||
// end-time error from the timed view is cleared.
|
||||
it('toggling All-day ON clamps an end date that is behind the start date up to the start date', async () => {
|
||||
renderForm()
|
||||
fireEvent.change(screen.getByPlaceholderText('Event title'), {
|
||||
target: { value: 'Span Title' },
|
||||
})
|
||||
const dateInputs = document.querySelectorAll('input[type="date"]')
|
||||
expect(dateInputs.length).toBeGreaterThanOrEqual(2)
|
||||
// Start 2026-06-10, end 2026-06-09 (end behind start) — invalid timed span
|
||||
fireEvent.change(dateInputs[0], { target: { value: '2026-06-10' } })
|
||||
fireEvent.change(dateInputs[1], { target: { value: '2026-06-09' } })
|
||||
|
||||
// Toggle all-day ON: endDate must clamp up to the start date (single-day event)
|
||||
const allDaySwitch = screen.getByRole('switch')
|
||||
fireEvent.click(allDaySwitch)
|
||||
|
||||
const dateInputsAfter = document.querySelectorAll('input[type="date"]')
|
||||
expect((dateInputsAfter[1] as HTMLInputElement).value).toBe('2026-06-10')
|
||||
|
||||
// The clamped all-day event validates cleanly (no end-time error surfaced)
|
||||
const saveButton = screen.getByText('Create Event')
|
||||
fireEvent.click(saveButton)
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('End time must be after start')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
// ── Calendar picker D-02 ───────────────────────────────────────────────────
|
||||
|
||||
it('calendar picker is absent when fetchWritableCalendars returns 1 calendar (D-02)', () => {
|
||||
@@ -368,6 +398,39 @@ describe('EventForm', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// WR-01 (iteration 2): edit mode shows explanatory helper text near the disabled
|
||||
// recurrence select so the locked schedule is not a silent surprise.
|
||||
it('WR-01: edit mode surfaces helper text that repeat cannot be changed', () => {
|
||||
renderForm({ mode: 'edit', uid: 'edit-uid-456', eventOccurrence: EDIT_OCCURRENCE })
|
||||
expect(screen.getByText(/Repeat can't be changed yet/i)).toBeDefined()
|
||||
})
|
||||
|
||||
it('WR-01: create mode does NOT show the repeat helper text', () => {
|
||||
renderForm({ mode: 'create' })
|
||||
expect(screen.queryByText(/Repeat can't be changed yet/i)).toBeNull()
|
||||
})
|
||||
|
||||
// IN-02 (iteration 2): in edit mode an unparseable cached start/end must leave the
|
||||
// field blank and block submit, rather than silently rewriting the event to today/09:00.
|
||||
it('IN-02: edit mode with an unparseable start leaves the date blank and blocks submit', async () => {
|
||||
const corruptOccurrence: CalendarOccurrence = {
|
||||
...EDIT_OCCURRENCE,
|
||||
start: 'not-a-real-date',
|
||||
}
|
||||
renderForm({ mode: 'edit', uid: 'edit-uid-456', eventOccurrence: corruptOccurrence })
|
||||
|
||||
// The start date input must be blank (not today's date)
|
||||
const dateInputs = document.querySelectorAll('input[type="date"]')
|
||||
expect((dateInputs[0] as HTMLInputElement).value).toBe('')
|
||||
|
||||
// Submit must be blocked with a guidance message; updateEvent must NOT fire.
|
||||
fireEvent.click(screen.getByText('Save Changes'))
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/Couldn't read this event's date/i)).toBeDefined()
|
||||
})
|
||||
expect(mockUpdateEvent).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// ── Close behaviors ────────────────────────────────────────────────────────
|
||||
|
||||
it('pressing Escape closes the form', () => {
|
||||
|
||||
Reference in New Issue
Block a user