teqo-backup/tests/unit/petitionPl5594Content.unit.spec.ts
Francisco Solla 5786bc57dc feat(petition): publica a petição do PL 5594/2026
A ferramenta de abaixo-assinado já existia, mas a petição do PL não tinha
caminho reproduzível fora do dump legado: produção só carregava as três
petições antigas editadas no admin. O conteúdo agora é versionado em
scripts/lib/petitionPl5594Content.mjs e provisionado por
pnpm seed:petition-pl-5594 — dry-run por padrão, create-if-missing por id,
Consent whatsapp-inscricao resolvido por chave (fail-closed) e guards de
escrita (PETITION_SEED_CONFIRM + TEQO_ENV casando o banco exato), sem
sobrescrever edição do admin.

O corpo traz os fatos do inteiro teor (autorização no registro, 5
exercícios de IR, sigilos bancário/fiscal/telefônico/de conexão, exclusão
do conteúdo das comunicações, auditoria, LGPD e divulgação pela Justiça
Eleitoral), a motivação de 18-19/10 sem acusar crime e o pedido sem
prometer aprovação. A copy hardcoded do bloco do formulário deixa de falar
em 'campanha'/'luta dos trabalhadores' e vira genérica.

Prova: unit full 475 arquivos/5238 testes verdes, lint/typecheck/format
limpos, seed aplicado e reaplicado em DB temporário (criação + no-op) e
smoke real no navegador (página 200, consent, assinatura nº 1). Sem
migration, collection, Consent novo ou mudança no fluxo de assinatura.
2026-10-22 00:51:20 -03:00

83 lines
3.5 KiB
TypeScript

// @vitest-environment node
import { describe, expect, it } from 'vitest'
import {
PETITION_BODY_HTML,
PETITION_BODY_SECTIONS,
PETITION_CONSENT_KEY,
PETITION_FORM_SUBTITLE,
PETITION_FORM_TITLE,
PETITION_ID,
PETITION_SUBTITLE,
PETITION_TITLE,
} from '../../scripts/lib/petitionPl5594Content.mjs'
// S48 — the PL 5594/2026 petition content is editorial but versioned: the seed
// writes it to a fresh/staging/production database, so these invariants are the
// guard against a silent editorial drift.
const plainText = PETITION_BODY_HTML.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ')
describe('petitionPl5594Content', () => {
it('pins the public identity (id is the URL and the signature FK)', () => {
expect(PETITION_ID).toBe('pl-5594-2026')
expect(PETITION_TITLE).toBe('Quem quer ser presidente deve abrir os sigilos')
expect(PETITION_SUBTITLE).toBe(
'Apoie o PL 5594/2026: candidatos à Presidência e à Vice-Presidência devem autorizar o acesso aos sigilos bancário, fiscal, telefônico e de internet.',
)
expect(PETITION_FORM_TITLE).toBe('Assine o abaixo-assinado')
expect(PETITION_FORM_SUBTITLE).toBe('Preencha seus dados para apoiar o PL 5594/2026.')
})
it('reuses the existing petition Consent by stable key, never by id', () => {
expect(PETITION_CONSENT_KEY).toBe('whatsapp-inscricao')
})
it('has the five planned sections with an h2 each', () => {
expect(PETITION_BODY_SECTIONS.map((section) => section.heading)).toEqual([
'O que o PL 5594/2026 propõe',
'Por que isso importa agora',
'O que o PL não faz',
'O pedido',
'Texto oficial e tramitação',
])
expect(PETITION_BODY_HTML.match(/<h2>/g)).toHaveLength(5)
for (const section of PETITION_BODY_SECTIONS) {
expect(section.html.trim().length).toBeGreaterThan(0)
}
})
it('carries the official facts of the bill', () => {
expect(plainText).toContain('cinco exercícios fiscais anteriores')
expect(plainText).toContain('excluído o conteúdo das comunicações')
expect(plainText).toContain('excluído o conteúdo de mensagens, arquivos')
expect(plainText).toContain('autoridades e órgãos públicos legalmente competentes')
expect(plainText).toContain('sistema de auditoria')
expect(plainText).toContain('proteção de dados pessoais')
expect(plainText).toContain('Justiça Eleitoral')
expect(PETITION_BODY_HTML).toContain(
'https://www.camara.leg.br/proposicoesWeb/fichadetramitacao?idProposicao=2648344',
)
expect(PETITION_BODY_HTML).toContain(
'https://www.camara.leg.br/proposicoesWeb/prop_mostrarintegra?codteor=3184912',
)
})
it('mentions the 18/10 debate without accusing anyone or promising approval', () => {
expect(plainText).toContain('18/10/2026')
expect(plainText).toContain('Lula desafiou Flávio Bolsonaro a abrir seus sigilos')
expect(plainText).toContain('19/10/2026')
// The law's own access purpose says "indícios concretos de ilícitos"; that
// is a legal competence, not an accusation. The guard is against naming a
// crime/irregularity as fact and against promising the bill's approval.
expect(plainText).not.toMatch(/\b(crime|corrupção|desvio|lavagem)\b/i)
expect(plainText).not.toMatch(
/será aprovad|vai ser aprovad|vamos aprovar|aprovação garantida|garantir a aprovação/i,
)
expect(plainText).toContain(
'não substitui a apuração de responsabilidades nem presume irregularidade',
)
})
})