/**
 * Tests for compliance mapper
 */
import { describe, it, expect } from "vitest";
import { getControlsForFramework, findingMatchesControl, meetsSeverityThreshold, mapFindingsToControls, calculateComplianceStatus, generateRecommendations, generateComplianceReport, generateMultiFrameworkReport, } from "./mapper.js";
import { SOC2_CONTROLS } from "./soc2.js";
describe("compliance mapper", () => {
    describe("getControlsForFramework", () => {
        it("returns SOC 2 controls", () => {
            const controls = getControlsForFramework("SOC2");
            expect(controls.length).toBeGreaterThan(0);
            expect(controls[0].framework).toBe("SOC2");
        });
        it("returns ISO 27001 controls", () => {
            const controls = getControlsForFramework("ISO27001");
            expect(controls.length).toBeGreaterThan(0);
            expect(controls[0].framework).toBe("ISO27001");
        });
        it("returns empty array for unsupported framework", () => {
            const controls = getControlsForFramework("UNKNOWN");
            expect(controls).toEqual([]);
        });
    });
    describe("findingMatchesControl", () => {
        const mockControl = {
            id: "CC6.8",
            framework: "SOC2",
            category: "Logical and Physical Access",
            title: "Malicious Software Prevention",
            description: "Prevention of malicious software",
            keywords: ["injection", "xss", "malware"],
            findingCategories: ["xss", "sql-injection"],
            cweIds: ["CWE-79", "CWE-89"],
        };
        it("matches by finding category", () => {
            const finding = {
                id: "sec-001",
                severity: "high",
                category: "xss",
                description: "Cross-site scripting vulnerability",
                evidence: "Test evidence for XSS finding",
                confidence: 90,
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(findingMatchesControl(finding, mockControl)).toBe(true);
        });
        it("matches by CWE ID", () => {
            const finding = {
                id: "sec-002",
                severity: "high",
                category: "other",
                description: "Some vulnerability",
                evidence: "Test evidence",
                confidence: 90,
                cwe_ids: ["CWE-79"],
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(findingMatchesControl(finding, mockControl)).toBe(true);
        });
        it("matches by keyword in description", () => {
            const finding = {
                id: "sec-003",
                severity: "high",
                category: "other",
                description: "Potential XSS injection vulnerability found",
                evidence: "Test evidence",
                confidence: 90,
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(findingMatchesControl(finding, mockControl)).toBe(true);
        });
        it("does not match unrelated finding", () => {
            const finding = {
                id: "sec-004",
                severity: "medium",
                category: "type-safety",
                description: "Using any type",
                evidence: "Test evidence",
                confidence: 90,
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(findingMatchesControl(finding, mockControl)).toBe(false);
        });
    });
    describe("meetsSeverityThreshold", () => {
        const controlWithThreshold = {
            id: "test",
            framework: "SOC2",
            category: "test",
            title: "Test",
            description: "Test",
            keywords: [],
            findingCategories: [],
            severityThreshold: "medium",
        };
        it("returns true when severity meets threshold", () => {
            const finding = {
                id: "test",
                severity: "high",
                category: "test",
                description: "Test",
                evidence: "Test",
                confidence: 90,
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(meetsSeverityThreshold(finding, controlWithThreshold)).toBe(true);
        });
        it("returns true when severity equals threshold", () => {
            const finding = {
                id: "test",
                severity: "medium",
                category: "test",
                description: "Test",
                evidence: "Test",
                confidence: 90,
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(meetsSeverityThreshold(finding, controlWithThreshold)).toBe(true);
        });
        it("returns false when severity is below threshold", () => {
            const finding = {
                id: "test",
                severity: "low",
                category: "test",
                description: "Test",
                evidence: "Test",
                confidence: 90,
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(meetsSeverityThreshold(finding, controlWithThreshold)).toBe(false);
        });
        it("returns true when control has no threshold", () => {
            const controlNoThreshold = {
                id: "test",
                framework: "SOC2",
                category: "test",
                title: "Test",
                description: "Test",
                keywords: [],
                findingCategories: [],
            };
            const finding = {
                id: "test",
                severity: "info",
                category: "test",
                description: "Test",
                evidence: "Test",
                confidence: 90,
                verifications: [],
                created_at: new Date().toISOString(),
            };
            expect(meetsSeverityThreshold(finding, controlNoThreshold)).toBe(true);
        });
    });
    describe("mapFindingsToControls", () => {
        it("maps findings to SOC 2 controls", () => {
            const findings = [
                {
                    id: "sec-001",
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection vulnerability",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const mappings = mapFindingsToControls(findings, "SOC2");
            expect(mappings.length).toBe(SOC2_CONTROLS.length);
            // Find the control that should have the finding
            const cc68 = mappings.find((m) => m.control.id === "CC6.8");
            expect(cc68).toBeDefined();
            expect(cc68.findings.length).toBeGreaterThan(0);
            expect(cc68.status).toBe("non_compliant");
        });
        it("marks controls as compliant when no findings", () => {
            const mappings = mapFindingsToControls([], "SOC2");
            expect(mappings.every((m) => m.status === "compliant")).toBe(true);
        });
        it("marks controls as at_risk for medium severity findings", () => {
            // Use security-misconfiguration which has a medium severity threshold (CC7.1)
            const findings = [
                {
                    id: "sec-001",
                    severity: "medium",
                    category: "security-misconfiguration",
                    description: "Security misconfiguration detected",
                    evidence: "Test evidence for security misconfiguration",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const mappings = mapFindingsToControls(findings, "SOC2");
            const hasAtRisk = mappings.some((m) => m.status === "at_risk");
            expect(hasAtRisk).toBe(true);
        });
    });
    describe("calculateComplianceStatus", () => {
        it("calculates compliance score", () => {
            const mappings = mapFindingsToControls([], "SOC2");
            const status = calculateComplianceStatus("SOC2", mappings);
            expect(status.framework).toBe("SOC2");
            expect(status.complianceScore).toBe(100);
            expect(status.riskScore).toBe(0);
            expect(status.controlsCovered).toBe(SOC2_CONTROLS.length);
            expect(status.controlsAtRisk).toBe(0);
            expect(status.controlsNonCompliant).toBe(0);
        });
        it("calculates risk score based on findings", () => {
            const findings = [
                {
                    id: "sec-001",
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const mappings = mapFindingsToControls(findings, "SOC2");
            const status = calculateComplianceStatus("SOC2", mappings);
            expect(status.riskScore).toBeGreaterThan(0);
            expect(status.controlsNonCompliant).toBeGreaterThan(0);
        });
    });
    describe("generateRecommendations", () => {
        it("generates recommendations for non-compliant controls", () => {
            const findings = [
                {
                    id: "sec-001",
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const mappings = mapFindingsToControls(findings, "SOC2");
            const recommendations = generateRecommendations(mappings);
            expect(recommendations.length).toBeGreaterThan(0);
            expect(recommendations[0].priority).toBe("critical");
        });
        it("returns empty array when all controls compliant", () => {
            const mappings = mapFindingsToControls([], "SOC2");
            const recommendations = generateRecommendations(mappings);
            expect(recommendations).toEqual([]);
        });
        it("prioritizes recommendations by risk", () => {
            const findings = [
                {
                    id: "sec-001",
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
                {
                    id: "sec-002",
                    severity: "low",
                    category: "type-safety",
                    description: "Type issue",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const mappings = mapFindingsToControls(findings, "SOC2");
            const recommendations = generateRecommendations(mappings);
            // First recommendation should be critical
            if (recommendations.length > 1) {
                const priorities = ["critical", "high", "medium", "low"];
                const firstIndex = priorities.indexOf(recommendations[0].priority);
                const secondIndex = priorities.indexOf(recommendations[1].priority);
                expect(firstIndex).toBeLessThanOrEqual(secondIndex);
            }
        });
    });
    describe("generateComplianceReport", () => {
        it("generates a complete compliance report", () => {
            const findings = [
                {
                    id: "sec-001",
                    severity: "high",
                    category: "xss",
                    description: "XSS vulnerability",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const report = generateComplianceReport(findings, "SOC2", "/test/path", "cert-123");
            expect(report.id).toBeDefined();
            expect(report.framework).toBe("SOC2");
            expect(report.projectPath).toBe("/test/path");
            expect(report.certificationId).toBe("cert-123");
            expect(report.status).toBeDefined();
            expect(report.controls.length).toBe(SOC2_CONTROLS.length);
            expect(report.recommendations.length).toBeGreaterThan(0);
        });
    });
    describe("generateMultiFrameworkReport", () => {
        it("generates report for multiple frameworks", () => {
            const findings = [
                {
                    id: "sec-001",
                    severity: "high",
                    category: "sql-injection",
                    description: "SQL injection",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const report = generateMultiFrameworkReport(findings, ["SOC2", "ISO27001"], "/test/path");
            expect(report.id).toBeDefined();
            expect(report.frameworks.SOC2).toBeDefined();
            expect(report.frameworks.ISO27001).toBeDefined();
            expect(report.prioritizedRecommendations.length).toBeGreaterThan(0);
        });
        it("deduplicates recommendations across frameworks", () => {
            const findings = [
                {
                    id: "sec-001",
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    evidence: "Test evidence",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const report = generateMultiFrameworkReport(findings, ["SOC2", "ISO27001"], "/test/path");
            // Check for no duplicate control IDs in recommendations
            const controlIds = report.prioritizedRecommendations.map((r) => r.controlId);
            const uniqueIds = new Set(controlIds);
            expect(uniqueIds.size).toBe(controlIds.length);
        });
    });
});
//# sourceMappingURL=mapper.test.js.map