Files
directus/api/src/middleware/validate-batch.test.ts
Boegie19 d82bb9c823 move api/errors to @directus/errors package (#20054)
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
2023-10-18 18:19:22 +02:00

112 lines
3.2 KiB
TypeScript

import type { Request, Response } from 'express';
import { beforeEach, expect, test, vi } from 'vitest';
import '../types/express.d.ts';
import { InvalidPayloadError } from '@directus/errors';
import { validateBatch } from './validate-batch.js';
let mockRequest: Partial<Request & { token?: string }>;
let mockResponse: Partial<Response>;
const nextFunction = vi.fn();
beforeEach(() => {
mockRequest = {};
mockResponse = {};
vi.clearAllMocks();
});
test('Sets body to empty, calls next on GET requests', async () => {
mockRequest.method = 'GET';
await validateBatch('read')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(mockRequest.body).toEqual({});
expect(nextFunction).toHaveBeenCalledTimes(1);
});
test(`Short circuits on singletons that aren't queried through SEARCH`, async () => {
mockRequest.method = 'PATCH';
mockRequest.singleton = true;
mockRequest.body = { title: 'test' };
await validateBatch('update')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(nextFunction).toHaveBeenCalledTimes(1);
});
test('Throws InvalidPayloadError on missing body', async () => {
mockRequest.method = 'SEARCH';
await validateBatch('read')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(nextFunction).toHaveBeenCalledTimes(1);
expect(vi.mocked(nextFunction).mock.calls[0][0]).toBeInstanceOf(InvalidPayloadError);
});
test(`Short circuits on Array body in update/delete use`, async () => {
mockRequest.method = 'PATCH';
mockRequest.body = [1, 2, 3];
await validateBatch('update')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(mockRequest.sanitizedQuery).toBe(undefined);
expect(nextFunction).toHaveBeenCalled();
});
test(`Sets sanitizedQuery based on body.query in read operations`, async () => {
mockRequest.method = 'SEARCH';
mockRequest.body = {
query: {
sort: 'id',
},
};
await validateBatch('read')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(mockRequest.sanitizedQuery).toEqual({
sort: ['id'],
});
});
test(`Doesn't allow both query and keys in a batch delete`, async () => {
mockRequest.method = 'DELETE';
mockRequest.body = {
keys: [1, 2, 3],
query: { filter: {} },
};
await validateBatch('delete')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(nextFunction).toHaveBeenCalledTimes(1);
expect(vi.mocked(nextFunction).mock.calls[0][0]).toBeInstanceOf(InvalidPayloadError);
});
test(`Requires 'data' on batch update`, async () => {
mockRequest.method = 'PATCH';
mockRequest.body = {
keys: [1, 2, 3],
query: { filter: {} },
};
await validateBatch('update')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(nextFunction).toHaveBeenCalledTimes(1);
expect(vi.mocked(nextFunction).mock.calls[0][0]).toBeInstanceOf(InvalidPayloadError);
});
test(`Calls next when all is well`, async () => {
mockRequest.method = 'PATCH';
mockRequest.body = {
query: { filter: {} },
data: {},
};
await validateBatch('update')(mockRequest as Request, mockResponse as Response, nextFunction);
expect(nextFunction).toHaveBeenCalledTimes(1);
expect(vi.mocked(nextFunction).mock.calls[0][0]).toBeUndefined();
});