diff --git a/packages/web3-core-subscriptions/src/index.js b/packages/web3-core-subscriptions/src/index.js index e12811af8e5..113f6757fd9 100644 --- a/packages/web3-core-subscriptions/src/index.js +++ b/packages/web3-core-subscriptions/src/index.js @@ -59,7 +59,7 @@ Subscriptions.prototype.buildCall = function() { } var subscription = new Subscription({ - subscription: _this.subscriptions[arguments[0]], + subscription: _this.subscriptions[arguments[0]] || {}, // Subscript might not exist requestManager: _this.requestManager, type: _this.type }); diff --git a/packages/web3-core-subscriptions/src/subscription.js b/packages/web3-core-subscriptions/src/subscription.js index 65310126f4a..dc44cf4c613 100644 --- a/packages/web3-core-subscriptions/src/subscription.js +++ b/packages/web3-core-subscriptions/src/subscription.js @@ -77,7 +77,11 @@ Subscription.prototype._validateArgs = function (args) { subscription.params = 0; if (args.length !== subscription.params) { - throw errors.InvalidNumberOfParams(args.length, subscription.params + 1, args[0]); + throw errors.InvalidNumberOfParams( + args.length, + subscription.params, + subscription.subscriptionName + ); } }; @@ -192,18 +196,28 @@ Subscription.prototype.subscribe = function() { return this; } + // throw error, if provider is not set if(!this.options.requestManager.provider) { - var err1 = new Error('No provider set.'); - this.callback(err1, null, this); - this.emit('error', err1); + setTimeout(function(){ + var err1 = new Error('No provider set.'); + _this.callback(err1, null, _this); + _this.emit('error', err1); + },0); + return this; } // throw error, if provider doesnt support subscriptions if(!this.options.requestManager.provider.on) { - var err2 = new Error('The current provider doesn\'t support subscriptions: '+ this.options.requestManager.provider.constructor.name); - this.callback(err2, null, this); - this.emit('error', err2); + setTimeout(function(){ + var err2 = new Error( + 'The current provider doesn\'t support subscriptions: ' + + _this.options.requestManager.provider.constructor.name + ); + _this.callback(err2, null, _this); + _this.emit('error', err2); + },0); + return this; } @@ -232,8 +246,10 @@ Subscription.prototype.subscribe = function() { // TODO subscribe here? after the past logs? } else { - _this.callback(err, null, _this); - _this.emit('error', err); + setTimeout(function(){ + _this.callback(err, null, _this); + _this.emit('error', err); + },0); } }); } @@ -275,8 +291,10 @@ Subscription.prototype.subscribe = function() { } }); } else { - _this.callback(err, false, _this); - _this.emit('error', err); + setTimeout(function(){ + _this.callback(err, false, _this); + _this.emit('error', err); + },0); } }); diff --git a/test/eth.subscribe.ganache.js b/test/eth.subscribe.ganache.js index cde97b6c2db..89a0d7c94dd 100644 --- a/test/eth.subscribe.ganache.js +++ b/test/eth.subscribe.ganache.js @@ -7,6 +7,7 @@ describe('subscription connect/reconnect', function() { let server; let web3; let accounts; + let subscription; const port = 8545; beforeEach(async function() { @@ -24,17 +25,135 @@ describe('subscription connect/reconnect', function() { } }); - it('subscribes (baseline)', function() { - return new Promise(async function (resolve) { - web3.eth - .subscribe('newBlockHeaders') - .on('data', function(result) { + it('subscribes (baseline)', function(done) { + web3.eth + .subscribe('newBlockHeaders') + .on('data', function(result) { + assert(result.parentHash); + done(); + }); + }); + + it('subscribes with a callback', function(done){ + subscription = web3.eth + .subscribe('newBlockHeaders', function(err, result){ + assert(result.parentHash); + subscription.unsubscribe(); // Stop listening.. + done(); + }); + }); + + it('subscription emits a connected event', function(done){ + subscription = web3.eth + .subscribe('newBlockHeaders') + .on('connected', function(result){ + assert(result) // First subscription + subscription.unsubscribe(); // Stop listening.. + done(); + }); + }); + + it('resubscribes to an existing subscription', function(done){ + this.timeout(5000); + + let stage = 0; + + subscription = web3.eth.subscribe('newBlockHeaders'); + + subscription.on('data', function(result){ + if (stage === 0) { + subscription.resubscribe(); + stage = 1; + return; + } + + assert(result.parentHash); + subscription.unsubscribe(); // Stop listening.. + done(); + }); + }); + + it('resubscribes after being unsubscribed', function(done){ + this.timeout(5000); + + let stage = 0; + + subscription = web3.eth + .subscribe('newBlockHeaders') + .on('data', function(result) { + assert(result.parentHash); + subscription.unsubscribe(); + stage = 1; + }); + + // Resubscribe from outside + interval = setInterval(async function(){ + if (stage === 1){ + clearInterval(interval); + subscription.resubscribe(); + subscription.on('data', function(result){ assert(result.parentHash); - resolve(); - }); + subscription.unsubscribe(); // Stop listening.. + done(); + }) + } + }, 500) + }); + + it('allows a subscription which does not exist', function(){ + web3.eth.subscribe('subscription-does-not-exists'); + }); + + it('errors when zero params subscrip. is called with the wrong arguments', function(){ + try { + web3.eth.subscribe('newBlockHeaders', 5) + assert.fail(); + } catch (err) { + assert(err.message.includes('Invalid number of parameters for "newHeads"')) + assert(err.message.includes('Got 1 expected 0')); + } + }); + + it('errors when the provider is not set (callback)', function(done){ + web3 = new Web3(); + + web3.eth.subscribe('newBlockHeaders', function(err, result){ + assert(err.message.includes('No provider set')); + done(); + }) + }); + + it('errors when the provider is not set (.on("error"))', function(done){ + web3 = new Web3(); + + web3.eth + .subscribe('newBlockHeaders') + .on("error", function(err){ + assert(err.message.includes('No provider set')); + done(); + }) + }); + + it('errors when the provider does not support subscriptions (callback)', function(done){ + web3 = new Web3('http://localhost:' + port); + + web3.eth.subscribe('newBlockHeaders', function(err, result){ + assert(err.message.includes("provider doesn't support subscriptions: HttpProvider")); + done(); }); }); + it('errors when the provider is not set (.on("error"))', function(done){ + web3 = new Web3('http://localhost:' + port); + + web3.eth + .subscribe('newBlockHeaders') + .on("error", function(err){ + assert(err.message.includes("provider doesn't support subscriptions: HttpProvider")); + done(); + }) + }); + it('errors when the `eth_subscribe` request got send, the reponse isnt returned from the node, and the connection does get closed in the mean time', async function() { await pify(server.close)();