test: cover confirmed canvas agent deletes
This commit is contained in:
parent
6d5604a84b
commit
6d66d126c8
@ -1003,4 +1003,128 @@ test.describe("canvas agent operation mutation contract", () => {
|
||||
"STALE_CANVAS_REVISION"
|
||||
);
|
||||
});
|
||||
|
||||
test("confirms delete-node mutations, removes connected edges, and keeps retries idempotent", () => {
|
||||
const source = buildImageNode("image-source");
|
||||
const target = buildImageNode("image-delete");
|
||||
const unrelated = buildImageNode("image-unrelated");
|
||||
const edge = {
|
||||
id: "edge-source-delete",
|
||||
source: "image-source",
|
||||
target: "image-delete",
|
||||
type: "reference",
|
||||
createdAt: "2026-06-22T00:00:00.000Z",
|
||||
};
|
||||
const canvasData = {
|
||||
...getCanvasData([source, target, unrelated]),
|
||||
edges: [edge],
|
||||
selectedNodeIds: ["image-delete"],
|
||||
};
|
||||
const plan: CanvasOperationPlan = {
|
||||
version: 1,
|
||||
operationId: "op-delete-node",
|
||||
operation: "delete_nodes",
|
||||
projectId,
|
||||
targetNodeIds: ["image-delete"],
|
||||
metadata: {
|
||||
messageId: "assistant-message-delete",
|
||||
chatId: "chat-1",
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
applyCanvasOperationPlanToCanvasData({
|
||||
canvasData,
|
||||
plan,
|
||||
})
|
||||
).toThrow(/需要用户确认/);
|
||||
|
||||
const deleted = applyCanvasOperationPlanToCanvasData({
|
||||
canvasData,
|
||||
plan: {
|
||||
...plan,
|
||||
confirmed: true,
|
||||
metadata: {
|
||||
...plan.metadata,
|
||||
confirmedByUser: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
const deletedCanvasData = deleted.canvasData as {
|
||||
nodes?: any[];
|
||||
edges?: any[];
|
||||
selectedNodeIds?: string[];
|
||||
metadata?: Record<string, any>;
|
||||
};
|
||||
|
||||
expect(deleted.createdNodeIds).toEqual([]);
|
||||
expect(deleted.updatedNodeIds).toEqual(["image-delete"]);
|
||||
expect(deletedCanvasData.nodes?.map((node) => node.id).sort()).toEqual([
|
||||
"image-source",
|
||||
"image-unrelated",
|
||||
]);
|
||||
expect(deletedCanvasData.edges).toEqual([]);
|
||||
expect(deletedCanvasData.selectedNodeIds).toEqual([]);
|
||||
expect(
|
||||
deletedCanvasData.nodes?.find((node) => node.id === "image-source")?.connections
|
||||
).toEqual([]);
|
||||
expect(deletedCanvasData.metadata?.canvasAgentOperationAudit).toEqual([
|
||||
expect.objectContaining({
|
||||
operationId: "op-delete-node",
|
||||
operation: "delete_nodes",
|
||||
targetNodeIds: ["image-delete"],
|
||||
deletedNodeIds: ["image-delete"],
|
||||
deletedEdges: [edge],
|
||||
metadata: expect.objectContaining({
|
||||
confirmedByUser: true,
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
|
||||
const retry = applyCanvasOperationPlanToCanvasData({
|
||||
canvasData: deleted.canvasData,
|
||||
plan: {
|
||||
...plan,
|
||||
confirmed: true,
|
||||
metadata: {
|
||||
...plan.metadata,
|
||||
confirmedByUser: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(retry.updatedNodeIds).toEqual(["image-delete"]);
|
||||
expect(getResultNodes(retry.canvasData)).toHaveLength(2);
|
||||
expect(getResultEdges(retry.canvasData)).toEqual([]);
|
||||
});
|
||||
|
||||
test("rejects confirmed stale delete-node mutations", () => {
|
||||
const target = buildImageNode("image-stale-delete");
|
||||
|
||||
let caughtError: unknown;
|
||||
try {
|
||||
applyCanvasOperationPlanToCanvasData({
|
||||
canvasData: getCanvasData([target]),
|
||||
baseCanvasWasStale: true,
|
||||
plan: {
|
||||
version: 1,
|
||||
operationId: "op-stale-delete-node",
|
||||
operation: "delete_nodes",
|
||||
projectId,
|
||||
targetNodeIds: ["image-stale-delete"],
|
||||
confirmed: true,
|
||||
metadata: {
|
||||
confirmedByUser: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
caughtError = error;
|
||||
}
|
||||
|
||||
expect(caughtError).toBeInstanceOf(CanvasAgentMutationError);
|
||||
expect((caughtError as CanvasAgentMutationError).code).toBe(
|
||||
"STALE_CANVAS_REVISION"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user