import { describe, it, expect } from 'vitest'; import { formatTriageNote, type TriageNoteEvidence } from './triage-note-format'; import type { BlastRadiusResult } from './mimecast-blast-radius'; function baseEvidence(overrides: Partial = {}): TriageNoteEvidence { return { campaignId: 'campaign-1', reportCount: 3, companyName: 'Acme Corp', subject: 'Your invoice is ready', verdict: 'THREAT', confidence: 0.85, summary: 'Credential-harvesting link found in message body.', reasons: ['Sender domain not in allowlist', 'URL matches known phishing indicator'], recommendedActions: ['block_sender', 'purge_message'], requiresApproval: true, blastRadius: { status: 'unavailable', reason: 'not_configured' }, remediationActions: [], urls: [], ...overrides, }; } describe('formatTriageNote', () => { it('includes the verdict label and confidence value', () => { const output = formatTriageNote(baseEvidence()); expect(output).toContain('THREAT'); expect(output).toContain('0.85'); }); it('includes a Summary line and a Reasons section listing each reason', () => { const output = formatTriageNote(baseEvidence()); expect(output).toContain('Credential-harvesting link found in message body.'); expect(output).toContain('Sender domain not in allowlist'); expect(output).toContain('URL matches known phishing indicator'); }); it('shows delivered/held/rejected/clicked counts when blast radius is ok', () => { const ok: BlastRadiusResult = { status: 'ok', matched: 5, delivered: 3, held: 1, rejected: 1, clicked: 2, perRecipient: [{ recipient: 'user@acme.example', status: 'delivered' }], source: 'fan-out', }; const output = formatTriageNote(baseEvidence({ blastRadius: ok })); expect(output).toContain('3'); expect(output).toContain('1'); expect(output).toContain('2'); }); it('shows an explicit unavailable reason when blast radius is unavailable', () => { const output = formatTriageNote( baseEvidence({ blastRadius: { status: 'unavailable', reason: 'not_configured' } }) ); expect(output).toContain('unavailable'); expect(output).toContain('not_configured'); }); it('states no action taken when remediationActions is empty', () => { const output = formatTriageNote(baseEvidence({ remediationActions: [] })); expect(output.toLowerCase()).toMatch(/proposed|no action/); }); it('lists each remediation action with status and approver when present', () => { const output = formatTriageNote( baseEvidence({ remediationActions: [ { actionType: 'block_sender', status: 'approved', approvedBy: 'operator@example.com', approvedAt: '2026-07-01T00:00:00Z' }, { actionType: 'purge_message', status: 'completed', approvedBy: 'operator@example.com', approvedAt: '2026-07-01T00:00:00Z' }, ], }) ); expect(output).toContain('block_sender'); expect(output).toContain('approved'); expect(output).toContain('purge_message'); expect(output).toContain('completed'); expect(output).toContain('operator@example.com'); }); it('renders indicator URLs in sanitized form, dropping query strings', () => { const output = formatTriageNote(baseEvidence({ urls: ['http://evil.example/p?token=leak'] })); expect(output).not.toContain('token=leak'); expect(output).toContain('http://evil.example/p'); }); it('never leaks a secret embedded in free-text fields (sanitizeNoteText applied to whole output)', () => { const output = formatTriageNote( baseEvidence({ summary: 'Found link http://evil.example/x?access_token=SECRETVALUE in body' }) ); expect(output).not.toContain('access_token=SECRETVALUE'); }); it('handles null verdict/confidence gracefully without throwing', () => { expect(() => formatTriageNote(baseEvidence({ verdict: null, confidence: null })) ).not.toThrow(); const output = formatTriageNote(baseEvidence({ verdict: null, confidence: null })); expect(output.toLowerCase()).toContain('not yet classified'); }); });