From 89ddc3c434eb9bc2b9cce2aff7748eb7fd67bcc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Bie=C5=84kowski?= Date: Thu, 18 Jul 2019 19:47:14 +0200 Subject: [PATCH] Bring back custom Promise class to not introduce breaking changes --- lib/helper.js | 7 +++ lib/promise.js | 64 ++++++++++++++++++++ lib/zk_promise.js | 5 +- package.json | 11 ++-- tests/util/helpertest.js | 32 ++++++++++ tests/util/promisetest.js | 120 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 232 insertions(+), 7 deletions(-) create mode 100644 lib/helper.js create mode 100644 lib/promise.js create mode 100644 tests/util/helpertest.js create mode 100644 tests/util/promisetest.js diff --git a/lib/helper.js b/lib/helper.js new file mode 100644 index 00000000..54d7500a --- /dev/null +++ b/lib/helper.js @@ -0,0 +1,7 @@ +const deprecationLog = (className, methodName) => { + console.warn(`ZOOKEEPER LOG: ${className}::${methodName} is being deprecated!`); +}; + +exports = module.exports = { + deprecationLog, +}; diff --git a/lib/promise.js b/lib/promise.js new file mode 100644 index 00000000..3505723c --- /dev/null +++ b/lib/promise.js @@ -0,0 +1,64 @@ +/* eslint-disable no-param-reassign */ +/* eslint-disable no-return-assign */ + +const { deprecationLog } = require('./helper'); + +class ZkPromise extends Promise { + /** + * @deprecated + */ + get(propertyName) { + deprecationLog(ZkPromise.name, 'get'); + return this.then(object => object[propertyName]); + } + + /** + * @deprecated + */ + put(propertyName, value) { + deprecationLog(ZkPromise.name, 'put'); + return this.then(object => object[propertyName] = value); + } + + /** + * @deprecated + */ + call(functionName, ...args) { + deprecationLog(ZkPromise.name, 'call'); + return this.then(object => object[functionName](...args)); + } + + /** + * @deprecated + */ + addCallback(callback) { + deprecationLog(ZkPromise.name, 'addCallback'); + return this.then(callback); + } + + /** + * @deprecated + */ + addErrback(callback) { + deprecationLog(ZkPromise.name, 'addErrback'); + return this.catch(callback); + } + + /** + * @deprecated + */ + addBoth(callback) { + deprecationLog(ZkPromise.name, 'addBoth'); + return this.then(callback, callback); + } + + /** + * @deprecated + */ + addCallbacks(callback, errback) { + deprecationLog(ZkPromise.name, 'addCallbacks'); + return this.then(callback, errback); + } +} + +exports = module.exports = ZkPromise; diff --git a/lib/zk_promise.js b/lib/zk_promise.js index 972b1151..f26616b8 100644 --- a/lib/zk_promise.js +++ b/lib/zk_promise.js @@ -1,10 +1,11 @@ // needed to not break the interface /* eslint-disable camelcase */ +const ZkPromise = require('./promise'); const ZooKeeper = require('./zookeeper'); class ZooKeeperPromise extends ZooKeeper { on_connected() { - return new Promise((resolve) => { + return new ZkPromise((resolve) => { this.once('connect', () => resolve(this)); }); } @@ -68,7 +69,7 @@ class ZooKeeperPromise extends ZooKeeper { } promisify(fn, args) { - return new Promise((resolve, reject) => { + return new ZkPromise((resolve, reject) => { const callback = (rc, error, result) => { if (rc) { reject(rc); diff --git a/package.json b/package.json index 256490ed..4b0ecefb 100644 --- a/package.json +++ b/package.json @@ -34,14 +34,15 @@ "shelljs": "0.8.x" }, "devDependencies": { + "eslint": "5.x", + "eslint-config-airbnb-base": "13.x", + "eslint-plugin-import": "2.x", + "log4js": "4.x", "proxyquire": "2.x", + "sinon": "7.x", "tap-spec": "5.x", "tape": "4.x", - "log4js": "4.x", - "webworker": "0.x", - "eslint": "5.x", - "eslint-config-airbnb-base": "13.x", - "eslint-plugin-import": "2.x" + "webworker": "0.x" }, "main": "lib/index", "scripts": { diff --git a/tests/util/helpertest.js b/tests/util/helpertest.js new file mode 100644 index 00000000..bf846513 --- /dev/null +++ b/tests/util/helpertest.js @@ -0,0 +1,32 @@ +const sinon = require('sinon'); +const test = require('tape'); +const { deprecationLog } = require('../../lib/helper'); + +class Test { + static method() { + deprecationLog(Test.name, 'method'); + } +} + +test('deprecation log is called with proper arguments', (t) => { + const deprecationLogStub = sinon.stub(); + t.plan(3); + + deprecationLogStub(Test.name, 'method'); + + t.equal(deprecationLogStub.callCount, 1); + t.equal(deprecationLogStub.getCall(0).args[0], 'Test'); + t.equal(deprecationLogStub.getCall(0).args[1], 'method'); +}); + +test('deprecation log gives proper message', (t) => { + const consoleStub = sinon.stub(console, 'warn'); + t.plan(2); + + Test.method(); + + t.equal(consoleStub.callCount, 1); + t.equal(consoleStub.getCall(0).args[0], 'ZOOKEEPER LOG: Test::method is being deprecated!'); + + consoleStub.restore(); +}); diff --git a/tests/util/promisetest.js b/tests/util/promisetest.js new file mode 100644 index 00000000..9d0bbadb --- /dev/null +++ b/tests/util/promisetest.js @@ -0,0 +1,120 @@ +const sinon = require('sinon'); +const test = require('tape'); + +const ZkPromise = require('../../lib/promise'); + +test('ZkPromise get', (t) => { + t.plan(1); + + const expected = 'value'; + const promise = ZkPromise.resolve({ + property: expected, + }); + + promise.get('property').then((actual) => { + t.equal(actual, expected); + }); +}); + +test('ZkPromise put', (t) => { + t.plan(1); + + const expected = 'value'; + const promise = ZkPromise.resolve({}); + + promise.put('property', expected).then((actual) => { + t.equal(actual, expected); + }); +}); + +test('ZkPromise call', (t) => { + t.plan(1); + + const promise = ZkPromise.resolve({ + multiply: (a, b) => a * b, + }); + + promise.call('multiply', 2, 3).then((actual) => { + t.equal(actual, 2 * 3); + }); +}); + +test('ZkPromise addCallback', (t) => { + t.plan(3); + + const callback = sinon.stub().callsFake(value => value * 2); + const promise = ZkPromise.resolve(10); + + promise.addCallback(callback).then((actual) => { + t.equal(actual, 20); + t.equal(callback.callCount, 1); + t.equal(callback.getCall(0).args[0], 10); + }); +}); + +test('ZkPromise addErrback', (t) => { + t.plan(3); + + const callback = sinon.stub().callsFake(value => value * 2); + const promise = ZkPromise.reject(10); + + promise.addErrback(callback).then((actual) => { + t.equal(actual, 20); + t.equal(callback.callCount, 1); + t.equal(callback.getCall(0).args[0], 10); + }); +}); + +test('ZkPromise addBoth', (t) => { + t.plan(7); + + const callback = sinon.stub().callsFake(value => value * 2); + const errback = sinon.stub().callsFake(() => { + throw new Error('errback!'); + }); + // eslint-disable-next-line max-len + const promise = succeeds => new ZkPromise((resolve, reject) => (succeeds ? resolve(10) : reject(10))); + + promise(true).addBoth(callback) + .then((actual) => { + t.equal(actual, 20); + t.equal(callback.callCount, 1); + t.equal(callback.getCall(0).args[0], 10); + return promise(false).addBoth(errback); + }) + .catch((actual) => { + t.true(actual instanceof Error); + t.equal(actual.message, 'errback!'); + t.equal(errback.callCount, 1); + t.equal(errback.getCall(0).args[0], 10); + }); +}); + +test('ZkPromise addCallbacks', (t) => { + t.plan(9); + + const callback = sinon.stub().callsFake(value => value * 2); + const errback = sinon.stub().callsFake(() => { + throw new Error('errback!'); + }); + // eslint-disable-next-line max-len + const promise = succeeds => new ZkPromise((resolve, reject) => (succeeds ? resolve(10) : reject(10))); + + promise(true).addCallbacks(callback, errback) + .then((actual) => { + t.equal(actual, 20); + t.equal(callback.callCount, 1); + t.equal(callback.getCall(0).args[0], 10); + t.equal(errback.callCount, 0); + callback.resetHistory(); + errback.resetHistory(); + return promise(false).addCallbacks(callback, errback); + }) + .catch((actual) => { + t.true(actual instanceof Error); + t.equal(actual.message, 'errback!'); + t.equal(callback.callCount, 0); + t.equal(errback.callCount, 1); + t.equal(errback.getCall(0).args[0], 10); + }); +});