-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
change: Refactor AllVoidCompositeHandler into SequenceHandler.
- Loading branch information
1 parent
7cae14a
commit ba47ce7
Showing
11 changed files
with
112 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { AsyncHandler } from './AsyncHandler'; | ||
|
||
/** | ||
* A composite handler that will try to run all supporting handlers sequentially | ||
* and return the value of the last supported handler. | ||
* The `canHandle` check of this handler will always succeed. | ||
*/ | ||
export class SequenceHandler<TIn = void, TOut = void> extends AsyncHandler<TIn, TOut | undefined> { | ||
private readonly handlers: AsyncHandler<TIn, TOut>[]; | ||
|
||
public constructor(handlers: AsyncHandler<TIn, TOut>[]) { | ||
super(); | ||
this.handlers = [ ...handlers ]; | ||
} | ||
|
||
public async handle(input: TIn): Promise<TOut | undefined> { | ||
let result: TOut | undefined; | ||
for (const handler of this.handlers) { | ||
let supported: boolean; | ||
try { | ||
await handler.canHandle(input); | ||
supported = true; | ||
} catch { | ||
supported = false; | ||
} | ||
if (supported) { | ||
result = await handler.handle(input); | ||
} | ||
} | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import type { AsyncHandler } from '../../../src/util/AsyncHandler'; | ||
import { SequenceHandler } from '../../../src/util/SequenceHandler'; | ||
|
||
describe('A SequenceHandler', (): void => { | ||
const handlers: jest.Mocked<AsyncHandler<string, string>>[] = [ | ||
{ | ||
canHandle: jest.fn(), | ||
handle: jest.fn().mockResolvedValue('0'), | ||
} as any, | ||
{ | ||
canHandle: jest.fn().mockRejectedValue(new Error('not supported')), | ||
handle: jest.fn().mockRejectedValue(new Error('should not be called')), | ||
} as any, | ||
{ | ||
canHandle: jest.fn(), | ||
handle: jest.fn().mockResolvedValue('2'), | ||
} as any, | ||
]; | ||
let composite: SequenceHandler<string, string>; | ||
|
||
beforeEach(async(): Promise<void> => { | ||
composite = new SequenceHandler<string, string>(handlers); | ||
}); | ||
|
||
it('can handle all input.', async(): Promise<void> => { | ||
await expect(composite.canHandle('test')).resolves.toBeUndefined(); | ||
}); | ||
|
||
it('runs all supported handlers.', async(): Promise<void> => { | ||
await composite.handleSafe('test'); | ||
|
||
expect(handlers[0].canHandle).toHaveBeenCalledTimes(1); | ||
expect(handlers[0].canHandle).toHaveBeenLastCalledWith('test'); | ||
expect(handlers[0].handle).toHaveBeenCalledTimes(1); | ||
expect(handlers[0].handle).toHaveBeenLastCalledWith('test'); | ||
|
||
expect(handlers[1].canHandle).toHaveBeenCalledTimes(1); | ||
expect(handlers[1].canHandle).toHaveBeenLastCalledWith('test'); | ||
expect(handlers[1].handle).toHaveBeenCalledTimes(0); | ||
|
||
expect(handlers[2].canHandle).toHaveBeenCalledTimes(1); | ||
expect(handlers[2].canHandle).toHaveBeenLastCalledWith('test'); | ||
expect(handlers[2].handle).toHaveBeenCalledTimes(1); | ||
expect(handlers[2].handle).toHaveBeenLastCalledWith('test'); | ||
}); | ||
|
||
it('returns the result of the last supported handler.', async(): Promise<void> => { | ||
await expect(composite.handleSafe('test')).resolves.toBe('2'); | ||
|
||
handlers[2].canHandle.mockRejectedValueOnce(new Error('not supported')); | ||
await expect(composite.handleSafe('test')).resolves.toBe('0'); | ||
}); | ||
|
||
it('returns undefined if no handler is supported.', async(): Promise<void> => { | ||
handlers[0].canHandle.mockRejectedValueOnce(new Error('not supported')); | ||
handlers[2].canHandle.mockRejectedValueOnce(new Error('not supported')); | ||
await expect(composite.handleSafe('test')).resolves.toBeUndefined(); | ||
}); | ||
|
||
it('errors if a handler errors.', async(): Promise<void> => { | ||
handlers[2].handle.mockRejectedValueOnce(new Error('failure')); | ||
await expect(composite.handleSafe('test')).rejects.toThrow('failure'); | ||
}); | ||
}); |