import type { INodeType, INodeTypeData, INodeTypes, IConnections, IDataObject, INode, IPinData, IWorkflowSettings, LoadedClass, INodeTypeDescription, INodeIssues, } from 'n8n-workflow'; import { NodeConnectionTypes, NodeHelpers, Workflow } from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; import { mock } from 'vitest-mock-extended'; import { AGENT_NODE_TYPE, CHAT_TRIGGER_NODE_TYPE, CODE_NODE_TYPE, EXECUTABLE_TRIGGER_NODE_TYPES, MANUAL_TRIGGER_NODE_TYPE, NO_OP_NODE_TYPE, SET_NODE_TYPE, SIMULATE_NODE_TYPE, STICKY_NODE_TYPE, } from '@/constants'; import type { INodeUi, IWorkflowDb } from '@/Interface'; import { CanvasNodeRenderType } from '@/types'; export const mockNode = ({ id = uuid(), name, type, position = [0, 0], disabled = false, issues = undefined, typeVersion = 1, parameters = {}, }: { id?: INodeUi['id']; name: INodeUi['name']; type: INodeUi['type']; position?: INodeUi['position']; disabled?: INodeUi['disabled']; issues?: INodeIssues; typeVersion?: INodeUi['typeVersion']; parameters?: INodeUi['parameters']; }) => mock({ id, name, type, position, disabled, issues, typeVersion, parameters }); export const mockNodeTypeDescription = ({ name = SET_NODE_TYPE, icon = 'fa:pen', version = 1, credentials = [], inputs = [NodeConnectionTypes.Main], outputs = [NodeConnectionTypes.Main], codex = undefined, properties = [], group, }: { name?: INodeTypeDescription['name']; icon?: INodeTypeDescription['icon']; version?: INodeTypeDescription['version']; credentials?: INodeTypeDescription['credentials']; inputs?: INodeTypeDescription['inputs']; outputs?: INodeTypeDescription['outputs']; codex?: INodeTypeDescription['codex']; properties?: INodeTypeDescription['properties']; group?: INodeTypeDescription['group']; } = {}) => mock({ name, icon, displayName: name, description: '', version, defaults: { name, }, defaultVersion: Array.isArray(version) ? version[version.length - 1] : version, properties: properties as [], maxNodes: Infinity, group: (group ?? EXECUTABLE_TRIGGER_NODE_TYPES.includes(name)) ? ['trigger'] : [], inputs, outputs, codex, credentials, documentationUrl: 'https://docs', iconUrl: 'nodes/test-node/icon.svg', webhooks: undefined, }); export const mockLoadedNodeType = (name: string) => mock>({ type: mock({ // @ts-expect-error description: mockNodeTypeDescription({ name }), }), }); export const mockNodes = [ mockNode({ name: 'Manual Trigger', type: MANUAL_TRIGGER_NODE_TYPE }), mockNode({ name: 'Set', type: SET_NODE_TYPE }), mockNode({ name: 'Code', type: CODE_NODE_TYPE }), mockNode({ name: 'Rename', type: SET_NODE_TYPE }), mockNode({ name: 'Chat Trigger', type: CHAT_TRIGGER_NODE_TYPE }), mockNode({ name: 'Agent', type: AGENT_NODE_TYPE }), mockNode({ name: 'Sticky', type: STICKY_NODE_TYPE }), mockNode({ name: 'Simulate', type: SIMULATE_NODE_TYPE }), mockNode({ name: CanvasNodeRenderType.AddNodes, type: CanvasNodeRenderType.AddNodes }), mockNode({ name: 'End', type: NO_OP_NODE_TYPE }), ]; export const defaultNodeTypes = mockNodes.reduce((acc, { type }) => { acc[type] = mockLoadedNodeType(type); return acc; }, {}); export const defaultNodeDescriptions = Object.values(defaultNodeTypes).map( ({ type }) => type.description, ) as INodeTypeDescription[]; const nodeTypes = mock({ getByName(nodeType) { return defaultNodeTypes[nodeType].type; }, getByNameAndVersion(nodeType: string, version?: number): INodeType { return NodeHelpers.getVersionedNodeType(defaultNodeTypes[nodeType].type, version); }, }); export function createTestWorkflowObject({ id = uuid(), name = 'Test Workflow', nodes = [], connections = {}, active = false, staticData = {}, settings = {}, pinData = {}, }: { id?: string; name?: string; nodes?: INode[]; connections?: IConnections; active?: boolean; staticData?: IDataObject; settings?: IWorkflowSettings; pinData?: IPinData; } = {}) { return new Workflow({ id, name, nodes, connections, active, staticData, settings, pinData, nodeTypes, }); } export function createTestWorkflow({ id = uuid(), name = 'Test Workflow', nodes = [], connections = {}, active = false, settings = { timezone: 'DEFAULT', executionOrder: 'v1', }, pinData = {}, ...rest }: Partial = {}): IWorkflowDb { return { createdAt: '', updatedAt: '', id, name, nodes, connections, active, settings, versionId: '1', meta: {}, pinData, ...rest, }; } export function createTestNode(node: Partial = {}): INode { return { id: uuid(), name: 'Node', type: 'n8n-nodes-base.set', typeVersion: 1, position: [0, 0] as [number, number], parameters: {}, ...node, }; }