* fix: skip untracked directories in review context * fix: skip broken untracked symlinks in reviews
104 lines
3.9 KiB
JavaScript
104 lines
3.9 KiB
JavaScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { collectReviewContext, resolveReviewTarget } from "../plugins/codex/scripts/lib/git.mjs";
|
|
import { initGitRepo, makeTempDir, run } from "./helpers.mjs";
|
|
|
|
test("resolveReviewTarget prefers working tree when repo is dirty", () => {
|
|
const cwd = makeTempDir();
|
|
initGitRepo(cwd);
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v1');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "init"], { cwd });
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v2');\n");
|
|
|
|
const target = resolveReviewTarget(cwd, {});
|
|
|
|
assert.equal(target.mode, "working-tree");
|
|
});
|
|
|
|
test("resolveReviewTarget falls back to branch diff when repo is clean", () => {
|
|
const cwd = makeTempDir();
|
|
initGitRepo(cwd);
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v1');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "init"], { cwd });
|
|
run("git", ["checkout", "-b", "feature/test"], { cwd });
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v2');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "change"], { cwd });
|
|
|
|
const target = resolveReviewTarget(cwd, {});
|
|
const context = collectReviewContext(cwd, target);
|
|
|
|
assert.equal(target.mode, "branch");
|
|
assert.match(target.label, /main/);
|
|
assert.match(context.content, /Branch Diff/);
|
|
});
|
|
|
|
test("resolveReviewTarget honors explicit base overrides", () => {
|
|
const cwd = makeTempDir();
|
|
initGitRepo(cwd);
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v1');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "init"], { cwd });
|
|
run("git", ["checkout", "-b", "feature/test"], { cwd });
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v2');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "change"], { cwd });
|
|
|
|
const target = resolveReviewTarget(cwd, { base: "main" });
|
|
|
|
assert.equal(target.mode, "branch");
|
|
assert.equal(target.baseRef, "main");
|
|
});
|
|
|
|
test("resolveReviewTarget requires an explicit base when no default branch can be inferred", () => {
|
|
const cwd = makeTempDir();
|
|
initGitRepo(cwd);
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v1');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "init"], { cwd });
|
|
run("git", ["branch", "-m", "feature-only"], { cwd });
|
|
|
|
assert.throws(
|
|
() => resolveReviewTarget(cwd, {}),
|
|
/Unable to detect the repository default branch\. Pass --base <ref> or use --scope working-tree\./
|
|
);
|
|
});
|
|
|
|
test("collectReviewContext skips untracked directories in working tree review", () => {
|
|
const cwd = makeTempDir();
|
|
initGitRepo(cwd);
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v1');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "init"], { cwd });
|
|
|
|
const nestedRepoDir = path.join(cwd, ".claude", "worktrees", "agent-test");
|
|
fs.mkdirSync(nestedRepoDir, { recursive: true });
|
|
initGitRepo(nestedRepoDir);
|
|
|
|
const target = resolveReviewTarget(cwd, { scope: "working-tree" });
|
|
const context = collectReviewContext(cwd, target);
|
|
|
|
assert.match(context.content, /### \.claude\/worktrees\/agent-test\/\n\(skipped: directory\)/);
|
|
});
|
|
|
|
test("collectReviewContext skips broken untracked symlinks instead of crashing", () => {
|
|
const cwd = makeTempDir();
|
|
initGitRepo(cwd);
|
|
fs.writeFileSync(path.join(cwd, "app.js"), "console.log('v1');\n");
|
|
run("git", ["add", "app.js"], { cwd });
|
|
run("git", ["commit", "-m", "init"], { cwd });
|
|
fs.symlinkSync("missing-target", path.join(cwd, "broken-link"));
|
|
|
|
const target = resolveReviewTarget(cwd, {});
|
|
const context = collectReviewContext(cwd, target);
|
|
|
|
assert.equal(target.mode, "working-tree");
|
|
assert.match(context.content, /### broken-link/);
|
|
assert.match(context.content, /skipped: broken symlink or unreadable file/i);
|
|
});
|