110 lines
3.9 KiB
TypeScript
110 lines
3.9 KiB
TypeScript
import { createMockPi, stubGitExec } from "@juicesharp/rpiv-test-utils";
|
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
import { clearGitContextCache, getGitContext, resetInjectedMarker, takeGitContextIfChanged } from "./git-context.js";
|
|
|
|
beforeEach(() => {
|
|
clearGitContextCache();
|
|
resetInjectedMarker();
|
|
});
|
|
|
|
describe("getGitContext", () => {
|
|
it("parses branch + commit + user from three exec calls", async () => {
|
|
const { pi } = createMockPi({
|
|
exec: stubGitExec({ branch: "main", commit: "abc1234", user: "alice" }) as never,
|
|
});
|
|
const ctx = await getGitContext(pi);
|
|
expect(ctx).toEqual({ branch: "main", commit: "abc1234", user: "alice" });
|
|
});
|
|
|
|
it("remaps literal HEAD to 'detached'", async () => {
|
|
const { pi } = createMockPi({
|
|
exec: stubGitExec({ branch: "HEAD", commit: "abc", user: "alice" }) as never,
|
|
});
|
|
const ctx = await getGitContext(pi);
|
|
expect(ctx?.branch).toBe("detached");
|
|
});
|
|
|
|
it("returns null when both branch and commit are empty (not a repo)", async () => {
|
|
const { pi } = createMockPi({ exec: stubGitExec({}) as never });
|
|
expect(await getGitContext(pi)).toBeNull();
|
|
});
|
|
|
|
it("falls back to process.env.USER when git config user.name errors", async () => {
|
|
const { pi } = createMockPi({
|
|
exec: stubGitExec({ branch: "main", commit: "abc", userError: new Error("no config") }) as never,
|
|
});
|
|
process.env.USER = "env-alice";
|
|
const ctx = await getGitContext(pi);
|
|
expect(ctx?.user).toBe("env-alice");
|
|
});
|
|
|
|
it("falls back to 'unknown' when neither git nor env has user", async () => {
|
|
const origUser = process.env.USER;
|
|
delete process.env.USER;
|
|
try {
|
|
const { pi } = createMockPi({
|
|
exec: stubGitExec({ branch: "main", commit: "abc", userError: new Error("x") }) as never,
|
|
});
|
|
const ctx = await getGitContext(pi);
|
|
expect(ctx?.user).toBe("unknown");
|
|
} finally {
|
|
if (origUser) process.env.USER = origUser;
|
|
}
|
|
});
|
|
|
|
it("memoises: subsequent calls do not re-exec", async () => {
|
|
const exec = stubGitExec({ branch: "main", commit: "abc", user: "alice" });
|
|
const { pi } = createMockPi({ exec: exec as never });
|
|
await getGitContext(pi);
|
|
await getGitContext(pi);
|
|
expect(exec).toHaveBeenCalledTimes(3); // 3 initial exec calls, no second-round
|
|
});
|
|
|
|
it("clearGitContextCache forces re-read", async () => {
|
|
const exec = stubGitExec({ branch: "main", commit: "abc", user: "alice" });
|
|
const { pi } = createMockPi({ exec: exec as never });
|
|
await getGitContext(pi);
|
|
clearGitContextCache();
|
|
await getGitContext(pi);
|
|
expect(exec).toHaveBeenCalledTimes(6);
|
|
});
|
|
});
|
|
|
|
describe("takeGitContextIfChanged", () => {
|
|
it("returns the context-line on first call", async () => {
|
|
const { pi } = createMockPi({
|
|
exec: stubGitExec({ branch: "main", commit: "abc", user: "alice" }) as never,
|
|
});
|
|
const r = await takeGitContextIfChanged(pi);
|
|
expect(r).toContain("- Branch: main");
|
|
expect(r).toContain("- Commit: abc");
|
|
expect(r).toContain("- User: alice");
|
|
});
|
|
|
|
it("returns null on second call when signature unchanged", async () => {
|
|
const { pi } = createMockPi({
|
|
exec: stubGitExec({ branch: "main", commit: "abc", user: "alice" }) as never,
|
|
});
|
|
await takeGitContextIfChanged(pi);
|
|
expect(await takeGitContextIfChanged(pi)).toBeNull();
|
|
});
|
|
|
|
it("re-emits after clearGitContextCache + resetInjectedMarker + signature change", async () => {
|
|
const { pi } = createMockPi({
|
|
exec: stubGitExec({ branch: "main", commit: "abc", user: "alice" }) as never,
|
|
});
|
|
await takeGitContextIfChanged(pi);
|
|
clearGitContextCache();
|
|
resetInjectedMarker();
|
|
const { pi: pi2 } = createMockPi({
|
|
exec: stubGitExec({ branch: "feature", commit: "def", user: "alice" }) as never,
|
|
});
|
|
expect(await takeGitContextIfChanged(pi2)).not.toBeNull();
|
|
});
|
|
|
|
it("returns null when not in a git repo", async () => {
|
|
const { pi } = createMockPi({ exec: stubGitExec({}) as never });
|
|
expect(await takeGitContextIfChanged(pi)).toBeNull();
|
|
});
|
|
});
|