diff options
Diffstat (limited to 'test/js/node/util/util-callbackify.test.js')
-rw-r--r-- | test/js/node/util/util-callbackify.test.js | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/test/js/node/util/util-callbackify.test.js b/test/js/node/util/util-callbackify.test.js new file mode 100644 index 000000000..38c20f5c0 --- /dev/null +++ b/test/js/node/util/util-callbackify.test.js @@ -0,0 +1,323 @@ +import { callbackify } from "util"; +import { createTest } from "node-harness"; + +const { describe, expect, it, createCallCheckCtx } = createTest(import.meta.path); + +const values = [ + "hello world", + null, + undefined, + false, + 0, + {}, + { key: "value" }, + Symbol("I am a symbol"), + function ok() {}, + ["array", "with", 4, "values"], + new Error("boo"), +]; + +describe("util.callbackify", () => { + describe("rejection reason", () => { + for (const value of values) { + it(`callback is async function, value is ${String(value)}`, done => { + const { mustCall } = createCallCheckCtx(done); + async function asyncFn() { + return Promise.reject(value); + } + + const cbAsyncFn = callbackify(asyncFn); + cbAsyncFn( + mustCall((err, ret) => { + try { + expect(ret).toBeUndefined(); + if (err instanceof Error) { + if ("reason" in err) { + expect(!value).toBeTrue(); + expect(err.code).toStrictEqual("ERR_FALSY_VALUE_REJECTION"); + expect(err.reason).toStrictEqual(value); + } else { + expect(String(value)).toEndWith(err.message); + } + } else { + expect(err).toStrictEqual(value); + } + + done(); + } catch (error) { + done(error); + } + }), + ); + }); + + it(`callback is promise, value is ${String(value)}`, done => { + const { mustCall } = createCallCheckCtx(done); + function promiseFn() { + return Promise.reject(value); + } + const obj = {}; + Object.defineProperty(promiseFn, "name", { + value: obj, + writable: false, + enumerable: false, + configurable: true, + }); + + const cbPromiseFn = callbackify(promiseFn); + try { + expect(promiseFn.name).toStrictEqual(obj); + } catch (error) { + done(error); + } + + cbPromiseFn( + mustCall((err, ret) => { + try { + expect(ret).toBeUndefined(); + if (err instanceof Error) { + if ("reason" in err) { + expect(!value).toBeTrue(); + expect(err.code).toStrictEqual("ERR_FALSY_VALUE_REJECTION"); + expect(err.reason).toStrictEqual(value); + } else { + expect(String(value)).toEndWith(err.message); + } + } else { + expect(err).toStrictEqual(value); + } + + done(); + } catch (error) { + done(error); + } + }), + ); + }); + + it(`callback is thenable, value is ${String(value)}`, done => { + const { mustCall } = createCallCheckCtx(done); + function thenableFn() { + return { + then(onRes, onRej) { + onRej(value); + }, + }; + } + + const cbThenableFn = callbackify(thenableFn); + cbThenableFn( + mustCall((err, ret) => { + try { + expect(ret).toBeUndefined(); + if (err instanceof Error) { + if ("reason" in err) { + expect(!value).toBeTrue(); + expect(err.code).toStrictEqual("ERR_FALSY_VALUE_REJECTION"); + expect(err.reason).toStrictEqual(value); + } else { + expect(String(value)).toEndWith(err.message); + } + } else { + expect(err).toStrictEqual(value); + } + + done(); + } catch (error) { + done(error); + } + }), + ); + }); + } + }); + + describe("return value", () => { + for (const value of values) { + it(`callback is async function, value is ${String(value)}`, done => { + const { mustSucceed } = createCallCheckCtx(done); + async function asyncFn() { + return value; + } + + const cbAsyncFn = callbackify(asyncFn); + cbAsyncFn( + mustSucceed(ret => { + try { + expect(ret).toStrictEqual(value); + expect(ret).toStrictEqual(value); + + done(); + } catch (error) { + done(error); + } + }), + ); + }); + + it(`callback is promise, value is ${String(value)}`, done => { + const { mustSucceed } = createCallCheckCtx(done); + function promiseFn() { + return Promise.resolve(value); + } + + const cbPromiseFn = callbackify(promiseFn); + cbPromiseFn( + mustSucceed(ret => { + try { + expect(ret).toStrictEqual(value); + done(); + } catch (error) { + done(error); + } + }), + ); + }); + + it(`callback is thenable, value is ${String(value)}`, done => { + const { mustSucceed } = createCallCheckCtx(done); + function thenableFn() { + return { + then(onRes, onRej) { + onRes(value); + }, + }; + } + + const cbThenableFn = callbackify(thenableFn); + cbThenableFn( + mustSucceed(ret => { + try { + expect(ret).toStrictEqual(value); + done(); + } catch (error) { + done(error); + } + }), + ); + }); + } + }); + + describe("arguments", () => { + for (const value of values) { + it(`callback is async function, value is ${String(value)}`, done => { + const { mustSucceed } = createCallCheckCtx(done); + async function asyncFn(arg) { + try { + expect(arg).toStrictEqual(value); + } catch (error) { + done(error); + } + return arg; + } + + const cbAsyncFn = callbackify(asyncFn); + cbAsyncFn( + value, + mustSucceed(ret => { + try { + expect(ret).toStrictEqual(value); + done(); + } catch (error) { + done(error); + } + }), + ); + }); + + it(`callback is promise, value is ${String(value)}`, done => { + const { mustSucceed } = createCallCheckCtx(done); + function promiseFn(arg) { + try { + expect(arg).toStrictEqual(value); + } catch (error) { + done(error); + } + + return Promise.resolve(arg); + } + const obj = {}; + Object.defineProperty(promiseFn, "length", { + value: obj, + writable: false, + enumerable: false, + configurable: true, + }); + const cbPromiseFn = callbackify(promiseFn); + try { + expect(promiseFn.length).toStrictEqual(obj); + } catch (error) { + done(error); + } + + cbPromiseFn( + value, + mustSucceed(ret => { + try { + expect(ret).toStrictEqual(value); + done(); + } catch (error) { + done(error); + } + }), + ); + }); + } + }); + + describe("this binding", () => { + const value = "hello world"; + it("callback is sync function", done => { + // TODO: + // const { mustSucceed } = createCallCheckCtx(done); + const iAmThis = { + fn(arg) { + try { + expect(this).toStrictEqual(iAmThis); + } catch (error) { + done(error); + } + return Promise.resolve(arg); + }, + }; + + iAmThis.cbFn = callbackify(iAmThis.fn); + iAmThis.cbFn(value, function (rej, ret) { + try { + expect(ret).toStrictEqual(value); + expect(this).toStrictEqual(iAmThis); + + done(); + } catch (error) { + done(error); + } + }); + }); + + it("callback is async function", done => { + const iAmThis = { + async fn(arg) { + try { + expect(this).toStrictEqual(iAmThis); + } catch (error) { + done(error); + } + return Promise.resolve(arg); + }, + }; + + iAmThis.cbFn = callbackify(iAmThis.fn); + iAmThis.cbFn(value, function (rej, ret) { + try { + expect(ret).toStrictEqual(value); + expect(this).toStrictEqual(iAmThis); + + done(); + } catch (error) { + done(error); + } + }); + }); + }); +}); |