mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-20 03:12:15 +00:00
fix(editor): Fix node graph generation for evaluation node in set metrics mode (#18344)
This commit is contained in:
@@ -51,11 +51,15 @@ import { useTelemetry } from './useTelemetry';
|
||||
import { useToast } from '@/composables/useToast';
|
||||
import * as nodeHelpers from '@/composables/useNodeHelpers';
|
||||
|
||||
import { TelemetryHelpers } from 'n8n-workflow';
|
||||
|
||||
vi.mock('n8n-workflow', async (importOriginal) => {
|
||||
const actual = await importOriginal<{}>();
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||
const actual = await importOriginal<typeof import('n8n-workflow')>();
|
||||
return {
|
||||
...actual,
|
||||
TelemetryHelpers: {
|
||||
...actual.TelemetryHelpers,
|
||||
generateNodesGraph: vi.fn().mockReturnValue({
|
||||
nodeGraph: {
|
||||
nodes: [],
|
||||
@@ -2726,34 +2730,6 @@ describe('useCanvasOperations', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('duplicateNodes', () => {
|
||||
it('should duplicate nodes', async () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const nodeTypeDescription = mockNodeTypeDescription({ name: SET_NODE_TYPE });
|
||||
|
||||
nodeTypesStore.nodeTypes = {
|
||||
[SET_NODE_TYPE]: { 1: nodeTypeDescription },
|
||||
};
|
||||
|
||||
const nodes = buildImportNodes();
|
||||
workflowsStore.setNodes(nodes);
|
||||
workflowsStore.getNodesByIds.mockReturnValue(nodes);
|
||||
workflowsStore.outgoingConnectionsByNodeName.mockReturnValue({});
|
||||
|
||||
const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
workflowsStore.workflowObject = workflowObject;
|
||||
workflowsStore.createWorkflowObject.mockReturnValue(workflowObject);
|
||||
|
||||
const canvasOperations = useCanvasOperations();
|
||||
const duplicatedNodeIds = await canvasOperations.duplicateNodes(['1', '2']);
|
||||
|
||||
expect(duplicatedNodeIds.length).toBe(2);
|
||||
expect(duplicatedNodeIds).not.toContain('1');
|
||||
expect(duplicatedNodeIds).not.toContain('2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('copyNodes', () => {
|
||||
it('should copy nodes', async () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
@@ -3420,6 +3396,69 @@ describe('useCanvasOperations', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('duplicateNodes', () => {
|
||||
it('should duplicate nodes', async () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const nodeTypeDescription = mockNodeTypeDescription({ name: SET_NODE_TYPE });
|
||||
|
||||
nodeTypesStore.nodeTypes = {
|
||||
[SET_NODE_TYPE]: { 1: nodeTypeDescription },
|
||||
};
|
||||
|
||||
const nodes = buildImportNodes();
|
||||
workflowsStore.setNodes(nodes);
|
||||
workflowsStore.getNodesByIds.mockReturnValue(nodes);
|
||||
workflowsStore.outgoingConnectionsByNodeName.mockReturnValue({});
|
||||
|
||||
const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
workflowsStore.workflowObject = workflowObject;
|
||||
workflowsStore.createWorkflowObject.mockReturnValue(workflowObject);
|
||||
|
||||
const canvasOperations = useCanvasOperations();
|
||||
const duplicatedNodeIds = await canvasOperations.duplicateNodes(['1', '2']);
|
||||
|
||||
expect(duplicatedNodeIds.length).toBe(2);
|
||||
expect(duplicatedNodeIds).not.toContain('1');
|
||||
expect(duplicatedNodeIds).not.toContain('2');
|
||||
});
|
||||
|
||||
it('should not crash when TelemetryHelpers.generateNodesGraph throws error', async () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const telemetry = useTelemetry();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const nodeTypeDescription = mockNodeTypeDescription({ name: SET_NODE_TYPE });
|
||||
|
||||
nodeTypesStore.nodeTypes = {
|
||||
[SET_NODE_TYPE]: { 1: nodeTypeDescription },
|
||||
};
|
||||
|
||||
const nodes = buildImportNodes();
|
||||
workflowsStore.setNodes(nodes);
|
||||
workflowsStore.getNodesByIds.mockReturnValue(nodes);
|
||||
workflowsStore.outgoingConnectionsByNodeName.mockReturnValue({});
|
||||
|
||||
const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
workflowsStore.workflowObject = workflowObject;
|
||||
workflowsStore.createWorkflowObject.mockReturnValue(workflowObject);
|
||||
|
||||
// Mock TelemetryHelpers.generateNodesGraph to throw an error for this test
|
||||
vi.mocked(TelemetryHelpers.generateNodesGraph).mockImplementationOnce(() => {
|
||||
throw new Error('Telemetry generation failed');
|
||||
});
|
||||
|
||||
// This should not throw even when telemetry fails
|
||||
const canvasOperations = useCanvasOperations();
|
||||
await expect(canvasOperations.duplicateNodes(['1', '2'])).resolves.not.toThrow();
|
||||
|
||||
// Telemetry should not be tracked when generation fails
|
||||
expect(telemetry.track).not.toHaveBeenCalledWith(
|
||||
'User imported workflow',
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('importTemplate', () => {
|
||||
it('should import template to canvas', async () => {
|
||||
const projectsStore = mockedStore(useProjectsStore);
|
||||
|
||||
@@ -1916,37 +1916,41 @@ export function useCanvasOperations() {
|
||||
|
||||
removeUnknownCredentials(workflowData);
|
||||
|
||||
const nodeGraph = JSON.stringify(
|
||||
TelemetryHelpers.generateNodesGraph(
|
||||
workflowData as IWorkflowBase,
|
||||
workflowHelpers.getNodeTypes(),
|
||||
{
|
||||
nodeIdMap,
|
||||
sourceInstanceId:
|
||||
workflowData.meta && workflowData.meta.instanceId !== rootStore.instanceId
|
||||
? workflowData.meta.instanceId
|
||||
: '',
|
||||
isCloudDeployment: settingsStore.isCloudDeployment,
|
||||
},
|
||||
).nodeGraph,
|
||||
);
|
||||
try {
|
||||
const nodeGraph = JSON.stringify(
|
||||
TelemetryHelpers.generateNodesGraph(
|
||||
workflowData as IWorkflowBase,
|
||||
workflowHelpers.getNodeTypes(),
|
||||
{
|
||||
nodeIdMap,
|
||||
sourceInstanceId:
|
||||
workflowData.meta && workflowData.meta.instanceId !== rootStore.instanceId
|
||||
? workflowData.meta.instanceId
|
||||
: '',
|
||||
isCloudDeployment: settingsStore.isCloudDeployment,
|
||||
},
|
||||
).nodeGraph,
|
||||
);
|
||||
|
||||
if (source === 'paste') {
|
||||
telemetry.track('User pasted nodes', {
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_graph_string: nodeGraph,
|
||||
});
|
||||
} else if (source === 'duplicate') {
|
||||
telemetry.track('User duplicated nodes', {
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_graph_string: nodeGraph,
|
||||
});
|
||||
} else {
|
||||
telemetry.track('User imported workflow', {
|
||||
source,
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_graph_string: nodeGraph,
|
||||
});
|
||||
if (source === 'paste') {
|
||||
telemetry.track('User pasted nodes', {
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_graph_string: nodeGraph,
|
||||
});
|
||||
} else if (source === 'duplicate') {
|
||||
telemetry.track('User duplicated nodes', {
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_graph_string: nodeGraph,
|
||||
});
|
||||
} else {
|
||||
telemetry.track('User imported workflow', {
|
||||
source,
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_graph_string: nodeGraph,
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// If telemetry fails, don't throw an error
|
||||
}
|
||||
|
||||
// Fix the node position as it could be totally offscreen
|
||||
|
||||
Reference in New Issue
Block a user