@getanthill/datastore
Version:
Event-Sourced Datastore
247 lines (218 loc) • 5.17 kB
text/typescript
import Ajv from 'ajv';
import assert from 'node:assert';
import { getEventTypes, getEventTypeVersions, validate } from './events';
describe('models/events', () => {
const schemas = {
$id: 'events',
components: {},
events: {
CREATED: {
'0_0_0': {
type: 'object',
properties: {
name: {
type: 'string',
},
},
},
'0_0_1': {
type: 'object',
properties: {
name: {
type: 'string',
},
tags: {
type: 'array',
items: {
type: 'string',
},
},
is_enabled: {
type: 'boolean',
default: true,
},
},
},
'0_1_0': {
type: 'object',
properties: {
name: {
type: 'string',
},
},
},
},
},
};
const validator = new Ajv({
strict: false,
schemas: [schemas],
useDefaults: true,
});
const schema = validator.getSchema('events');
describe('#getEventTypes', () => {
it('returns the list of all supported events', () => {
expect(getEventTypes(schemas.events)).toEqual(['CREATED']);
});
});
describe('#getEventTypeVersions', () => {
it('returns the mapping of versions for every event', () => {
expect(
getEventTypeVersions(schema, {
type: 'CREATED',
v: '0_0_0',
}),
).toEqual({
v: '0_0_0',
all: ['0_0_0', '0_0_1', '0_1_0'],
});
});
});
describe('#validate', () => {
it('throws an exception on unknown event type', () => {
let error;
try {
validate(
{
type: 'UNKNOWN',
v: '0_0_0',
},
schema,
validator,
);
} catch (err) {
error = err;
}
expect(error).toBeInstanceOf(assert.AssertionError);
expect(error.message).toEqual('Invalid event type');
expect(error.details).toEqual(['CREATED']);
});
it('throws an exception on invalid version', () => {
let error;
try {
validate(
{
type: 'CREATED',
v: 'a.b.c',
},
schema,
validator,
);
} catch (err) {
error = err;
}
expect(error).toBeInstanceOf(assert.AssertionError);
expect(error.message).toEqual('Invalid event type version');
expect(error.details).toEqual({
v: 'a.b.c',
all: ['0_0_0', '0_0_1', '0_1_0'],
});
});
it('throws an exception on undefined version', () => {
let error;
try {
validate(
{
type: 'CREATED',
},
schema,
validator,
);
} catch (err) {
error = err;
}
expect(error).toBeInstanceOf(assert.AssertionError);
expect(error.message).toEqual('Invalid event type version');
expect(error.details).toEqual({
v: undefined,
all: ['0_0_0', '0_0_1', '0_1_0'],
});
});
it('throws an exception on invalid event schema', () => {
let error;
try {
validate(
{
type: 'CREATED',
v: '0_0_0',
name: 12,
},
schema,
validator,
);
} catch (err) {
error = err;
}
expect(error).toBeInstanceOf(assert.AssertionError);
expect(error.message).toEqual('Event schema validation error');
});
it('does not throw on invalid version if `throwOnInvalidEvent = false`', () => {
let error;
try {
validate(
{
type: 'CREATED',
v: '0_0_0',
name: 12,
},
schema,
validator,
false,
);
} catch (err) {
error = err;
}
expect(error).toBeUndefined();
});
it('returns the schema if everything is fine', () => {
expect(
validate(
{
type: 'CREATED',
v: '0_0_0',
name: 'John',
},
schema,
validator,
),
).toEqual({
type: 'object',
properties: {
name: {
type: 'string',
},
},
});
});
it('mutates the event if validated', () => {
const event = {
type: 'CREATED',
v: '0_0_1',
name: 'John',
};
validate(event, schema, validator);
expect(event).toEqual({
type: 'CREATED',
v: '0_0_1',
name: 'John',
is_enabled: true,
});
});
it('mutates the event if validated with arrays', () => {
const event = {
type: 'CREATED',
v: '0_0_1',
name: 'John',
tags: ['paris'],
};
validate(event, schema, validator);
expect(event).toEqual({
type: 'CREATED',
v: '0_0_1',
name: 'John',
tags: ['paris'],
is_enabled: true,
});
});
});
});