const { test } = require('node:test'); const assert = require('node:assert/strict'); const { validateAiClassification, VALID_CLASSIFICATIONS } = require('./classification'); function validRaw(overrides) { return Object.assign({ classification: 'ACTIONABLE_NOW', actionable_today: true, confidence: 0.91, blocker_type: null, waiting_for: null, next_action: 'Validar equipamento e registrar resultado.', suggested_action_type: 'technical_action', business_risk: 'medium', reason: 'Existe acao tecnica pendente.', evidence: ['ultimo apontamento indica necessidade de validacao'], }, overrides); } test('objeto valido passa e normaliza campos', () => { const result = validateAiClassification(validRaw({})); assert.equal(result.valid, true); assert.equal(result.data.classification, 'ACTIONABLE_NOW'); assert.equal(result.data.is_fallback, false); }); test('classification invalida falha com erro claro', () => { const result = validateAiClassification(validRaw({ classification: 'ALGO_INVENTADO' })); assert.equal(result.valid, false); assert.ok(result.errors.some((e) => e.includes('classification'))); }); test('JSON invalido/null nao lanca excecao', () => { assert.doesNotThrow(() => validateAiClassification(null)); assert.doesNotThrow(() => validateAiClassification('nao e objeto')); assert.equal(validateAiClassification(null).valid, false); }); test('next_action vazia ou so espacos falha (nao vazia e requisito minimo de qualidade)', () => { assert.equal(validateAiClassification(validRaw({ next_action: '' })).valid, false); assert.equal(validateAiClassification(validRaw({ next_action: ' ' })).valid, false); }); test('confidence fora de 0..1 falha', () => { const result = validateAiClassification(validRaw({ confidence: 1.5 })); assert.equal(result.valid, false); }); test('evidence e limitado a 5 itens', () => { const result = validateAiClassification(validRaw({ evidence: ['a', 'b', 'c', 'd', 'e', 'f', 'g'] })); assert.equal(result.data.evidence.length, 5); }); test('todas as classes do dominio sao aceitas', () => { for (const classification of VALID_CLASSIFICATIONS) { const result = validateAiClassification(validRaw({ classification })); assert.equal(result.valid, true, `classe ${classification} deveria ser valida`); } }); test('AI_FALLBACK nao esta no dominio de classes que a IA pode retornar', () => { assert.ok(!VALID_CLASSIFICATIONS.includes('AI_FALLBACK')); }); test('blocker_type/waiting_for como string "null" sao normalizados para null de verdade', () => { const result = validateAiClassification(validRaw({ blocker_type: 'null', waiting_for: 'None' })); assert.equal(result.valid, true); assert.equal(result.data.blocker_type, null); assert.equal(result.data.waiting_for, null); }); test('blocker_type/waiting_for como "n/a" ou string vazia tambem viram null', () => { const result = validateAiClassification(validRaw({ blocker_type: 'N/A', waiting_for: '' })); assert.equal(result.data.blocker_type, null); assert.equal(result.data.waiting_for, null); }); test('blocker_type/waiting_for com valor real nao sao afetados pela normalizacao', () => { const result = validateAiClassification(validRaw({ blocker_type: 'fornecedor', waiting_for: 'Patricia' })); assert.equal(result.data.blocker_type, 'fornecedor'); assert.equal(result.data.waiting_for, 'Patricia'); });