test(03-12): RED — WR-07 focus trap Tab/Shift+Tab cycle tests

Add two failing tests for the focus trap:
- Tab from last focusable element must wrap to first inside dialog
- Shift+Tab from first focusable element must wrap to last inside dialog

Both fail today because EventForm only calls .focus() once on open;
Tab escapes the modal to background content.
This commit is contained in:
Lucas Berger
2026-06-05 20:40:40 -04:00
parent f0f1361fba
commit 4244e8cd29
@@ -616,4 +616,58 @@ describe('EventForm — Plan 03-12 gap closures', () => {
// Should return a YYYY-MM-DD string // Should return a YYYY-MM-DD string
expect(result).toMatch(/^\d{4}-\d{2}-\d{2}$/) expect(result).toMatch(/^\d{4}-\d{2}-\d{2}$/)
}) })
// ── WR-07: Tab/Shift+Tab focus trap ──────────────────────────────────────
//
// The dialog must trap Tab focus: pressing Tab from the last focusable element
// wraps to the first, and Shift+Tab from the first wraps to the last.
// Today EventForm only calls .focus() once on open — Tab escapes the modal.
it('WR-07: Tab from last focusable element wraps focus to first inside dialog', () => {
renderForm({ mode: 'create' })
const dialog = screen.getByRole('dialog')
const focusable = Array.from(
dialog.querySelectorAll<HTMLElement>(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
),
)
expect(focusable.length).toBeGreaterThan(1)
const lastElement = focusable[focusable.length - 1]
const firstElement = focusable[0]
// Focus the last element, then dispatch Tab
lastElement.focus()
expect(document.activeElement).toBe(lastElement)
fireEvent.keyDown(dialog, { key: 'Tab', shiftKey: false })
// WR-07 fix: focus should have wrapped to first element inside dialog
expect(document.activeElement).toBe(firstElement)
})
it('WR-07: Shift+Tab from first focusable element wraps focus to last inside dialog', () => {
renderForm({ mode: 'create' })
const dialog = screen.getByRole('dialog')
const focusable = Array.from(
dialog.querySelectorAll<HTMLElement>(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
),
)
expect(focusable.length).toBeGreaterThan(1)
const firstElement = focusable[0]
const lastElement = focusable[focusable.length - 1]
// Focus the first element, then dispatch Shift+Tab
firstElement.focus()
expect(document.activeElement).toBe(firstElement)
fireEvent.keyDown(dialog, { key: 'Tab', shiftKey: true })
// WR-07 fix: focus should have wrapped to last element inside dialog
expect(document.activeElement).toBe(lastElement)
})
}) })