test(core): Move unit tests closer to testable components (no-changelog) (#10287)
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||
import { ExecutionsController } from '@/executions/executions.controller';
|
||||
import type { ExecutionRequest, ExecutionSummaries } from '@/executions/execution.types';
|
||||
import type { ExecutionService } from '@/executions/execution.service';
|
||||
import type { WorkflowSharingService } from '@/workflows/workflowSharing.service';
|
||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
|
||||
describe('ExecutionsController', () => {
|
||||
const executionService = mock<ExecutionService>();
|
||||
const workflowSharingService = mock<WorkflowSharingService>();
|
||||
|
||||
const executionsController = new ExecutionsController(
|
||||
executionService,
|
||||
mock(),
|
||||
workflowSharingService,
|
||||
mock(),
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('getOne', () => {
|
||||
it('should 400 when execution is not a number', async () => {
|
||||
const req = mock<ExecutionRequest.GetOne>({ params: { id: 'test' } });
|
||||
|
||||
await expect(executionsController.getOne(req)).rejects.toThrow(BadRequestError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMany', () => {
|
||||
const NO_EXECUTIONS = { count: 0, estimated: false, results: [] };
|
||||
|
||||
const QUERIES_WITH_EITHER_STATUS_OR_RANGE: ExecutionSummaries.RangeQuery[] = [
|
||||
{
|
||||
kind: 'range',
|
||||
workflowId: undefined,
|
||||
status: undefined,
|
||||
range: { lastId: '999', firstId: '111', limit: 20 },
|
||||
},
|
||||
{
|
||||
kind: 'range',
|
||||
workflowId: undefined,
|
||||
status: [],
|
||||
range: { lastId: '999', firstId: '111', limit: 20 },
|
||||
},
|
||||
{
|
||||
kind: 'range',
|
||||
workflowId: undefined,
|
||||
status: ['waiting'],
|
||||
range: { lastId: undefined, firstId: undefined, limit: 20 },
|
||||
},
|
||||
{
|
||||
kind: 'range',
|
||||
workflowId: undefined,
|
||||
status: [],
|
||||
range: { lastId: '999', firstId: '111', limit: 20 },
|
||||
},
|
||||
];
|
||||
|
||||
const QUERIES_NEITHER_STATUS_NOR_RANGE_PROVIDED: ExecutionSummaries.RangeQuery[] = [
|
||||
{
|
||||
kind: 'range',
|
||||
workflowId: undefined,
|
||||
status: undefined,
|
||||
range: { lastId: undefined, firstId: undefined, limit: 20 },
|
||||
},
|
||||
{
|
||||
kind: 'range',
|
||||
workflowId: undefined,
|
||||
status: [],
|
||||
range: { lastId: undefined, firstId: undefined, limit: 20 },
|
||||
},
|
||||
];
|
||||
|
||||
describe('if either status or range provided', () => {
|
||||
test.each(QUERIES_WITH_EITHER_STATUS_OR_RANGE)(
|
||||
'should fetch executions per query',
|
||||
async (rangeQuery) => {
|
||||
workflowSharingService.getSharedWorkflowIds.mockResolvedValue(['123']);
|
||||
executionService.findLatestCurrentAndCompleted.mockResolvedValue(NO_EXECUTIONS);
|
||||
|
||||
const req = mock<ExecutionRequest.GetMany>({ rangeQuery });
|
||||
|
||||
await executionsController.getMany(req);
|
||||
|
||||
expect(executionService.findLatestCurrentAndCompleted).not.toHaveBeenCalled();
|
||||
expect(executionService.findRangeWithCount).toHaveBeenCalledWith(rangeQuery);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('if neither status nor range provided', () => {
|
||||
test.each(QUERIES_NEITHER_STATUS_NOR_RANGE_PROVIDED)(
|
||||
'should fetch executions per query',
|
||||
async (rangeQuery) => {
|
||||
workflowSharingService.getSharedWorkflowIds.mockResolvedValue(['123']);
|
||||
executionService.findLatestCurrentAndCompleted.mockResolvedValue(NO_EXECUTIONS);
|
||||
|
||||
const req = mock<ExecutionRequest.GetMany>({ rangeQuery });
|
||||
|
||||
await executionsController.getMany(req);
|
||||
|
||||
expect(executionService.findLatestCurrentAndCompleted).toHaveBeenCalled();
|
||||
expect(executionService.findRangeWithCount).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('if both status and range provided', () => {
|
||||
it('should fetch executions per query', async () => {
|
||||
workflowSharingService.getSharedWorkflowIds.mockResolvedValue(['123']);
|
||||
executionService.findLatestCurrentAndCompleted.mockResolvedValue(NO_EXECUTIONS);
|
||||
|
||||
const rangeQuery: ExecutionSummaries.RangeQuery = {
|
||||
kind: 'range',
|
||||
workflowId: undefined,
|
||||
status: ['success'],
|
||||
range: { lastId: '999', firstId: '111', limit: 5 },
|
||||
};
|
||||
|
||||
const req = mock<ExecutionRequest.GetMany>({ rangeQuery });
|
||||
|
||||
await executionsController.getMany(req);
|
||||
|
||||
expect(executionService.findLatestCurrentAndCompleted).not.toHaveBeenCalled();
|
||||
expect(executionService.findRangeWithCount).toHaveBeenCalledWith(rangeQuery);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('stop', () => {
|
||||
const executionId = '999';
|
||||
const req = mock<ExecutionRequest.Stop>({ params: { id: executionId } });
|
||||
|
||||
it('should 404 when execution is inaccessible for user', async () => {
|
||||
workflowSharingService.getSharedWorkflowIds.mockResolvedValue([]);
|
||||
|
||||
const promise = executionsController.stop(req);
|
||||
|
||||
await expect(promise).rejects.toThrow(NotFoundError);
|
||||
expect(executionService.stop).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call ask for an execution to be stopped', async () => {
|
||||
workflowSharingService.getSharedWorkflowIds.mockResolvedValue(['123']);
|
||||
|
||||
await executionsController.stop(req);
|
||||
|
||||
expect(executionService.stop).toHaveBeenCalledWith(executionId);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,178 @@
|
||||
import { parseRangeQuery } from '@/executions/parse-range-query.middleware';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { NextFunction } from 'express';
|
||||
import type * as express from 'express';
|
||||
import type { ExecutionRequest } from '@/executions/execution.types';
|
||||
|
||||
describe('`parseRangeQuery` middleware', () => {
|
||||
const res = mock<express.Response>({
|
||||
status: () => mock<express.Response>({ json: jest.fn() }),
|
||||
});
|
||||
|
||||
const nextFn: NextFunction = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('errors', () => {
|
||||
test('should fail on invalid JSON', () => {
|
||||
const statusSpy = jest.spyOn(res, 'status');
|
||||
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: '{ "status": ["waiting }',
|
||||
limit: undefined,
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(nextFn).toBeCalledTimes(0);
|
||||
expect(statusSpy).toBeCalledWith(400);
|
||||
});
|
||||
|
||||
test('should fail on invalid schema', () => {
|
||||
const statusSpy = jest.spyOn(res, 'status');
|
||||
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: '{ "status": 123 }',
|
||||
limit: undefined,
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(nextFn).toBeCalledTimes(0);
|
||||
expect(statusSpy).toBeCalledWith(400);
|
||||
});
|
||||
});
|
||||
|
||||
describe('filter', () => {
|
||||
test('should parse status and mode fields', () => {
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: '{ "status": ["waiting"], "mode": "manual" }',
|
||||
limit: undefined,
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(req.rangeQuery.status).toEqual(['waiting']);
|
||||
expect(req.rangeQuery.mode).toEqual('manual');
|
||||
expect(nextFn).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should parse date-related fields', () => {
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter:
|
||||
'{ "startedBefore": "2021-01-01", "startedAfter": "2020-01-01", "waitTill": "true" }',
|
||||
limit: undefined,
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(req.rangeQuery.startedBefore).toBe('2021-01-01');
|
||||
expect(req.rangeQuery.startedAfter).toBe('2020-01-01');
|
||||
expect(req.rangeQuery.waitTill).toBe(true);
|
||||
expect(nextFn).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should parse ID-related fields', () => {
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: '{ "id": "123", "workflowId": "456" }',
|
||||
limit: undefined,
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(req.rangeQuery.id).toBe('123');
|
||||
expect(req.rangeQuery.workflowId).toBe('456');
|
||||
expect(nextFn).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should delete invalid fields', () => {
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: '{ "id": "123", "test": "789" }',
|
||||
limit: undefined,
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(req.rangeQuery.id).toBe('123');
|
||||
expect('test' in req.rangeQuery).toBe(false);
|
||||
expect(nextFn).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('range', () => {
|
||||
test('should parse first and last IDs', () => {
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: undefined,
|
||||
limit: undefined,
|
||||
firstId: '111',
|
||||
lastId: '999',
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(req.rangeQuery.range.firstId).toBe('111');
|
||||
expect(req.rangeQuery.range.lastId).toBe('999');
|
||||
expect(nextFn).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should parse limit', () => {
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: undefined,
|
||||
limit: '50',
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(req.rangeQuery.range.limit).toEqual(50);
|
||||
expect(nextFn).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should default limit to 20 if absent', () => {
|
||||
const req = mock<ExecutionRequest.GetMany>({
|
||||
query: {
|
||||
filter: undefined,
|
||||
limit: undefined,
|
||||
firstId: undefined,
|
||||
lastId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
parseRangeQuery(req, res, nextFn);
|
||||
|
||||
expect(req.rangeQuery.range.limit).toEqual(20);
|
||||
expect(nextFn).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user