feat: add CompositeAsyncHandler to support multiple handlers

This commit is contained in:
Joachim Van Herwegen
2020-05-28 10:55:29 +02:00
parent 57405f3e26
commit 4229932a3a
14 changed files with 275 additions and 23 deletions

View File

@@ -0,0 +1,30 @@
import { AsyncHandler } from '../../../src/util/AsyncHandler';
import { StaticAsyncHandler } from '../../util/StaticAsyncHandler';
describe('An AsyncHandler', (): void => {
it('calls canHandle and handle when handleSafe is called.', async (): Promise<void> => {
const handlerTrue: AsyncHandler<any, any> = new StaticAsyncHandler(true, null);
const canHandleFn = jest.fn(async (input: any): Promise<void> => input);
const handleFn = jest.fn(async (input: any): Promise<any> => input);
handlerTrue.canHandle = canHandleFn;
handlerTrue.handle = handleFn;
await expect(handlerTrue.handleSafe('test')).resolves.toBe('test');
expect(canHandleFn).toHaveBeenCalledTimes(1);
expect(handleFn).toHaveBeenCalledTimes(1);
});
it('does not call handle when canHandle errors during a handleSafe call.', async (): Promise<void> => {
const handlerFalse: AsyncHandler<any, any> = new StaticAsyncHandler(false, null);
const canHandleFn = jest.fn(async (): Promise<void> => {
throw new Error('test');
});
const handleFn = jest.fn(async (input: any): Promise<any> => input);
handlerFalse.canHandle = canHandleFn;
handlerFalse.handle = handleFn;
await expect(handlerFalse.handleSafe('test')).rejects.toThrow(Error);
expect(canHandleFn).toHaveBeenCalledTimes(1);
expect(handleFn).toHaveBeenCalledTimes(0);
});
});

View File

@@ -0,0 +1,76 @@
import { AsyncHandler } from '../../../src/util/AsyncHandler';
import { CompositeAsyncHandler } from '../../../src/util/CompositeAsyncHandler';
import { StaticAsyncHandler } from '../../util/StaticAsyncHandler';
describe('A CompositeAsyncHandler', (): void => {
describe('with no handlers', (): void => {
it('can never handle data.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([]);
await expect(handler.canHandle(null)).rejects.toThrow(Error);
});
it('errors if its handle function is called.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([]);
await expect(handler.handle(null)).rejects.toThrow(Error);
});
});
describe('with multiple handlers', (): void => {
let handlerTrue: AsyncHandler<any, any>;
let handlerFalse: AsyncHandler<any, any>;
let canHandleFn: jest.Mock<Promise<void>, [any]>;
let handleFn: jest.Mock<Promise<void>, [any]>;
beforeEach(async (): Promise<void> => {
handlerTrue = new StaticAsyncHandler(true, null);
handlerFalse = new StaticAsyncHandler(false, null);
canHandleFn = jest.fn(async (input: any): Promise<any> => input);
handleFn = jest.fn(async (input: any): Promise<any> => input);
handlerTrue.canHandle = canHandleFn;
handlerTrue.handle = handleFn;
});
it('can handle data if a handler supports it.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([ handlerFalse, handlerTrue ]);
await expect(handler.canHandle(null)).resolves.toBeUndefined();
});
it('can not handle data if no handler supports it.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([ handlerFalse, handlerFalse ]);
await expect(handler.canHandle(null)).rejects.toThrow('[Not supported., Not supported.]');
});
it('handles data if a handler supports it.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([ handlerFalse, handlerTrue ]);
await expect(handler.handle('test')).resolves.toEqual('test');
expect(canHandleFn).toHaveBeenCalledTimes(1);
expect(handleFn).toHaveBeenCalledTimes(1);
});
it('errors if the handle function is called but no handler supports the data.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([ handlerFalse, handlerFalse ]);
await expect(handler.handle('test')).rejects.toThrow('All handlers failed.');
});
it('only calls the canHandle function once of its handlers when handleSafe is called.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([ handlerFalse, handlerTrue ]);
await expect(handler.handleSafe('test')).resolves.toEqual('test');
expect(canHandleFn).toHaveBeenCalledTimes(1);
expect(handleFn).toHaveBeenCalledTimes(1);
});
it('throws the same error as canHandle when calling handleSafe if no handler supports the data.', async (): Promise<void> => {
const handler = new CompositeAsyncHandler([ handlerFalse, handlerFalse ]);
await expect(handler.handleSafe(null)).rejects.toThrow('[Not supported., Not supported.]');
});
});
});