fix(editor): Only show node executing spinner if workflow is executing (no-changelog) (#16846)

This commit is contained in:
Alex Grozav
2025-07-01 11:44:28 +03:00
committed by GitHub
parent 4124b96a00
commit 4abb6a6aa1
3 changed files with 68 additions and 23 deletions

View File

@@ -78,6 +78,7 @@ const mappedConnectionsThrottled = throttledRef(mappedConnections, 200);
:connections="executing ? mappedConnectionsThrottled : mappedConnections"
:event-bus="eventBus"
:read-only="readOnly"
:executing="executing"
v-bind="$attrs"
/>
</div>

View File

@@ -1,6 +1,6 @@
import CanvasNodeStatusIcons from './CanvasNodeStatusIcons.vue';
import { createComponentRenderer } from '@/__tests__/render';
import { createCanvasNodeProvide } from '@/__tests__/data';
import { createCanvasNodeProvide, createCanvasProvide } from '@/__tests__/data';
import { createTestingPinia } from '@pinia/testing';
import { CanvasNodeDirtiness, CanvasNodeRenderType } from '@/types';
@@ -12,7 +12,10 @@ describe('CanvasNodeStatusIcons', () => {
it('should render correctly for a pinned node', () => {
const { getByTestId } = renderComponent({
global: {
provide: createCanvasNodeProvide({ data: { pinnedData: { count: 5, visible: true } } }),
provide: {
...createCanvasProvide(),
...createCanvasNodeProvide({ data: { pinnedData: { count: 5, visible: true } } }),
},
},
});
@@ -22,31 +25,59 @@ describe('CanvasNodeStatusIcons', () => {
it('should not render pinned icon when disabled', () => {
const { queryByTestId } = renderComponent({
global: {
provide: createCanvasNodeProvide({
data: { disabled: true, pinnedData: { count: 5, visible: true } },
}),
provide: {
...createCanvasProvide(),
...createCanvasNodeProvide({
data: { disabled: true, pinnedData: { count: 5, visible: true } },
}),
},
},
});
expect(queryByTestId('canvas-node-status-pinned')).not.toBeInTheDocument();
});
it('should render correctly for a running node', () => {
const { getByTestId } = renderComponent({
global: {
provide: createCanvasNodeProvide({ data: { execution: { running: true } } }),
},
describe('executing', () => {
it('should not show node as executing if workflow is not executing', () => {
const { getByTestId } = renderComponent({
global: {
provide: {
...createCanvasProvide({
isExecuting: false,
}),
...createCanvasNodeProvide({ data: { execution: { running: true } } }),
},
},
});
expect(() => getByTestId('canvas-node-status-running')).toThrow();
});
expect(getByTestId('canvas-node-status-running')).toBeInTheDocument();
it('should render running node correctly', () => {
const { getByTestId } = renderComponent({
global: {
provide: {
...createCanvasProvide({
isExecuting: true,
}),
...createCanvasNodeProvide({ data: { execution: { running: true } } }),
},
},
});
expect(getByTestId('canvas-node-status-running')).toBeVisible();
});
});
it('should render correctly for a node that ran successfully', () => {
const { getByTestId } = renderComponent({
global: {
provide: createCanvasNodeProvide({
data: { runData: { outputMap: {}, iterations: 15, visible: true } },
}),
provide: {
...createCanvasProvide(),
...createCanvasNodeProvide({
data: { runData: { outputMap: {}, iterations: 15, visible: true } },
}),
},
},
});
@@ -56,15 +87,18 @@ describe('CanvasNodeStatusIcons', () => {
it('should render correctly for a dirty node that has run successfully', () => {
const { getByTestId } = renderComponent({
global: {
provide: createCanvasNodeProvide({
data: {
runData: { outputMap: {}, iterations: 15, visible: true },
render: {
type: CanvasNodeRenderType.Default,
options: { dirtiness: CanvasNodeDirtiness.PARAMETERS_UPDATED },
provide: {
...createCanvasProvide(),
...createCanvasNodeProvide({
data: {
runData: { outputMap: {}, iterations: 15, visible: true },
render: {
type: CanvasNodeRenderType.Default,
options: { dirtiness: CanvasNodeDirtiness.PARAMETERS_UPDATED },
},
},
},
}),
}),
},
},
});

View File

@@ -6,6 +6,7 @@ import { useCanvasNode } from '@/composables/useCanvasNode';
import { useI18n } from '@n8n/i18n';
import { CanvasNodeDirtiness, CanvasNodeRenderType } from '@/types';
import { N8nTooltip } from '@n8n/design-system';
import { useCanvas } from '@/composables/useCanvas';
const nodeHelpers = useNodeHelpers();
const i18n = useI18n();
@@ -23,11 +24,20 @@ const {
isDisabled,
render,
} = useCanvasNode();
const { isExecuting } = useCanvas();
const hideNodeIssues = computed(() => false); // @TODO Implement this
const dirtiness = computed(() =>
render.value.type === CanvasNodeRenderType.Default ? render.value.options.dirtiness : undefined,
);
const isNodeExecuting = computed(() => {
if (!isExecuting.value) return false;
return (
executionRunning.value || executionWaitingForNext.value || executionStatus.value === 'running' // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing
);
});
</script>
<template>
@@ -60,7 +70,7 @@ const dirtiness = computed(() =>
<!-- Do nothing, unknown means the node never executed -->
</div>
<div
v-else-if="executionRunning || executionWaitingForNext || executionStatus === 'running'"
v-else-if="isNodeExecuting"
data-test-id="canvas-node-status-running"
:class="[$style.status, $style.running]"
>