teqo-backup/tests/unit/petition-page-layout.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

63 lines
2.6 KiB
TypeScript

import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
describe('petition page layout', () => {
const pageSource = readFileSync(
resolve(process.cwd(), 'src/app/(frontend)/abaixo-assinado/[id]/page.tsx'),
'utf8',
)
const formSource = readFileSync(resolve(process.cwd(), 'src/components/PetitionForm.tsx'), 'utf8')
const stylesSource = readFileSync(resolve(process.cwd(), 'src/app/(frontend)/styles.css'), 'utf8')
const inputSource = readFileSync(resolve(process.cwd(), 'src/components/ui/input.tsx'), 'utf8')
const textareaSource = readFileSync(
resolve(process.cwd(), 'src/components/ui/textarea.tsx'),
'utf8',
)
const nativeSelectSource = readFileSync(
resolve(process.cwd(), 'src/components/ui/native-select.tsx'),
'utf8',
)
it('uses the main element as the vertical scroll container', () => {
const mainClass = pageSource.match(/<main[\s\S]*?className="([^"]+)"/)?.[1]
expect(mainClass?.split(/\s+/)).toEqual(
expect.arrayContaining(['h-screen', 'w-screen', 'overflow-y-auto']),
)
})
it('scopes the petition color system to the petition page', () => {
expect(pageSource).toContain('data-theme="petition"')
expect(stylesSource).toMatch(/\[data-theme=['"]petition['"]\]/)
expect(stylesSource).toContain('--petition-hero')
expect(stylesSource).toContain('--petition-form-section')
})
it('keeps petition form copy and consent HTML data-driven', () => {
expect(formSource).toContain('petition.form.subtitle')
expect(formSource).not.toContain('manter a orla de Salvador')
expect(pageSource).toContain('consentHTML')
expect(formSource).not.toContain('convertLexicalToHTML')
})
it('uses the generic mobilization copy instead of campaign/trabalhadores', () => {
const normalizedPage = pageSource.replace(/\s+/g, ' ')
expect(normalizedPage).toContain('Sua assinatura fortalece esta mobilização.')
expect(normalizedPage).toContain(
'Os dados serão usados apenas para registrar sua participação e a comunicação de conteúdos relacionados.',
)
expect(normalizedPage).not.toContain('fortalece a luta dos trabalhadores')
expect(normalizedPage).not.toContain('participação nesta campanha')
})
it('uses semantic field color variables for shared form controls', () => {
for (const source of [inputSource, textareaSource, nativeSelectSource]) {
expect(source).toContain('--field-background')
expect(source).toContain('--field-foreground')
expect(source).toContain('--field-border')
}
})
})