From ab491eb1419a76d181ae974abe81c163156117ae Mon Sep 17 00:00:00 2001 From: Matthias Meister Date: Sat, 11 Apr 2026 09:12:53 +0200 Subject: [PATCH] fix(canvas): align magnetism tests and connection-line lint --- .../canvas/__tests__/use-node-local-data.test.tsx | 1 + .../canvas/canvas-connection-magnetism-context.tsx | 12 ++++++------ components/canvas/custom-connection-line.tsx | 12 +++++++----- tests/agent-node-runtime.test.ts | 1 + tests/agent-node.test.ts | 1 + tests/agent-output-node.test.ts | 1 + tests/ai-video-node.test.ts | 1 + tests/crop-node.test.ts | 1 + tests/light-adjust-node.test.ts | 1 + tests/prompt-node.test.ts | 1 + tests/use-pipeline-preview.test.ts | 9 +++++++++ tests/video-prompt-node.test.ts | 1 + 12 files changed, 31 insertions(+), 11 deletions(-) diff --git a/components/canvas/__tests__/use-node-local-data.test.tsx b/components/canvas/__tests__/use-node-local-data.test.tsx index ed2c6cb..4a30b0b 100644 --- a/components/canvas/__tests__/use-node-local-data.test.tsx +++ b/components/canvas/__tests__/use-node-local-data.test.tsx @@ -699,6 +699,7 @@ describe("favorite retention in strict local node flows", () => { vi.doMock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); const importedModule = (await import(modulePath)) as { diff --git a/components/canvas/canvas-connection-magnetism-context.tsx b/components/canvas/canvas-connection-magnetism-context.tsx index e0b85aa..b2a5504 100644 --- a/components/canvas/canvas-connection-magnetism-context.tsx +++ b/components/canvas/canvas-connection-magnetism-context.tsx @@ -18,6 +18,11 @@ type CanvasConnectionMagnetismState = { const CanvasConnectionMagnetismContext = createContext(null); +const FALLBACK_MAGNETISM_STATE: CanvasConnectionMagnetismState = { + activeTarget: null, + setActiveTarget: () => undefined, +}; + export function CanvasConnectionMagnetismProvider({ children, }: { @@ -42,10 +47,5 @@ export function CanvasConnectionMagnetismProvider({ export function useCanvasConnectionMagnetism(): CanvasConnectionMagnetismState { const context = useContext(CanvasConnectionMagnetismContext); - if (!context) { - throw new Error( - "useCanvasConnectionMagnetism must be used within CanvasConnectionMagnetismProvider", - ); - } - return context; + return context ?? FALLBACK_MAGNETISM_STATE; } diff --git a/components/canvas/custom-connection-line.tsx b/components/canvas/custom-connection-line.tsx index 2824177..51bcbe7 100644 --- a/components/canvas/custom-connection-line.tsx +++ b/components/canvas/custom-connection-line.tsx @@ -53,6 +53,8 @@ export default function CustomConnectionLine({ }: ConnectionLineComponentProps) { const { getNodes, getEdges } = useReactFlow(); const { activeTarget, setActiveTarget } = useCanvasConnectionMagnetism(); + const fromHandleId = fromHandle?.id; + const fromNodeId = fromNode?.id; const fromHandleType = fromHandle?.type === "source" || fromHandle?.type === "target" @@ -60,19 +62,19 @@ export default function CustomConnectionLine({ : null; const resolvedMagnetTarget = useMemo(() => { - if (!fromHandleType || !fromNode?.id) { + if (!fromHandleType || !fromNodeId) { return null; } return resolveCanvasMagnetTarget({ point: { x: toX, y: toY }, - fromNodeId: fromNode.id, - fromHandleId: fromHandle?.id ?? undefined, + fromNodeId, + fromHandleId: fromHandleId ?? undefined, fromHandleType, nodes: getNodes(), edges: getEdges(), }); - }, [fromHandle?.id, fromHandleType, fromNode?.id, getEdges, getNodes, toX, toY]); + }, [fromHandleId, fromHandleType, fromNodeId, getEdges, getNodes, toX, toY]); useEffect(() => { if (hasSameMagnetTarget(activeTarget, resolvedMagnetTarget)) { @@ -119,7 +121,7 @@ export default function CustomConnectionLine({ [path] = getStraightPath(pathParams); } - const [r, g, b] = connectionLineAccentRgb(fromNode.type, fromHandle.id); + const [r, g, b] = connectionLineAccentRgb(fromNode.type, fromHandleId); const opacity = connectionStatus === "invalid" ? 0.45 : 1; const strokeWidth = snappedTarget ? 3.25 : 2.5; const filter = snappedTarget diff --git a/tests/agent-node-runtime.test.ts b/tests/agent-node-runtime.test.ts index b630b54..bba58cc 100644 --- a/tests/agent-node-runtime.test.ts +++ b/tests/agent-node-runtime.test.ts @@ -142,6 +142,7 @@ vi.mock("next-intl", () => ({ vi.mock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); import AgentNode from "@/components/canvas/nodes/agent-node"; diff --git a/tests/agent-node.test.ts b/tests/agent-node.test.ts index 197f2f4..f9cb350 100644 --- a/tests/agent-node.test.ts +++ b/tests/agent-node.test.ts @@ -60,6 +60,7 @@ vi.mock("@xyflow/react", () => ({ }); }, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); const translations: Record = { diff --git a/tests/agent-output-node.test.ts b/tests/agent-output-node.test.ts index 54cc19b..4bd5d9f 100644 --- a/tests/agent-output-node.test.ts +++ b/tests/agent-output-node.test.ts @@ -20,6 +20,7 @@ vi.mock("@xyflow/react", () => ({ }); }, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); const translations: Record = { diff --git a/tests/ai-video-node.test.ts b/tests/ai-video-node.test.ts index d27084f..e4cd82d 100644 --- a/tests/ai-video-node.test.ts +++ b/tests/ai-video-node.test.ts @@ -54,6 +54,7 @@ vi.mock("@/components/canvas/nodes/base-node-wrapper", () => ({ vi.mock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), useReactFlow: () => ({ getEdges: mocks.getEdges, getNode: mocks.getNode, diff --git a/tests/crop-node.test.ts b/tests/crop-node.test.ts index 7172230..2a797ab 100644 --- a/tests/crop-node.test.ts +++ b/tests/crop-node.test.ts @@ -18,6 +18,7 @@ const mocks = vi.hoisted(() => ({ vi.mock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); vi.mock("next-intl", () => ({ diff --git a/tests/light-adjust-node.test.ts b/tests/light-adjust-node.test.ts index 7a10e8e..dfb9cd5 100644 --- a/tests/light-adjust-node.test.ts +++ b/tests/light-adjust-node.test.ts @@ -19,6 +19,7 @@ const parameterSliderState = vi.hoisted(() => ({ vi.mock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); vi.mock("convex/react", () => ({ diff --git a/tests/prompt-node.test.ts b/tests/prompt-node.test.ts index 1e1e469..1c0dc51 100644 --- a/tests/prompt-node.test.ts +++ b/tests/prompt-node.test.ts @@ -135,6 +135,7 @@ vi.mock("@/components/canvas/nodes/base-node-wrapper", () => ({ vi.mock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), useStore: (selector: (state: { edges: typeof mocks.edges; nodes: typeof mocks.nodes }) => unknown) => selector({ edges: mocks.edges, nodes: mocks.nodes }), useReactFlow: () => ({ diff --git a/tests/use-pipeline-preview.test.ts b/tests/use-pipeline-preview.test.ts index 6545edc..ae01755 100644 --- a/tests/use-pipeline-preview.test.ts +++ b/tests/use-pipeline-preview.test.ts @@ -691,6 +691,7 @@ describe("preview histogram call sites", () => { vi.doMock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); vi.doMock("convex/react", () => ({ useMutation: () => vi.fn(async () => undefined), @@ -754,6 +755,8 @@ describe("preview histogram call sites", () => { })); vi.doMock("@/lib/canvas-utils", () => ({ resolveMediaAspectRatio: () => null, + canvasHandleAccentColor: () => "rgb(13, 148, 136)", + canvasHandleAccentColorWithAlpha: () => "rgba(13, 148, 136, 0.4)", })); vi.doMock("@/lib/image-formats", () => ({ parseAspectRatioString: () => ({ w: 1, h: 1 }), @@ -875,6 +878,7 @@ describe("preview histogram call sites", () => { vi.doMock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); vi.doMock("convex/react", () => ({ useMutation: () => vi.fn(async () => undefined), @@ -935,6 +939,8 @@ describe("preview histogram call sites", () => { })); vi.doMock("@/lib/canvas-utils", () => ({ resolveMediaAspectRatio: () => null, + canvasHandleAccentColor: () => "rgb(13, 148, 136)", + canvasHandleAccentColorWithAlpha: () => "rgba(13, 148, 136, 0.4)", })); vi.doMock("@/lib/image-formats", () => ({ parseAspectRatioString: () => ({ w: 1, h: 1 }), @@ -1063,6 +1069,7 @@ describe("preview histogram call sites", () => { vi.doMock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), })); vi.doMock("convex/react", () => ({ useMutation: () => vi.fn(async () => undefined), @@ -1126,6 +1133,8 @@ describe("preview histogram call sites", () => { })); vi.doMock("@/lib/canvas-utils", () => ({ resolveMediaAspectRatio: () => null, + canvasHandleAccentColor: () => "rgb(13, 148, 136)", + canvasHandleAccentColorWithAlpha: () => "rgba(13, 148, 136, 0.4)", })); vi.doMock("@/lib/image-formats", () => ({ parseAspectRatioString: () => ({ w: 1, h: 1 }), diff --git a/tests/video-prompt-node.test.ts b/tests/video-prompt-node.test.ts index 2cdc28d..1bf88ea 100644 --- a/tests/video-prompt-node.test.ts +++ b/tests/video-prompt-node.test.ts @@ -123,6 +123,7 @@ vi.mock("@/components/canvas/nodes/base-node-wrapper", () => ({ vi.mock("@xyflow/react", () => ({ Handle: () => null, Position: { Left: "left", Right: "right" }, + useConnection: () => ({ inProgress: false }), useStore: (selector: (state: { edges: typeof mocks.edges; nodes: typeof mocks.nodes }) => unknown) => selector({ edges: mocks.edges, nodes: mocks.nodes }), useReactFlow: () => ({