Skip to content

Commit

Permalink
feat(hook): add AsyncSeriesHook & AsyncSeriesBailHook
Browse files Browse the repository at this point in the history
  • Loading branch information
Repraance authored Aug 29, 2022
1 parent 55321ba commit 61b4eae
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 154 deletions.
146 changes: 27 additions & 119 deletions packages/hook/src/__tests__/hooks/asyncParallelHook.test.ts
Original file line number Diff line number Diff line change
@@ -1,135 +1,43 @@
import { createAsyncParallelHook } from '../../hooks';
import { AsyncParallelHookHandler, createAsyncParallelHook } from '../../hooks';
import { sleep } from '../utils';

beforeEach(() => {
console.log = jest.fn();
});

afterEach(async () => {});

describe('syncHook', () => {
test('initialValue-normal extraArg-normal', async () => {
const hook = createAsyncParallelHook<number, number>();
hook.use((i, e) => {
console.log(i, e);
});
hook.use(async (i, e) => {
console.log(i * 2, e * 2);
});
await hook.run(10, 20);
expect(console.log).toHaveBeenNthCalledWith(1, 10, 20);
expect(console.log).toHaveBeenNthCalledWith(2, 20, 40);
});
test('initialValue-void extraArg-normal', async () => {
const hook = createAsyncParallelHook<void, number>();
hook.use(e => {
console.log(e);
});
hook.use(async e => {
console.log(e * 2);
});
await hook.run(10);
expect(console.log).toHaveBeenNthCalledWith(1, 10);
expect(console.log).toHaveBeenNthCalledWith(2, 20);
});

test('initialValue-any extraArg-normal', async () => {
const hook = createAsyncParallelHook<any, number>();
hook.use((i, e) => {
console.log(i, e);
});
hook.use(async (i, e) => {
console.log(i + '0', e * 2);
});
await hook.run('10', 20);
expect(console.log).toHaveBeenNthCalledWith(1, '10', 20);
expect(console.log).toHaveBeenNthCalledWith(2, '100', 40);
});

test('initialValue-normal extraArg-void', async () => {
const hook = createAsyncParallelHook<number, void>();
hook.use(i => {
console.log(i);
});
hook.use(async i => {
console.log(i * 2);
});
await hook.run(10);
expect(console.log).toHaveBeenNthCalledWith(1, 10);
expect(console.log).toHaveBeenNthCalledWith(2, 20);
});
test('initialValue-void extraArg-void', async () => {
const hook = createAsyncParallelHook<void, void>();
hook.use(() => {
console.log('test1');
});
describe('AsyncParallelHook', () => {
test('hooks should run in parallel', async () => {
const hook = createAsyncParallelHook<void>();
const logs: number[] = [];
hook.use(async () => {
console.log('test2');
});
await hook.run();
expect(console.log).toHaveBeenNthCalledWith(1, 'test1');
expect(console.log).toHaveBeenNthCalledWith(2, 'test2');
});

test('initialValue-any extraArg-void', async () => {
const hook = createAsyncParallelHook<any, void>();
hook.use(i => {
console.log(i);
});
hook.use(async i => {
console.log(i + ' async');
});
await hook.run('test any');
expect(console.log).toHaveBeenNthCalledWith(1, 'test any');
expect(console.log).toHaveBeenNthCalledWith(2, 'test any async');
});

test('initialValue-normal extraArg-any', async () => {
const hook = createAsyncParallelHook<number, any>();
hook.use((i, e) => {
console.log(i, e);
await sleep(10);
logs.push(1);
});
hook.use(async (i, e) => {
console.log(i * 2, e + '0');
hook.use(async () => {
logs.push(2);
});
await hook.run(10, '20');
expect(console.log).toHaveBeenNthCalledWith(1, 10, '20');
expect(console.log).toHaveBeenNthCalledWith(2, 20, '200');
});
test('initialValue-void extraArg-any', async () => {
const hook = createAsyncParallelHook<void, any>();
hook.use(() => {
console.log('test any');
});
hook.use(async () => {
console.log('test any' + ' async');
logs.push(3);
});
await hook.run('test any');
expect(console.log).toHaveBeenNthCalledWith(1, 'test any');
expect(console.log).toHaveBeenNthCalledWith(2, 'test any async');
await hook.run();
expect(logs).toEqual([2, 3, 1]);
});

test('initialValue-any extraArg-any', async () => {
const hook = createAsyncParallelHook<any, any>();
hook.use((i, e) => {
console.log(i, e);
});
hook.use((i, e) => {
console.log(i + ' async', e + ' async');
});
await hook.run('test 1', 'test 2');
expect(console.log).toHaveBeenNthCalledWith(1, 'test 1', 'test 2');
expect(console.log).toHaveBeenNthCalledWith(
2,
'test 1 async',
'test 2 async'
test('the params of run() should be as the params of the hook handler', async () => {
const hook = createAsyncParallelHook<number, number>();
const handler: AsyncParallelHookHandler<number, number, void> = jest.fn(
(i, e) => {
expect(i).toBe(1);
expect(e).toBe(2);
}
);
hook.use(handler);
await hook.run(1, 2);
expect(handler).toBeCalledTimes(1);
});

test('with return value', async () => {
const hook = createAsyncParallelHook<void, void, number>();
test('result should be array', async () => {
const hook = createAsyncParallelHook<void, void, number | void>();
hook.use(() => 10);
hook.use(() => {});
hook.use(async () => 20);
const result = await hook.run();
expect(result).toStrictEqual([10, 20]);
expect(result).toStrictEqual([10, undefined, 20]);
});
});
61 changes: 61 additions & 0 deletions packages/hook/src/__tests__/hooks/asyncSeriesBailHook.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
createAsyncSeriesBailHook,
AsyncSeriesBailHookHandler
} from '../../index';
import { sleep } from '../utils';

describe('AsyncSeriesBailHook', () => {
test('hooks should run in sequence', async () => {
const hook = createAsyncSeriesBailHook<void>();
const logs: string[] = [];
hook.use(async () => {
await sleep(10);
logs.push('hook 1');
});
hook.use(() => {
logs.push('hook 2');
});
await hook.run();
expect(logs).toEqual(['hook 1', 'hook 2']);
});

test('the params of run() should be as the params of the hook handler', async () => {
const hook = createAsyncSeriesBailHook<number, number>();
const handler: AsyncSeriesBailHookHandler<number, number, void> = jest.fn(
(i, e) => {
expect(i).toBe(1);
expect(e).toBe(2);
}
);
hook.use(handler);
await hook.run(1, 2);
expect(handler).toBeCalledTimes(1);
});

test('hook result should be the return value of the first handler that returns value', async () => {
const hook = createAsyncSeriesBailHook<void, void, number>();
const handler1 = jest.fn(() => {});
const handler2 = jest.fn(async () => 10);
const handler3 = jest.fn(async () => 20);
hook.use(handler1);
hook.use(handler2);
hook.use(handler3);
const result = await hook.run();
expect(result).toBe(10);
expect(handler1).toBeCalledTimes(1);
expect(handler2).toBeCalledTimes(1);
expect(handler3).toBeCalledTimes(0);
});

test('hook result should be undefined if none of the handlers returns value', async () => {
const hook = createAsyncSeriesBailHook<void, void, number>();
const handler1 = jest.fn(() => {});
const handler2 = jest.fn(async () => {});
hook.use(handler1);
hook.use(handler2);
const result = await hook.run();
expect(result).toBe(undefined);
expect(handler1).toBeCalledTimes(1);
expect(handler2).toBeCalledTimes(1);
});
});
40 changes: 40 additions & 0 deletions packages/hook/src/__tests__/hooks/asyncSeriesHook.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { AsyncSeriesHookHandler, createAsyncSeriesHook } from '../../hooks';
import { sleep } from '../utils';

describe('AsyncSeriesHook', () => {
test('hooks should run in sequence', async () => {
const hook = createAsyncSeriesHook<void>();
const logs: string[] = [];
hook.use(async () => {
await sleep(10);
logs.push('hook 1');
});
hook.use(() => {
logs.push('hook 2');
});
await hook.run();
expect(logs).toEqual(['hook 1', 'hook 2']);
});

test('the params of run() should be as the params of the hook handler', async () => {
const hook = createAsyncSeriesHook<number, number>();
const handler: AsyncSeriesHookHandler<number, number, void> = jest.fn(
(i, e) => {
expect(i).toBe(1);
expect(e).toBe(2);
}
);
hook.use(handler);
await hook.run(1, 2);
expect(handler).toBeCalledTimes(1);
});

test('result should be array', async () => {
const hook = createAsyncSeriesHook<void, void, number | void>();
hook.use(() => 10);
hook.use(() => {});
hook.use(async () => 20);
const result = await hook.run();
expect(result).toStrictEqual([10, undefined, 20]);
});
});
85 changes: 60 additions & 25 deletions packages/hook/src/__tests__/hooks/asyncSeriesWaterfallHook.test.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,72 @@
import { createAsyncSeriesWaterfallHook } from '../../hooks';
import {
AsyncSeriesWaterfallHookHandler,
createAsyncSeriesWaterfallHook
} from '../../hooks';
import { sleep } from '../utils';

beforeEach(() => {});

afterEach(async () => {});

describe('syncHook', () => {
console.log = jest.fn();
test('initialValue-void', async () => {
describe('AsyncSeriesWaterfallHook', () => {
test('hooks should run in sequence', async () => {
const hook = createAsyncSeriesWaterfallHook<void>();
hook.use(() => {
console.log('hook 1');
const logs: string[] = [];
hook.use(async () => {
await sleep(10);
logs.push('hook 1');
});
hook.use(() => {
console.log('hook 2');
});
hook.use(async () => {
console.log('hook 3');
logs.push('hook 2');
});
await hook.run();
expect(console.log).toHaveBeenNthCalledWith(1, 'hook 1');
expect(console.log).toHaveBeenNthCalledWith(2, 'hook 2');
expect(console.log).toHaveBeenNthCalledWith(3, 'hook 3');
expect(logs).toEqual(['hook 1', 'hook 2']);
});

test('initialValue-normal extraArg-void', async () => {
const hook = createAsyncSeriesWaterfallHook<number, void>();
hook.use(async i => {
return i * 2;
test('the params of run() should be as the params of the hook handler', async () => {
const hook = createAsyncSeriesWaterfallHook<number, number>();
const handler: AsyncSeriesWaterfallHookHandler<number, number> = jest.fn(
(i, e) => {
expect(i).toBe(1);
expect(e).toBe(2);
return i + e;
}
);
hook.use(handler);
await hook.run(1, 2);
expect(handler).toBeCalledTimes(1);
});

test('the initial value of the hook handler should be the return value of the previous hook handler', async () => {
const hook = createAsyncSeriesWaterfallHook<number | undefined, number>();
const handler1: AsyncSeriesWaterfallHookHandler<
number | undefined,
number
> = jest.fn((i, e) => {
expect(i).toBe(1);
expect(e).toBe(2);
return undefined;
});

const handler2: AsyncSeriesWaterfallHookHandler<
number | undefined,
number
> = jest.fn(async (i, e) => {
expect(i).toBe(undefined);
expect(e).toBe(2);
return 10;
});
hook.use(i => {
return i * 3;

const handler3: AsyncSeriesWaterfallHookHandler<
number | undefined,
number
> = jest.fn((i, e) => {
expect(i).toBe(10);
expect(e).toBe(2);
return undefined;
});
const result = await hook.run(10);
expect(result).toBe(60);

hook.use(handler1, handler2, handler3);
const result = await hook.run(1, 2);
expect(result).toBeUndefined();
expect(handler1).toBeCalledTimes(1);
expect(handler2).toBeCalledTimes(1);
expect(handler3).toBeCalledTimes(1);
});
});
3 changes: 3 additions & 0 deletions packages/hook/src/__tests__/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function sleep(timeout: number) {
return new Promise(resolve => setTimeout(resolve, timeout));
}
Loading

0 comments on commit 61b4eae

Please sign in to comment.