From 5b760e7f7fc612b10307b4871e24b549f5d9d420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20FIlipovi=C4=87?= Date: Fri, 24 Jan 2025 09:38:57 +0100 Subject: [PATCH] fix(editor): Show input selector when node has error (#12813) --- .../editor-ui/src/components/RunData.test.ts | 157 ++++++++++++++++-- packages/editor-ui/src/components/RunData.vue | 3 +- 2 files changed, 144 insertions(+), 16 deletions(-) diff --git a/packages/editor-ui/src/components/RunData.test.ts b/packages/editor-ui/src/components/RunData.test.ts index 26a58b06aca2e..fb6dcbcdb3171 100644 --- a/packages/editor-ui/src/components/RunData.test.ts +++ b/packages/editor-ui/src/components/RunData.test.ts @@ -34,17 +34,6 @@ vi.mock('@/composables/useExecutionHelpers', () => ({ }), })); -const nodes = [ - { - id: '1', - typeVersion: 3, - name: 'Test Node', - position: [0, 0], - type: SET_NODE_TYPE, - parameters: {}, - }, -] as INodeUi[]; - describe('RunData', () => { beforeAll(() => { resolveRelatedExecutionUrl.mockReturnValue('execution.url/123'); @@ -398,8 +387,146 @@ describe('RunData', () => { expect(trackOpeningRelatedExecution).toHaveBeenCalledWith(metadata, 'json'); }); + it('should render input selector when input node has error', async () => { + const testNodes = [ + { + id: '1', + name: 'When clicking ‘Test workflow’', + type: 'n8n-nodes-base.manualTrigger', + typeVersion: 1, + position: [80, -180], + disabled: false, + parameters: { notice: '' }, + }, + { + id: '2', + name: 'Edit Fields', + type: 'n8n-nodes-base.set', + parameters: { + mode: 'manual', + duplicateItem: false, + assignments: { + _custom: { type: 'reactive', stateTypeName: 'Reactive', value: {} }, + }, + includeOtherFields: false, + options: {}, + }, + typeVersion: 3.4, + position: [500, -180], + }, + { + id: '3', + name: 'Test Node', + type: 'n8n-nodes-base.code', + parameters: { + mode: 'runOnceForAllItems', + language: 'javaScript', + jsCode: "throw Error('yo')", + notice: '', + }, + typeVersion: 2, + position: [300, -180], + issues: { + _custom: { + type: 'reactive', + stateTypeName: 'Reactive', + value: { execution: true }, + }, + }, + }, + ] as INodeUi[]; + + const { getByTestId } = render({ + workflowNodes: testNodes, + runs: [ + { + hints: [], + startTime: 1737643696893, + executionTime: 2, + source: [ + { + previousNode: 'When clicking ‘Test workflow’', + }, + ], + executionStatus: 'error', + // @ts-expect-error allow missing properties in test + error: { + level: 'error', + tags: { + packageName: 'nodes-base', + }, + description: null, + lineNumber: 1, + node: { + type: 'n8n-nodes-base.code', + typeVersion: 2, + position: [300, -180], + id: 'e41f12e0-d178-4294-8748-da5a6a531be6', + name: 'Test Node', + parameters: { + mode: 'runOnceForAllItems', + language: 'javaScript', + jsCode: "throw Error('yo')", + notice: '', + }, + }, + message: 'yo [line 1]', + stack: 'Error: yo\n n8n/packages/core/src/execution-engine/workflow-execute.ts:2066:11', + }, + }, + ], + defaultRunItems: [ + { + hints: [], + startTime: 1737641598215, + executionTime: 3, + // @ts-expect-error allow missing properties in test + source: [{ previousNode: 'Execute Workflow Trigger' }], + // @ts-expect-error allow missing properties in test + executionStatus: 'error', + // @ts-expect-error allow missing properties in test + error: { + level: 'error', + tags: { packageName: 'nodes-base' }, + description: null, + lineNumber: 1, + node: { + id: 'e41f12e0-d178-4294-8748-da5a6a531be6', + name: 'Test Node', + type: 'n8n-nodes-base.code', + typeVersion: 2, + position: [300, -180], + parameters: { + mode: 'runOnceForAllItems', + language: 'javaScript', + jsCode: "throw Error('yo')", + notice: '', + }, + }, + message: 'yo [line 1]', + stack: 'Error: yo\n n8n/packages/core/src/execution-engine/workflow-execute.ts:2066:11', + }, + }, + ], + }); + expect(getByTestId('ndv-items-count')).toBeInTheDocument(); + }); + + // Default values for the render function + const nodes = [ + { + id: '1', + typeVersion: 3, + name: 'Test Node', + position: [0, 0], + type: SET_NODE_TYPE, + parameters: {}, + }, + ] as INodeUi[]; + const render = ({ defaultRunItems, + workflowNodes = nodes, displayMode, pinnedData, paneType = 'output', @@ -407,6 +534,7 @@ describe('RunData', () => { runs, }: { defaultRunItems?: INodeExecutionData[]; + workflowNodes?: INodeUi[]; displayMode: IRunDataDisplayMode; pinnedData?: INodeExecutionData[]; paneType?: NodePanelType; @@ -433,7 +561,7 @@ describe('RunData', () => { }, [STORES.WORKFLOWS]: { workflow: { - nodes, + workflowNodes, }, workflowExecutionData: { id: '1', @@ -468,7 +596,7 @@ describe('RunData', () => { const nodeTypesStore = useNodeTypesStore(); nodeTypesStore.setNodeTypes(defaultNodeDescriptions); - vi.mocked(workflowsStore).getNodeByName.mockReturnValue(nodes[0]); + vi.mocked(workflowsStore).getNodeByName.mockReturnValue(workflowNodes[0]); if (pinnedData) { vi.mocked(workflowsStore).pinDataByNodeName.mockReturnValue(pinnedData); @@ -480,7 +608,8 @@ describe('RunData', () => { name: 'Test Node', }, workflow: createTestWorkflowObject({ - nodes, + // @ts-expect-error allow missing properties in test + workflowNodes, }), }, global: { diff --git a/packages/editor-ui/src/components/RunData.vue b/packages/editor-ui/src/components/RunData.vue index 1c1ddbde90d39..05a94aaa45dfb 100644 --- a/packages/editor-ui/src/components/RunData.vue +++ b/packages/editor-ui/src/components/RunData.vue @@ -1493,14 +1493,13 @@ defineExpose({ enterEditMode });