jest.mock("./logger.js", () => ({
    logger: {
        debug: jest.fn(),
        info: jest.fn(),
        warning: jest.fn(),
        error: jest.fn(),
    },
}));
jest.mock("fs", () => ({
    statSync: (p) => ({
        isDirectory: () => !p.includes("."),
    }),
}));
const execFileMock = jest.fn();
const execFileSyncMock = jest.fn();
jest.mock("child_process", () => ({
    execFile: (cmd, args, opts, cb) => {
        const result = execFileMock(cmd, args, opts);
        const cbErr = result && typeof result === "object" && "err" in result
            ? result.err
            : null;
        const cbStdout = result && typeof result === "object" && "stdout" in result
            ? result.stdout
            : "";
        cb(cbErr, cbStdout, "");
    },
    execFileSync: (cmd, args, opts) => execFileSyncMock(cmd, args, opts),
}));
import { stageGeneratedPaths } from "./gitStaging.js";
import { logger } from "./logger.js";
const loggerInfoMock = logger.info;
let originalTestbotEnv;
beforeAll(() => {
    originalTestbotEnv = process.env.SKYRAMP_FEATURE_TESTBOT;
});
afterAll(() => {
    if (originalTestbotEnv === undefined) {
        delete process.env.SKYRAMP_FEATURE_TESTBOT;
    }
    else {
        process.env.SKYRAMP_FEATURE_TESTBOT = originalTestbotEnv;
    }
});
beforeEach(() => {
    execFileMock.mockReset();
    execFileSyncMock.mockReset();
    loggerInfoMock.mockReset();
});
afterEach(() => {
    delete process.env.SKYRAMP_FEATURE_TESTBOT;
});
describe("stageGeneratedPaths", () => {
    describe("gated on (SKYRAMP_FEATURE_TESTBOT=1)", () => {
        beforeEach(() => {
            process.env.SKYRAMP_FEATURE_TESTBOT = "1";
        });
        it("runs `git add -- <path>` with the supplied path", async () => {
            await stageGeneratedPaths("tests/a.py");
            expect(execFileMock).toHaveBeenCalledTimes(1);
            expect(execFileMock).toHaveBeenCalledWith("git", ["add", "--", "tests/a.py"], expect.objectContaining({}));
            expect(loggerInfoMock).toHaveBeenCalledWith("Staged generated file", expect.objectContaining({ path: "tests/a.py" }));
        });
        it("auto-detects git root for absolute paths and uses it as cwd", async () => {
            execFileSyncMock.mockReturnValue("/tmp/test-repo\n");
            await stageGeneratedPaths("/tmp/test-repo/tests/a.py");
            // Uses path.dirname for the cwd since the path is a file
            expect(execFileSyncMock).toHaveBeenCalledWith("git", ["rev-parse", "--show-toplevel"], expect.objectContaining({ cwd: "/tmp/test-repo/tests" }));
            expect(execFileMock).toHaveBeenCalledWith("git", ["add", "--", "/tmp/test-repo/tests/a.py"], expect.objectContaining({ cwd: "/tmp/test-repo" }));
        });
        it("passes through the cwd option when provided", async () => {
            await stageGeneratedPaths("tests/a.py", "/repo/root");
            expect(execFileMock).toHaveBeenCalledWith("git", ["add", "--", "tests/a.py"], expect.objectContaining({ cwd: "/repo/root" }));
        });
        it("propagates errors from git add", async () => {
            const err = new Error("fatal: not a git repository");
            execFileMock.mockImplementation(() => {
                throw err;
            });
            await expect(stageGeneratedPaths("tests/a.py")).rejects.toThrow("fatal: not a git repository");
        });
        it("propagates async callback errors from git add", async () => {
            const err = Object.assign(new Error("git: command not found"), {
                code: "ENOENT",
            });
            execFileMock.mockReturnValueOnce({ err });
            await expect(stageGeneratedPaths("tests/a.py", "/repo/root")).rejects.toThrow("git: command not found");
        });
    });
    describe("gated off (SKYRAMP_FEATURE_TESTBOT unset)", () => {
        it("does not invoke git add", async () => {
            await stageGeneratedPaths("tests/a.py");
            expect(execFileMock).not.toHaveBeenCalled();
            expect(loggerInfoMock).not.toHaveBeenCalled();
        });
    });
    describe("gated off (SKYRAMP_FEATURE_TESTBOT='0')", () => {
        beforeEach(() => {
            process.env.SKYRAMP_FEATURE_TESTBOT = "0";
        });
        it("does not invoke git add", async () => {
            await stageGeneratedPaths("tests/a.py");
            expect(execFileMock).not.toHaveBeenCalled();
        });
    });
});
