n8cn / packages /cli /src /execution-lifecycle /__tests__ /save-execution-progress.test.ts
gallyga's picture
Add n8n Chinese version
aec3094
import { Logger } from '@n8n/backend-common';
import type { IExecutionResponse } from '@n8n/db';
import { ExecutionRepository } from '@n8n/db';
import { mock } from 'jest-mock-extended';
import { ErrorReporter } from 'n8n-core';
import type { IRunExecutionData, ITaskData } from 'n8n-workflow';
import { mockInstance } from '@test/mocking';
import { saveExecutionProgress } from '../save-execution-progress';
describe('saveExecutionProgress', () => {
mockInstance(Logger);
const errorReporter = mockInstance(ErrorReporter);
const executionRepository = mockInstance(ExecutionRepository);
afterEach(() => {
jest.resetAllMocks();
});
const workflowId = 'some-workflow-id';
const executionId = 'some-execution-id';
const nodeName = 'My Node';
const taskData = mock<ITaskData>();
const runExecutionData = mock<IRunExecutionData>();
const commonArgs = [workflowId, executionId, nodeName, taskData, runExecutionData] as const;
test('should not try to update non-existent executions', async () => {
executionRepository.findSingleExecution.mockResolvedValue(undefined);
await saveExecutionProgress(...commonArgs);
expect(executionRepository.updateExistingExecution).not.toHaveBeenCalled();
});
test('should handle DB errors on execution lookup', async () => {
const error = new Error('Something went wrong');
executionRepository.findSingleExecution.mockImplementation(() => {
throw error;
});
await saveExecutionProgress(...commonArgs);
expect(executionRepository.updateExistingExecution).not.toHaveBeenCalled();
expect(errorReporter.error).toHaveBeenCalledWith(error);
});
test('should handle DB errors when updating the execution', async () => {
const error = new Error('Something went wrong');
executionRepository.findSingleExecution.mockResolvedValue({} as IExecutionResponse);
executionRepository.updateExistingExecution.mockImplementation(() => {
throw error;
});
await saveExecutionProgress(...commonArgs);
expect(executionRepository.findSingleExecution).toHaveBeenCalled();
expect(executionRepository.updateExistingExecution).toHaveBeenCalled();
expect(errorReporter.error).toHaveBeenCalledWith(error);
});
test('should not try to update finished executions', async () => {
executionRepository.findSingleExecution.mockResolvedValue(
mock<IExecutionResponse>({
finished: true,
}),
);
await saveExecutionProgress(...commonArgs);
expect(executionRepository.updateExistingExecution).not.toHaveBeenCalled();
});
test('should populate `.data` when it is missing', async () => {
const fullExecutionData = {} as IExecutionResponse;
executionRepository.findSingleExecution.mockResolvedValue(fullExecutionData);
await saveExecutionProgress(...commonArgs);
expect(fullExecutionData).toEqual({
data: {
executionData: runExecutionData.executionData,
resultData: {
lastNodeExecuted: nodeName,
runData: {
[nodeName]: [taskData],
},
},
startData: {},
},
status: 'running',
});
expect(executionRepository.updateExistingExecution).toHaveBeenCalledWith(
executionId,
fullExecutionData,
);
expect(errorReporter.error).not.toHaveBeenCalled();
});
test('should augment `.data` if it already exists', async () => {
const fullExecutionData = {
data: {
startData: {},
resultData: {
runData: {
[nodeName]: [{}],
},
},
},
} as unknown as IExecutionResponse;
executionRepository.findSingleExecution.mockResolvedValue(fullExecutionData);
await saveExecutionProgress(...commonArgs);
expect(fullExecutionData).toEqual({
data: {
executionData: runExecutionData.executionData,
resultData: {
lastNodeExecuted: nodeName,
runData: {
[nodeName]: [{}, taskData],
},
},
startData: {},
},
status: 'running',
});
expect(executionRepository.updateExistingExecution).toHaveBeenCalledWith(
executionId,
fullExecutionData,
);
});
test('should set last executed node correctly', async () => {
const fullExecutionData = {
data: {
resultData: {
lastNodeExecuted: 'Another Node',
runData: {},
},
},
} as unknown as IExecutionResponse;
executionRepository.findSingleExecution.mockResolvedValue(fullExecutionData);
await saveExecutionProgress(...commonArgs);
expect(fullExecutionData.data.resultData.lastNodeExecuted).toEqual(nodeName);
});
});