mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com> Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
112 lines
3.2 KiB
TypeScript
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();
|
|
});
|