mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
1ad329f9cf
Co-authored-by: alejandrobailo <alejandrobailo94@gmail.com> Co-authored-by: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com>
101 lines
2.7 KiB
TypeScript
101 lines
2.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { Framework, REQUIREMENT_STATUS } from "@/types/compliance";
|
|
|
|
import { getTopFailedSections } from "./threat-helpers";
|
|
import { THREATSCORE_PILLARS } from "./threatscore-pillars";
|
|
|
|
const buildFramework = (
|
|
categoriesSpec: Array<{
|
|
name: string;
|
|
statuses: Array<"PASS" | "FAIL" | "MANUAL">;
|
|
}>,
|
|
): Framework => ({
|
|
name: "ProwlerThreatScore",
|
|
pass: 0,
|
|
fail: 0,
|
|
manual: 0,
|
|
categories: categoriesSpec.map((spec) => ({
|
|
name: spec.name,
|
|
pass: 0,
|
|
fail: 0,
|
|
manual: 0,
|
|
controls: [
|
|
{
|
|
label: "control-0",
|
|
pass: 0,
|
|
fail: 0,
|
|
manual: 0,
|
|
requirements: spec.statuses.map((status, i) => ({
|
|
name: `${spec.name}-req-${i}`,
|
|
description: "",
|
|
status: REQUIREMENT_STATUS[status],
|
|
check_ids: [],
|
|
pass: 0,
|
|
fail: 0,
|
|
manual: 0,
|
|
})),
|
|
},
|
|
],
|
|
})),
|
|
});
|
|
|
|
describe("threat.getTopFailedSections", () => {
|
|
it("returns every canonical pillar with zero-fill when no failures", () => {
|
|
const data = [buildFramework([{ name: "1. IAM", statuses: ["PASS"] }])];
|
|
const result = getTopFailedSections(data);
|
|
|
|
expect(result.items.map((i) => i.name)).toEqual([...THREATSCORE_PILLARS]);
|
|
expect(result.items.every((i) => i.total === 0)).toBe(true);
|
|
});
|
|
|
|
it("counts FAIL requirements per category and keeps canonical order", () => {
|
|
const data = [
|
|
buildFramework([
|
|
{ name: "1. IAM", statuses: ["FAIL", "FAIL"] },
|
|
{ name: "4. Encryption", statuses: ["FAIL"] },
|
|
]),
|
|
];
|
|
const result = getTopFailedSections(data);
|
|
|
|
expect(result.items).toEqual([
|
|
{ name: "1. IAM", total: 2 },
|
|
{ name: "2. Attack Surface", total: 0 },
|
|
{ name: "3. Logging and Monitoring", total: 0 },
|
|
{ name: "4. Encryption", total: 1 },
|
|
]);
|
|
});
|
|
|
|
it("appends non-canonical sections after the canonical ones", () => {
|
|
const data = [
|
|
buildFramework([
|
|
{ name: "1. IAM", statuses: ["FAIL"] },
|
|
{ name: "5. Data Protection", statuses: ["FAIL", "FAIL"] },
|
|
]),
|
|
];
|
|
const result = getTopFailedSections(data);
|
|
|
|
expect(result.items.map((i) => i.name)).toEqual([
|
|
"1. IAM",
|
|
"2. Attack Surface",
|
|
"3. Logging and Monitoring",
|
|
"4. Encryption",
|
|
"5. Data Protection",
|
|
]);
|
|
expect(
|
|
result.items.find((i) => i.name === "5. Data Protection")?.total,
|
|
).toBe(2);
|
|
});
|
|
|
|
it("ignores PASS and MANUAL when counting failures", () => {
|
|
const data = [
|
|
buildFramework([
|
|
{ name: "1. IAM", statuses: ["PASS", "MANUAL", "FAIL", "PASS"] },
|
|
]),
|
|
];
|
|
const result = getTopFailedSections(data);
|
|
|
|
expect(result.items.find((i) => i.name === "1. IAM")?.total).toBe(1);
|
|
});
|
|
});
|