test(FN-5139): cover lineage cancel paths in modal tests

Fusion-Task-Id: FN-5139
Fusion-Task-Lineage: c16f4245-bfda-4b9a-bd98-ffc44b45f5a0
This commit is contained in:
Fusion (runfusion.ai)
2026-05-19 18:48:41 -07:00
committed by gsxdsm
parent e6c7dcdd64
commit e167df431b

View File

@@ -307,6 +307,43 @@ describe("TaskDetailModal", () => {
fireEvent.click(screen.getByRole("menuitem", { name: "Delete" }));
await waitFor(() => {
expect(mockConfirm).toHaveBeenCalledTimes(2);
expect(onDeleteTask).toHaveBeenCalledTimes(1);
});
});
it("does not retry delete when lineage-force confirmation is canceled", async () => {
const onDeleteTask = vi.fn();
const conflict = new Error("Cannot delete task FN-099: still referenced as a lineage parent by FN-104.") as Error & {
status: number;
details: { code: string; lineageChildIds: string[] };
};
conflict.status = 409;
conflict.details = { code: "TASK_HAS_LINEAGE_CHILDREN", lineageChildIds: ["FN-104"] };
onDeleteTask.mockRejectedValue(conflict);
mockConfirm
.mockResolvedValueOnce(true)
.mockResolvedValueOnce(true)
.mockResolvedValueOnce(false);
render(
<TaskDetailModal
task={makeTask({ githubTracking: { enabled: true, issue: { owner: "owner", repo: "repo", number: 42, url: "https://github.com/owner/repo/issues/42", createdAt: "2026-01-01T00:00:00.000Z" } } })}
onClose={noop}
onMoveTask={noopMove}
onDeleteTask={onDeleteTask}
onMergeTask={noopMerge}
onOpenDetail={noopOpenDetail}
addToast={noop}
/>,
);
fireEvent.click(screen.getByRole("button", { name: /actions/i }));
fireEvent.click(screen.getByRole("menuitem", { name: "Delete" }));
await waitFor(() => {
expect(mockConfirm).toHaveBeenCalledTimes(3);
expect(onDeleteTask).toHaveBeenCalledTimes(1);
});
});
@@ -427,6 +464,40 @@ describe("TaskDetailModal", () => {
});
});
it("does not retry archive when lineage-force confirmation is canceled", async () => {
const onArchiveTask = vi.fn();
const conflict = new Error("Cannot archive task FN-099: still referenced as a lineage parent by FN-202.") as Error & {
status: number;
details: { code: string; lineageChildIds: string[] };
};
conflict.status = 409;
conflict.details = { code: "TASK_HAS_LINEAGE_CHILDREN", lineageChildIds: ["FN-202"] };
onArchiveTask.mockRejectedValue(conflict);
mockConfirmWithChoice.mockResolvedValueOnce("tertiary");
mockConfirm.mockResolvedValueOnce(false);
render(
<TaskDetailModal
task={makeTask({ column: "done" as any })}
onClose={noop}
onMoveTask={noopMove}
onDeleteTask={noopDelete}
onArchiveTask={onArchiveTask}
onMergeTask={noopMerge}
onOpenDetail={noopOpenDetail}
addToast={noop}
/>,
);
fireEvent.click(screen.getByRole("button", { name: /actions/i }));
fireEvent.click(screen.getByRole("menuitem", { name: "Delete" }));
await waitFor(() => {
expect(onArchiveTask).toHaveBeenCalledTimes(1);
expect(mockConfirm).toHaveBeenCalledTimes(1);
});
});
it("in-review modal-actions contains Merge & Close and Back to In Progress buttons", () => {
render(
<TaskDetailModal