import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { join } from "path";
import { mkdir, writeFile, rm, readFile } from "fs/promises";
import { tmpdir } from "os";
import { loadFlow, discoverFlows, generateSampleFlow, runFlow, } from "../../../scanners/runtime/golden-path-runner.js";
describe("golden-path-runner", () => {
    let testDir;
    beforeEach(async () => {
        testDir = join(tmpdir(), `golden-path-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
        await mkdir(testDir, { recursive: true });
    });
    afterEach(async () => {
        await rm(testDir, { recursive: true, force: true });
    });
    describe("loadFlow", () => {
        it("loads a valid YAML flow", async () => {
            const flowContent = `
name: "test-flow"
description: "A test flow"
priority: high
steps:
  - action: navigate
    url: "/"
  - action: assert
    url: "/"
`;
            const flowPath = join(testDir, "test.yaml");
            await writeFile(flowPath, flowContent);
            const flow = await loadFlow(flowPath);
            expect(flow.name).toBe("test-flow");
            expect(flow.priority).toBe("high");
            expect(flow.steps).toHaveLength(2);
        });
        it("throws on invalid YAML", async () => {
            const flowPath = join(testDir, "invalid.yaml");
            await writeFile(flowPath, "invalid: yaml: content:");
            await expect(loadFlow(flowPath)).rejects.toThrow();
        });
        it("throws on schema validation failure", async () => {
            const flowContent = `
name: "test"
priority: "invalid-priority"
steps: []
`;
            const flowPath = join(testDir, "invalid-schema.yaml");
            await writeFile(flowPath, flowContent);
            await expect(loadFlow(flowPath)).rejects.toThrow();
        });
    });
    describe("discoverFlows", () => {
        it("discovers all flows in .vaspera/flows/", async () => {
            const flowsDir = join(testDir, ".vaspera/flows");
            await mkdir(flowsDir, { recursive: true });
            const flow1 = `name: "flow1"\nsteps:\n  - action: navigate\n    url: "/"`;
            const flow2 = `name: "flow2"\nsteps:\n  - action: navigate\n    url: "/about"`;
            await writeFile(join(flowsDir, "flow1.yaml"), flow1);
            await writeFile(join(flowsDir, "flow2.yml"), flow2);
            const flows = await discoverFlows(testDir);
            expect(flows).toHaveLength(2);
            expect(flows.map((f) => f.flow.name).sort()).toEqual(["flow1", "flow2"]);
        });
        it("returns empty array when no flows directory", async () => {
            const flows = await discoverFlows(testDir);
            expect(flows).toEqual([]);
        });
        it("skips invalid flow files", async () => {
            const flowsDir = join(testDir, ".vaspera/flows");
            await mkdir(flowsDir, { recursive: true });
            const validFlow = `name: "valid"\nsteps:\n  - action: navigate\n    url: "/"`;
            const invalidFlow = `name: 123\nsteps: "not an array"`;
            await writeFile(join(flowsDir, "valid.yaml"), validFlow);
            await writeFile(join(flowsDir, "invalid.yaml"), invalidFlow);
            const flows = await discoverFlows(testDir);
            expect(flows).toHaveLength(1);
            expect(flows[0].flow.name).toBe("valid");
        });
        it("ignores non-yaml files", async () => {
            const flowsDir = join(testDir, ".vaspera/flows");
            await mkdir(flowsDir, { recursive: true });
            await writeFile(join(flowsDir, "flow.yaml"), `name: "flow"\nsteps:\n  - action: wait\n    timeout: 100`);
            await writeFile(join(flowsDir, "readme.md"), "# README");
            await writeFile(join(flowsDir, "config.json"), "{}");
            const flows = await discoverFlows(testDir);
            expect(flows).toHaveLength(1);
        });
    });
    describe("generateSampleFlow", () => {
        it("creates a sample flow file", async () => {
            const flowPath = await generateSampleFlow(testDir, "checkout");
            expect(flowPath).toBe(join(testDir, ".vaspera/flows/checkout.yaml"));
            const content = await readFile(flowPath, "utf-8");
            expect(content).toContain('name: "checkout"');
            expect(content).toContain("action: navigate");
        });
        it("creates flows directory if not exists", async () => {
            await generateSampleFlow(testDir, "test");
            const flows = await discoverFlows(testDir);
            expect(flows).toHaveLength(1);
        });
        it("uses default name when not specified", async () => {
            const flowPath = await generateSampleFlow(testDir);
            expect(flowPath).toContain("sample.yaml");
        });
    });
    describe("runFlow", () => {
        it("executes navigate step successfully", async () => {
            const flow = {
                name: "navigate-test",
                priority: "medium",
                steps: [
                    { action: "navigate", url: "/" },
                ],
            };
            const result = await runFlow(flow, "http://example.com");
            expect(result.flowName).toBe("navigate-test");
            expect(result.totalSteps).toBe(1);
            expect(result.steps[0].action).toBe("navigate");
        });
        it("executes wait step", async () => {
            const flow = {
                name: "wait-test",
                priority: "medium",
                steps: [
                    { action: "wait", timeout: 100 },
                ],
            };
            const startTime = Date.now();
            const result = await runFlow(flow, "http://example.com");
            const elapsed = Date.now() - startTime;
            expect(result.success).toBe(true);
            expect(elapsed).toBeGreaterThanOrEqual(100);
        });
        it("marks Playwright-required actions as skipped", async () => {
            const flow = {
                name: "playwright-test",
                priority: "medium",
                steps: [
                    { action: "click", selector: "#button" },
                    { action: "fill", selector: "#input", value: "test" },
                    { action: "screenshot" },
                ],
            };
            const result = await runFlow(flow, "http://example.com");
            expect(result.success).toBe(true);
            for (const step of result.steps) {
                expect(step.error).toContain("Playwright");
                expect(step.error).toContain("skipped");
            }
        });
        it("stops on failure and marks remaining as skipped", async () => {
            const flow = {
                name: "failure-test",
                priority: "medium",
                steps: [
                    { action: "navigate", url: "/" },
                    { action: "navigate", url: "http://localhost:99999/nonexistent" },
                    { action: "wait", timeout: 100 },
                ],
            };
            const result = await runFlow(flow, "http://example.com");
            expect(result.success).toBe(false);
            expect(result.failedSteps).toBeGreaterThan(0);
            const lastStep = result.steps[result.steps.length - 1];
            expect(lastStep.error).toContain("previous failure");
        });
        it("calculates step durations", async () => {
            const flow = {
                name: "duration-test",
                priority: "medium",
                steps: [
                    { action: "wait", timeout: 50 },
                ],
            };
            const result = await runFlow(flow, "http://example.com");
            expect(result.steps[0].duration).toBeGreaterThanOrEqual(45);
            expect(result.duration).toBeGreaterThanOrEqual(45);
        });
        it("handles URL assertion", async () => {
            const flow = {
                name: "assert-test",
                priority: "medium",
                steps: [
                    { action: "navigate", url: "/" },
                    { action: "assert", url: "example.com" },
                ],
            };
            const result = await runFlow(flow, "http://example.com");
            const assertStep = result.steps[1];
            expect(assertStep.action).toBe("assert");
            expect(assertStep.assertion).toBeDefined();
            expect(assertStep.assertion?.passed).toBe(true);
        });
    });
});
//# sourceMappingURL=golden-path-runner.test.js.map