acelga-bus
Version:
An extensible typescript message bus with support for middlewares
213 lines (184 loc) • 7.15 kB
text/typescript
import {IScheduler, ErrorLogger} from '../../../corebus/interfaces';
import {Dispatcher} from '../../../corebus/dispatchers/single';
import BulkDispatcher from '../../../corebus/dispatchers/bulk';
import ParallelScheduler from '../../../corebus/schedulers/parallel';
import {pipelineFactory} from '../../../corebus/pipeline/factory';
import {pipelineThrowErrorFactory} from '../mocks/pipelineThrowError';
import {pipelinePromiseRejectFactory} from '../mocks/pipelinePromiseReject';
import SequentialScheduler from '../../../corebus/schedulers/sequential';
import {NotExecutedByOrderDependency} from '../../../corebus/pipeline';
class CustomEvent{}
class OtherEvent{}
describe('BulkDispatcher', () => {
let dispatcher: Dispatcher<any>;
let scheduler: IScheduler<any>;
let bulkDispatcher: BulkDispatcher<any>;
let errorLogger: ErrorLogger;
beforeEach(() => {
scheduler = new ParallelScheduler();
errorLogger = async (error) => {};
dispatcher = new Dispatcher();
bulkDispatcher = new BulkDispatcher(dispatcher, scheduler, pipelineFactory, errorLogger);
});
it('should dispatch the event to the correct handler', (done) => {
const handler1 = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.resolve();
});
const handler11 = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.resolve();
});
const handler2 = jest.fn((event) => {
expect(event).toBeInstanceOf(OtherEvent);
return Promise.resolve();
});
const handlerAny = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.resolve();
});
bulkDispatcher.on(CustomEvent, handler1);
bulkDispatcher.on(CustomEvent, handler2);
bulkDispatcher.off(CustomEvent, handler2);
bulkDispatcher.on(CustomEvent, handler11);
bulkDispatcher.on(OtherEvent, handler2);
bulkDispatcher.onAny(handlerAny);
bulkDispatcher.trigger([new CustomEvent()])
.then(() => {
expect(handler1.mock.calls.length).toBe(1);
expect(handler11.mock.calls.length).toBe(1);
expect(handler2.mock.calls.length).toBe(0);
expect(handlerAny.mock.calls.length).toBe(1);
done();
});
});
it('should recognize when a event is already subscribed', () => {
const handler1 = jest.fn((event) => {
return Promise.resolve();
});
bulkDispatcher.on(CustomEvent, handler1);
expect(bulkDispatcher.isListened(CustomEvent)).toBe(true);
expect(bulkDispatcher.isListened(OtherEvent)).toBe(false);
});
it('should return the errors in case of error in the handlers', (done) => {
const handler1 = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.resolve();
});
const handler11 = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
throw new Error('hola');
});
bulkDispatcher.on(CustomEvent, handler1);
bulkDispatcher.on(CustomEvent, handler11);
bulkDispatcher.trigger([new CustomEvent()])
.then(errors => {
expect(errors).toEqual([{error: new Error('hola'), event: new CustomEvent(), isError: true}]);
expect(handler1.mock.calls.length).toBe(1);
expect(handler11.mock.calls.length).toBe(1);
done();
});
});
it('should return the errors in case of rejected promise in the handlers', (done) => {
const okHandler = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.resolve();
});
const okHandler2 = jest.fn((event) => {
expect(event).toBeInstanceOf(OtherEvent);
return Promise.resolve();
});
const rejecHandler = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.reject(new Error('hola'));
});
bulkDispatcher.on(CustomEvent, okHandler);
bulkDispatcher.on(CustomEvent, rejecHandler);
bulkDispatcher.on(OtherEvent, okHandler2);
bulkDispatcher.trigger([new CustomEvent(), new OtherEvent(), new CustomEvent(), new OtherEvent()])
.then(errors => {
expect(errors).toEqual([
{error: new Error('hola'), event: new CustomEvent(), isError: true},
{error: null, event: new CustomEvent(), isError: false},
{error: new Error('hola'), event: new CustomEvent(), isError: true},
{error: null, event: new CustomEvent(), isError: false},
]);
expect(okHandler.mock.calls.length).toBe(2);
expect(rejecHandler.mock.calls.length).toBe(2);
done();
});
});
it('should return the error via catch in case of internal error (case pipeline throw error)', (done) => {
const customErrorLogger = jest.fn(errorLogger);
const customBulkDispatcher = new BulkDispatcher(dispatcher, scheduler, pipelineThrowErrorFactory, customErrorLogger);
const handler2 = jest.fn((event) => {
expect(event).toBeInstanceOf(OtherEvent);
return Promise.resolve();
});
customBulkDispatcher.on(OtherEvent, handler2);
customBulkDispatcher.trigger([new OtherEvent()])
.catch(errors => {
expect(customErrorLogger).toHaveBeenCalledTimes(1);
expect(errors).toEqual(new Error('executeContinueOnError'));
expect(handler2.mock.calls.length).toBe(0);
done();
});
});
it('should return the errors via then in case of internal error (case pipeline promise reject)', (done) => {
const customErrorLogger = jest.fn(errorLogger);
const customBulkDispatcher = new BulkDispatcher(dispatcher, scheduler, pipelinePromiseRejectFactory, customErrorLogger);
const handler1 = jest.fn((event) => {
expect(event).toBeInstanceOf(OtherEvent);
return Promise.reject(new Error('Hola'));
});
const handler2 = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.resolve();
});
customBulkDispatcher.on(OtherEvent, handler1);
customBulkDispatcher.on(CustomEvent, handler2);
customBulkDispatcher.trigger([new OtherEvent(), new CustomEvent()])
.then((value) => {
expect(customErrorLogger).toHaveBeenCalledTimes(2);
expect(customErrorLogger.mock.calls[0][0]).toBeInstanceOf(Error);
expect(handler2.mock.calls.length).toBe(0);
done();
});
});
it('should stop if preserve order is true', (done) => {
const customerScheduler = new SequentialScheduler(true);
const customBulkDispatcher = new BulkDispatcher(dispatcher, customerScheduler, pipelineFactory, errorLogger);
const handler1 = jest.fn((event) => {
expect(event).toBeInstanceOf(CustomEvent);
return Promise.resolve();
});
const handler2 = jest.fn((event) => {
expect(event).toBeInstanceOf(OtherEvent);
return Promise.reject();
});
customBulkDispatcher.on(CustomEvent, handler1);
customBulkDispatcher.on(OtherEvent, handler2);
customBulkDispatcher.trigger([new OtherEvent(), new OtherEvent(), new CustomEvent(), new OtherEvent()])
.then(errors => {
expect(errors).toEqual([{
error: undefined,
event: new OtherEvent(),
isError: true,
}, {
error: new NotExecutedByOrderDependency(),
event: new OtherEvent(),
isError: true,
}, {
error: new NotExecutedByOrderDependency(),
event: new CustomEvent(),
isError: true,
}, {
error: new NotExecutedByOrderDependency(),
event: new OtherEvent(),
isError: true,
}]);
expect(handler2.mock.calls.length).toBe(1);
done();
});
});
});