Skip to content

Commit e13f07a

Browse files
authoredMar 18, 2025··
feat: add mode to fn hooks (#259)
1 parent 2aa3ae6 commit e13f07a

File tree

3 files changed

+34
-16
lines changed

3 files changed

+34
-16
lines changed
 

‎src/task.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export class Task extends EventTarget {
107107
this.dispatchEvent(createBenchEvent('start', this))
108108
await this.bench.opts.setup?.(this, 'run')
109109
const { error, samples: latencySamples } = (await this.benchmark(
110+
'run',
110111
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
111112
this.bench.opts.time!,
112113
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -142,6 +143,7 @@ export class Task extends EventTarget {
142143
)
143144

144145
const { error, samples: latencySamples } = this.benchmarkSync(
146+
'run',
145147
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
146148
this.bench.opts.time!,
147149
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -170,6 +172,7 @@ export class Task extends EventTarget {
170172
this.dispatchEvent(createBenchEvent('warmup', this))
171173
await this.bench.opts.setup?.(this, 'warmup')
172174
const { error } = (await this.benchmark(
175+
'warmup',
173176
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
174177
this.bench.opts.warmupTime!,
175178
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -198,6 +201,7 @@ export class Task extends EventTarget {
198201
)
199202

200203
const { error } = this.benchmarkSync(
204+
'warmup',
201205
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
202206
this.bench.opts.warmupTime!,
203207
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -214,12 +218,13 @@ export class Task extends EventTarget {
214218
}
215219

216220
private async benchmark (
221+
mode: 'run' | 'warmup',
217222
time: number,
218223
iterations: number
219224
): Promise<{ error?: unknown; samples?: number[] }> {
220225
if (this.fnOpts.beforeAll != null) {
221226
try {
222-
await this.fnOpts.beforeAll.call(this)
227+
await this.fnOpts.beforeAll.call(this, mode)
223228
} catch (error) {
224229
return { error }
225230
}
@@ -230,7 +235,7 @@ export class Task extends EventTarget {
230235
const samples: number[] = []
231236
const benchmarkTask = async () => {
232237
if (this.fnOpts.beforeEach != null) {
233-
await this.fnOpts.beforeEach.call(this)
238+
await this.fnOpts.beforeEach.call(this, mode)
234239
}
235240

236241
let taskTime = 0 // ms;
@@ -254,7 +259,7 @@ export class Task extends EventTarget {
254259
totalTime += taskTime
255260

256261
if (this.fnOpts.afterEach != null) {
257-
await this.fnOpts.afterEach.call(this)
262+
await this.fnOpts.afterEach.call(this, mode)
258263
}
259264
}
260265

@@ -282,7 +287,7 @@ export class Task extends EventTarget {
282287

283288
if (this.fnOpts.afterAll != null) {
284289
try {
285-
await this.fnOpts.afterAll.call(this)
290+
await this.fnOpts.afterAll.call(this, mode)
286291
} catch (error) {
287292
return { error }
288293
}
@@ -291,12 +296,13 @@ export class Task extends EventTarget {
291296
}
292297

293298
private benchmarkSync (
299+
mode: 'run' | 'warmup',
294300
time: number,
295301
iterations: number
296302
): { error?: unknown; samples?: number[] } {
297303
if (this.fnOpts.beforeAll != null) {
298304
try {
299-
const beforeAllResult = this.fnOpts.beforeAll.call(this)
305+
const beforeAllResult = this.fnOpts.beforeAll.call(this, mode)
300306
invariant(
301307
!isPromiseLike(beforeAllResult),
302308
'`beforeAll` function must be sync when using `runSync()`'
@@ -311,7 +317,7 @@ export class Task extends EventTarget {
311317
const samples: number[] = []
312318
const benchmarkTask = () => {
313319
if (this.fnOpts.beforeEach != null) {
314-
const beforeEachResult = this.fnOpts.beforeEach.call(this)
320+
const beforeEachResult = this.fnOpts.beforeEach.call(this, mode)
315321
invariant(
316322
!isPromiseLike(beforeEachResult),
317323
'`beforeEach` function must be sync when using `runSync()`'
@@ -336,7 +342,7 @@ export class Task extends EventTarget {
336342
totalTime += taskTime
337343

338344
if (this.fnOpts.afterEach != null) {
339-
const afterEachResult = this.fnOpts.afterEach.call(this)
345+
const afterEachResult = this.fnOpts.afterEach.call(this, mode)
340346
invariant(
341347
!isPromiseLike(afterEachResult),
342348
'`afterEach` function must be sync when using `runSync()`'
@@ -358,7 +364,7 @@ export class Task extends EventTarget {
358364

359365
if (this.fnOpts.afterAll != null) {
360366
try {
361-
const afterAllResult = this.fnOpts.afterAll.call(this)
367+
const afterAllResult = this.fnOpts.afterAll.call(this, mode)
362368
invariant(
363369
!isPromiseLike(afterAllResult),
364370
'`afterAll` function must be sync when using `runSync()`'

‎src/types.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -113,33 +113,41 @@ export type EventListener = (evt: BenchEvent) => void
113113
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
114114
export type Fn = () => Promise<unknown> | unknown
115115

116+
/**
117+
* The task hook function signature
118+
* If warmup is enabled, the hook will be called twice, once for the warmup and once for the run.
119+
* @param mode the mode where the hook is being called
120+
*/
121+
export type FnHook = (this: Task, mode?: 'run' | 'warmup') => Promise<void> | void
122+
116123
/**
117124
* the task function options
118125
*/
119126
export interface FnOptions {
120127
/**
121128
* An optional function that is run after all iterations of this task end
122129
*/
123-
afterAll?: (this: Task) => Promise<void> | void
130+
afterAll?: FnHook
124131

125132
/**
126133
* An optional function that is run after each iteration of this task
127134
*/
128-
afterEach?: (this: Task) => Promise<void> | void
135+
afterEach?: FnHook
129136

130137
/**
131138
* An optional function that is run before iterations of this task begin
132139
*/
133-
beforeAll?: (this: Task) => Promise<void> | void
140+
beforeAll?: FnHook
134141

135142
/**
136143
* An optional function that is run before each iteration of this task
137144
*/
138-
beforeEach?: (this: Task) => Promise<void> | void
145+
beforeEach?: FnHook
139146
}
140147

141148
/**
142149
* Hook function signature
150+
* If warmup is enabled, the hook will be called twice, once for the warmup and once for the run.
143151
* @param task the task instance
144152
* @param mode the mode where the hook is being called
145153
*/

‎test/index.test.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -990,11 +990,13 @@ test('task beforeAll, afterAll, beforeEach, afterEach (async)', async () => {
990990
await bench.run()
991991

992992
expect(beforeAll).toHaveBeenCalledTimes(2 /* warmup + run */)
993+
expect(beforeAll.mock.calls).toEqual([['warmup'], ['run']])
993994
expect(afterAll).toHaveBeenCalledTimes(2 /* warmup + run */)
994-
expect(beforeAll.mock.calls.length).toBe(afterAll.mock.calls.length)
995+
expect(afterAll.mock.calls).toEqual([['warmup'], ['run']])
995996
expect(beforeEach).toHaveBeenCalledTimes(iterations * 2 /* warmup + run */)
997+
expect(beforeEach.mock.calls).toEqual(Array(iterations).fill(['warmup']).concat(Array(iterations).fill(['run'])))
996998
expect(afterEach).toHaveBeenCalledTimes(iterations * 2 /* warmup + run */)
997-
expect(beforeEach.mock.calls.length).toBe(afterEach.mock.calls.length)
999+
expect(afterEach.mock.calls).toEqual(Array(iterations).fill(['warmup']).concat(Array(iterations).fill(['run'])))
9981000
})
9991001

10001002
test('task beforeAll, afterAll, beforeEach, afterEach (sync)', () => {
@@ -1034,11 +1036,13 @@ test('task beforeAll, afterAll, beforeEach, afterEach (sync)', () => {
10341036
bench.runSync()
10351037

10361038
expect(beforeAll).toHaveBeenCalledTimes(2 /* warmup + run */)
1039+
expect(beforeAll.mock.calls).toEqual([['warmup'], ['run']])
10371040
expect(afterAll).toHaveBeenCalledTimes(2 /* warmup + run */)
1038-
expect(beforeAll.mock.calls.length).toBe(afterAll.mock.calls.length)
1041+
expect(afterAll.mock.calls).toEqual([['warmup'], ['run']])
10391042
expect(beforeEach).toHaveBeenCalledTimes(iterations * 2 /* warmup + run */)
1043+
expect(beforeEach.mock.calls).toEqual(Array(iterations).fill(['warmup']).concat(Array(iterations).fill(['run'])))
10401044
expect(afterEach).toHaveBeenCalledTimes(iterations * 2 /* warmup + run */)
1041-
expect(beforeEach.mock.calls.length).toBe(afterEach.mock.calls.length)
1045+
expect(afterEach.mock.calls).toEqual(Array(iterations).fill(['warmup']).concat(Array(iterations).fill(['run'])))
10421046
})
10431047

10441048
test(

0 commit comments

Comments
 (0)
Please sign in to comment.