docs: enterprise refactor plan with ralph specs
This commit is contained in:
91
tests/server/cli.test.ts
Normal file
91
tests/server/cli.test.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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>');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user