fix(editor): Disable test step option in context menu for sub-nodes (#13816)

This commit is contained in:
jeanpaul
2025-03-11 14:56:49 +01:00
committed by GitHub
parent e8334eefa1
commit b6d5092258
4 changed files with 300 additions and 3 deletions

View File

@@ -47,6 +47,7 @@ describe('useContextMenu', () => {
} as never);
vi.spyOn(NodeHelpers, 'getNodeInputs').mockReturnValue([]);
vi.spyOn(NodeHelpers, 'isExecutable').mockReturnValue(true);
});
afterEach(() => {
@@ -106,6 +107,18 @@ describe('useContextMenu', () => {
expect(targetNodeIds.value).toEqual([basicChain.id]);
});
it('should disable test step option for sub-nodes (AI tool nodes)', () => {
const { open, isOpen, actions, targetNodeIds } = useContextMenu();
const subNode = nodeFactory({ type: 'n8n-nodes-base.hackerNewsTool' });
vi.spyOn(workflowsStore, 'getNodeById').mockReturnValue(subNode);
vi.spyOn(NodeHelpers, 'isExecutable').mockReturnValueOnce(false);
open(mockEvent, { source: 'node-right-click', nodeId: subNode.id });
expect(isOpen.value).toBe(true);
expect(actions.value.find((action) => action.id === 'execute')?.disabled).toBe(true);
expect(targetNodeIds.value).toEqual([subNode.id]);
});
it('should return the correct actions when right clicking a Node', () => {
const { open, isOpen, actions, targetNodeIds } = useContextMenu();
const node = nodeFactory();
@@ -141,7 +154,6 @@ describe('useContextMenu', () => {
expect(actions.value).toMatchSnapshot();
expect(targetNodeIds.value).toEqual([sticky.id]);
});
it('should return the correct actions when right clicking a Node', () => {
vi.spyOn(uiStore, 'isReadOnlyView', 'get').mockReturnValue(true);
const { open, isOpen, actions, targetNodeIds } = useContextMenu();

View File

@@ -1,10 +1,11 @@
import type { ActionDropdownItem, XYPosition } from '@/Interface';
import type { ActionDropdownItem, XYPosition, INodeUi } from '@/Interface';
import { NOT_DUPLICATABLE_NODE_TYPES, STICKY_NODE_TYPE } from '@/constants';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useSourceControlStore } from '@/stores/sourceControl.store';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import type { INode, INodeTypeDescription } from 'n8n-workflow';
import { NodeHelpers } from 'n8n-workflow';
import { computed, ref, watch } from 'vue';
import { getMousePosition } from '../utils/nodeViewUtils';
import { useI18n } from './useI18n';
@@ -94,6 +95,16 @@ export const useContextMenu = (onAction: ContextMenuActionCallback = () => {}) =
position.value = [0, 0];
};
const isExecutable = (node: INodeUi) => {
const currentWorkflow = workflowsStore.getCurrentWorkflow();
const workflowNode = currentWorkflow.getNode(node.name) as INode;
const nodeType = nodeTypesStore.getNodeType(
workflowNode.type,
workflowNode.typeVersion,
) as INodeTypeDescription;
return NodeHelpers.isExecutable(currentWorkflow, workflowNode, nodeType);
};
const open = (event: MouseEvent, menuTarget: ContextMenuTarget) => {
event.stopPropagation();
@@ -228,7 +239,7 @@ export const useContextMenu = (onAction: ContextMenuActionCallback = () => {}) =
{
id: 'execute',
label: i18n.baseText('contextMenu.test'),
disabled: isReadOnly.value,
disabled: isReadOnly.value || !isExecutable(nodes[0]),
},
{
id: 'rename',