mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
- useAgendaKeyboardNavigation: ArrowLeft/Right → prev/next no mobile (FullCalendar v7 não tem setas no grid — verificado no bundle); skips para modificadores/dialog/menu/inputs; restore de foco na região - Região de teclado mobile-only: tabIndex/role/aria-label gateados por isMobile (desktop mantém a toolbar e sua árvore a11y intacta) - onTitleClick ganha icon?: LucideIcon (glyph da página, aria-hidden); agenda passa RotateCcw como affordance do 'voltar para hoje' - E2E: teste de teclado (dia e mês), glyph no título, hardening do swipe CDP (pacing 25ms — burst era classificado como flick pelo Chromium e disparava back-nav ~35% das runs) - Unit: 14 testes do hook/pura + 4 do renderer do glyph; impl plan docs/plans/c101-ux-pos-critique-impl.md (aprovado pelo humano) Closes #512
65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
import { cleanup, render, screen } from '@testing-library/react'
|
|
import { CalendarDays } from 'lucide-react'
|
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import { CampaignPageChromeText } from '@/components/campaign/shell/CampaignPageChromeText'
|
|
|
|
afterEach(() => {
|
|
cleanup()
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
describe('CampaignPageChromeText (mobile)', () => {
|
|
it('renderiza o título como botão quando há onTitleClick', () => {
|
|
const action = vi.fn()
|
|
render(
|
|
<CampaignPageChromeText
|
|
layout="mobile"
|
|
chrome={{ title: '9 Agosto', onTitleClick: { action, hint: 'Voltar para hoje' } }}
|
|
/>,
|
|
)
|
|
const button = screen.getByRole('button', { name: '9 Agosto' })
|
|
button.click()
|
|
expect(action).toHaveBeenCalled()
|
|
// Sem `icon` no contrato, o botão não renderiza glyph nenhum.
|
|
expect(button.querySelector('svg')).toBeNull()
|
|
})
|
|
|
|
it('renderiza o glyph do affordance (aria-hidden) quando onTitleClick.icon existe', () => {
|
|
render(
|
|
<CampaignPageChromeText
|
|
layout="mobile"
|
|
chrome={{
|
|
title: '9 Agosto',
|
|
onTitleClick: { action: vi.fn(), hint: 'Voltar para hoje', icon: CalendarDays },
|
|
}}
|
|
/>,
|
|
)
|
|
const button = screen.getByRole('button', { name: '9 Agosto' })
|
|
const icon = button.querySelector('svg')
|
|
expect(icon).not.toBeNull()
|
|
expect(icon?.getAttribute('aria-hidden')).toBe('true')
|
|
})
|
|
|
|
it('não renderiza glyph sem icon no contrato', () => {
|
|
render(<CampaignPageChromeText layout="mobile" chrome={{ title: 'Agenda' }} />)
|
|
expect(screen.queryByRole('button')).toBeNull()
|
|
expect(screen.getByText('Agenda')).toBeTruthy()
|
|
})
|
|
})
|
|
|
|
describe('CampaignPageChromeText (desktop)', () => {
|
|
it('não vira botão nem renderiza glyph — o chrome do desktop é texto', () => {
|
|
render(
|
|
<CampaignPageChromeText
|
|
layout="desktop"
|
|
chrome={{
|
|
title: '9 Agosto',
|
|
onTitleClick: { action: vi.fn(), hint: 'Voltar para hoje', icon: CalendarDays },
|
|
}}
|
|
/>,
|
|
)
|
|
expect(screen.queryByRole('button')).toBeNull()
|
|
expect(screen.getByText('9 Agosto')).toBeTruthy()
|
|
})
|
|
})
|