From 21c9868c62d2b0e1b1a61b043925e1d9f767c902 Mon Sep 17 00:00:00 2001 From: dimaver Date: Wed, 18 Dec 2019 16:35:16 +0300 Subject: [PATCH] v1.1.3 addAsync fixes --- test/unit/utils.spec.js | 36 ++++++++++++++++++++++++++++++++++++ utils.js | 13 ++++++++++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/test/unit/utils.spec.js b/test/unit/utils.spec.js index 2ba7793..326df4d 100644 --- a/test/unit/utils.spec.js +++ b/test/unit/utils.spec.js @@ -477,6 +477,42 @@ describe('# utils:', function() { }); }); + describe('context of wrapped method', function() { + let context; + let instance; + let spy1; + let spy2; + beforeEach(() => { + spy1 = sinon.spy(); + spy2 = sinon.spy(); + context = { + method: spy1, + }; + const Cls = function() {}; + Cls.prototype = { + method: spy2, + } + addAsync(context, 'method'); + instance = new Cls(); + addAsync(instance, 'method'); + }); + it('should use correct `this` when context is a plain object', async () => { + expect(typeof context.methodAsync, 'has async method').to.be.equal('function'); + let res = await context.methodAsync(); + expect(spy1, 'called once').to.be.calledOnce; + expect(res, 'instanceof AsyncResult').to.be.instanceOf(AsyncResult); + let call = spy1.getCall(0); + expect(call, 'correct context').calledOn(context); + }); + it('should use correct `this` when context is an instance of a class', async () => { + expect(typeof instance.methodAsync, 'has async method').to.be.equal('function'); + let res = await instance.methodAsync(); + expect(spy2, 'called once').to.be.calledOnce; + expect(res, 'instanceof AsyncResult').to.be.instanceOf(AsyncResult); + let call = spy2.getCall(0); + expect(call, 'correct context').calledOn(instance); + }); + }); }); }); diff --git a/utils.js b/utils.js index 573b198..8e4b2e1 100644 --- a/utils.js +++ b/utils.js @@ -46,15 +46,20 @@ function toAsyncResult(promise, OwnAsyncResult) { * @param {object} [options] - You may specify context and AsyncResult for new method through options * @return {function} - wrapped method */ -function wrapMethod(method, { context, AsyncResult } = {}) { +function wrapMethod(method, { context, AsyncResult, prototypeMethod, methodName } = {}) { if (typeof method !== 'function') { - throw new Error('first argument should be a function'); + throw new Error('first argument should be a function or context should be provided'); } !AsyncResult && (AsyncResult = config.AsyncResult); let asyncMethod = function() { try { - let result = method.apply(this, arguments); + let result; + if (methodName) { + result = this[methodName].apply(this, arguments); + } else { + result = method.apply(this, arguments); + } return toAsyncResult(result, AsyncResult); } catch (error) { return toAsyncResult(error, AsyncResult); @@ -81,8 +86,10 @@ function addAsync(context, methodName, options = {}) { } } else { let isCtor = typeof context === 'function'; + options.methodName = methodName; if (isCtor && !options.static) { context = context.prototype + options.prototypeMethod = true; } if (!isCtor && options.context === void 0) { options.context = context;