@getanthill/datastore
Version:
Event-Sourced Datastore
392 lines (368 loc) • 10.6 kB
text/typescript
import { MongoDbConnector } from '@getanthill/mongodb-connector';
import * as builder from './builder';
import setup from '../../../test/setup';
import { Services } from '../../typings';
describe('api/spec/builder', () => {
let models;
let app;
let services: Services;
let mongodb: MongoDbConnector;
const defaultSpec = {
components: {
schemas: {},
},
};
beforeAll(async () => {
app = await setup.build();
services = app.services;
mongodb = services.mongodb;
models = await setup.initModels(services, []);
});
afterEach(async () => {
models.reset();
jest.restoreAllMocks();
});
afterAll(async () => {
await setup.teardownDb(mongodb);
});
describe('build', () => {
it('must match empty spec if no model is defined', () => {
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a simple default specification with a very simple model', () => {
models.addModel({
db: 'datastore',
name: 'users',
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with required field on CREATED event', () => {
models.addModel({
db: 'datastore',
name: 'users',
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
CREATED: {
'0_0_0': {
required: ['firstname'],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification without default CREATED event', () => {
models.addModel({
db: 'datastore',
name: 'users',
with_default_events: false,
schema: {
events: {},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with required field on UPDATED event', () => {
models.addModel({
db: 'datastore',
name: 'users',
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
UPDATED: {
'0_0_0': {
required: ['firstname'],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with custom events', () => {
models.addModel({
db: 'datastore',
name: 'users',
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
required: ['firstname'],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with custom events and encrypted fields', () => {
models.addModel({
db: 'datastore',
name: 'users',
encrypted_fields: ['firstname'],
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
'x-show-handler': true,
required: ['firstname'],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with custom events and special responses defined', () => {
models.addModel({
db: 'datastore',
name: 'users',
encrypted_fields: ['firstname'],
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
required: ['firstname'],
properties: {
firstname: {
type: 'string',
},
},
'x-responses': [
{
status: 200,
description: 'User created',
},
],
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with custom events and dedicated handler (`x-show-handler=true`)', () => {
models.addModel({
db: 'datastore',
name: 'users',
encrypted_fields: ['firstname'],
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
'x-show-handler': true,
handler: `if (state.email_verification_token !== event.email_verification_token) {\n const err = new Error('Invalid email verification token');\n // @ts-ignore\n err.status = 412;\n throw err;\n }\n return [\n Object.assign(Object.assign({}, state), { is_email_verified: true }),\n ];`,
required: ['firstname'],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with custom events and dedicated handler (`x-show-handler=unknown`)', () => {
models.addModel({
db: 'datastore',
name: 'users',
encrypted_fields: ['firstname'],
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
handler: `if (state.email_verification_token !== event.email_verification_token) {\n const err = new Error('Invalid email verification token');\n // @ts-ignore\n err.status = 412;\n throw err;\n }\n return [\n Object.assign(Object.assign({}, state), { is_email_verified: true }),\n ];`,
required: ['firstname'],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with custom events but no required field', () => {
models.addModel({
db: 'datastore',
name: 'users',
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
required: [],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with specified data processings', () => {
models.addModel({
db: 'datastore',
name: 'users',
processings: [
{
field: 'firstname',
name: 'Say hello',
purpose:
'The objective of this processing is to access the firstname of the user to say hello politely.',
persons: ['users'],
recipients: ['anthill'],
tokens: ['say_hello_processing'],
duration_in_seconds: 31536000,
},
],
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
required: [],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
it('must match a specification with specified data processings without access tokens', () => {
models.addModel({
db: 'datastore',
name: 'users',
processings: [
{
field: 'firstname',
name: 'Say hello',
purpose:
'The objective of this processing is to access the firstname of the user to say hello politely.',
persons: ['users'],
recipients: ['anthill'],
duration_in_seconds: 31536000,
},
],
schema: {
model: {
properties: {
firstname: {
type: 'string',
},
},
},
events: {
FIRSTNAME_UPDATED: {
'0_0_0': {
required: [],
properties: {
firstname: {
type: 'string',
},
},
},
},
},
},
});
expect(builder.build(defaultSpec, models)).toMatchSnapshot();
});
});
});