CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
auto-repair-mechanical.test.ts
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| b0a3ba2 | 1 | /** |
| 2 | * Tests for the mechanical-repair classifier. | |
| 3 | * The actual repair handlers do real subprocess work + git ops; those | |
| 4 | * are covered by a separate integration test path. Here we lock down | |
| 5 | * the cheap-and-deterministic classifier that decides whether a failure | |
| 6 | * even has a mechanical handler. | |
| 7 | */ | |
| 8 | import { describe, expect, it } from "bun:test"; | |
| 9 | import { classifyFailure } from "../lib/auto-repair-mechanical"; | |
| 10 | ||
| 11 | describe("classifyFailure", () => { | |
| 12 | it("detects bun lockfile drift", () => { | |
| 13 | expect(classifyFailure("error: lockfile is out of sync")).toBe("lockfile"); | |
| 14 | expect( | |
| 15 | classifyFailure( | |
| 16 | "bun install failed: bun.lock is outdated relative to package.json", | |
| 17 | ), | |
| 18 | ).toBe("lockfile"); | |
| 19 | expect( | |
| 20 | classifyFailure("error: --frozen-lockfile failed: lockfile mismatch"), | |
| 21 | ).toBe("lockfile"); | |
| 22 | }); | |
| 23 | ||
| 24 | it("detects npm lockfile drift", () => { | |
| 25 | expect( | |
| 26 | classifyFailure( | |
| 27 | "npm error code EUSAGE: package-lock.json is not in sync with package.json", | |
| 28 | ), | |
| 29 | ).toBe("lockfile"); | |
| 30 | }); | |
| 31 | ||
| 32 | it("detects formatting failures across tools", () => { | |
| 33 | expect( | |
| 34 | classifyFailure("12 files would be reformatted with prettier"), | |
| 35 | ).toBe("formatting"); | |
| 36 | expect( | |
| 37 | classifyFailure("style/formatting check failed: see ./biome-report"), | |
| 38 | ).toBe("formatting"); | |
| 39 | expect(classifyFailure("biome ci . — format errors found")).toBe( | |
| 40 | "formatting", | |
| 41 | ); | |
| 42 | expect(classifyFailure("bun fmt would change 4 files")).toBe( | |
| 43 | "formatting", | |
| 44 | ); | |
| 45 | }); | |
| 46 | ||
| 47 | it("detects import-order failures", () => { | |
| 48 | expect(classifyFailure("imports are not sorted: src/foo.ts:3")).toBe( | |
| 49 | "imports", | |
| 50 | ); | |
| 51 | expect( | |
| 52 | classifyFailure( | |
| 53 | "lint/correctness/organize-imports: imports must be ordered", | |
| 54 | ), | |
| 55 | ).toBe("imports"); | |
| 56 | expect(classifyFailure("import/order: groups out of order")).toBe( | |
| 57 | "imports", | |
| 58 | ); | |
| 59 | expect(classifyFailure("unused-imports: 3 unused imports found")).toBe( | |
| 60 | "imports", | |
| 61 | ); | |
| 62 | }); | |
| 63 | ||
| 64 | it("returns null for everything that's not mechanically fixable", () => { | |
| 65 | expect(classifyFailure("expected 1 to equal 2")).toBeNull(); | |
| 66 | expect( | |
| 67 | classifyFailure( | |
| 68 | "TypeError: Cannot read property 'foo' of undefined at index.ts:42", | |
| 69 | ), | |
| 70 | ).toBeNull(); | |
| 71 | expect(classifyFailure("ECONNREFUSED 127.0.0.1:5432")).toBeNull(); | |
| 72 | expect(classifyFailure("")).toBeNull(); | |
| 73 | expect(classifyFailure("random unrelated noise from CI")).toBeNull(); | |
| 74 | }); | |
| 75 | ||
| 76 | it("is case-insensitive on the heuristic match", () => { | |
| 77 | expect(classifyFailure("LOCKFILE IS OUT OF SYNC")).toBe("lockfile"); | |
| 78 | expect(classifyFailure("Prettier: 1 file would be reformatted")).toBe( | |
| 79 | "formatting", | |
| 80 | ); | |
| 81 | }); | |
| 82 | }); |