teqo/tests/unit/campaignInviteInteractions.unit.spec.ts
Francisco Ignácio Fontoura Solla cf13c441aa Remodel /campanha around predefined Praças replacing electoral nuclei.
436 seeded Praças (municipality-based; per-TSE-zone in Salvador/Camaçari) become
the operational unit; roles renamed to coordinator/advisor/leader with advisors
scoped to administered Praças. Leadership is one record per person across many
Praças/organizations; vote pledges split leader-declared vs staff-estimated
(estimates never serialized to leaders). Adds organizations, demand workflow
with staff-only cost/receipts, action-plan results with deputy presence, manual
political trend, multi-candidate comparison and the diverging red/white/blue
map mode. Migration 20260721_020109_remodel_plazas deliberately resets the
campaign vertical in production (public site untouched); test suite ported to
the new model (unit 187 / int 306 / e2e 9 green).
2026-07-21 02:28:00 -03:00

93 lines
3.1 KiB
TypeScript

import { createElement } from 'react'
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
const inviteActionState = vi.hoisted(() => ({
createCampaignInvite: vi.fn(),
}))
vi.mock('@/app/(campaign)/campanha/actions/invite', () => ({
createCampaignInvite: inviteActionState.createCampaignInvite,
}))
import { LeadershipInviteButtons } from '@/components/campaign/LeadershipInviteButtons'
describe('campaign invite interactions', () => {
afterEach(() => {
cleanup()
vi.restoreAllMocks()
inviteActionState.createCampaignInvite.mockReset()
})
it('creates an autofill invite, links WhatsApp, and copies the invite URL', async () => {
const inviteUrl = 'https://example.com/campanha/convite/secret'
const whatsappUrl =
'https://wa.me/5571999990000?text=Convite%20https%3A%2F%2Fexample.com%2Fcampanha%2Fconvite%2Fsecret'
inviteActionState.createCampaignInvite.mockResolvedValue({ inviteUrl, whatsappUrl })
const writeText = vi.fn(async () => undefined)
Object.defineProperty(navigator, 'clipboard', {
configurable: true,
value: { writeText },
})
render(
createElement(LeadershipInviteButtons, {
leadershipID: 31,
canInviteLogin: true,
}),
)
fireEvent.click(
screen.getByRole('button', { name: 'Convidar para completar cadastro' }),
)
await screen.findByText(/Convite para completar cadastro gerado/)
expect(inviteActionState.createCampaignInvite).toHaveBeenCalledWith({
leadership: 31,
kind: 'autopreenchimento',
})
const whatsappLink = screen.getByRole('link', { name: 'Enviar pelo WhatsApp' })
expect(whatsappLink.getAttribute('href')).toBe(whatsappUrl)
expect(whatsappLink.getAttribute('target')).toBe('_blank')
expect(whatsappLink.getAttribute('rel')).toBe('noopener noreferrer')
fireEvent.click(screen.getByRole('button', { name: 'Copiar link' }))
await waitFor(() => expect(writeText).toHaveBeenCalledWith(inviteUrl))
expect(await screen.findByRole('button', { name: 'Link copiado' })).toBeTruthy()
})
it('hides the login invite button when the leadership is not engaged', () => {
render(
createElement(LeadershipInviteButtons, {
leadershipID: 31,
canInviteLogin: false,
}),
)
expect(screen.queryByRole('button', { name: 'Convidar para o app' })).toBeNull()
})
it('shows the fail-closed consent message when the consent key is missing', async () => {
inviteActionState.createCampaignInvite.mockRejectedValue(
new Error('Consentimento ainda não configurado.'),
)
render(
createElement(LeadershipInviteButtons, {
leadershipID: 31,
canInviteLogin: true,
}),
)
fireEvent.click(screen.getByRole('button', { name: 'Convidar para o app' }))
expect(
await screen.findByText(/Consentimento ainda não configurado — peça a um admin/),
).toBeTruthy()
expect(inviteActionState.createCampaignInvite).toHaveBeenCalledWith({
leadership: 31,
kind: 'login',
})
})
})