99f29a169c
closes https://github.com/TryGhost/Arch/issues/91
- We have on cascade delete (a9f9f6121a/ghost/core/core/server/data/schema/schema.js (L1068)
) on `post_id` column which handles post deletion logic automatically on DB level.
- The commented out handlers in the long term should be hooked up with public CollectionService methods on the client side.
257 lines
8.1 KiB
TypeScript
257 lines
8.1 KiB
TypeScript
import assert from 'assert/strict';
|
|
import events from 'events';
|
|
import sinon from 'sinon';
|
|
import DomainEvents from '@tryghost/domain-events';
|
|
import {
|
|
PostDeletedEvent
|
|
} from '@tryghost/post-events';
|
|
import {
|
|
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 post.deleted Model event without an id property 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', {
|
|
_previousAttributes: {
|
|
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', {
|
|
_previousAttributes: {
|
|
id: '1234-deleted',
|
|
slug: 'tag-slug'
|
|
}
|
|
});
|
|
|
|
await DomainEvents.allSettled();
|
|
|
|
assert.ok(interceptedEvent);
|
|
});
|
|
|
|
it('Intercepts tag.deleted Model event without an id property 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);
|
|
});
|
|
});
|