-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(hook): add AsyncSeriesHook & AsyncSeriesBailHook
- Loading branch information
Showing
7 changed files
with
308 additions
and
154 deletions.
There are no files selected for viewing
146 changes: 27 additions & 119 deletions
146
packages/hook/src/__tests__/hooks/asyncParallelHook.test.ts
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 |
---|---|---|
@@ -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
61
packages/hook/src/__tests__/hooks/asyncSeriesBailHook.test.ts
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,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); | ||
}); | ||
}); |
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,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
85
packages/hook/src/__tests__/hooks/asyncSeriesWaterfallHook.test.ts
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 |
---|---|---|
@@ -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); | ||
}); | ||
}); |
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,3 @@ | ||
export function sleep(timeout: number) { | ||
return new Promise(resolve => setTimeout(resolve, timeout)); | ||
} |
Oops, something went wrong.