diff --git a/README.md b/README.md index 7eb7bcf..847cb44 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,9 @@ If you need to configure the script at runtime, use environment variables and op ### TypeScript -cronometro uses [ts-node](https://www.npmjs.com/package/ts-node) to compile TypeScript files on the fly. +cronometro can run on TypeScript files. Type deletion happens on the fly with no additional configuration required. -ts-node and TypeScript are not installed automatically by cronometro (as they are listed in `peerDependencies`) so you need to do it manually. - -To pass the `tsconfig.json` project file to use, use the `TS_NODE_PROJECT` environment variable. +Use the `TS_NODE_PROJECT` environment variable to provide a TypeScript configuration. ### API use @@ -102,10 +100,10 @@ Each property value is a object with the following properties: import cronometro from 'cronometro' const results = cronometro({ - test1: function () { + await test1: function () { // Do something }, - test2: function () { + await test2: function () { // Do something else } }) diff --git a/package.json b/package.json index fe72136..3c7ecc8 100644 --- a/package.json +++ b/package.json @@ -33,13 +33,14 @@ "format": "prettier -w src test", "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src test", "typecheck": "tsc -p . --emitDeclarationOnly", - "test": "c8 -c test/config/c8-local.json tap test/*.test.ts", - "test:ci": "c8 -c test/config/c8-ci.json tap --no-color test/*.test.ts", + "test": "TS_NODE_PROJECT=tsconfig.test.json c8 -c test/config/c8-local.json node --import @swc-node/register/esm-register --test test/*.test.ts", + "test:ci": "TS_NODE_PROJECT=tsconfig.test.json c8 -c test/config/c8-ci.json node --import @swc-node/register/esm-register --test-reporter=tap --test test/*.test.ts", "ci": "npm run build && npm run test:ci", "prepublishOnly": "npm run ci", "postpublish": "git push origin && git push origin -f --tags" }, "dependencies": { + "@swc-node/register": "^1.8.0", "acquerello": "^2.0.6", "hdr-histogram-js": "^3.0.0", "table": "^6.8.1" @@ -55,14 +56,9 @@ "concurrently": "^8.2.2", "prettier": "^3.2.4", "proxyquire": "^2.1.3", - "tap": "^18.7.0", - "ts-node": "^10.9.2", "typescript": "^5.3.3" }, "engines": { "node": ">= 18.18.0" - }, - "tap": { - "extends": "./test/config/tap.yml" } } diff --git a/src/index.ts b/src/index.ts index 1e06442..0abb104 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,12 @@ import { isMainThread, Worker, workerData } from 'node:worker_threads' import { defaultOptions, - type Result, runnerPath, type Callback, type Context, type Options, type PrintOptions, + type Result, type Results, type Tests } from './models.js' diff --git a/src/models.ts b/src/models.ts index ef1a64d..e4bee50 100644 --- a/src/models.ts +++ b/src/models.ts @@ -8,8 +8,10 @@ export interface PrintOptions { compareMode?: 'base' | 'previous' } +export type SetupFunctionCallback = (err?: Error | null) => void + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -export type SetupFunction = (cb: (err?: Error | null) => void) => Promise | void +export type SetupFunction = (cb: SetupFunctionCallback) => Promise | void export interface Options { iterations: number @@ -33,8 +35,6 @@ export interface Test { after?: SetupFunction } -export type Callback = (err: Error | null, results: Results) => any - export type Percentiles = Record export interface Result { @@ -49,6 +49,8 @@ export interface Result { percentiles: Percentiles } +export type Callback = (err: Error | null, results: Results) => any + export type Tests = Record export type Results = Record @@ -98,4 +100,10 @@ export const defaultOptions = { export const percentiles = [0.001, 0.01, 0.1, 1, 2.5, 10, 25, 50, 75, 90, 97.5, 99, 99.9, 99.99, 99.999] -export const runnerPath = resolve(import.meta.url.replace('file://', '').replace(/models.(js|ts)/, ''), './runner.js') +export const runnerPath = resolve( + import.meta.url + .replace('file://', '') + .replace('/src/', '/dist/') + .replace(/models.(js|ts)/, ''), + './runner.js' +) diff --git a/src/runner.ts b/src/runner.ts index 8c7e121..54e1dfe 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -1,3 +1,4 @@ +/* c8 ignore start */ import { isMainThread, parentPort, workerData } from 'node:worker_threads' import { type WorkerContext } from './models.js' import { runWorker } from './worker.js' @@ -6,45 +7,31 @@ if (isMainThread) { throw new Error('Do not run this file as main script.') } -// Register ts-node for TypeScript inclusion -let chain: Promise = Promise.resolve() - -/* c8 ignore start */ if (workerData.path.endsWith('.ts')) { - const instance = Symbol.for('ts-node.register.instance') - - if (!(instance in process)) { - chain = import('ts-node').then(({ register }) => { - register({ project: process.env.TS_NODE_PROJECT }) - }) - } + await import('@swc-node/register/esm-register') } // Require the script to set tests -chain - .then(() => { - return import(workerData.path) - }) - .then(module => { - if (typeof module === 'function') { - return module() - } else if (typeof module.default === 'function') { - return module.default() - } - }) - .then(() => { - // Run the worker - runWorker( - workerData as WorkerContext, - value => { - parentPort!.postMessage({ type: 'cronometro.result', payload: value }) - }, - (code: number) => process.exit(code) - ) - }) - .catch(error => { - process.nextTick(() => { - throw error - }) +try { + const module = await import(workerData.path) + + if (typeof module === 'function') { + await module() + } else if (typeof module.default === 'function') { + await module.default() + } + + // Run the worker + runWorker( + workerData as WorkerContext, + value => { + parentPort!.postMessage({ type: 'cronometro.result', payload: value }) + }, + (code: number) => process.exit(code) + ) +} catch (error) { + process.nextTick(() => { + throw error }) +} /* c8 ignore stop */ diff --git a/src/worker.ts b/src/worker.ts index ea534a1..4b4a9ef 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -101,11 +101,13 @@ function runTestIteration(context: TestContext): void { context.handler(null) } } catch (error) { + /* c8 ignore start */ // If a error was thrown, only handle if the original function length is 0, which means it's a sync error, otherwise propagate if (context.test.length === 0) { context.handler(error as Error) return } + /* c8 ignore end */ throw error } diff --git a/test/asyncImport.test.ts b/test/asyncImport.test.ts index 70a5779..2dab3a0 100644 --- a/test/asyncImport.test.ts +++ b/test/asyncImport.test.ts @@ -1,14 +1,26 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - +import { deepStrictEqual, ifError, ok } from 'node:assert' +import { test } from 'node:test' import { isMainThread } from 'node:worker_threads' -import t from 'tap' import { cronometro, percentiles } from '../src/index.js' -async function main(): Promise { - await new Promise(resolve => setTimeout(resolve, 100)) +await new Promise(resolve => setTimeout(resolve, 100)) - if (!isMainThread) { - cronometro( +if (!isMainThread) { + cronometro( + { + single() { + Buffer.alloc(10) + }, + multiple() { + Buffer.alloc(10) + Buffer.alloc(20) + } + }, + () => false + ) +} else { + await test('Collecting results', async () => { + const results = await cronometro( { single() { Buffer.alloc(10) @@ -18,43 +30,24 @@ async function main(): Promise { Buffer.alloc(20) } }, - () => false + { iterations: 10, print: false } ) - } else { - t.test('Collecting results', async t => { - const results = await cronometro( - { - single() { - Buffer.alloc(10) - }, - multiple() { - Buffer.alloc(10) - Buffer.alloc(20) - } - }, - { iterations: 10, print: false } - ) - t.strictSame(Object.keys(results), ['single', 'multiple']) + deepStrictEqual(Object.keys(results), ['single', 'multiple']) - for (const entry of Object.values(results)) { - t.ok(entry.success) - t.type(entry.error, 'undefined') - t.equal(entry.size, 10) - t.type(entry.min, 'number') - t.type(entry.max, 'number') - t.type(entry.mean, 'number') - t.type(entry.stddev, 'number') - t.type(entry.standardError, 'number') + for (const entry of Object.values(results)) { + ok(entry.success) + ifError(entry.error) + deepStrictEqual(entry.size, 10) + deepStrictEqual(typeof entry.min, 'number') + deepStrictEqual(typeof entry.max, 'number') + deepStrictEqual(typeof entry.mean, 'number') + deepStrictEqual(typeof entry.stddev, 'number') + deepStrictEqual(typeof entry.standardError, 'number') - for (const percentile of percentiles) { - t.type(entry.percentiles[percentile.toString()], 'number') - } + for (const percentile of percentiles) { + ok(typeof entry.percentiles[percentile.toString()], 'number') } - }) - } + } + }) } - -main() - -export default main diff --git a/test/callbacks.test.ts b/test/callbacks.test.ts index 7659b6a..464ac4b 100644 --- a/test/callbacks.test.ts +++ b/test/callbacks.test.ts @@ -1,10 +1,13 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ -import { isMainThread, Worker } from 'node:worker_threads' -import t from 'tap' +import { deepStrictEqual, match, ok } from 'node:assert' +import { test } from 'node:test' +import { Worker, isMainThread, parentPort } from 'node:worker_threads' import { cronometro, type Result, type TestFunction } from '../src/index.js' if (!isMainThread) { + parentPort!.postMessage('another') + cronometro( { single() { @@ -18,7 +21,7 @@ if (!isMainThread) { () => false ) } else { - t.test('Callbacks', async t => { + test('Callbacks', async () => { await cronometro( { single() { @@ -35,24 +38,24 @@ if (!isMainThread) { iterations: 10, print: false, onTestStart(name: string, data: any, worker: Worker) { - t.match(name, /single|multiple|missing/) - t.ok(data.index < 3) - t.ok(worker instanceof Worker) + match(name, /single|multiple|missing/) + ok(data.index < 3) + ok(worker instanceof Worker) }, onTestEnd(name: string, result: Result, worker: Worker) { if (result.success) { - t.same(name, 'single') - t.ok(result.size > 0) + deepStrictEqual(name, 'single') + ok(result.size > 0) } else { - t.same(name, 'multiple') - t.same(result.error!.message, 'INVALID') + deepStrictEqual(name, 'multiple') + deepStrictEqual(result.error!.message, 'INVALID') } - t.ok(worker instanceof Worker) + ok(worker instanceof Worker) }, onTestError(name: string, error: Error, worker: Worker) { - t.same(name, 'missing') - t.same(error.message, "Cannot read properties of undefined (reading 'test')") - t.ok(worker instanceof Worker) + deepStrictEqual(name, 'missing') + deepStrictEqual(error.message, "Cannot read properties of undefined (reading 'test')") + ok(worker instanceof Worker) } } ) diff --git a/test/config/c8-ci.json b/test/config/c8-ci.json index a8081eb..bcd0a27 100644 --- a/test/config/c8-ci.json +++ b/test/config/c8-ci.json @@ -1,6 +1,7 @@ { "check-coverage": true, "reporter": ["text", "json"], + "exclude": ["dist", "test"], "branches": 90, "functions": 90, "lines": 90, diff --git a/test/config/c8-local.json b/test/config/c8-local.json index 916baeb..e06f7ab 100644 --- a/test/config/c8-local.json +++ b/test/config/c8-local.json @@ -1,3 +1,4 @@ { + "exclude": ["dist", "test"], "reporter": ["text", "html"] } diff --git a/test/config/tap.yml b/test/config/tap.yml deleted file mode 100644 index b5cb13c..0000000 --- a/test/config/tap.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -jobs: 5 -timeout: 60 -disable-coverage: true -allow-empty-coverage: true -node-arg: - - --loader=ts-node/esm diff --git a/test/errorHandling.test.ts b/test/errorHandling.test.ts index 92de5d2..1072e3c 100644 --- a/test/errorHandling.test.ts +++ b/test/errorHandling.test.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ +import { deepStrictEqual, ifError, ok, rejects } from 'node:assert' +import { test } from 'node:test' import { isMainThread } from 'node:worker_threads' -import t from 'tap' import { cronometro, percentiles } from '../src/index.js' if (!isMainThread) { @@ -17,7 +18,7 @@ if (!isMainThread) { () => false ) } else { - t.test('Errored tests handling', async t => { + test('Errored tests handling', async () => { const results = await cronometro( { single() { @@ -30,38 +31,38 @@ if (!isMainThread) { { iterations: 10, print: false } ) - t.strictSame(Object.keys(results), ['single', 'multiple']) + deepStrictEqual(Object.keys(results), ['single', 'multiple']) - t.ok(results.single.success) - t.type(results.single.error, 'undefined') - t.equal(results.single.size, 10) - t.type(results.single.min, 'number') - t.type(results.single.max, 'number') - t.type(results.single.mean, 'number') - t.type(results.single.stddev, 'number') - t.type(results.single.standardError, 'number') + ok(results.single.success) + ifError(results.single.error) + deepStrictEqual(results.single.size, 10) + deepStrictEqual(typeof results.single.min, 'number') + deepStrictEqual(typeof results.single.max, 'number') + deepStrictEqual(typeof results.single.mean, 'number') + deepStrictEqual(typeof results.single.stddev, 'number') + deepStrictEqual(typeof results.single.standardError, 'number') for (const percentile of percentiles) { - t.type(results.single.percentiles[percentile.toString()], 'number') + ok(typeof results.single.percentiles[percentile.toString()], 'number') } - t.notOk(results.multiple.success) - t.type(results.multiple.error, Error) - t.equal(results.multiple.error!.message, 'FAILED') - t.equal(results.multiple.size, 0) - t.equal(results.multiple.min, 0) - t.equal(results.multiple.max, 0) - t.equal(results.multiple.mean, 0) - t.equal(results.multiple.stddev, 0) - t.equal(results.multiple.standardError, 0) - t.strictSame(results.multiple.percentiles, {}) + ok(!results.multiple.success) + ok(results.multiple.error instanceof Error) + deepStrictEqual(results.multiple.error.message, 'FAILED') + deepStrictEqual(results.multiple.size, 0) + deepStrictEqual(results.multiple.min, 0) + deepStrictEqual(results.multiple.max, 0) + deepStrictEqual(results.multiple.mean, 0) + deepStrictEqual(results.multiple.stddev, 0) + deepStrictEqual(results.multiple.standardError, 0) + deepStrictEqual(results.multiple.percentiles, {}) }) - t.test('Runner cannot be run in main thread', async t => { - await t.rejects(import('../src/runner.js'), { message: 'Do not run this file as main script.' }) + test('Runner cannot be run in main thread', async () => { + await rejects(import('../src/runner.js'), { message: 'Do not run this file as main script.' }) }) - t.test('Runner reports setup errors', async t => { + test('Runner reports setup errors', async () => { const results = await cronometro( { notDefined() { @@ -71,6 +72,6 @@ if (!isMainThread) { { iterations: 10, print: false } ) - t.strictSame(Object.keys(results), ['notDefined']) + deepStrictEqual(Object.keys(results), ['notDefined']) }) } diff --git a/test/genericErrorHandling.test.ts b/test/genericErrorHandling.test.ts index cb968bd..3cd1ea5 100644 --- a/test/genericErrorHandling.test.ts +++ b/test/genericErrorHandling.test.ts @@ -1,13 +1,12 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - +import { deepStrictEqual, ok } from 'node:assert' +import { test } from 'node:test' import { isMainThread } from 'node:worker_threads' -import t from 'tap' import { cronometro, type Tests } from '../src/index.js' if (!isMainThread) { cronometro(undefined as unknown as Tests, () => false) } else { - t.test('Generic error handling', async t => { + await test('Generic error handling', async () => { const results = await cronometro( { single() { @@ -20,12 +19,12 @@ if (!isMainThread) { { iterations: 10, print: false } ) - t.notOk(results.single.success) - t.type(results.single.error, Error) - t.equal(results.single.error!.message, 'Cannot convert undefined or null to object') + ok(!results.single.success) + ok(results.single.error instanceof Error) + deepStrictEqual(results.single.error.message, 'Cannot convert undefined or null to object') - t.notOk(results.single.success) - t.type(results.single.error, Error) - t.equal(results.single.error!.message, 'Cannot convert undefined or null to object') + ok(!results.single.success) + ok(results.single.error instanceof Error) + deepStrictEqual(results.single.error.message, 'Cannot convert undefined or null to object') }) } diff --git a/test/optionsValidation.test.ts b/test/optionsValidation.test.ts index d22ae3e..d804f48 100644 --- a/test/optionsValidation.test.ts +++ b/test/optionsValidation.test.ts @@ -1,10 +1,11 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ -import t from 'tap' +import { deepStrictEqual, ok, rejects } from 'node:assert' +import { test } from 'node:test' import { cronometro } from '../src/index.js' -t.test('Options validation', async t => { - await t.rejects( +test('Options validation', async () => { + await rejects( () => cronometro( { @@ -33,8 +34,8 @@ t.test('Options validation', async t => { }, { errorThreshold: -1 }, err => { - t.type(err, 'Error') - t.equal(err!.message, 'The errorThreshold option must be a number between 0 and 100.') + ok(err instanceof Error) + deepStrictEqual(err.message, 'The errorThreshold option must be a number between 0 and 100.') } ) @@ -50,8 +51,8 @@ t.test('Options validation', async t => { }, { onTestStart: 1 as any }, err => { - t.type(err, 'Error') - t.equal(err!.message, 'The onTestStart option must be a function.') + ok(err instanceof Error) + deepStrictEqual(err.message, 'The onTestStart option must be a function.') } ) @@ -67,8 +68,8 @@ t.test('Options validation', async t => { }, { onTestEnd: 1 as any }, err => { - t.type(err, 'Error') - t.equal(err!.message, 'The onTestEnd option must be a function.') + ok(err instanceof Error) + deepStrictEqual(err.message, 'The onTestEnd option must be a function.') } ) @@ -84,8 +85,8 @@ t.test('Options validation', async t => { }, { onTestError: 1 as any }, err => { - t.type(err, 'Error') - t.equal(err!.message, 'The onTestError option must be a function.') + ok(err instanceof Error) + deepStrictEqual(err.message, 'The onTestError option must be a function.') } ) }) diff --git a/test/print.test.ts b/test/print.test.ts index e5ac283..e85e2d6 100644 --- a/test/print.test.ts +++ b/test/print.test.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ +import { deepStrictEqual, ifError, match, ok } from 'node:assert' +import { test } from 'node:test' import { isMainThread } from 'node:worker_threads' -import t from 'tap' import { cronometro, defaultOptions, percentiles } from '../src/index.js' import { setLogger } from '../src/print.js' @@ -10,8 +11,6 @@ function removeStyle(source: string): string { return source.replaceAll(/\u001B\[\d+m/g, '') } -function loggerBase(): void {} - defaultOptions.iterations = 10 if (!isMainThread) { @@ -30,8 +29,8 @@ if (!isMainThread) { () => false ) } else { - t.test('Printing - Default options', t => { - const logger = t.captureFn(loggerBase) + test('Printing - Default options', (t, done) => { + const logger = t.mock.fn() setLogger(logger) cronometro( @@ -47,48 +46,48 @@ if (!isMainThread) { } }, (err, results) => { - t.equal(err, null) - t.strictSame(Object.keys(results), ['single', 'multiple', 'error']) - - t.notOk(results.error.success) - t.type(results.error.error, Error) - t.equal(results.error.error!.message, 'FAILED') - t.equal(results.error.size, 0) - t.equal(results.error.min, 0) - t.equal(results.error.max, 0) - t.equal(results.error.mean, 0) - t.equal(results.error.stddev, 0) - t.equal(results.error.standardError, 0) - t.strictSame(results.error.percentiles, {}) + ifError(err) + deepStrictEqual(Object.keys(results), ['single', 'multiple', 'error']) + + ok(!results.error.success) + ok(results.error.error instanceof Error) + deepStrictEqual(results.error.error.message, 'FAILED') + deepStrictEqual(results.error.size, 0) + deepStrictEqual(results.error.min, 0) + deepStrictEqual(results.error.max, 0) + deepStrictEqual(results.error.mean, 0) + deepStrictEqual(results.error.stddev, 0) + deepStrictEqual(results.error.standardError, 0) + deepStrictEqual(results.error.percentiles, {}) delete results.error for (const entry of Object.values(results)) { - t.ok(entry.success) - t.type(entry.error, 'undefined') - t.equal(entry.size, 10) - t.type(entry.min, 'number') - t.type(entry.max, 'number') - t.type(entry.mean, 'number') - t.type(entry.stddev, 'number') - t.type(entry.standardError, 'number') + ok(entry.success) + ifError(entry.error) + deepStrictEqual(entry.size, 10) + ok(typeof entry.min, 'number') + ok(typeof entry.max, 'number') + ok(typeof entry.mean, 'number') + ok(typeof entry.stddev, 'number') + ok(typeof entry.standardError, 'number') for (const percentile of percentiles) { - t.type(entry.percentiles[percentile.toString()], 'number') + ok(typeof entry.percentiles[percentile.toString()], 'number') } } - const output = removeStyle(logger.calls[0].args[0 as number]!) - t.match(output, /║\s+Slower tests\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+║/) - t.match(output, /║\s+Faster test\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+║/) - t.match(output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+║/) - t.match(output, /║\s+(error)\s+|\s+0\s+|\s+Errored\s+|\s+N\/A\s+║/) - t.end() + const output = removeStyle(logger.mock.calls[0].arguments[0] as string) + match(output, /║\s+Slower tests\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+║/) + match(output, /║\s+Faster test\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+║/) + match(output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+║/) + match(output, /║\s+(error)\s+|\s+0\s+|\s+Errored\s+|\s+N\/A\s+║/) + done() } ) }) - t.test('Printing - No colors', t => { - const logger = t.captureFn(loggerBase) + test('Printing - No colors', (t, done) => { + const logger = t.mock.fn() setLogger(logger) cronometro( @@ -105,20 +104,19 @@ if (!isMainThread) { }, { print: { colors: false } }, err => { - t.equal(err, null) + ifError(err) - const output = removeStyle(logger.calls[0].args[0 as number]!) + const output = removeStyle(logger.mock.calls[0].arguments[0] as string) // eslint-disable-next-line no-control-regex - t.notMatch(output, /\u001B/) - - t.end() + ok(!output.match(/\u001B/)) + done() } ) }) - t.test('Printing - Base compare', t => { - const logger = t.captureFn(loggerBase) + test('Printing - Base compare', (t, done) => { + const logger = t.mock.fn() setLogger(logger) cronometro( @@ -135,24 +133,24 @@ if (!isMainThread) { }, { print: { compare: true } }, err => { - t.equal(err, null) + ifError(err) - const output = removeStyle(logger.calls[0].args[0 as number]!) - t.match(output, /║\s+Slower tests\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with slowest║/) - t.match(output, /║\s+Fastest test\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with slowest║/) - t.match(output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+|\s+║/) - t.match( + const output = removeStyle(logger.mock.calls[0].arguments[0] as string) + match(output, /║\s+Slower tests\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with slowest║/) + match(output, /║\s+Fastest test\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with slowest║/) + match(output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+|\s+║/) + match( output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+|\s+\\+\s+\d+.\d{2}\s%\s+║/ ) - t.match(output, /║\s+(error)\s+|\s+0\s+|\s+Errored\s+|\s+N\/A\s+|\s+N\/A\s+║/) - t.end() + match(output, /║\s+(error)\s+|\s+0\s+|\s+Errored\s+|\s+N\/A\s+|\s+N\/A\s+║/) + done() } ) }) - t.test('Printing - Previous compare', t => { - const logger = t.captureFn(loggerBase) + test('Printing - Previous compare', (t, done) => { + const logger = t.mock.fn() setLogger(logger) cronometro( @@ -169,21 +167,18 @@ if (!isMainThread) { }, { print: { compare: true, compareMode: 'previous' } }, err => { - t.equal(err, null) + ifError(err) - const output = removeStyle(logger.calls[0].args[0 as number]!) - t.match( - output, - /║\s+Slower tests\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with previous\s+║/ - ) - t.match(output, /║\s+Faster test\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with previous\s+║/) - t.match(output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+|\s+║/) - t.match( + const output = removeStyle(logger.mock.calls[0].arguments[0] as string) + match(output, /║\s+Slower tests\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with previous\s+║/) + match(output, /║\s+Faster test\s+|\s+Samples\s+|\s+Result\s+|\s+Tolerance\s+|\s+Difference with previous\s+║/) + match(output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+|\s+║/) + match( output, /║\s+(single|multiple)\s+|\s+10\s+|\s+\d+\.\d{2}\sop\/sec\s+|\s+±\s\d+.\d{2}\s%\s+|\s+\\+\s+\d+.\d{2}\s%\s+║/ ) - t.match(output, /║\s+(error)\s+|\s+0\s+|\s+Errored\s+|\s+N\/A\s+|\s+N\/A\s+║/) - t.end() + match(output, /║\s+(error)\s+|\s+0\s+|\s+Errored\s+|\s+N\/A\s+|\s+N\/A\s+║/) + done() } ) }) diff --git a/test/success.test.ts b/test/success.test.ts index 816f125..591ada0 100644 --- a/test/success.test.ts +++ b/test/success.test.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - +import { deepStrictEqual, ifError, ok } from 'node:assert' +import { test } from 'node:test' import { isMainThread } from 'node:worker_threads' -import t from 'tap' import { cronometro, percentiles } from '../src/index.js' if (!isMainThread) { @@ -18,7 +17,7 @@ if (!isMainThread) { () => false ) } else { - t.test('Collecting results', async t => { + await test('Collecting results', async () => { const results = await cronometro( { single() { @@ -32,20 +31,20 @@ if (!isMainThread) { { iterations: 10, print: false } ) - t.strictSame(Object.keys(results), ['single', 'multiple']) + deepStrictEqual(Object.keys(results), ['single', 'multiple']) for (const entry of Object.values(results)) { - t.ok(entry.success) - t.type(entry.error, 'undefined') - t.equal(entry.size, 10) - t.type(entry.min, 'number') - t.type(entry.max, 'number') - t.type(entry.mean, 'number') - t.type(entry.stddev, 'number') - t.type(entry.standardError, 'number') + ok(entry.success) + ifError(entry.error) + deepStrictEqual(entry.size, 10) + ok(typeof entry.min, 'number') + ok(typeof entry.max, 'number') + ok(typeof entry.mean, 'number') + ok(typeof entry.stddev, 'number') + ok(typeof entry.standardError, 'number') for (const percentile of percentiles) { - t.type(entry.percentiles[percentile.toString()], 'number') + ok(typeof entry.percentiles[percentile.toString()], 'number') } } }) diff --git a/test/testsCallbacks.test.ts b/test/testsCallbacks.test.ts new file mode 100644 index 0000000..985b598 --- /dev/null +++ b/test/testsCallbacks.test.ts @@ -0,0 +1,88 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ + +import { deepStrictEqual, ifError, ok } from 'node:assert' +import { test } from 'node:test' +import { isMainThread } from 'node:worker_threads' +import { cronometro, type SetupFunctionCallback } from '../src/index.js' + +if (!isMainThread) { + cronometro( + { + first: { + before(cb: SetupFunctionCallback) { + cb() + }, + test() { + Buffer.alloc(20) + }, + after(cb: SetupFunctionCallback) { + cb() + } + }, + second: { + // eslint-disable-next-line @typescript-eslint/require-await + async before() { + throw new Error('FAILED ON BEFORE') + }, + test() { + Buffer.alloc(20) + } + }, + third: { + test() { + Buffer.alloc(20) + }, + after(cb: SetupFunctionCallback) { + cb(new Error('FAILED ON AFTER')) + } + } + }, + () => false + ) +} else { + test('Lifecycle Callbacks', async () => { + const results = await cronometro( + { + first: { + before(cb: SetupFunctionCallback) { + cb() + }, + test() { + Buffer.alloc(20) + }, + after(cb: SetupFunctionCallback) { + cb() + } + }, + second: { + // eslint-disable-next-line @typescript-eslint/require-await + async before() { + throw new Error('FAILED ON BEFORE') + }, + test() { + Buffer.alloc(20) + } + }, + third: { + test() { + Buffer.alloc(20) + }, + after(cb: SetupFunctionCallback) { + cb(new Error('FAILED ON AFTER')) + } + } + }, + { + iterations: 10, + print: false + } + ) + + ifError(results.first.error) + ok(results.second.error instanceof Error) + deepStrictEqual(results.second.error.message, 'FAILED ON BEFORE') + + ok(results.third.error instanceof Error) + deepStrictEqual(results.third.error.message, 'FAILED ON AFTER') + }) +} diff --git a/test/unhandledErrorHandling.test.ts b/test/unhandledErrorHandling.test.ts index 5a9893b..7d79457 100644 --- a/test/unhandledErrorHandling.test.ts +++ b/test/unhandledErrorHandling.test.ts @@ -1,8 +1,7 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - +import { deepStrictEqual, ifError, ok } from 'node:assert' +import { test } from 'node:test' import { isMainThread } from 'node:worker_threads' -import t from 'tap' -import { type Callback, cronometro, percentiles } from '../src/index.js' +import { cronometro, percentiles, type Callback } from '../src/index.js' if (!isMainThread) { cronometro( @@ -21,7 +20,7 @@ if (!isMainThread) { () => false ) } else { - t.test('Unhandled errored tests handling', async t => { + await test('Unhandled errored tests handling', async () => { const results = await cronometro( { single() { @@ -38,30 +37,30 @@ if (!isMainThread) { { iterations: 10, print: false } ) - t.strictSame(Object.keys(results), ['single', 'multiple']) + deepStrictEqual(Object.keys(results), ['single', 'multiple']) - t.ok(results.single.success) - t.type(results.single.error, 'undefined') - t.equal(results.single.size, 10) - t.type(results.single.min, 'number') - t.type(results.single.max, 'number') - t.type(results.single.mean, 'number') - t.type(results.single.stddev, 'number') - t.type(results.single.standardError, 'number') + ok(results.single.success) + ifError(results.single.error, 'undefined') + deepStrictEqual(results.single.size, 10) + ok(typeof results.single.min, 'number') + ok(typeof results.single.max, 'number') + ok(typeof results.single.mean, 'number') + ok(typeof results.single.stddev, 'number') + ok(typeof results.single.standardError, 'number') for (const percentile of percentiles) { - t.type(results.single.percentiles[percentile.toString()], 'number') + ok(typeof results.single.percentiles[percentile.toString()], 'number') } - t.notOk(results.multiple.success) - t.type(results.multiple.error, Error) - t.equal(results.multiple.error!.message, 'FAILED') - t.equal(results.multiple.size, 0) - t.equal(results.multiple.min, 0) - t.equal(results.multiple.max, 0) - t.equal(results.multiple.mean, 0) - t.equal(results.multiple.stddev, 0) - t.equal(results.multiple.standardError, 0) - t.strictSame(results.multiple.percentiles, {}) + ok(!results.multiple.success) + ok(results.multiple.error instanceof Error) + deepStrictEqual(results.multiple.error.message, 'FAILED') + deepStrictEqual(results.multiple.size, 0) + deepStrictEqual(results.multiple.min, 0) + deepStrictEqual(results.multiple.max, 0) + deepStrictEqual(results.multiple.mean, 0) + deepStrictEqual(results.multiple.stddev, 0) + deepStrictEqual(results.multiple.standardError, 0) + deepStrictEqual(results.multiple.percentiles, {}) }) } diff --git a/test/worker.test.ts b/test/worker.test.ts index eb98ebd..939e289 100644 --- a/test/worker.test.ts +++ b/test/worker.test.ts @@ -1,11 +1,13 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ -import t from 'tap' + +import { deepStrictEqual, ifError, ok } from 'node:assert' +import { test } from 'node:test' import { percentiles, type AsyncTest, type Result } from '../src/index.js' import { runWorker } from '../src/worker.js' -t.test('Worker execution - Handle sync functions that succeed', t => { +test('Worker execution - Handle sync functions that succeed', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -22,32 +24,32 @@ t.test('Worker execution - Handle sync functions that succeed', t => { }, notifier, code => { - t.equal(code, 0) - t.ok(mainCalls > 0) + deepStrictEqual(code, 0) + ok(mainCalls > 0) - const result = notifier.calls[0].args[0 as number]! as Result + const result = notifier.mock.calls[0].arguments[0] as Result - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 1000) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 1000) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker execution - Handle sync functions that throw errors', t => { +test('Worker execution - Handle sync functions that throw errors', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() /* eslint-disable-next-line @typescript-eslint/require-await */ async function main(): Promise { @@ -66,30 +68,30 @@ t.test('Worker execution - Handle sync functions that throw errors', t => { }, notifier, code => { - t.equal(code, 1) - t.ok(mainCalls > 0) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.notOk(result.success) - t.type(result.error, Error) - t.equal(result.error!.message, 'FAILED') - t.equal(result.size, 0) - t.equal(result.min, 0) - t.equal(result.max, 0) - t.equal(result.mean, 0) - t.equal(result.stddev, 0) - t.equal(result.standardError, 0) - t.strictSame(result.percentiles, {}) - - t.end() + deepStrictEqual(code, 1) + ok(mainCalls > 0) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(!result.success) + ok(result.error instanceof Error) + deepStrictEqual(result.error.message, 'FAILED') + deepStrictEqual(result.size, 0) + deepStrictEqual(result.min, 0) + deepStrictEqual(result.max, 0) + deepStrictEqual(result.mean, 0) + deepStrictEqual(result.stddev, 0) + deepStrictEqual(result.standardError, 0) + deepStrictEqual(result.percentiles, {}) + + done() } ) }) -t.test('Worker execution - Handle callback functions that succeed', t => { +test('Worker execution - Handle callback functions that succeed', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(cb: (err?: Error) => void): void { mainCalls++ @@ -108,32 +110,32 @@ t.test('Worker execution - Handle callback functions that succeed', t => { }, notifier, code => { - t.equal(code, 0) - t.ok(mainCalls > 0) + deepStrictEqual(code, 0) + ok(mainCalls > 0) - const result = notifier.calls[0].args[0 as number]! as Result + const result = notifier.mock.calls[0].arguments[0] as Result - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 10_000) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 10_000) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker execution - Handle callback functions that throw errors', t => { +test('Worker execution - Handle callback functions that throw errors', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(cb: (err?: Error) => void): void { mainCalls++ @@ -152,30 +154,30 @@ t.test('Worker execution - Handle callback functions that throw errors', t => { }, notifier, code => { - t.equal(code, 1) - t.ok(mainCalls > 0) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.notOk(result.success) - t.type(result.error, Error) - t.equal(result.error!.message, 'FAILED') - t.equal(result.size, 0) - t.equal(result.min, 0) - t.equal(result.max, 0) - t.equal(result.mean, 0) - t.equal(result.stddev, 0) - t.equal(result.standardError, 0) - t.strictSame(result.percentiles, {}) - - t.end() + deepStrictEqual(code, 1) + ok(mainCalls > 0) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(!result.success) + ok(result.error instanceof Error) + deepStrictEqual(result.error.message, 'FAILED') + deepStrictEqual(result.size, 0) + deepStrictEqual(result.min, 0) + deepStrictEqual(result.max, 0) + deepStrictEqual(result.mean, 0) + deepStrictEqual(result.stddev, 0) + deepStrictEqual(result.standardError, 0) + deepStrictEqual(result.percentiles, {}) + + done() } ) }) -t.test('Worker execution - Handle promise functions that resolve', t => { +test('Worker execution - Handle promise functions that resolve', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() /* eslint-disable-next-line @typescript-eslint/require-await */ async function main(): Promise { @@ -194,32 +196,32 @@ t.test('Worker execution - Handle promise functions that resolve', t => { }, notifier, code => { - t.equal(code, 0) - t.ok(mainCalls > 0) + deepStrictEqual(code, 0) + ok(mainCalls > 0) - const result = notifier.calls[0].args[0 as number]! as Result + const result = notifier.mock.calls[0].arguments[0] as Result - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 5) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 5) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker execution - Handle promise functions that reject', t => { +test('Worker execution - Handle promise functions that reject', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() /* eslint-disable-next-line @typescript-eslint/require-await */ async function main(): Promise { @@ -239,30 +241,30 @@ t.test('Worker execution - Handle promise functions that reject', t => { }, notifier, code => { - t.equal(code, 1) - t.ok(mainCalls > 0) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.notOk(result.success) - t.type(result.error, Error) - t.equal(result.error!.message, 'FAILED') - t.equal(result.size, 0) - t.equal(result.min, 0) - t.equal(result.max, 0) - t.equal(result.mean, 0) - t.equal(result.stddev, 0) - t.equal(result.standardError, 0) - t.strictSame(result.percentiles, {}) - - t.end() + deepStrictEqual(code, 1) + ok(mainCalls > 0) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(!result.success) + ok(result.error instanceof Error) + deepStrictEqual(result.error.message, 'FAILED') + deepStrictEqual(result.size, 0) + deepStrictEqual(result.min, 0) + deepStrictEqual(result.max, 0) + deepStrictEqual(result.mean, 0) + deepStrictEqual(result.stddev, 0) + deepStrictEqual(result.standardError, 0) + deepStrictEqual(result.percentiles, {}) + + done() } ) }) -t.test('Worker execution - Handle warmup mode enabled', t => { +test('Worker execution - Handle warmup mode enabled', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -280,33 +282,33 @@ t.test('Worker execution - Handle warmup mode enabled', t => { }, notifier, code => { - t.equal(code, 0) - t.equal(mainCalls, 10) - t.equal(notifier.calls.length, 1) + deepStrictEqual(code, 0) + deepStrictEqual(mainCalls, 10) + deepStrictEqual(notifier.mock.callCount(), 1) - const result = notifier.calls[0].args[0 as number]! as Result + const result = notifier.mock.calls[0].arguments[0] as Result - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 5) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 5) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker execution - Handle warmup mode disabled', t => { +test('Worker execution - Handle warmup mode disabled', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -324,34 +326,34 @@ t.test('Worker execution - Handle warmup mode disabled', t => { }, notifier, code => { - t.equal(code, 0) - t.equal(mainCalls, 5) - t.equal(notifier.calls.length, 1) + deepStrictEqual(code, 0) + deepStrictEqual(mainCalls, 5) + deepStrictEqual(notifier.mock.callCount(), 1) - const result = notifier.calls[0].args[0 as number]! as Result + const result = notifier.mock.calls[0].arguments[0] as Result - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 5) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 5) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker setup - Handle callback before functions', t => { +test('Worker setup - Handle callback before functions', (t, done) => { let mainCalls = 0 let setupCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -379,34 +381,34 @@ t.test('Worker setup - Handle callback before functions', t => { }, notifier, code => { - t.equal(code, 0) - t.equal(setupCalls, 1) - t.ok(mainCalls > 0) - t.equal(notifier.calls.length, 1) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 1000) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + deepStrictEqual(code, 0) + deepStrictEqual(setupCalls, 1) + ok(mainCalls > 0) + deepStrictEqual(notifier.mock.callCount(), 1) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 1000) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker setup - Handle callback before functions that throw errors', t => { +test('Worker setup - Handle callback before functions that throw errors', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -433,31 +435,31 @@ t.test('Worker setup - Handle callback before functions that throw errors', t => }, notifier, code => { - t.equal(code, 1) - t.notOk(mainCalls) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.notOk(result.success) - t.type(result.error, Error) - t.equal(result.error!.message, 'FAILED') - t.equal(result.size, 0) - t.equal(result.min, 0) - t.equal(result.max, 0) - t.equal(result.mean, 0) - t.equal(result.stddev, 0) - t.equal(result.standardError, 0) - t.strictSame(result.percentiles, {}) - - t.end() + deepStrictEqual(code, 1) + ok(!mainCalls) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(!result.success) + ok(result.error instanceof Error) + deepStrictEqual(result.error.message, 'FAILED') + deepStrictEqual(result.size, 0) + deepStrictEqual(result.min, 0) + deepStrictEqual(result.max, 0) + deepStrictEqual(result.mean, 0) + deepStrictEqual(result.stddev, 0) + deepStrictEqual(result.standardError, 0) + deepStrictEqual(result.percentiles, {}) + + done() } ) }) -t.test('Worker setup - Handle promise before functions that resolve', t => { +test('Worker setup - Handle promise before functions that resolve', (t, done) => { let mainCalls = 0 let setupCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -485,34 +487,34 @@ t.test('Worker setup - Handle promise before functions that resolve', t => { }, notifier, code => { - t.equal(code, 0) - t.equal(setupCalls, 1) - t.ok(mainCalls > 0) - t.equal(notifier.calls.length, 1) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 1000) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + deepStrictEqual(code, 0) + deepStrictEqual(setupCalls, 1) + ok(mainCalls > 0) + deepStrictEqual(notifier.mock.callCount(), 1) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 1000) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker setup - Handle promise before functions that reject', t => { +test('Worker setup - Handle promise before functions that reject', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -539,31 +541,31 @@ t.test('Worker setup - Handle promise before functions that reject', t => { }, notifier, code => { - t.equal(code, 1) - t.notOk(mainCalls) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.notOk(result.success) - t.type(result.error, Error) - t.equal(result.error!.message, 'FAILED') - t.equal(result.size, 0) - t.equal(result.min, 0) - t.equal(result.max, 0) - t.equal(result.mean, 0) - t.equal(result.stddev, 0) - t.equal(result.standardError, 0) - t.strictSame(result.percentiles, {}) - - t.end() + deepStrictEqual(code, 1) + ok(!mainCalls) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(!result.success) + ok(result.error instanceof Error) + deepStrictEqual(result.error.message, 'FAILED') + deepStrictEqual(result.size, 0) + deepStrictEqual(result.min, 0) + deepStrictEqual(result.max, 0) + deepStrictEqual(result.mean, 0) + deepStrictEqual(result.stddev, 0) + deepStrictEqual(result.standardError, 0) + deepStrictEqual(result.percentiles, {}) + + done() } ) }) -t.test('Worker setup - Handle callback after functions', t => { +test('Worker setup - Handle callback after functions', (t, done) => { let mainCalls = 0 let setupCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -591,34 +593,34 @@ t.test('Worker setup - Handle callback after functions', t => { }, notifier, code => { - t.equal(code, 0) - t.equal(setupCalls, 1) - t.ok(mainCalls > 0) - t.equal(notifier.calls.length, 1) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 1000) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + deepStrictEqual(code, 0) + deepStrictEqual(setupCalls, 1) + ok(mainCalls > 0) + deepStrictEqual(notifier.mock.callCount(), 1) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 1000) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker setup - Handle callback after functions that throw errors', t => { +test('Worker setup - Handle callback after functions that throw errors', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -645,31 +647,31 @@ t.test('Worker setup - Handle callback after functions that throw errors', t => }, notifier, code => { - t.equal(code, 1) - t.ok(mainCalls > 0) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.notOk(result.success) - t.type(result.error, Error) - t.equal(result.error!.message, 'FAILED') - t.equal(result.size, 0) - t.equal(result.min, 0) - t.equal(result.max, 0) - t.equal(result.mean, 0) - t.equal(result.stddev, 0) - t.equal(result.standardError, 0) - t.strictSame(result.percentiles, {}) - - t.end() + deepStrictEqual(code, 1) + ok(mainCalls > 0) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(!result.success) + ok(result.error instanceof Error) + deepStrictEqual(result.error.message, 'FAILED') + deepStrictEqual(result.size, 0) + deepStrictEqual(result.min, 0) + deepStrictEqual(result.max, 0) + deepStrictEqual(result.mean, 0) + deepStrictEqual(result.stddev, 0) + deepStrictEqual(result.standardError, 0) + deepStrictEqual(result.percentiles, {}) + + done() } ) }) -t.test('Worker setup - Handle promise after functions that resolve', t => { +test('Worker setup - Handle promise after functions that resolve', (t, done) => { let mainCalls = 0 let setupCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -697,34 +699,34 @@ t.test('Worker setup - Handle promise after functions that resolve', t => { }, notifier, code => { - t.equal(code, 0) - t.equal(setupCalls, 1) - t.ok(mainCalls > 0) - t.equal(notifier.calls.length, 1) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 1000) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + deepStrictEqual(code, 0) + deepStrictEqual(setupCalls, 1) + ok(mainCalls > 0) + deepStrictEqual(notifier.mock.callCount(), 1) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 1000) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) }) -t.test('Worker setup - Handle promise after functions that reject', t => { +test('Worker setup - Handle promise after functions that reject', (t, done) => { let mainCalls = 0 - const notifier = t.captureFn(() => {}) + const notifier = t.mock.fn() function main(): void { mainCalls++ @@ -751,29 +753,29 @@ t.test('Worker setup - Handle promise after functions that reject', t => { }, notifier, code => { - t.equal(code, 1) - t.ok(mainCalls > 0) - - const result = notifier.calls[0].args[0 as number]! as Result - - t.notOk(result.success) - t.type(result.error, Error) - t.equal(result.error!.message, 'FAILED') - t.equal(result.size, 0) - t.equal(result.min, 0) - t.equal(result.max, 0) - t.equal(result.mean, 0) - t.equal(result.stddev, 0) - t.equal(result.standardError, 0) - t.strictSame(result.percentiles, {}) - - t.end() + deepStrictEqual(code, 1) + ok(mainCalls > 0) + + const result = notifier.mock.calls[0].arguments[0] as Result + + ok(!result.success) + ok(result.error instanceof Error) + deepStrictEqual(result.error.message, 'FAILED') + deepStrictEqual(result.size, 0) + deepStrictEqual(result.min, 0) + deepStrictEqual(result.max, 0) + deepStrictEqual(result.mean, 0) + deepStrictEqual(result.stddev, 0) + deepStrictEqual(result.standardError, 0) + deepStrictEqual(result.percentiles, {}) + + done() } ) }) -t.test('Worker execution - Handle empty tests', t => { - const notifier = t.captureFn(() => {}) +test('Worker execution - Handle empty tests', (t, done) => { + const notifier = t.mock.fn() runWorker( { @@ -786,24 +788,24 @@ t.test('Worker execution - Handle empty tests', t => { }, notifier, code => { - t.equal(code, 0) + deepStrictEqual(code, 0) - const result = notifier.calls[0].args[0 as number]! as Result + const result = notifier.mock.calls[0].arguments[0] as Result - t.ok(result.success) - t.type(result.error, 'undefined') - t.equal(result.size, 1000) - t.type(result.min, 'number') - t.type(result.max, 'number') - t.type(result.mean, 'number') - t.type(result.stddev, 'number') - t.type(result.standardError, 'number') + ok(result.success) + ifError(result.error) + deepStrictEqual(result.size, 1000) + ok(typeof result.min, 'number') + ok(typeof result.max, 'number') + ok(typeof result.mean, 'number') + ok(typeof result.stddev, 'number') + ok(typeof result.standardError, 'number') for (const percentile of percentiles) { - t.type(result.percentiles[percentile.toString()], 'number') + ok(typeof result.percentiles[percentile.toString()], 'number') } - t.end() + done() } ) })