diff options
author | 2023-01-08 03:49:49 -0600 | |
---|---|---|
committer | 2023-01-08 01:49:49 -0800 | |
commit | 94409770dece8bb9dfc23f4bdc2f240836035d87 (patch) | |
tree | 4cc627eb67c476871e84141a6c7a583e29e98309 /test/bun.js/node-test-helpers.ts | |
parent | c505f172b84f5359aa186513f3ef7d6394bfc7b2 (diff) | |
download | bun-94409770dece8bb9dfc23f4bdc2f240836035d87.tar.gz bun-94409770dece8bb9dfc23f4bdc2f240836035d87.tar.zst bun-94409770dece8bb9dfc23f4bdc2f240836035d87.zip |
feat(node:readline): add node:readline and node:readline/promises (#1738)
* feat(readline): WIP: add readline
* test(helpers): add deepStrictEqual helper
* feat(readline): add readline & readline/promises to loader
* fix(node:events): emit newListener on new listener added
* feat(readline): finish readline cb interface, add tests
* fix(stream): fix Transform.end()
* fix(node-test-helpers): correct throws behavior, improve how all asserts work
* feat(readline/promises): add readline/promises
* feat(assert): add assert.match
* test(readline): uncomment more tests
* fix(readline): MaxCeil -> MathCeil 🤦
* fix(readline): export promises from node:readline
* fix(readline): temp fix for circular dependency
* cleanup(readline): remove console.log
* fix(readline): change true -> 0 for CommonJS export
* perf(readline): micro-optimizations with some getters
* perf(readline): lazy load isWritable
* cleanup(readline): rename debug flag env var to BUN_JS_DEBUG
Diffstat (limited to 'test/bun.js/node-test-helpers.ts')
-rw-r--r-- | test/bun.js/node-test-helpers.ts | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/test/bun.js/node-test-helpers.ts b/test/bun.js/node-test-helpers.ts new file mode 100644 index 000000000..ff7b8ece3 --- /dev/null +++ b/test/bun.js/node-test-helpers.ts @@ -0,0 +1,198 @@ +import { expect as expect_ } from "bun:test"; +// @ts-ignore +import { gcTick } from "gc"; +import assertNode from "node:assert"; + +type DoneCb = (err?: Error) => any; +function noop() {} + +const expect = (actual) => { + gcTick(); + const ret = expect_(actual); + gcTick(); + return ret; +}; + +// Assert +export const strictEqual = ( + ...args: Parameters<typeof assertNode.strictEqual> +) => { + assertNode.strictEqual.apply(this, args); + expect(true).toBe(true); +}; + +export const notStrictEqual = ( + ...args: Parameters<typeof assertNode.notStrictEqual> +) => { + assertNode.notStrictEqual.apply(this, args); + expect(true).toBe(true); +}; + +export const deepStrictEqual = ( + ...args: Parameters<typeof assertNode.deepStrictEqual> +) => { + assertNode.deepStrictEqual.apply(this, args); + expect(true).toBe(true); +}; + +export const throws = (...args: Parameters<typeof assertNode.throws>) => { + assertNode.throws.apply(this, args); + expect(true).toBe(true); +}; + +export const ok = (...args: Parameters<typeof assertNode.ok>) => { + assertNode.ok.apply(this, args); + expect(true).toBe(true); +}; + +export const ifError = (...args: Parameters<typeof assertNode.ifError>) => { + assertNode.ifError.apply(this, args); + expect(true).toBe(true); +}; + +export const match = (...args: Parameters<typeof assertNode.match>) => { + assertNode.match.apply(this, args); + expect(true).toBe(true); +}; + +export const assert = { + strictEqual, + deepStrictEqual, + notStrictEqual, + throws, + ok, + ifError, + match, +}; + +// End assert + +export const createCallCheckCtx = (done: DoneCb) => { + const createDone = createDoneDotAll(done); + + // const mustCallChecks = []; + + // failed.forEach(function (context) { + // console.log( + // "Mismatched %s function calls. Expected %s, actual %d.", + // context.name, + // context.messageSegment, + // context.actual + // ); + // console.log(context.stack.split("\n").slice(2).join("\n")); + // }); + + // TODO: Implement this to be exact only + function mustCall(fn?: (...args) => any, exact?: number) { + return mustCallAtLeast(fn, exact); + } + + function mustNotCall( + reason: string = "function should not have been called", + ) { + const localDone = createDone(); + setTimeout(() => localDone(), 200); + return () => { + done(new Error(reason)); + }; + } + + function mustSucceed(fn: () => any, exact?: number) { + return mustCall(function (err, ...args) { + ifError(err); + // @ts-ignore + if (typeof fn === "function") return fn.apply(this, args as []); + }, exact); + } + + function mustCallAtLeast(fn, minimum) { + return _mustCallInner(fn, minimum, "minimum"); + } + + function _mustCallInner(fn, criteria = 1, field) { + if (process._exiting) + throw new Error("Cannot use common.mustCall*() in process exit handler"); + if (typeof fn === "number") { + criteria = fn; + fn = noop; + } else if (fn === undefined) { + fn = noop; + } + + if (typeof criteria !== "number") + throw new TypeError(`Invalid ${field} value: ${criteria}`); + + let actual = 0; + let expected = criteria; + + // mustCallChecks.push(context); + const done = createDone(); + const _return = (...args) => { + // @ts-ignore + const result = fn.apply(this, args); + actual++; + if (actual >= expected) { + done(); + } + return result; + }; + // Function instances have own properties that may be relevant. + // Let's replicate those properties to the returned function. + // Refs: https://tc39.es/ecma262/#sec-function-instances + Object.defineProperties(_return, { + name: { + value: fn.name, + writable: false, + enumerable: false, + configurable: true, + }, + length: { + value: fn.length, + writable: false, + enumerable: false, + configurable: true, + }, + }); + return _return; + } + return { + mustSucceed, + mustCall, + mustCallAtLeast, + mustNotCall, + }; +}; + +export function createDoneDotAll(done: DoneCb, globalTimeout?: number) { + let toComplete = 0; + let completed = 0; + const globalTimer = globalTimeout + ? setTimeout(() => { + console.log("Global Timeout"); + done(new Error("Timed out!")); + }, globalTimeout) + : undefined; + function createDoneCb(timeout?: number) { + toComplete += 1; + const timer = + timeout !== undefined + ? setTimeout(() => { + console.log("Timeout"); + done(new Error("Timed out!")); + }, timeout) + : timeout; + return (result?: Error) => { + if (timer) clearTimeout(timer); + if (globalTimer) clearTimeout(globalTimer); + if (result instanceof Error) { + done(result); + return; + } + completed += 1; + if (completed === toComplete) { + done(); + } + }; + } + return createDoneCb; +} |