refactor(core): Use DI for WorkflowRunner (no-changelog) (#8372)
This commit is contained in:
committed by
GitHub
parent
bf11c7c1bd
commit
c70fa66e76
@@ -1,5 +1,4 @@
|
||||
import { Container } from 'typedi';
|
||||
|
||||
import { NodeApiError, NodeOperationError, Workflow } from 'n8n-workflow';
|
||||
import type { IWebhookData, WorkflowActivateMode } from 'n8n-workflow';
|
||||
|
||||
@@ -12,20 +11,20 @@ import { SecretsHelper } from '@/SecretsHelpers';
|
||||
import { WebhookService } from '@/services/webhook.service';
|
||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
||||
import * as AdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||
import { WorkflowRunner } from '@/WorkflowRunner';
|
||||
import type { User } from '@db/entities/User';
|
||||
import type { WebhookEntity } from '@db/entities/WebhookEntity';
|
||||
import { NodeTypes } from '@/NodeTypes';
|
||||
import { chooseRandomly } from './shared/random';
|
||||
import { OrchestrationService } from '@/services/orchestration.service';
|
||||
import { ExecutionService } from '@/executions/execution.service';
|
||||
import { WorkflowService } from '@/workflows/workflow.service';
|
||||
import { ActiveWorkflowsService } from '@/services/activeWorkflows.service';
|
||||
|
||||
import { mockInstance } from '../shared/mocking';
|
||||
import { chooseRandomly } from './shared/random';
|
||||
import { setSchedulerAsLoadedNode } from './shared/utils';
|
||||
import * as testDb from './shared/testDb';
|
||||
import { createOwner } from './shared/db/users';
|
||||
import { createWorkflow } from './shared/db/workflows';
|
||||
import { ExecutionService } from '@/executions/execution.service';
|
||||
import { WorkflowService } from '@/workflows/workflow.service';
|
||||
import { ActiveWorkflowsService } from '@/services/activeWorkflows.service';
|
||||
|
||||
mockInstance(ActiveExecutions);
|
||||
mockInstance(Push);
|
||||
@@ -182,26 +181,6 @@ describe('isActive()', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('runWorkflow()', () => {
|
||||
test('should call `WorkflowRunner.run()`', async () => {
|
||||
const workflow = await createWorkflow({ active: true }, owner);
|
||||
|
||||
await activeWorkflowRunner.init();
|
||||
|
||||
const additionalData = await AdditionalData.getBase('fake-user-id');
|
||||
|
||||
const runSpy = jest
|
||||
.spyOn(WorkflowRunner.prototype, 'run')
|
||||
.mockResolvedValue('fake-execution-id');
|
||||
|
||||
const [node] = workflow.nodes;
|
||||
|
||||
await activeWorkflowRunner.runWorkflow(workflow, node, [[]], additionalData, 'trigger');
|
||||
|
||||
expect(runSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('executeErrorWorkflow()', () => {
|
||||
test('should call `WorkflowExecuteAdditionalData.executeErrorWorkflow()`', async () => {
|
||||
const workflow = await createWorkflow({ active: true }, owner);
|
||||
|
||||
@@ -4,7 +4,6 @@ import type { SuperAgentTest } from 'supertest';
|
||||
import type { InstalledPackages } from '@db/entities/InstalledPackages';
|
||||
import type { InstalledNodes } from '@db/entities/InstalledNodes';
|
||||
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
||||
import { Push } from '@/push';
|
||||
import { CommunityPackagesService } from '@/services/communityPackages.service';
|
||||
|
||||
import { mockInstance } from '../shared/mocking';
|
||||
@@ -16,7 +15,6 @@ const communityPackagesService = mockInstance(CommunityPackagesService, {
|
||||
hasMissingPackages: false,
|
||||
});
|
||||
mockInstance(LoadNodesAndCredentials);
|
||||
mockInstance(Push);
|
||||
|
||||
const testServer = setupTestServer({ endpointGroups: ['community-packages'] });
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import type { User } from '@db/entities/User';
|
||||
import { Push } from '@/push';
|
||||
import { EnterpriseExecutionsService } from '@/executions/execution.service.ee';
|
||||
import { WaitTracker } from '@/WaitTracker';
|
||||
|
||||
import { createSuccessfulExecution, getAllExecutions } from './shared/db/executions';
|
||||
import { createOwner } from './shared/db/users';
|
||||
import { createWorkflow } from './shared/db/workflows';
|
||||
import * as testDb from './shared/testDb';
|
||||
import { setupTestServer } from './shared/utils';
|
||||
import { mockInstance } from '../shared/mocking';
|
||||
import { EnterpriseExecutionsService } from '@/executions/execution.service.ee';
|
||||
|
||||
mockInstance(EnterpriseExecutionsService);
|
||||
mockInstance(WaitTracker);
|
||||
|
||||
mockInstance(Push);
|
||||
let testServer = setupTestServer({ endpointGroups: ['executions'] });
|
||||
|
||||
let owner: User;
|
||||
|
||||
@@ -7,7 +7,6 @@ import type { User } from '@db/entities/User';
|
||||
import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository';
|
||||
import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository';
|
||||
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
|
||||
import { Push } from '@/push';
|
||||
import { ExecutionService } from '@/executions/execution.service';
|
||||
|
||||
import { randomApiKey } from '../shared/random';
|
||||
@@ -27,7 +26,6 @@ let workflowRunner: ActiveWorkflowRunner;
|
||||
const testServer = utils.setupTestServer({ endpointGroups: ['publicApi'] });
|
||||
const license = testServer.license;
|
||||
|
||||
mockInstance(Push);
|
||||
mockInstance(ExecutionService);
|
||||
|
||||
beforeAll(async () => {
|
||||
|
||||
@@ -11,14 +11,15 @@ import { v4 as uuid } from 'uuid';
|
||||
|
||||
import config from '@/config';
|
||||
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
import { AUTH_COOKIE_NAME } from '@/constants';
|
||||
|
||||
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
||||
import { SettingsRepository } from '@db/repositories/settings.repository';
|
||||
import { mockNodeTypesData } from '../../../unit/Helpers';
|
||||
import { OrchestrationService } from '@/services/orchestration.service';
|
||||
import { mockInstance } from '../../../shared/mocking';
|
||||
import { AUTH_COOKIE_NAME } from '@/constants';
|
||||
import { ExecutionService } from '@/executions/execution.service';
|
||||
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
||||
import { Push } from '@/push';
|
||||
import { OrchestrationService } from '@/services/orchestration.service';
|
||||
|
||||
import { mockNodeTypesData } from '../../../unit/Helpers';
|
||||
import { mockInstance } from '../../../shared/mocking';
|
||||
|
||||
export { setupTestServer } from './testServer';
|
||||
|
||||
@@ -30,6 +31,7 @@ export { setupTestServer } from './testServer';
|
||||
* Initialize node types.
|
||||
*/
|
||||
export async function initActiveWorkflowRunner() {
|
||||
mockInstance(Push);
|
||||
mockInstance(OrchestrationService);
|
||||
|
||||
mockInstance(ExecutionService);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { issueJWT } from '@/auth/jwt';
|
||||
import { registerController } from '@/decorators';
|
||||
import { rawBodyReader, bodyParser, setupAuthMiddlewares } from '@/middlewares';
|
||||
import { PostHogClient } from '@/posthog';
|
||||
import { Push } from '@/push';
|
||||
import { License } from '@/License';
|
||||
import { Logger } from '@/Logger';
|
||||
import { InternalHooks } from '@/InternalHooks';
|
||||
@@ -78,6 +79,7 @@ export const setupTestServer = ({
|
||||
mockInstance(Logger);
|
||||
mockInstance(InternalHooks);
|
||||
mockInstance(PostHogClient);
|
||||
mockInstance(Push);
|
||||
|
||||
const testServer: TestServer = {
|
||||
app,
|
||||
|
||||
@@ -6,7 +6,6 @@ import type { INode } from 'n8n-workflow';
|
||||
import type { User } from '@db/entities/User';
|
||||
import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository';
|
||||
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
|
||||
import { Push } from '@/push';
|
||||
import { WorkflowSharingService } from '@/workflows/workflowSharing.service';
|
||||
|
||||
import { mockInstance } from '../../shared/mocking';
|
||||
@@ -30,7 +29,6 @@ let authAnotherMemberAgent: SuperAgentTest;
|
||||
let saveCredential: SaveCredentialFunction;
|
||||
|
||||
const activeWorkflowRunner = mockInstance(ActiveWorkflowRunner);
|
||||
mockInstance(Push);
|
||||
|
||||
const sharingSpy = jest.spyOn(License.prototype, 'isSharingEnabled').mockReturnValue(true);
|
||||
const testServer = utils.setupTestServer({
|
||||
|
||||
@@ -9,7 +9,6 @@ import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
import type { ListQuery } from '@/requests';
|
||||
import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository';
|
||||
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
|
||||
import { Push } from '@/push';
|
||||
import { EnterpriseWorkflowService } from '@/workflows/workflow.service.ee';
|
||||
|
||||
import { mockInstance } from '../../shared/mocking';
|
||||
@@ -34,7 +33,6 @@ const license = testServer.license;
|
||||
const { objectContaining, arrayContaining, any } = expect;
|
||||
|
||||
const activeWorkflowRunnerLike = mockInstance(ActiveWorkflowRunner);
|
||||
mockInstance(Push);
|
||||
|
||||
beforeAll(async () => {
|
||||
owner = await createOwner();
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { ActiveExecutions } from '@/ActiveExecutions';
|
||||
import PCancelable from 'p-cancelable';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Container } from 'typedi';
|
||||
import type { IExecuteResponsePromiseData, IRun } from 'n8n-workflow';
|
||||
import { createDeferredPromise } from 'n8n-workflow';
|
||||
import type { IWorkflowExecutionDataProcess } from '@/Interfaces';
|
||||
import { ExecutionRepository } from '@db/repositories/execution.repository';
|
||||
import type { ExecutionRepository } from '@db/repositories/execution.repository';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
|
||||
const FAKE_EXECUTION_ID = '15';
|
||||
@@ -14,7 +13,7 @@ const FAKE_SECOND_EXECUTION_ID = '20';
|
||||
const updateExistingExecution = jest.fn();
|
||||
const createNewExecution = jest.fn(async () => FAKE_EXECUTION_ID);
|
||||
|
||||
Container.set(ExecutionRepository, {
|
||||
const executionRepository = mock<ExecutionRepository>({
|
||||
updateExistingExecution,
|
||||
createNewExecution,
|
||||
});
|
||||
@@ -23,7 +22,7 @@ describe('ActiveExecutions', () => {
|
||||
let activeExecutions: ActiveExecutions;
|
||||
|
||||
beforeEach(() => {
|
||||
activeExecutions = new ActiveExecutions(mock());
|
||||
activeExecutions = new ActiveExecutions(mock(), executionRepository);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -21,7 +21,7 @@ describe('WaitTracker', () => {
|
||||
it('should query DB for waiting executions', async () => {
|
||||
executionRepository.getWaitingExecutions.mockResolvedValue([execution]);
|
||||
|
||||
new WaitTracker(mock(), executionRepository, mock());
|
||||
new WaitTracker(mock(), executionRepository, mock(), mock());
|
||||
|
||||
expect(executionRepository.getWaitingExecutions).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
@@ -29,7 +29,7 @@ describe('WaitTracker', () => {
|
||||
it('if no executions to start, should do nothing', () => {
|
||||
executionRepository.getWaitingExecutions.mockResolvedValue([]);
|
||||
|
||||
new WaitTracker(mock(), executionRepository, mock());
|
||||
new WaitTracker(mock(), executionRepository, mock(), mock());
|
||||
|
||||
expect(executionRepository.findSingleExecution).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -37,7 +37,7 @@ describe('WaitTracker', () => {
|
||||
describe('if execution to start', () => {
|
||||
it('if not enough time passed, should not start execution', async () => {
|
||||
executionRepository.getWaitingExecutions.mockResolvedValue([execution]);
|
||||
const waitTracker = new WaitTracker(mock(), executionRepository, mock());
|
||||
const waitTracker = new WaitTracker(mock(), executionRepository, mock(), mock());
|
||||
|
||||
executionRepository.getWaitingExecutions.mockResolvedValue([execution]);
|
||||
await waitTracker.getWaitingExecutions();
|
||||
@@ -51,7 +51,7 @@ describe('WaitTracker', () => {
|
||||
|
||||
it('if enough time passed, should start execution', async () => {
|
||||
executionRepository.getWaitingExecutions.mockResolvedValue([]);
|
||||
const waitTracker = new WaitTracker(mock(), executionRepository, mock());
|
||||
const waitTracker = new WaitTracker(mock(), executionRepository, mock(), mock());
|
||||
|
||||
executionRepository.getWaitingExecutions.mockResolvedValue([execution]);
|
||||
await waitTracker.getWaitingExecutions();
|
||||
@@ -68,7 +68,7 @@ describe('WaitTracker', () => {
|
||||
describe('startExecution()', () => {
|
||||
it('should query for execution to start', async () => {
|
||||
executionRepository.getWaitingExecutions.mockResolvedValue([]);
|
||||
const waitTracker = new WaitTracker(mock(), executionRepository, mock());
|
||||
const waitTracker = new WaitTracker(mock(), executionRepository, mock(), mock());
|
||||
|
||||
executionRepository.findSingleExecution.mockResolvedValue(execution);
|
||||
waitTracker.startExecution(execution.id);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import Container from 'typedi';
|
||||
import { WorkflowHooks, type ExecutionError, type IWorkflowExecuteHooks } from 'n8n-workflow';
|
||||
import type { User } from '@db/entities/User';
|
||||
import { WorkflowRunner } from '@/WorkflowRunner';
|
||||
import { WorkflowHooks, type ExecutionError, type IWorkflowExecuteHooks } from 'n8n-workflow';
|
||||
import { Push } from '@/push';
|
||||
import Container from 'typedi';
|
||||
import config from '@/config';
|
||||
|
||||
import { mockInstance } from '../shared/mocking';
|
||||
import * as testDb from '../integration/shared/testDb';
|
||||
import { setupTestServer } from '../integration/shared/utils';
|
||||
import { createUser } from '../integration/shared/db/users';
|
||||
@@ -26,10 +24,7 @@ const watchedWorkflowExecuteAfter = jest.spyOn(watchers, 'workflowExecuteAfter')
|
||||
beforeAll(async () => {
|
||||
owner = await createUser({ role: 'global:owner' });
|
||||
|
||||
mockInstance(Push);
|
||||
Container.set(Push, new Push());
|
||||
|
||||
runner = new WorkflowRunner();
|
||||
runner = Container.get(WorkflowRunner);
|
||||
|
||||
hookFunctions = {
|
||||
workflowExecuteAfter: [watchers.workflowExecuteAfter],
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import type { INode } from 'n8n-workflow';
|
||||
import { WorkflowExecutionService } from '@/workflows/workflowExecution.service';
|
||||
import type { IWorkflowDb } from '@/Interfaces';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
|
||||
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||
import type { IWorkflowDb } from '@/Interfaces';
|
||||
import { WorkflowExecutionService } from '@/workflows/workflowExecution.service';
|
||||
import type { WorkflowRunner } from '@/WorkflowRunner';
|
||||
|
||||
const webhookNode: INode = {
|
||||
name: 'Webhook',
|
||||
type: 'n8n-nodes-base.webhook',
|
||||
@@ -47,17 +50,28 @@ const hackerNewsNode: INode = {
|
||||
};
|
||||
|
||||
describe('WorkflowExecutionService', () => {
|
||||
let workflowExecutionService: WorkflowExecutionService;
|
||||
const workflowRunner = mock<WorkflowRunner>();
|
||||
const workflowExecutionService = new WorkflowExecutionService(
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
workflowRunner,
|
||||
);
|
||||
|
||||
beforeAll(() => {
|
||||
workflowExecutionService = new WorkflowExecutionService(
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
mock(),
|
||||
);
|
||||
describe('runWorkflow()', () => {
|
||||
test('should call `WorkflowRunner.run()`', async () => {
|
||||
const node = mock<INode>();
|
||||
const workflow = mock<WorkflowEntity>({ active: true, nodes: [node] });
|
||||
|
||||
workflowRunner.run.mockResolvedValue('fake-execution-id');
|
||||
|
||||
await workflowExecutionService.runWorkflow(workflow, node, [[]], mock(), 'trigger');
|
||||
|
||||
expect(workflowRunner.run).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectPinnedActivatorStarter()', () => {
|
||||
|
||||
Reference in New Issue
Block a user