test(FN-4763): strengthen pr-conflict reclaim interaction coverage
Fusion-Task-Id: FN-4763 Fusion-Task-Lineage: b3628e63-682b-4a39-9a7d-2c96278c5366
This commit is contained in:
committed by
gsxdsm
parent
86c3063d9d
commit
f9bcf2acff
@@ -4,6 +4,7 @@ import type { Settings, Task, TaskStore } from "@fusion/core";
|
||||
import { SelfHealingManager } from "../../self-healing.js";
|
||||
import * as branchConflicts from "../../branch-conflicts.js";
|
||||
import * as worktreePool from "../../worktree-pool.js";
|
||||
import { activeSessionRegistry } from "../../active-session-registry.js";
|
||||
|
||||
function task(overrides: Partial<Task> = {}): Task {
|
||||
return {
|
||||
@@ -51,6 +52,7 @@ function store(t: Task): TaskStore & EventEmitter {
|
||||
describe("reliability interaction: pr conflict reclaim", () => {
|
||||
beforeEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
activeSessionRegistry.clear();
|
||||
vi.spyOn(worktreePool, "isUsableTaskWorktree").mockResolvedValue(true);
|
||||
});
|
||||
|
||||
@@ -64,11 +66,22 @@ describe("reliability interaction: pr conflict reclaim", () => {
|
||||
expect(branchConflicts.inspectBranchConflict).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("skips checked-out task during pr conflict reclaim", async () => {
|
||||
const t = task({ checkedOutBy: "agent-1" });
|
||||
it("skips active heartbeat-style session during pr conflict reclaim", async () => {
|
||||
const t = task();
|
||||
const s = store(t);
|
||||
activeSessionRegistry.registerPath(t.worktree!, { taskId: t.id, kind: "executor", ownerKey: t.id });
|
||||
const manager = new SelfHealingManager(s as any, { rootDir: "/tmp/test" } as any);
|
||||
const result = await manager.reclaimPrConflictForTask(t.id);
|
||||
expect(result).toEqual({ outcome: "skipped", reason: "checked-out" });
|
||||
expect(result).toEqual({ outcome: "skipped", reason: "active-session" });
|
||||
});
|
||||
|
||||
it("keeps paused-review reclaim path resumable", async () => {
|
||||
const t = task();
|
||||
const s = store(t);
|
||||
vi.spyOn(branchConflicts, "inspectBranchConflict").mockResolvedValue({ kind: "reclaimable", livePath: t.worktree, tipSha: "abc123", taskAttributedCommitCount: 2, strandedCommits: [{ sha: "abc123" }] } as any);
|
||||
const manager = new SelfHealingManager(s as any, { rootDir: "/tmp/test" } as any);
|
||||
const result = await manager.reclaimPrConflictForTask(t.id);
|
||||
expect(result.outcome).toBe("reclaimed");
|
||||
expect(t.column).toBe("todo");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -89,6 +89,25 @@ describe("SelfHealingManager.reclaimPrConflictForTask", () => {
|
||||
expect(sweepSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns reclaimed for reclaimable conflicts", async () => {
|
||||
const task = makeTask({ column: "in-review", paused: true, pausedReason: "branch-conflict-unrecoverable" as any });
|
||||
const store = makeStore(task);
|
||||
vi.spyOn(branchConflicts, "inspectBranchConflict").mockResolvedValue({ kind: "reclaimable", livePath: task.worktree, tipSha: "abc123", taskAttributedCommitCount: 1, strandedCommits: [{ sha: "abc123" }] } as any);
|
||||
const manager = new SelfHealingManager(store as any, { rootDir: "/tmp/test" } as any);
|
||||
const result = await manager.reclaimPrConflictForTask(task.id);
|
||||
expect(result.outcome).toBe("reclaimed");
|
||||
expect((store.moveTask as any).mock.calls.some((c: any[]) => c[1] === "todo")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns reclaimed for fully-subsumed conflicts", async () => {
|
||||
const task = makeTask({ branch: "feature/non-fusion-branch" });
|
||||
const store = makeStore(task);
|
||||
vi.spyOn(branchConflicts, "inspectBranchConflict").mockResolvedValue({ kind: "fully-subsumed", livePath: task.worktree, tipSha: "abc123", taskAttributedCommitCount: 0, strandedCommits: [] } as any);
|
||||
const manager = new SelfHealingManager(store as any, { rootDir: "/tmp/test" } as any);
|
||||
const result = await manager.reclaimPrConflictForTask(task.id);
|
||||
expect(result.outcome).toBe("reclaimed");
|
||||
});
|
||||
|
||||
it("returns paused-unrecoverable when conflict is unrecoverable and dispatcher pauses", async () => {
|
||||
const task = makeTask();
|
||||
const store = makeStore(task);
|
||||
|
||||
Reference in New Issue
Block a user