92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
/**
|
|
* Tests for CLI flag parsing and exit code logic.
|
|
* These test the logic functions extracted from the CLI, not the CLI process itself.
|
|
*/
|
|
|
|
describe('CLI exit code logic', () => {
|
|
const severityRank: Record<string, number> = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
|
|
function shouldFailOnSeverity(
|
|
anomalies: Array<{ severity: string }>,
|
|
threshold: string
|
|
): boolean {
|
|
const thresholdRank = severityRank[threshold] ?? 0;
|
|
return anomalies.some((a) => (severityRank[a.severity] ?? 0) >= thresholdRank);
|
|
}
|
|
|
|
it('exit 0 when no anomalies', () => {
|
|
expect(shouldFailOnSeverity([], 'high')).toBe(false);
|
|
});
|
|
|
|
it('exit 1 when anomaly at threshold', () => {
|
|
expect(shouldFailOnSeverity([{ severity: 'high' }], 'high')).toBe(true);
|
|
});
|
|
|
|
it('exit 1 when anomaly above threshold', () => {
|
|
expect(shouldFailOnSeverity([{ severity: 'critical' }], 'high')).toBe(true);
|
|
});
|
|
|
|
it('exit 0 when anomaly below threshold', () => {
|
|
expect(shouldFailOnSeverity([{ severity: 'low' }], 'high')).toBe(false);
|
|
});
|
|
|
|
it('exit 0 when medium anomaly and threshold is high', () => {
|
|
expect(shouldFailOnSeverity([{ severity: 'medium' }], 'high')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('JUnit XML generation', () => {
|
|
function buildJunit(
|
|
anomalies: Array<{ id: string; type: string; severity: string; description: string }>,
|
|
url: string
|
|
): string {
|
|
function escapeXml(s: string): string {
|
|
return s
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"');
|
|
}
|
|
const cases = anomalies
|
|
.map(
|
|
(a) =>
|
|
` <testcase name="${escapeXml(a.description)}" classname="abe.anomaly.${escapeXml(a.type)}">\n` +
|
|
` <failure message="${escapeXml(a.description)}" type="${escapeXml(a.severity)}">${escapeXml(a.id)}</failure>\n` +
|
|
` </testcase>`
|
|
)
|
|
.join('\n');
|
|
return (
|
|
`<?xml version="1.0" encoding="UTF-8"?>\n` +
|
|
`<testsuite name="ABE Exploration: ${escapeXml(url)}" tests="${anomalies.length}" failures="${anomalies.length}">\n` +
|
|
cases + '\n' +
|
|
`</testsuite>\n`
|
|
);
|
|
}
|
|
|
|
it('generates valid XML with one anomaly', () => {
|
|
const xml = buildJunit(
|
|
[{ id: 'a1', type: 'http_error', severity: 'high', description: 'Server error on form' }],
|
|
'http://localhost:3000'
|
|
);
|
|
expect(xml).toContain('<testsuite');
|
|
expect(xml).toContain('<failure');
|
|
expect(xml).toContain('http_error');
|
|
expect(xml).toContain('Server error on form');
|
|
});
|
|
|
|
it('generates empty testsuite for no anomalies', () => {
|
|
const xml = buildJunit([], 'http://localhost:3000');
|
|
expect(xml).toContain('tests="0"');
|
|
expect(xml).not.toContain('<failure');
|
|
});
|
|
|
|
it('escapes XML special characters', () => {
|
|
const xml = buildJunit(
|
|
[{ id: 'a1', type: 'http_error', severity: 'high', description: '<script>alert(1)</script>' }],
|
|
'http://app.com'
|
|
);
|
|
expect(xml).not.toContain('<script>');
|
|
expect(xml).toContain('<script>');
|
|
});
|
|
});
|