/**
 * Unit tests for sarif-upload module
 */
import { describe, it, expect, beforeEach, afterEach, afterAll } from "vitest";
import { mkdir, rm, readFile } from "fs/promises";
import { join } from "path";
import { tmpdir } from "os";
import { convertToSarif, writeSarifFile, getSarifFilePath } from "./sarif-upload.js";
const TEST_BASE = join(tmpdir(), "vaspera-sarif-test-" + Date.now() + "-" + Math.random().toString(36).slice(2));
let testDir;
beforeEach(async () => {
    testDir = join(TEST_BASE, "dir-" + Math.random().toString(36).slice(2));
    await mkdir(testDir, { recursive: true });
});
afterEach(async () => {
    try {
        await rm(testDir, { recursive: true, force: true });
    }
    catch {
        // Ignore cleanup errors
    }
});
afterAll(async () => {
    try {
        await rm(TEST_BASE, { recursive: true, force: true });
    }
    catch {
        // Ignore cleanup errors
    }
});
const createMockFinding = (overrides = {}) => ({
    scanner: "semgrep",
    ruleId: "semgrep:sql-injection",
    file: "src/db.ts",
    line: 42,
    message: "SQL injection vulnerability",
    severity: "high",
    confidence: 100,
    ...overrides,
});
const createMockScanResult = (findings = []) => ({
    timestamp: "2024-01-01T00:00:00.000Z",
    projectPath: "/test/project",
    scanners: [
        {
            scanner: "semgrep",
            findings,
            duration: 1000,
            success: true,
        },
    ],
    totalFindings: findings.length,
    bySeverity: {
        critical: findings.filter((f) => f.severity === "critical").length,
        high: findings.filter((f) => f.severity === "high").length,
        medium: findings.filter((f) => f.severity === "medium").length,
        low: findings.filter((f) => f.severity === "low").length,
        info: findings.filter((f) => f.severity === "info").length,
    },
    byScanner: {
        semgrep: findings.length,
        "npm-audit": 0,
        gitleaks: 0,
        tsc: 0,
        eslint: 0,
        bandit: 0,
        gosec: 0,
        brakeman: 0,
        trivy: 0,
        "binary-analysis": 0,
        "memory-safety": 0,
        "race-condition": 0,
        healthcare: 0,
        plugin: 0,
        logic: 0,
        dast: 0,
        zap: 0,
        nuclei: 0,
        terraform: 0,
        tfsec: 0,
        checkov: 0,
        openapi: 0,
        spectral: 0,
        rust: 0,
        "cargo-audit": 0,
        clippy: 0,
        detection: 0,
    },
    totalDuration: 1000,
    allSucceeded: true,
    failedScanners: [],
});
describe("convertToSarif", () => {
    it("generates valid SARIF structure", () => {
        const scanResult = createMockScanResult();
        const sarif = convertToSarif(scanResult);
        expect(sarif.$schema).toContain("sarif-schema-2.1.0.json");
        expect(sarif.version).toBe("2.1.0");
        expect(sarif.runs).toHaveLength(1);
    });
    it("includes tool information", () => {
        const scanResult = createMockScanResult();
        const sarif = convertToSarif(scanResult);
        const tool = sarif.runs[0].tool.driver;
        expect(tool.name).toBe("Vaspera Hardening");
        expect(tool.version).toBeDefined();
        expect(tool.informationUri).toContain("github.com");
    });
    it("converts findings to SARIF results", () => {
        const findings = [
            createMockFinding({ ruleId: "rule-1", file: "a.ts", line: 10 }),
            createMockFinding({ ruleId: "rule-2", file: "b.ts", line: 20 }),
        ];
        const scanResult = createMockScanResult(findings);
        const sarif = convertToSarif(scanResult);
        expect(sarif.runs[0].results).toHaveLength(2);
    });
    it("includes rule definitions", () => {
        const findings = [
            createMockFinding({ ruleId: "semgrep:sql-injection" }),
            createMockFinding({ ruleId: "semgrep:xss" }),
        ];
        const scanResult = createMockScanResult(findings);
        const sarif = convertToSarif(scanResult);
        const rules = sarif.runs[0].tool.driver.rules;
        expect(rules).toHaveLength(2);
        expect(rules.map((r) => r.id)).toContain("semgrep:sql-injection");
        expect(rules.map((r) => r.id)).toContain("semgrep:xss");
    });
    it("maps severity to SARIF level", () => {
        const findings = [
            createMockFinding({ severity: "critical", ruleId: "rule-1" }),
            createMockFinding({ severity: "high", ruleId: "rule-2" }),
            createMockFinding({ severity: "medium", ruleId: "rule-3" }),
            createMockFinding({ severity: "low", ruleId: "rule-4" }),
            createMockFinding({ severity: "info", ruleId: "rule-5" }),
        ];
        const scanResult = createMockScanResult(findings);
        const sarif = convertToSarif(scanResult);
        const results = sarif.runs[0].results;
        expect(results[0].level).toBe("error"); // critical
        expect(results[1].level).toBe("error"); // high
        expect(results[2].level).toBe("warning"); // medium
        expect(results[3].level).toBe("note"); // low
        expect(results[4].level).toBe("note"); // info
    });
    it("includes file location in results", () => {
        const findings = [createMockFinding({ file: "src/api/users.ts", line: 100, column: 5 })];
        const scanResult = createMockScanResult(findings);
        const sarif = convertToSarif(scanResult);
        const location = sarif.runs[0].results[0].locations[0].physicalLocation;
        expect(location.artifactLocation.uri).toBe("src/api/users.ts");
        expect(location.region.startLine).toBe(100);
        expect(location.region.startColumn).toBe(5);
    });
    it("includes automation details", () => {
        const scanResult = createMockScanResult();
        const sarif = convertToSarif(scanResult);
        expect(sarif.runs[0].automationDetails).toBeDefined();
        expect(sarif.runs[0].automationDetails?.id).toContain("vaspera-hardening");
    });
    it("generates fingerprints for deduplication", () => {
        const findings = [createMockFinding()];
        const scanResult = createMockScanResult(findings);
        const sarif = convertToSarif(scanResult);
        const result = sarif.runs[0].results[0];
        expect(result.fingerprints).toBeDefined();
        expect(result.fingerprints?.primaryLocationLineHash).toBeDefined();
    });
    it("includes security-severity score", () => {
        const findings = [createMockFinding({ severity: "critical" })];
        const scanResult = createMockScanResult(findings);
        const sarif = convertToSarif(scanResult);
        const rule = sarif.runs[0].tool.driver.rules[0];
        expect(rule.properties?.["security-severity"]).toBe("9.0");
    });
    it("handles empty scan results", () => {
        const scanResult = createMockScanResult([]);
        const sarif = convertToSarif(scanResult);
        expect(sarif.runs[0].results).toHaveLength(0);
        expect(sarif.runs[0].tool.driver.rules).toHaveLength(0);
    });
});
describe("writeSarifFile", () => {
    it("writes SARIF to file", async () => {
        const scanResult = createMockScanResult([createMockFinding()]);
        const sarif = convertToSarif(scanResult);
        const outputPath = join(testDir, "results.sarif");
        await writeSarifFile(sarif, outputPath);
        const content = await readFile(outputPath, "utf-8");
        const parsed = JSON.parse(content);
        expect(parsed.$schema).toContain("sarif-schema-2.1.0.json");
        expect(parsed.version).toBe("2.1.0");
    });
    it("returns the output path", async () => {
        const sarif = convertToSarif(createMockScanResult());
        const outputPath = join(testDir, "output.sarif");
        const result = await writeSarifFile(sarif, outputPath);
        expect(result).toBe(outputPath);
    });
    it("writes formatted JSON", async () => {
        const sarif = convertToSarif(createMockScanResult());
        const outputPath = join(testDir, "formatted.sarif");
        await writeSarifFile(sarif, outputPath);
        const content = await readFile(outputPath, "utf-8");
        // Formatted JSON has newlines
        expect(content).toContain("\n");
    });
});
describe("getSarifFilePath", () => {
    it("returns path in working directory", () => {
        const path = getSarifFilePath("/project/root");
        expect(path).toBe("/project/root/vaspera-results.sarif");
    });
    it("uses correct filename", () => {
        const path = getSarifFilePath("/any/path");
        expect(path).toContain("vaspera-results.sarif");
    });
});
//# sourceMappingURL=sarif-upload.test.js.map