Ghost/ghost/model-to-domain-event-interceptor/test/model-to-domain-event-interceptor.test.ts
Fabien "egg" O'Carroll 8d71841918 Mapped tag.deleted event to TagDeletedEvent
refs https://github.com/TryGhost/Arch/issues/61

Because the tags system is still written in the old way, the tag.deleted
bookshelf event needs to be mapped to the DomainEvents to bridge the gap with
the collections package.
2023-07-26 12:54:42 +02:00

201 lines
6.4 KiB
TypeScript

import assert from 'assert/strict';
import events from 'events';
import sinon from 'sinon';
import DomainEvents from '@tryghost/domain-events';
import {
PostDeletedEvent,
PostEditedEvent,
PostAddedEvent,
TagDeletedEvent
} from '@tryghost/collections';
import {ModelToDomainEventInterceptor} from '../src';
class EventRegistry extends events.EventEmitter {
hasRegisteredListener(eventName: string, listenerName: string) {
return !!(this.listeners(eventName).find(listener => (listener.name === listenerName)));
}
}
describe('ModelToDomainEventInterceptor', function () {
it('Can instantiate a ModelToDomainEventInterceptor', function () {
const modelToDomainEventInterceptor = new ModelToDomainEventInterceptor({
ModelEvents: new EventRegistry(),
DomainEvents: DomainEvents
});
assert.ok(modelToDomainEventInterceptor);
});
it('Starts event listeners after initialization', function () {
let eventRegistry = new EventRegistry();
const modelToDomainEventInterceptor = new ModelToDomainEventInterceptor({
ModelEvents: eventRegistry,
DomainEvents: DomainEvents
});
modelToDomainEventInterceptor.init();
assert.ok(eventRegistry.hasRegisteredListener('post.added', 'post.added.domainEventInterceptorListener'), 'post.added listener is registered');
});
it('Intercepts post.added Model event and dispatches PostAddedEvent Domain event', async function () {
let eventRegistry = new EventRegistry();
const modelToDomainEventInterceptor = new ModelToDomainEventInterceptor({
ModelEvents: eventRegistry,
DomainEvents: DomainEvents
});
modelToDomainEventInterceptor.init();
let interceptedEvent;
DomainEvents.subscribe(PostAddedEvent, (event: any) => {
assert.equal(event.id, '1234-added');
interceptedEvent = event;
});
eventRegistry.emit('post.added', {
id: '1234-added',
attributes: {
status: 'draft',
featured: false,
published_at: new Date()
}
});
await DomainEvents.allSettled();
assert.ok(interceptedEvent);
});
it('Intercepts post.edited Model event and dispatches PostEditedEvent Domain event', async function () {
let eventRegistry = new EventRegistry();
const modelToDomainEventInterceptor = new ModelToDomainEventInterceptor({
ModelEvents: eventRegistry,
DomainEvents: DomainEvents
});
modelToDomainEventInterceptor.init();
let interceptedEvent;
DomainEvents.subscribe(PostEditedEvent, async (event: any) => {
assert.equal(event.id, '1234-edited');
assert.ok(event.data);
assert.ok(event.data.current);
assert.equal(event.data.current.status, 'draft');
assert.equal(event.data.previous.status, 'published');
assert.deepEqual(event.data.current.tags[0], {slug: 'tag-current-slug'});
assert.deepEqual(event.data.previous.tags[0], {slug: 'tag-previous-slug'});
interceptedEvent = event;
});
eventRegistry.emit('post.edited', {
id: '1234-edited',
attributes: {
status: 'draft',
featured: false,
published_at: new Date()
},
_previousAttributes: {
status: 'published',
featured: true
},
relations: {
tags: {
models: [{
get: function (key: string) {
return `tag-current-${key}`;
}
}]
}
},
_previousRelations: {
tags: {
models: [{
get: function (key: string) {
return `tag-previous-${key}`;
}
}]
}
}
});
await DomainEvents.allSettled();
assert.ok(interceptedEvent);
});
it('Intercepts post.deleted Model event and dispatches PostAddedEvent Domain event', async function () {
let eventRegistry = new EventRegistry();
const modelToDomainEventInterceptor = new ModelToDomainEventInterceptor({
ModelEvents: eventRegistry,
DomainEvents: DomainEvents
});
modelToDomainEventInterceptor.init();
let interceptedEvent;
DomainEvents.subscribe(PostDeletedEvent, (event: any) => {
assert.equal(event.id, '1234-deleted');
interceptedEvent = event;
});
eventRegistry.emit('post.deleted', {
id: '1234-deleted'
});
await DomainEvents.allSettled();
assert.ok(interceptedEvent);
});
it('Intercepts tag.deleted Model event and dispatches TagDeletedEvent Domain event', async function () {
let eventRegistry = new EventRegistry();
const modelToDomainEventInterceptor = new ModelToDomainEventInterceptor({
ModelEvents: eventRegistry,
DomainEvents: DomainEvents
});
modelToDomainEventInterceptor.init();
let interceptedEvent;
DomainEvents.subscribe(TagDeletedEvent, (event: TagDeletedEvent) => {
assert.equal(event.id, '1234-deleted');
assert.equal(event.data.slug, 'tag-slug');
interceptedEvent = event;
});
eventRegistry.emit('tag.deleted', {
id: '1234-deleted',
attributes: {
slug: 'tag-slug'
}
});
await DomainEvents.allSettled();
assert.ok(interceptedEvent);
});
it('Intercepts unmapped Model event and dispatches nothing', async function () {
let eventRegistry = new EventRegistry();
const modelToDomainEventInterceptor = new ModelToDomainEventInterceptor({
ModelEvents: eventRegistry,
DomainEvents: DomainEvents
});
const domainEventsSpy = sinon.spy(DomainEvents, 'dispatch');
modelToDomainEventInterceptor.init();
eventRegistry.emit('tag.added', {
id: '1234-tag'
});
await DomainEvents.allSettled();
assert.equal(domainEventsSpy.called, false);
});
});