mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
No mobile (<768px) staff perde o botão de abrir sidebar na top bar (CampaignMobileTopBar role-gated via useCampaignPageChromeRole + isStaffCampaignRole; leader mantém) e o sheet de navegação deixa de montar (CampaignSidebar early-return quando isMobile && staff). Filtros salvos de Municípios (B18) migram para o drawer Mais (MunicipalityNavSavedFilters variant 'overflow', mesma store, apagar/desfazer/sucessão de foco; drawer ganha overflow-y-auto). Correção de bug pré-existente (D4): o Toaster vivia dentro do wrapper [contain:layout_paint] do painel da AI, que vira containing block para position:fixed e stacking context próprio — toasts com ação (ex. Desfazer) ficavam inalcançáveis sob os portais z-50 de drawer/sheet. Movido para o root layout (campaign). Testes: unit top bar (staff sem trigger / leader com trigger) + e2e (staff sem trigger/dialog, leader com sheet, B18 no drawer completo).
228 lines
8.1 KiB
TypeScript
228 lines
8.1 KiB
TypeScript
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const pathnameState = vi.hoisted(() => ({ value: '/campanha/municipios' }))
|
|
|
|
vi.mock('next/navigation', () => ({
|
|
usePathname: () => pathnameState.value,
|
|
useRouter: () => ({
|
|
push: vi.fn(),
|
|
replace: vi.fn(),
|
|
}),
|
|
}))
|
|
|
|
import {
|
|
CampaignHomeSearchChromeProvider,
|
|
useSetCampaignHomeSearchChrome,
|
|
type CampaignHomeSearchChromeState,
|
|
} from '@/components/campaign/shell/CampaignHomeSearchChromeContext'
|
|
import { CampaignMobileTopBar } from '@/components/campaign/shell/CampaignMobileTopBar'
|
|
import { CampaignPageChromeProvider } from '@/components/campaign/shell/CampaignPageChromeContext'
|
|
import {
|
|
CampaignWizardChromeProvider,
|
|
useSetCampaignWizardChrome,
|
|
type CampaignWizardChromeState,
|
|
} from '@/components/campaign/shell/CampaignWizardChromeContext'
|
|
import { SidebarProvider } from '@/components/ui/Sidebar'
|
|
import { stubMatchMedia } from '../helpers/matchMedia'
|
|
|
|
const WizardChromeProbe = ({ chrome }: { chrome: CampaignWizardChromeState | null }) => {
|
|
useSetCampaignWizardChrome(chrome)
|
|
return null
|
|
}
|
|
|
|
const HomeSearchChromeProbe = ({ chrome }: { chrome: CampaignHomeSearchChromeState | null }) => {
|
|
useSetCampaignHomeSearchChrome(chrome)
|
|
return null
|
|
}
|
|
|
|
const renderTopBar = (input: {
|
|
wizardChrome?: CampaignWizardChromeState | null
|
|
homeSearchChrome?: CampaignHomeSearchChromeState | null
|
|
pathname?: string
|
|
}) => {
|
|
pathnameState.value = input.pathname ?? '/campanha/municipios'
|
|
return render(
|
|
<SidebarProvider>
|
|
<CampaignPageChromeProvider role="coordinator">
|
|
<CampaignWizardChromeProvider>
|
|
<CampaignHomeSearchChromeProvider>
|
|
<WizardChromeProbe chrome={input.wizardChrome ?? null} />
|
|
<HomeSearchChromeProbe chrome={input.homeSearchChrome ?? null} />
|
|
<CampaignMobileTopBar />
|
|
</CampaignHomeSearchChromeProvider>
|
|
</CampaignWizardChromeProvider>
|
|
</CampaignPageChromeProvider>
|
|
</SidebarProvider>,
|
|
)
|
|
}
|
|
|
|
describe('CampaignMobileTopBar', () => {
|
|
beforeEach(() => {
|
|
stubMatchMedia()
|
|
})
|
|
|
|
afterEach(() => {
|
|
cleanup()
|
|
vi.unstubAllGlobals()
|
|
})
|
|
|
|
it('renders page chrome from pathname in app mode', () => {
|
|
const { container } = renderTopBar({})
|
|
|
|
const topBar = container.querySelector('[data-slot="campaign-mobile-top-bar"]')
|
|
expect(topBar?.getAttribute('data-mode')).toBe('app')
|
|
expect(screen.getByText('Municípios')).toBeTruthy()
|
|
expect(screen.queryByRole('link', { name: /Voltar/ })).toBeNull()
|
|
expect(screen.queryByRole('button', { name: 'Fechar busca' })).toBeNull()
|
|
expect(screen.queryByRole('link', { name: 'Sair da ação' })).toBeNull()
|
|
})
|
|
|
|
it('renders empty chrome on home', () => {
|
|
const { container } = renderTopBar({ pathname: '/campanha' })
|
|
|
|
const topBar = container.querySelector('[data-slot="campaign-mobile-top-bar"]')
|
|
expect(topBar?.getAttribute('data-mode')).toBe('app')
|
|
expect(container.querySelector('[data-slot="campaign-page-chrome"]')).toBeNull()
|
|
})
|
|
|
|
it('renders app mode with Voltar when home search is focused (B106)', () => {
|
|
const collapse = vi.fn()
|
|
const { container } = renderTopBar({
|
|
pathname: '/campanha',
|
|
homeSearchChrome: { focused: true, collapse },
|
|
})
|
|
|
|
const topBar = container.querySelector('[data-slot="campaign-mobile-top-bar"]')
|
|
expect(topBar?.getAttribute('data-home-search-focused')).toBe('true')
|
|
expect(screen.queryByRole('button', { name: 'Abrir ou fechar menu da campanha' })).toBeNull()
|
|
|
|
fireEvent.click(screen.getByRole('button', { name: 'Fechar busca' }))
|
|
expect(collapse).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('does not render the sidebar trigger for staff in app mode (C102)', () => {
|
|
const { container } = renderTopBar({})
|
|
|
|
const topBar = container.querySelector('[data-slot="campaign-mobile-top-bar"]')
|
|
expect(topBar?.getAttribute('data-mode')).toBe('app')
|
|
expect(screen.queryByRole('button', { name: 'Abrir ou fechar menu da campanha' })).toBeNull()
|
|
})
|
|
|
|
it('renders the sidebar trigger for the leader in app mode (C102)', () => {
|
|
const { container } = render(
|
|
<SidebarProvider>
|
|
<CampaignPageChromeProvider role="leader">
|
|
<CampaignWizardChromeProvider>
|
|
<CampaignHomeSearchChromeProvider>
|
|
<CampaignMobileTopBar />
|
|
</CampaignHomeSearchChromeProvider>
|
|
</CampaignWizardChromeProvider>
|
|
</CampaignPageChromeProvider>
|
|
</SidebarProvider>,
|
|
)
|
|
|
|
const topBar = container.querySelector('[data-slot="campaign-mobile-top-bar"]')
|
|
expect(topBar?.getAttribute('data-mode')).toBe('app')
|
|
expect(screen.getByRole('button', { name: 'Abrir ou fechar menu da campanha' })).toBeTruthy()
|
|
})
|
|
|
|
it('renders wizard entry mode with dismiss control and flow title', () => {
|
|
renderTopBar({
|
|
wizardChrome: {
|
|
flowTitle: 'Ajustar votos',
|
|
stepKind: 'entry',
|
|
dismissHref: '/campanha',
|
|
},
|
|
})
|
|
|
|
expect(screen.getByText('Ajustar votos')).toBeTruthy()
|
|
expect(screen.getByRole('link', { name: 'Sair da ação' }).getAttribute('href')).toBe(
|
|
'/campanha',
|
|
)
|
|
expect(screen.queryByRole('link', { name: /Voltar/ })).toBeNull()
|
|
})
|
|
|
|
it('renders wizard continue mode with back link and municipality subtitle', () => {
|
|
renderTopBar({
|
|
wizardChrome: {
|
|
flowTitle: 'Ajustar votos',
|
|
municipalityLabel: 'Cairu',
|
|
stepKind: 'continue',
|
|
previousHref: '/campanha/acoes/atualizar-votos',
|
|
dismissHref: '/campanha',
|
|
},
|
|
})
|
|
|
|
expect(screen.getByRole('link', { name: /Voltar/ }).getAttribute('href')).toBe(
|
|
'/campanha/acoes/atualizar-votos',
|
|
)
|
|
expect(screen.getByLabelText('Município em atualização: Cairu').textContent).toBe('Cairu')
|
|
expect(screen.getByRole('link', { name: 'Sair da ação' })).toBeTruthy()
|
|
})
|
|
|
|
it('renders dismiss on every wizard step and never a skip link (B168)', () => {
|
|
renderTopBar({
|
|
wizardChrome: {
|
|
flowTitle: 'Registrar atualização',
|
|
stepKind: 'continue',
|
|
previousHref: '/campanha/acoes/atualizar-votos?municipio=cairu',
|
|
dismissHref: '/campanha',
|
|
},
|
|
})
|
|
|
|
expect(screen.getByRole('link', { name: 'Sair da ação' }).getAttribute('href')).toBe(
|
|
'/campanha',
|
|
)
|
|
expect(screen.queryByRole('link', { name: 'Pular' })).toBeNull()
|
|
})
|
|
|
|
it('keeps wizard mode when chrome updates between steps', () => {
|
|
const { rerender } = render(
|
|
<SidebarProvider>
|
|
<CampaignPageChromeProvider role="coordinator">
|
|
<CampaignWizardChromeProvider>
|
|
<CampaignHomeSearchChromeProvider>
|
|
<WizardChromeProbe
|
|
chrome={{
|
|
flowTitle: 'Ajustar votos',
|
|
stepKind: 'entry',
|
|
dismissHref: '/campanha',
|
|
}}
|
|
/>
|
|
<CampaignMobileTopBar />
|
|
</CampaignHomeSearchChromeProvider>
|
|
</CampaignWizardChromeProvider>
|
|
</CampaignPageChromeProvider>
|
|
</SidebarProvider>,
|
|
)
|
|
|
|
expect(screen.queryByText('Municípios')).toBeNull()
|
|
|
|
rerender(
|
|
<SidebarProvider>
|
|
<CampaignPageChromeProvider role="coordinator">
|
|
<CampaignWizardChromeProvider>
|
|
<CampaignHomeSearchChromeProvider>
|
|
<WizardChromeProbe
|
|
chrome={{
|
|
flowTitle: 'Ajustar votos',
|
|
municipalityLabel: 'Cairu',
|
|
stepKind: 'continue',
|
|
previousHref: '/campanha/acoes/atualizar-votos',
|
|
dismissHref: '/campanha',
|
|
}}
|
|
/>
|
|
<CampaignMobileTopBar />
|
|
</CampaignHomeSearchChromeProvider>
|
|
</CampaignWizardChromeProvider>
|
|
</CampaignPageChromeProvider>
|
|
</SidebarProvider>,
|
|
)
|
|
|
|
const topBar = document.querySelector('[data-slot="campaign-mobile-top-bar"]')
|
|
expect(topBar?.getAttribute('data-mode')).toBe('wizard')
|
|
expect(screen.queryByText('Municípios')).toBeNull()
|
|
expect(screen.getByLabelText('Município em atualização: Cairu')).toBeTruthy()
|
|
})
|
|
})
|