ci: Delete unused code in some backend tests (no-changelog) (#9456)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-05-17 18:43:50 +02:00 committed by GitHub
parent 6f2d83bffd
commit bf2ee51e36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 118 additions and 766 deletions

View file

@ -4,14 +4,8 @@ import { readdirSync, readFileSync } from 'fs';
const BASE_DIR = path.resolve(__dirname, '../../..');
import type {
ICredentialDataDecryptedObject,
IDataObject,
IDeferredPromise,
IExecuteWorkflowInfo,
IHttpRequestHelper,
IHttpRequestOptions,
INode,
INodeCredentialsDetails,
INodeType,
INodeTypes,
IRun,
@ -24,66 +18,13 @@ import type {
INodeTypeData,
} from 'n8n-workflow';
import { ApplicationError, ICredentialsHelper, NodeHelpers, WorkflowHooks } from 'n8n-workflow';
import { Credentials } from '@/Credentials';
import { ApplicationError, NodeHelpers, WorkflowHooks } from 'n8n-workflow';
import { predefinedNodesTypes } from './constants';
export class CredentialsHelper extends ICredentialsHelper {
async authenticate(
credentials: ICredentialDataDecryptedObject,
typeName: string,
requestParams: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
return requestParams;
}
async preAuthentication(
helpers: IHttpRequestHelper,
credentials: ICredentialDataDecryptedObject,
typeName: string,
node: INode,
credentialsExpired: boolean,
): Promise<ICredentialDataDecryptedObject | undefined> {
return undefined;
}
getParentTypes(name: string): string[] {
return [];
}
async getDecrypted(
additionalData: IWorkflowExecuteAdditionalData,
nodeCredentials: INodeCredentialsDetails,
type: string,
): Promise<ICredentialDataDecryptedObject> {
return {};
}
async getCredentials(
nodeCredentials: INodeCredentialsDetails,
type: string,
): Promise<Credentials> {
return new Credentials({ id: null, name: '' }, '', [], '');
}
async updateCredentials(
nodeCredentials: INodeCredentialsDetails,
type: string,
data: ICredentialDataDecryptedObject,
): Promise<void> {}
}
import { mock } from 'jest-mock-extended';
class NodeTypesClass implements INodeTypes {
nodeTypes: INodeTypeData;
constructor(nodeTypes?: INodeTypeData) {
if (nodeTypes) {
this.nodeTypes = nodeTypes;
} else {
this.nodeTypes = predefinedNodesTypes;
}
}
constructor(private nodeTypes: INodeTypeData = predefinedNodesTypes) {}
getByName(nodeType: string): INodeType | IVersionedNodeType {
return this.nodeTypes[nodeType].type;
@ -92,11 +33,15 @@ class NodeTypesClass implements INodeTypes {
getByNameAndVersion(nodeType: string, version?: number): INodeType {
return NodeHelpers.getVersionedNodeType(this.nodeTypes[nodeType].type, version);
}
getKnownTypes(): IDataObject {
throw new Error('Method not implemented.');
}
}
let nodeTypesInstance: NodeTypesClass | undefined;
export function NodeTypes(nodeTypes?: INodeTypeData): NodeTypesClass {
export function NodeTypes(nodeTypes?: INodeTypeData): INodeTypes {
if (nodeTypesInstance === undefined || nodeTypes !== undefined) {
nodeTypesInstance = new NodeTypesClass(nodeTypes);
}
@ -110,7 +55,7 @@ export function WorkflowExecuteAdditionalData(
): IWorkflowExecuteAdditionalData {
const hookFunctions = {
nodeExecuteAfter: [
async (nodeName: string, data: ITaskData): Promise<void> => {
async (nodeName: string, _data: ITaskData): Promise<void> => {
nodeExecutionOrder.push(nodeName);
},
],
@ -121,26 +66,9 @@ export function WorkflowExecuteAdditionalData(
],
};
const workflowData: IWorkflowBase = {
name: '',
createdAt: new Date(),
updatedAt: new Date(),
active: true,
nodes: [],
connections: {},
};
return {
credentialsHelper: new CredentialsHelper(),
hooks: new WorkflowHooks(hookFunctions, 'trigger', '1', workflowData),
executeWorkflow: async (workflowInfo: IExecuteWorkflowInfo) => {},
sendDataToUI: (message: string) => {},
restApiUrl: '',
webhookBaseUrl: 'webhook',
webhookWaitingBaseUrl: 'webhook-waiting',
webhookTestBaseUrl: 'webhook-test',
userId: '123',
};
return mock<IWorkflowExecuteAdditionalData>({
hooks: new WorkflowHooks(hookFunctions, 'trigger', '1', mock()),
});
}
const preparePinData = (pinData: IDataObject) => {

View file

@ -10,6 +10,7 @@ export async function executeWorkflow(testData: WorkflowTestData, nodeTypes: INo
const { baseUrl, mocks } = testData.nock;
const agent = nock(baseUrl);
mocks.forEach(({ method, path, statusCode, responseBody }) =>
// @ts-expect-error
agent[method](path).reply(statusCode, responseBody),
);
}
@ -24,11 +25,7 @@ export async function executeWorkflow(testData: WorkflowTestData, nodeTypes: INo
});
const waitPromise = await createDeferredPromise<IRun>();
const nodeExecutionOrder: string[] = [];
const additionalData = Helpers.WorkflowExecuteAdditionalData(
waitPromise,
nodeExecutionOrder,
testData,
);
const additionalData = Helpers.WorkflowExecuteAdditionalData(waitPromise, nodeExecutionOrder);
let executionData: IRun;
const runExecutionData: IRunExecutionData = {
@ -36,6 +33,7 @@ export async function executeWorkflow(testData: WorkflowTestData, nodeTypes: INo
runData: {},
},
executionData: {
metadata: {},
contextData: {},
waitingExecution: {},
waitingExecutionSource: null,

View file

@ -6,6 +6,7 @@ import { isEmpty } from 'lodash';
import { get } from 'lodash';
import { BinaryDataService, Credentials, constructExecutionMetaData } from 'n8n-core';
import { Container } from 'typedi';
import { mock } from 'jest-mock-extended';
import type {
CredentialLoadingDetails,
ICredentialDataDecryptedObject,
@ -15,7 +16,6 @@ import type {
IDataObject,
IDeferredPromise,
IExecuteFunctions,
IExecuteWorkflowInfo,
IGetNodeParameterOptions,
IHttpRequestHelper,
IHttpRequestOptions,
@ -87,22 +87,20 @@ class CredentialType implements ICredentialTypes {
return knownCredentials[type]?.supportedNodes ?? [];
}
getParentTypes(typeName: string): string[] {
getParentTypes(_typeName: string): string[] {
return [];
}
}
export class CredentialsHelper extends ICredentialsHelper {
constructor(private credentialTypes: ICredentialTypes) {
super('');
}
const credentialTypes = new CredentialType();
class CredentialsHelper extends ICredentialsHelper {
async authenticate(
credentials: ICredentialDataDecryptedObject,
typeName: string,
requestParams: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const credentialType = this.credentialTypes.getByName(typeName);
const credentialType = credentialTypes.getByName(typeName);
if (typeof credentialType.authenticate === 'function') {
return await credentialType.authenticate(credentials, requestParams);
}
@ -110,21 +108,21 @@ export class CredentialsHelper extends ICredentialsHelper {
}
async preAuthentication(
helpers: IHttpRequestHelper,
credentials: ICredentialDataDecryptedObject,
typeName: string,
node: INode,
credentialsExpired: boolean,
_helpers: IHttpRequestHelper,
_credentials: ICredentialDataDecryptedObject,
_typeName: string,
_node: INode,
_credentialsExpired: boolean,
): Promise<ICredentialDataDecryptedObject | undefined> {
return undefined;
}
getParentTypes(name: string): string[] {
getParentTypes(_name: string): string[] {
return [];
}
async getDecrypted(
additionalData: IWorkflowExecuteAdditionalData,
_additionalData: IWorkflowExecuteAdditionalData,
nodeCredentials: INodeCredentialsDetails,
type: string,
): Promise<ICredentialDataDecryptedObject> {
@ -132,27 +130,26 @@ export class CredentialsHelper extends ICredentialsHelper {
}
async getCredentials(
nodeCredentials: INodeCredentialsDetails,
type: string,
_nodeCredentials: INodeCredentialsDetails,
_type: string,
): Promise<Credentials> {
return new Credentials({ id: null, name: '' }, '', [], '');
return new Credentials({ id: null, name: '' }, '', '');
}
async updateCredentials(
nodeCredentials: INodeCredentialsDetails,
type: string,
data: ICredentialDataDecryptedObject,
_nodeCredentials: INodeCredentialsDetails,
_type: string,
_data: ICredentialDataDecryptedObject,
): Promise<void> {}
}
export function WorkflowExecuteAdditionalData(
waitPromise: IDeferredPromise<IRun>,
nodeExecutionOrder: string[],
workflowTestData?: WorkflowTestData,
): IWorkflowExecuteAdditionalData {
const hookFunctions = {
nodeExecuteAfter: [
async (nodeName: string, data: ITaskData): Promise<void> => {
async (nodeName: string, _data: ITaskData): Promise<void> => {
nodeExecutionOrder.push(nodeName);
},
],
@ -163,27 +160,10 @@ export function WorkflowExecuteAdditionalData(
],
};
const workflowData: IWorkflowBase = {
name: '',
createdAt: new Date(),
updatedAt: new Date(),
active: true,
nodes: [],
connections: {},
};
return {
credentialsHelper: new CredentialsHelper(credentialTypes),
hooks: new WorkflowHooks(hookFunctions, 'trigger', '1', workflowData),
executeWorkflow: async (workflowInfo: IExecuteWorkflowInfo): Promise<any> => {},
sendDataToUI: (message: string) => {},
restApiUrl: '',
webhookBaseUrl: 'webhook',
webhookWaitingBaseUrl: 'webhook-waiting',
webhookTestBaseUrl: 'webhook-test',
userId: '123',
variables: {},
instanceBaseUrl: '',
};
return mock<IWorkflowExecuteAdditionalData>({
credentialsHelper: new CredentialsHelper(),
hooks: new WorkflowHooks(hookFunctions, 'trigger', '1', mock()),
});
}
class NodeTypes implements INodeTypes {
@ -209,6 +189,10 @@ class NodeTypes implements INodeTypes {
getByNameAndVersion(nodeType: string, version?: number): INodeType {
return NodeHelpers.getVersionedNodeType(this.nodeTypes[nodeType].type, version);
}
getKnownTypes(): IDataObject {
throw new Error('Method not implemented.');
}
}
export function createTemporaryDir(prefix = 'n8n') {
@ -225,8 +209,6 @@ export async function initBinaryDataService(mode: 'default' | 'filesystem' = 'de
Container.set(BinaryDataService, binaryDataService);
}
const credentialTypes = new CredentialType();
export function setup(testData: WorkflowTestData[] | WorkflowTestData) {
if (!Array.isArray(testData)) {
testData = [testData];

View file

@ -2060,21 +2060,23 @@ export const eventNamesAiNodes = [
export type EventNamesAiNodesType = (typeof eventNamesAiNodes)[number];
export interface ExecuteWorkflowOptions {
node?: INode;
parentWorkflowId: string;
inputData?: INodeExecutionData[];
parentExecutionId?: string;
loadedWorkflowData?: IWorkflowBase;
loadedRunData?: any;
parentWorkflowSettings?: IWorkflowSettings;
parentCallbackManager?: CallbackManager;
}
export interface IWorkflowExecuteAdditionalData {
credentialsHelper: ICredentialsHelper;
executeWorkflow: (
workflowInfo: IExecuteWorkflowInfo,
additionalData: IWorkflowExecuteAdditionalData,
options: {
node?: INode;
parentWorkflowId: string;
inputData?: INodeExecutionData[];
parentExecutionId?: string;
loadedWorkflowData?: IWorkflowBase;
loadedRunData?: any;
parentWorkflowSettings?: IWorkflowSettings;
parentCallbackManager?: CallbackManager;
},
options: ExecuteWorkflowOptions,
) => Promise<any>;
executionId?: string;
restartExecutionId?: string;

View file

@ -1,531 +1,65 @@
import { readFileSync } from 'fs';
import path from 'path';
import { mock } from 'jest-mock-extended';
import get from 'lodash/get';
import type {
IAdditionalCredentialOptions,
IAllExecuteFunctions,
IContextObject,
ICredentialDataDecryptedObject,
ICredentialsEncrypted,
IDataObject,
IExecuteData,
IExecuteFunctions,
IExecuteResponsePromiseData,
IExecuteSingleFunctions,
IExecuteWorkflowInfo,
IHttpRequestHelper,
IHttpRequestOptions,
IN8nHttpFullResponse,
IN8nHttpResponse,
INode,
INodeCredentialsDetails,
INodeExecutionData,
INodeParameters,
INodeType,
INodeTypes,
IRunExecutionData,
ITaskDataConnections,
IWorkflowBase,
IWorkflowDataProxyAdditionalKeys,
IWorkflowDataProxyData,
IWorkflowExecuteAdditionalData,
NodeParameterValue,
WorkflowExecuteMode,
} from '@/Interfaces';
import { ICredentials, ICredentialsHelper } from '@/Interfaces';
import type { Workflow } from '@/Workflow';
import { WorkflowDataProxy } from '@/WorkflowDataProxy';
import { WorkflowHooks } from '@/WorkflowHooks';
import * as NodeHelpers from '@/NodeHelpers';
import { deepCopy } from '@/utils';
import { getGlobalState } from '@/GlobalState';
import { ApplicationError } from '@/errors/application.error';
import { NodeTypes as NodeTypesClass } from './NodeTypes';
import { readFileSync } from 'fs';
import path from 'path';
export interface INodeTypesObject {
[key: string]: INodeType;
}
export class Credentials extends ICredentials {
setData(data: ICredentialDataDecryptedObject) {
this.data = JSON.stringify(data);
}
getData(): ICredentialDataDecryptedObject {
if (this.data === undefined) {
throw new ApplicationError('No data is set so nothing can be returned');
}
return JSON.parse(this.data);
}
getDataToSave(): ICredentialsEncrypted {
if (this.data === undefined) {
throw new ApplicationError('No credentials were set to save');
}
return {
id: this.id,
name: this.name,
type: this.type,
data: this.data,
};
}
}
export class CredentialsHelper extends ICredentialsHelper {
async authenticate(
credentials: ICredentialDataDecryptedObject,
typeName: string,
requestParams: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
return requestParams;
}
async preAuthentication(
helpers: IHttpRequestHelper,
credentials: ICredentialDataDecryptedObject,
typeName: string,
node: INode,
credentialsExpired: boolean,
): Promise<{ updatedCredentials: boolean; data: ICredentialDataDecryptedObject }> {
return { updatedCredentials: false, data: {} };
}
getParentTypes(name: string): string[] {
return [];
}
async getDecrypted(
additionalData: IWorkflowExecuteAdditionalData,
nodeCredentials: INodeCredentialsDetails,
type: string,
): Promise<ICredentialDataDecryptedObject> {
return {};
}
async getCredentials(
nodeCredentials: INodeCredentialsDetails,
type: string,
): Promise<ICredentials> {
return new Credentials({ id: null, name: '' }, '', [], '');
}
async updateCredentials(
nodeCredentials: INodeCredentialsDetails,
type: string,
data: ICredentialDataDecryptedObject,
): Promise<void> {}
}
export function getNodeParameter(
workflow: Workflow,
runExecutionData: IRunExecutionData | null,
runIndex: number,
connectionInputData: INodeExecutionData[],
node: INode,
parameterName: string,
itemIndex: number,
mode: WorkflowExecuteMode,
additionalKeys: IWorkflowDataProxyAdditionalKeys,
executeData: IExecuteData,
fallbackValue?: any,
): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object {
const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
if (nodeType === undefined) {
throw new ApplicationError('Node type is unknown so cannot return parameter value', {
tags: { nodeType: node.type },
});
}
const value = get(node.parameters, parameterName, fallbackValue);
if (value === undefined) {
throw new ApplicationError('Could not get parameter', { extra: { parameterName } });
}
let returnData;
try {
returnData = workflow.expression.getParameterValue(
value,
runExecutionData,
runIndex,
itemIndex,
node.name,
connectionInputData,
mode,
additionalKeys,
);
} catch (e) {
e.message += ` [Error in parameter: "${parameterName}"]`;
throw e;
}
return returnData;
}
export function getExecuteFunctions(
workflow: Workflow,
runExecutionData: IRunExecutionData,
runIndex: number,
connectionInputData: INodeExecutionData[],
inputData: ITaskDataConnections,
node: INode,
itemIndex: number,
additionalData: IWorkflowExecuteAdditionalData,
executeData: IExecuteData,
mode: WorkflowExecuteMode,
): IExecuteFunctions {
return ((workflow, runExecutionData, connectionInputData, inputData, node) => {
return {
continueOnFail: () => {
return false;
},
evaluateExpression: (expression: string, itemIndex: number) => {
return expression;
},
async executeWorkflow(
workflowInfo: IExecuteWorkflowInfo,
inputData?: INodeExecutionData[],
): Promise<any> {
return await additionalData.executeWorkflow(workflowInfo, additionalData, { inputData });
},
getContext(type: string): IContextObject {
return NodeHelpers.getContext(runExecutionData, type, node);
},
async getCredentials(
type: string,
itemIndex?: number,
): Promise<ICredentialDataDecryptedObject> {
return {
apiKey: '12345',
};
},
getExecutionId: (): string => {
return additionalData.executionId!;
},
getInputData: (inputIndex = 0, inputName = 'main') => {
if (!inputData.hasOwnProperty(inputName)) {
// Return empty array because else it would throw error when nothing is connected to input
return [];
}
if (inputData[inputName].length < inputIndex) {
throw new ApplicationError('Could not get input index', {
extra: { inputIndex, inputName },
});
}
if (inputData[inputName][inputIndex] === null) {
throw new ApplicationError('Value of input did not get set', {
extra: { inputIndex, inputName },
});
}
return inputData[inputName][inputIndex] as INodeExecutionData[];
},
getNodeParameter: (
parameterName: string,
itemIndex: number,
fallbackValue?: any,
):
| NodeParameterValue
| INodeParameters
| NodeParameterValue[]
| INodeParameters[]
| object => {
return getNodeParameter(
workflow,
runExecutionData,
runIndex,
connectionInputData,
node,
parameterName,
itemIndex,
mode,
{},
fallbackValue,
);
},
getMode: (): WorkflowExecuteMode => {
return mode;
},
getNode: () => {
return deepCopy(node);
},
getRestApiUrl: (): string => {
return additionalData.restApiUrl;
},
getTimezone: (): string => {
return workflow.settings.timezone ?? getGlobalState().defaultTimezone;
},
getExecuteData: (): IExecuteData => {
return executeData;
},
getWorkflow: () => {
return {
id: workflow.id,
name: workflow.name,
active: workflow.active,
};
},
getWorkflowDataProxy: (itemIndex: number): IWorkflowDataProxyData => {
const dataProxy = new WorkflowDataProxy(
workflow,
runExecutionData,
runIndex,
itemIndex,
node.name,
connectionInputData,
{},
mode,
{},
executeData,
);
return dataProxy.getDataProxy();
},
getWorkflowStaticData(type: string): IDataObject {
return workflow.getStaticData(type, node);
},
prepareOutputData: NodeHelpers.prepareOutputData,
async putExecutionToWait(waitTill: Date): Promise<void> {
runExecutionData.waitTill = waitTill;
},
sendMessageToUI(...args: any[]): void {
if (mode !== 'manual') {
return;
}
try {
if (additionalData.sendMessageToUI) {
additionalData.sendMessageToUI(node.name, args);
}
} catch (error) {
console.error(`There was a problem sending message to UI: ${error.message}`);
}
},
async sendResponse(response: IExecuteResponsePromiseData): Promise<void> {
await additionalData.hooks?.executeHookFunctions('sendResponse', [response]);
},
helpers: {
async httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpFullResponse | IN8nHttpResponse> {
return {
body: {
headers: {},
statusCode: 200,
requestOptions,
},
};
},
async requestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<any> {
return {
body: {
headers: {},
statusCode: 200,
credentialsType,
requestOptions,
additionalCredentialOptions,
},
};
},
async httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<any> {
return {
body: {
headers: {},
statusCode: 200,
credentialsType,
requestOptions,
additionalCredentialOptions,
},
};
},
},
};
})(workflow, runExecutionData, connectionInputData, inputData, node);
}
export function getExecuteSingleFunctions(
workflow: Workflow,
runExecutionData: IRunExecutionData,
runIndex: number,
connectionInputData: INodeExecutionData[],
inputData: ITaskDataConnections,
node: INode,
itemIndex: number,
additionalData: IWorkflowExecuteAdditionalData,
executeData: IExecuteData,
mode: WorkflowExecuteMode,
): IExecuteSingleFunctions {
return ((workflow, runExecutionData, connectionInputData, inputData, node, itemIndex) => {
return {
continueOnFail: () => {
return false;
},
evaluateExpression: (expression: string, evaluateItemIndex: number | undefined) => {
return expression;
},
getContext(type: string): IContextObject {
return NodeHelpers.getContext(runExecutionData, type, node);
},
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject> {
return mock<IExecuteSingleFunctions>({
getItemIndex: () => itemIndex,
getNodeParameter: (parameterName: string) => {
return workflow.expression.getParameterValue(
get(node.parameters, parameterName),
runExecutionData,
runIndex,
itemIndex,
node.name,
[],
'internal',
{},
);
},
getWorkflow: () => ({
id: workflow.id,
name: workflow.name,
active: workflow.active,
}),
helpers: mock<IExecuteSingleFunctions['helpers']>({
async httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpFullResponse | IN8nHttpResponse> {
return {
apiKey: '12345',
body: {
headers: {},
statusCode: 200,
requestOptions,
},
};
},
getInputData: (inputIndex = 0, inputName = 'main') => {
if (!inputData.hasOwnProperty(inputName)) {
// Return empty array because else it would throw error when nothing is connected to input
return { json: {} };
}
if (inputData[inputName].length < inputIndex) {
throw new ApplicationError('Could not get input index', {
extra: { inputIndex, inputName },
});
}
const allItems = inputData[inputName][inputIndex];
if (allItems === null) {
throw new ApplicationError('Value of input did not get set', {
extra: { inputIndex, inputName },
});
}
if (allItems[itemIndex] === null) {
throw new ApplicationError('Value of input with item index did not get set', {
extra: { inputIndex, inputName, itemIndex },
});
}
return allItems[itemIndex];
},
getItemIndex: () => {
return itemIndex;
},
getMode: (): WorkflowExecuteMode => {
return mode;
},
getNode: () => {
return deepCopy(node);
},
getRestApiUrl: (): string => {
return additionalData.restApiUrl;
},
getTimezone: (): string => {
return workflow.settings.timezone ?? getGlobalState().defaultTimezone;
},
getExecuteData: (): IExecuteData => {
return executeData;
},
getNodeParameter: (
parameterName: string,
fallbackValue?: any,
):
| NodeParameterValue
| INodeParameters
| NodeParameterValue[]
| INodeParameters[]
| object => {
return getNodeParameter(
workflow,
runExecutionData,
runIndex,
connectionInputData,
node,
parameterName,
itemIndex,
mode,
{},
fallbackValue,
);
},
getWorkflow: () => {
return {
id: workflow.id,
name: workflow.name,
active: workflow.active,
};
},
getWorkflowDataProxy: (): IWorkflowDataProxyData => {
const dataProxy = new WorkflowDataProxy(
workflow,
runExecutionData,
runIndex,
itemIndex,
node.name,
connectionInputData,
{},
mode,
{},
executeData,
);
return dataProxy.getDataProxy();
},
getWorkflowStaticData(type: string): IDataObject {
return workflow.getStaticData(type, node);
},
helpers: {
async httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpFullResponse | IN8nHttpResponse> {
return {
body: {
headers: {},
statusCode: 200,
requestOptions,
},
};
},
async requestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<any> {
return {
body: {
headers: {},
statusCode: 200,
credentialsType,
requestOptions,
additionalCredentialOptions,
},
};
},
async httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<any> {
return {
body: {
headers: {},
statusCode: 200,
credentialsType,
requestOptions,
additionalCredentialOptions,
},
};
},
},
};
})(workflow, runExecutionData, connectionInputData, inputData, node, itemIndex);
}),
});
}
let nodeTypesInstance: NodeTypesClass | undefined;
export function NodeTypes(): NodeTypesClass {
export function NodeTypes(): INodeTypes {
if (nodeTypesInstance === undefined) {
nodeTypesInstance = new NodeTypesClass();
}
@ -533,29 +67,6 @@ export function NodeTypes(): NodeTypesClass {
return nodeTypesInstance;
}
export function WorkflowExecuteAdditionalData(): IWorkflowExecuteAdditionalData {
const workflowData: IWorkflowBase = {
name: '',
createdAt: new Date(),
updatedAt: new Date(),
active: true,
nodes: [],
connections: {},
};
return {
credentialsHelper: new CredentialsHelper(),
hooks: new WorkflowHooks({}, 'trigger', '1', workflowData),
executeWorkflow: async (workflowInfo: IExecuteWorkflowInfo): Promise<any> => {},
sendDataToUI: (message: string) => {},
restApiUrl: '',
webhookBaseUrl: 'webhook',
webhookWaitingBaseUrl: 'webhook-waiting',
webhookTestBaseUrl: 'webhook-test',
userId: '123',
};
}
const BASE_DIR = path.resolve(__dirname, '..');
export const readJsonFileSync = <T>(filePath: string) =>
JSON.parse(readFileSync(path.join(BASE_DIR, filePath), 'utf-8')) as T;

View file

@ -1,11 +1,13 @@
import {
NodeHelpers,
type INodeType,
type INodeTypeData,
type INodeTypes,
type IVersionedNodeType,
type LoadedClass,
} from '@/index';
import { mock } from 'jest-mock-extended';
import type {
IDataObject,
INodeType,
INodeTypeData,
INodeTypes,
IVersionedNodeType,
LoadedClass,
} from '@/Interfaces';
import * as NodeHelpers from '@/NodeHelpers';
const stickyNode: LoadedClass<INodeType> = {
type: {
@ -626,39 +628,6 @@ export class NodeTypes implements INodeTypes {
},
},
},
'test.switch': {
sourcePath: '',
type: {
description: {
displayName: 'Set',
name: 'set',
group: ['input'],
version: 1,
description: 'Switches',
defaults: {
name: 'Switch',
color: '#0000FF',
},
inputs: ['main'],
outputs: ['main', 'main', 'main', 'main'],
outputNames: ['0', '1', '2', '3'],
properties: [
{
displayName: 'Value1',
name: 'value1',
type: 'string',
default: 'default-value1',
},
{
displayName: 'Value2',
name: 'value2',
type: 'string',
default: 'default-value2',
},
],
},
},
},
};
getByName(nodeType: string): INodeType | IVersionedNodeType {
@ -669,5 +638,14 @@ export class NodeTypes implements INodeTypes {
if (this.nodeTypes[nodeType]?.type) {
return NodeHelpers.getVersionedNodeType(this.nodeTypes[nodeType]?.type, version);
}
return mock<INodeType>({
description: {
properties: [],
},
});
}
getKnownTypes(): IDataObject {
throw new Error('Method not implemented.');
}
}

View file

@ -7,23 +7,24 @@ import type {
INodeProperties,
IExecuteSingleFunctions,
IHttpRequestOptions,
IN8nHttpFullResponse,
ITaskDataConnections,
INodeExecuteFunctions,
IN8nRequestOperations,
INodeCredentialDescription,
IExecuteData,
INodeTypeDescription,
IWorkflowExecuteAdditionalData,
IExecuteFunctions,
} from '@/Interfaces';
import { RoutingNode } from '@/RoutingNode';
import { Workflow } from '@/Workflow';
import * as Helpers from './Helpers';
import { mock } from 'jest-mock-extended';
const postReceiveFunction1 = async function (
this: IExecuteSingleFunctions,
items: INodeExecutionData[],
response: IN8nHttpFullResponse,
): Promise<INodeExecutionData[]> {
items.forEach((item) => (item.json1 = { success: true }));
return items;
@ -39,6 +40,8 @@ const preSendFunction1 = async function (
};
describe('RoutingNode', () => {
const additionalData = mock<IWorkflowExecuteAdditionalData>();
describe('getRequestOptionsFromParameters', () => {
const tests: Array<{
description: string;
@ -659,7 +662,6 @@ describe('RoutingNode', () => {
const itemIndex = 0;
const connectionInputData: INodeExecutionData[] = [];
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
const additionalData = Helpers.WorkflowExecuteAdditionalData();
const path = '';
const nodeType = nodeTypes.getByNameAndVersion(node.type);
@ -693,17 +695,8 @@ describe('RoutingNode', () => {
workflow,
runExecutionData,
runIndex,
connectionInputData,
{},
node,
itemIndex,
additionalData,
{
node,
data: {},
source: null,
},
mode,
);
const result = routingNode.getRequestOptionsFromParameters(
@ -1704,7 +1697,6 @@ describe('RoutingNode', () => {
const itemIndex = 0;
const connectionInputData: INodeExecutionData[] = [];
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
const additionalData = Helpers.WorkflowExecuteAdditionalData();
const nodeType = nodeTypes.getByNameAndVersion(baseNode.type);
const inputData: ITaskDataConnections = {
@ -1751,34 +1743,15 @@ describe('RoutingNode', () => {
} as IExecuteData;
const nodeExecuteFunctions: Partial<INodeExecuteFunctions> = {
getExecuteFunctions: () => {
return Helpers.getExecuteFunctions(
getExecuteFunctions: () => mock<IExecuteFunctions>(),
getExecuteSingleFunctions: () =>
Helpers.getExecuteSingleFunctions(
workflow,
runExecutionData,
runIndex,
connectionInputData,
{},
node,
itemIndex,
additionalData,
executeData,
mode,
);
},
getExecuteSingleFunctions: () => {
return Helpers.getExecuteSingleFunctions(
workflow,
runExecutionData,
runIndex,
connectionInputData,
{},
node,
itemIndex,
additionalData,
executeData,
mode,
);
},
),
};
const result = await routingNode.runNode(
@ -1870,7 +1843,6 @@ describe('RoutingNode', () => {
const itemIndex = 0;
const connectionInputData: INodeExecutionData[] = [];
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
const additionalData = Helpers.WorkflowExecuteAdditionalData();
const nodeType = nodeTypes.getByNameAndVersion(baseNode.type);
const inputData: ITaskDataConnections = {
@ -1925,32 +1897,13 @@ describe('RoutingNode', () => {
let currentItemIndex = 0;
for (let iteration = 0; iteration < inputData.main[0]!.length; iteration++) {
const nodeExecuteFunctions: Partial<INodeExecuteFunctions> = {
getExecuteFunctions: () => {
return Helpers.getExecuteFunctions(
workflow,
runExecutionData,
runIndex,
connectionInputData,
{},
node,
itemIndex + iteration,
additionalData,
executeData,
mode,
);
},
getExecuteSingleFunctions: () => {
return Helpers.getExecuteSingleFunctions(
workflow,
runExecutionData,
runIndex,
connectionInputData,
{},
node,
itemIndex + iteration,
additionalData,
executeData,
mode,
);
},
};