test: cover confirmed canvas agent moves
This commit is contained in:
parent
6d66d126c8
commit
733d6338c2
@ -1004,6 +1004,138 @@ test.describe("canvas agent operation mutation contract", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("confirms move-node mutations and keeps retries from moving nodes again", () => {
|
||||
const first = buildImageNode("image-move-a");
|
||||
first.position = { x: 300, y: 100 };
|
||||
const second = buildImageNode("image-move-b");
|
||||
second.position = { x: 100, y: 100 };
|
||||
const unrelated = buildImageNode("image-unrelated");
|
||||
unrelated.position = { x: 900, y: 500 };
|
||||
const canvasData = getCanvasData([first, second, unrelated]);
|
||||
const plan: CanvasOperationPlan = {
|
||||
version: 1,
|
||||
operationId: "op-move-nodes",
|
||||
operation: "move_nodes",
|
||||
projectId,
|
||||
targetNodeIds: ["image-move-a", "image-move-b"],
|
||||
targetPosition: { x: 10, y: 20 },
|
||||
layoutStrategy: "row",
|
||||
spacing: 30,
|
||||
metadata: {
|
||||
messageId: "assistant-message-move",
|
||||
chatId: "chat-1",
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
applyCanvasOperationPlanToCanvasData({
|
||||
canvasData,
|
||||
plan,
|
||||
})
|
||||
).toThrow(/需要用户确认/);
|
||||
|
||||
const moved = applyCanvasOperationPlanToCanvasData({
|
||||
canvasData,
|
||||
plan: {
|
||||
...plan,
|
||||
confirmed: true,
|
||||
metadata: {
|
||||
...plan.metadata,
|
||||
confirmedByUser: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
const movedNodes = getResultNodes(moved.canvasData);
|
||||
const movedFirst = movedNodes.find((node) => node.id === "image-move-a");
|
||||
const movedSecond = movedNodes.find((node) => node.id === "image-move-b");
|
||||
const movedUnrelated = movedNodes.find((node) => node.id === "image-unrelated");
|
||||
|
||||
expect(moved.createdNodeIds).toEqual([]);
|
||||
expect(moved.updatedNodeIds).toEqual(["image-move-b", "image-move-a"]);
|
||||
expect(movedSecond).toMatchObject({
|
||||
position: { x: 10, y: 20 },
|
||||
data: {
|
||||
metadata: {
|
||||
movedByAgent: true,
|
||||
canvasAgentOperationId: "op-move-nodes",
|
||||
canvasAgentOperation: "move_nodes",
|
||||
canvasAgentLayoutStrategy: "row",
|
||||
previousPosition: { x: 100, y: 100 },
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(movedFirst).toMatchObject({
|
||||
position: { x: 360, y: 20 },
|
||||
data: {
|
||||
metadata: {
|
||||
movedByAgent: true,
|
||||
previousPosition: { x: 300, y: 100 },
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(movedUnrelated?.position).toEqual({ x: 900, y: 500 });
|
||||
expect((moved.canvasData as { selectedNodeIds?: string[] }).selectedNodeIds).toEqual([
|
||||
"image-move-b",
|
||||
"image-move-a",
|
||||
]);
|
||||
|
||||
const retry = applyCanvasOperationPlanToCanvasData({
|
||||
canvasData: moved.canvasData,
|
||||
plan: {
|
||||
...plan,
|
||||
confirmed: true,
|
||||
metadata: {
|
||||
...plan.metadata,
|
||||
confirmedByUser: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
const retryNodes = getResultNodes(retry.canvasData);
|
||||
|
||||
expect(new Set(retry.updatedNodeIds)).toEqual(
|
||||
new Set(["image-move-a", "image-move-b"])
|
||||
);
|
||||
expect(retryNodes.find((node) => node.id === "image-move-b")?.position).toEqual({
|
||||
x: 10,
|
||||
y: 20,
|
||||
});
|
||||
expect(retryNodes.find((node) => node.id === "image-move-a")?.position).toEqual({
|
||||
x: 360,
|
||||
y: 20,
|
||||
});
|
||||
});
|
||||
|
||||
test("rejects confirmed stale move-node mutations", () => {
|
||||
const target = buildImageNode("image-stale-move");
|
||||
|
||||
let caughtError: unknown;
|
||||
try {
|
||||
applyCanvasOperationPlanToCanvasData({
|
||||
canvasData: getCanvasData([target]),
|
||||
baseCanvasWasStale: true,
|
||||
plan: {
|
||||
version: 1,
|
||||
operationId: "op-stale-move-node",
|
||||
operation: "move_nodes",
|
||||
projectId,
|
||||
targetNodeIds: ["image-stale-move"],
|
||||
targetPosition: { x: 10, y: 20 },
|
||||
confirmed: true,
|
||||
metadata: {
|
||||
confirmedByUser: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
caughtError = error;
|
||||
}
|
||||
|
||||
expect(caughtError).toBeInstanceOf(CanvasAgentMutationError);
|
||||
expect((caughtError as CanvasAgentMutationError).code).toBe(
|
||||
"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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user