@getanthill/datastore
Version:
Event-Sourced Datastore
179 lines (140 loc) • 4.6 kB
text/typescript
import type { Models } from '../../models';
import { MongoDbConnector } from '@getanthill/mongodb-connector';
import setup from '../../../test/setup';
import { aggregate } from './controllers';
import fixtureUsers from '../../../test/fixtures/users';
import { Services } from '../../typings';
import { Aggregator } from '../../sdk';
describe('controllers/aggregate', () => {
let app;
let services: Services;
let mongodb: MongoDbConnector;
let models: Models;
beforeAll(async () => {
app = await setup.build({
datastores: [
{
name: 'datastore',
config: {},
},
],
});
services = app.services;
mongodb = services.mongodb;
models = await setup.initModels(services, [fixtureUsers]);
});
beforeEach(async () => {
const Users = models.getModel(fixtureUsers.name);
await Promise.all([
Users.getStatesCollection(Users.db(mongodb)).deleteMany({}),
Users.getEventsCollection(Users.db(mongodb)).deleteMany({}),
Users.getSnapshotsCollection(Users.db(mongodb)).deleteMany({}),
]);
});
afterEach(() => {
jest.restoreAllMocks();
});
afterAll(async () => {
await setup.teardownDb(mongodb);
});
describe('#aggregate', () => {
let error;
let req;
let res;
let next;
beforeEach(() => {
error = null;
next = jest.fn().mockImplementation((err) => (error = err));
req = {
header: (h) => req.headers[h],
params: {},
body: {},
headers: {},
};
res = {
json: jest.fn(),
};
});
afterEach(() => {
jest.restoreAllMocks();
});
it('returns a simple aggregation result', async () => {
// @ts-ignore
const controller = aggregate(services);
req.body = [];
await controller(req, res, next);
expect(res.json).toHaveBeenCalledTimes(1);
expect(res.body).toEqual({});
});
it('returns a simple aggregation result with logs if requested in headers', async () => {
// @ts-ignore
const controller = aggregate(services);
req.headers['logs'] = 'true';
req.body = [];
await controller(req, res, next);
expect(res.json).toHaveBeenCalledTimes(1);
expect(res.body).toMatchObject({
aggregation: {},
});
});
it('returns a 400 Bad Request error in case of aggregation common error', async () => {
// @ts-ignore
const controller = aggregate(services);
req.body = [
{
type: 'invalid',
},
];
await controller(req, res, next);
expect(next).toHaveBeenCalledTimes(1);
expect(next).toHaveBeenLastCalledWith(
Aggregator.ERROR_INVALID_PIPELINE_DEFINITION,
);
expect(next.mock.calls[0][0].status).toEqual(400);
});
it('returns a 422 Unprocessable Entity error in case of valid aggregation but processing error', async () => {
// @ts-ignore
const controller = aggregate(services);
req.header = jest.fn().mockImplementation((str) => {
throw Aggregator.ERROR_ENTITY_NOT_FOUND;
});
req.body = [
{
type: 'fetch',
model: 'test',
},
];
await controller(req, res, next);
expect(next).toHaveBeenCalledTimes(1);
expect(next).toHaveBeenLastCalledWith(Aggregator.ERROR_ENTITY_NOT_FOUND);
expect(next.mock.calls[0][0].status).toEqual(422);
});
it('returns a 422 Unprocessable Entity error in case of valid aggregation but processing error with aggregator logs if initialized', async () => {
// @ts-ignore
const controller = aggregate(services);
req.header = jest.fn().mockImplementation((str) => {
if (str === 'logs') {
throw Aggregator.ERROR_ENTITY_NOT_FOUND;
}
});
req.body = [];
await controller(req, res, next);
expect(next).toHaveBeenCalledTimes(1);
expect(next).toHaveBeenLastCalledWith(Aggregator.ERROR_ENTITY_NOT_FOUND);
expect(next.mock.calls[0][0].status).toEqual(422);
expect(next.mock.calls[0][0]).toHaveProperty('details');
});
it('returns a 500 error in case of unknown error', async () => {
const error = new Error('Ooops');
req.header = jest.fn().mockImplementation((str) => {
throw error;
});
// @ts-ignore
const controller = aggregate(services);
req.body = [];
await controller(req, res, next);
expect(next).toHaveBeenCalledTimes(1);
expect(next).toHaveBeenLastCalledWith(error);
});
});
});