teqo/tests/unit/wizardExpectedVotesStep.unit.spec.tsx
Cursor Agent 346949d035
B98 — Encadear ajustes do wizard após a ação principal
Após salvar (ou Pular) votos/tendência/sinal/liderança, navega ao
próximo elo da matriz v1 no mesmo município via entryAction, em vez
de voltar ao Início. Helper puro wizardActionChain + skips alinhados.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 11:41:26 +00:00

122 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { WizardExpectedVotesStep } from '@/components/campaign/shared/WizardExpectedVotesStep'
import { CampaignWizardChromeProvider } from '@/components/campaign/shell/CampaignWizardChromeContext'
import { CAMPAIGN_ACTIONS_HOME } from '@/lib/campaignActionRoutes'
import { postCampaignJson } from '@/lib/campaignJsonRequest'
const replaceMock = vi.fn()
vi.mock('next/navigation', () => ({
useRouter: () => ({
push: vi.fn(),
replace: replaceMock,
}),
}))
vi.mock('@/lib/campaignJsonRequest', () => ({
postCampaignJson: vi.fn(),
}))
vi.mock('sonner', () => ({
toast: { success: vi.fn() },
}))
const defaultProps = {
actionSlug: 'atualizar-votos',
municipalityId: 1,
municipalityName: 'Cairu',
municipalitySlug: 'cairu',
initialExpectedVotes: { pessimistic: 100, central: 200, optimistic: 300 },
}
const renderVotesStep = (props: React.ComponentProps<typeof WizardExpectedVotesStep>) =>
render(
<CampaignWizardChromeProvider>
<WizardExpectedVotesStep {...props} />
</CampaignWizardChromeProvider>,
)
describe('WizardExpectedVotesStep', () => {
afterEach(() => {
cleanup()
vi.mocked(postCampaignJson).mockReset()
replaceMock.mockReset()
})
it('applies shortcuts to the focused scenario', () => {
renderVotesStep({ ...defaultProps })
fireEvent.focus(screen.getByLabelText('Pessimista'))
fireEvent.click(screen.getByRole('button', { name: '2×' }))
expect((screen.getByLabelText('Pessimista') as HTMLInputElement).value).toBe('200')
expect((screen.getByLabelText('Média') as HTMLInputElement).value).toBe('200')
})
it('shows violation alert and highlights inputs without navigation', () => {
renderVotesStep({ ...defaultProps })
fireEvent.change(screen.getByLabelText('Pessimista'), { target: { value: '900' } })
fireEvent.click(screen.getByRole('button', { name: 'Salvar estimativas →' }))
const step = screen.getByRole('main', { name: /Ajustar votos estimados/i })
expect(within(step).getByRole('alert').textContent).toMatch(/Pessimista/i)
expect(screen.getByLabelText('Pessimista').getAttribute('aria-invalid')).toBe('true')
expect(screen.getByLabelText('Média').getAttribute('aria-invalid')).toBe('true')
})
it('clears violation when a draft is edited', () => {
renderVotesStep({ ...defaultProps })
fireEvent.change(screen.getByLabelText('Pessimista'), { target: { value: '900' } })
fireEvent.click(screen.getByRole('button', { name: 'Salvar estimativas →' }))
const step = screen.getByRole('main', { name: /Ajustar votos estimados/i })
expect(within(step).getByRole('alert')).toBeTruthy()
fireEvent.change(screen.getByLabelText('Média'), { target: { value: '950' } })
expect(within(step).queryByRole('alert')).toBeNull()
expect(screen.getByLabelText('Pessimista').getAttribute('aria-invalid')).toBeNull()
})
it('posts batch expected votes and continues the wizard chain', async () => {
vi.mocked(postCampaignJson).mockResolvedValue({
ok: true,
payload: {
status: 'success',
savedExpectedVotes: { pessimistic: 150, central: 250, optimistic: 350 },
},
})
renderVotesStep({ ...defaultProps })
fireEvent.change(screen.getByLabelText('Pessimista'), { target: { value: '150' } })
fireEvent.change(screen.getByLabelText('Média'), { target: { value: '250' } })
fireEvent.change(screen.getByLabelText('Otimista'), { target: { value: '350' } })
fireEvent.click(screen.getByRole('button', { name: 'Salvar estimativas →' }))
await waitFor(() => {
expect(postCampaignJson).toHaveBeenCalledWith('/campanha/municipios/expected-votes', {
municipalityId: 1,
expectedVotes: { pessimistic: 150, central: 250, optimistic: 350 },
})
})
await waitFor(() => {
expect(replaceMock).toHaveBeenCalledWith(
`${CAMPAIGN_ACTIONS_HOME}/mudar-tendencia?municipio=cairu&entry=update-votes`,
)
})
})
it('shows skip to the next chain step when votes is chained', () => {
renderVotesStep({ ...defaultProps, entryAction: 'register-signal' })
const skip = screen.getByRole('link', { name: /Pular ajuste de votos/i })
expect(skip.getAttribute('href')).toBe(
`${CAMPAIGN_ACTIONS_HOME}/atualizar-lideranca?municipio=cairu&entry=register-signal`,
)
})
})