/**
 * Tests for evaluation harness
 */
import { describe, it, expect } from "vitest";
import { matchFindings } from "./harness.js";
describe("harness", () => {
    describe("matchFindings", () => {
        it("matches findings with exact file and line", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "sql-injection",
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    message: "SQL injection vulnerability",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(1);
            expect(result.falsePositives.length).toBe(0);
            expect(result.falseNegatives.length).toBe(0);
        });
        it("matches findings within 5 line tolerance", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "xss",
                    file: "render.ts",
                    line: 12,
                    severity: "high",
                    message: "XSS vulnerability",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "render.ts",
                    line: 10,
                    severity: "high",
                    category: "xss",
                    description: "XSS vulnerability",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(1);
        });
        it("does not match findings beyond 5 line tolerance", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "xss",
                    file: "render.ts",
                    line: 20,
                    severity: "high",
                    message: "XSS vulnerability",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "render.ts",
                    line: 10,
                    severity: "high",
                    category: "xss",
                    description: "XSS vulnerability",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(0);
            expect(result.falsePositives.length).toBe(1);
            expect(result.falseNegatives.length).toBe(1);
        });
        it("handles case-insensitive file matching", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "sqli",
                    file: "./DB.ts",
                    line: 10,
                    severity: "critical",
                    message: "sql injection found",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(1);
        });
        it("identifies false positives", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "false-alarm",
                    file: "safe.ts",
                    line: 5,
                    severity: "high",
                    message: "Potential issue",
                    confidence: 100,
                },
            ];
            const expected = [];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(0);
            expect(result.falsePositives.length).toBe(1);
            expect(result.falseNegatives.length).toBe(0);
        });
        it("identifies false negatives", () => {
            const actual = [];
            const expected = [
                {
                    file: "vulnerable.ts",
                    line: 10,
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(0);
            expect(result.falsePositives.length).toBe(0);
            expect(result.falseNegatives.length).toBe(1);
        });
        it("ignores non-vulnerable expected findings", () => {
            const actual = [];
            const expected = [
                {
                    file: "safe.ts",
                    line: 10,
                    severity: "low",
                    category: "sql-injection",
                    description: "Safe parameterized query",
                    isVulnerable: false,
                },
            ];
            const result = matchFindings(actual, expected);
            // Non-vulnerable findings should not be counted as false negatives
            expect(result.falseNegatives.length).toBe(0);
        });
        it("handles multiple findings correctly", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "sqli",
                    file: "a.ts",
                    line: 5,
                    severity: "critical",
                    message: "sql injection",
                    confidence: 100,
                },
                {
                    scanner: "gitleaks",
                    ruleId: "aws-key",
                    file: "b.ts",
                    line: 10,
                    severity: "critical",
                    message: "AWS key found",
                    confidence: 100,
                },
                {
                    scanner: "semgrep",
                    ruleId: "unused",
                    file: "c.ts",
                    line: 15,
                    severity: "low",
                    message: "Unused variable",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "a.ts",
                    line: 5,
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    isVulnerable: true,
                },
                {
                    file: "b.ts",
                    line: 10,
                    severity: "critical",
                    category: "secrets",
                    description: "Hardcoded secret",
                    isVulnerable: true,
                },
                {
                    file: "d.ts",
                    line: 20,
                    severity: "high",
                    category: "xss",
                    description: "Missed XSS",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(2); // a.ts and b.ts matched
            expect(result.falsePositives.length).toBe(1); // c.ts is a false positive
            expect(result.falseNegatives.length).toBe(1); // d.ts was missed
        });
        it("matches based on CWE ID", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "CWE-89-sql",
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    message: "Potential SQL issue",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    category: "command-injection", // Different category
                    cweId: "CWE-89",
                    description: "SQL injection",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(1);
        });
        it("handles relative path matching", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "sqli",
                    file: "/tmp/project/src/db.ts",
                    line: 10,
                    severity: "critical",
                    message: "SQL injection",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            expect(result.truePositives.length).toBe(1);
        });
        it("only matches each finding once", () => {
            const actual = [
                {
                    scanner: "semgrep",
                    ruleId: "sqli-1",
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    message: "SQL injection pattern 1",
                    confidence: 100,
                },
                {
                    scanner: "semgrep",
                    ruleId: "sqli-2",
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    message: "SQL injection pattern 2",
                    confidence: 100,
                },
            ];
            const expected = [
                {
                    file: "db.ts",
                    line: 10,
                    severity: "critical",
                    category: "sql-injection",
                    description: "SQL injection",
                    isVulnerable: true,
                },
            ];
            const result = matchFindings(actual, expected);
            // Only one should match, the other is a false positive
            expect(result.truePositives.length).toBe(1);
            expect(result.falsePositives.length).toBe(1);
            expect(result.falseNegatives.length).toBe(0);
        });
    });
});
//# sourceMappingURL=harness.test.js.map