From 3edecffd710006eb9ea4f06c105f7d9c665c8e78 Mon Sep 17 00:00:00 2001 From: Tomi Turtiainen <10324676+tomi@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:32:15 +0200 Subject: [PATCH 01/53] refactor: Move runner types to runner package (#11552) --- packages/@n8n/task-runner/package.json | 14 +- packages/@n8n/task-runner/src/index.ts | 1 + .../built-ins-parser-state.ts | 4 +- .../@n8n/task-runner/src/message-types.ts | 204 +++++++++++++ packages/@n8n/task-runner/src/runner-types.ts | 268 +++++------------- packages/@n8n/task-runner/src/task-runner.ts | 26 +- .../src/runners/__tests__/task-broker.test.ts | 16 +- packages/cli/src/runners/runner-types.ts | 229 +-------------- packages/cli/src/runners/runner-ws-server.ts | 13 +- .../cli/src/runners/task-broker.service.ts | 43 +-- .../data-request-response-builder.test.ts | 2 +- .../data-request-response-builder.ts | 11 +- .../task-managers/local-task-manager.ts | 4 +- .../src/runners/task-managers/task-manager.ts | 104 ++----- .../cli/src/runners/task-runner-process.ts | 2 +- .../task-runner-module.internal.test.ts | 1 + 16 files changed, 376 insertions(+), 566 deletions(-) create mode 100644 packages/@n8n/task-runner/src/message-types.ts diff --git a/packages/@n8n/task-runner/package.json b/packages/@n8n/task-runner/package.json index cb47095c15b..4b5478a97d3 100644 --- a/packages/@n8n/task-runner/package.json +++ b/packages/@n8n/task-runner/package.json @@ -17,10 +17,22 @@ }, "main": "dist/start.js", "module": "src/start.ts", - "types": "dist/start.d.ts", + "types": "dist/index.d.ts", "files": [ "dist/**/*" ], + "exports": { + "./start": { + "require": "./dist/start.js", + "import": "./src/start.ts", + "types": "./dist/start.d.ts" + }, + ".": { + "require": "./dist/index.js", + "import": "./src/index.ts", + "types": "./dist/index.d.ts" + } + }, "dependencies": { "@n8n/config": "workspace:*", "acorn": "8.14.0", diff --git a/packages/@n8n/task-runner/src/index.ts b/packages/@n8n/task-runner/src/index.ts index 59e6f6d2884..bc770ea08ea 100644 --- a/packages/@n8n/task-runner/src/index.ts +++ b/packages/@n8n/task-runner/src/index.ts @@ -1,2 +1,3 @@ export * from './task-runner'; export * from './runner-types'; +export * from './message-types'; diff --git a/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser-state.ts b/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser-state.ts index 112c97ccdae..064a45df676 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser-state.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser-state.ts @@ -1,4 +1,4 @@ -import type { N8nMessage } from '../../runner-types'; +import type { BrokerMessage } from '@/message-types'; /** * Class to keep track of which built-in variables are accessed in the code @@ -53,7 +53,7 @@ export class BuiltInsParserState { this.needs$prevNode = true; } - toDataRequestParams(): N8nMessage.ToRequester.TaskDataRequest['requestParams'] { + toDataRequestParams(): BrokerMessage.ToRequester.TaskDataRequest['requestParams'] { return { dataOfNodes: this.needsAllNodes ? 'all' : Array.from(this.neededNodeNames), env: this.needs$env, diff --git a/packages/@n8n/task-runner/src/message-types.ts b/packages/@n8n/task-runner/src/message-types.ts new file mode 100644 index 00000000000..95c5f5b72f5 --- /dev/null +++ b/packages/@n8n/task-runner/src/message-types.ts @@ -0,0 +1,204 @@ +import type { INodeTypeBaseDescription } from 'n8n-workflow'; + +import type { RPC_ALLOW_LIST, TaskDataRequestParams, TaskResultData } from './runner-types'; + +export namespace BrokerMessage { + export namespace ToRunner { + export interface InfoRequest { + type: 'broker:inforequest'; + } + + export interface RunnerRegistered { + type: 'broker:runnerregistered'; + } + + export interface TaskOfferAccept { + type: 'broker:taskofferaccept'; + taskId: string; + offerId: string; + } + + export interface TaskCancel { + type: 'broker:taskcancel'; + taskId: string; + reason: string; + } + + export interface TaskSettings { + type: 'broker:tasksettings'; + taskId: string; + settings: unknown; + } + + export interface RPCResponse { + type: 'broker:rpcresponse'; + callId: string; + taskId: string; + status: 'success' | 'error'; + data: unknown; + } + + export interface TaskDataResponse { + type: 'broker:taskdataresponse'; + taskId: string; + requestId: string; + data: unknown; + } + + export interface NodeTypes { + type: 'broker:nodetypes'; + nodeTypes: INodeTypeBaseDescription[]; + } + + export type All = + | InfoRequest + | TaskOfferAccept + | TaskCancel + | TaskSettings + | RunnerRegistered + | RPCResponse + | TaskDataResponse + | NodeTypes; + } + + export namespace ToRequester { + export interface TaskReady { + type: 'broker:taskready'; + requestId: string; + taskId: string; + } + + export interface TaskDone { + type: 'broker:taskdone'; + taskId: string; + data: TaskResultData; + } + + export interface TaskError { + type: 'broker:taskerror'; + taskId: string; + error: unknown; + } + + export interface TaskDataRequest { + type: 'broker:taskdatarequest'; + taskId: string; + requestId: string; + requestParams: TaskDataRequestParams; + } + + export interface RPC { + type: 'broker:rpc'; + callId: string; + taskId: string; + name: (typeof RPC_ALLOW_LIST)[number]; + params: unknown[]; + } + + export type All = TaskReady | TaskDone | TaskError | TaskDataRequest | RPC; + } +} + +export namespace RequesterMessage { + export namespace ToBroker { + export interface TaskSettings { + type: 'requester:tasksettings'; + taskId: string; + settings: unknown; + } + + export interface TaskCancel { + type: 'requester:taskcancel'; + taskId: string; + reason: string; + } + + export interface TaskDataResponse { + type: 'requester:taskdataresponse'; + taskId: string; + requestId: string; + data: unknown; + } + + export interface RPCResponse { + type: 'requester:rpcresponse'; + taskId: string; + callId: string; + status: 'success' | 'error'; + data: unknown; + } + + export interface TaskRequest { + type: 'requester:taskrequest'; + requestId: string; + taskType: string; + } + + export type All = TaskSettings | TaskCancel | RPCResponse | TaskDataResponse | TaskRequest; + } +} + +export namespace RunnerMessage { + export namespace ToBroker { + export interface Info { + type: 'runner:info'; + name: string; + types: string[]; + } + + export interface TaskAccepted { + type: 'runner:taskaccepted'; + taskId: string; + } + + export interface TaskRejected { + type: 'runner:taskrejected'; + taskId: string; + reason: string; + } + + export interface TaskDone { + type: 'runner:taskdone'; + taskId: string; + data: TaskResultData; + } + + export interface TaskError { + type: 'runner:taskerror'; + taskId: string; + error: unknown; + } + + export interface TaskOffer { + type: 'runner:taskoffer'; + offerId: string; + taskType: string; + validFor: number; + } + + export interface TaskDataRequest { + type: 'runner:taskdatarequest'; + taskId: string; + requestId: string; + requestParams: TaskDataRequestParams; + } + + export interface RPC { + type: 'runner:rpc'; + callId: string; + taskId: string; + name: (typeof RPC_ALLOW_LIST)[number]; + params: unknown[]; + } + + export type All = + | Info + | TaskDone + | TaskError + | TaskAccepted + | TaskRejected + | TaskOffer + | RPC + | TaskDataRequest; + } +} diff --git a/packages/@n8n/task-runner/src/runner-types.ts b/packages/@n8n/task-runner/src/runner-types.ts index 898279feacf..c55b50bf4c8 100644 --- a/packages/@n8n/task-runner/src/runner-types.ts +++ b/packages/@n8n/task-runner/src/runner-types.ts @@ -1,216 +1,90 @@ -import type { INodeExecutionData, INodeTypeBaseDescription } from 'n8n-workflow'; +import type { + EnvProviderState, + IDataObject, + IExecuteData, + IExecuteFunctions, + INode, + INodeExecutionData, + INodeParameters, + IRunExecutionData, + ITaskDataConnections, + IWorkflowExecuteAdditionalData, + Workflow, + WorkflowExecuteMode, + WorkflowParameters, +} from 'n8n-workflow'; +/** + * Specifies what data should be included for a task data request. + */ export interface TaskDataRequestParams { dataOfNodes: string[] | 'all'; prevNode: boolean; + /** Whether input data for the node should be included */ input: boolean; + /** Whether env provider's state should be included */ env: boolean; } +export interface DataRequestResponse { + workflow: Omit; + inputData: ITaskDataConnections; + node: INode; + + runExecutionData: IRunExecutionData; + runIndex: number; + itemIndex: number; + activeNodeName: string; + connectionInputData: INodeExecutionData[]; + siblingParameters: INodeParameters; + mode: WorkflowExecuteMode; + envProviderState: EnvProviderState; + executeData?: IExecuteData; + defaultReturnRunIndex: number; + selfData: IDataObject; + contextNodeName: string; + additionalData: PartialAdditionalData; +} + export interface TaskResultData { result: INodeExecutionData[]; customData?: Record; } -export namespace N8nMessage { - export namespace ToRunner { - export interface InfoRequest { - type: 'broker:inforequest'; - } +export interface TaskData { + executeFunctions: IExecuteFunctions; + inputData: ITaskDataConnections; + node: INode; - export interface RunnerRegistered { - type: 'broker:runnerregistered'; - } - - export interface TaskOfferAccept { - type: 'broker:taskofferaccept'; - taskId: string; - offerId: string; - } - - export interface TaskCancel { - type: 'broker:taskcancel'; - taskId: string; - reason: string; - } - - export interface TaskSettings { - type: 'broker:tasksettings'; - taskId: string; - settings: unknown; - } - - export interface RPCResponse { - type: 'broker:rpcresponse'; - callId: string; - taskId: string; - status: 'success' | 'error'; - data: unknown; - } - - export interface TaskDataResponse { - type: 'broker:taskdataresponse'; - taskId: string; - requestId: string; - data: unknown; - } - - export interface NodeTypes { - type: 'broker:nodetypes'; - nodeTypes: INodeTypeBaseDescription[]; - } - - export type All = - | InfoRequest - | TaskOfferAccept - | TaskCancel - | TaskSettings - | RunnerRegistered - | RPCResponse - | TaskDataResponse - | NodeTypes; - } - - export namespace ToRequester { - export interface TaskReady { - type: 'broker:taskready'; - requestId: string; - taskId: string; - } - - export interface TaskDone { - type: 'broker:taskdone'; - taskId: string; - data: TaskResultData; - } - - export interface TaskError { - type: 'broker:taskerror'; - taskId: string; - error: unknown; - } - - export interface TaskDataRequest { - type: 'broker:taskdatarequest'; - taskId: string; - requestId: string; - requestParams: TaskDataRequestParams; - } - - export interface RPC { - type: 'broker:rpc'; - callId: string; - taskId: string; - name: (typeof RPC_ALLOW_LIST)[number]; - params: unknown[]; - } - - export type All = TaskReady | TaskDone | TaskError | TaskDataRequest | RPC; - } + workflow: Workflow; + runExecutionData: IRunExecutionData; + runIndex: number; + itemIndex: number; + activeNodeName: string; + connectionInputData: INodeExecutionData[]; + siblingParameters: INodeParameters; + mode: WorkflowExecuteMode; + envProviderState: EnvProviderState; + executeData?: IExecuteData; + defaultReturnRunIndex: number; + selfData: IDataObject; + contextNodeName: string; + additionalData: IWorkflowExecuteAdditionalData; } -export namespace RequesterMessage { - export namespace ToN8n { - export interface TaskSettings { - type: 'requester:tasksettings'; - taskId: string; - settings: unknown; - } - - export interface TaskCancel { - type: 'requester:taskcancel'; - taskId: string; - reason: string; - } - - export interface TaskDataResponse { - type: 'requester:taskdataresponse'; - taskId: string; - requestId: string; - data: unknown; - } - - export interface RPCResponse { - type: 'requester:rpcresponse'; - taskId: string; - callId: string; - status: 'success' | 'error'; - data: unknown; - } - - export interface TaskRequest { - type: 'requester:taskrequest'; - requestId: string; - taskType: string; - } - - export type All = TaskSettings | TaskCancel | RPCResponse | TaskDataResponse | TaskRequest; - } -} - -export namespace RunnerMessage { - export namespace ToN8n { - export interface Info { - type: 'runner:info'; - name: string; - types: string[]; - } - - export interface TaskAccepted { - type: 'runner:taskaccepted'; - taskId: string; - } - - export interface TaskRejected { - type: 'runner:taskrejected'; - taskId: string; - reason: string; - } - - export interface TaskDone { - type: 'runner:taskdone'; - taskId: string; - data: TaskResultData; - } - - export interface TaskError { - type: 'runner:taskerror'; - taskId: string; - error: unknown; - } - - export interface TaskOffer { - type: 'runner:taskoffer'; - offerId: string; - taskType: string; - validFor: number; - } - - export interface TaskDataRequest { - type: 'runner:taskdatarequest'; - taskId: string; - requestId: string; - requestParams: TaskDataRequestParams; - } - - export interface RPC { - type: 'runner:rpc'; - callId: string; - taskId: string; - name: (typeof RPC_ALLOW_LIST)[number]; - params: unknown[]; - } - - export type All = - | Info - | TaskDone - | TaskError - | TaskAccepted - | TaskRejected - | TaskOffer - | RPC - | TaskDataRequest; - } +export interface PartialAdditionalData { + executionId?: string; + restartExecutionId?: string; + restApiUrl: string; + instanceBaseUrl: string; + formWaitingBaseUrl: string; + webhookBaseUrl: string; + webhookWaitingBaseUrl: string; + webhookTestBaseUrl: string; + currentNodeParameters?: INodeParameters; + executionTimeoutTimestamp?: number; + userId?: string; + variables: IDataObject; } export const RPC_ALLOW_LIST = [ diff --git a/packages/@n8n/task-runner/src/task-runner.ts b/packages/@n8n/task-runner/src/task-runner.ts index b292bd44135..81de93e6b03 100644 --- a/packages/@n8n/task-runner/src/task-runner.ts +++ b/packages/@n8n/task-runner/src/task-runner.ts @@ -2,14 +2,10 @@ import { ApplicationError, type INodeTypeDescription } from 'n8n-workflow'; import { nanoid } from 'nanoid'; import { type MessageEvent, WebSocket } from 'ws'; -import type { BaseRunnerConfig } from './config/base-runner-config'; -import { TaskRunnerNodeTypes } from './node-types'; -import { - RPC_ALLOW_LIST, - type RunnerMessage, - type N8nMessage, - type TaskResultData, -} from './runner-types'; +import type { BaseRunnerConfig } from '@/config/base-runner-config'; +import type { BrokerMessage, RunnerMessage } from '@/message-types'; +import { TaskRunnerNodeTypes } from '@/node-types'; +import { RPC_ALLOW_LIST, type TaskResultData } from '@/runner-types'; export interface Task { taskId: string; @@ -90,7 +86,7 @@ export abstract class TaskRunner { private receiveMessage = (message: MessageEvent) => { // eslint-disable-next-line n8n-local-rules/no-uncaught-json-parse - const data = JSON.parse(message.data as string) as N8nMessage.ToRunner.All; + const data = JSON.parse(message.data as string) as BrokerMessage.ToRunner.All; void this.onMessage(data); }; @@ -140,11 +136,11 @@ export abstract class TaskRunner { } } - send(message: RunnerMessage.ToN8n.All) { + send(message: RunnerMessage.ToBroker.All) { this.ws.send(JSON.stringify(message)); } - onMessage(message: N8nMessage.ToRunner.All) { + onMessage(message: BrokerMessage.ToRunner.All) { switch (message.type) { case 'broker:inforequest': this.send({ @@ -252,7 +248,7 @@ export abstract class TaskRunner { this.sendOffers(); } - taskDone(taskId: string, data: RunnerMessage.ToN8n.TaskDone['data']) { + taskDone(taskId: string, data: RunnerMessage.ToBroker.TaskDone['data']) { this.send({ type: 'runner:taskdone', taskId, @@ -288,7 +284,7 @@ export abstract class TaskRunner { async requestData( taskId: Task['taskId'], - requestParams: RunnerMessage.ToN8n.TaskDataRequest['requestParams'], + requestParams: RunnerMessage.ToBroker.TaskDataRequest['requestParams'], ): Promise { const requestId = nanoid(); @@ -314,7 +310,7 @@ export abstract class TaskRunner { } } - async makeRpcCall(taskId: string, name: RunnerMessage.ToN8n.RPC['name'], params: unknown[]) { + async makeRpcCall(taskId: string, name: RunnerMessage.ToBroker.RPC['name'], params: unknown[]) { const callId = nanoid(); const dataPromise = new Promise((resolve, reject) => { @@ -342,7 +338,7 @@ export abstract class TaskRunner { handleRpcResponse( callId: string, - status: N8nMessage.ToRunner.RPCResponse['status'], + status: BrokerMessage.ToRunner.RPCResponse['status'], data: unknown, ) { const call = this.rpcCalls.get(callId); diff --git a/packages/cli/src/runners/__tests__/task-broker.test.ts b/packages/cli/src/runners/__tests__/task-broker.test.ts index 8787ba59557..715c5d8eb8b 100644 --- a/packages/cli/src/runners/__tests__/task-broker.test.ts +++ b/packages/cli/src/runners/__tests__/task-broker.test.ts @@ -1,7 +1,7 @@ +import type { RunnerMessage, TaskResultData } from '@n8n/task-runner'; import { mock } from 'jest-mock-extended'; import { TaskRejectError } from '../errors'; -import type { RunnerMessage, TaskResultData } from '../runner-types'; import { TaskBroker } from '../task-broker.service'; import type { TaskOffer, TaskRequest, TaskRunner } from '../task-broker.service'; @@ -381,7 +381,7 @@ describe('TaskBroker', () => { const runnerId = 'runner1'; const taskId = 'task1'; - const message: RunnerMessage.ToN8n.TaskAccepted = { + const message: RunnerMessage.ToBroker.TaskAccepted = { type: 'runner:taskaccepted', taskId, }; @@ -406,7 +406,7 @@ describe('TaskBroker', () => { const taskId = 'task1'; const rejectionReason = 'Task execution failed'; - const message: RunnerMessage.ToN8n.TaskRejected = { + const message: RunnerMessage.ToBroker.TaskRejected = { type: 'runner:taskrejected', taskId, reason: rejectionReason, @@ -433,7 +433,7 @@ describe('TaskBroker', () => { const requesterId = 'requester1'; const data = mock(); - const message: RunnerMessage.ToN8n.TaskDone = { + const message: RunnerMessage.ToBroker.TaskDone = { type: 'runner:taskdone', taskId, data, @@ -464,7 +464,7 @@ describe('TaskBroker', () => { const requesterId = 'requester1'; const errorMessage = 'Task execution failed'; - const message: RunnerMessage.ToN8n.TaskError = { + const message: RunnerMessage.ToBroker.TaskError = { type: 'runner:taskerror', taskId, error: errorMessage, @@ -494,14 +494,14 @@ describe('TaskBroker', () => { const taskId = 'task1'; const requesterId = 'requester1'; const requestId = 'request1'; - const requestParams: RunnerMessage.ToN8n.TaskDataRequest['requestParams'] = { + const requestParams: RunnerMessage.ToBroker.TaskDataRequest['requestParams'] = { dataOfNodes: 'all', env: true, input: true, prevNode: true, }; - const message: RunnerMessage.ToN8n.TaskDataRequest = { + const message: RunnerMessage.ToBroker.TaskDataRequest = { type: 'runner:taskdatarequest', taskId, requestId, @@ -534,7 +534,7 @@ describe('TaskBroker', () => { const rpcName = 'helpers.httpRequestWithAuthentication'; const rpcParams = ['param1', 'param2']; - const message: RunnerMessage.ToN8n.RPC = { + const message: RunnerMessage.ToBroker.RPC = { type: 'runner:rpc', taskId, callId, diff --git a/packages/cli/src/runners/runner-types.ts b/packages/cli/src/runners/runner-types.ts index c5d4eb81c3a..8fcfe968d3c 100644 --- a/packages/cli/src/runners/runner-types.ts +++ b/packages/cli/src/runners/runner-types.ts @@ -1,5 +1,5 @@ import type { Response } from 'express'; -import type { INodeExecutionData, INodeTypeBaseDescription } from 'n8n-workflow'; +import type { INodeExecutionData } from 'n8n-workflow'; import type WebSocket from 'ws'; import type { TaskRunner } from './task-broker.service'; @@ -34,230 +34,3 @@ export interface TaskRunnerServerInitRequest } export type TaskRunnerServerInitResponse = Response & { req: TaskRunnerServerInitRequest }; - -export namespace N8nMessage { - export namespace ToRunner { - export interface InfoRequest { - type: 'broker:inforequest'; - } - - export interface RunnerRegistered { - type: 'broker:runnerregistered'; - } - - export interface TaskOfferAccept { - type: 'broker:taskofferaccept'; - taskId: string; - offerId: string; - } - - export interface TaskCancel { - type: 'broker:taskcancel'; - taskId: string; - reason: string; - } - - export interface TaskSettings { - type: 'broker:tasksettings'; - taskId: string; - settings: unknown; - } - - export interface RPCResponse { - type: 'broker:rpcresponse'; - callId: string; - taskId: string; - status: 'success' | 'error'; - data: unknown; - } - - export interface TaskDataResponse { - type: 'broker:taskdataresponse'; - taskId: string; - requestId: string; - data: unknown; - } - - export interface NodeTypes { - type: 'broker:nodetypes'; - nodeTypes: INodeTypeBaseDescription[]; - } - - export type All = - | InfoRequest - | TaskOfferAccept - | TaskCancel - | TaskSettings - | RunnerRegistered - | RPCResponse - | TaskDataResponse - | NodeTypes; - } - - export namespace ToRequester { - export interface TaskReady { - type: 'broker:taskready'; - requestId: string; - taskId: string; - } - - export interface TaskDone { - type: 'broker:taskdone'; - taskId: string; - data: TaskResultData; - } - - export interface TaskError { - type: 'broker:taskerror'; - taskId: string; - error: unknown; - } - - export interface TaskDataRequest { - type: 'broker:taskdatarequest'; - taskId: string; - requestId: string; - requestParams: TaskDataRequestParams; - } - - export interface RPC { - type: 'broker:rpc'; - callId: string; - taskId: string; - name: (typeof RPC_ALLOW_LIST)[number]; - params: unknown[]; - } - - export type All = TaskReady | TaskDone | TaskError | TaskDataRequest | RPC; - } -} - -export namespace RequesterMessage { - export namespace ToN8n { - export interface TaskSettings { - type: 'requester:tasksettings'; - taskId: string; - settings: unknown; - } - - export interface TaskCancel { - type: 'requester:taskcancel'; - taskId: string; - reason: string; - } - - export interface TaskDataResponse { - type: 'requester:taskdataresponse'; - taskId: string; - requestId: string; - data: unknown; - } - - export interface RPCResponse { - type: 'requester:rpcresponse'; - taskId: string; - callId: string; - status: 'success' | 'error'; - data: unknown; - } - - export interface TaskRequest { - type: 'requester:taskrequest'; - requestId: string; - taskType: string; - } - - export type All = TaskSettings | TaskCancel | RPCResponse | TaskDataResponse | TaskRequest; - } -} - -export namespace RunnerMessage { - export namespace ToN8n { - export interface Info { - type: 'runner:info'; - name: string; - types: string[]; - } - - export interface TaskAccepted { - type: 'runner:taskaccepted'; - taskId: string; - } - - export interface TaskRejected { - type: 'runner:taskrejected'; - taskId: string; - reason: string; - } - - export interface TaskDone { - type: 'runner:taskdone'; - taskId: string; - data: TaskResultData; - } - - export interface TaskError { - type: 'runner:taskerror'; - taskId: string; - error: unknown; - } - - export interface TaskOffer { - type: 'runner:taskoffer'; - offerId: string; - taskType: string; - validFor: number; - } - - export interface TaskDataRequest { - type: 'runner:taskdatarequest'; - taskId: string; - requestId: string; - requestParams: TaskDataRequestParams; - } - - export interface RPC { - type: 'runner:rpc'; - callId: string; - taskId: string; - name: (typeof RPC_ALLOW_LIST)[number]; - params: unknown[]; - } - - export type All = - | Info - | TaskDone - | TaskError - | TaskAccepted - | TaskRejected - | TaskOffer - | RPC - | TaskDataRequest; - } -} - -export const RPC_ALLOW_LIST = [ - 'logNodeOutput', - 'helpers.httpRequestWithAuthentication', - 'helpers.requestWithAuthenticationPaginated', - // "helpers.normalizeItems" - // "helpers.constructExecutionMetaData" - // "helpers.assertBinaryData" - 'helpers.getBinaryDataBuffer', - // "helpers.copyInputItems" - // "helpers.returnJsonArray" - 'helpers.getSSHClient', - 'helpers.createReadStream', - // "helpers.getStoragePath" - 'helpers.writeContentToFile', - 'helpers.prepareBinaryData', - 'helpers.setBinaryDataBuffer', - 'helpers.copyBinaryFile', - 'helpers.binaryToBuffer', - // "helpers.binaryToString" - // "helpers.getBinaryPath" - 'helpers.getBinaryStream', - 'helpers.getBinaryMetadata', - 'helpers.createDeferredPromise', - 'helpers.httpRequest', -] as const; diff --git a/packages/cli/src/runners/runner-ws-server.ts b/packages/cli/src/runners/runner-ws-server.ts index 5d4c4e96079..baaac82bf35 100644 --- a/packages/cli/src/runners/runner-ws-server.ts +++ b/packages/cli/src/runners/runner-ws-server.ts @@ -1,3 +1,4 @@ +import type { BrokerMessage, RunnerMessage } from '@n8n/task-runner'; import { Service } from 'typedi'; import type WebSocket from 'ws'; @@ -5,11 +6,9 @@ import { Logger } from '@/logging/logger.service'; import { DefaultTaskRunnerDisconnectAnalyzer } from './default-task-runner-disconnect-analyzer'; import type { - RunnerMessage, - N8nMessage, + DisconnectAnalyzer, TaskRunnerServerInitRequest, TaskRunnerServerInitResponse, - DisconnectAnalyzer, } from './runner-types'; import { TaskBroker, type MessageCallback, type TaskRunner } from './task-broker.service'; @@ -35,7 +34,7 @@ export class TaskRunnerWsServer { return this.disconnectAnalyzer; } - sendMessage(id: TaskRunner['id'], message: N8nMessage.ToRunner.All) { + sendMessage(id: TaskRunner['id'], message: BrokerMessage.ToRunner.All) { this.runnerConnections.get(id)?.send(JSON.stringify(message)); } @@ -49,9 +48,9 @@ export class TaskRunnerWsServer { try { const buffer = Array.isArray(data) ? Buffer.concat(data) : Buffer.from(data); - const message: RunnerMessage.ToN8n.All = JSON.parse( + const message: RunnerMessage.ToBroker.All = JSON.parse( buffer.toString('utf8'), - ) as RunnerMessage.ToN8n.All; + ) as RunnerMessage.ToBroker.All; if (!isConnected && message.type !== 'runner:info') { return; @@ -94,7 +93,7 @@ export class TaskRunnerWsServer { connection.on('message', onMessage); connection.send( - JSON.stringify({ type: 'broker:inforequest' } as N8nMessage.ToRunner.InfoRequest), + JSON.stringify({ type: 'broker:inforequest' } as BrokerMessage.ToRunner.InfoRequest), ); } diff --git a/packages/cli/src/runners/task-broker.service.ts b/packages/cli/src/runners/task-broker.service.ts index 754d99ef325..7d00cf232e0 100644 --- a/packages/cli/src/runners/task-broker.service.ts +++ b/packages/cli/src/runners/task-broker.service.ts @@ -1,3 +1,9 @@ +import type { + BrokerMessage, + RequesterMessage, + RunnerMessage, + TaskResultData, +} from '@n8n/task-runner'; import { ApplicationError } from 'n8n-workflow'; import { nanoid } from 'nanoid'; import { Service } from 'typedi'; @@ -6,7 +12,6 @@ import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import { Logger } from '@/logging/logger.service'; import { TaskRejectError } from './errors'; -import type { N8nMessage, RunnerMessage, RequesterMessage, TaskResultData } from './runner-types'; export interface TaskRunner { id: string; @@ -38,13 +43,15 @@ export interface TaskRequest { acceptInProgress?: boolean; } -export type MessageCallback = (message: N8nMessage.ToRunner.All) => Promise | void; +export type MessageCallback = (message: BrokerMessage.ToRunner.All) => Promise | void; export type RequesterMessageCallback = ( - message: N8nMessage.ToRequester.All, + message: BrokerMessage.ToRequester.All, ) => Promise | void; type RunnerAcceptCallback = () => void; -type RequesterAcceptCallback = (settings: RequesterMessage.ToN8n.TaskSettings['settings']) => void; +type RequesterAcceptCallback = ( + settings: RequesterMessage.ToBroker.TaskSettings['settings'], +) => void; type TaskRejectCallback = (reason: TaskRejectError) => void; @Service() @@ -134,11 +141,11 @@ export class TaskBroker { this.requesters.delete(requesterId); } - private async messageRunner(runnerId: TaskRunner['id'], message: N8nMessage.ToRunner.All) { + private async messageRunner(runnerId: TaskRunner['id'], message: BrokerMessage.ToRunner.All) { await this.knownRunners.get(runnerId)?.messageCallback(message); } - private async messageAllRunners(message: N8nMessage.ToRunner.All) { + private async messageAllRunners(message: BrokerMessage.ToRunner.All) { await Promise.allSettled( [...this.knownRunners.values()].map(async (runner) => { await runner.messageCallback(message); @@ -146,11 +153,11 @@ export class TaskBroker { ); } - private async messageRequester(requesterId: string, message: N8nMessage.ToRequester.All) { + private async messageRequester(requesterId: string, message: BrokerMessage.ToRequester.All) { await this.requesters.get(requesterId)?.(message); } - async onRunnerMessage(runnerId: TaskRunner['id'], message: RunnerMessage.ToN8n.All) { + async onRunnerMessage(runnerId: TaskRunner['id'], message: RunnerMessage.ToBroker.All) { const runner = this.knownRunners.get(runnerId); if (!runner) { return; @@ -193,7 +200,7 @@ export class TaskBroker { async handleRpcRequest( taskId: Task['id'], callId: string, - name: RunnerMessage.ToN8n.RPC['name'], + name: RunnerMessage.ToBroker.RPC['name'], params: unknown[], ) { const task = this.tasks.get(taskId); @@ -227,8 +234,8 @@ export class TaskBroker { async handleDataRequest( taskId: Task['id'], - requestId: RunnerMessage.ToN8n.TaskDataRequest['requestId'], - requestParams: RunnerMessage.ToN8n.TaskDataRequest['requestParams'], + requestId: RunnerMessage.ToBroker.TaskDataRequest['requestId'], + requestParams: RunnerMessage.ToBroker.TaskDataRequest['requestParams'], ) { const task = this.tasks.get(taskId); if (!task) { @@ -244,7 +251,7 @@ export class TaskBroker { async handleResponse( taskId: Task['id'], - requestId: RunnerMessage.ToN8n.TaskDataRequest['requestId'], + requestId: RunnerMessage.ToBroker.TaskDataRequest['requestId'], data: unknown, ) { const task = this.tasks.get(taskId); @@ -259,7 +266,7 @@ export class TaskBroker { }); } - async onRequesterMessage(requesterId: string, message: RequesterMessage.ToN8n.All) { + async onRequesterMessage(requesterId: string, message: RequesterMessage.ToBroker.All) { switch (message.type) { case 'requester:tasksettings': this.handleRequesterAccept(message.taskId, message.settings); @@ -291,7 +298,7 @@ export class TaskBroker { async handleRequesterRpcResponse( taskId: string, callId: string, - status: RequesterMessage.ToN8n.RPCResponse['status'], + status: RequesterMessage.ToBroker.RPCResponse['status'], data: unknown, ) { const runner = await this.getRunnerOrFailTask(taskId); @@ -317,7 +324,7 @@ export class TaskBroker { handleRequesterAccept( taskId: Task['id'], - settings: RequesterMessage.ToN8n.TaskSettings['settings'], + settings: RequesterMessage.ToBroker.TaskSettings['settings'], ) { const acceptReject = this.requesterAcceptRejects.get(taskId); if (acceptReject) { @@ -467,10 +474,12 @@ export class TaskBroker { this.pendingTaskRequests.splice(requestIndex, 1); try { - const acceptPromise = new Promise( + const acceptPromise = new Promise( (resolve, reject) => { this.requesterAcceptRejects.set(taskId, { - accept: resolve as (settings: RequesterMessage.ToN8n.TaskSettings['settings']) => void, + accept: resolve as ( + settings: RequesterMessage.ToBroker.TaskSettings['settings'], + ) => void, reject, }); diff --git a/packages/cli/src/runners/task-managers/__tests__/data-request-response-builder.test.ts b/packages/cli/src/runners/task-managers/__tests__/data-request-response-builder.test.ts index 8fc0198488b..ea1492f64ef 100644 --- a/packages/cli/src/runners/task-managers/__tests__/data-request-response-builder.test.ts +++ b/packages/cli/src/runners/task-managers/__tests__/data-request-response-builder.test.ts @@ -1,9 +1,9 @@ +import type { TaskData } from '@n8n/task-runner'; import { mock } from 'jest-mock-extended'; import type { IExecuteFunctions, IWorkflowExecuteAdditionalData } from 'n8n-workflow'; import { type INode, type INodeExecutionData, type Workflow } from 'n8n-workflow'; import { DataRequestResponseBuilder } from '../data-request-response-builder'; -import type { TaskData } from '../task-manager'; const triggerNode: INode = mock({ name: 'Trigger', diff --git a/packages/cli/src/runners/task-managers/data-request-response-builder.ts b/packages/cli/src/runners/task-managers/data-request-response-builder.ts index 6f49743aebc..bc498c33a7e 100644 --- a/packages/cli/src/runners/task-managers/data-request-response-builder.ts +++ b/packages/cli/src/runners/task-managers/data-request-response-builder.ts @@ -1,3 +1,9 @@ +import type { + DataRequestResponse, + BrokerMessage, + PartialAdditionalData, + TaskData, +} from '@n8n/task-runner'; import type { EnvProviderState, IExecuteData, @@ -11,9 +17,6 @@ import type { WorkflowParameters, } from 'n8n-workflow'; -import type { DataRequestResponse, PartialAdditionalData, TaskData } from './task-manager'; -import type { N8nMessage } from '../runner-types'; - /** * Builds the response to a data request coming from a Task Runner. Tries to minimize * the amount of data that is sent to the runner by only providing what is requested. @@ -23,7 +26,7 @@ export class DataRequestResponseBuilder { constructor( private readonly taskData: TaskData, - private readonly requestParams: N8nMessage.ToRequester.TaskDataRequest['requestParams'], + private readonly requestParams: BrokerMessage.ToRequester.TaskDataRequest['requestParams'], ) { this.requestedNodeNames = new Set(requestParams.dataOfNodes); diff --git a/packages/cli/src/runners/task-managers/local-task-manager.ts b/packages/cli/src/runners/task-managers/local-task-manager.ts index a8fca01b2c0..623b9c912e2 100644 --- a/packages/cli/src/runners/task-managers/local-task-manager.ts +++ b/packages/cli/src/runners/task-managers/local-task-manager.ts @@ -1,7 +1,7 @@ +import type { RequesterMessage } from '@n8n/task-runner'; import Container from 'typedi'; import { TaskManager } from './task-manager'; -import type { RequesterMessage } from '../runner-types'; import type { RequesterMessageCallback } from '../task-broker.service'; import { TaskBroker } from '../task-broker.service'; @@ -24,7 +24,7 @@ export class LocalTaskManager extends TaskManager { ); } - sendMessage(message: RequesterMessage.ToN8n.All) { + sendMessage(message: RequesterMessage.ToBroker.All) { void this.taskBroker.onRequesterMessage(this.id, message); } } diff --git a/packages/cli/src/runners/task-managers/task-manager.ts b/packages/cli/src/runners/task-managers/task-manager.ts index d1ef30665ae..617008a4505 100644 --- a/packages/cli/src/runners/task-managers/task-manager.ts +++ b/packages/cli/src/runners/task-managers/task-manager.ts @@ -1,30 +1,24 @@ -import { - type EnvProviderState, - type IExecuteFunctions, - type Workflow, - type IRunExecutionData, - type INodeExecutionData, - type ITaskDataConnections, - type INode, - type WorkflowParameters, - type INodeParameters, - type WorkflowExecuteMode, - type IExecuteData, - type IDataObject, - type IWorkflowExecuteAdditionalData, - type Result, - createResultOk, - createResultError, +import type { TaskResultData, RequesterMessage, BrokerMessage, TaskData } from '@n8n/task-runner'; +import { RPC_ALLOW_LIST } from '@n8n/task-runner'; +import type { + EnvProviderState, + IExecuteFunctions, + Workflow, + IRunExecutionData, + INodeExecutionData, + ITaskDataConnections, + INode, + INodeParameters, + WorkflowExecuteMode, + IExecuteData, + IDataObject, + IWorkflowExecuteAdditionalData, + Result, } from 'n8n-workflow'; +import { createResultOk, createResultError } from 'n8n-workflow'; import { nanoid } from 'nanoid'; import { DataRequestResponseBuilder } from './data-request-response-builder'; -import { - RPC_ALLOW_LIST, - type TaskResultData, - type N8nMessage, - type RequesterMessage, -} from '../runner-types'; export type RequestAccept = (jobId: string) => void; export type RequestReject = (reason: string) => void; @@ -32,62 +26,6 @@ export type RequestReject = (reason: string) => void; export type TaskAccept = (data: TaskResultData) => void; export type TaskReject = (error: unknown) => void; -export interface TaskData { - executeFunctions: IExecuteFunctions; - inputData: ITaskDataConnections; - node: INode; - - workflow: Workflow; - runExecutionData: IRunExecutionData; - runIndex: number; - itemIndex: number; - activeNodeName: string; - connectionInputData: INodeExecutionData[]; - siblingParameters: INodeParameters; - mode: WorkflowExecuteMode; - envProviderState: EnvProviderState; - executeData?: IExecuteData; - defaultReturnRunIndex: number; - selfData: IDataObject; - contextNodeName: string; - additionalData: IWorkflowExecuteAdditionalData; -} - -export interface PartialAdditionalData { - executionId?: string; - restartExecutionId?: string; - restApiUrl: string; - instanceBaseUrl: string; - formWaitingBaseUrl: string; - webhookBaseUrl: string; - webhookWaitingBaseUrl: string; - webhookTestBaseUrl: string; - currentNodeParameters?: INodeParameters; - executionTimeoutTimestamp?: number; - userId?: string; - variables: IDataObject; -} - -export interface DataRequestResponse { - workflow: Omit; - inputData: ITaskDataConnections; - node: INode; - - runExecutionData: IRunExecutionData; - runIndex: number; - itemIndex: number; - activeNodeName: string; - connectionInputData: INodeExecutionData[]; - siblingParameters: INodeParameters; - mode: WorkflowExecuteMode; - envProviderState: EnvProviderState; - executeData?: IExecuteData; - defaultReturnRunIndex: number; - selfData: IDataObject; - contextNodeName: string; - additionalData: PartialAdditionalData; -} - export interface TaskRequest { requestId: string; taskType: string; @@ -219,9 +157,9 @@ export class TaskManager { } } - sendMessage(_message: RequesterMessage.ToN8n.All) {} + sendMessage(_message: RequesterMessage.ToBroker.All) {} - onMessage(message: N8nMessage.ToRequester.All) { + onMessage(message: BrokerMessage.ToRequester.All) { switch (message.type) { case 'broker:taskready': this.taskReady(message.requestId, message.taskId); @@ -282,7 +220,7 @@ export class TaskManager { sendTaskData( taskId: string, requestId: string, - requestParams: N8nMessage.ToRequester.TaskDataRequest['requestParams'], + requestParams: BrokerMessage.ToRequester.TaskDataRequest['requestParams'], ) { const job = this.tasks.get(taskId); if (!job) { @@ -304,7 +242,7 @@ export class TaskManager { async handleRpc( taskId: string, callId: string, - name: N8nMessage.ToRequester.RPC['name'], + name: BrokerMessage.ToRequester.RPC['name'], params: unknown[], ) { const job = this.tasks.get(taskId); diff --git a/packages/cli/src/runners/task-runner-process.ts b/packages/cli/src/runners/task-runner-process.ts index 2eaa62621c0..9e731a99c5d 100644 --- a/packages/cli/src/runners/task-runner-process.ts +++ b/packages/cli/src/runners/task-runner-process.ts @@ -92,7 +92,7 @@ export class TaskRunnerProcess extends TypedEmitter { } startNode(grantToken: string, n8nUri: string) { - const startScript = require.resolve('@n8n/task-runner'); + const startScript = require.resolve('@n8n/task-runner/start'); return spawn('node', [startScript], { env: this.getProcessEnvVars(grantToken, n8nUri), diff --git a/packages/cli/test/integration/runners/task-runner-module.internal.test.ts b/packages/cli/test/integration/runners/task-runner-module.internal.test.ts index f53adde5e71..922f7fee4b6 100644 --- a/packages/cli/test/integration/runners/task-runner-module.internal.test.ts +++ b/packages/cli/test/integration/runners/task-runner-module.internal.test.ts @@ -8,6 +8,7 @@ import { TaskRunnerWsServer } from '../../../src/runners/runner-ws-server'; describe('TaskRunnerModule in internal_childprocess mode', () => { const runnerConfig = Container.get(TaskRunnersConfig); + runnerConfig.port = 0; // Random port runnerConfig.mode = 'internal_childprocess'; const module = Container.get(TaskRunnerModule); From fc49dc63ccf25ef10b21399a72a621bdd9e32ecd Mon Sep 17 00:00:00 2001 From: oleg Date: Tue, 5 Nov 2024 11:22:31 +0100 Subject: [PATCH 02/53] test: Skip flaky 39-projects e2e tests (no-changelog) (#11553) --- cypress/e2e/39-projects.cy.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cypress/e2e/39-projects.cy.ts b/cypress/e2e/39-projects.cy.ts index 138f67838a8..84d062fff5b 100644 --- a/cypress/e2e/39-projects.cy.ts +++ b/cypress/e2e/39-projects.cy.ts @@ -441,7 +441,9 @@ describe('Projects', { disableAutoLogin: true }, () => { .should('contain.text', 'Notion account personal project'); }); - it('should move resources between projects', () => { + // Skip flaky test + // eslint-disable-next-line n8n-local-rules/no-skipped-tests + it.skip('should move resources between projects', () => { cy.signinAsOwner(); cy.visit(workflowsPage.url); @@ -684,7 +686,9 @@ describe('Projects', { disableAutoLogin: true }, () => { .should('have.length', 1); }); - it('should allow to change inaccessible credential when the workflow was moved to a team project', () => { + // Skip flaky test + // eslint-disable-next-line n8n-local-rules/no-skipped-tests + it.skip('should allow to change inaccessible credential when the workflow was moved to a team project', () => { cy.signinAsOwner(); cy.visit(workflowsPage.url); From 8b398256a81594a52f20f8eb8adf8ff205209bc1 Mon Sep 17 00:00:00 2001 From: oleg Date: Tue, 5 Nov 2024 11:50:10 +0100 Subject: [PATCH 03/53] feat(Anthropic Chat Model Node): Add support for Haiku 3.5 (#11551) --- .../nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts b/packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts index 77df60da799..fa51ed3a45e 100644 --- a/packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts @@ -1,4 +1,7 @@ /* eslint-disable n8n-nodes-base/node-dirname-against-convention */ + +import { ChatAnthropic } from '@langchain/anthropic'; +import type { LLMResult } from '@langchain/core/outputs'; import { NodeConnectionType, type INodePropertyOptions, @@ -9,8 +12,6 @@ import { type SupplyData, } from 'n8n-workflow'; -import { ChatAnthropic } from '@langchain/anthropic'; -import type { LLMResult } from '@langchain/core/outputs'; import { getConnectionHintNoticeField } from '../../../utils/sharedFields'; import { N8nLlmTracing } from '../N8nLlmTracing'; @@ -36,6 +37,10 @@ const modelField: INodeProperties = { name: 'Claude 3 Sonnet(20240229)', value: 'claude-3-sonnet-20240229', }, + { + name: 'Claude 3.5 Haiku(20241022)', + value: 'claude-3-5-haiku-20241022', + }, { name: 'Claude 3 Haiku(20240307)', value: 'claude-3-haiku-20240307', From 1f25e8e096f737a05e4bac24caad78e6a5a79d77 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Tue, 5 Nov 2024 13:02:55 +0200 Subject: [PATCH 04/53] fix(editor): Add optional chaining to error handler (no-changelog) (#11500) --- packages/editor-ui/src/utils/apiUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/utils/apiUtils.ts b/packages/editor-ui/src/utils/apiUtils.ts index fef135769e0..8eb9f9548fd 100644 --- a/packages/editor-ui/src/utils/apiUtils.ts +++ b/packages/editor-ui/src/utils/apiUtils.ts @@ -113,8 +113,8 @@ export async function request(config: { }); } - const errorResponseData = error.response.data; - if (errorResponseData !== undefined && errorResponseData.message !== undefined) { + const errorResponseData = error.response?.data; + if (errorResponseData?.message !== undefined) { if (errorResponseData.name === 'NodeApiError') { errorResponseData.httpStatusCode = error.response.status; throw errorResponseData; From 38da319507df564c9cba8ce80e9b2e78674c8b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 5 Nov 2024 12:11:54 +0100 Subject: [PATCH 05/53] chore(editor): Delete some of the unused code (no-changelog) (#11554) --- .../components/AnnotationTagsContainer.ee.vue | 40 ------------ .../editor-ui/src/components/RBAC.test.ts | 57 ----------------- packages/editor-ui/src/components/RBAC.vue | 61 ------------------- .../render-types/CanvasNodeStickyNote.vue | 2 +- packages/editor-ui/src/plugins/components.ts | 2 - 5 files changed, 1 insertion(+), 161 deletions(-) delete mode 100644 packages/editor-ui/src/components/AnnotationTagsContainer.ee.vue delete mode 100644 packages/editor-ui/src/components/RBAC.test.ts delete mode 100644 packages/editor-ui/src/components/RBAC.vue diff --git a/packages/editor-ui/src/components/AnnotationTagsContainer.ee.vue b/packages/editor-ui/src/components/AnnotationTagsContainer.ee.vue deleted file mode 100644 index efc69968f53..00000000000 --- a/packages/editor-ui/src/components/AnnotationTagsContainer.ee.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - diff --git a/packages/editor-ui/src/components/RBAC.test.ts b/packages/editor-ui/src/components/RBAC.test.ts deleted file mode 100644 index 511786c3180..00000000000 --- a/packages/editor-ui/src/components/RBAC.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import RBAC from '@/components/RBAC.vue'; -import { createComponentRenderer } from '@/__tests__/render'; -import { useRBACStore } from '@/stores/rbac.store'; - -const renderComponent = createComponentRenderer(RBAC); - -vi.mock('vue-router', () => ({ - useRoute: vi.fn(() => ({ - path: '/workflows', - params: {}, - })), - RouterLink: vi.fn(), -})); - -vi.mock('@/stores/rbac.store', () => ({ - useRBACStore: vi.fn(), -})); - -describe('RBAC', () => { - it('renders default slot when hasScope is true', async () => { - vi.mocked(useRBACStore).mockImplementation( - () => - ({ - hasScope: () => true, - }) as unknown as ReturnType, - ); - - const wrapper = renderComponent({ - props: { scope: 'worfklow:list' }, - slots: { - default: 'Default Content', - fallback: 'Fallback Content', - }, - }); - - expect(wrapper.getByText('Default Content')).toBeInTheDocument(); - }); - - it('renders fallback slot when hasScope is false', async () => { - vi.mocked(useRBACStore).mockImplementation( - () => - ({ - hasScope: () => false, - }) as unknown as ReturnType, - ); - - const wrapper = renderComponent({ - props: { scope: 'worfklow:list' }, - slots: { - default: 'Default Content', - fallback: 'Fallback Content', - }, - }); - - expect(wrapper.getByText('Fallback Content')).toBeInTheDocument(); - }); -}); diff --git a/packages/editor-ui/src/components/RBAC.vue b/packages/editor-ui/src/components/RBAC.vue deleted file mode 100644 index 741f2771c7f..00000000000 --- a/packages/editor-ui/src/components/RBAC.vue +++ /dev/null @@ -1,61 +0,0 @@ - diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.vue b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.vue index 6a0d0ac8ec2..1fb597be690 100644 --- a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.vue +++ b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.vue @@ -4,7 +4,7 @@ import { useCanvasNode } from '@/composables/useCanvasNode'; import type { CanvasNodeStickyNoteRender } from '@/types'; import { ref, computed, useCssModule, onMounted, onBeforeUnmount } from 'vue'; import { NodeResizer } from '@vue-flow/node-resizer'; -import type { OnResize } from '@vue-flow/node-resizer/dist/types'; +import type { OnResize } from '@vue-flow/node-resizer'; import type { XYPosition } from '@vue-flow/core'; defineOptions({ diff --git a/packages/editor-ui/src/plugins/components.ts b/packages/editor-ui/src/plugins/components.ts index d87d7f0ac6f..38c600a8f42 100644 --- a/packages/editor-ui/src/plugins/components.ts +++ b/packages/editor-ui/src/plugins/components.ts @@ -6,7 +6,6 @@ import ElementPlus, { ElLoading, ElMessageBox } from 'element-plus'; import { N8nPlugin } from 'n8n-design-system'; import { useMessage } from '@/composables/useMessage'; import EnterpriseEdition from '@/components/EnterpriseEdition.ee.vue'; -import RBAC from '@/components/RBAC.vue'; import ParameterInputList from '@/components/ParameterInputList.vue'; export const GlobalComponentsPlugin: Plugin = { @@ -14,7 +13,6 @@ export const GlobalComponentsPlugin: Plugin = { const messageService = useMessage(); app.component('EnterpriseEdition', EnterpriseEdition); - app.component('RBAC', RBAC); app.component('ParameterInputList', ParameterInputList); app.use(ElementPlus); From e80f7e0a02a972379f73af6a44de11768081086e Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 5 Nov 2024 06:52:52 -0500 Subject: [PATCH 06/53] fix: Toast not aligned to the bottom when AI assistant disable (#11549) --- packages/editor-ui/src/composables/useToast.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/editor-ui/src/composables/useToast.ts b/packages/editor-ui/src/composables/useToast.ts index 7d07cdf2492..04bf24700c0 100644 --- a/packages/editor-ui/src/composables/useToast.ts +++ b/packages/editor-ui/src/composables/useToast.ts @@ -10,6 +10,7 @@ import { useExternalHooks } from './useExternalHooks'; import { VIEWS } from '@/constants'; import type { ApplicationError } from 'n8n-workflow'; import { useStyles } from './useStyles'; +import { useSettingsStore } from '@/stores/settings.store'; export interface NotificationErrorWithNodeAndDescription extends ApplicationError { node: { @@ -26,13 +27,14 @@ export function useToast() { const uiStore = useUIStore(); const externalHooks = useExternalHooks(); const i18n = useI18n(); + const settingsStore = useSettingsStore(); const { APP_Z_INDEXES } = useStyles(); const messageDefaults: Partial> = { dangerouslyUseHTMLString: false, position: 'bottom-right', zIndex: APP_Z_INDEXES.TOASTS, // above NDV and modal overlays - offset: 64, + offset: settingsStore.isAiAssistantEnabled ? 64 : 0, appendTo: '#app-grid', customClass: 'content-toast', }; From 981a852648880ffdc538d17c40f5b37b57f13901 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 5 Nov 2024 06:55:55 -0500 Subject: [PATCH 07/53] fix(editor): Do not show success message if there is an error saving credentials (no-changelog) (#11548) --- .../CredentialEdit/CredentialEdit.vue | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue index c6d5ee07ece..b1b6c653ad7 100644 --- a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue +++ b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue @@ -36,7 +36,7 @@ import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useSettingsStore } from '@/stores/settings.store'; import { useUIStore } from '@/stores/ui.store'; import { useWorkflowsStore } from '@/stores/workflows.store'; -import type { ProjectSharingData } from '@/types/projects.types'; +import type { Project, ProjectSharingData } from '@/types/projects.types'; import { assert } from '@/utils/assert'; import type { IMenuItem } from 'n8n-design-system'; import { createEventBus } from 'n8n-design-system/utils'; @@ -680,30 +680,7 @@ async function saveCredential(): Promise { const isNewCredential = props.mode === 'new' && !credentialId.value; if (isNewCredential) { - credential = await createCredential(credentialDetails, projectsStore.currentProjectId); - - let toastTitle = i18n.baseText('credentials.create.personal.toast.title'); - let toastText = ''; - - if (!credentialDetails.sharedWithProjects) { - toastText = i18n.baseText('credentials.create.personal.toast.text'); - } - - if (projectsStore.currentProject) { - toastTitle = i18n.baseText('credentials.create.project.toast.title', { - interpolate: { projectName: projectsStore.currentProject.name ?? '' }, - }); - - toastText = i18n.baseText('credentials.create.project.toast.text', { - interpolate: { projectName: projectsStore.currentProject.name ?? '' }, - }); - } - - toast.showMessage({ - title: toastTitle, - message: toastText, - type: 'success', - }); + credential = await createCredential(credentialDetails, projectsStore.currentProject); } else { if (settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.Sharing]) { credentialDetails.sharedWithProjects = credentialData.value @@ -770,15 +747,50 @@ async function saveCredential(): Promise { return credential; } +const createToastMessagingForNewCredentials = ( + credentialDetails: ICredentialsDecrypted, + project?: Project | null, +) => { + let toastTitle = i18n.baseText('credentials.create.personal.toast.title'); + let toastText = ''; + + if (!credentialDetails.sharedWithProjects) { + toastText = i18n.baseText('credentials.create.personal.toast.text'); + } + + if (projectsStore.currentProject) { + toastTitle = i18n.baseText('credentials.create.project.toast.title', { + interpolate: { projectName: project?.name ?? '' }, + }); + + toastText = i18n.baseText('credentials.create.project.toast.text', { + interpolate: { projectName: project?.name ?? '' }, + }); + } + + return { + title: toastTitle, + message: toastText, + }; +}; + async function createCredential( credentialDetails: ICredentialsDecrypted, - projectId?: string, + project?: Project | null, ): Promise { let credential; try { - credential = await credentialsStore.createNewCredential(credentialDetails, projectId); + credential = await credentialsStore.createNewCredential(credentialDetails, project?.id); hasUnsavedChanges.value = false; + + const { title, message } = createToastMessagingForNewCredentials(credentialDetails, project); + + toast.showMessage({ + title, + message, + type: 'success', + }); } catch (error) { toast.showError( error, From 63d454b776c092ff8c6c521a7e083774adb8f649 Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 5 Nov 2024 12:17:01 +0000 Subject: [PATCH 08/53] feat(Convert to File Node): Add delimiter convert to csv (#11556) --- .../actions/spreadsheet.operation.ts | 12 + .../ConvertToFile/test/toText.workflow.json | 416 ++++++++++++------ .../nodes-base/utils/__tests__/binary.test.ts | 92 ++++ packages/nodes-base/utils/binary.ts | 5 + 4 files changed, 396 insertions(+), 129 deletions(-) create mode 100644 packages/nodes-base/utils/__tests__/binary.test.ts diff --git a/packages/nodes-base/nodes/Files/ConvertToFile/actions/spreadsheet.operation.ts b/packages/nodes-base/nodes/Files/ConvertToFile/actions/spreadsheet.operation.ts index 0bc914454df..f0683b6a6f1 100644 --- a/packages/nodes-base/nodes/Files/ConvertToFile/actions/spreadsheet.operation.ts +++ b/packages/nodes-base/nodes/Files/ConvertToFile/actions/spreadsheet.operation.ts @@ -41,6 +41,18 @@ export const properties: INodeProperties[] = [ default: false, description: 'Whether to reduce the output file size', }, + { + displayName: 'Delimiter', + name: 'delimiter', + type: 'string', + displayOptions: { + show: { + '/operation': ['csv'], + }, + }, + default: ',', + description: 'The character to use to separate fields', + }, { displayName: 'File Name', name: 'fileName', diff --git a/packages/nodes-base/nodes/Files/ConvertToFile/test/toText.workflow.json b/packages/nodes-base/nodes/Files/ConvertToFile/test/toText.workflow.json index ea9b0fc6a95..478c112acf2 100644 --- a/packages/nodes-base/nodes/Files/ConvertToFile/test/toText.workflow.json +++ b/packages/nodes-base/nodes/Files/ConvertToFile/test/toText.workflow.json @@ -1,15 +1,68 @@ { - "name": "My workflow 2", + "name": "Test ConvertToFile", "nodes": [ { "parameters": {}, - "id": "59f5ae0f-52f7-4bc8-b325-29d2b0d810f8", + "id": "f2557b99-e65c-4136-9bc5-7cb328a62d30", "name": "When clicking ‘Test workflow’", "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ - 460, - 500 + 300, + 1040 + ] + }, + { + "parameters": { + "operation": "toBinary", + "sourceProperty": "base64", + "options": {} + }, + "id": "71711ee7-9df5-456a-b1d0-def85b8d6669", + "name": "Convert to File2", + "type": "n8n-nodes-base.convertToFile", + "typeVersion": 1.1, + "position": [ + 880, + 540 + ] + }, + { + "parameters": { + "jsCode": "return {\n \"id\": \"23423532\",\n \"name\": \"Jay Gatsby\",\n \"email\": \"gatsby@west-egg.com\",\n \"notes\": \"Keeps asking about a green light??\",\n \"country\": \"US\",\n \"created\": \"1925-04-10\",\n \"base64\": \"VGhpcyBpcyBzb21lIHRleHQgZW5jb2RlZCBhcyBiYXNlNjQ=\"\n }" + }, + "id": "ff53ab4c-43dd-4c35-b066-59d59e4a8209", + "name": "Code", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 520, + 1040 + ] + }, + { + "parameters": { + "operation": "text", + "options": {} + }, + "id": "6322369c-fef5-4172-bbd3-8738cbb67e05", + "name": "Extract From File", + "type": "n8n-nodes-base.extractFromFile", + "typeVersion": 1, + "position": [ + 1100, + 540 + ] + }, + { + "parameters": {}, + "id": "b5aed50b-65d3-4356-b02d-cbeab7fb3d6e", + "name": "No Operation, do nothing", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 1320, + 540 ] }, { @@ -18,13 +71,38 @@ "sourceProperty": "notes", "options": {} }, - "id": "add99ca3-7bd3-4561-a654-fac4b8ded285", - "name": "Convert to File", + "id": "65c4c4ac-da33-4ba1-b337-51ee319a8652", + "name": "Convert to Text File", "type": "n8n-nodes-base.convertToFile", "typeVersion": 1, "position": [ - 940, - 400 + 880, + 740 + ] + }, + { + "parameters": { + "operation": "text", + "options": {} + }, + "id": "b2f49de3-5d0d-4eff-8156-89e5a2a0edae", + "name": "Extract From Text File", + "type": "n8n-nodes-base.extractFromFile", + "typeVersion": 1, + "position": [ + 1100, + 740 + ] + }, + { + "parameters": {}, + "id": "86d5e979-5ff0-4312-8b4f-7ff83f1eebd6", + "name": "Text File Result", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 1320, + 740 ] }, { @@ -34,41 +112,13 @@ "format": true } }, - "id": "89498c96-f1a0-49ec-890d-79f12c5554e6", - "name": "Convert to File1", + "id": "a938ea30-3acb-4618-a80a-6e759ba7d8db", + "name": "Convert to JSON (with Formatting)", "type": "n8n-nodes-base.convertToFile", "typeVersion": 1.1, "position": [ - 940, - 580 - ] - }, - { - "parameters": { - "operation": "toBinary", - "sourceProperty": "base64", - "options": {} - }, - "id": "ae06c883-f2af-4d25-bc64-4f0ecad53c85", - "name": "Convert to File2", - "type": "n8n-nodes-base.convertToFile", - "typeVersion": 1.1, - "position": [ - 940, - 200 - ] - }, - { - "parameters": { - "jsCode": "return {\n \"id\": \"23423532\",\n \"name\": \"Jay Gatsby\",\n \"email\": \"gatsby@west-egg.com\",\n \"notes\": \"Keeps asking about a green light??\",\n \"country\": \"US\",\n \"created\": \"1925-04-10\",\n \"base64\": \"VGhpcyBpcyBzb21lIHRleHQgZW5jb2RlZCBhcyBiYXNlNjQ=\"\n }" - }, - "id": "b14b18b0-6570-4376-85cf-f3cc74835e58", - "name": "Code", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 680, - 500 + 880, + 920 ] }, { @@ -76,13 +126,13 @@ "operation": "text", "options": {} }, - "id": "76373e3f-e103-465a-8b15-dd643915c532", - "name": "Extract From File", + "id": "fa35a5ed-4746-48c5-b260-314c517cdd45", + "name": "Extract From JSON (1)", "type": "n8n-nodes-base.extractFromFile", "typeVersion": 1, "position": [ - 1160, - 200 + 1100, + 920 ] }, { @@ -90,27 +140,24 @@ "operation": "text", "options": {} }, - "id": "d8ba3980-873d-47d7-ad88-f5ff6c66774c", - "name": "Extract From File1", + "id": "4a3c5c68-6621-4463-8623-83a6572ae760", + "name": "Extract From JSON (2)", "type": "n8n-nodes-base.extractFromFile", "typeVersion": 1, "position": [ - 1160, - 400 + 1100, + 1120 ] }, { - "parameters": { - "operation": "text", - "options": {} - }, - "id": "34838f1e-aee5-4b17-a9ec-bd9e09789045", - "name": "Extract From File2", - "type": "n8n-nodes-base.extractFromFile", + "parameters": {}, + "id": "dbd03dcb-435c-4af7-ada8-2492c69f1cd6", + "name": "JSON Result (with Formatting)", + "type": "n8n-nodes-base.noOp", "typeVersion": 1, "position": [ - 1160, - 580 + 1320, + 920 ] }, { @@ -118,71 +165,102 @@ "operation": "toJson", "options": {} }, - "id": "a6617075-83f4-4157-9d07-7e5df0cbd9b6", - "name": "Convert to File3", + "id": "c461944d-3141-4a1d-abe1-a74e1f71615f", + "name": "Convert to JSON", "type": "n8n-nodes-base.convertToFile", "typeVersion": 1.1, "position": [ - 960, - 780 + 880, + 1120 ] }, { "parameters": { - "operation": "text", "options": {} }, - "id": "b2deb5a4-0f7a-4a1f-858f-17235db0b94e", - "name": "Extract From File3", + "id": "c9ca03b3-0f01-49f5-ab9d-ed4497829a09", + "name": "Convert to CSV", + "type": "n8n-nodes-base.convertToFile", + "typeVersion": 1.1, + "position": [ + 880, + 1320 + ] + }, + { + "parameters": { + "options": {} + }, + "id": "1ad12799-7916-4780-aca9-9a966f9e5820", + "name": "Extract From CSV", "type": "n8n-nodes-base.extractFromFile", "typeVersion": 1, "position": [ - 1160, - 780 + 1100, + 1320 + ] + }, + { + "parameters": { + "options": { + "delimiter": "|" + } + }, + "id": "58caeb17-7434-4808-b8c4-4ca443baecff", + "name": "Convert to CSV (custom delimiter)", + "type": "n8n-nodes-base.convertToFile", + "typeVersion": 1.1, + "position": [ + 880, + 1520 ] }, { "parameters": {}, - "id": "11022c53-136b-44a0-af32-faac16e2fa89", - "name": "No Operation, do nothing", + "id": "b113b6d9-7928-4de1-bf7f-e2984d124edf", + "name": "CSV Result", "type": "n8n-nodes-base.noOp", "typeVersion": 1, "position": [ - 1380, - 200 + 1320, + 1320 ] }, { "parameters": {}, - "id": "f5ec42e5-8088-4a93-91ea-3a1cb4997eee", - "name": "No Operation, do nothing1", + "id": "12554f8d-592a-4500-80f7-42518840f718", + "name": "JSON Result", "type": "n8n-nodes-base.noOp", "typeVersion": 1, "position": [ - 1380, - 400 + 1320, + 1120 ] }, { "parameters": {}, - "id": "d7106de2-455f-428f-bdfa-fe701136bdfa", - "name": "No Operation, do nothing2", + "id": "8a6ab018-9f38-4a5b-9483-769bf38f0b7c", + "name": "CSV Result (custom delimiter)", "type": "n8n-nodes-base.noOp", "typeVersion": 1, "position": [ - 1380, - 580 + 1320, + 1520 ] }, { - "parameters": {}, - "id": "14dbc74c-fc0b-4339-88ea-76b3e9534de0", - "name": "No Operation, do nothing3", - "type": "n8n-nodes-base.noOp", + "parameters": { + "options": { + "delimiter": "|" + } + }, + "id": "e8a4114f-5264-4255-982e-4690c950fb86", + "name": "Extract From Custom Delimiter", + "type": "n8n-nodes-base.extractFromFile", "typeVersion": 1, "position": [ - 1380, - 780 + 1100, + 1520 ] } ], @@ -194,26 +272,52 @@ } } ], - "No Operation, do nothing1": [ + "Text File Result": [ { "json": { "data": "Keeps asking about a green light??" } } ], - "No Operation, do nothing2": [ + "JSON Result (with Formatting)": [ { "json": { "data": "[\n {\n \"id\": \"23423532\",\n \"name\": \"Jay Gatsby\",\n \"email\": \"gatsby@west-egg.com\",\n \"notes\": \"Keeps asking about a green light??\",\n \"country\": \"US\",\n \"created\": \"1925-04-10\",\n \"base64\": \"VGhpcyBpcyBzb21lIHRleHQgZW5jb2RlZCBhcyBiYXNlNjQ=\"\n }\n]" } } ], - "No Operation, do nothing3": [ + "CSV Result": [ + { + "json": { + "id": "23423532", + "name": "Jay Gatsby", + "email": "gatsby@west-egg.com", + "notes": "Keeps asking about a green light??", + "country": "US", + "created": "1925-04-10", + "base64": "VGhpcyBpcyBzb21lIHRleHQgZW5jb2RlZCBhcyBiYXNlNjQ=" + } + } + ], + "JSON Result": [ { "json": { "data": "[{\"id\":\"23423532\",\"name\":\"Jay Gatsby\",\"email\":\"gatsby@west-egg.com\",\"notes\":\"Keeps asking about a green light??\",\"country\":\"US\",\"created\":\"1925-04-10\",\"base64\":\"VGhpcyBpcyBzb21lIHRleHQgZW5jb2RlZCBhcyBiYXNlNjQ=\"}]" } } + ], + "CSV Result (custom delimiter)": [ + { + "json": { + "id": "23423532", + "name": "Jay Gatsby", + "email": "gatsby@west-egg.com", + "notes": "Keeps asking about a green light??", + "country": "US", + "created": "1925-04-10", + "base64": "VGhpcyBpcyBzb21lIHRleHQgZW5jb2RlZCBhcyBiYXNlNjQ=" + } + } ] }, "connections": { @@ -237,17 +341,27 @@ "index": 0 }, { - "node": "Convert to File", + "node": "Convert to Text File", "type": "main", "index": 0 }, { - "node": "Convert to File1", + "node": "Convert to JSON (with Formatting)", "type": "main", "index": 0 }, { - "node": "Convert to File3", + "node": "Convert to JSON", + "type": "main", + "index": 0 + }, + { + "node": "Convert to CSV", + "type": "main", + "index": 0 + }, + { + "node": "Convert to CSV (custom delimiter)", "type": "main", "index": 0 } @@ -265,39 +379,6 @@ ] ] }, - "Convert to File": { - "main": [ - [ - { - "node": "Extract From File1", - "type": "main", - "index": 0 - } - ] - ] - }, - "Convert to File1": { - "main": [ - [ - { - "node": "Extract From File2", - "type": "main", - "index": 0 - } - ] - ] - }, - "Convert to File3": { - "main": [ - [ - { - "node": "Extract From File3", - "type": "main", - "index": 0 - } - ] - ] - }, "Extract From File": { "main": [ [ @@ -309,33 +390,110 @@ ] ] }, - "Extract From File3": { + "Convert to Text File": { "main": [ [ { - "node": "No Operation, do nothing3", + "node": "Extract From Text File", "type": "main", "index": 0 } ] ] }, - "Extract From File2": { + "Extract From Text File": { "main": [ [ { - "node": "No Operation, do nothing2", + "node": "Text File Result", "type": "main", "index": 0 } ] ] }, - "Extract From File1": { + "Convert to JSON (with Formatting)": { "main": [ [ { - "node": "No Operation, do nothing1", + "node": "Extract From JSON (1)", + "type": "main", + "index": 0 + } + ] + ] + }, + "Extract From JSON (1)": { + "main": [ + [ + { + "node": "JSON Result (with Formatting)", + "type": "main", + "index": 0 + } + ] + ] + }, + "Extract From JSON (2)": { + "main": [ + [ + { + "node": "JSON Result", + "type": "main", + "index": 0 + } + ] + ] + }, + "Convert to JSON": { + "main": [ + [ + { + "node": "Extract From JSON (2)", + "type": "main", + "index": 0 + } + ] + ] + }, + "Convert to CSV": { + "main": [ + [ + { + "node": "Extract From CSV", + "type": "main", + "index": 0 + } + ] + ] + }, + "Extract From CSV": { + "main": [ + [ + { + "node": "CSV Result", + "type": "main", + "index": 0 + } + ] + ] + }, + "Convert to CSV (custom delimiter)": { + "main": [ + [ + { + "node": "Extract From Custom Delimiter", + "type": "main", + "index": 0 + } + ] + ] + }, + "Extract From Custom Delimiter": { + "main": [ + [ + { + "node": "CSV Result (custom delimiter)", "type": "main", "index": 0 } diff --git a/packages/nodes-base/utils/__tests__/binary.test.ts b/packages/nodes-base/utils/__tests__/binary.test.ts new file mode 100644 index 00000000000..b8e9e6ddbac --- /dev/null +++ b/packages/nodes-base/utils/__tests__/binary.test.ts @@ -0,0 +1,92 @@ +import { mock } from 'jest-mock-extended'; +import type { IBinaryData, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { type WorkSheet, utils as xlsxUtils, write as xlsxWrite } from 'xlsx'; + +import { convertJsonToSpreadsheetBinary } from '@utils/binary'; + +jest.mock('xlsx', () => ({ + utils: { + json_to_sheet: jest.fn(), + }, + write: jest.fn(), +})); + +describe('convertJsonToSpreadsheetBinary', () => { + const helpers = mock(); + const executeFunctions = mock({ helpers }); + const items = [ + { json: { key1: 'value1', key2: 'value2' } }, + { json: { key1: 'value3', key2: 'value4' } }, + ] as INodeExecutionData[]; + const mockSheet = mock(); + const workBook = { + SheetNames: ['Sheet'], + Sheets: { + Sheet: mockSheet, + }, + }; + const mockBuffer = mock(); + const mockBinaryData = mock({ id: 'binaryId' }); + + beforeEach(() => { + jest.clearAllMocks(); + (xlsxUtils.json_to_sheet as jest.Mock).mockReturnValue(mockSheet); + (xlsxWrite as jest.Mock).mockReturnValue(mockBuffer); + helpers.prepareBinaryData.mockResolvedValue(mockBinaryData); + }); + + describe('for fileFormat xlsx', () => { + it('should convert from JSON', async () => { + const result = await convertJsonToSpreadsheetBinary.call(executeFunctions, items, 'xlsx', {}); + + expect(result).toEqual(mockBinaryData); + expect(xlsxUtils.json_to_sheet).toHaveBeenCalledWith( + items.map((item) => item.json), + undefined, + ); + expect(xlsxWrite).toHaveBeenCalledWith(workBook, { + bookType: 'xlsx', + bookSST: false, + type: 'buffer', + }); + expect(helpers.prepareBinaryData).toHaveBeenCalledWith(mockBuffer, 'spreadsheet.xlsx'); + }); + }); + + describe('for fileFormat csv', () => { + it('should convert from JSON', async () => { + const result = await convertJsonToSpreadsheetBinary.call(executeFunctions, items, 'csv', {}); + + expect(result).toEqual(mockBinaryData); + expect(xlsxUtils.json_to_sheet).toHaveBeenCalledWith( + items.map((item) => item.json), + undefined, + ); + expect(xlsxWrite).toHaveBeenCalledWith(workBook, { + bookType: 'csv', + bookSST: false, + type: 'buffer', + }); + expect(helpers.prepareBinaryData).toHaveBeenCalledWith(mockBuffer, 'spreadsheet.csv'); + }); + + it('should handle custom delimiter', async () => { + const result = await convertJsonToSpreadsheetBinary.call(executeFunctions, items, 'csv', { + delimiter: ';', + }); + + expect(result).toEqual(mockBinaryData); + expect(xlsxUtils.json_to_sheet).toHaveBeenCalledWith( + items.map((item) => item.json), + undefined, + ); + expect(xlsxWrite).toHaveBeenCalledWith(workBook, { + bookType: 'csv', + bookSST: false, + type: 'buffer', + FS: ';', + }); + expect(helpers.prepareBinaryData).toHaveBeenCalledWith(mockBuffer, 'spreadsheet.csv'); + }); + }); +}); diff --git a/packages/nodes-base/utils/binary.ts b/packages/nodes-base/utils/binary.ts index 1a7b16f24d5..c552f6064fa 100644 --- a/packages/nodes-base/utils/binary.ts +++ b/packages/nodes-base/utils/binary.ts @@ -17,6 +17,7 @@ export type JsonToSpreadsheetBinaryOptions = { compression?: boolean; fileName?: string; sheetName?: string; + delimiter?: string; }; export type JsonToBinaryOptions = { @@ -59,6 +60,10 @@ export async function convertJsonToSpreadsheetBinary( type: 'buffer', }; + if (fileFormat === 'csv' && options.delimiter?.length) { + writingOptions.FS = options.delimiter ?? ','; + } + if (['xlsx', 'ods'].includes(fileFormat) && options.compression) { writingOptions.compression = true; } From 5ca781bf3a5276bbb602929adaa292b460aea938 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Tue, 5 Nov 2024 14:20:02 +0200 Subject: [PATCH 09/53] refactor(editor): Rename design-system unit test files and snapshots (no-changelog) (#11539) --- .git-blame-ignore-revs | 1 + .../AskAssistantAvatar.spec.ts => AskAssistantAvatar.test.ts} | 2 +- .../AskAssistantAvatar.test.ts.snap} | 0 .../AskAssistantButton.spec.ts => AskAssistantButton.test.ts} | 2 +- .../AskAssistantButton.test.ts.snap} | 0 .../AskAssistantChat.spec.ts => AskAssistantChat.test.ts} | 2 +- .../AskAssistantChat.test.ts.snap} | 0 .../AssistantIcon.spec.ts => AssistantIcon.test.ts} | 2 +- .../AssistantIcon.test.ts.snap} | 0 ...dingMessage.spec.ts => AskAssistantLoadingMessage.test.ts} | 2 +- .../AskAssistantLoadingMessage.test.ts.snap} | 0 .../AssistantText.spec.ts => AssistantText.test.ts} | 2 +- .../AssistantText.test.ts.snap} | 0 .../BetaTag/{__tests__/BetaTag.spec.ts => BetaTag.test.ts} | 2 +- .../BetaTag.test.ts.snap} | 0 .../BlinkingCursor.spec.ts => BlinkingCursor.test.ts} | 2 +- .../BlinkingCursor.test.ts.snap} | 0 .../CodeDiff/{__tests__/CodeDiff.spec.ts => CodeDiff.test.ts} | 2 +- .../CodeDiff.test.ts.snap} | 0 ...tionalRouterLink.spec.ts => ConditionalRouterLink.test.ts} | 2 +- .../ConditionalRouterLink.test.ts.snap} | 0 .../{__tests__/ActionBox.spec.ts => ActionBox.test.ts} | 2 +- .../ActionBox.test.ts.snap} | 0 .../ActionDropdown.spec.ts => ActionDropdown.test.ts} | 2 +- .../ActionDropdown.test.ts.snap} | 0 .../N8nAlert/{__tests__/Alert.spec.ts => Alert.test.ts} | 4 ++-- .../src/components/N8nAvatar/{__tests__ => }/Avatar.test.ts | 2 +- .../N8nBadge/{__tests__/Badge.spec.ts => Badge.test.ts} | 2 +- .../Badge.spec.ts.snap => __snapshots__/Badge.test.ts.snap} | 0 .../N8nBlockUi/{__tests__/BlockUi.spec.ts => BlockUi.test.ts} | 2 +- .../N8nButton/{__tests__/Button.spec.ts => Button.test.ts} | 2 +- .../Button.spec.ts.snap => __snapshots__/Button.test.ts.snap} | 0 .../N8nCallout/{__tests__/Callout.spec.ts => Callout.test.ts} | 2 +- .../Callout.test.ts.snap} | 0 .../N8nCard/{__tests__/Card.spec.ts => Card.test.ts} | 2 +- .../Card.spec.ts.snap => __snapshots__/Card.test.ts.snap} | 0 .../{__tests__/Checkbox.spec.ts => Checkbox.test.ts} | 2 +- .../Checkbox.test.ts.snap} | 0 .../{__tests__/CircleLoader.spec.ts => CircleLoader.test.ts} | 2 +- .../CircleLoader.test.ts.snap} | 0 .../{__tests__/ColorPicker.spec.ts => ColorPicker.test.ts} | 2 +- .../ColorPicker.test.ts.snap} | 0 .../{__tests__/Datatable.spec.ts => Datatable.test.ts} | 4 ++-- .../Datatable.test.ts.snap} | 0 .../src/components/N8nFormBox/{__tests__ => }/FormBox.test.ts | 4 ++-- .../{__tests__ => }/__snapshots__/FormBox.test.ts.snap | 0 .../N8nInfoTip/{__tests__/InfoTip.spec.ts => InfoTip.test.ts} | 2 +- .../InfoTip.test.ts.snap} | 0 .../N8nInput/{__tests__/Input.spec.ts => Input.test.ts} | 2 +- .../Input.spec.ts.snap => __snapshots__/Input.test.ts.snap} | 0 .../{__tests__/InputLabel.spec.ts => InputLabel.test.ts} | 2 +- .../InputLabel.test.ts.snap} | 0 .../{__tests__/Markdown.spec.ts => Markdown.test.ts} | 2 +- .../NavigationDropdown.spec.ts => NavigationDropdown.test.ts} | 2 +- .../N8nNotice/{__tests__/Notice.spec.ts => Notice.test.ts} | 2 +- .../Notice.spec.ts.snap => __snapshots__/Notice.test.ts.snap} | 0 .../RecycleScroller.spec.ts => RecycleScroller.test.ts} | 2 +- .../RecycleScroller.test.ts.snap} | 0 .../N8nRoute/{__tests__/Route.spec.ts => Route.test.ts} | 2 +- .../Route.spec.ts.snap => __snapshots__/Route.test.ts.snap} | 0 .../N8nSelect/{__tests__/Select.spec.ts => Select.test.ts} | 4 ++-- .../Select.spec.ts.snap => __snapshots__/Select.test.ts.snap} | 0 .../N8nTooltip/{__tests__/Tooltip.spec.ts => Tooltip.test.ts} | 2 +- .../N8nTree/{__tests__/Tree.spec.ts => Tree.test.ts} | 2 +- .../Tree.spec.ts.snap => __snapshots__/Tree.test.ts.snap} | 0 .../{__tests__/UserStack.spec.ts => UserStack.test.ts} | 2 +- .../{__tests__/ColorCircles.spec.ts => ColorCircles.test.ts} | 2 +- .../src/styleguide/{__tests__/Sizes.spec.ts => Sizes.test.ts} | 2 +- .../ColorCircles.test.ts.snap} | 0 .../Sizes.spec.ts.snap => __snapshots__/Sizes.test.ts.snap} | 0 .../utils/{__tests__/event-bus.spec.ts => event-bus.test.ts} | 2 +- .../src/utils/{labelUtil.spec.ts => labelUtil.test.ts} | 0 .../utils/{__tests__/markdown.spec.ts => markdown.test.ts} | 2 +- .../{__tests__/valueByPath.spec.ts => valueByPath.test.ts} | 0 ...tallModal.spec.ts => CommunityPackageInstallModal.test.ts} | 0 .../src/components/{Feedback.spec.ts => Feedback.test.ts} | 0 .../components/MainHeader/{TabBar.spec.ts => TabBar.test.ts} | 0 .../{WorkflowDetails.spec.ts => WorkflowDetails.test.ts} | 0 .../{NDVSubConnections.spec.ts => NDVSubConnections.test.ts} | 0 .../components/{VariablesRow.spec.ts => VariablesRow.test.ts} | 0 .../{WorkflowSettings.spec.ts => WorkflowSettings.test.ts} | 0 .../components/banners/{V1Banner.spec.ts => V1Banner.test.ts} | 0 .../{V1Banner.spec.ts.snap => V1Banner.test.ts.snap} | 0 .../src/components/canvas/{Canvas.spec.ts => Canvas.test.ts} | 0 .../canvas/{WorkflowCanvas.spec.ts => WorkflowCanvas.test.ts} | 0 .../{CanvasChatButton.spec.ts => CanvasChatButton.test.ts} | 0 ...aButton.spec.ts => CanvasClearExecutionDataButton.test.ts} | 0 ...vasControlButtons.spec.ts => CanvasControlButtons.test.ts} | 0 ...WorkflowButton.spec.ts => CanvasRunWorkflowButton.test.ts} | 0 ...utton.spec.ts => CanvasStopCurrentExecutionButton.test.ts} | 0 ...tton.spec.ts => CanvasStopWaitingForWebhookButton.test.ts} | 0 ...sChatButton.spec.ts.snap => CanvasChatButton.test.ts.snap} | 0 ...ec.ts.snap => CanvasClearExecutionDataButton.test.ts.snap} | 0 ...Buttons.spec.ts.snap => CanvasControlButtons.test.ts.snap} | 0 ....spec.ts.snap => CanvasExecuteWorkflowButton.test.ts.snap} | 0 ...tton.spec.ts.snap => CanvasRunWorkflowButton.test.ts.snap} | 0 ....ts.snap => CanvasStopCurrentExecutionButton.test.ts.snap} | 0 ...ts.snap => CanvasStopWaitingForWebhookButton.test.ts.snap} | 0 ...vasConnectionLine.spec.ts => CanvasConnectionLine.test.ts} | 0 .../elements/edges/{CanvasEdge.spec.ts => CanvasEdge.test.ts} | 0 .../{CanvasEdgeToolbar.spec.ts => CanvasEdgeToolbar.test.ts} | 0 ...vasHandleRenderer.spec.ts => CanvasHandleRenderer.test.ts} | 0 ...sHandleMainInput.spec.ts => CanvasHandleMainInput.test.ts} | 0 ...andleMainOutput.spec.ts => CanvasHandleMainOutput.test.ts} | 0 ...eNonMainInput.spec.ts => CanvasHandleNonMainInput.test.ts} | 0 ...onMainOutput.spec.ts => CanvasHandleNonMainOutput.test.ts} | 0 ...anvasHandleDiamond.spec.ts => CanvasHandleDiamond.test.ts} | 0 .../{CanvasHandleDot.spec.ts => CanvasHandleDot.test.ts} | 0 .../{CanvasHandlePlus.spec.ts => CanvasHandlePlus.test.ts} | 0 ...sHandleRectangle.spec.ts => CanvasHandleRectangle.test.ts} | 0 ...eDiamond.spec.ts.snap => CanvasHandleDiamond.test.ts.snap} | 0 ...vasHandleDot.spec.ts.snap => CanvasHandleDot.test.ts.snap} | 0 ...sHandlePlus.spec.ts.snap => CanvasHandlePlus.test.ts.snap} | 0 ...tangle.spec.ts.snap => CanvasHandleRectangle.test.ts.snap} | 0 .../elements/nodes/{CanvasNode.spec.ts => CanvasNode.test.ts} | 0 ...{CanvasNodeRenderer.spec.ts => CanvasNodeRenderer.test.ts} | 0 .../{CanvasNodeToolbar.spec.ts => CanvasNodeToolbar.test.ts} | 0 .../{CanvasNodeDefault.spec.ts => CanvasNodeDefault.test.ts} | 0 ...vasNodeStickyNote.spec.ts => CanvasNodeStickyNote.test.ts} | 0 ...odeDefault.spec.ts.snap => CanvasNodeDefault.test.ts.snap} | 0 ...ckyNote.spec.ts.snap => CanvasNodeStickyNote.test.ts.snap} | 0 ...hrough.spec.ts => CanvasNodeDisabledStrikeThrough.test.ts} | 0 ...sNodeStatusIcons.spec.ts => CanvasNodeStatusIcons.test.ts} | 0 ...Selector.spec.ts => CanvasNodeStickyColorSelector.test.ts} | 0 ...BugReporting.spec.ts.snap => useBugReporting.test.ts.snap} | 0 ...erations.spec.ts.snap => useCanvasOperations.test.ts.snap} | 0 .../{useDebugInfo.spec.ts.snap => useDebugInfo.test.ts.snap} | 0 .../{useBugReporting.spec.ts => useBugReporting.test.ts} | 0 .../{useCanvasMapping.spec.ts => useCanvasMapping.test.ts} | 0 .../{useCanvasNode.spec.ts => useCanvasNode.test.ts} | 0 ...seCanvasOperations.spec.ts => useCanvasOperations.test.ts} | 0 .../{useDebugInfo.spec.ts => useDebugInfo.test.ts} | 0 ...ecutionDebugging.spec.ts => useExecutionDebugging.test.ts} | 0 .../composables/{useNodeBase.spec.ts => useNodeBase.test.ts} | 0 ...{useNodeConnections.spec.ts => useNodeConnections.test.ts} | 0 .../{usePushConnection.spec.ts => usePushConnection.test.ts} | 0 .../{useRunWorkflow.spec.ts => useRunWorkflow.test.ts} | 0 .../src/composables/{useStyles.spec.ts => useStyles.test.ts} | 0 ...{useWorkflowHelpers.spec.ts => useWorkflowHelpers.test.ts} | 0 .../{workflowHelpers.spec.ts => workflowHelpers.test.ts} | 0 .../src/{permissions.spec.ts => permissions.test.ts} | 0 .../editor-ui/src/plugins/{sentry.spec.ts => sentry.test.ts} | 0 .../src/stores/{credentials.spec.ts => credentials.test.ts} | 0 .../src/stores/{environments.spec.ts => environments.test.ts} | 0 .../stores/{npsStore.store.spec.ts => npsStore.store.test.ts} | 0 .../{workflows.store.spec.ts => workflows.store.test.ts} | 0 .../src/utils/{apiUtils.spec.ts => apiUtils.test.ts} | 0 .../utils/{canvasUtilsV2.spec.ts => canvasUtilsV2.test.ts} | 0 .../utils/{executionUtils.spec.ts => executionUtils.test.ts} | 0 .../src/utils/{htmlUtils.spec.ts => htmlUtils.test.ts} | 0 .../utils/{nodeViewUtils.spec.ts => nodeViewUtils.test.ts} | 0 .../views/{VariablesView.spec.ts => VariablesView.test.ts} | 0 152 files changed, 45 insertions(+), 44 deletions(-) rename packages/design-system/src/components/AskAssistantAvatar/{__tests__/AskAssistantAvatar.spec.ts => AskAssistantAvatar.test.ts} (89%) rename packages/design-system/src/components/AskAssistantAvatar/{__tests__/__snapshots__/AskAssistantAvatar.spec.ts.snap => __snapshots__/AskAssistantAvatar.test.ts.snap} (100%) rename packages/design-system/src/components/AskAssistantButton/{__tests__/AskAssistantButton.spec.ts => AskAssistantButton.test.ts} (88%) rename packages/design-system/src/components/AskAssistantButton/{__tests__/__snapshots__/AskAssistantButton.spec.ts.snap => __snapshots__/AskAssistantButton.test.ts.snap} (100%) rename packages/design-system/src/components/AskAssistantChat/{__tests__/AskAssistantChat.spec.ts => AskAssistantChat.test.ts} (99%) rename packages/design-system/src/components/AskAssistantChat/{__tests__/__snapshots__/AskAssistantChat.spec.ts.snap => __snapshots__/AskAssistantChat.test.ts.snap} (100%) rename packages/design-system/src/components/AskAssistantIcon/{__tests__/AssistantIcon.spec.ts => AssistantIcon.test.ts} (95%) rename packages/design-system/src/components/AskAssistantIcon/{__tests__/__snapshots__/AssistantIcon.spec.ts.snap => __snapshots__/AssistantIcon.test.ts.snap} (100%) rename packages/design-system/src/components/AskAssistantLoadingMessage/{__tests__/AskAssistantLoadingMessage.spec.ts => AskAssistantLoadingMessage.test.ts} (81%) rename packages/design-system/src/components/AskAssistantLoadingMessage/{__tests__/__snapshots__/AskAssistantLoadingMessage.spec.ts.snap => __snapshots__/AskAssistantLoadingMessage.test.ts.snap} (100%) rename packages/design-system/src/components/AskAssistantText/{__tests__/AssistantText.spec.ts => AssistantText.test.ts} (94%) rename packages/design-system/src/components/AskAssistantText/{__tests__/__snapshots__/AssistantText.spec.ts.snap => __snapshots__/AssistantText.test.ts.snap} (100%) rename packages/design-system/src/components/BetaTag/{__tests__/BetaTag.spec.ts => BetaTag.test.ts} (84%) rename packages/design-system/src/components/BetaTag/{__tests__/__snapshots__/BetaTag.spec.ts.snap => __snapshots__/BetaTag.test.ts.snap} (100%) rename packages/design-system/src/components/BlinkingCursor/{__tests__/BlinkingCursor.spec.ts => BlinkingCursor.test.ts} (81%) rename packages/design-system/src/components/BlinkingCursor/{__tests__/__snapshots__/BlinkingCursor.spec.ts.snap => __snapshots__/BlinkingCursor.test.ts.snap} (100%) rename packages/design-system/src/components/CodeDiff/{__tests__/CodeDiff.spec.ts => CodeDiff.test.ts} (98%) rename packages/design-system/src/components/CodeDiff/{__tests__/__snapshots__/CodeDiff.spec.ts.snap => __snapshots__/CodeDiff.test.ts.snap} (100%) rename packages/design-system/src/components/ConditionalRouterLink/{__tests__/ConditionalRouterLink.spec.ts => ConditionalRouterLink.test.ts} (95%) rename packages/design-system/src/components/ConditionalRouterLink/{__tests__/__snapshots__/ConditionalRouterLink.spec.ts.snap => __snapshots__/ConditionalRouterLink.test.ts.snap} (100%) rename packages/design-system/src/components/N8nActionBox/{__tests__/ActionBox.spec.ts => ActionBox.test.ts} (92%) rename packages/design-system/src/components/N8nActionBox/{__tests__/__snapshots__/ActionBox.spec.ts.snap => __snapshots__/ActionBox.test.ts.snap} (100%) rename packages/design-system/src/components/N8nActionDropdown/{__tests__/ActionDropdown.spec.ts => ActionDropdown.test.ts} (95%) rename packages/design-system/src/components/N8nActionDropdown/{__tests__/__snapshots__/ActionDropdown.spec.ts.snap => __snapshots__/ActionDropdown.test.ts.snap} (100%) rename packages/design-system/src/components/N8nAlert/{__tests__/Alert.spec.ts => Alert.test.ts} (93%) rename packages/design-system/src/components/N8nAvatar/{__tests__ => }/Avatar.test.ts (94%) rename packages/design-system/src/components/N8nBadge/{__tests__/Badge.spec.ts => Badge.test.ts} (96%) rename packages/design-system/src/components/N8nBadge/{__tests__/__snapshots__/Badge.spec.ts.snap => __snapshots__/Badge.test.ts.snap} (100%) rename packages/design-system/src/components/N8nBlockUi/{__tests__/BlockUi.spec.ts => BlockUi.test.ts} (91%) rename packages/design-system/src/components/N8nButton/{__tests__/Button.spec.ts => Button.test.ts} (97%) rename packages/design-system/src/components/N8nButton/{__tests__/__snapshots__/Button.spec.ts.snap => __snapshots__/Button.test.ts.snap} (100%) rename packages/design-system/src/components/N8nCallout/{__tests__/Callout.spec.ts => Callout.test.ts} (98%) rename packages/design-system/src/components/N8nCallout/{__tests__/__snapshots__/Callout.spec.ts.snap => __snapshots__/Callout.test.ts.snap} (100%) rename packages/design-system/src/components/N8nCard/{__tests__/Card.spec.ts => Card.test.ts} (94%) rename packages/design-system/src/components/N8nCard/{__tests__/__snapshots__/Card.spec.ts.snap => __snapshots__/Card.test.ts.snap} (100%) rename packages/design-system/src/components/N8nCheckbox/{__tests__/Checkbox.spec.ts => Checkbox.test.ts} (95%) rename packages/design-system/src/components/N8nCheckbox/{__tests__/__snapshots__/Checkbox.spec.ts.snap => __snapshots__/Checkbox.test.ts.snap} (100%) rename packages/design-system/src/components/N8nCircleLoader/{__tests__/CircleLoader.spec.ts => CircleLoader.test.ts} (85%) rename packages/design-system/src/components/N8nCircleLoader/{__tests__/__snapshots__/CircleLoader.spec.ts.snap => __snapshots__/CircleLoader.test.ts.snap} (100%) rename packages/design-system/src/components/N8nColorPicker/{__tests__/ColorPicker.spec.ts => ColorPicker.test.ts} (91%) rename packages/design-system/src/components/N8nColorPicker/{__tests__/__snapshots__/ColorPicker.spec.ts.snap => __snapshots__/ColorPicker.test.ts.snap} (100%) rename packages/design-system/src/components/N8nDatatable/{__tests__/Datatable.spec.ts => Datatable.test.ts} (96%) rename packages/design-system/src/components/N8nDatatable/{__tests__/__snapshots__/Datatable.spec.ts.snap => __snapshots__/Datatable.test.ts.snap} (100%) rename packages/design-system/src/components/N8nFormBox/{__tests__ => }/FormBox.test.ts (91%) rename packages/design-system/src/components/N8nFormBox/{__tests__ => }/__snapshots__/FormBox.test.ts.snap (100%) rename packages/design-system/src/components/N8nInfoTip/{__tests__/InfoTip.spec.ts => InfoTip.test.ts} (93%) rename packages/design-system/src/components/N8nInfoTip/{__tests__/__snapshots__/InfoTip.spec.ts.snap => __snapshots__/InfoTip.test.ts.snap} (100%) rename packages/design-system/src/components/N8nInput/{__tests__/Input.spec.ts => Input.test.ts} (94%) rename packages/design-system/src/components/N8nInput/{__tests__/__snapshots__/Input.spec.ts.snap => __snapshots__/Input.test.ts.snap} (100%) rename packages/design-system/src/components/N8nInputLabel/{__tests__/InputLabel.spec.ts => InputLabel.test.ts} (93%) rename packages/design-system/src/components/N8nInputLabel/{__tests__/__snapshots__/InputLabel.spec.ts.snap => __snapshots__/InputLabel.test.ts.snap} (100%) rename packages/design-system/src/components/N8nMarkdown/{__tests__/Markdown.spec.ts => Markdown.test.ts} (98%) rename packages/design-system/src/components/N8nNavigationDropdown/{__tests__/NavigationDropdown.spec.ts => NavigationDropdown.test.ts} (98%) rename packages/design-system/src/components/N8nNotice/{__tests__/Notice.spec.ts => Notice.test.ts} (97%) rename packages/design-system/src/components/N8nNotice/{__tests__/__snapshots__/Notice.spec.ts.snap => __snapshots__/Notice.test.ts.snap} (100%) rename packages/design-system/src/components/N8nRecycleScroller/{__tests__/RecycleScroller.spec.ts => RecycleScroller.test.ts} (91%) rename packages/design-system/src/components/N8nRecycleScroller/{__tests__/__snapshots__/RecycleScroller.spec.ts.snap => __snapshots__/RecycleScroller.test.ts.snap} (100%) rename packages/design-system/src/components/N8nRoute/{__tests__/Route.spec.ts => Route.test.ts} (94%) rename packages/design-system/src/components/N8nRoute/{__tests__/__snapshots__/Route.spec.ts.snap => __snapshots__/Route.test.ts.snap} (100%) rename packages/design-system/src/components/N8nSelect/{__tests__/Select.spec.ts => Select.test.ts} (95%) rename packages/design-system/src/components/N8nSelect/{__tests__/__snapshots__/Select.spec.ts.snap => __snapshots__/Select.test.ts.snap} (100%) rename packages/design-system/src/components/N8nTooltip/{__tests__/Tooltip.spec.ts => Tooltip.test.ts} (95%) rename packages/design-system/src/components/N8nTree/{__tests__/Tree.spec.ts => Tree.test.ts} (97%) rename packages/design-system/src/components/N8nTree/{__tests__/__snapshots__/Tree.spec.ts.snap => __snapshots__/Tree.test.ts.snap} (100%) rename packages/design-system/src/components/N8nUserStack/{__tests__/UserStack.spec.ts => UserStack.test.ts} (98%) rename packages/design-system/src/styleguide/{__tests__/ColorCircles.spec.ts => ColorCircles.test.ts} (94%) rename packages/design-system/src/styleguide/{__tests__/Sizes.spec.ts => Sizes.test.ts} (94%) rename packages/design-system/src/styleguide/{__tests__/__snapshots__/ColorCircles.spec.ts.snap => __snapshots__/ColorCircles.test.ts.snap} (100%) rename packages/design-system/src/styleguide/{__tests__/__snapshots__/Sizes.spec.ts.snap => __snapshots__/Sizes.test.ts.snap} (100%) rename packages/design-system/src/utils/{__tests__/event-bus.spec.ts => event-bus.test.ts} (97%) rename packages/design-system/src/utils/{labelUtil.spec.ts => labelUtil.test.ts} (100%) rename packages/design-system/src/utils/{__tests__/markdown.spec.ts => markdown.test.ts} (95%) rename packages/design-system/src/utils/{__tests__/valueByPath.spec.ts => valueByPath.test.ts} (100%) rename packages/editor-ui/src/components/{CommunityPackageInstallModal.spec.ts => CommunityPackageInstallModal.test.ts} (100%) rename packages/editor-ui/src/components/{Feedback.spec.ts => Feedback.test.ts} (100%) rename packages/editor-ui/src/components/MainHeader/{TabBar.spec.ts => TabBar.test.ts} (100%) rename packages/editor-ui/src/components/MainHeader/{WorkflowDetails.spec.ts => WorkflowDetails.test.ts} (100%) rename packages/editor-ui/src/components/{NDVSubConnections.spec.ts => NDVSubConnections.test.ts} (100%) rename packages/editor-ui/src/components/{VariablesRow.spec.ts => VariablesRow.test.ts} (100%) rename packages/editor-ui/src/components/{WorkflowSettings.spec.ts => WorkflowSettings.test.ts} (100%) rename packages/editor-ui/src/components/banners/{V1Banner.spec.ts => V1Banner.test.ts} (100%) rename packages/editor-ui/src/components/banners/__snapshots__/{V1Banner.spec.ts.snap => V1Banner.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/{Canvas.spec.ts => Canvas.test.ts} (100%) rename packages/editor-ui/src/components/canvas/{WorkflowCanvas.spec.ts => WorkflowCanvas.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/{CanvasChatButton.spec.ts => CanvasChatButton.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/{CanvasClearExecutionDataButton.spec.ts => CanvasClearExecutionDataButton.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/{CanvasControlButtons.spec.ts => CanvasControlButtons.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/{CanvasRunWorkflowButton.spec.ts => CanvasRunWorkflowButton.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/{CanvasStopCurrentExecutionButton.spec.ts => CanvasStopCurrentExecutionButton.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/{CanvasStopWaitingForWebhookButton.spec.ts => CanvasStopWaitingForWebhookButton.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/{CanvasChatButton.spec.ts.snap => CanvasChatButton.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/{CanvasClearExecutionDataButton.spec.ts.snap => CanvasClearExecutionDataButton.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/{CanvasControlButtons.spec.ts.snap => CanvasControlButtons.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/{CanvasExecuteWorkflowButton.spec.ts.snap => CanvasExecuteWorkflowButton.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/{CanvasRunWorkflowButton.spec.ts.snap => CanvasRunWorkflowButton.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/{CanvasStopCurrentExecutionButton.spec.ts.snap => CanvasStopCurrentExecutionButton.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/{CanvasStopWaitingForWebhookButton.spec.ts.snap => CanvasStopWaitingForWebhookButton.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/edges/{CanvasConnectionLine.spec.ts => CanvasConnectionLine.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/edges/{CanvasEdge.spec.ts => CanvasEdge.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/edges/{CanvasEdgeToolbar.spec.ts => CanvasEdgeToolbar.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/{CanvasHandleRenderer.spec.ts => CanvasHandleRenderer.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/{CanvasHandleMainInput.spec.ts => CanvasHandleMainInput.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/{CanvasHandleMainOutput.spec.ts => CanvasHandleMainOutput.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/{CanvasHandleNonMainInput.spec.ts => CanvasHandleNonMainInput.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/{CanvasHandleNonMainOutput.spec.ts => CanvasHandleNonMainOutput.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/{CanvasHandleDiamond.spec.ts => CanvasHandleDiamond.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/{CanvasHandleDot.spec.ts => CanvasHandleDot.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/{CanvasHandlePlus.spec.ts => CanvasHandlePlus.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/{CanvasHandleRectangle.spec.ts => CanvasHandleRectangle.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/{CanvasHandleDiamond.spec.ts.snap => CanvasHandleDiamond.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/{CanvasHandleDot.spec.ts.snap => CanvasHandleDot.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/{CanvasHandlePlus.spec.ts.snap => CanvasHandlePlus.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/{CanvasHandleRectangle.spec.ts.snap => CanvasHandleRectangle.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/{CanvasNode.spec.ts => CanvasNode.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/{CanvasNodeRenderer.spec.ts => CanvasNodeRenderer.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/{CanvasNodeToolbar.spec.ts => CanvasNodeToolbar.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/render-types/{CanvasNodeDefault.spec.ts => CanvasNodeDefault.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/render-types/{CanvasNodeStickyNote.spec.ts => CanvasNodeStickyNote.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/{CanvasNodeDefault.spec.ts.snap => CanvasNodeDefault.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/{CanvasNodeStickyNote.spec.ts.snap => CanvasNodeStickyNote.test.ts.snap} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/{CanvasNodeDisabledStrikeThrough.spec.ts => CanvasNodeDisabledStrikeThrough.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/{CanvasNodeStatusIcons.spec.ts => CanvasNodeStatusIcons.test.ts} (100%) rename packages/editor-ui/src/components/canvas/elements/nodes/toolbar/{CanvasNodeStickyColorSelector.spec.ts => CanvasNodeStickyColorSelector.test.ts} (100%) rename packages/editor-ui/src/composables/__snapshots__/{useBugReporting.spec.ts.snap => useBugReporting.test.ts.snap} (100%) rename packages/editor-ui/src/composables/__snapshots__/{useCanvasOperations.spec.ts.snap => useCanvasOperations.test.ts.snap} (100%) rename packages/editor-ui/src/composables/__snapshots__/{useDebugInfo.spec.ts.snap => useDebugInfo.test.ts.snap} (100%) rename packages/editor-ui/src/composables/{useBugReporting.spec.ts => useBugReporting.test.ts} (100%) rename packages/editor-ui/src/composables/{useCanvasMapping.spec.ts => useCanvasMapping.test.ts} (100%) rename packages/editor-ui/src/composables/{useCanvasNode.spec.ts => useCanvasNode.test.ts} (100%) rename packages/editor-ui/src/composables/{useCanvasOperations.spec.ts => useCanvasOperations.test.ts} (100%) rename packages/editor-ui/src/composables/{useDebugInfo.spec.ts => useDebugInfo.test.ts} (100%) rename packages/editor-ui/src/composables/{useExecutionDebugging.spec.ts => useExecutionDebugging.test.ts} (100%) rename packages/editor-ui/src/composables/{useNodeBase.spec.ts => useNodeBase.test.ts} (100%) rename packages/editor-ui/src/composables/{useNodeConnections.spec.ts => useNodeConnections.test.ts} (100%) rename packages/editor-ui/src/composables/{usePushConnection.spec.ts => usePushConnection.test.ts} (100%) rename packages/editor-ui/src/composables/{useRunWorkflow.spec.ts => useRunWorkflow.test.ts} (100%) rename packages/editor-ui/src/composables/{useStyles.spec.ts => useStyles.test.ts} (100%) rename packages/editor-ui/src/composables/{useWorkflowHelpers.spec.ts => useWorkflowHelpers.test.ts} (100%) rename packages/editor-ui/src/mixins/{workflowHelpers.spec.ts => workflowHelpers.test.ts} (100%) rename packages/editor-ui/src/{permissions.spec.ts => permissions.test.ts} (100%) rename packages/editor-ui/src/plugins/{sentry.spec.ts => sentry.test.ts} (100%) rename packages/editor-ui/src/stores/{credentials.spec.ts => credentials.test.ts} (100%) rename packages/editor-ui/src/stores/{environments.spec.ts => environments.test.ts} (100%) rename packages/editor-ui/src/stores/{npsStore.store.spec.ts => npsStore.store.test.ts} (100%) rename packages/editor-ui/src/stores/{workflows.store.spec.ts => workflows.store.test.ts} (100%) rename packages/editor-ui/src/utils/{apiUtils.spec.ts => apiUtils.test.ts} (100%) rename packages/editor-ui/src/utils/{canvasUtilsV2.spec.ts => canvasUtilsV2.test.ts} (100%) rename packages/editor-ui/src/utils/{executionUtils.spec.ts => executionUtils.test.ts} (100%) rename packages/editor-ui/src/utils/{htmlUtils.spec.ts => htmlUtils.test.ts} (100%) rename packages/editor-ui/src/utils/{nodeViewUtils.spec.ts => nodeViewUtils.test.ts} (100%) rename packages/editor-ui/src/views/{VariablesView.spec.ts => VariablesView.test.ts} (100%) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 330174e6dd3..68bd149419b 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -15,3 +15,4 @@ # refactor: Move test files alongside tested files (#11504) 7e58fc4fec468aca0b45d5bfe6150e1af632acbc +f32b13c6ed078be042a735bc8621f27e00dc3116 diff --git a/packages/design-system/src/components/AskAssistantAvatar/__tests__/AskAssistantAvatar.spec.ts b/packages/design-system/src/components/AskAssistantAvatar/AskAssistantAvatar.test.ts similarity index 89% rename from packages/design-system/src/components/AskAssistantAvatar/__tests__/AskAssistantAvatar.spec.ts rename to packages/design-system/src/components/AskAssistantAvatar/AskAssistantAvatar.test.ts index f77e9d1e370..c6392f23054 100644 --- a/packages/design-system/src/components/AskAssistantAvatar/__tests__/AskAssistantAvatar.spec.ts +++ b/packages/design-system/src/components/AskAssistantAvatar/AskAssistantAvatar.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import AssistantAvatar from '../AssistantAvatar.vue'; +import AssistantAvatar from './AssistantAvatar.vue'; describe('AskAssistantAvatar', () => { it('renders small avatar correctly', () => { diff --git a/packages/design-system/src/components/AskAssistantAvatar/__tests__/__snapshots__/AskAssistantAvatar.spec.ts.snap b/packages/design-system/src/components/AskAssistantAvatar/__snapshots__/AskAssistantAvatar.test.ts.snap similarity index 100% rename from packages/design-system/src/components/AskAssistantAvatar/__tests__/__snapshots__/AskAssistantAvatar.spec.ts.snap rename to packages/design-system/src/components/AskAssistantAvatar/__snapshots__/AskAssistantAvatar.test.ts.snap diff --git a/packages/design-system/src/components/AskAssistantButton/__tests__/AskAssistantButton.spec.ts b/packages/design-system/src/components/AskAssistantButton/AskAssistantButton.test.ts similarity index 88% rename from packages/design-system/src/components/AskAssistantButton/__tests__/AskAssistantButton.spec.ts rename to packages/design-system/src/components/AskAssistantButton/AskAssistantButton.test.ts index 3edf52e2794..a0e669352c0 100644 --- a/packages/design-system/src/components/AskAssistantButton/__tests__/AskAssistantButton.spec.ts +++ b/packages/design-system/src/components/AskAssistantButton/AskAssistantButton.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import AskAssistantButton from '../AskAssistantButton.vue'; +import AskAssistantButton from './AskAssistantButton.vue'; describe('AskAssistantButton', () => { it('renders default button correctly', () => { diff --git a/packages/design-system/src/components/AskAssistantButton/__tests__/__snapshots__/AskAssistantButton.spec.ts.snap b/packages/design-system/src/components/AskAssistantButton/__snapshots__/AskAssistantButton.test.ts.snap similarity index 100% rename from packages/design-system/src/components/AskAssistantButton/__tests__/__snapshots__/AskAssistantButton.spec.ts.snap rename to packages/design-system/src/components/AskAssistantButton/__snapshots__/AskAssistantButton.test.ts.snap diff --git a/packages/design-system/src/components/AskAssistantChat/__tests__/AskAssistantChat.spec.ts b/packages/design-system/src/components/AskAssistantChat/AskAssistantChat.test.ts similarity index 99% rename from packages/design-system/src/components/AskAssistantChat/__tests__/AskAssistantChat.spec.ts rename to packages/design-system/src/components/AskAssistantChat/AskAssistantChat.test.ts index 003755561eb..9874965e829 100644 --- a/packages/design-system/src/components/AskAssistantChat/__tests__/AskAssistantChat.spec.ts +++ b/packages/design-system/src/components/AskAssistantChat/AskAssistantChat.test.ts @@ -2,7 +2,7 @@ import { render } from '@testing-library/vue'; import { n8nHtml } from 'n8n-design-system/directives'; -import AskAssistantChat from '../AskAssistantChat.vue'; +import AskAssistantChat from './AskAssistantChat.vue'; const stubs = ['n8n-avatar', 'n8n-button', 'n8n-icon', 'n8n-icon-button']; diff --git a/packages/design-system/src/components/AskAssistantChat/__tests__/__snapshots__/AskAssistantChat.spec.ts.snap b/packages/design-system/src/components/AskAssistantChat/__snapshots__/AskAssistantChat.test.ts.snap similarity index 100% rename from packages/design-system/src/components/AskAssistantChat/__tests__/__snapshots__/AskAssistantChat.spec.ts.snap rename to packages/design-system/src/components/AskAssistantChat/__snapshots__/AskAssistantChat.test.ts.snap diff --git a/packages/design-system/src/components/AskAssistantIcon/__tests__/AssistantIcon.spec.ts b/packages/design-system/src/components/AskAssistantIcon/AssistantIcon.test.ts similarity index 95% rename from packages/design-system/src/components/AskAssistantIcon/__tests__/AssistantIcon.spec.ts rename to packages/design-system/src/components/AskAssistantIcon/AssistantIcon.test.ts index 0ad1b13d19f..bc88be2a839 100644 --- a/packages/design-system/src/components/AskAssistantIcon/__tests__/AssistantIcon.spec.ts +++ b/packages/design-system/src/components/AskAssistantIcon/AssistantIcon.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import AssistantIcon from '../AssistantIcon.vue'; +import AssistantIcon from './AssistantIcon.vue'; describe('AssistantIcon', () => { it('renders default icon correctly', () => { diff --git a/packages/design-system/src/components/AskAssistantIcon/__tests__/__snapshots__/AssistantIcon.spec.ts.snap b/packages/design-system/src/components/AskAssistantIcon/__snapshots__/AssistantIcon.test.ts.snap similarity index 100% rename from packages/design-system/src/components/AskAssistantIcon/__tests__/__snapshots__/AssistantIcon.spec.ts.snap rename to packages/design-system/src/components/AskAssistantIcon/__snapshots__/AssistantIcon.test.ts.snap diff --git a/packages/design-system/src/components/AskAssistantLoadingMessage/__tests__/AskAssistantLoadingMessage.spec.ts b/packages/design-system/src/components/AskAssistantLoadingMessage/AskAssistantLoadingMessage.test.ts similarity index 81% rename from packages/design-system/src/components/AskAssistantLoadingMessage/__tests__/AskAssistantLoadingMessage.spec.ts rename to packages/design-system/src/components/AskAssistantLoadingMessage/AskAssistantLoadingMessage.test.ts index 218414391c1..4284dcd3130 100644 --- a/packages/design-system/src/components/AskAssistantLoadingMessage/__tests__/AskAssistantLoadingMessage.spec.ts +++ b/packages/design-system/src/components/AskAssistantLoadingMessage/AskAssistantLoadingMessage.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import AssistantLoadingMessage from '../AssistantLoadingMessage.vue'; +import AssistantLoadingMessage from './AssistantLoadingMessage.vue'; describe('AssistantLoadingMessage', () => { it('renders loading message correctly', () => { diff --git a/packages/design-system/src/components/AskAssistantLoadingMessage/__tests__/__snapshots__/AskAssistantLoadingMessage.spec.ts.snap b/packages/design-system/src/components/AskAssistantLoadingMessage/__snapshots__/AskAssistantLoadingMessage.test.ts.snap similarity index 100% rename from packages/design-system/src/components/AskAssistantLoadingMessage/__tests__/__snapshots__/AskAssistantLoadingMessage.spec.ts.snap rename to packages/design-system/src/components/AskAssistantLoadingMessage/__snapshots__/AskAssistantLoadingMessage.test.ts.snap diff --git a/packages/design-system/src/components/AskAssistantText/__tests__/AssistantText.spec.ts b/packages/design-system/src/components/AskAssistantText/AssistantText.test.ts similarity index 94% rename from packages/design-system/src/components/AskAssistantText/__tests__/AssistantText.spec.ts rename to packages/design-system/src/components/AskAssistantText/AssistantText.test.ts index 30aa136674c..1bbfeab8cb9 100644 --- a/packages/design-system/src/components/AskAssistantText/__tests__/AssistantText.spec.ts +++ b/packages/design-system/src/components/AskAssistantText/AssistantText.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import AssistantText from '../AssistantText.vue'; +import AssistantText from './AssistantText.vue'; describe('AssistantText', () => { it('renders default text correctly', () => { diff --git a/packages/design-system/src/components/AskAssistantText/__tests__/__snapshots__/AssistantText.spec.ts.snap b/packages/design-system/src/components/AskAssistantText/__snapshots__/AssistantText.test.ts.snap similarity index 100% rename from packages/design-system/src/components/AskAssistantText/__tests__/__snapshots__/AssistantText.spec.ts.snap rename to packages/design-system/src/components/AskAssistantText/__snapshots__/AssistantText.test.ts.snap diff --git a/packages/design-system/src/components/BetaTag/__tests__/BetaTag.spec.ts b/packages/design-system/src/components/BetaTag/BetaTag.test.ts similarity index 84% rename from packages/design-system/src/components/BetaTag/__tests__/BetaTag.spec.ts rename to packages/design-system/src/components/BetaTag/BetaTag.test.ts index 7f92713ce8e..b04d64329d3 100644 --- a/packages/design-system/src/components/BetaTag/__tests__/BetaTag.spec.ts +++ b/packages/design-system/src/components/BetaTag/BetaTag.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import BetaTag from '../BetaTag.vue'; +import BetaTag from './BetaTag.vue'; describe('BetaTag', () => { it('renders beta tag correctly', () => { diff --git a/packages/design-system/src/components/BetaTag/__tests__/__snapshots__/BetaTag.spec.ts.snap b/packages/design-system/src/components/BetaTag/__snapshots__/BetaTag.test.ts.snap similarity index 100% rename from packages/design-system/src/components/BetaTag/__tests__/__snapshots__/BetaTag.spec.ts.snap rename to packages/design-system/src/components/BetaTag/__snapshots__/BetaTag.test.ts.snap diff --git a/packages/design-system/src/components/BlinkingCursor/__tests__/BlinkingCursor.spec.ts b/packages/design-system/src/components/BlinkingCursor/BlinkingCursor.test.ts similarity index 81% rename from packages/design-system/src/components/BlinkingCursor/__tests__/BlinkingCursor.spec.ts rename to packages/design-system/src/components/BlinkingCursor/BlinkingCursor.test.ts index 65c4193e8d9..13bac6c61de 100644 --- a/packages/design-system/src/components/BlinkingCursor/__tests__/BlinkingCursor.spec.ts +++ b/packages/design-system/src/components/BlinkingCursor/BlinkingCursor.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import BlinkingCursor from '../BlinkingCursor.vue'; +import BlinkingCursor from './BlinkingCursor.vue'; describe('BlinkingCursor', () => { it('renders blinking cursor correctly', () => { diff --git a/packages/design-system/src/components/BlinkingCursor/__tests__/__snapshots__/BlinkingCursor.spec.ts.snap b/packages/design-system/src/components/BlinkingCursor/__snapshots__/BlinkingCursor.test.ts.snap similarity index 100% rename from packages/design-system/src/components/BlinkingCursor/__tests__/__snapshots__/BlinkingCursor.spec.ts.snap rename to packages/design-system/src/components/BlinkingCursor/__snapshots__/BlinkingCursor.test.ts.snap diff --git a/packages/design-system/src/components/CodeDiff/__tests__/CodeDiff.spec.ts b/packages/design-system/src/components/CodeDiff/CodeDiff.test.ts similarity index 98% rename from packages/design-system/src/components/CodeDiff/__tests__/CodeDiff.spec.ts rename to packages/design-system/src/components/CodeDiff/CodeDiff.test.ts index d23d49d6d15..e9a48ce7376 100644 --- a/packages/design-system/src/components/CodeDiff/__tests__/CodeDiff.spec.ts +++ b/packages/design-system/src/components/CodeDiff/CodeDiff.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import CodeDiff from '../CodeDiff.vue'; +import CodeDiff from './CodeDiff.vue'; const stubs = ['n8n-button', 'n8n-icon']; diff --git a/packages/design-system/src/components/CodeDiff/__tests__/__snapshots__/CodeDiff.spec.ts.snap b/packages/design-system/src/components/CodeDiff/__snapshots__/CodeDiff.test.ts.snap similarity index 100% rename from packages/design-system/src/components/CodeDiff/__tests__/__snapshots__/CodeDiff.spec.ts.snap rename to packages/design-system/src/components/CodeDiff/__snapshots__/CodeDiff.test.ts.snap diff --git a/packages/design-system/src/components/ConditionalRouterLink/__tests__/ConditionalRouterLink.spec.ts b/packages/design-system/src/components/ConditionalRouterLink/ConditionalRouterLink.test.ts similarity index 95% rename from packages/design-system/src/components/ConditionalRouterLink/__tests__/ConditionalRouterLink.spec.ts rename to packages/design-system/src/components/ConditionalRouterLink/ConditionalRouterLink.test.ts index 250950d6d71..2689228c6b8 100644 --- a/packages/design-system/src/components/ConditionalRouterLink/__tests__/ConditionalRouterLink.spec.ts +++ b/packages/design-system/src/components/ConditionalRouterLink/ConditionalRouterLink.test.ts @@ -2,7 +2,7 @@ import { render } from '@testing-library/vue'; import { beforeAll, describe } from 'vitest'; import { createRouter, createWebHistory } from 'vue-router'; -import CondtionalRouterLink from '../CondtionalRouterLink.vue'; +import CondtionalRouterLink from './CondtionalRouterLink.vue'; const slots = { default: 'Button', diff --git a/packages/design-system/src/components/ConditionalRouterLink/__tests__/__snapshots__/ConditionalRouterLink.spec.ts.snap b/packages/design-system/src/components/ConditionalRouterLink/__snapshots__/ConditionalRouterLink.test.ts.snap similarity index 100% rename from packages/design-system/src/components/ConditionalRouterLink/__tests__/__snapshots__/ConditionalRouterLink.spec.ts.snap rename to packages/design-system/src/components/ConditionalRouterLink/__snapshots__/ConditionalRouterLink.test.ts.snap diff --git a/packages/design-system/src/components/N8nActionBox/__tests__/ActionBox.spec.ts b/packages/design-system/src/components/N8nActionBox/ActionBox.test.ts similarity index 92% rename from packages/design-system/src/components/N8nActionBox/__tests__/ActionBox.spec.ts rename to packages/design-system/src/components/N8nActionBox/ActionBox.test.ts index 8bbbee267fd..f336b5167d2 100644 --- a/packages/design-system/src/components/N8nActionBox/__tests__/ActionBox.spec.ts +++ b/packages/design-system/src/components/N8nActionBox/ActionBox.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8NActionBox from '../ActionBox.vue'; +import N8NActionBox from './ActionBox.vue'; describe('N8NActionBox', () => { it('should render correctly', () => { diff --git a/packages/design-system/src/components/N8nActionBox/__tests__/__snapshots__/ActionBox.spec.ts.snap b/packages/design-system/src/components/N8nActionBox/__snapshots__/ActionBox.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nActionBox/__tests__/__snapshots__/ActionBox.spec.ts.snap rename to packages/design-system/src/components/N8nActionBox/__snapshots__/ActionBox.test.ts.snap diff --git a/packages/design-system/src/components/N8nActionDropdown/__tests__/ActionDropdown.spec.ts b/packages/design-system/src/components/N8nActionDropdown/ActionDropdown.test.ts similarity index 95% rename from packages/design-system/src/components/N8nActionDropdown/__tests__/ActionDropdown.spec.ts rename to packages/design-system/src/components/N8nActionDropdown/ActionDropdown.test.ts index 40c605f225e..be6a810d14d 100644 --- a/packages/design-system/src/components/N8nActionDropdown/__tests__/ActionDropdown.spec.ts +++ b/packages/design-system/src/components/N8nActionDropdown/ActionDropdown.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nActionDropdown from '../ActionDropdown.vue'; +import N8nActionDropdown from './ActionDropdown.vue'; describe('components', () => { describe('N8nActionDropdown', () => { diff --git a/packages/design-system/src/components/N8nActionDropdown/__tests__/__snapshots__/ActionDropdown.spec.ts.snap b/packages/design-system/src/components/N8nActionDropdown/__snapshots__/ActionDropdown.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nActionDropdown/__tests__/__snapshots__/ActionDropdown.spec.ts.snap rename to packages/design-system/src/components/N8nActionDropdown/__snapshots__/ActionDropdown.test.ts.snap diff --git a/packages/design-system/src/components/N8nAlert/__tests__/Alert.spec.ts b/packages/design-system/src/components/N8nAlert/Alert.test.ts similarity index 93% rename from packages/design-system/src/components/N8nAlert/__tests__/Alert.spec.ts rename to packages/design-system/src/components/N8nAlert/Alert.test.ts index fe1d5d3aeb4..9324e1054aa 100644 --- a/packages/design-system/src/components/N8nAlert/__tests__/Alert.spec.ts +++ b/packages/design-system/src/components/N8nAlert/Alert.test.ts @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/vue'; -import N8nIcon from '../../N8nIcon'; -import N8nAlert from '../Alert.vue'; +import N8nAlert from './Alert.vue'; +import N8nIcon from '../N8nIcon'; describe('components', () => { describe('N8nAlert', () => { diff --git a/packages/design-system/src/components/N8nAvatar/__tests__/Avatar.test.ts b/packages/design-system/src/components/N8nAvatar/Avatar.test.ts similarity index 94% rename from packages/design-system/src/components/N8nAvatar/__tests__/Avatar.test.ts rename to packages/design-system/src/components/N8nAvatar/Avatar.test.ts index 3abc2b5b532..d4ea1063900 100644 --- a/packages/design-system/src/components/N8nAvatar/__tests__/Avatar.test.ts +++ b/packages/design-system/src/components/N8nAvatar/Avatar.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nAvatar from '../Avatar.vue'; +import N8nAvatar from './Avatar.vue'; describe('components', () => { describe('N8nAlert', () => { diff --git a/packages/design-system/src/components/N8nBadge/__tests__/Badge.spec.ts b/packages/design-system/src/components/N8nBadge/Badge.test.ts similarity index 96% rename from packages/design-system/src/components/N8nBadge/__tests__/Badge.spec.ts rename to packages/design-system/src/components/N8nBadge/Badge.test.ts index 20d6a29d840..0b8c4defd45 100644 --- a/packages/design-system/src/components/N8nBadge/__tests__/Badge.spec.ts +++ b/packages/design-system/src/components/N8nBadge/Badge.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nBadge from '../Badge.vue'; +import N8nBadge from './Badge.vue'; describe('components', () => { describe('N8nBadge', () => { diff --git a/packages/design-system/src/components/N8nBadge/__tests__/__snapshots__/Badge.spec.ts.snap b/packages/design-system/src/components/N8nBadge/__snapshots__/Badge.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nBadge/__tests__/__snapshots__/Badge.spec.ts.snap rename to packages/design-system/src/components/N8nBadge/__snapshots__/Badge.test.ts.snap diff --git a/packages/design-system/src/components/N8nBlockUi/__tests__/BlockUi.spec.ts b/packages/design-system/src/components/N8nBlockUi/BlockUi.test.ts similarity index 91% rename from packages/design-system/src/components/N8nBlockUi/__tests__/BlockUi.spec.ts rename to packages/design-system/src/components/N8nBlockUi/BlockUi.test.ts index 2238f07b224..fa83b44e7f5 100644 --- a/packages/design-system/src/components/N8nBlockUi/__tests__/BlockUi.spec.ts +++ b/packages/design-system/src/components/N8nBlockUi/BlockUi.test.ts @@ -1,6 +1,6 @@ import { render, screen } from '@testing-library/vue'; -import N8nBlockUi from '../BlockUi.vue'; +import N8nBlockUi from './BlockUi.vue'; describe('components', () => { describe('N8nBlockUi', () => { diff --git a/packages/design-system/src/components/N8nButton/__tests__/Button.spec.ts b/packages/design-system/src/components/N8nButton/Button.test.ts similarity index 97% rename from packages/design-system/src/components/N8nButton/__tests__/Button.spec.ts rename to packages/design-system/src/components/N8nButton/Button.test.ts index 371599f8771..5b224594b21 100644 --- a/packages/design-system/src/components/N8nButton/__tests__/Button.spec.ts +++ b/packages/design-system/src/components/N8nButton/Button.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nButton from '../Button.vue'; +import N8nButton from './Button.vue'; const slots = { default: 'Button', diff --git a/packages/design-system/src/components/N8nButton/__tests__/__snapshots__/Button.spec.ts.snap b/packages/design-system/src/components/N8nButton/__snapshots__/Button.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nButton/__tests__/__snapshots__/Button.spec.ts.snap rename to packages/design-system/src/components/N8nButton/__snapshots__/Button.test.ts.snap diff --git a/packages/design-system/src/components/N8nCallout/__tests__/Callout.spec.ts b/packages/design-system/src/components/N8nCallout/Callout.test.ts similarity index 98% rename from packages/design-system/src/components/N8nCallout/__tests__/Callout.spec.ts rename to packages/design-system/src/components/N8nCallout/Callout.test.ts index 782ce7c4174..e308a738286 100644 --- a/packages/design-system/src/components/N8nCallout/__tests__/Callout.spec.ts +++ b/packages/design-system/src/components/N8nCallout/Callout.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nCallout from '../Callout.vue'; +import N8nCallout from './Callout.vue'; describe('components', () => { describe('N8nCallout', () => { diff --git a/packages/design-system/src/components/N8nCallout/__tests__/__snapshots__/Callout.spec.ts.snap b/packages/design-system/src/components/N8nCallout/__snapshots__/Callout.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nCallout/__tests__/__snapshots__/Callout.spec.ts.snap rename to packages/design-system/src/components/N8nCallout/__snapshots__/Callout.test.ts.snap diff --git a/packages/design-system/src/components/N8nCard/__tests__/Card.spec.ts b/packages/design-system/src/components/N8nCard/Card.test.ts similarity index 94% rename from packages/design-system/src/components/N8nCard/__tests__/Card.spec.ts rename to packages/design-system/src/components/N8nCard/Card.test.ts index 3228a51e2b1..544ce61c237 100644 --- a/packages/design-system/src/components/N8nCard/__tests__/Card.spec.ts +++ b/packages/design-system/src/components/N8nCard/Card.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nCard from '../Card.vue'; +import N8nCard from './Card.vue'; describe('components', () => { describe('N8nCard', () => { diff --git a/packages/design-system/src/components/N8nCard/__tests__/__snapshots__/Card.spec.ts.snap b/packages/design-system/src/components/N8nCard/__snapshots__/Card.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nCard/__tests__/__snapshots__/Card.spec.ts.snap rename to packages/design-system/src/components/N8nCard/__snapshots__/Card.test.ts.snap diff --git a/packages/design-system/src/components/N8nCheckbox/__tests__/Checkbox.spec.ts b/packages/design-system/src/components/N8nCheckbox/Checkbox.test.ts similarity index 95% rename from packages/design-system/src/components/N8nCheckbox/__tests__/Checkbox.spec.ts rename to packages/design-system/src/components/N8nCheckbox/Checkbox.test.ts index 43ef21a9c54..ed80d59e641 100644 --- a/packages/design-system/src/components/N8nCheckbox/__tests__/Checkbox.spec.ts +++ b/packages/design-system/src/components/N8nCheckbox/Checkbox.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nCheckbox from '../Checkbox.vue'; +import N8nCheckbox from './Checkbox.vue'; describe('components', () => { describe('N8nCheckbox', () => { diff --git a/packages/design-system/src/components/N8nCheckbox/__tests__/__snapshots__/Checkbox.spec.ts.snap b/packages/design-system/src/components/N8nCheckbox/__snapshots__/Checkbox.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nCheckbox/__tests__/__snapshots__/Checkbox.spec.ts.snap rename to packages/design-system/src/components/N8nCheckbox/__snapshots__/Checkbox.test.ts.snap diff --git a/packages/design-system/src/components/N8nCircleLoader/__tests__/CircleLoader.spec.ts b/packages/design-system/src/components/N8nCircleLoader/CircleLoader.test.ts similarity index 85% rename from packages/design-system/src/components/N8nCircleLoader/__tests__/CircleLoader.spec.ts rename to packages/design-system/src/components/N8nCircleLoader/CircleLoader.test.ts index 76b76d5a30f..afe5a6b8f08 100644 --- a/packages/design-system/src/components/N8nCircleLoader/__tests__/CircleLoader.spec.ts +++ b/packages/design-system/src/components/N8nCircleLoader/CircleLoader.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8NCircleLoader from '../CircleLoader.vue'; +import N8NCircleLoader from './CircleLoader.vue'; describe('N8NCircleLoader', () => { it('should render correctly', () => { diff --git a/packages/design-system/src/components/N8nCircleLoader/__tests__/__snapshots__/CircleLoader.spec.ts.snap b/packages/design-system/src/components/N8nCircleLoader/__snapshots__/CircleLoader.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nCircleLoader/__tests__/__snapshots__/CircleLoader.spec.ts.snap rename to packages/design-system/src/components/N8nCircleLoader/__snapshots__/CircleLoader.test.ts.snap diff --git a/packages/design-system/src/components/N8nColorPicker/__tests__/ColorPicker.spec.ts b/packages/design-system/src/components/N8nColorPicker/ColorPicker.test.ts similarity index 91% rename from packages/design-system/src/components/N8nColorPicker/__tests__/ColorPicker.spec.ts rename to packages/design-system/src/components/N8nColorPicker/ColorPicker.test.ts index bf1253b8b94..62da81ee001 100644 --- a/packages/design-system/src/components/N8nColorPicker/__tests__/ColorPicker.spec.ts +++ b/packages/design-system/src/components/N8nColorPicker/ColorPicker.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nColorPicker from '../ColorPicker.vue'; +import N8nColorPicker from './ColorPicker.vue'; describe('components', () => { describe('N8nColorPicker', () => { diff --git a/packages/design-system/src/components/N8nColorPicker/__tests__/__snapshots__/ColorPicker.spec.ts.snap b/packages/design-system/src/components/N8nColorPicker/__snapshots__/ColorPicker.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nColorPicker/__tests__/__snapshots__/ColorPicker.spec.ts.snap rename to packages/design-system/src/components/N8nColorPicker/__snapshots__/ColorPicker.test.ts.snap diff --git a/packages/design-system/src/components/N8nDatatable/__tests__/Datatable.spec.ts b/packages/design-system/src/components/N8nDatatable/Datatable.test.ts similarity index 96% rename from packages/design-system/src/components/N8nDatatable/__tests__/Datatable.spec.ts rename to packages/design-system/src/components/N8nDatatable/Datatable.test.ts index c19fa3ca0d1..de8659c71ce 100644 --- a/packages/design-system/src/components/N8nDatatable/__tests__/Datatable.spec.ts +++ b/packages/design-system/src/components/N8nDatatable/Datatable.test.ts @@ -2,8 +2,8 @@ import { render } from '@testing-library/vue'; import { removeDynamicAttributes } from 'n8n-design-system/utils'; -import { rows, columns } from './data'; -import N8nDatatable from '../Datatable.vue'; +import { rows, columns } from './__tests__/data'; +import N8nDatatable from './Datatable.vue'; const stubs = [ 'n8n-option', diff --git a/packages/design-system/src/components/N8nDatatable/__tests__/__snapshots__/Datatable.spec.ts.snap b/packages/design-system/src/components/N8nDatatable/__snapshots__/Datatable.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nDatatable/__tests__/__snapshots__/Datatable.spec.ts.snap rename to packages/design-system/src/components/N8nDatatable/__snapshots__/Datatable.test.ts.snap diff --git a/packages/design-system/src/components/N8nFormBox/__tests__/FormBox.test.ts b/packages/design-system/src/components/N8nFormBox/FormBox.test.ts similarity index 91% rename from packages/design-system/src/components/N8nFormBox/__tests__/FormBox.test.ts rename to packages/design-system/src/components/N8nFormBox/FormBox.test.ts index a309e1aa407..268c70c0608 100644 --- a/packages/design-system/src/components/N8nFormBox/__tests__/FormBox.test.ts +++ b/packages/design-system/src/components/N8nFormBox/FormBox.test.ts @@ -1,5 +1,5 @@ -import { createComponentRenderer } from '../../../__tests__/render'; -import FormBox from '../FormBox.vue'; +import FormBox from './FormBox.vue'; +import { createComponentRenderer } from '../../__tests__/render'; const render = createComponentRenderer(FormBox); diff --git a/packages/design-system/src/components/N8nFormBox/__tests__/__snapshots__/FormBox.test.ts.snap b/packages/design-system/src/components/N8nFormBox/__snapshots__/FormBox.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nFormBox/__tests__/__snapshots__/FormBox.test.ts.snap rename to packages/design-system/src/components/N8nFormBox/__snapshots__/FormBox.test.ts.snap diff --git a/packages/design-system/src/components/N8nInfoTip/__tests__/InfoTip.spec.ts b/packages/design-system/src/components/N8nInfoTip/InfoTip.test.ts similarity index 93% rename from packages/design-system/src/components/N8nInfoTip/__tests__/InfoTip.spec.ts rename to packages/design-system/src/components/N8nInfoTip/InfoTip.test.ts index ce3eb230fa0..8f4e9051389 100644 --- a/packages/design-system/src/components/N8nInfoTip/__tests__/InfoTip.spec.ts +++ b/packages/design-system/src/components/N8nInfoTip/InfoTip.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nInfoTip from '../InfoTip.vue'; +import N8nInfoTip from './InfoTip.vue'; const slots = { default: ['Need help doing something?', 'Open docs'], diff --git a/packages/design-system/src/components/N8nInfoTip/__tests__/__snapshots__/InfoTip.spec.ts.snap b/packages/design-system/src/components/N8nInfoTip/__snapshots__/InfoTip.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nInfoTip/__tests__/__snapshots__/InfoTip.spec.ts.snap rename to packages/design-system/src/components/N8nInfoTip/__snapshots__/InfoTip.test.ts.snap diff --git a/packages/design-system/src/components/N8nInput/__tests__/Input.spec.ts b/packages/design-system/src/components/N8nInput/Input.test.ts similarity index 94% rename from packages/design-system/src/components/N8nInput/__tests__/Input.spec.ts rename to packages/design-system/src/components/N8nInput/Input.test.ts index cea5a1f0060..41b1d1636d3 100644 --- a/packages/design-system/src/components/N8nInput/__tests__/Input.spec.ts +++ b/packages/design-system/src/components/N8nInput/Input.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nInput from '../Input.vue'; +import N8nInput from './Input.vue'; describe('N8nInput', () => { it('should render correctly', () => { diff --git a/packages/design-system/src/components/N8nInput/__tests__/__snapshots__/Input.spec.ts.snap b/packages/design-system/src/components/N8nInput/__snapshots__/Input.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nInput/__tests__/__snapshots__/Input.spec.ts.snap rename to packages/design-system/src/components/N8nInput/__snapshots__/Input.test.ts.snap diff --git a/packages/design-system/src/components/N8nInputLabel/__tests__/InputLabel.spec.ts b/packages/design-system/src/components/N8nInputLabel/InputLabel.test.ts similarity index 93% rename from packages/design-system/src/components/N8nInputLabel/__tests__/InputLabel.spec.ts rename to packages/design-system/src/components/N8nInputLabel/InputLabel.test.ts index ab46c89e12f..841be5e147d 100644 --- a/packages/design-system/src/components/N8nInputLabel/__tests__/InputLabel.spec.ts +++ b/packages/design-system/src/components/N8nInputLabel/InputLabel.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import InputLabel from '../InputLabel.vue'; +import InputLabel from './InputLabel.vue'; describe('component', () => { describe('Text overflow behavior', () => { diff --git a/packages/design-system/src/components/N8nInputLabel/__tests__/__snapshots__/InputLabel.spec.ts.snap b/packages/design-system/src/components/N8nInputLabel/__snapshots__/InputLabel.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nInputLabel/__tests__/__snapshots__/InputLabel.spec.ts.snap rename to packages/design-system/src/components/N8nInputLabel/__snapshots__/InputLabel.test.ts.snap diff --git a/packages/design-system/src/components/N8nMarkdown/__tests__/Markdown.spec.ts b/packages/design-system/src/components/N8nMarkdown/Markdown.test.ts similarity index 98% rename from packages/design-system/src/components/N8nMarkdown/__tests__/Markdown.spec.ts rename to packages/design-system/src/components/N8nMarkdown/Markdown.test.ts index d9671464d22..0e77779b5d1 100644 --- a/packages/design-system/src/components/N8nMarkdown/__tests__/Markdown.spec.ts +++ b/packages/design-system/src/components/N8nMarkdown/Markdown.test.ts @@ -2,7 +2,7 @@ import { render, fireEvent } from '@testing-library/vue'; import { n8nHtml } from 'n8n-design-system/directives'; -import N8nMarkdown from '../Markdown.vue'; +import N8nMarkdown from './Markdown.vue'; describe('components', () => { describe('N8nMarkdown', () => { diff --git a/packages/design-system/src/components/N8nNavigationDropdown/__tests__/NavigationDropdown.spec.ts b/packages/design-system/src/components/N8nNavigationDropdown/NavigationDropdown.test.ts similarity index 98% rename from packages/design-system/src/components/N8nNavigationDropdown/__tests__/NavigationDropdown.spec.ts rename to packages/design-system/src/components/N8nNavigationDropdown/NavigationDropdown.test.ts index 465f1f0c2b4..adb73aa6d1c 100644 --- a/packages/design-system/src/components/N8nNavigationDropdown/__tests__/NavigationDropdown.spec.ts +++ b/packages/design-system/src/components/N8nNavigationDropdown/NavigationDropdown.test.ts @@ -3,7 +3,7 @@ import { configure, render, waitFor } from '@testing-library/vue'; import { h } from 'vue'; import { createRouter, createWebHistory } from 'vue-router'; -import NavigationDropdown from '../NavigationDropdown.vue'; +import NavigationDropdown from './NavigationDropdown.vue'; configure({ testIdAttribute: 'data-test-id' }); diff --git a/packages/design-system/src/components/N8nNotice/__tests__/Notice.spec.ts b/packages/design-system/src/components/N8nNotice/Notice.test.ts similarity index 97% rename from packages/design-system/src/components/N8nNotice/__tests__/Notice.spec.ts rename to packages/design-system/src/components/N8nNotice/Notice.test.ts index 25c098b5583..8ef26d1a9ce 100644 --- a/packages/design-system/src/components/N8nNotice/__tests__/Notice.spec.ts +++ b/packages/design-system/src/components/N8nNotice/Notice.test.ts @@ -3,7 +3,7 @@ import { render } from '@testing-library/vue'; import { N8nText } from 'n8n-design-system/components'; import { n8nHtml } from 'n8n-design-system/directives'; -import N8nNotice from '../Notice.vue'; +import N8nNotice from './Notice.vue'; describe('components', () => { describe('N8nNotice', () => { diff --git a/packages/design-system/src/components/N8nNotice/__tests__/__snapshots__/Notice.spec.ts.snap b/packages/design-system/src/components/N8nNotice/__snapshots__/Notice.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nNotice/__tests__/__snapshots__/Notice.spec.ts.snap rename to packages/design-system/src/components/N8nNotice/__snapshots__/Notice.test.ts.snap diff --git a/packages/design-system/src/components/N8nRecycleScroller/__tests__/RecycleScroller.spec.ts b/packages/design-system/src/components/N8nRecycleScroller/RecycleScroller.test.ts similarity index 91% rename from packages/design-system/src/components/N8nRecycleScroller/__tests__/RecycleScroller.spec.ts rename to packages/design-system/src/components/N8nRecycleScroller/RecycleScroller.test.ts index 85c83db4288..8324ef9aa26 100644 --- a/packages/design-system/src/components/N8nRecycleScroller/__tests__/RecycleScroller.spec.ts +++ b/packages/design-system/src/components/N8nRecycleScroller/RecycleScroller.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nRecycleScroller from '../RecycleScroller.vue'; +import N8nRecycleScroller from './RecycleScroller.vue'; const itemSize = 100; const itemKey = 'id'; diff --git a/packages/design-system/src/components/N8nRecycleScroller/__tests__/__snapshots__/RecycleScroller.spec.ts.snap b/packages/design-system/src/components/N8nRecycleScroller/__snapshots__/RecycleScroller.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nRecycleScroller/__tests__/__snapshots__/RecycleScroller.spec.ts.snap rename to packages/design-system/src/components/N8nRecycleScroller/__snapshots__/RecycleScroller.test.ts.snap diff --git a/packages/design-system/src/components/N8nRoute/__tests__/Route.spec.ts b/packages/design-system/src/components/N8nRoute/Route.test.ts similarity index 94% rename from packages/design-system/src/components/N8nRoute/__tests__/Route.spec.ts rename to packages/design-system/src/components/N8nRoute/Route.test.ts index 430c8f1ae02..ea307826d43 100644 --- a/packages/design-system/src/components/N8nRoute/__tests__/Route.spec.ts +++ b/packages/design-system/src/components/N8nRoute/Route.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nRoute from '../Route.vue'; +import N8nRoute from './Route.vue'; describe('N8nRoute', () => { it('should render internal router links', () => { diff --git a/packages/design-system/src/components/N8nRoute/__tests__/__snapshots__/Route.spec.ts.snap b/packages/design-system/src/components/N8nRoute/__snapshots__/Route.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nRoute/__tests__/__snapshots__/Route.spec.ts.snap rename to packages/design-system/src/components/N8nRoute/__snapshots__/Route.test.ts.snap diff --git a/packages/design-system/src/components/N8nSelect/__tests__/Select.spec.ts b/packages/design-system/src/components/N8nSelect/Select.test.ts similarity index 95% rename from packages/design-system/src/components/N8nSelect/__tests__/Select.spec.ts rename to packages/design-system/src/components/N8nSelect/Select.test.ts index bba6055e466..9aafcf2bfff 100644 --- a/packages/design-system/src/components/N8nSelect/__tests__/Select.spec.ts +++ b/packages/design-system/src/components/N8nSelect/Select.test.ts @@ -4,8 +4,8 @@ import { defineComponent, ref } from 'vue'; import { removeDynamicAttributes } from 'n8n-design-system/utils'; -import N8nOption from '../../N8nOption/Option.vue'; -import N8nSelect from '../Select.vue'; +import N8nSelect from './Select.vue'; +import N8nOption from '../N8nOption/Option.vue'; describe('components', () => { describe('N8nSelect', () => { diff --git a/packages/design-system/src/components/N8nSelect/__tests__/__snapshots__/Select.spec.ts.snap b/packages/design-system/src/components/N8nSelect/__snapshots__/Select.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nSelect/__tests__/__snapshots__/Select.spec.ts.snap rename to packages/design-system/src/components/N8nSelect/__snapshots__/Select.test.ts.snap diff --git a/packages/design-system/src/components/N8nTooltip/__tests__/Tooltip.spec.ts b/packages/design-system/src/components/N8nTooltip/Tooltip.test.ts similarity index 95% rename from packages/design-system/src/components/N8nTooltip/__tests__/Tooltip.spec.ts rename to packages/design-system/src/components/N8nTooltip/Tooltip.test.ts index 8fe4219d2d0..230a239910e 100644 --- a/packages/design-system/src/components/N8nTooltip/__tests__/Tooltip.spec.ts +++ b/packages/design-system/src/components/N8nTooltip/Tooltip.test.ts @@ -1,7 +1,7 @@ import userEvent from '@testing-library/user-event'; import { render } from '@testing-library/vue'; -import N8nTooltip from '../Tooltip.vue'; +import N8nTooltip from './Tooltip.vue'; describe('components', () => { describe('N8nTooltip', () => { diff --git a/packages/design-system/src/components/N8nTree/__tests__/Tree.spec.ts b/packages/design-system/src/components/N8nTree/Tree.test.ts similarity index 97% rename from packages/design-system/src/components/N8nTree/__tests__/Tree.spec.ts rename to packages/design-system/src/components/N8nTree/Tree.test.ts index 1728a6f9fce..8266d03f6a1 100644 --- a/packages/design-system/src/components/N8nTree/__tests__/Tree.spec.ts +++ b/packages/design-system/src/components/N8nTree/Tree.test.ts @@ -1,6 +1,6 @@ import { render } from '@testing-library/vue'; -import N8nTree from '../Tree.vue'; +import N8nTree from './Tree.vue'; describe('components', () => { describe('N8nTree', () => { diff --git a/packages/design-system/src/components/N8nTree/__tests__/__snapshots__/Tree.spec.ts.snap b/packages/design-system/src/components/N8nTree/__snapshots__/Tree.test.ts.snap similarity index 100% rename from packages/design-system/src/components/N8nTree/__tests__/__snapshots__/Tree.spec.ts.snap rename to packages/design-system/src/components/N8nTree/__snapshots__/Tree.test.ts.snap diff --git a/packages/design-system/src/components/N8nUserStack/__tests__/UserStack.spec.ts b/packages/design-system/src/components/N8nUserStack/UserStack.test.ts similarity index 98% rename from packages/design-system/src/components/N8nUserStack/__tests__/UserStack.spec.ts rename to packages/design-system/src/components/N8nUserStack/UserStack.test.ts index b08fe3d3d30..1b5ae600ae7 100644 --- a/packages/design-system/src/components/N8nUserStack/__tests__/UserStack.spec.ts +++ b/packages/design-system/src/components/N8nUserStack/UserStack.test.ts @@ -2,7 +2,7 @@ import { render } from '@testing-library/vue'; import { N8nAvatar, N8nUserInfo } from 'n8n-design-system/main'; -import UserStack from '../UserStack.vue'; +import UserStack from './UserStack.vue'; describe('UserStack', () => { it('should render flat user list', () => { diff --git a/packages/design-system/src/styleguide/__tests__/ColorCircles.spec.ts b/packages/design-system/src/styleguide/ColorCircles.test.ts similarity index 94% rename from packages/design-system/src/styleguide/__tests__/ColorCircles.spec.ts rename to packages/design-system/src/styleguide/ColorCircles.test.ts index 0e8f7cb4796..3f82ff2a189 100644 --- a/packages/design-system/src/styleguide/__tests__/ColorCircles.spec.ts +++ b/packages/design-system/src/styleguide/ColorCircles.test.ts @@ -1,7 +1,7 @@ import { render } from '@testing-library/vue'; import { mock, mockClear } from 'vitest-mock-extended'; -import ColorCircles from '../ColorCircles.vue'; +import ColorCircles from './ColorCircles.vue'; describe('ColorCircles', () => { const mockCssDeclaration = mock(); diff --git a/packages/design-system/src/styleguide/__tests__/Sizes.spec.ts b/packages/design-system/src/styleguide/Sizes.test.ts similarity index 94% rename from packages/design-system/src/styleguide/__tests__/Sizes.spec.ts rename to packages/design-system/src/styleguide/Sizes.test.ts index 9ac613c4d38..2a7f6d916fd 100644 --- a/packages/design-system/src/styleguide/__tests__/Sizes.spec.ts +++ b/packages/design-system/src/styleguide/Sizes.test.ts @@ -1,7 +1,7 @@ import { render } from '@testing-library/vue'; import { mock, mockClear } from 'vitest-mock-extended'; -import Sizes from '../Sizes.vue'; +import Sizes from './Sizes.vue'; describe('Sizes', () => { const mockCssDeclaration = mock(); diff --git a/packages/design-system/src/styleguide/__tests__/__snapshots__/ColorCircles.spec.ts.snap b/packages/design-system/src/styleguide/__snapshots__/ColorCircles.test.ts.snap similarity index 100% rename from packages/design-system/src/styleguide/__tests__/__snapshots__/ColorCircles.spec.ts.snap rename to packages/design-system/src/styleguide/__snapshots__/ColorCircles.test.ts.snap diff --git a/packages/design-system/src/styleguide/__tests__/__snapshots__/Sizes.spec.ts.snap b/packages/design-system/src/styleguide/__snapshots__/Sizes.test.ts.snap similarity index 100% rename from packages/design-system/src/styleguide/__tests__/__snapshots__/Sizes.spec.ts.snap rename to packages/design-system/src/styleguide/__snapshots__/Sizes.test.ts.snap diff --git a/packages/design-system/src/utils/__tests__/event-bus.spec.ts b/packages/design-system/src/utils/event-bus.test.ts similarity index 97% rename from packages/design-system/src/utils/__tests__/event-bus.spec.ts rename to packages/design-system/src/utils/event-bus.test.ts index 2fb0735404e..0d1500dc543 100644 --- a/packages/design-system/src/utils/__tests__/event-bus.spec.ts +++ b/packages/design-system/src/utils/event-bus.test.ts @@ -1,4 +1,4 @@ -import { createEventBus } from '../event-bus'; +import { createEventBus } from './event-bus'; describe('createEventBus()', () => { const eventBus = createEventBus(); diff --git a/packages/design-system/src/utils/labelUtil.spec.ts b/packages/design-system/src/utils/labelUtil.test.ts similarity index 100% rename from packages/design-system/src/utils/labelUtil.spec.ts rename to packages/design-system/src/utils/labelUtil.test.ts diff --git a/packages/design-system/src/utils/__tests__/markdown.spec.ts b/packages/design-system/src/utils/markdown.test.ts similarity index 95% rename from packages/design-system/src/utils/__tests__/markdown.spec.ts rename to packages/design-system/src/utils/markdown.test.ts index c712b940480..d2d3d0089f9 100644 --- a/packages/design-system/src/utils/__tests__/markdown.spec.ts +++ b/packages/design-system/src/utils/markdown.test.ts @@ -1,4 +1,4 @@ -import { toggleCheckbox } from '../markdown'; +import { toggleCheckbox } from './markdown'; describe('toggleCheckbox', () => { it('should do nothing when there are no checkboxes', () => { diff --git a/packages/design-system/src/utils/__tests__/valueByPath.spec.ts b/packages/design-system/src/utils/valueByPath.test.ts similarity index 100% rename from packages/design-system/src/utils/__tests__/valueByPath.spec.ts rename to packages/design-system/src/utils/valueByPath.test.ts diff --git a/packages/editor-ui/src/components/CommunityPackageInstallModal.spec.ts b/packages/editor-ui/src/components/CommunityPackageInstallModal.test.ts similarity index 100% rename from packages/editor-ui/src/components/CommunityPackageInstallModal.spec.ts rename to packages/editor-ui/src/components/CommunityPackageInstallModal.test.ts diff --git a/packages/editor-ui/src/components/Feedback.spec.ts b/packages/editor-ui/src/components/Feedback.test.ts similarity index 100% rename from packages/editor-ui/src/components/Feedback.spec.ts rename to packages/editor-ui/src/components/Feedback.test.ts diff --git a/packages/editor-ui/src/components/MainHeader/TabBar.spec.ts b/packages/editor-ui/src/components/MainHeader/TabBar.test.ts similarity index 100% rename from packages/editor-ui/src/components/MainHeader/TabBar.spec.ts rename to packages/editor-ui/src/components/MainHeader/TabBar.test.ts diff --git a/packages/editor-ui/src/components/MainHeader/WorkflowDetails.spec.ts b/packages/editor-ui/src/components/MainHeader/WorkflowDetails.test.ts similarity index 100% rename from packages/editor-ui/src/components/MainHeader/WorkflowDetails.spec.ts rename to packages/editor-ui/src/components/MainHeader/WorkflowDetails.test.ts diff --git a/packages/editor-ui/src/components/NDVSubConnections.spec.ts b/packages/editor-ui/src/components/NDVSubConnections.test.ts similarity index 100% rename from packages/editor-ui/src/components/NDVSubConnections.spec.ts rename to packages/editor-ui/src/components/NDVSubConnections.test.ts diff --git a/packages/editor-ui/src/components/VariablesRow.spec.ts b/packages/editor-ui/src/components/VariablesRow.test.ts similarity index 100% rename from packages/editor-ui/src/components/VariablesRow.spec.ts rename to packages/editor-ui/src/components/VariablesRow.test.ts diff --git a/packages/editor-ui/src/components/WorkflowSettings.spec.ts b/packages/editor-ui/src/components/WorkflowSettings.test.ts similarity index 100% rename from packages/editor-ui/src/components/WorkflowSettings.spec.ts rename to packages/editor-ui/src/components/WorkflowSettings.test.ts diff --git a/packages/editor-ui/src/components/banners/V1Banner.spec.ts b/packages/editor-ui/src/components/banners/V1Banner.test.ts similarity index 100% rename from packages/editor-ui/src/components/banners/V1Banner.spec.ts rename to packages/editor-ui/src/components/banners/V1Banner.test.ts diff --git a/packages/editor-ui/src/components/banners/__snapshots__/V1Banner.spec.ts.snap b/packages/editor-ui/src/components/banners/__snapshots__/V1Banner.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/banners/__snapshots__/V1Banner.spec.ts.snap rename to packages/editor-ui/src/components/banners/__snapshots__/V1Banner.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/Canvas.spec.ts b/packages/editor-ui/src/components/canvas/Canvas.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/Canvas.spec.ts rename to packages/editor-ui/src/components/canvas/Canvas.test.ts diff --git a/packages/editor-ui/src/components/canvas/WorkflowCanvas.spec.ts b/packages/editor-ui/src/components/canvas/WorkflowCanvas.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/WorkflowCanvas.spec.ts rename to packages/editor-ui/src/components/canvas/WorkflowCanvas.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/CanvasChatButton.spec.ts b/packages/editor-ui/src/components/canvas/elements/buttons/CanvasChatButton.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/CanvasChatButton.spec.ts rename to packages/editor-ui/src/components/canvas/elements/buttons/CanvasChatButton.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/CanvasClearExecutionDataButton.spec.ts b/packages/editor-ui/src/components/canvas/elements/buttons/CanvasClearExecutionDataButton.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/CanvasClearExecutionDataButton.spec.ts rename to packages/editor-ui/src/components/canvas/elements/buttons/CanvasClearExecutionDataButton.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/CanvasControlButtons.spec.ts b/packages/editor-ui/src/components/canvas/elements/buttons/CanvasControlButtons.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/CanvasControlButtons.spec.ts rename to packages/editor-ui/src/components/canvas/elements/buttons/CanvasControlButtons.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/CanvasRunWorkflowButton.spec.ts b/packages/editor-ui/src/components/canvas/elements/buttons/CanvasRunWorkflowButton.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/CanvasRunWorkflowButton.spec.ts rename to packages/editor-ui/src/components/canvas/elements/buttons/CanvasRunWorkflowButton.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopCurrentExecutionButton.spec.ts b/packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopCurrentExecutionButton.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopCurrentExecutionButton.spec.ts rename to packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopCurrentExecutionButton.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopWaitingForWebhookButton.spec.ts b/packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopWaitingForWebhookButton.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopWaitingForWebhookButton.spec.ts rename to packages/editor-ui/src/components/canvas/elements/buttons/CanvasStopWaitingForWebhookButton.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasChatButton.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasChatButton.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasChatButton.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasChatButton.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasClearExecutionDataButton.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasClearExecutionDataButton.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasClearExecutionDataButton.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasClearExecutionDataButton.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasControlButtons.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasControlButtons.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasControlButtons.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasControlButtons.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasExecuteWorkflowButton.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasExecuteWorkflowButton.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasExecuteWorkflowButton.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasExecuteWorkflowButton.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasRunWorkflowButton.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasRunWorkflowButton.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasRunWorkflowButton.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasRunWorkflowButton.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopCurrentExecutionButton.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopCurrentExecutionButton.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopCurrentExecutionButton.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopCurrentExecutionButton.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopWaitingForWebhookButton.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopWaitingForWebhookButton.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopWaitingForWebhookButton.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/buttons/__snapshots__/CanvasStopWaitingForWebhookButton.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts b/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts rename to packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/edges/CanvasEdge.spec.ts b/packages/editor-ui/src/components/canvas/elements/edges/CanvasEdge.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/edges/CanvasEdge.spec.ts rename to packages/editor-ui/src/components/canvas/elements/edges/CanvasEdge.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.spec.ts b/packages/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.spec.ts rename to packages/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainInput.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainInput.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainInput.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainInput.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainOutput.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainOutput.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainOutput.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleMainOutput.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainInput.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainInput.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainInput.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainInput.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainOutput.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainOutput.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainOutput.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/CanvasHandleNonMainOutput.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDiamond.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDiamond.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDiamond.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDiamond.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDot.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDot.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDot.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleDot.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandlePlus.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandlePlus.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandlePlus.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandlePlus.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleRectangle.spec.ts b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleRectangle.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleRectangle.spec.ts rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/CanvasHandleRectangle.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDiamond.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDiamond.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDiamond.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDiamond.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDot.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDot.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDot.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleDot.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandlePlus.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandlePlus.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandlePlus.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandlePlus.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleRectangle.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleRectangle.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleRectangle.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/handles/render-types/parts/__snapshots__/CanvasHandleRectangle.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNode.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNode.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/CanvasNode.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/CanvasNode.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeRenderer.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeRenderer.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeRenderer.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeRenderer.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeStickyNote.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeStickyNote.spec.ts.snap b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeStickyNote.test.ts.snap similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeStickyNote.spec.ts.snap rename to packages/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeStickyNote.test.ts.snap diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.test.ts diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/toolbar/CanvasNodeStickyColorSelector.spec.ts b/packages/editor-ui/src/components/canvas/elements/nodes/toolbar/CanvasNodeStickyColorSelector.test.ts similarity index 100% rename from packages/editor-ui/src/components/canvas/elements/nodes/toolbar/CanvasNodeStickyColorSelector.spec.ts rename to packages/editor-ui/src/components/canvas/elements/nodes/toolbar/CanvasNodeStickyColorSelector.test.ts diff --git a/packages/editor-ui/src/composables/__snapshots__/useBugReporting.spec.ts.snap b/packages/editor-ui/src/composables/__snapshots__/useBugReporting.test.ts.snap similarity index 100% rename from packages/editor-ui/src/composables/__snapshots__/useBugReporting.spec.ts.snap rename to packages/editor-ui/src/composables/__snapshots__/useBugReporting.test.ts.snap diff --git a/packages/editor-ui/src/composables/__snapshots__/useCanvasOperations.spec.ts.snap b/packages/editor-ui/src/composables/__snapshots__/useCanvasOperations.test.ts.snap similarity index 100% rename from packages/editor-ui/src/composables/__snapshots__/useCanvasOperations.spec.ts.snap rename to packages/editor-ui/src/composables/__snapshots__/useCanvasOperations.test.ts.snap diff --git a/packages/editor-ui/src/composables/__snapshots__/useDebugInfo.spec.ts.snap b/packages/editor-ui/src/composables/__snapshots__/useDebugInfo.test.ts.snap similarity index 100% rename from packages/editor-ui/src/composables/__snapshots__/useDebugInfo.spec.ts.snap rename to packages/editor-ui/src/composables/__snapshots__/useDebugInfo.test.ts.snap diff --git a/packages/editor-ui/src/composables/useBugReporting.spec.ts b/packages/editor-ui/src/composables/useBugReporting.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useBugReporting.spec.ts rename to packages/editor-ui/src/composables/useBugReporting.test.ts diff --git a/packages/editor-ui/src/composables/useCanvasMapping.spec.ts b/packages/editor-ui/src/composables/useCanvasMapping.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useCanvasMapping.spec.ts rename to packages/editor-ui/src/composables/useCanvasMapping.test.ts diff --git a/packages/editor-ui/src/composables/useCanvasNode.spec.ts b/packages/editor-ui/src/composables/useCanvasNode.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useCanvasNode.spec.ts rename to packages/editor-ui/src/composables/useCanvasNode.test.ts diff --git a/packages/editor-ui/src/composables/useCanvasOperations.spec.ts b/packages/editor-ui/src/composables/useCanvasOperations.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useCanvasOperations.spec.ts rename to packages/editor-ui/src/composables/useCanvasOperations.test.ts diff --git a/packages/editor-ui/src/composables/useDebugInfo.spec.ts b/packages/editor-ui/src/composables/useDebugInfo.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useDebugInfo.spec.ts rename to packages/editor-ui/src/composables/useDebugInfo.test.ts diff --git a/packages/editor-ui/src/composables/useExecutionDebugging.spec.ts b/packages/editor-ui/src/composables/useExecutionDebugging.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useExecutionDebugging.spec.ts rename to packages/editor-ui/src/composables/useExecutionDebugging.test.ts diff --git a/packages/editor-ui/src/composables/useNodeBase.spec.ts b/packages/editor-ui/src/composables/useNodeBase.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useNodeBase.spec.ts rename to packages/editor-ui/src/composables/useNodeBase.test.ts diff --git a/packages/editor-ui/src/composables/useNodeConnections.spec.ts b/packages/editor-ui/src/composables/useNodeConnections.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useNodeConnections.spec.ts rename to packages/editor-ui/src/composables/useNodeConnections.test.ts diff --git a/packages/editor-ui/src/composables/usePushConnection.spec.ts b/packages/editor-ui/src/composables/usePushConnection.test.ts similarity index 100% rename from packages/editor-ui/src/composables/usePushConnection.spec.ts rename to packages/editor-ui/src/composables/usePushConnection.test.ts diff --git a/packages/editor-ui/src/composables/useRunWorkflow.spec.ts b/packages/editor-ui/src/composables/useRunWorkflow.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useRunWorkflow.spec.ts rename to packages/editor-ui/src/composables/useRunWorkflow.test.ts diff --git a/packages/editor-ui/src/composables/useStyles.spec.ts b/packages/editor-ui/src/composables/useStyles.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useStyles.spec.ts rename to packages/editor-ui/src/composables/useStyles.test.ts diff --git a/packages/editor-ui/src/composables/useWorkflowHelpers.spec.ts b/packages/editor-ui/src/composables/useWorkflowHelpers.test.ts similarity index 100% rename from packages/editor-ui/src/composables/useWorkflowHelpers.spec.ts rename to packages/editor-ui/src/composables/useWorkflowHelpers.test.ts diff --git a/packages/editor-ui/src/mixins/workflowHelpers.spec.ts b/packages/editor-ui/src/mixins/workflowHelpers.test.ts similarity index 100% rename from packages/editor-ui/src/mixins/workflowHelpers.spec.ts rename to packages/editor-ui/src/mixins/workflowHelpers.test.ts diff --git a/packages/editor-ui/src/permissions.spec.ts b/packages/editor-ui/src/permissions.test.ts similarity index 100% rename from packages/editor-ui/src/permissions.spec.ts rename to packages/editor-ui/src/permissions.test.ts diff --git a/packages/editor-ui/src/plugins/sentry.spec.ts b/packages/editor-ui/src/plugins/sentry.test.ts similarity index 100% rename from packages/editor-ui/src/plugins/sentry.spec.ts rename to packages/editor-ui/src/plugins/sentry.test.ts diff --git a/packages/editor-ui/src/stores/credentials.spec.ts b/packages/editor-ui/src/stores/credentials.test.ts similarity index 100% rename from packages/editor-ui/src/stores/credentials.spec.ts rename to packages/editor-ui/src/stores/credentials.test.ts diff --git a/packages/editor-ui/src/stores/environments.spec.ts b/packages/editor-ui/src/stores/environments.test.ts similarity index 100% rename from packages/editor-ui/src/stores/environments.spec.ts rename to packages/editor-ui/src/stores/environments.test.ts diff --git a/packages/editor-ui/src/stores/npsStore.store.spec.ts b/packages/editor-ui/src/stores/npsStore.store.test.ts similarity index 100% rename from packages/editor-ui/src/stores/npsStore.store.spec.ts rename to packages/editor-ui/src/stores/npsStore.store.test.ts diff --git a/packages/editor-ui/src/stores/workflows.store.spec.ts b/packages/editor-ui/src/stores/workflows.store.test.ts similarity index 100% rename from packages/editor-ui/src/stores/workflows.store.spec.ts rename to packages/editor-ui/src/stores/workflows.store.test.ts diff --git a/packages/editor-ui/src/utils/apiUtils.spec.ts b/packages/editor-ui/src/utils/apiUtils.test.ts similarity index 100% rename from packages/editor-ui/src/utils/apiUtils.spec.ts rename to packages/editor-ui/src/utils/apiUtils.test.ts diff --git a/packages/editor-ui/src/utils/canvasUtilsV2.spec.ts b/packages/editor-ui/src/utils/canvasUtilsV2.test.ts similarity index 100% rename from packages/editor-ui/src/utils/canvasUtilsV2.spec.ts rename to packages/editor-ui/src/utils/canvasUtilsV2.test.ts diff --git a/packages/editor-ui/src/utils/executionUtils.spec.ts b/packages/editor-ui/src/utils/executionUtils.test.ts similarity index 100% rename from packages/editor-ui/src/utils/executionUtils.spec.ts rename to packages/editor-ui/src/utils/executionUtils.test.ts diff --git a/packages/editor-ui/src/utils/htmlUtils.spec.ts b/packages/editor-ui/src/utils/htmlUtils.test.ts similarity index 100% rename from packages/editor-ui/src/utils/htmlUtils.spec.ts rename to packages/editor-ui/src/utils/htmlUtils.test.ts diff --git a/packages/editor-ui/src/utils/nodeViewUtils.spec.ts b/packages/editor-ui/src/utils/nodeViewUtils.test.ts similarity index 100% rename from packages/editor-ui/src/utils/nodeViewUtils.spec.ts rename to packages/editor-ui/src/utils/nodeViewUtils.test.ts diff --git a/packages/editor-ui/src/views/VariablesView.spec.ts b/packages/editor-ui/src/views/VariablesView.test.ts similarity index 100% rename from packages/editor-ui/src/views/VariablesView.spec.ts rename to packages/editor-ui/src/views/VariablesView.test.ts From ef54760064fa568f61f005c3395bfd2c66e0df23 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Tue, 5 Nov 2024 14:48:51 +0200 Subject: [PATCH 10/53] feat: Upload sourcemaps to Sentry on release (no-changelog) (#11557) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ --- .github/workflows/release-publish.yml | 39 +++++ package.json | 1 - packages/editor-ui/package.json | 1 - packages/editor-ui/vite.config.mts | 18 +-- patches/@sentry__cli@2.36.2.patch | 12 -- pnpm-lock.yaml | 196 +------------------------- 6 files changed, 47 insertions(+), 220 deletions(-) delete mode 100644 patches/@sentry__cli@2.36.2.patch diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index c3548a0cdac..e8d5fdc714f 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -38,6 +38,12 @@ jobs: - name: Build run: pnpm build + - name: Cache build artifacts + uses: actions/cache/save@v4.0.0 + with: + path: ./packages/**/dist + key: ${{ github.sha }}-base:build + - name: Dry-run publishing run: pnpm publish -r --no-git-checks --dry-run @@ -119,6 +125,39 @@ jobs: makeLatest: false body: ${{github.event.pull_request.body}} + create-sentry-release: + name: Create release on Sentry + needs: [publish-to-npm, publish-to-docker-hub] + runs-on: ubuntu-latest + if: github.event.pull_request.merged == true + timeout-minutes: 5 + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + + steps: + - name: Restore cached build artifacts + uses: actions/cache/restore@v4.0.0 + with: + path: ./packages/**/dist + key: ${{ github.sha }}:db-tests + + - name: Create a frontend release + uses: getsentry/action-release@v1.7.0 + continue-on-error: true + with: + projects: ${{ secrets.SENTRY_FRONTEND_PROJECT }} + version: {{ needs.publish-to-npm.outputs.release }} + sourcemaps: packages/editor-ui/dist + + - name: Create a backend release + uses: getsentry/action-release@v1.7.0 + continue-on-error: true + with: + projects: ${{ secrets.SENTRY_BACKEND_PROJECT }} + version: {{ needs.publish-to-npm.outputs.release }} + sourcemaps: packages/cli/dist packages/core/dist packages/nodes-base/dist packages/@n8n/n8n-nodes-langchain/dist + trigger-release-note: name: Trigger a release note needs: [publish-to-npm, create-github-release] diff --git a/package.json b/package.json index 82130f01b48..ffa892d51b2 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,6 @@ }, "patchedDependencies": { "typedi@0.10.0": "patches/typedi@0.10.0.patch", - "@sentry/cli@2.36.2": "patches/@sentry__cli@2.36.2.patch", "pkce-challenge@3.0.0": "patches/pkce-challenge@3.0.0.patch", "pyodide@0.23.4": "patches/pyodide@0.23.4.patch", "@types/express-serve-static-core@4.17.43": "patches/@types__express-serve-static-core@4.17.43.patch", diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index 4243dddc9a7..f6498d6ca5e 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -85,7 +85,6 @@ "@faker-js/faker": "^8.0.2", "@iconify/json": "^2.2.228", "@pinia/testing": "^0.1.6", - "@sentry/vite-plugin": "^2.22.5", "@types/dateformat": "^3.0.0", "@types/file-saver": "^2.0.1", "@types/humanize-duration": "^3.27.1", diff --git a/packages/editor-ui/vite.config.mts b/packages/editor-ui/vite.config.mts index f7d81cc3cff..3a20ff3eea9 100644 --- a/packages/editor-ui/vite.config.mts +++ b/packages/editor-ui/vite.config.mts @@ -1,7 +1,6 @@ import vue from '@vitejs/plugin-vue'; import { resolve } from 'path'; import { defineConfig, mergeConfig } from 'vite'; -import { sentryVitePlugin } from '@sentry/vite-plugin'; import { vitestConfig } from '../design-system/vite.config.mts'; import icons from 'unplugin-icons/vite'; @@ -57,22 +56,7 @@ const plugins = [ vue(), ]; -const { SENTRY_AUTH_TOKEN: authToken, RELEASE: release } = process.env; -if (release && authToken) { - plugins.push( - sentryVitePlugin({ - org: 'n8nio', - project: 'instance-frontend', - // Auth tokens can be obtained from https://sentry.io/settings/account/api/auth-tokens/ - // and needs the `project:releases` and `org:read` scopes - authToken, - telemetry: false, - release: { - name: release, - }, - }), - ); -} +const { RELEASE: release } = process.env; export default mergeConfig( defineConfig({ diff --git a/patches/@sentry__cli@2.36.2.patch b/patches/@sentry__cli@2.36.2.patch deleted file mode 100644 index 04882a4fa05..00000000000 --- a/patches/@sentry__cli@2.36.2.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/js/helper.js b/js/helper.js -index 37798b9444d39a8713327ed12adf3e76f03188a4..08d49b7a5c058c4d29c9929c0c524c85b14b330e 100644 ---- a/js/helper.js -+++ b/js/helper.js -@@ -15,6 +15,7 @@ function getBinaryPath() { - const parts = []; - parts.push(__dirname); - parts.push('..'); -+ parts.push('bin'); - parts.push(`sentry-cli${process.platform === 'win32' ? '.exe' : ''}`); - return path.resolve(...parts); - } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c576185a1b3..2f08b44b133 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -103,9 +103,6 @@ overrides: ws: '>=8.17.1' patchedDependencies: - '@sentry/cli@2.36.2': - hash: saib6xuadkfhahfipsdedqib2i - path: patches/@sentry__cli@2.36.2.patch '@types/express-serve-static-core@4.17.43': hash: 5orrj4qleu2iko5t27vl44u4we path: patches/@types__express-serve-static-core@4.17.43.patch @@ -687,7 +684,7 @@ importers: version: 8.57.0 eslint-config-airbnb-typescript: specifier: ^18.0.0 - version: 18.0.0(@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2))(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + version: 18.0.0(@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2))(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0) eslint-config-prettier: specifier: ^9.1.0 version: 9.1.0(eslint@8.57.0) @@ -1505,9 +1502,6 @@ importers: '@pinia/testing': specifier: ^0.1.6 version: 0.1.6(pinia@2.2.4(typescript@5.6.2)(vue@3.5.11(typescript@5.6.2)))(vue@3.5.11(typescript@5.6.2)) - '@sentry/vite-plugin': - specifier: ^2.22.5 - version: 2.22.5(encoding@0.1.13) '@types/dateformat': specifier: ^3.0.0 version: 3.0.1 @@ -4074,64 +4068,10 @@ packages: resolution: {integrity: sha512-HYa0+rfFmYQ/DadXoiuarTSxrcnYDCd/fm0pFuOHjICtfja8IcLegVYP2/r3CgwB+IjquCtJ5kDcqS/NTgUcpA==} engines: {node: '>=8'} - '@sentry/babel-plugin-component-annotate@2.22.5': - resolution: {integrity: sha512-+93qwB9vTX1nj4hD8AMWowXZsZVkvmP9OwTqSh5d4kOeiJ+dZftUk4+FKeKkAX9lvY2reyHV8Gms5mo67c27RQ==} - engines: {node: '>= 14'} - '@sentry/browser@8.33.1': resolution: {integrity: sha512-c6zI/igexkLwZuGk+u8Rj26ChjxGgkhe6ZbKFsXCYaKAp5ep5X7HQRkkqgbxApiqlC0LduHdd/ymzh139JLg8w==} engines: {node: '>=14.18'} - '@sentry/bundler-plugin-core@2.22.5': - resolution: {integrity: sha512-nfvTthV0aNM9/MwgnCi1WjAlCtau1I4kw6+oZIDOwJRDqGNziz517mYRXSsvCUebtGxDZtPcF7hSEBMSHjpncA==} - engines: {node: '>= 14'} - - '@sentry/cli-darwin@2.36.2': - resolution: {integrity: sha512-To64Pq+pcmecEr+gFXiqaZy8oKhyLQLXO/SVDdf16CUL2qpuahE3bO5h9kFacMxPPxOWcgc2btF+4gYa1+bQTA==} - engines: {node: '>=10'} - os: [darwin] - - '@sentry/cli-linux-arm64@2.36.2': - resolution: {integrity: sha512-g+FFmj1oJ2iRMsfs1ORz6THOO6MiAR55K9YxdZUBvqfoHLjSMt7Jst43sbZ3O0u55hnfixSKLNzDaTGaM/jxIQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux, freebsd] - - '@sentry/cli-linux-arm@2.36.2': - resolution: {integrity: sha512-cRSvOQK97WM0m03k/c+LVAWT042Qz887WP/2Gy64eUi/PfArwb+QZZnsu4FCygxK9jnzgLTo4+ewoJVi17xaLQ==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux, freebsd] - - '@sentry/cli-linux-i686@2.36.2': - resolution: {integrity: sha512-rjxTw/CMd0Q7qlOb7gWFiwn3hJIxNkhbn1bOU54xj9CZvQSCvh10l7l4Y9o8znJLl41c5kMXVq8yuYws9A7AGQ==} - engines: {node: '>=10'} - cpu: [x86, ia32] - os: [linux, freebsd] - - '@sentry/cli-linux-x64@2.36.2': - resolution: {integrity: sha512-cF8IPFTlwiC7JgVvSW4rS99sxb1W1N//iANxuzqaDswUnmJLi0AJy/jES87qE5GRB6ljaPVMvH7Kq0OCp3bvPA==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux, freebsd] - - '@sentry/cli-win32-i686@2.36.2': - resolution: {integrity: sha512-YDH/Kcd8JAo1Bg4jtSwF8dr7FZZ8QbYLMx8q/5eenHpq6VdOgPENsTvayLW3cAjWLcm44u8Ed/gcEK0z1IxQmQ==} - engines: {node: '>=10'} - cpu: [x86, ia32] - os: [win32] - - '@sentry/cli-win32-x64@2.36.2': - resolution: {integrity: sha512-Kac8WPbkFSVAJqPAVRBiW0uij9PVoXo0owf+EDeIIDLs9yxZat0d1xgyQPlUWrCGdxowMSbDvaSUz1YnE7MUmg==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - - '@sentry/cli@2.36.2': - resolution: {integrity: sha512-QoijP9TnO1UVNnRKtH718jlu/F9bBki6ffrOfmcjxkvLT6Q3nBMmqhYNH/AJV/RcgqLd6noWss4fbDMXZLzgIQ==} - engines: {node: '>= 10'} - hasBin: true - '@sentry/core@7.87.0': resolution: {integrity: sha512-jkoXqK/nuYh8DYS+n7uaSuSIdw4HJemyRkXsWjAEPtEgD7taGMafZGbP5pl+XE38SE59jTBxmKnkUEZOFMgZGA==} engines: {node: '>=8'} @@ -4164,10 +4104,6 @@ packages: resolution: {integrity: sha512-uzuYpiiJuFY3N4WNHMBWUQX5oNv2t/TbG0OHRp3Rr7yeu+HSfD542TIp9/gMZ+G0Cxd8AmVO3wkKIFbk0TL4Qg==} engines: {node: '>=14.18'} - '@sentry/vite-plugin@2.22.5': - resolution: {integrity: sha512-dFARM360varU+hdU1MCpl0VTL03FkVIC+A9egCE+ureuOryjVNe3cm2mUjv/gnDHHNTOxWC2H2c8BlOkqTGP/w==} - engines: {node: '>= 14'} - '@sentry/vue@8.33.1': resolution: {integrity: sha512-Ec3Z/KM96PhSdc3NSQUkKRETSipnIy55M35ujGCbdMnlGr95TjmInxVIxQGZap8S0EVzcpGCWFTGlzUR/pmVJQ==} engines: {node: '>=14.18'} @@ -7728,10 +7664,6 @@ packages: engines: {node: '>=12'} deprecated: Glob versions prior to v9 are no longer supported - glob@9.3.2: - resolution: {integrity: sha512-BTv/JhKXFEHsErMte/AnfiSv8yYOLLiyH2lTg8vn02O21zWFgHPTfxtgn1QRe7NRgggUhC8hacR2Re94svHqeA==} - engines: {node: '>=16 || 14 >=14.17'} - global-dirs@3.0.0: resolution: {integrity: sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==} engines: {node: '>=10'} @@ -9062,10 +8994,6 @@ packages: magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} - magic-string@0.30.8: - resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} - engines: {node: '>=12'} - magicast@0.3.5: resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} @@ -9229,10 +9157,6 @@ packages: resolution: {integrity: sha512-CI8wwdrll4ehjPAqs8TL8lBPyNnpZlQI02Wn8C1weNz/QbUbjh3OMxgMKSnvqfKFdLlks3EzHB9tO0BqGc3phQ==} engines: {node: '>=10'} - minimatch@7.4.2: - resolution: {integrity: sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==} - engines: {node: '>=10'} - minimatch@9.0.1: resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} engines: {node: '>=16 || 14 >=14.17'} @@ -9272,10 +9196,6 @@ packages: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} - minipass@4.2.5: - resolution: {integrity: sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==} - engines: {node: '>=8'} - minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} @@ -10304,10 +10224,6 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - prom-client@13.2.0: resolution: {integrity: sha512-wGr5mlNNdRNzEhRYXgboUU2LxHWIojxscJKmtG3R8f4/KiWqyYgXTLHs0+Ted7tG3zFT7pgHJbtomzZ1L0ARaQ==} engines: {node: '>=10'} @@ -11914,9 +11830,6 @@ packages: '@nuxt/kit': optional: true - unplugin@1.0.1: - resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} - unplugin@1.11.0: resolution: {integrity: sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==} engines: {node: '>=14.0.0'} @@ -12247,9 +12160,6 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack-virtual-modules@0.5.0: - resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - webpack-virtual-modules@0.6.1: resolution: {integrity: sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==} @@ -15457,8 +15367,6 @@ snapshots: '@sentry/types': 7.87.0 '@sentry/utils': 7.87.0 - '@sentry/babel-plugin-component-annotate@2.22.5': {} - '@sentry/browser@8.33.1': dependencies: '@sentry-internal/browser-utils': 8.33.1 @@ -15469,60 +15377,6 @@ snapshots: '@sentry/types': 8.33.1 '@sentry/utils': 8.33.1 - '@sentry/bundler-plugin-core@2.22.5(encoding@0.1.13)': - dependencies: - '@babel/core': 7.24.0 - '@sentry/babel-plugin-component-annotate': 2.22.5 - '@sentry/cli': 2.36.2(patch_hash=saib6xuadkfhahfipsdedqib2i)(encoding@0.1.13) - dotenv: 16.3.1 - find-up: 5.0.0 - glob: 9.3.2 - magic-string: 0.30.8 - unplugin: 1.0.1 - transitivePeerDependencies: - - encoding - - supports-color - - '@sentry/cli-darwin@2.36.2': - optional: true - - '@sentry/cli-linux-arm64@2.36.2': - optional: true - - '@sentry/cli-linux-arm@2.36.2': - optional: true - - '@sentry/cli-linux-i686@2.36.2': - optional: true - - '@sentry/cli-linux-x64@2.36.2': - optional: true - - '@sentry/cli-win32-i686@2.36.2': - optional: true - - '@sentry/cli-win32-x64@2.36.2': - optional: true - - '@sentry/cli@2.36.2(patch_hash=saib6xuadkfhahfipsdedqib2i)(encoding@0.1.13)': - dependencies: - https-proxy-agent: 5.0.1 - node-fetch: 2.7.0(encoding@0.1.13) - progress: 2.0.3 - proxy-from-env: 1.1.0 - which: 2.0.2 - optionalDependencies: - '@sentry/cli-darwin': 2.36.2 - '@sentry/cli-linux-arm': 2.36.2 - '@sentry/cli-linux-arm64': 2.36.2 - '@sentry/cli-linux-i686': 2.36.2 - '@sentry/cli-linux-x64': 2.36.2 - '@sentry/cli-win32-i686': 2.36.2 - '@sentry/cli-win32-x64': 2.36.2 - transitivePeerDependencies: - - encoding - - supports-color - '@sentry/core@7.87.0': dependencies: '@sentry/types': 7.87.0 @@ -15562,14 +15416,6 @@ snapshots: dependencies: '@sentry/types': 8.33.1 - '@sentry/vite-plugin@2.22.5(encoding@0.1.13)': - dependencies: - '@sentry/bundler-plugin-core': 2.22.5(encoding@0.1.13) - unplugin: 1.0.1 - transitivePeerDependencies: - - encoding - - supports-color - '@sentry/vue@8.33.1(vue@3.5.11(typescript@5.6.2))': dependencies: '@sentry/browser': 8.33.1 @@ -19354,7 +19200,7 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0): + eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: confusing-browser-globals: 1.0.11 eslint: 8.57.0 @@ -19363,12 +19209,12 @@ snapshots: object.entries: 1.1.5 semver: 7.6.0 - eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2))(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1)(eslint@8.57.0): + eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2))(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: '@typescript-eslint/eslint-plugin': 7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2) '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) eslint: 8.57.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - eslint-plugin-import @@ -19391,7 +19237,7 @@ snapshots: debug: 4.3.4 enhanced-resolve: 5.13.0 eslint: 8.57.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.5.0 @@ -19403,7 +19249,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7(supports-color@5.5.0) optionalDependencies: @@ -19429,7 +19275,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -20183,13 +20029,6 @@ snapshots: minimatch: 5.1.5 once: 1.4.0 - glob@9.3.2: - dependencies: - fs.realpath: 1.0.0 - minimatch: 7.4.2 - minipass: 4.2.5 - path-scurry: 1.11.1 - global-dirs@3.0.0: dependencies: ini: 2.0.0 @@ -21879,10 +21718,6 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.8: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - magicast@0.3.5: dependencies: '@babel/parser': 7.25.6 @@ -22058,10 +21893,6 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimatch@7.4.2: - dependencies: - brace-expansion: 2.0.1 - minimatch@9.0.1: dependencies: brace-expansion: 2.0.1 @@ -22109,8 +21940,6 @@ snapshots: dependencies: yallist: 4.0.0 - minipass@4.2.5: {} - minipass@5.0.0: {} minipass@7.1.2: {} @@ -23403,8 +23232,6 @@ snapshots: process@0.11.10: {} - progress@2.0.3: {} - prom-client@13.2.0: dependencies: tdigest: 0.1.2 @@ -25339,13 +25166,6 @@ snapshots: - rollup - supports-color - unplugin@1.0.1: - dependencies: - acorn: 8.14.0 - chokidar: 4.0.1 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.5.0 - unplugin@1.11.0: dependencies: acorn: 8.14.0 @@ -25690,8 +25510,6 @@ snapshots: webpack-sources@3.2.3: {} - webpack-virtual-modules@0.5.0: {} - webpack-virtual-modules@0.6.1: {} whatwg-encoding@2.0.0: From 463d101f3592e6df4afd66c4d0fde0cb4aec34cc Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Tue, 5 Nov 2024 15:17:41 +0200 Subject: [PATCH 11/53] fix(editor): Fix emitting `n8nReady` notification via `postmessage` on new canvas (#11558) --- packages/editor-ui/src/views/NodeView.v2.vue | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/editor-ui/src/views/NodeView.v2.vue b/packages/editor-ui/src/views/NodeView.v2.vue index 9cd22e3ea31..5d8905be821 100644 --- a/packages/editor-ui/src/views/NodeView.v2.vue +++ b/packages/editor-ui/src/views/NodeView.v2.vue @@ -1276,7 +1276,13 @@ function removeSourceControlEventBindings() { function addPostMessageEventBindings() { window.addEventListener('message', onPostMessageReceived); +} +function removePostMessageEventBindings() { + window.removeEventListener('message', onPostMessageReceived); +} + +function emitPostMessageReady() { if (window.parent) { window.parent.postMessage( JSON.stringify({ command: 'n8nReady', version: rootStore.versionCli }), @@ -1285,10 +1291,6 @@ function addPostMessageEventBindings() { } } -function removePostMessageEventBindings() { - window.removeEventListener('message', onPostMessageReceived); -} - async function onPostMessageReceived(messageEvent: MessageEvent) { if ( !messageEvent || @@ -1516,6 +1518,8 @@ onBeforeMount(() => { if (!isDemoRoute.value) { pushConnectionStore.pushConnect(); } + + addPostMessageEventBindings(); }); onMounted(() => { @@ -1536,6 +1540,8 @@ onMounted(() => { canvasStore.stopLoading(); void externalHooks.run('nodeView.mount').catch(() => {}); + + emitPostMessageReady(); }); void usersStore.showPersonalizationSurvey(); @@ -1544,7 +1550,6 @@ onMounted(() => { }); addSourceControlEventBindings(); - addPostMessageEventBindings(); addWorkflowSavedEventBindings(); addBeforeUnloadEventBindings(); addImportEventBindings(); From dfd785bc0894257eb6e62b0dd8f71248c27aae53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 5 Nov 2024 15:06:23 +0100 Subject: [PATCH 12/53] fix(editor): Do not overwrite the webhookId in the new canvas (#11562) --- packages/editor-ui/src/Interface.ts | 47 +------------- .../composables/useCanvasOperations.test.ts | 65 ++++++++++++++++++- .../src/composables/useCanvasOperations.ts | 3 +- 3 files changed, 66 insertions(+), 49 deletions(-) diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index b6691ac76b5..aec28890705 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -8,7 +8,7 @@ import type { IVersionNotificationSettings, } from '@n8n/api-types'; import type { Scope } from '@n8n/permissions'; -import type { IMenuItem, NodeCreatorTag } from 'n8n-design-system'; +import type { NodeCreatorTag } from 'n8n-design-system'; import type { GenericValue, IConnections, @@ -888,51 +888,6 @@ export interface RootState { export interface NodeMetadataMap { [nodeName: string]: INodeMetadata; } -export interface IRootState { - activeExecutions: IExecutionsCurrentSummaryExtended[]; - activeWorkflows: string[]; - activeActions: string[]; - activeCredentialType: string | null; - baseUrl: string; - defaultLocale: string; - endpointForm: string; - endpointFormTest: string; - endpointFormWaiting: string; - endpointWebhook: string; - endpointWebhookTest: string; - endpointWebhookWaiting: string; - executionId: string | null; - executingNode: string[]; - executionWaitingForWebhook: boolean; - pushConnectionActive: boolean; - saveDataErrorExecution: string; - saveDataSuccessExecution: string; - saveManualExecutions: boolean; - timezone: string; - stateIsDirty: boolean; - executionTimeout: number; - maxExecutionTimeout: number; - versionCli: string; - oauthCallbackUrls: object; - n8nMetadata: object; - workflowExecutionData: IExecutionResponse | null; - workflowExecutionPairedItemMappings: { [itemId: string]: Set }; - lastSelectedNode: string | null; - lastSelectedNodeOutputIndex: number | null; - nodeViewOffsetPosition: XYPosition; - nodeViewMoveInProgress: boolean; - selectedNodes: INodeUi[]; - pushRef: string; - urlBaseEditor: string; - urlBaseWebhook: string; - workflow: IWorkflowDb; - workflowsById: IWorkflowsMap; - sidebarMenuItems: IMenuItem[]; - instanceId: string; - nodeMetadata: NodeMetadataMap; - subworkflowExecutionError: Error | null; - binaryDataMode: string; -} export interface CommunityPackageMap { [name: string]: PublicInstalledPackage; diff --git a/packages/editor-ui/src/composables/useCanvasOperations.test.ts b/packages/editor-ui/src/composables/useCanvasOperations.test.ts index 7128c223fef..9b6a8192382 100644 --- a/packages/editor-ui/src/composables/useCanvasOperations.test.ts +++ b/packages/editor-ui/src/composables/useCanvasOperations.test.ts @@ -1,5 +1,10 @@ import { setActivePinia } from 'pinia'; -import type { IConnection, Workflow } from 'n8n-workflow'; +import type { + IConnection, + INodeTypeDescription, + IWebhookDescription, + Workflow, +} from 'n8n-workflow'; import { NodeConnectionType, NodeHelpers } from 'n8n-workflow'; import { useCanvasOperations } from '@/composables/useCanvasOperations'; import type { CanvasNode } from '@/types'; @@ -23,7 +28,13 @@ import { useCredentialsStore } from '@/stores/credentials.store'; import { waitFor } from '@testing-library/vue'; import { createTestingPinia } from '@pinia/testing'; import { mockedStore } from '@/__tests__/utils'; -import { SET_NODE_TYPE, STICKY_NODE_TYPE, STORES } from '@/constants'; +import { + FORM_TRIGGER_NODE_TYPE, + SET_NODE_TYPE, + STICKY_NODE_TYPE, + STORES, + WEBHOOK_NODE_TYPE, +} from '@/constants'; import type { Connection } from '@vue-flow/core'; import { useClipboard } from '@/composables/useClipboard'; import { createCanvasConnectionHandleString } from '@/utils/canvasUtilsV2'; @@ -1889,6 +1900,56 @@ describe('useCanvasOperations', () => { expect(vi.mocked(useClipboard().copy).mock.calls).toMatchSnapshot(); }); }); + + describe('resolveNodeWebhook', () => { + const nodeTypeDescription = mock({ + webhooks: [mock()], + }); + + it("should set webhookId if it doesn't already exist", () => { + const node = mock({ webhookId: undefined }); + + const { resolveNodeWebhook } = useCanvasOperations({ router }); + resolveNodeWebhook(node, nodeTypeDescription); + + expect(node.webhookId).toBeDefined(); + }); + + it('should not set webhookId if it already exists', () => { + const node = mock({ webhookId: 'random-id' }); + + const { resolveNodeWebhook } = useCanvasOperations({ router }); + resolveNodeWebhook(node, nodeTypeDescription); + + expect(node.webhookId).toBe('random-id'); + }); + + it("should not set webhookId if node description doesn't define any webhooks", () => { + const node = mock({ webhookId: undefined }); + + const { resolveNodeWebhook } = useCanvasOperations({ router }); + resolveNodeWebhook(node, mock({ webhooks: [] })); + + expect(node.webhookId).toBeUndefined(); + }); + + test.each([WEBHOOK_NODE_TYPE, FORM_TRIGGER_NODE_TYPE])( + 'should update the webhook path, if the node type is %s, and the path parameter is empty', + (nodeType) => { + const node = mock({ + webhookId: 'random-id', + type: nodeType, + parameters: { path: '' }, + }); + + const { resolveNodeWebhook } = useCanvasOperations({ router }); + resolveNodeWebhook(node, nodeTypeDescription); + + expect(node.webhookId).toBe('random-id'); + expect(node.parameters.path).toBe('random-id'); + }, + ); + }); }); function buildImportNodes() { diff --git a/packages/editor-ui/src/composables/useCanvasOperations.ts b/packages/editor-ui/src/composables/useCanvasOperations.ts index 27dccaf305a..2d811a539e0 100644 --- a/packages/editor-ui/src/composables/useCanvasOperations.ts +++ b/packages/editor-ui/src/composables/useCanvasOperations.ts @@ -1080,7 +1080,7 @@ export function useCanvasOperations({ router }: { router: ReturnType Date: Tue, 5 Nov 2024 16:47:45 +0100 Subject: [PATCH 13/53] fix(editor): Fix run index input for RunData view in sub-nodes (#11538) --- cypress/e2e/30-langchain.cy.ts | 222 ++++++----- ...n_memory_vector_store_fake_embeddings.json | 347 ++++++++++++++++++ cypress/utils/executions.ts | 3 +- .../editor-ui/src/components/InputPanel.vue | 4 +- .../src/components/NodeDetailsView.vue | 23 ++ .../src/components/RunDataAi/RunDataAi.vue | 7 +- 6 files changed, 516 insertions(+), 90 deletions(-) create mode 100644 cypress/fixtures/In_memory_vector_store_fake_embeddings.json diff --git a/cypress/e2e/30-langchain.cy.ts b/cypress/e2e/30-langchain.cy.ts index e23b7e4da36..fb453816f68 100644 --- a/cypress/e2e/30-langchain.cy.ts +++ b/cypress/e2e/30-langchain.cy.ts @@ -44,6 +44,7 @@ import { openNode, getConnectionBySourceAndTarget, } from '../composables/workflow'; +import { NDV, WorkflowPage } from '../pages'; import { createMockNodeExecutionData, runMockWorkflowExecution } from '../utils'; describe('Langchain Integration', () => { @@ -232,95 +233,96 @@ describe('Langchain Integration', () => { const inputMessage = 'Hello!'; const outputMessage = 'Hi there! How can I assist you today?'; + const runData = [ + createMockNodeExecutionData(MANUAL_CHAT_TRIGGER_NODE_NAME, { + jsonData: { + main: { input: inputMessage }, + }, + }), + createMockNodeExecutionData(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, { + jsonData: { + ai_languageModel: { + response: { + generations: [ + { + text: `{ + "action": "Final Answer", + "action_input": "${outputMessage}" +}`, + message: { + lc: 1, + type: 'constructor', + id: ['langchain', 'schema', 'AIMessage'], + kwargs: { + content: `{ + "action": "Final Answer", + "action_input": "${outputMessage}" +}`, + additional_kwargs: {}, + }, + }, + generationInfo: { finish_reason: 'stop' }, + }, + ], + llmOutput: { + tokenUsage: { + completionTokens: 26, + promptTokens: 519, + totalTokens: 545, + }, + }, + }, + }, + }, + metadata: { + subRun: [{ node: AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, runIndex: 0 }], + }, + inputOverride: { + ai_languageModel: [ + [ + { + json: { + messages: [ + { + lc: 1, + type: 'constructor', + id: ['langchain', 'schema', 'SystemMessage'], + kwargs: { + content: + 'Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist. However, above all else, all responses must adhere to the format of RESPONSE FORMAT INSTRUCTIONS.', + additional_kwargs: {}, + }, + }, + { + lc: 1, + type: 'constructor', + id: ['langchain', 'schema', 'HumanMessage'], + kwargs: { + content: + 'TOOLS\n------\nAssistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are:\n\n\n\nRESPONSE FORMAT INSTRUCTIONS\n----------------------------\n\nOutput a JSON markdown code snippet containing a valid JSON object in one of two formats:\n\n**Option 1:**\nUse this if you want the human to use a tool.\nMarkdown code snippet formatted in the following schema:\n\n```json\n{\n "action": string, // The action to take. Must be one of []\n "action_input": string // The input to the action. May be a stringified object.\n}\n```\n\n**Option #2:**\nUse this if you want to respond directly and conversationally to the human. Markdown code snippet formatted in the following schema:\n\n```json\n{\n "action": "Final Answer",\n "action_input": string // You should put what you want to return to use here and make sure to use valid json newline characters.\n}\n```\n\nFor both options, remember to always include the surrounding markdown code snippet delimiters (begin with "```json" and end with "```")!\n\n\nUSER\'S INPUT\n--------------------\nHere is the user\'s input (remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else):\n\nHello!', + additional_kwargs: {}, + }, + }, + ], + options: { stop: ['Observation:'], promptIndex: 0 }, + }, + }, + ], + ], + }, + }), + createMockNodeExecutionData(AGENT_NODE_NAME, { + jsonData: { + main: { output: 'Hi there! How can I assist you today?' }, + }, + }), + ]; runMockWorkflowExecution({ trigger: () => { sendManualChatMessage(inputMessage); }, - runData: [ - createMockNodeExecutionData(MANUAL_CHAT_TRIGGER_NODE_NAME, { - jsonData: { - main: { input: inputMessage }, - }, - }), - createMockNodeExecutionData(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, { - jsonData: { - ai_languageModel: { - response: { - generations: [ - { - text: `{ - "action": "Final Answer", - "action_input": "${outputMessage}" -}`, - message: { - lc: 1, - type: 'constructor', - id: ['langchain', 'schema', 'AIMessage'], - kwargs: { - content: `{ - "action": "Final Answer", - "action_input": "${outputMessage}" -}`, - additional_kwargs: {}, - }, - }, - generationInfo: { finish_reason: 'stop' }, - }, - ], - llmOutput: { - tokenUsage: { - completionTokens: 26, - promptTokens: 519, - totalTokens: 545, - }, - }, - }, - }, - }, - metadata: { - subRun: [{ node: AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, runIndex: 0 }], - }, - inputOverride: { - ai_languageModel: [ - [ - { - json: { - messages: [ - { - lc: 1, - type: 'constructor', - id: ['langchain', 'schema', 'SystemMessage'], - kwargs: { - content: - 'Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist. However, above all else, all responses must adhere to the format of RESPONSE FORMAT INSTRUCTIONS.', - additional_kwargs: {}, - }, - }, - { - lc: 1, - type: 'constructor', - id: ['langchain', 'schema', 'HumanMessage'], - kwargs: { - content: - 'TOOLS\n------\nAssistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are:\n\n\n\nRESPONSE FORMAT INSTRUCTIONS\n----------------------------\n\nOutput a JSON markdown code snippet containing a valid JSON object in one of two formats:\n\n**Option 1:**\nUse this if you want the human to use a tool.\nMarkdown code snippet formatted in the following schema:\n\n```json\n{\n "action": string, // The action to take. Must be one of []\n "action_input": string // The input to the action. May be a stringified object.\n}\n```\n\n**Option #2:**\nUse this if you want to respond directly and conversationally to the human. Markdown code snippet formatted in the following schema:\n\n```json\n{\n "action": "Final Answer",\n "action_input": string // You should put what you want to return to use here and make sure to use valid json newline characters.\n}\n```\n\nFor both options, remember to always include the surrounding markdown code snippet delimiters (begin with "```json" and end with "```")!\n\n\nUSER\'S INPUT\n--------------------\nHere is the user\'s input (remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else):\n\nHello!', - additional_kwargs: {}, - }, - }, - ], - options: { stop: ['Observation:'], promptIndex: 0 }, - }, - }, - ], - ], - }, - }), - createMockNodeExecutionData(AGENT_NODE_NAME, { - jsonData: { - main: { output: 'Hi there! How can I assist you today?' }, - }, - }), - ], + runData, lastNodeExecuted: AGENT_NODE_NAME, }); @@ -357,4 +359,56 @@ describe('Langchain Integration', () => { getConnectionBySourceAndTarget(CHAT_TRIGGER_NODE_DISPLAY_NAME, AGENT_NODE_NAME).should('exist'); getNodes().should('have.length', 3); }); + it('should render runItems for sub-nodes and allow switching between them', () => { + const workflowPage = new WorkflowPage(); + const ndv = new NDV(); + + cy.visit(workflowPage.url); + cy.createFixtureWorkflow('In_memory_vector_store_fake_embeddings.json'); + workflowPage.actions.zoomToFit(); + + workflowPage.actions.executeNode('Populate VS'); + cy.get('[data-label="25 items"]').should('exist'); + + const assertInputOutputText = (text: string, assertion: 'exist' | 'not.exist') => { + ndv.getters.outputPanel().contains(text).should(assertion); + ndv.getters.inputPanel().contains(text).should(assertion); + }; + + workflowPage.actions.openNode('Character Text Splitter'); + ndv.getters.outputRunSelector().should('exist'); + ndv.getters.inputRunSelector().should('exist'); + ndv.getters.inputRunSelector().find('input').should('include.value', '3 of 3'); + ndv.getters.outputRunSelector().find('input').should('include.value', '3 of 3'); + assertInputOutputText('Kyiv', 'exist'); + assertInputOutputText('Berlin', 'not.exist'); + assertInputOutputText('Prague', 'not.exist'); + + ndv.actions.changeOutputRunSelector('2 of 3'); + assertInputOutputText('Berlin', 'exist'); + assertInputOutputText('Kyiv', 'not.exist'); + assertInputOutputText('Prague', 'not.exist'); + + ndv.actions.changeOutputRunSelector('1 of 3'); + assertInputOutputText('Prague', 'exist'); + assertInputOutputText('Berlin', 'not.exist'); + assertInputOutputText('Kyiv', 'not.exist'); + + ndv.actions.toggleInputRunLinking(); + ndv.actions.changeOutputRunSelector('2 of 3'); + ndv.getters.inputRunSelector().find('input').should('include.value', '1 of 3'); + ndv.getters.outputRunSelector().find('input').should('include.value', '2 of 3'); + ndv.getters.inputPanel().contains('Prague').should('exist'); + ndv.getters.inputPanel().contains('Berlin').should('not.exist'); + + ndv.getters.outputPanel().contains('Berlin').should('exist'); + ndv.getters.outputPanel().contains('Prague').should('not.exist'); + + ndv.actions.toggleInputRunLinking(); + ndv.getters.inputRunSelector().find('input').should('include.value', '1 of 3'); + ndv.getters.outputRunSelector().find('input').should('include.value', '1 of 3'); + assertInputOutputText('Prague', 'exist'); + assertInputOutputText('Berlin', 'not.exist'); + assertInputOutputText('Kyiv', 'not.exist'); + }); }); diff --git a/cypress/fixtures/In_memory_vector_store_fake_embeddings.json b/cypress/fixtures/In_memory_vector_store_fake_embeddings.json new file mode 100644 index 00000000000..1f804bedb34 --- /dev/null +++ b/cypress/fixtures/In_memory_vector_store_fake_embeddings.json @@ -0,0 +1,347 @@ +{ + "name": "fake_embeddings", + "nodes": [ + { + "parameters": {}, + "id": "de3c1210-3be7-49a6-86ef-9435e661f23f", + "name": "When clicking ‘Test workflow’", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [ + 480, + 760 + ] + }, + { + "parameters": { + "jsonMode": "expressionData", + "jsonData": "={{ $('Code').item.json.city }}", + "options": {} + }, + "id": "de3cb132-14ef-426b-ad33-8365a93dd11f", + "name": "Default Data Loader", + "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", + "typeVersion": 1, + "position": [ + 1100, + 900 + ] + }, + { + "parameters": { + "jsCode": "const kyiv = `Kyiv (also Kiev)[a] is the capital and most populous city of Ukraine. It is in north-central Ukraine along the Dnieper River. As of 1 January 2022, its population was 2,952,301,[2] making Kyiv the seventh-most populous city in Europe.[11] Kyiv is an important industrial, scientific, educational, and cultural center in Eastern Europe. It is home to many high-tech industries, higher education institutions, and historical landmarks. The city has an extensive system of public transport and infrastructure, including the Kyiv Metro.\n\nThe city's name is said to derive from the name of Kyi, one of its four legendary founders. During its history, Kyiv, one of the oldest cities in Eastern Europe, passed through several stages of prominence and obscurity. The city probably existed as a commercial center as early as the 5th century. A Slavic settlement on the great trade route between Scandinavia and Constantinople, Kyiv was a tributary of the Khazars,[12] until its capture by the Varangians (Vikings) in the mid-9th century. Under Varangian rule, the city became a capital of Kievan Rus', the first East Slavic state. Completely destroyed during the Mongol invasions in 1240, the city lost most of its influence for the centuries to come. Coming under Lithuania, then Poland and then Russia, the city would grow from a frontier market into an important centre of Orthodox learning in the sixteenth century, and later of industry, commerce, and administration by the nineteenth.[1]\n\nThe city prospered again during the Russian Empire's Industrial Revolution in the late 19th century. In 1918, when the Ukrainian People's Republic declared independence from the Russian Republic after the October Revolution there, Kyiv became its capital. From the end of the Ukrainian-Soviet and Polish-Soviet wars in 1921, Kyiv was a city of the Ukrainian SSR, and made its capital in 1934. The city suffered significant destruction during World War II but quickly recovered in the postwar years, remaining the Soviet Union's third-largest city.\n\nFollowing the collapse of the Soviet Union and Ukrainian independence in 1991, Kyiv remained Ukraine's capital and experienced a steady influx of ethnic Ukrainian migrants from other regions of the country.[13] During the country's transformation to a market economy and electoral democracy, Kyiv has continued to be Ukraine's largest and wealthiest city. Its armament-dependent industrial output fell after the Soviet collapse, adversely affecting science and technology, but new sectors of the economy such as services and finance facilitated Kyiv's growth in salaries and investment, as well as providing continuous funding for the development of housing and urban infrastructure. Kyiv emerged as the most pro-Western region of Ukraine; parties advocating tighter integration with the European Union dominate during elections.`\n\nconst berlin = `Berlin[a] is the capital and largest city of Germany, both by area and by population.[11] Its more than 3.85 million inhabitants[12] make it the European Union's most populous city, as measured by population within city limits.[13] The city is also one of the states of Germany, and is the third smallest state in the country in terms of area. Berlin is surrounded by the state of Brandenburg, and Brandenburg's capital Potsdam is nearby. The urban area of Berlin has a population of over 4.5 million and is therefore the most populous urban area in Germany.[5][14] The Berlin-Brandenburg capital region has around 6.2 million inhabitants and is Germany's second-largest metropolitan region after the Rhine-Ruhr region, and the sixth-biggest metropolitan region by GDP in the European Union.[15]\n\nBerlin was built along the banks of the Spree river, which flows into the Havel in the western borough of Spandau. The city incorporates lakes in the western and southeastern boroughs, the largest of which is Müggelsee. About one-third of the city's area is composed of forests, parks and gardens, rivers, canals, and lakes.[16]\n\nFirst documented in the 13th century[10] and at the crossing of two important historic trade routes,[17] Berlin was designated the capital of the Margraviate of Brandenburg (1417–1701), Kingdom of Prussia (1701–1918), German Empire (1871–1918), Weimar Republic (1919–1933), and Nazi Germany (1933–1945). Berlin has served as a scientific, artistic, and philosophical hub during the Age of Enlightenment, Neoclassicism, and the German revolutions of 1848–1849. During the Gründerzeit, an industrialization-induced economic boom triggered a rapid population increase in Berlin. 1920s Berlin was the third-largest city in the world by population.[18]\n\nAfter World War II and following Berlin's occupation, the city was split into West Berlin and East Berlin, divided by the Berlin Wall.[19] East Berlin was declared the capital of East Germany, while Bonn became the West German capital. Following German reunification in 1990, Berlin once again became the capital of all of Germany. Due to its geographic location and history, Berlin has been called \"the heart of Europe\".[20][21][22]`\n\nconst prague = `Prague (/ˈprɑːɡ/ PRAHG; Czech: Praha [ˈpraɦa] ⓘ)[a] is the capital and largest city of the Czech Republic[9] and the historical capital of Bohemia. Situated on the Vltava river, Prague is home to about 1.4 million people.\n\nPrague is a political, cultural, and economic hub of Central Europe, with a rich history and Romanesque, Gothic, Renaissance and Baroque architectures. It was the capital of the Kingdom of Bohemia and residence of several Holy Roman Emperors, most notably Charles IV (r. 1346–1378) and Rudolf II (r. 1575–1611).[9] It was an important city to the Habsburg monarchy and Austria-Hungary. The city played major roles in the Bohemian and the Protestant Reformations, the Thirty Years' War and in 20th-century history as the capital of Czechoslovakia between the World Wars and the post-war Communist era.[10]\n\nPrague is home to a number of cultural attractions including Prague Castle, Charles Bridge, Old Town Square with the Prague astronomical clock, the Jewish Quarter, Petřín hill and Vyšehrad. Since 1992, the historic center of Prague has been included in the UNESCO list of World Heritage Sites.\n\nThe city has more than ten major museums, along with numerous theatres, galleries, cinemas, and other historical exhibits. An extensive modern public transportation system connects the city. It is home to a wide range of public and private schools, including Charles University in Prague, the oldest university in Central Europe.\n\nPrague is classified as an \"Alpha-\" global city according to GaWC studies.[11] In 2019, the city was ranked as 69th most livable city in the world by Mercer.[12] In the same year, the PICSA Index ranked the city as 13th most livable city in the world.[13] Its rich history makes it a popular tourist destination and as of 2017, the city receives more than 8.5 million international visitors annually. In 2017, Prague was listed as the fifth most visited European city after London, Paris, Rome, and Istanbul.[14]`\n\nreturn [prague, berlin, kyiv].map(i => ({ city: i}))" + }, + "id": "ce9d517e-2dd9-45e4-a566-79bd79cd809b", + "name": "Code", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 740, + 760 + ] + }, + { + "parameters": { + "chunkSize": 300 + }, + "id": "ebe5f3a5-4d90-4a33-bf48-f160f0e83967", + "name": "Character Text Splitter", + "type": "@n8n/n8n-nodes-langchain.textSplitterCharacterTextSplitter", + "typeVersion": 1, + "position": [ + 1100, + 1060 + ] + }, + { + "parameters": { + "code": { + "supplyData": { + "code": "const { FakeEmbeddings } = require('@langchain/core/utils/testing');\n\nreturn new FakeEmbeddings();" + } + }, + "outputs": { + "output": [ + { + "type": "ai_embedding" + } + ] + } + }, + "id": "0eac6c5b-89a9-48a4-bd21-19f2b20c3424", + "name": "Fake Embeddings 3", + "type": "@n8n/n8n-nodes-langchain.code", + "typeVersion": 1, + "position": [ + 660, + 1220 + ] + }, + { + "parameters": { + "mode": "load", + "prompt": "Tester", + "topK": 3 + }, + "id": "8c9b39bf-59d6-4769-98e1-54988d9d6b53", + "name": "Get All VS", + "type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory", + "typeVersion": 1, + "position": [ + 680, + 1080 + ] + }, + { + "parameters": { + "code": { + "supplyData": { + "code": "const { FakeEmbeddings } = require('@langchain/core/utils/testing');\n\nreturn new FakeEmbeddings();" + } + }, + "outputs": { + "output": [ + { + "type": "ai_embedding" + } + ] + } + }, + "id": "e46004ec-baf6-425c-9897-3faec9e29676", + "name": "Fake Embeddings", + "type": "@n8n/n8n-nodes-langchain.code", + "typeVersion": 1, + "position": [ + 920, + 900 + ] + }, + { + "parameters": { + "promptType": "define", + "text": "Just testing", + "options": {} + }, + "id": "b132b323-a813-469c-859b-f1b3ede743a3", + "name": "Question and Answer Chain", + "type": "@n8n/n8n-nodes-langchain.chainRetrievalQa", + "typeVersion": 1.3, + "position": [ + 1680, + 780 + ] + }, + { + "parameters": {}, + "id": "b9c412e5-d739-4c82-9a2e-6c0af0cae8f9", + "name": "Vector Store Retriever", + "type": "@n8n/n8n-nodes-langchain.retrieverVectorStore", + "typeVersion": 1, + "position": [ + 1760, + 920 + ] + }, + { + "parameters": { + "code": { + "supplyData": { + "code": "const { FakeChatModel } = require('@langchain/core/utils/testing');\n\nreturn new FakeChatModel({});" + } + }, + "outputs": { + "output": [ + { + "type": "ai_languageModel" + } + ] + } + }, + "id": "962b4b87-ffd6-4ab8-8776-6e9c0920930a", + "name": "Fake Language Model", + "type": "@n8n/n8n-nodes-langchain.code", + "typeVersion": 1, + "position": [ + 1620, + 920 + ] + }, + { + "parameters": { + "code": { + "supplyData": { + "code": "const { FakeEmbeddings } = require('@langchain/core/utils/testing');\n\nreturn new FakeEmbeddings();" + } + }, + "outputs": { + "output": [ + { + "type": "ai_embedding" + } + ] + } + }, + "id": "c78be34f-6459-4414-86bd-f2670ece129d", + "name": "Fake Embeddings 2", + "type": "@n8n/n8n-nodes-langchain.code", + "typeVersion": 1, + "position": [ + 1700, + 1200 + ] + }, + { + "parameters": {}, + "id": "3cee9727-6b97-477c-8277-e8883a98786d", + "name": "Retriever VS", + "type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory", + "typeVersion": 1, + "position": [ + 1700, + 1060 + ] + }, + { + "parameters": { + "mode": "insert" + }, + "id": "5793ec6b-ac00-4a5d-a79c-ff557143e46b", + "name": "Populate VS", + "type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory", + "typeVersion": 1, + "position": [ + 980, + 760 + ] + } + ], + "pinData": {}, + "connections": { + "When clicking ‘Test workflow’": { + "main": [ + [ + { + "node": "Code", + "type": "main", + "index": 0 + }, + { + "node": "Get All VS", + "type": "main", + "index": 0 + } + ] + ] + }, + "Default Data Loader": { + "ai_document": [ + [ + { + "node": "Populate VS", + "type": "ai_document", + "index": 0 + } + ] + ] + }, + "Code": { + "main": [ + [ + { + "node": "Populate VS", + "type": "main", + "index": 0 + } + ] + ] + }, + "Character Text Splitter": { + "ai_textSplitter": [ + [ + { + "node": "Default Data Loader", + "type": "ai_textSplitter", + "index": 0 + } + ] + ] + }, + "Fake Embeddings 3": { + "ai_embedding": [ + [ + { + "node": "Get All VS", + "type": "ai_embedding", + "index": 0 + } + ] + ] + }, + "Fake Embeddings": { + "ai_embedding": [ + [ + { + "node": "Populate VS", + "type": "ai_embedding", + "index": 0 + } + ] + ] + }, + "Vector Store Retriever": { + "ai_retriever": [ + [ + { + "node": "Question and Answer Chain", + "type": "ai_retriever", + "index": 0 + } + ] + ] + }, + "Fake Language Model": { + "ai_languageModel": [ + [ + { + "node": "Question and Answer Chain", + "type": "ai_languageModel", + "index": 0 + } + ] + ] + }, + "Fake Embeddings 2": { + "ai_embedding": [ + [ + { + "node": "Retriever VS", + "type": "ai_embedding", + "index": 0 + } + ] + ] + }, + "Retriever VS": { + "ai_vectorStore": [ + [ + { + "node": "Vector Store Retriever", + "type": "ai_vectorStore", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "4ad44cc6-d5f7-48af-8455-c3957baba04c", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "27cc9b56542ad45b38725555722c50a1c3fee1670bbb67980558314ee08517c4" + }, + "id": "ZjxsuN0rMHRVCb2c", + "tags": [] +} diff --git a/cypress/utils/executions.ts b/cypress/utils/executions.ts index 0b4814fdc9f..0f429728560 100644 --- a/cypress/utils/executions.ts +++ b/cypress/utils/executions.ts @@ -16,7 +16,7 @@ export function createMockNodeExecutionData( return { [name]: { startTime: new Date().getTime(), - executionTime: 0, + executionTime: 1, executionStatus, data: jsonData ? Object.keys(jsonData).reduce((acc, key) => { @@ -33,6 +33,7 @@ export function createMockNodeExecutionData( }, {} as ITaskDataConnections) : data, source: [null], + inputOverride, ...rest, }, }; diff --git a/packages/editor-ui/src/components/InputPanel.vue b/packages/editor-ui/src/components/InputPanel.vue index a5f5dc96d83..36a191eaecd 100644 --- a/packages/editor-ui/src/components/InputPanel.vue +++ b/packages/editor-ui/src/components/InputPanel.vue @@ -179,7 +179,7 @@ export default defineComponent({ rootNode(): string { const workflow = this.workflow; - const rootNodes = workflow.getChildNodes(this.activeNode?.name ?? '', 'ALL_NON_MAIN'); + const rootNodes = workflow.getChildNodes(this.activeNode?.name ?? '', 'ALL'); return rootNodes[0]; }, @@ -342,7 +342,7 @@ export default defineComponent({ :node="currentNode" :nodes="isMappingMode ? rootNodesParents : parentNodes" :workflow="workflow" - :run-index="runIndex" + :run-index="isMappingMode ? 0 : runIndex" :linked-runs="linkedRuns" :can-link-runs="!mappedNode && canLinkRuns" :too-much-data-title="$locale.baseText('ndv.input.tooMuchData.title')" diff --git a/packages/editor-ui/src/components/NodeDetailsView.vue b/packages/editor-ui/src/components/NodeDetailsView.vue index 8294ff2f24c..8deda08ccf7 100644 --- a/packages/editor-ui/src/components/NodeDetailsView.vue +++ b/packages/editor-ui/src/components/NodeDetailsView.vue @@ -154,6 +154,29 @@ const parentNode = computed(() => { }); const inputNodeName = computed(() => { + const nodeOutputs = + activeNode.value && activeNodeType.value + ? NodeHelpers.getNodeOutputs(props.workflowObject, activeNode.value, activeNodeType.value) + : []; + + const nonMainOutputs = nodeOutputs.filter((output) => { + if (typeof output === 'string') return output !== NodeConnectionType.Main; + + return output.type !== NodeConnectionType.Main; + }); + + const isSubNode = nonMainOutputs.length > 0; + + if (isSubNode && activeNode.value) { + // For sub-nodes, we need to get their connected output node to determine the input + // because sub-nodes use specialized outputs (e.g. NodeConnectionType.AiTool) + // instead of the standard Main output type + const connectedOutputNode = props.workflowObject.getChildNodes( + activeNode.value.name, + 'ALL_NON_MAIN', + )?.[0]; + return connectedOutputNode; + } return selectedInput.value || parentNode.value; }); diff --git a/packages/editor-ui/src/components/RunDataAi/RunDataAi.vue b/packages/editor-ui/src/components/RunDataAi/RunDataAi.vue index aa4cefd1699..4092f098848 100644 --- a/packages/editor-ui/src/components/RunDataAi/RunDataAi.vue +++ b/packages/editor-ui/src/components/RunDataAi/RunDataAi.vue @@ -164,8 +164,9 @@ const aiData = computed(() => { const result: AIResult[] = []; const connectedSubNodes = props.workflow.getParentNodes(props.node.name, 'ALL_NON_MAIN'); const rootNodeResult = workflowsStore.getWorkflowResultDataByNodeName(props.node.name); - const rootNodeStartTime = rootNodeResult?.[0]?.startTime ?? 0; - const rootNodeEndTime = rootNodeStartTime + (rootNodeResult?.[0]?.executionTime ?? 0); + const rootNodeStartTime = rootNodeResult?.[props.runIndex ?? 0]?.startTime ?? 0; + const rootNodeEndTime = + rootNodeStartTime + (rootNodeResult?.[props.runIndex ?? 0]?.executionTime ?? 0); connectedSubNodes.forEach((nodeName) => { const nodeRunData = workflowsStore.getWorkflowResultDataByNodeName(nodeName) ?? []; @@ -193,7 +194,7 @@ const aiData = computed(() => { const currentNodeResult = result.filter((r) => { const startTime = r.data?.metadata?.startTime ?? 0; - return startTime >= rootNodeStartTime && startTime <= rootNodeEndTime; + return startTime >= rootNodeStartTime && startTime < rootNodeEndTime; }); return currentNodeResult; From be05ae36e7790156cb48b317fc254ae46a3b2d8c Mon Sep 17 00:00:00 2001 From: Ivan Atanasov Date: Tue, 5 Nov 2024 17:39:55 +0100 Subject: [PATCH 14/53] fix(editor): Ensure Enter key on Cancel button correctly cancels node rename (#11563) --- .../src/components/NodeTitle.test.ts | 95 +++++++++++++++++++ .../editor-ui/src/components/NodeTitle.vue | 1 + 2 files changed, 96 insertions(+) create mode 100644 packages/editor-ui/src/components/NodeTitle.test.ts diff --git a/packages/editor-ui/src/components/NodeTitle.test.ts b/packages/editor-ui/src/components/NodeTitle.test.ts new file mode 100644 index 00000000000..18650559ac1 --- /dev/null +++ b/packages/editor-ui/src/components/NodeTitle.test.ts @@ -0,0 +1,95 @@ +import { describe, it, expect, vi } from 'vitest'; +import { createComponentRenderer } from '@/__tests__/render'; +import userEvent from '@testing-library/user-event'; +import { fireEvent } from '@testing-library/vue'; + +import NodeTitle from '@/components/NodeTitle.vue'; +import { createTestingPinia } from '@pinia/testing'; + +const renderComponent = createComponentRenderer(NodeTitle); + +describe('NodeTitle', () => { + beforeEach(() => { + createTestingPinia(); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('renders the component', () => { + const { getByTestId } = renderComponent({ + props: { + modelValue: 'Test Node', + }, + }); + expect(getByTestId('node-title-container')).toBeInTheDocument(); + expect(getByTestId('node-rename-input')).toBeInTheDocument(); + }); + + it('displays the node title', () => { + const { getByText } = renderComponent({ + props: { + modelValue: 'My Test Node', + }, + }); + expect(getByText('My Test Node')).toBeInTheDocument(); + }); + + it('shows the edit input when clicked', async () => { + const { getByTestId } = renderComponent({ + props: { + modelValue: 'Test Node', + }, + }); + await userEvent.click(getByTestId('node-title-container')); + expect(getByTestId('node-rename-input')).toHaveValue('Test Node'); + }); + + it('emits update:model-value when renaming', async () => { + const { getByTestId, getByRole, emitted } = renderComponent({ + props: { + modelValue: 'Test Node', + }, + }); + await userEvent.click(getByTestId('node-title-container')); + const renameInput = getByTestId('node-rename-input'); + await userEvent.clear(renameInput); + await userEvent.type(renameInput, 'New Node Name'); + + expect(renameInput).toHaveValue('New Node Name'); + + await userEvent.click(getByRole('button', { name: 'Rename' })); + expect(emitted('update:model-value')).toEqual([['New Node Name']]); + }); + + it('cancels renaming when cancel button is clicked', async () => { + const { getByTestId, getByRole, emitted } = renderComponent({ + props: { + modelValue: 'Test Node', + }, + }); + await userEvent.click(getByTestId('node-title-container')); + await userEvent.click(getByRole('button', { name: 'Cancel' })); + expect(emitted('update:model-value')).toBeUndefined(); + }); + + it('does not call onRename when Enter is pressed on cancel button', async () => { + const { getByTestId, getByRole, emitted } = renderComponent({ + props: { + modelValue: 'Test Node', + }, + }); + await userEvent.click(getByTestId('node-title-container')); + const renameInput = getByTestId('node-rename-input'); + await userEvent.clear(renameInput); + await userEvent.type(renameInput, 'New Node Name'); + + expect(renameInput).toHaveValue('New Node Name'); + + const cancelButton = getByRole('button', { name: 'Cancel' }); + await fireEvent.focus(cancelButton); + await fireEvent.keyDown(cancelButton, { key: 'Enter' }); + expect(emitted('update:model-value')).toBeUndefined(); + }); +}); diff --git a/packages/editor-ui/src/components/NodeTitle.vue b/packages/editor-ui/src/components/NodeTitle.vue index 01324b01281..d0fd1b5c05a 100644 --- a/packages/editor-ui/src/components/NodeTitle.vue +++ b/packages/editor-ui/src/components/NodeTitle.vue @@ -63,6 +63,7 @@ function onRename() { size="small" :label="$locale.baseText('ndv.title.cancel')" @click="editName = false" + @keydown.enter.stop /> Date: Tue, 5 Nov 2024 19:07:01 +0200 Subject: [PATCH 15/53] feat: Add Rapid7 InsightVm credentials (#11462) --- .../Rapid7InsightVmApi.credentials.ts | 61 +++++++++++++++++++ .../credentials/icons/Rapid7InsightVm.svg | 14 +++++ packages/nodes-base/package.json | 1 + 3 files changed, 76 insertions(+) create mode 100644 packages/nodes-base/credentials/Rapid7InsightVmApi.credentials.ts create mode 100644 packages/nodes-base/credentials/icons/Rapid7InsightVm.svg diff --git a/packages/nodes-base/credentials/Rapid7InsightVmApi.credentials.ts b/packages/nodes-base/credentials/Rapid7InsightVmApi.credentials.ts new file mode 100644 index 00000000000..d46675298b3 --- /dev/null +++ b/packages/nodes-base/credentials/Rapid7InsightVmApi.credentials.ts @@ -0,0 +1,61 @@ +import type { + IAuthenticateGeneric, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class Rapid7InsightVmApi implements ICredentialType { + name = 'rapid7InsightVmApi'; + + displayName = 'Rapid7 InsightVm API'; + + documentationUrl = 'Rapid7 InsightVm'; + + icon = { + light: 'file:icons/Rapid7InsightVm.svg', + dark: 'file:icons/Rapid7InsightVm.svg', + } as const; + + httpRequestNode = { + name: 'Rapid7 Insight Vm', + docsUrl: 'https://docs.rapid7.com/', + apiBaseUrlPlaceholder: 'https://insight.rapid7.com/', + }; + + properties: INodeProperties[] = [ + { + displayName: 'URL', + name: 'url', + required: true, + type: 'string', + default: '', + }, + { + displayName: 'API Key', + name: 'apiKey', + required: true, + type: 'string', + typeOptions: { password: true }, + default: '', + }, + ]; + + authenticate: IAuthenticateGeneric = { + type: 'generic', + properties: { + headers: { + 'x-api-key': '={{$credentials.apiKey}}', + Accept: 'application/json', + }, + }, + }; + + test: ICredentialTestRequest = { + request: { + baseURL: '={{$credentials.url}}'.replace(/\/$/, ''), + url: '/validate', + method: 'GET', + }, + }; +} diff --git a/packages/nodes-base/credentials/icons/Rapid7InsightVm.svg b/packages/nodes-base/credentials/icons/Rapid7InsightVm.svg new file mode 100644 index 00000000000..509f8287be7 --- /dev/null +++ b/packages/nodes-base/credentials/icons/Rapid7InsightVm.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index d7c23ff3e02..f04cea20b49 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -286,6 +286,7 @@ "dist/credentials/QuickBooksOAuth2Api.credentials.js", "dist/credentials/RabbitMQ.credentials.js", "dist/credentials/RaindropOAuth2Api.credentials.js", + "dist/credentials/Rapid7InsightVmApi.credentials.js", "dist/credentials/RecordedFutureApi.credentials.js", "dist/credentials/RedditOAuth2Api.credentials.js", "dist/credentials/Redis.credentials.js", From 19d55da4ad84ea2c1a29ae9e3fe47ad16e8fb552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Tue, 5 Nov 2024 18:21:56 +0100 Subject: [PATCH 16/53] test(core): Expand test coverage for pruning (#11567) --- .../@n8n/config/src/configs/logging.config.ts | 1 + packages/cli/src/commands/start.ts | 2 +- .../repositories/execution.repository.ts | 2 +- .../pruning/__tests__/pruning.service.test.ts | 213 ++++++++++++++++++ .../services/{ => pruning}/pruning.service.ts | 44 ++-- .../test/integration/pruning.service.test.ts | 7 +- 6 files changed, 242 insertions(+), 27 deletions(-) create mode 100644 packages/cli/src/services/pruning/__tests__/pruning.service.test.ts rename packages/cli/src/services/{ => pruning}/pruning.service.ts (75%) diff --git a/packages/@n8n/config/src/configs/logging.config.ts b/packages/@n8n/config/src/configs/logging.config.ts index 94e46422236..ef4661c1159 100644 --- a/packages/@n8n/config/src/configs/logging.config.ts +++ b/packages/@n8n/config/src/configs/logging.config.ts @@ -7,6 +7,7 @@ export const LOG_SCOPES = [ 'external-secrets', 'license', 'multi-main-setup', + 'pruning', 'pubsub', 'redis', 'scaling', diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index 041b6a87411..bb8b56d32b4 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -27,7 +27,7 @@ import { Subscriber } from '@/scaling/pubsub/subscriber.service'; import { Server } from '@/server'; import { OrchestrationService } from '@/services/orchestration.service'; import { OwnershipService } from '@/services/ownership.service'; -import { PruningService } from '@/services/pruning.service'; +import { PruningService } from '@/services/pruning/pruning.service'; import { UrlService } from '@/services/url.service'; import { WaitTracker } from '@/wait-tracker'; import { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/databases/repositories/execution.repository.ts b/packages/cli/src/databases/repositories/execution.repository.ts index 39f5e92cad2..3b93d15ca00 100644 --- a/packages/cli/src/databases/repositories/execution.repository.ts +++ b/packages/cli/src/databases/repositories/execution.repository.ts @@ -513,7 +513,7 @@ export class ExecutionRepository extends Repository { .execute(); } - async hardDeleteSoftDeletedExecutions() { + async findSoftDeletedExecutions() { const date = new Date(); date.setHours(date.getHours() - this.globalConfig.pruning.hardDeleteBuffer); diff --git a/packages/cli/src/services/pruning/__tests__/pruning.service.test.ts b/packages/cli/src/services/pruning/__tests__/pruning.service.test.ts new file mode 100644 index 00000000000..5ea26ad540f --- /dev/null +++ b/packages/cli/src/services/pruning/__tests__/pruning.service.test.ts @@ -0,0 +1,213 @@ +import type { GlobalConfig } from '@n8n/config'; +import { mock } from 'jest-mock-extended'; +import type { InstanceSettings } from 'n8n-core'; + +import type { MultiMainSetup } from '@/scaling/multi-main-setup.ee'; +import type { OrchestrationService } from '@/services/orchestration.service'; +import { mockLogger } from '@test/mocking'; + +import { PruningService } from '../pruning.service'; + +describe('PruningService', () => { + describe('init', () => { + it('should start pruning if leader', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: true }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock(), + ); + const startPruningSpy = jest.spyOn(pruningService, 'startPruning'); + + pruningService.init(); + + expect(startPruningSpy).toHaveBeenCalled(); + }); + + it('should not start pruning if follower', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: false }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock(), + ); + const startPruningSpy = jest.spyOn(pruningService, 'startPruning'); + + pruningService.init(); + + expect(startPruningSpy).not.toHaveBeenCalled(); + }); + + it('should register leadership events if multi-main setup is enabled', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: true }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock({ on: jest.fn() }), + }), + mock(), + ); + + pruningService.init(); + + // @ts-expect-error Private method + expect(pruningService.orchestrationService.multiMainSetup.on).toHaveBeenCalledWith( + 'leader-takeover', + expect.any(Function), + ); + + // @ts-expect-error Private method + expect(pruningService.orchestrationService.multiMainSetup.on).toHaveBeenCalledWith( + 'leader-stepdown', + expect.any(Function), + ); + }); + }); + + describe('isEnabled', () => { + it('should return `true` based on config if leader main', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: true, instanceType: 'main' }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock({ pruning: { isEnabled: true } }), + ); + + // @ts-expect-error Private method + const isEnabled = pruningService.isEnabled(); + + expect(isEnabled).toBe(true); + }); + + it('should return `false` based on config if leader main', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: true, instanceType: 'main' }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock({ pruning: { isEnabled: false } }), + ); + + // @ts-expect-error Private method + const isEnabled = pruningService.isEnabled(); + + expect(isEnabled).toBe(false); + }); + + it('should return `false` if non-main even if enabled', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: false, instanceType: 'worker' }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock({ pruning: { isEnabled: true } }), + ); + + // @ts-expect-error Private method + const isEnabled = pruningService.isEnabled(); + + expect(isEnabled).toBe(false); + }); + + it('should return `false` if follower main even if enabled', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: false, isFollower: true, instanceType: 'main' }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock({ pruning: { isEnabled: true }, multiMainSetup: { enabled: true } }), + ); + + // @ts-expect-error Private method + const isEnabled = pruningService.isEnabled(); + + expect(isEnabled).toBe(false); + }); + }); + + describe('startPruning', () => { + it('should not start pruning if service is disabled', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: true, instanceType: 'main' }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock({ pruning: { isEnabled: false } }), + ); + + // @ts-expect-error Private method + const setSoftDeletionInterval = jest.spyOn(pruningService, 'setSoftDeletionInterval'); + + // @ts-expect-error Private method + const scheduleHardDeletion = jest.spyOn(pruningService, 'scheduleHardDeletion'); + + pruningService.startPruning(); + + expect(setSoftDeletionInterval).not.toHaveBeenCalled(); + expect(scheduleHardDeletion).not.toHaveBeenCalled(); + }); + + it('should start pruning if service is enabled', () => { + const pruningService = new PruningService( + mockLogger(), + mock({ isLeader: true, instanceType: 'main' }), + mock(), + mock(), + mock({ + isMultiMainSetupEnabled: true, + multiMainSetup: mock(), + }), + mock({ pruning: { isEnabled: true } }), + ); + + const setSoftDeletionInterval = jest + // @ts-expect-error Private method + .spyOn(pruningService, 'setSoftDeletionInterval') + .mockImplementation(); + + const scheduleHardDeletion = jest + // @ts-expect-error Private method + .spyOn(pruningService, 'scheduleHardDeletion') + .mockImplementation(); + + pruningService.startPruning(); + + expect(setSoftDeletionInterval).toHaveBeenCalled(); + expect(scheduleHardDeletion).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/cli/src/services/pruning.service.ts b/packages/cli/src/services/pruning/pruning.service.ts similarity index 75% rename from packages/cli/src/services/pruning.service.ts rename to packages/cli/src/services/pruning/pruning.service.ts index 943f8d30ca3..7314015091d 100644 --- a/packages/cli/src/services/pruning.service.ts +++ b/packages/cli/src/services/pruning/pruning.service.ts @@ -3,12 +3,12 @@ import { BinaryDataService, InstanceSettings } from 'n8n-core'; import { jsonStringify } from 'n8n-workflow'; import { Service } from 'typedi'; -import { inTest, TIME } from '@/constants'; +import { TIME } from '@/constants'; import { ExecutionRepository } from '@/databases/repositories/execution.repository'; import { OnShutdown } from '@/decorators/on-shutdown'; import { Logger } from '@/logging/logger.service'; -import { OrchestrationService } from './orchestration.service'; +import { OrchestrationService } from '../orchestration.service'; @Service() export class PruningService { @@ -32,7 +32,9 @@ export class PruningService { private readonly binaryDataService: BinaryDataService, private readonly orchestrationService: OrchestrationService, private readonly globalConfig: GlobalConfig, - ) {} + ) { + this.logger = this.logger.scoped('pruning'); + } /** * @important Requires `OrchestrationService` to be initialized. @@ -49,9 +51,9 @@ export class PruningService { } } - private isPruningEnabled() { + private isEnabled() { const { instanceType, isFollower } = this.instanceSettings; - if (!this.globalConfig.pruning.isEnabled || inTest || instanceType !== 'main') { + if (!this.globalConfig.pruning.isEnabled || instanceType !== 'main') { return false; } @@ -66,23 +68,23 @@ export class PruningService { * @important Call this method only after DB migrations have completed. */ startPruning() { - if (!this.isPruningEnabled()) return; + if (!this.isEnabled()) return; if (this.isShuttingDown) { - this.logger.warn('[Pruning] Cannot start pruning while shutting down'); + this.logger.warn('Cannot start pruning while shutting down'); return; } - this.logger.debug('[Pruning] Starting soft-deletion and hard-deletion timers'); + this.logger.debug('Starting soft-deletion and hard-deletion timers'); this.setSoftDeletionInterval(); this.scheduleHardDeletion(); } stopPruning() { - if (!this.isPruningEnabled()) return; + if (!this.isEnabled()) return; - this.logger.debug('[Pruning] Removing soft-deletion and hard-deletion timers'); + this.logger.debug('Removing soft-deletion and hard-deletion timers'); clearInterval(this.softDeletionInterval); clearTimeout(this.hardDeletionTimeout); @@ -96,7 +98,7 @@ export class PruningService { this.rates.softDeletion, ); - this.logger.debug(`[Pruning] Soft-deletion scheduled every ${when}`); + this.logger.debug(`Soft-deletion scheduled every ${when}`); } private scheduleHardDeletion(rateMs = this.rates.hardDeletion) { @@ -113,27 +115,27 @@ export class PruningService { ? error.message : jsonStringify(error, { replaceCircularRefs: true }); - this.logger.error('[Pruning] Failed to hard-delete executions', { errorMessage }); + this.logger.error('Failed to hard-delete executions', { errorMessage }); }); }, rateMs); - this.logger.debug(`[Pruning] Hard-deletion scheduled for next ${when}`); + this.logger.debug(`Hard-deletion scheduled for next ${when}`); } /** * Mark executions as deleted based on age and count, in a pruning cycle. */ async softDeleteOnPruningCycle() { - this.logger.debug('[Pruning] Starting soft-deletion of executions'); + this.logger.debug('Starting soft-deletion of executions'); const result = await this.executionRepository.softDeletePrunableExecutions(); if (result.affected === 0) { - this.logger.debug('[Pruning] Found no executions to soft-delete'); + this.logger.debug('Found no executions to soft-delete'); return; } - this.logger.debug('[Pruning] Soft-deleted executions', { count: result.affected }); + this.logger.debug('Soft-deleted executions', { count: result.affected }); } @OnShutdown() @@ -147,26 +149,26 @@ export class PruningService { * @return Delay in ms after which the next cycle should be started */ private async hardDeleteOnPruningCycle() { - const ids = await this.executionRepository.hardDeleteSoftDeletedExecutions(); + const ids = await this.executionRepository.findSoftDeletedExecutions(); const executionIds = ids.map((o) => o.executionId); if (executionIds.length === 0) { - this.logger.debug('[Pruning] Found no executions to hard-delete'); + this.logger.debug('Found no executions to hard-delete'); return this.rates.hardDeletion; } try { - this.logger.debug('[Pruning] Starting hard-deletion of executions', { executionIds }); + this.logger.debug('Starting hard-deletion of executions', { executionIds }); await this.binaryDataService.deleteMany(ids); await this.executionRepository.deleteByIds(executionIds); - this.logger.debug('[Pruning] Hard-deleted executions', { executionIds }); + this.logger.debug('Hard-deleted executions', { executionIds }); } catch (error) { - this.logger.error('[Pruning] Failed to hard-delete executions', { + this.logger.error('Failed to hard-delete executions', { executionIds, error: error instanceof Error ? error.message : `${error}`, }); diff --git a/packages/cli/test/integration/pruning.service.test.ts b/packages/cli/test/integration/pruning.service.test.ts index 7ade1d3fe5a..76ee1079036 100644 --- a/packages/cli/test/integration/pruning.service.test.ts +++ b/packages/cli/test/integration/pruning.service.test.ts @@ -8,8 +8,7 @@ import { TIME } from '@/constants'; import type { ExecutionEntity } from '@/databases/entities/execution-entity'; import type { WorkflowEntity } from '@/databases/entities/workflow-entity'; import { ExecutionRepository } from '@/databases/repositories/execution.repository'; -import { Logger } from '@/logging/logger.service'; -import { PruningService } from '@/services/pruning.service'; +import { PruningService } from '@/services/pruning/pruning.service'; import { annotateExecution, @@ -18,7 +17,7 @@ import { } from './shared/db/executions'; import { createWorkflow } from './shared/db/workflows'; import * as testDb from './shared/test-db'; -import { mockInstance } from '../shared/mocking'; +import { mockInstance, mockLogger } from '../shared/mocking'; describe('softDeleteOnPruningCycle()', () => { let pruningService: PruningService; @@ -35,7 +34,7 @@ describe('softDeleteOnPruningCycle()', () => { globalConfig = Container.get(GlobalConfig); pruningService = new PruningService( - mockInstance(Logger), + mockLogger(), instanceSettings, Container.get(ExecutionRepository), mockInstance(BinaryDataService), From 2ed4ce3d7abe8b15f7b2bef0663a3dbbcb601f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 5 Nov 2024 19:16:03 +0100 Subject: [PATCH 17/53] refactor(editor): Convert TagsView to composition API (no-changelog) (#11566) --- .../TagsManager/TagsView/TagsView.vue | 321 +++++++++--------- 1 file changed, 158 insertions(+), 163 deletions(-) diff --git a/packages/editor-ui/src/components/TagsManager/TagsView/TagsView.vue b/packages/editor-ui/src/components/TagsManager/TagsView/TagsView.vue index e3d0342afc1..9a75eb61f17 100644 --- a/packages/editor-ui/src/components/TagsManager/TagsView/TagsView.vue +++ b/packages/editor-ui/src/components/TagsManager/TagsView/TagsView.vue @@ -1,181 +1,176 @@ -