Iniciativa Cidadã Independente · Transparência Parlamentar
TS174 linhas7.854 bytes

apps/worker/tests/premiacao-edicoes.ts

SHA-256

a53accea68aa533a0231ccea97f13ba9e7a93151cb9bfb629934c68c51d71ed9

Somente leiturafonte-0531042d9f3e
/**
 * Testes das edições do prêmio, do certificado e do e-mail de entrega.
 * Só funções puras: não abre banco, rede nem Chrome.
 *   pnpm --filter worker test:premiacao-edicoes
 */
import assert from 'node:assert/strict'
import {
  definirEdicao,
  edicoesPossiveis,
  normalizarCodigo,
  EdicaoInvalida,
} from '../src/services/premiacao-edicoes'
import type { Certificado, DadosCertificado } from '../src/services/premiacao-edicoes'
import { dataPorExtenso, justificativa, nomeArquivo } from '../src/services/certificado'
import { montarEmail } from '../src/services/premiacao-email'
import { REGUA_ANO, REGUA_LEGISLATURA } from '../src/services/premiacao'

let passou = 0
let total = 0
function teste(nome: string, fn: () => void) {
  total++
  try {
    fn()
    passou++
    console.log(`ok    ${nome}`)
  } catch (err) {
    console.log(`FALHA ${nome}\n      ${(err as Error).message}`)
  }
}

function dados(over: Partial<DadosCertificado> = {}): DadosCertificado {
  return {
    codigo: 'OS-L57-7K3M-Q9XA',
    edicao: {
      id: 'leg57', tipo: 'legislatura', titulo: '57ª Legislatura (2023–2027)',
      subtitulo: 'Edição da Legislatura', periodo: { inicio: '2023-02-01', fim: '2027-01-31' },
      apuracaoSha256: 'a'.repeat(64),
    },
    categoria: {
      id: 'regional_ne', eixo: 'regional', titulo: 'Destaque Nordeste', descricao: '',
      ambito: 'Região Nordeste', concorrentes: 23,
    },
    senador: { codigo: '1', nome: 'Fulana de Tal', tratamento: 'Senadora', partido: 'PXX', uf: 'BA' },
    idsTotal: 78.4,
    valor: 78.4,
    indicador: { rotulo: 'Composição do IDS', valor: 78.4, unidade: 'de 100', detalhe: 'em 47 meses de exercício' },
    houveDesempate: false,
    emitidoEm: '2027-02-01',
    ...over,
  }
}

function cert(d: DadosCertificado): Certificado {
  return {
    codigo: d.codigo, edicaoId: d.edicao.id, categoriaId: d.categoria.id, senadorCod: d.senador.codigo,
    dados: d, pdfSha256: null, pdfGerado: false, emitidoEm: d.emitidoEm, email: null,
    emailOficial: null, enviadoEm: null, envios: 0, envioErro: null, revogadoEm: null, motivoRevogacao: null,
  }
}

teste('há uma edição da legislatura e uma por ano legislativo da Leg 57', () => {
  assert.deepEqual(edicoesPossiveis().map((e) => e.id),
    ['leg57', 'leg57-2023', 'leg57-2024', 'leg57-2025', 'leg57-2026'])
})

teste('o ano de 2023 começa com a legislatura, não em 1º de janeiro', () => {
  assert.deepEqual(definirEdicao('ano', 57, 2023).periodo, { inicio: '2023-02-01', fim: '2023-12-31' })
  assert.deepEqual(definirEdicao('ano', 57, 2025).periodo, { inicio: '2025-01-01', fim: '2025-12-31' })
})

teste('sessão legislativa ordinal no subtítulo do ano', () => {
  assert.equal(definirEdicao('ano', 57, 2025).subtitulo, '3ª Sessão Legislativa da 57ª Legislatura')
})

teste('edições anuais usam a régua de meio ano; a legislatura, a de meia legislatura', () => {
  assert.equal(definirEdicao('ano', 57, 2024).regua, REGUA_ANO)
  assert.equal(definirEdicao('legislatura', 57).regua, REGUA_LEGISLATURA)
  assert.ok(REGUA_ANO.mesesMinVitoria <= 11, 'um ano tem no máximo 11 meses contáveis')
})

teste('legislatura não suportada e ano fora da Leg 57 são recusados', () => {
  assert.throws(() => definirEdicao('legislatura', 58), EdicaoInvalida)
  assert.throws(() => definirEdicao('ano', 57, 2027), EdicaoInvalida)
})

teste('código digitado com caixa, espaços e O/I/L trocados é normalizado', () => {
  assert.equal(normalizarCodigo(' os-l57-7k3m-q9xa '), 'OS-L57-7K3M-Q9XA')
  assert.equal(normalizarCodigo('OS-L57-O1IL-AB0C'), 'OS-L57-0111-AB0C')
  assert.equal(normalizarCodigo('OS-A25-LLLL-OOOO'), 'OS-A25-1111-0000', 'o prefixo não é tocado')
})

teste('data por extenso usa ordinal no dia 1', () => {
  assert.equal(dataPorExtenso('2027-02-01'), '1º de fevereiro de 2027')
  assert.equal(dataPorExtenso('2026-10-29T10:00:00Z'), '29 de outubro de 2026')
})

teste('justificativa regional cita a nota, os concorrentes e a região', () => {
  assert.equal(
    justificativa(dados()),
    'Maior Índice de Desempenho Senatorial de 78,4 em 100 entre 23 concorrentes da Região Nordeste, em 47 meses de exercício.',
  )
})

teste('justificativa temática mostra o número contado, sem repetir a unidade', () => {
  const t = justificativa(dados({
    categoria: { id: 'fiscalizacao', eixo: 'tematico', titulo: 'Fiscalização e Relatoria',
      descricao: 'Relatorias assumidas por mês.', ambito: 'Temático', concorrentes: 74 },
    indicador: { rotulo: 'Relatorias', valor: 150, unidade: 'relatorias', detalhe: 'em 40 meses de exercício' },
  }))
  assert.equal(t, 'Relatorias assumidas por mês. Primeiro lugar entre 74 concorrentes, com 150 relatorias em 40 meses de exercício.')
})

teste('justificativa de presença e de CEAP formata % e R$', () => {
  const pres = justificativa(dados({
    categoria: { id: 'participacao', eixo: 'tematico', titulo: 'Presença', descricao: 'X.', ambito: 'Temático', concorrentes: 80 },
    indicador: { rotulo: 'Presença em plenário', valor: 97.5, unidade: '%', detalhe: '390 de 400 votações em plenário' },
  }))
  assert.match(pres, /com 97,5% de presença em plenário \(390 de 400/)
  const ceap = justificativa(dados({
    categoria: { id: 'ceap', eixo: 'tematico', titulo: 'CEAP', descricao: 'X.', ambito: 'Temático', concorrentes: 80 },
    indicador: { rotulo: 'Cota parlamentar', valor: 12345.6, unidade: 'R$/mês', detalhe: 'R$ 500.000 no total' },
  }))
  assert.match(ceap, /média de R\$ 12\.346 por mês na cota parlamentar/)
})

teste('saudação segue a forma oficial de tratamento', () => {
  assert.match(montarEmail([cert(dados())]).texto, /^Excelentíssima Senhora Senadora Fulana de Tal,/)
  const masc = dados({ senador: { ...dados().senador, tratamento: 'Senador', nome: 'Fulano' } })
  assert.match(montarEmail([cert(masc)]).texto, /^Excelentíssimo Senhor Senador Fulano,/)
})

teste('sem tratamento oficial, a saudação é neutra', () => {
  const d = dados({ senador: { ...dados().senador, tratamento: 'Senador(a)' } })
  assert.match(montarEmail([cert(d)]).texto, /^Ao Gabinete de Senador\(a\) Fulana de Tal,/)
})

teste('o corpo do e-mail não depende de gênero', () => {
  const texto = montarEmail([cert(dados())]).texto.split('\n').slice(1).join('\n')
  assert.doesNotMatch(texto, /reconhecid[oa]\b|premiad[oa]\b|agraciad[oa]\b/)
})

teste('vários certificados: plural no assunto e uma linha por categoria', () => {
  const a = cert(dados())
  const b = cert(dados({ codigo: 'OS-L57-AAAA-BBBB', categoria: { ...dados().categoria, id: 'grande_premio', titulo: 'Grande Prêmio', eixo: 'grande_premio', ambito: 'Nacional' } }))
  const e = montarEmail([a, b])
  assert.match(e.assunto, /certificados de reconhecimento$/)
  assert.match(e.texto, /em 2 categorias/)
  assert.match(e.texto, /OS-L57-7K3M-Q9XA/)
  assert.match(e.texto, /OS-L57-AAAA-BBBB/)
})

teste('teste e reenvio marcam o assunto', () => {
  assert.match(montarEmail([cert(dados())], { teste: true }).assunto, /^\[TESTE\] /)
  assert.match(montarEmail([cert(dados())], { reenvio: true }).assunto, /^Reenvio: /)
})

teste('assinatura do e-mail e do certificado é só institucional', () => {
  const { texto, html } = montarEmail([cert(dados())], { mensagem: 'Divulgação em fevereiro.' })
  assert.match(texto, /Respeitosamente,\nObservatório do Senado\n/)
  assert.match(html, /Divulgação em fevereiro\./)
})

teste('mensagem do admin é escapada no HTML', () => {
  const { html } = montarEmail([cert(dados())], { mensagem: '<script>x</script>' })
  assert.doesNotMatch(html, /<script>x/)
})

teste('nome do arquivo sem acento nem espaço', () => {
  assert.equal(nomeArquivo(dados()), 'certificado-leg57-destaque-nordeste-fulana-de-tal.pdf')
})

console.log(`\n${passou}/${total} testes passaram`)
if (passou !== total) process.exit(1)