feat(dialogs): gedeelde primitives — useDirtyCloseGuard, useDialogSubmitShortcut, layout-classes
Story 1 van PBI "Alle dialogen conform docs/patterns/dialog.md". - components/shared/use-dirty-close-guard.tsx — hook + paired AlertDialog - components/shared/use-dialog-submit-shortcut.ts — Cmd/Ctrl+Enter handler - components/shared/entity-dialog-layout.ts — MD3-conforme classes voor §4 - TaskDialog refactored om beide hooks + classes te gebruiken (geen gedragsverandering) - 8 nieuwe unit-tests Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b47f62966e
commit
b05c4d241b
6 changed files with 219 additions and 47 deletions
57
__tests__/components/use-dialog-submit-shortcut.test.ts
Normal file
57
__tests__/components/use-dialog-submit-shortcut.test.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// @vitest-environment jsdom
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { useDialogSubmitShortcut } from '@/components/shared/use-dialog-submit-shortcut'
|
||||
|
||||
function makeEvent(opts: Partial<KeyboardEvent>) {
|
||||
return {
|
||||
metaKey: false,
|
||||
ctrlKey: false,
|
||||
key: '',
|
||||
preventDefault: vi.fn(),
|
||||
...opts,
|
||||
} as unknown as React.KeyboardEvent
|
||||
}
|
||||
|
||||
describe('useDialogSubmitShortcut', () => {
|
||||
it('triggert submit op Cmd+Enter', () => {
|
||||
const submit = vi.fn()
|
||||
const handler = useDialogSubmitShortcut(submit)
|
||||
const e = makeEvent({ metaKey: true, key: 'Enter' })
|
||||
|
||||
handler(e)
|
||||
|
||||
expect(submit).toHaveBeenCalledTimes(1)
|
||||
expect(e.preventDefault).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('triggert submit op Ctrl+Enter', () => {
|
||||
const submit = vi.fn()
|
||||
const handler = useDialogSubmitShortcut(submit)
|
||||
const e = makeEvent({ ctrlKey: true, key: 'Enter' })
|
||||
|
||||
handler(e)
|
||||
|
||||
expect(submit).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('triggert NIET op Enter zonder modifier', () => {
|
||||
const submit = vi.fn()
|
||||
const handler = useDialogSubmitShortcut(submit)
|
||||
const e = makeEvent({ key: 'Enter' })
|
||||
|
||||
handler(e)
|
||||
|
||||
expect(submit).not.toHaveBeenCalled()
|
||||
expect(e.preventDefault).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('triggert NIET op Cmd+andere toets', () => {
|
||||
const submit = vi.fn()
|
||||
const handler = useDialogSubmitShortcut(submit)
|
||||
const e = makeEvent({ metaKey: true, key: 'a' })
|
||||
|
||||
handler(e)
|
||||
|
||||
expect(submit).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
50
__tests__/components/use-dirty-close-guard.test.tsx
Normal file
50
__tests__/components/use-dirty-close-guard.test.tsx
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// @vitest-environment jsdom
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { renderHook, act } from '@testing-library/react'
|
||||
import { useDirtyCloseGuard } from '@/components/shared/use-dirty-close-guard'
|
||||
|
||||
describe('useDirtyCloseGuard', () => {
|
||||
it('sluit direct als form niet dirty is', () => {
|
||||
const onClose = vi.fn()
|
||||
const { result } = renderHook(() => useDirtyCloseGuard(false, onClose))
|
||||
|
||||
act(() => result.current.attemptClose())
|
||||
|
||||
expect(onClose).toHaveBeenCalledTimes(1)
|
||||
expect(result.current.confirmOpen).toBe(false)
|
||||
})
|
||||
|
||||
it('opent confirm als form dirty is', () => {
|
||||
const onClose = vi.fn()
|
||||
const { result } = renderHook(() => useDirtyCloseGuard(true, onClose))
|
||||
|
||||
act(() => result.current.attemptClose())
|
||||
|
||||
expect(onClose).not.toHaveBeenCalled()
|
||||
expect(result.current.confirmOpen).toBe(true)
|
||||
})
|
||||
|
||||
it('confirmDiscard sluit confirm en roept onClose', () => {
|
||||
const onClose = vi.fn()
|
||||
const { result } = renderHook(() => useDirtyCloseGuard(true, onClose))
|
||||
|
||||
act(() => result.current.attemptClose())
|
||||
expect(result.current.confirmOpen).toBe(true)
|
||||
|
||||
act(() => result.current.confirmDiscard())
|
||||
|
||||
expect(onClose).toHaveBeenCalledTimes(1)
|
||||
expect(result.current.confirmOpen).toBe(false)
|
||||
})
|
||||
|
||||
it('setConfirmOpen(false) annuleert zonder onClose te roepen', () => {
|
||||
const onClose = vi.fn()
|
||||
const { result } = renderHook(() => useDirtyCloseGuard(true, onClose))
|
||||
|
||||
act(() => result.current.attemptClose())
|
||||
act(() => result.current.setConfirmOpen(false))
|
||||
|
||||
expect(onClose).not.toHaveBeenCalled()
|
||||
expect(result.current.confirmOpen).toBe(false)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue