Files
Gustavo Santos d21c4596e1 chore: import relatorio (subtree)
git-subtree-dir: relatorio
git-subtree-mainline: e322cec92b
git-subtree-split: 34bcb132f3
2026-10-01 14:26:02 -03:00

170 lines
5.6 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const {
formatFallbackMessage,
computeOperationalStatus,
buildDestaques,
formatShortMessage,
} = require('../src/v2/format');
const { loadConfig } = require('../src/v2/config');
const config = loadConfig();
test('formatFallbackMessage reproduz o formato atual da V1 (numeros do exemplo da missao, 20/08)', () => {
const row = {
tipo_periodo: 'diario',
periodo_label: '2026-08-20',
abertos: 12,
fechados: 11,
pendentes: 22,
alta_prioridade_pendentes: 3,
saldo: -1,
categorias_recorrentes: 'Software / SO: 4\nBug / Falha do Sistema: 2',
clientes_volume: 'IMDI: 2 chamados\nLaboratorio da Cidade: 2 chamados',
};
const texto = formatFallbackMessage(row);
assert.match(texto, /Resumo diario do suporte GLPI/);
assert.match(texto, /Data do relatorio: 2026-08-20/);
assert.match(texto, /Chamados abertos no dia: 12/);
assert.match(texto, /Chamados fechados no dia: 11/);
assert.match(texto, /Pendentes atuais: 22/);
assert.match(texto, /Alta prioridade ainda pendentes: 3/);
assert.match(texto, /Saldo fechados - abertos: -1/);
assert.match(texto, /Software \/ SO: 4/);
assert.match(texto, /IMDI: 2 chamados/);
});
test('formatFallbackMessage nunca lanca excecao com dados vazios (fallback tem que ser sempre seguro)', () => {
assert.doesNotThrow(() => {
formatFallbackMessage({
tipo_periodo: 'diario',
periodo_label: '2026-08-20',
abertos: 0,
fechados: 0,
pendentes: 0,
alta_prioridade_pendentes: 0,
saldo: 0,
categorias_recorrentes: '',
clientes_volume: '',
});
});
});
test('computeOperationalStatus: sem insights e backlog estavel -> NORMAL', () => {
const s = computeOperationalStatus({ insightsAceitos: [], tendenciaBacklog: { direcao: 'estavel' } });
assert.equal(s, 'NORMAL');
});
test('computeOperationalStatus: insight severity high -> CRITICAL mesmo com backlog estavel', () => {
const s = computeOperationalStatus({
insightsAceitos: [{ severity: 'high' }],
tendenciaBacklog: { direcao: 'estavel' },
});
assert.equal(s, 'CRITICAL');
});
test('computeOperationalStatus: backlog aumentando sem insights -> ATTENTION', () => {
const s = computeOperationalStatus({ insightsAceitos: [], tendenciaBacklog: { direcao: 'aumentando' } });
assert.equal(s, 'ATTENTION');
});
test('buildDestaques nao produz mais itens que MAX_REPORT_INSIGHTS', () => {
const insightsAceitos = Array.from({ length: 10 }, (_, i) => ({ title: `Insight ${i}`, occurrenceText: null }));
const destaques = buildDestaques(
{ topCategoria: null, concentracoesCliente: [], altaPrioridadeDelta: null, insightsAceitos, unidade: 'no dia' },
config
);
assert.ok(destaques.length <= config.MAX_REPORT_INSIGHTS);
});
test('buildDestaques nao inventa destaque de alta prioridade quando o valor nao mudou', () => {
const destaques = buildDestaques(
{
topCategoria: null,
concentracoesCliente: [],
altaPrioridadeDelta: { anterior: 3, atual: 3 },
insightsAceitos: [],
unidade: 'no dia',
},
config
);
assert.equal(destaques.length, 0);
});
test('formatShortMessage: mensagem diaria contem os numeros oficiais e fica curta (sem paragrafos longos)', () => {
const { texto, status } = formatShortMessage(
{
tipo_periodo: 'diario',
data_inicio: '2026-08-20',
data_fim: '2026-08-20',
abertos: 12,
fechados: 11,
saldo: -1,
pendentes: 22,
alta_prioridade_pendentes: 3,
topCategoria: { nome: 'Software / SO', total: 4 },
concentracoesCliente: [],
altaPrioridadeDelta: { anterior: 2, atual: 3 },
insightsAceitos: [],
tendenciaBacklog: { direcao: 'aumentando', delta: 2 },
},
config
);
assert.match(texto, /Resumo do suporte — 20\/08/);
assert.match(texto, /12 abertos \| 11 fechados \| saldo -1/);
assert.match(texto, /22 pendentes \| 3 alta prioridade/);
assert.match(texto, /Software \/ SO liderou no dia com 4 chamados\./);
assert.match(texto, /subiram de 2 para 3/);
assert.equal(status, 'ATTENTION');
assert.ok(texto.length < 700, `mensagem deveria ser curta, tinha ${texto.length} chars`);
});
test('formatShortMessage: sem nenhum destaque real, mostra a frase padrao (nao inventa observacao)', () => {
const { texto } = formatShortMessage(
{
tipo_periodo: 'diario',
data_inicio: '2026-08-20',
data_fim: '2026-08-20',
abertos: 5,
fechados: 5,
saldo: 0,
pendentes: 10,
alta_prioridade_pendentes: 1,
topCategoria: null,
concentracoesCliente: [],
altaPrioridadeDelta: null,
insightsAceitos: [],
tendenciaBacklog: { direcao: 'estavel', delta: 0 },
},
config
);
assert.match(texto, /Sem anomalias relevantes no periodo\./);
});
test('formatShortMessage: mensagem semanal usa titulo e secao "Leitura"', () => {
const { texto } = formatShortMessage(
{
tipo_periodo: 'semanal',
data_inicio: '2026-08-17',
data_fim: '2026-08-23',
abertos: 51,
fechados: 52,
saldo: 1,
pendentes: 21,
alta_prioridade_pendentes: 3,
topCategoria: { nome: 'Bug / Falha do Sistema', total: 9 },
concentracoesCliente: [],
altaPrioridadeDelta: null,
insightsAceitos: [],
tendenciaBacklog: { direcao: 'estavel', delta: 0 },
},
config
);
assert.match(texto, /Resumo semanal do suporte — 17\/08 a 23\/08/);
assert.match(texto, /51 abertos \| 52 fechados \| saldo \+1/);
assert.match(texto, /Leitura/);
assert.match(texto, /→ Semana equilibrada/);
});