/**
 * TypeScript AST Transform Tests
 */
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { mkdtemp, rm, writeFile } from "fs/promises";
import { join } from "path";
import { tmpdir } from "os";
import { transformXSS, transformHardcodedSecrets, transformIDOR, hasASTTransform, listASTTransforms, applyASTTransform, } from "../typescript.js";
describe("AST Transforms", () => {
    let tempDir;
    beforeEach(async () => {
        tempDir = await mkdtemp(join(tmpdir(), `ast-test-${Math.random().toString(36).slice(2, 8)}-`));
    });
    afterEach(async () => {
        await rm(tempDir, { recursive: true, force: true });
    });
    describe("hasASTTransform", () => {
        it("returns true for supported categories", () => {
            expect(hasASTTransform("sql-injection")).toBe(true);
            expect(hasASTTransform("xss")).toBe(true);
            expect(hasASTTransform("secrets")).toBe(true);
            expect(hasASTTransform("idor")).toBe(true);
        });
        it("returns false for unsupported categories", () => {
            expect(hasASTTransform("unknown")).toBe(false);
            expect(hasASTTransform("random")).toBe(false);
        });
        it("is case-insensitive", () => {
            expect(hasASTTransform("SQL-INJECTION")).toBe(true);
            expect(hasASTTransform("XSS")).toBe(true);
        });
    });
    describe("listASTTransforms", () => {
        it("returns all available transforms", () => {
            const transforms = listASTTransforms();
            expect(transforms).toContain("sql-injection");
            expect(transforms).toContain("xss");
            expect(transforms).toContain("hardcoded-secrets");
            expect(transforms).toContain("secrets");
            expect(transforms).toContain("idor");
            expect(transforms).toContain("authorization");
        });
    });
    describe("transformXSS", () => {
        it("transforms innerHTML to textContent", async () => {
            const filePath = join(tempDir, "xss.ts");
            const code = `
function render(userInput: string) {
  document.getElementById("target").innerHTML = userInput;
}
`;
            await writeFile(filePath, code, "utf-8");
            const context = {
                filePath,
                projectPath: tempDir,
                finding: {
                    id: "test-1",
                    file: "xss.ts",
                    line: 3,
                    category: "xss",
                    description: "innerHTML assignment",
                },
            };
            const result = await transformXSS(context);
            expect(result.success).toBe(true);
            expect(result.changesApplied.length).toBeGreaterThan(0);
            expect(result.transformedCode).toContain("textContent");
            expect(result.transformedCode).not.toContain("innerHTML");
        });
        it("handles insertAdjacentHTML", async () => {
            const filePath = join(tempDir, "xss2.ts");
            const code = `
function insertContent(el: HTMLElement, content: string) {
  el.insertAdjacentHTML("beforeend", content);
}
`;
            await writeFile(filePath, code, "utf-8");
            const context = {
                filePath,
                projectPath: tempDir,
                finding: {
                    id: "test-2",
                    file: "xss2.ts",
                    line: 3,
                    category: "xss",
                    description: "insertAdjacentHTML usage",
                },
            };
            const result = await transformXSS(context);
            expect(result.success).toBe(true);
            expect(result.changesApplied.length).toBeGreaterThan(0);
        });
    });
    describe("transformHardcodedSecrets", () => {
        it("replaces hardcoded API key with env var", async () => {
            const filePath = join(tempDir, "secrets.ts");
            const code = `
const apiKey = "sk_live_1234567890abcdef";
const config = { apiKey };
`;
            await writeFile(filePath, code, "utf-8");
            const context = {
                filePath,
                projectPath: tempDir,
                finding: {
                    id: "test-3",
                    file: "secrets.ts",
                    line: 2,
                    category: "secrets",
                    description: "Hardcoded API key",
                },
            };
            const result = await transformHardcodedSecrets(context);
            expect(result.success).toBe(true);
            expect(result.changesApplied.length).toBeGreaterThan(0);
            expect(result.transformedCode).toContain("process.env");
            expect(result.transformedCode).not.toContain("sk_live_");
        });
        it("converts camelCase to SCREAMING_SNAKE_CASE for env vars", async () => {
            const filePath = join(tempDir, "secrets2.ts");
            const code = `
const secretKey = "super_secret_value_123456";
`;
            await writeFile(filePath, code, "utf-8");
            const context = {
                filePath,
                projectPath: tempDir,
                finding: {
                    id: "test-4",
                    file: "secrets2.ts",
                    line: 2,
                    category: "secrets",
                    description: "Hardcoded secret",
                },
            };
            const result = await transformHardcodedSecrets(context);
            expect(result.success).toBe(true);
            expect(result.transformedCode).toContain("SECRET_KEY");
        });
    });
    describe("transformIDOR", () => {
        it("adds ownership check to database access", async () => {
            const filePath = join(tempDir, "idor.ts");
            const code = `
async function getUser(req: Request) {
  const user = await db.users.findById(req.params.id);
  return user;
}
`;
            await writeFile(filePath, code, "utf-8");
            const context = {
                filePath,
                projectPath: tempDir,
                finding: {
                    id: "test-5",
                    file: "idor.ts",
                    line: 3,
                    category: "idor",
                    description: "IDOR vulnerability",
                },
            };
            const result = await transformIDOR(context);
            expect(result.success).toBe(true);
            expect(result.changesApplied.length).toBeGreaterThan(0);
            expect(result.transformedCode).toContain("userId");
            expect(result.transformedCode).toContain("Access denied");
        });
    });
    describe("applyASTTransform", () => {
        it("applies correct transform based on category", async () => {
            const filePath = join(tempDir, "generic.ts");
            const code = `
document.body.innerHTML = userInput;
`;
            await writeFile(filePath, code, "utf-8");
            const context = {
                filePath,
                projectPath: tempDir,
                finding: {
                    id: "test-6",
                    file: "generic.ts",
                    line: 2,
                    category: "xss",
                    description: "XSS vulnerability",
                },
            };
            const result = await applyASTTransform("xss", context);
            expect(result.success).toBe(true);
        });
        it("returns error for unknown category", async () => {
            const filePath = join(tempDir, "unknown.ts");
            await writeFile(filePath, "const x = 1;", "utf-8");
            const context = {
                filePath,
                projectPath: tempDir,
                finding: {
                    id: "test-7",
                    file: "unknown.ts",
                    line: 1,
                    category: "unknown",
                    description: "Unknown",
                },
            };
            const result = await applyASTTransform("unknown", context);
            expect(result.success).toBe(false);
            expect(result.error).toContain("No AST transform available");
        });
    });
});
//# sourceMappingURL=typescript.test.js.map