mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-04 02:37:46 +02:00
chore(core): Migrate task-runner from Jest to Vitest (no-changelog) (#31481)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dbe395202b
commit
2e683ffc0f
|
|
@ -1,5 +0,0 @@
|
|||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
...require('../../../jest.config'),
|
||||
testTimeout: 10_000,
|
||||
};
|
||||
|
|
@ -10,9 +10,9 @@
|
|||
"build": "tsc -p ./tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
||||
"format": "biome format --write src",
|
||||
"format:check": "biome ci src",
|
||||
"test": "jest",
|
||||
"test:unit": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test": "vitest run",
|
||||
"test:unit": "vitest run",
|
||||
"test:dev": "vitest --silent=false",
|
||||
"lint": "eslint . --quiet",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\""
|
||||
|
|
@ -51,6 +51,10 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@n8n/typescript-config": "workspace:*",
|
||||
"@types/lodash": "catalog:"
|
||||
"@n8n/vitest-config": "workspace:*",
|
||||
"@types/lodash": "catalog:",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"vitest": "catalog:",
|
||||
"vitest-mock-extended": "catalog:"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ErrorEvent } from '@sentry/core';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { ErrorReporter } from 'n8n-core';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
|
||||
import { TaskRunnerSentry } from '../task-runner-sentry';
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ describe('TaskRunnerSentry', () => {
|
|||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('filterOutUserCodeErrors', () => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { mock } from 'jest-mock-extended';
|
||||
import type {
|
||||
IExecuteData,
|
||||
INode,
|
||||
INodeExecutionData,
|
||||
ITaskDataConnectionsSource,
|
||||
} from 'n8n-workflow';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
|
||||
import type { DataRequestResponse, InputDataChunkDefinition } from '@/runner-types';
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ describe('DataRequestResponseReconstruct', () => {
|
|||
|
||||
const result = reconstruct.reconstructConnectionInputItems(inputData, chunk);
|
||||
|
||||
expect(result).toEqual([undefined, undefined, { json: { key: 'chunked' } }, undefined]);
|
||||
expect(result).toEqual([undefined, undefined, { json: { key: 'chunked' } }]);
|
||||
});
|
||||
|
||||
it('should handle empty input data gracefully', () => {
|
||||
|
|
|
|||
|
|
@ -19,14 +19,17 @@ export class DataRequestResponseReconstruct {
|
|||
return inputItems;
|
||||
}
|
||||
|
||||
// Only a chunk of the input items was requested. We reconstruct
|
||||
// the array by filling in the missing items with `undefined`.
|
||||
// Only a chunk of the input items was requested (the sender slices the data down to
|
||||
// the chunk). We reconstruct the array by prefixing the chunk with `undefined` for the
|
||||
// items before `startIndex`, so the chunk items land at their original indices —
|
||||
// WorkflowDataProxy addresses items by position. Items after the chunk are never
|
||||
// iterated, and the original total length isn't recoverable from the chunk, so we
|
||||
// don't pad the tail.
|
||||
let sparseInputItems: Array<INodeExecutionData | undefined> = [];
|
||||
|
||||
sparseInputItems = sparseInputItems
|
||||
.concat(Array.from({ length: chunk.startIndex }))
|
||||
.concat(inputItems)
|
||||
.concat(Array.from({ length: inputItems.length - chunk.startIndex - chunk.count }));
|
||||
.concat(inputItems);
|
||||
|
||||
return sparseInputItems;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import {
|
|||
wrapIntoJson,
|
||||
} from './test-data';
|
||||
|
||||
jest.mock('ws');
|
||||
vi.mock('ws');
|
||||
|
||||
const defaultConfig = new MainConfig();
|
||||
defaultConfig.jsRunnerConfig ??= {
|
||||
|
|
@ -78,12 +78,12 @@ describe('JsTaskRunner', () => {
|
|||
taskData: DataRequestResponse;
|
||||
runner?: JsTaskRunner;
|
||||
}) => {
|
||||
jest.spyOn(runner, 'requestData').mockResolvedValue(taskData);
|
||||
vi.spyOn(runner, 'requestData').mockResolvedValue(taskData);
|
||||
return await runner.executeTask(task, new AbortController().signal);
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
const executeForAllItems = async ({
|
||||
|
|
@ -236,7 +236,7 @@ describe('JsTaskRunner', () => {
|
|||
test.each<[CodeExecutionMode]>([['runOnceForAllItems'], ['runOnceForEachItem']])(
|
||||
'should make an rpc call for console log in %s mode',
|
||||
async (nodeMode) => {
|
||||
jest.spyOn(defaultTaskRunner, 'makeRpcCall').mockResolvedValue(undefined);
|
||||
vi.spyOn(defaultTaskRunner, 'makeRpcCall').mockResolvedValue(undefined);
|
||||
const task = newTaskParamsWithSettings({
|
||||
code: "console.log('Hello', 'world!'); return {}",
|
||||
nodeMode,
|
||||
|
|
@ -302,7 +302,7 @@ describe('JsTaskRunner', () => {
|
|||
});
|
||||
|
||||
it('should log the context object as [[ExecutionContext]]', async () => {
|
||||
const rpcCallSpy = jest.spyOn(defaultTaskRunner, 'makeRpcCall').mockResolvedValue(undefined);
|
||||
const rpcCallSpy = vi.spyOn(defaultTaskRunner, 'makeRpcCall').mockResolvedValue(undefined);
|
||||
|
||||
const task = newTaskParamsWithSettings({
|
||||
code: `
|
||||
|
|
@ -777,7 +777,7 @@ describe('JsTaskRunner', () => {
|
|||
for (const group of groups) {
|
||||
it(`${group.method} for runOnceForAllItems`, async () => {
|
||||
// Arrange
|
||||
const rpcCallSpy = jest
|
||||
const rpcCallSpy = vi
|
||||
.spyOn(defaultTaskRunner, 'makeRpcCall')
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
|
|
@ -799,7 +799,7 @@ describe('JsTaskRunner', () => {
|
|||
|
||||
it(`${group.method} for runOnceForEachItem`, async () => {
|
||||
// Arrange
|
||||
const rpcCallSpy = jest
|
||||
const rpcCallSpy = vi
|
||||
.spyOn(defaultTaskRunner, 'makeRpcCall')
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
|
|
@ -1347,11 +1347,11 @@ describe('JsTaskRunner', () => {
|
|||
};
|
||||
runner.runningTasks.set(taskId, task);
|
||||
|
||||
const sendSpy = jest.spyOn(runner.ws, 'send').mockImplementation(() => {});
|
||||
jest.spyOn(runner, 'sendOffers').mockImplementation(() => {});
|
||||
jest
|
||||
.spyOn(runner, 'requestData')
|
||||
.mockResolvedValue(newDataRequestResponse([wrapIntoJson({ a: 1 })]));
|
||||
const sendSpy = vi.spyOn(runner.ws, 'send').mockImplementation(() => {});
|
||||
vi.spyOn(runner, 'sendOffers').mockImplementation(() => {});
|
||||
vi.spyOn(runner, 'requestData').mockResolvedValue(
|
||||
newDataRequestResponse([wrapIntoJson({ a: 1 })]),
|
||||
);
|
||||
|
||||
await runner.receivedSettings(taskId, taskSettings);
|
||||
|
||||
|
|
@ -1374,22 +1374,22 @@ describe('JsTaskRunner', () => {
|
|||
|
||||
describe('idle timeout', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should set idle timer when instantiated', () => {
|
||||
const idleTimeout = 5;
|
||||
const runner = createRunnerWithOpts({}, { idleTimeout });
|
||||
const emitSpy = jest.spyOn(runner, 'emit');
|
||||
const emitSpy = vi.spyOn(runner, 'emit');
|
||||
|
||||
jest.advanceTimersByTime(idleTimeout * 1000 - 100);
|
||||
vi.advanceTimersByTime(idleTimeout * 1000 - 100);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
|
||||
jest.advanceTimersByTime(idleTimeout * 1000);
|
||||
vi.advanceTimersByTime(idleTimeout * 1000);
|
||||
expect(emitSpy).toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
});
|
||||
|
||||
|
|
@ -1398,9 +1398,9 @@ describe('JsTaskRunner', () => {
|
|||
const runner = createRunnerWithOpts({}, { idleTimeout });
|
||||
const taskId = '123';
|
||||
const offerId = 'offer123';
|
||||
const emitSpy = jest.spyOn(runner, 'emit');
|
||||
const emitSpy = vi.spyOn(runner, 'emit');
|
||||
|
||||
jest.advanceTimersByTime(idleTimeout * 1000 - 100);
|
||||
vi.advanceTimersByTime(idleTimeout * 1000 - 100);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
|
||||
runner.openOffers.set(offerId, {
|
||||
|
|
@ -1409,12 +1409,12 @@ describe('JsTaskRunner', () => {
|
|||
});
|
||||
runner.offerAccepted(offerId, taskId);
|
||||
|
||||
jest.advanceTimersByTime(200);
|
||||
vi.advanceTimersByTime(200);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith('runner:reached-idle-timeout'); // because timer was reset
|
||||
|
||||
runner.runningTasks.clear();
|
||||
|
||||
jest.advanceTimersByTime(idleTimeout * 1000);
|
||||
vi.advanceTimersByTime(idleTimeout * 1000);
|
||||
expect(emitSpy).toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
});
|
||||
|
||||
|
|
@ -1422,28 +1422,28 @@ describe('JsTaskRunner', () => {
|
|||
const idleTimeout = 5;
|
||||
const runner = createRunnerWithOpts({}, { idleTimeout });
|
||||
const taskId = '123';
|
||||
const emitSpy = jest.spyOn(runner, 'emit');
|
||||
jest.spyOn(runner, 'executeTask').mockResolvedValue({ result: [] });
|
||||
const emitSpy = vi.spyOn(runner, 'emit');
|
||||
vi.spyOn(runner, 'executeTask').mockResolvedValue({ result: [] });
|
||||
|
||||
runner.runningTasks.set(taskId, newTaskState(taskId));
|
||||
|
||||
jest.advanceTimersByTime(idleTimeout * 1000 - 100);
|
||||
vi.advanceTimersByTime(idleTimeout * 1000 - 100);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
|
||||
await runner.receivedSettings(taskId, {});
|
||||
|
||||
jest.advanceTimersByTime(200);
|
||||
vi.advanceTimersByTime(200);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith('runner:reached-idle-timeout'); // because timer was reset
|
||||
|
||||
jest.advanceTimersByTime(idleTimeout * 1000);
|
||||
vi.advanceTimersByTime(idleTimeout * 1000);
|
||||
expect(emitSpy).toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
});
|
||||
|
||||
it('should never reach idle timeout if idle timeout is set to 0', () => {
|
||||
const runner = createRunnerWithOpts({}, { idleTimeout: 0 });
|
||||
const emitSpy = jest.spyOn(runner, 'emit');
|
||||
const emitSpy = vi.spyOn(runner, 'emit');
|
||||
|
||||
jest.advanceTimersByTime(999999);
|
||||
vi.advanceTimersByTime(999999);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
});
|
||||
|
||||
|
|
@ -1451,12 +1451,12 @@ describe('JsTaskRunner', () => {
|
|||
const idleTimeout = 5;
|
||||
const runner = createRunnerWithOpts({}, { idleTimeout });
|
||||
const taskId = '123';
|
||||
const emitSpy = jest.spyOn(runner, 'emit');
|
||||
const emitSpy = vi.spyOn(runner, 'emit');
|
||||
const task = newTaskState(taskId);
|
||||
|
||||
runner.runningTasks.set(taskId, task);
|
||||
|
||||
jest.advanceTimersByTime(idleTimeout * 1000);
|
||||
vi.advanceTimersByTime(idleTimeout * 1000);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith('runner:reached-idle-timeout');
|
||||
task.cleanup();
|
||||
});
|
||||
|
|
@ -1764,11 +1764,11 @@ describe('JsTaskRunner', () => {
|
|||
};
|
||||
runner.runningTasks.set(taskId, task);
|
||||
|
||||
const sendSpy = jest.spyOn(runner.ws, 'send').mockImplementation(() => {});
|
||||
jest.spyOn(runner, 'sendOffers').mockImplementation(() => {});
|
||||
jest
|
||||
.spyOn(runner, 'requestData')
|
||||
.mockResolvedValue(newDataRequestResponse([wrapIntoJson({ a: 1 })]));
|
||||
const sendSpy = vi.spyOn(runner.ws, 'send').mockImplementation(() => {});
|
||||
vi.spyOn(runner, 'sendOffers').mockImplementation(() => {});
|
||||
vi.spyOn(runner, 'requestData').mockResolvedValue(
|
||||
newDataRequestResponse([wrapIntoJson({ a: 1 })]),
|
||||
);
|
||||
|
||||
await runner.receivedSettings(taskId, taskSettings);
|
||||
|
||||
|
|
@ -1817,7 +1817,7 @@ describe('JsTaskRunner', () => {
|
|||
});
|
||||
|
||||
// runCode mode doesn't fetch data, so we can pass empty response
|
||||
jest.spyOn(runner, 'requestData').mockResolvedValue(newDataRequestResponse([]));
|
||||
vi.spyOn(runner, 'requestData').mockResolvedValue(newDataRequestResponse([]));
|
||||
|
||||
return await runner.executeTask(task, new AbortController().signal);
|
||||
};
|
||||
|
|
@ -1958,7 +1958,7 @@ describe('JsTaskRunner', () => {
|
|||
|
||||
describe('console methods', () => {
|
||||
it('should allow console.log without making RPC calls', async () => {
|
||||
const rpcSpy = jest.spyOn(defaultTaskRunner, 'makeRpcCall');
|
||||
const rpcSpy = vi.spyOn(defaultTaskRunner, 'makeRpcCall');
|
||||
|
||||
const outcome = await executeRunCode({
|
||||
code: `
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import type { Mock, MockInstance } from 'vitest';
|
||||
import { WebSocket } from 'ws';
|
||||
|
||||
import { newTaskState } from '@/js-task-runner/__tests__/test-data';
|
||||
|
|
@ -7,7 +8,7 @@ import type { TaskStatus } from '@/task-state';
|
|||
|
||||
class TestRunner extends TaskRunner {}
|
||||
|
||||
jest.mock('ws');
|
||||
vi.mock('ws');
|
||||
|
||||
describe('TestRunner', () => {
|
||||
let runner: TestRunner;
|
||||
|
|
@ -36,7 +37,7 @@ describe('TestRunner', () => {
|
|||
|
||||
describe('constructor', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should correctly construct WebSocket URI with provided taskBrokerUri', () => {
|
||||
|
|
@ -82,11 +83,11 @@ describe('TestRunner', () => {
|
|||
|
||||
describe('sendOffers', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllTimers();
|
||||
vi.clearAllTimers();
|
||||
});
|
||||
|
||||
it('should not send offers if canSendOffers is false', () => {
|
||||
|
|
@ -94,7 +95,7 @@ describe('TestRunner', () => {
|
|||
taskType: 'test-task',
|
||||
maxConcurrency: 2,
|
||||
});
|
||||
const sendSpy = jest.spyOn(runner, 'send');
|
||||
const sendSpy = vi.spyOn(runner, 'send');
|
||||
expect(runner.canSendOffers).toBe(false);
|
||||
|
||||
runner.sendOffers();
|
||||
|
|
@ -123,7 +124,7 @@ describe('TestRunner', () => {
|
|||
type: 'broker:runnerregistered',
|
||||
});
|
||||
|
||||
const sendSpy = jest.spyOn(runner, 'send');
|
||||
const sendSpy = vi.spyOn(runner, 'send');
|
||||
|
||||
runner.sendOffers();
|
||||
runner.sendOffers();
|
||||
|
|
@ -159,7 +160,7 @@ describe('TestRunner', () => {
|
|||
});
|
||||
const taskState = newTaskState('test-task');
|
||||
runner.runningTasks.set('test-task', taskState);
|
||||
const sendSpy = jest.spyOn(runner, 'send');
|
||||
const sendSpy = vi.spyOn(runner, 'send');
|
||||
|
||||
runner.sendOffers();
|
||||
|
||||
|
|
@ -186,13 +187,13 @@ describe('TestRunner', () => {
|
|||
type: 'broker:runnerregistered',
|
||||
});
|
||||
|
||||
const sendSpy = jest.spyOn(runner, 'send');
|
||||
const sendSpy = vi.spyOn(runner, 'send');
|
||||
|
||||
runner.sendOffers();
|
||||
expect(sendSpy).toHaveBeenCalledTimes(2);
|
||||
sendSpy.mockClear();
|
||||
|
||||
jest.advanceTimersByTime(6000);
|
||||
vi.advanceTimersByTime(6000);
|
||||
runner.sendOffers();
|
||||
expect(sendSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
|
@ -222,7 +223,7 @@ describe('TestRunner', () => {
|
|||
|
||||
const taskId = 'test-task';
|
||||
const task = newTaskState(taskId);
|
||||
const taskCleanupSpy = jest.spyOn(task, 'cleanup');
|
||||
const taskCleanupSpy = vi.spyOn(task, 'cleanup');
|
||||
runner.runningTasks.set(taskId, task);
|
||||
|
||||
await runner.taskCancelled(taskId, 'test-reason');
|
||||
|
|
@ -239,20 +240,20 @@ describe('TestRunner', () => {
|
|||
task.status = 'running';
|
||||
runner.runningTasks.set(taskId, task);
|
||||
|
||||
const dataRequestReject = jest.fn();
|
||||
const nodeTypesRequestReject = jest.fn();
|
||||
const dataRequestReject = vi.fn();
|
||||
const nodeTypesRequestReject = vi.fn();
|
||||
|
||||
runner.dataRequests.set('data-req', {
|
||||
taskId,
|
||||
requestId: 'data-req',
|
||||
resolve: jest.fn(),
|
||||
resolve: vi.fn(),
|
||||
reject: dataRequestReject,
|
||||
});
|
||||
|
||||
runner.nodeTypesRequests.set('node-req', {
|
||||
taskId,
|
||||
requestId: 'node-req',
|
||||
resolve: jest.fn(),
|
||||
resolve: vi.fn(),
|
||||
reject: nodeTypesRequestReject,
|
||||
});
|
||||
|
||||
|
|
@ -283,7 +284,7 @@ describe('TestRunner', () => {
|
|||
const task = newTaskState(taskId);
|
||||
task.status = 'waitingForSettings';
|
||||
runner.runningTasks.set(taskId, task);
|
||||
const sendSpy = jest.spyOn(runner, 'send');
|
||||
const sendSpy = vi.spyOn(runner, 'send');
|
||||
|
||||
await runner.taskTimedOut(taskId);
|
||||
|
||||
|
|
@ -303,20 +304,20 @@ describe('TestRunner', () => {
|
|||
task.status = 'running';
|
||||
runner.runningTasks.set(taskId, task);
|
||||
|
||||
const dataRequestReject = jest.fn();
|
||||
const nodeTypesRequestReject = jest.fn();
|
||||
const dataRequestReject = vi.fn();
|
||||
const nodeTypesRequestReject = vi.fn();
|
||||
|
||||
runner.dataRequests.set('data-req', {
|
||||
taskId,
|
||||
requestId: 'data-req',
|
||||
resolve: jest.fn(),
|
||||
resolve: vi.fn(),
|
||||
reject: dataRequestReject,
|
||||
});
|
||||
|
||||
runner.nodeTypesRequests.set('node-req', {
|
||||
taskId,
|
||||
requestId: 'node-req',
|
||||
resolve: jest.fn(),
|
||||
resolve: vi.fn(),
|
||||
reject: nodeTypesRequestReject,
|
||||
});
|
||||
|
||||
|
|
@ -349,7 +350,7 @@ describe('TestRunner', () => {
|
|||
|
||||
void runner.stop();
|
||||
|
||||
const sendSpy = jest.spyOn(runner, 'send');
|
||||
const sendSpy = vi.spyOn(runner, 'send');
|
||||
|
||||
runner.offerAccepted(offerId, 'task-1');
|
||||
|
||||
|
|
@ -387,10 +388,10 @@ describe('TestRunner', () => {
|
|||
});
|
||||
|
||||
describe('connection close', () => {
|
||||
let processExitSpy: jest.SpyInstance;
|
||||
let processExitSpy: MockInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
processExitSpy = jest.spyOn(process, 'exit').mockImplementation(() => undefined as never);
|
||||
processExitSpy = vi.spyOn(process, 'exit').mockImplementation(() => undefined as never);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -401,8 +402,8 @@ describe('TestRunner', () => {
|
|||
runner = newTestRunner();
|
||||
|
||||
// Get the close handler that was registered
|
||||
const closeHandler = (runner.ws.addEventListener as jest.Mock).mock.calls.find(
|
||||
([event]: [string]) => event === 'close',
|
||||
const closeHandler = (runner.ws.addEventListener as unknown as Mock).mock.calls.find(
|
||||
([event]: unknown[]) => event === 'close',
|
||||
)?.[1] as () => void;
|
||||
expect(closeHandler).toBeDefined();
|
||||
|
||||
|
|
@ -415,8 +416,8 @@ describe('TestRunner', () => {
|
|||
runner = newTestRunner();
|
||||
|
||||
// Get the close handler registered via addEventListener in constructor
|
||||
const closeHandler = (runner.ws.addEventListener as jest.Mock).mock.calls.find(
|
||||
([event]: [string]) => event === 'close',
|
||||
const closeHandler = (runner.ws.addEventListener as unknown as Mock).mock.calls.find(
|
||||
([event]: unknown[]) => event === 'close',
|
||||
)?.[1] as () => void;
|
||||
expect(closeHandler).toBeDefined();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"types": ["node", "vitest/globals"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
|
|
|
|||
19
packages/@n8n/task-runner/vite.config.ts
Normal file
19
packages/@n8n/task-runner/vite.config.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { createVitestConfigWithDecorators } from '@n8n/vitest-config/node-decorators';
|
||||
import path from 'node:path';
|
||||
import { mergeConfig } from 'vite';
|
||||
|
||||
export default mergeConfig(
|
||||
createVitestConfigWithDecorators({
|
||||
// The n8n root jest.config sets `restoreMocks: true`, and test files silently rely on
|
||||
// it — omit this and mocks bleed between tests.
|
||||
restoreMocks: true,
|
||||
testTimeout: 10_000,
|
||||
}),
|
||||
{
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
@ -2684,9 +2684,21 @@ importers:
|
|||
'@n8n/typescript-config':
|
||||
specifier: workspace:*
|
||||
version: link:../typescript-config
|
||||
'@n8n/vitest-config':
|
||||
specifier: workspace:*
|
||||
version: link:../vitest-config
|
||||
'@types/lodash':
|
||||
specifier: 'catalog:'
|
||||
version: 4.17.17
|
||||
'@vitest/coverage-v8':
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.1(vitest@4.1.1)
|
||||
vitest:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.1(@opentelemetry/api@1.9.0)(@types/node@20.19.21)(@vitest/browser-playwright@4.0.16)(jsdom@23.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(vite@8.0.2(@types/node@20.19.21)(esbuild@0.25.10)(jiti@2.6.1)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.16.1)(tsx@4.19.3)(yaml@2.8.3))
|
||||
vitest-mock-extended:
|
||||
specifier: 'catalog:'
|
||||
version: 3.1.0(typescript@6.0.2)(vitest@4.1.1(@opentelemetry/api@1.9.0)(@types/node@20.19.21)(jsdom@23.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(vite@8.0.2(@types/node@20.19.21)(esbuild@0.25.10)(jiti@2.6.1)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.16.1)(tsx@4.19.3)(yaml@2.8.3)))
|
||||
|
||||
packages/@n8n/tournament:
|
||||
dependencies:
|
||||
|
|
@ -24632,7 +24644,7 @@ snapshots:
|
|||
'@currents/commit-info': 1.0.1-beta.0
|
||||
async-retry: 1.3.3
|
||||
axios: 1.16.1(debug@4.4.3)
|
||||
axios-retry: 4.5.0(axios@1.16.1(debug@4.4.3))
|
||||
axios-retry: 4.5.0(axios@1.16.1)
|
||||
chalk: 4.1.2
|
||||
commander: 13.1.0
|
||||
date-fns: 2.30.0
|
||||
|
|
@ -28022,7 +28034,7 @@ snapshots:
|
|||
'@rudderstack/rudder-sdk-node@3.0.5':
|
||||
dependencies:
|
||||
axios: 1.16.1(debug@4.4.3)
|
||||
axios-retry: 4.5.0(axios@1.16.1(debug@4.4.3))
|
||||
axios-retry: 4.5.0(axios@1.16.1)
|
||||
component-type: 2.0.0
|
||||
join-component: 1.1.0
|
||||
lodash.clonedeep: 4.5.0
|
||||
|
|
@ -31190,7 +31202,7 @@ snapshots:
|
|||
|
||||
axe-core@4.7.2: {}
|
||||
|
||||
axios-retry@4.5.0(axios@1.16.1(debug@4.4.3)):
|
||||
axios-retry@4.5.0(axios@1.16.1):
|
||||
dependencies:
|
||||
axios: 1.16.1(debug@4.4.3)
|
||||
is-retry-allowed: 2.2.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user