Promote WEIGHTS const to named export with Object.freeze for downstream use in scoring.mjs (severity-weighted scoreByArea, F3). Tests: +2 cases asserting WEIGHTS shape.
146 lines
3.9 KiB
JavaScript
146 lines
3.9 KiB
JavaScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { SEVERITY, WEIGHTS, riskScore, verdict, riskBand, gradeFromPassRate, QUALITY_CATEGORIES } from '../../scanners/lib/severity.mjs';
|
|
|
|
describe('SEVERITY constants', () => {
|
|
it('has all 5 levels', () => {
|
|
assert.deepStrictEqual(Object.keys(SEVERITY).sort(), ['critical', 'high', 'info', 'low', 'medium']);
|
|
});
|
|
|
|
it('is frozen', () => {
|
|
assert.throws(() => { SEVERITY.critical = 'x'; }, TypeError);
|
|
});
|
|
});
|
|
|
|
describe('WEIGHTS named export (v5 F3 prep)', () => {
|
|
it('exposes critical=25', () => {
|
|
assert.strictEqual(WEIGHTS.critical, 25);
|
|
});
|
|
|
|
it('exposes high=10, medium=4, low=1, info=0', () => {
|
|
assert.strictEqual(WEIGHTS.high, 10);
|
|
assert.strictEqual(WEIGHTS.medium, 4);
|
|
assert.strictEqual(WEIGHTS.low, 1);
|
|
assert.strictEqual(WEIGHTS.info, 0);
|
|
});
|
|
});
|
|
|
|
describe('riskScore', () => {
|
|
it('returns 0 for empty counts', () => {
|
|
assert.strictEqual(riskScore({}), 0);
|
|
});
|
|
|
|
it('returns 0 for info-only findings', () => {
|
|
assert.strictEqual(riskScore({ info: 10 }), 0);
|
|
});
|
|
|
|
it('scores low findings at 1 point each', () => {
|
|
assert.strictEqual(riskScore({ low: 5 }), 5);
|
|
});
|
|
|
|
it('scores medium findings at 4 points each', () => {
|
|
assert.strictEqual(riskScore({ medium: 3 }), 12);
|
|
});
|
|
|
|
it('scores high findings at 10 points each', () => {
|
|
assert.strictEqual(riskScore({ high: 2 }), 20);
|
|
});
|
|
|
|
it('scores critical findings at 25 points each', () => {
|
|
assert.strictEqual(riskScore({ critical: 1 }), 25);
|
|
});
|
|
|
|
it('caps at 100', () => {
|
|
assert.strictEqual(riskScore({ critical: 10 }), 100);
|
|
});
|
|
|
|
it('combines all severities', () => {
|
|
assert.strictEqual(riskScore({ critical: 1, high: 1, medium: 1, low: 1, info: 1 }), 40);
|
|
});
|
|
});
|
|
|
|
describe('verdict', () => {
|
|
it('returns PASS for no findings', () => {
|
|
assert.strictEqual(verdict({}), 'PASS');
|
|
});
|
|
|
|
it('returns PASS for low findings only', () => {
|
|
assert.strictEqual(verdict({ low: 5, info: 10 }), 'PASS');
|
|
});
|
|
|
|
it('returns WARNING for any high finding', () => {
|
|
assert.strictEqual(verdict({ high: 1 }), 'WARNING');
|
|
});
|
|
|
|
it('returns FAIL for any critical finding', () => {
|
|
assert.strictEqual(verdict({ critical: 1 }), 'FAIL');
|
|
});
|
|
|
|
it('returns FAIL for score >= 61', () => {
|
|
assert.strictEqual(verdict({ high: 6, medium: 1 }), 'FAIL');
|
|
});
|
|
|
|
it('returns WARNING for score >= 21', () => {
|
|
assert.strictEqual(verdict({ medium: 6 }), 'WARNING');
|
|
});
|
|
});
|
|
|
|
describe('riskBand', () => {
|
|
it('returns Low for score 0', () => {
|
|
assert.strictEqual(riskBand(0), 'Low');
|
|
});
|
|
|
|
it('returns Low for score 10', () => {
|
|
assert.strictEqual(riskBand(10), 'Low');
|
|
});
|
|
|
|
it('returns Medium for score 11-30', () => {
|
|
assert.strictEqual(riskBand(20), 'Medium');
|
|
});
|
|
|
|
it('returns High for score 31-60', () => {
|
|
assert.strictEqual(riskBand(50), 'High');
|
|
});
|
|
|
|
it('returns Critical for score 61-80', () => {
|
|
assert.strictEqual(riskBand(70), 'Critical');
|
|
});
|
|
|
|
it('returns Extreme for score > 80', () => {
|
|
assert.strictEqual(riskBand(90), 'Extreme');
|
|
});
|
|
});
|
|
|
|
describe('gradeFromPassRate', () => {
|
|
it('returns A for 90+', () => {
|
|
assert.strictEqual(gradeFromPassRate(95), 'A');
|
|
});
|
|
|
|
it('returns B for 75-89', () => {
|
|
assert.strictEqual(gradeFromPassRate(80), 'B');
|
|
});
|
|
|
|
it('returns C for 60-74', () => {
|
|
assert.strictEqual(gradeFromPassRate(65), 'C');
|
|
});
|
|
|
|
it('returns D for 40-59', () => {
|
|
assert.strictEqual(gradeFromPassRate(50), 'D');
|
|
});
|
|
|
|
it('returns F for below 40', () => {
|
|
assert.strictEqual(gradeFromPassRate(20), 'F');
|
|
});
|
|
});
|
|
|
|
describe('QUALITY_CATEGORIES', () => {
|
|
it('has expected categories', () => {
|
|
assert.ok(QUALITY_CATEGORIES.STRUCTURE);
|
|
assert.ok(QUALITY_CATEGORIES.FEATURES);
|
|
assert.ok(QUALITY_CATEGORIES.SECURITY);
|
|
});
|
|
|
|
it('is frozen', () => {
|
|
assert.throws(() => { QUALITY_CATEGORIES.NEW = 'x'; }, TypeError);
|
|
});
|
|
});
|