initial import: @mikefreno/omp-pygenium (omp port)
This commit is contained in:
137
tests/run-state.test.ts
Normal file
137
tests/run-state.test.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* run-state.test.ts — run-state reconciliation, error hygiene, and the
|
||||
* .gitignore guard (issues surfaced by the MagnaFluo all-run: "partial" for
|
||||
* all-failed runs, stale errors on completed checks, staged artifacts).
|
||||
*/
|
||||
import { describe, expect, it, beforeEach, afterEach } from "bun:test";
|
||||
import { mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import {
|
||||
ensureRunStateIgnored,
|
||||
initRunState,
|
||||
markCheckStatus,
|
||||
reconcileRunStatus,
|
||||
} from "../src/run-state.js";
|
||||
|
||||
/** Build a run state whose checks carry the given statuses. */
|
||||
function stateWith(
|
||||
...statuses: Array<[name: string, status: string]>
|
||||
): ReturnType<typeof initRunState> {
|
||||
const state = initRunState(
|
||||
"/virtual/cwd",
|
||||
statuses.map(([name]) => ({ name, label: name })),
|
||||
);
|
||||
for (const [name, status] of statuses) {
|
||||
markCheckStatus(
|
||||
state,
|
||||
name,
|
||||
status as "complete" | "failed" | "skipped",
|
||||
status === "failed" ? "boom" : undefined,
|
||||
);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
describe("reconcileRunStatus", () => {
|
||||
it("is in_progress while nothing is terminal", () => {
|
||||
expect(reconcileRunStatus(stateWith())).toBe("in_progress");
|
||||
expect(
|
||||
reconcileRunStatus(initRunState("/virt", [{ name: "a", label: "a" }])),
|
||||
).toBe("in_progress");
|
||||
});
|
||||
|
||||
it("is complete only when every check is complete", () => {
|
||||
expect(
|
||||
reconcileRunStatus(stateWith(["a", "complete"], ["b", "complete"])),
|
||||
).toBe("complete");
|
||||
});
|
||||
|
||||
it("is partial when some checks failed and others completed", () => {
|
||||
expect(
|
||||
reconcileRunStatus(stateWith(["a", "complete"], ["b", "failed"])),
|
||||
).toBe("partial");
|
||||
});
|
||||
|
||||
it("is partial when checks were skipped", () => {
|
||||
expect(
|
||||
reconcileRunStatus(stateWith(["a", "complete"], ["b", "skipped"])),
|
||||
).toBe("partial");
|
||||
});
|
||||
|
||||
it("is failed when every check failed (not partial)", () => {
|
||||
expect(
|
||||
reconcileRunStatus(stateWith(["a", "failed"], ["b", "failed"])),
|
||||
).toBe("failed");
|
||||
expect(reconcileRunStatus(stateWith(["a", "failed"]))).toBe("failed");
|
||||
});
|
||||
|
||||
it("is partial for a mixed failed/skipped run (some degraded, none ok)", () => {
|
||||
expect(
|
||||
reconcileRunStatus(stateWith(["a", "failed"], ["b", "skipped"])),
|
||||
).toBe("partial");
|
||||
});
|
||||
});
|
||||
|
||||
describe("check error hygiene", () => {
|
||||
it("a failed check records its error", () => {
|
||||
const s = stateWith(["a", "failed"]);
|
||||
expect(s.checks.a?.error).toBe("boom");
|
||||
});
|
||||
|
||||
it("a later success clears the stale error (resume-complete invariant)", () => {
|
||||
const s = stateWith(["a", "failed"]);
|
||||
expect(s.checks.a?.error).toBe("boom");
|
||||
markCheckStatus(s, "a", "complete");
|
||||
expect(s.checks.a?.error).toBeUndefined();
|
||||
expect(s.checks.a?.status).toBe("complete");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ensureRunStateIgnored", () => {
|
||||
let cwd: string;
|
||||
beforeEach(async () => {
|
||||
cwd = await mkdtemp(join(tmpdir(), "pygium-git-"));
|
||||
await mkdir(join(cwd, ".git"), { recursive: true }); // pretend it's a work tree
|
||||
});
|
||||
afterEach(async () => {
|
||||
await rm(cwd, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("creates .gitignore with .pygienium/ when absent", async () => {
|
||||
expect(await ensureRunStateIgnored(cwd)).toBe(true);
|
||||
const content = await readFile(join(cwd, ".gitignore"), "utf8");
|
||||
expect(content).toContain(".pygienium/");
|
||||
});
|
||||
|
||||
it("appends to an existing .gitignore without the marker", async () => {
|
||||
await writeFile(join(cwd, ".gitignore"), "node_modules/\n", "utf8");
|
||||
expect(await ensureRunStateIgnored(cwd)).toBe(true);
|
||||
const content = await readFile(join(cwd, ".gitignore"), "utf8");
|
||||
expect(content).toContain(".pygienium/");
|
||||
expect(content).toContain("node_modules/");
|
||||
});
|
||||
|
||||
it("leaves an existing marker untouched and reports no change", async () => {
|
||||
await writeFile(
|
||||
join(cwd, ".gitignore"),
|
||||
".pygienium/\nnode_modules/\n",
|
||||
"utf8",
|
||||
);
|
||||
expect(await ensureRunStateIgnored(cwd)).toBe(false);
|
||||
const content = await readFile(join(cwd, ".gitignore"), "utf8");
|
||||
expect(content).toBe(".pygienium/\nnode_modules/\n");
|
||||
});
|
||||
|
||||
it("is a no-op outside a git work tree", async () => {
|
||||
const plain = await mkdtemp(join(tmpdir(), "pygium-nogit-"));
|
||||
try {
|
||||
expect(await ensureRunStateIgnored(plain)).toBe(false);
|
||||
await expect(
|
||||
readFile(join(plain, ".gitignore"), "utf8"),
|
||||
).rejects.toThrow();
|
||||
} finally {
|
||||
await rm(plain, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user