fix(canvas): align magnetism tests and connection-line lint

This commit is contained in:
2026-04-11 09:12:53 +02:00
parent baeb709acd
commit ab491eb141
12 changed files with 31 additions and 11 deletions

View File

@@ -699,6 +699,7 @@ describe("favorite retention in strict local node flows", () => {
vi.doMock("@xyflow/react", () => ({ vi.doMock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
const importedModule = (await import(modulePath)) as { const importedModule = (await import(modulePath)) as {

View File

@@ -18,6 +18,11 @@ type CanvasConnectionMagnetismState = {
const CanvasConnectionMagnetismContext = const CanvasConnectionMagnetismContext =
createContext<CanvasConnectionMagnetismState | null>(null); createContext<CanvasConnectionMagnetismState | null>(null);
const FALLBACK_MAGNETISM_STATE: CanvasConnectionMagnetismState = {
activeTarget: null,
setActiveTarget: () => undefined,
};
export function CanvasConnectionMagnetismProvider({ export function CanvasConnectionMagnetismProvider({
children, children,
}: { }: {
@@ -42,10 +47,5 @@ export function CanvasConnectionMagnetismProvider({
export function useCanvasConnectionMagnetism(): CanvasConnectionMagnetismState { export function useCanvasConnectionMagnetism(): CanvasConnectionMagnetismState {
const context = useContext(CanvasConnectionMagnetismContext); const context = useContext(CanvasConnectionMagnetismContext);
if (!context) { return context ?? FALLBACK_MAGNETISM_STATE;
throw new Error(
"useCanvasConnectionMagnetism must be used within CanvasConnectionMagnetismProvider",
);
}
return context;
} }

View File

@@ -53,6 +53,8 @@ export default function CustomConnectionLine({
}: ConnectionLineComponentProps) { }: ConnectionLineComponentProps) {
const { getNodes, getEdges } = useReactFlow(); const { getNodes, getEdges } = useReactFlow();
const { activeTarget, setActiveTarget } = useCanvasConnectionMagnetism(); const { activeTarget, setActiveTarget } = useCanvasConnectionMagnetism();
const fromHandleId = fromHandle?.id;
const fromNodeId = fromNode?.id;
const fromHandleType = const fromHandleType =
fromHandle?.type === "source" || fromHandle?.type === "target" fromHandle?.type === "source" || fromHandle?.type === "target"
@@ -60,19 +62,19 @@ export default function CustomConnectionLine({
: null; : null;
const resolvedMagnetTarget = useMemo(() => { const resolvedMagnetTarget = useMemo(() => {
if (!fromHandleType || !fromNode?.id) { if (!fromHandleType || !fromNodeId) {
return null; return null;
} }
return resolveCanvasMagnetTarget({ return resolveCanvasMagnetTarget({
point: { x: toX, y: toY }, point: { x: toX, y: toY },
fromNodeId: fromNode.id, fromNodeId,
fromHandleId: fromHandle?.id ?? undefined, fromHandleId: fromHandleId ?? undefined,
fromHandleType, fromHandleType,
nodes: getNodes(), nodes: getNodes(),
edges: getEdges(), edges: getEdges(),
}); });
}, [fromHandle?.id, fromHandleType, fromNode?.id, getEdges, getNodes, toX, toY]); }, [fromHandleId, fromHandleType, fromNodeId, getEdges, getNodes, toX, toY]);
useEffect(() => { useEffect(() => {
if (hasSameMagnetTarget(activeTarget, resolvedMagnetTarget)) { if (hasSameMagnetTarget(activeTarget, resolvedMagnetTarget)) {
@@ -119,7 +121,7 @@ export default function CustomConnectionLine({
[path] = getStraightPath(pathParams); [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 opacity = connectionStatus === "invalid" ? 0.45 : 1;
const strokeWidth = snappedTarget ? 3.25 : 2.5; const strokeWidth = snappedTarget ? 3.25 : 2.5;
const filter = snappedTarget const filter = snappedTarget

View File

@@ -142,6 +142,7 @@ vi.mock("next-intl", () => ({
vi.mock("@xyflow/react", () => ({ vi.mock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
import AgentNode from "@/components/canvas/nodes/agent-node"; import AgentNode from "@/components/canvas/nodes/agent-node";

View File

@@ -60,6 +60,7 @@ vi.mock("@xyflow/react", () => ({
}); });
}, },
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
const translations: Record<string, string> = { const translations: Record<string, string> = {

View File

@@ -20,6 +20,7 @@ vi.mock("@xyflow/react", () => ({
}); });
}, },
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
const translations: Record<string, string> = { const translations: Record<string, string> = {

View File

@@ -54,6 +54,7 @@ vi.mock("@/components/canvas/nodes/base-node-wrapper", () => ({
vi.mock("@xyflow/react", () => ({ vi.mock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
useReactFlow: () => ({ useReactFlow: () => ({
getEdges: mocks.getEdges, getEdges: mocks.getEdges,
getNode: mocks.getNode, getNode: mocks.getNode,

View File

@@ -18,6 +18,7 @@ const mocks = vi.hoisted(() => ({
vi.mock("@xyflow/react", () => ({ vi.mock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
vi.mock("next-intl", () => ({ vi.mock("next-intl", () => ({

View File

@@ -19,6 +19,7 @@ const parameterSliderState = vi.hoisted(() => ({
vi.mock("@xyflow/react", () => ({ vi.mock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
vi.mock("convex/react", () => ({ vi.mock("convex/react", () => ({

View File

@@ -135,6 +135,7 @@ vi.mock("@/components/canvas/nodes/base-node-wrapper", () => ({
vi.mock("@xyflow/react", () => ({ vi.mock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
useStore: (selector: (state: { edges: typeof mocks.edges; nodes: typeof mocks.nodes }) => unknown) => useStore: (selector: (state: { edges: typeof mocks.edges; nodes: typeof mocks.nodes }) => unknown) =>
selector({ edges: mocks.edges, nodes: mocks.nodes }), selector({ edges: mocks.edges, nodes: mocks.nodes }),
useReactFlow: () => ({ useReactFlow: () => ({

View File

@@ -691,6 +691,7 @@ describe("preview histogram call sites", () => {
vi.doMock("@xyflow/react", () => ({ vi.doMock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
vi.doMock("convex/react", () => ({ vi.doMock("convex/react", () => ({
useMutation: () => vi.fn(async () => undefined), useMutation: () => vi.fn(async () => undefined),
@@ -754,6 +755,8 @@ describe("preview histogram call sites", () => {
})); }));
vi.doMock("@/lib/canvas-utils", () => ({ vi.doMock("@/lib/canvas-utils", () => ({
resolveMediaAspectRatio: () => null, resolveMediaAspectRatio: () => null,
canvasHandleAccentColor: () => "rgb(13, 148, 136)",
canvasHandleAccentColorWithAlpha: () => "rgba(13, 148, 136, 0.4)",
})); }));
vi.doMock("@/lib/image-formats", () => ({ vi.doMock("@/lib/image-formats", () => ({
parseAspectRatioString: () => ({ w: 1, h: 1 }), parseAspectRatioString: () => ({ w: 1, h: 1 }),
@@ -875,6 +878,7 @@ describe("preview histogram call sites", () => {
vi.doMock("@xyflow/react", () => ({ vi.doMock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
vi.doMock("convex/react", () => ({ vi.doMock("convex/react", () => ({
useMutation: () => vi.fn(async () => undefined), useMutation: () => vi.fn(async () => undefined),
@@ -935,6 +939,8 @@ describe("preview histogram call sites", () => {
})); }));
vi.doMock("@/lib/canvas-utils", () => ({ vi.doMock("@/lib/canvas-utils", () => ({
resolveMediaAspectRatio: () => null, resolveMediaAspectRatio: () => null,
canvasHandleAccentColor: () => "rgb(13, 148, 136)",
canvasHandleAccentColorWithAlpha: () => "rgba(13, 148, 136, 0.4)",
})); }));
vi.doMock("@/lib/image-formats", () => ({ vi.doMock("@/lib/image-formats", () => ({
parseAspectRatioString: () => ({ w: 1, h: 1 }), parseAspectRatioString: () => ({ w: 1, h: 1 }),
@@ -1063,6 +1069,7 @@ describe("preview histogram call sites", () => {
vi.doMock("@xyflow/react", () => ({ vi.doMock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
})); }));
vi.doMock("convex/react", () => ({ vi.doMock("convex/react", () => ({
useMutation: () => vi.fn(async () => undefined), useMutation: () => vi.fn(async () => undefined),
@@ -1126,6 +1133,8 @@ describe("preview histogram call sites", () => {
})); }));
vi.doMock("@/lib/canvas-utils", () => ({ vi.doMock("@/lib/canvas-utils", () => ({
resolveMediaAspectRatio: () => null, resolveMediaAspectRatio: () => null,
canvasHandleAccentColor: () => "rgb(13, 148, 136)",
canvasHandleAccentColorWithAlpha: () => "rgba(13, 148, 136, 0.4)",
})); }));
vi.doMock("@/lib/image-formats", () => ({ vi.doMock("@/lib/image-formats", () => ({
parseAspectRatioString: () => ({ w: 1, h: 1 }), parseAspectRatioString: () => ({ w: 1, h: 1 }),

View File

@@ -123,6 +123,7 @@ vi.mock("@/components/canvas/nodes/base-node-wrapper", () => ({
vi.mock("@xyflow/react", () => ({ vi.mock("@xyflow/react", () => ({
Handle: () => null, Handle: () => null,
Position: { Left: "left", Right: "right" }, Position: { Left: "left", Right: "right" },
useConnection: () => ({ inProgress: false }),
useStore: (selector: (state: { edges: typeof mocks.edges; nodes: typeof mocks.nodes }) => unknown) => useStore: (selector: (state: { edges: typeof mocks.edges; nodes: typeof mocks.nodes }) => unknown) =>
selector({ edges: mocks.edges, nodes: mocks.nodes }), selector({ edges: mocks.edges, nodes: mocks.nodes }),
useReactFlow: () => ({ useReactFlow: () => ({