Removes event name in unsubscribe API + Tests (#2364) (#2844)

This commit is contained in:
Nicolas Gotchac 2016-10-25 11:43:24 +02:00 committed by Jaco Greeff
parent 9f6da3f829
commit 037a8c7625
5 changed files with 65 additions and 34 deletions

View File

@ -90,8 +90,8 @@ export default class Api {
return this._subscriptions.subscribe(subscriptionName, callback); return this._subscriptions.subscribe(subscriptionName, callback);
} }
unsubscribe (subscriptionName, subscriptionId) { unsubscribe (subscriptionId) {
return this._subscriptions.unsubscribe(subscriptionName, subscriptionId); return this._subscriptions.unsubscribe(subscriptionId);
} }
pollMethod (method, input, validate) { pollMethod (method, input, validate) {

View File

@ -29,17 +29,14 @@ const events = {
'personal_requestsToConfirm': { module: 'signer' } 'personal_requestsToConfirm': { module: 'signer' }
}; };
let nextSubscriptionId = 0;
export default class Manager { export default class Manager {
constructor (api) { constructor (api) {
this._api = api; this._api = api;
this.subscriptions = {}; this.subscriptions = [];
this.values = {}; this.values = {};
Object.keys(events).forEach((subscriptionName) => { Object.keys(events).forEach((subscriptionName) => {
this.subscriptions[subscriptionName] = {};
this.values[subscriptionName] = { this.values[subscriptionName] = {
error: null, error: null,
data: null data: null
@ -71,60 +68,58 @@ export default class Manager {
return; return;
} }
const subscriptionId = nextSubscriptionId++; const subscriptionId = this.subscriptions.length;
const { error, data } = this.values[subscriptionName]; const { error, data } = this.values[subscriptionName];
const engine = this[`_${subscription.module}`]; const engine = this[`_${subscription.module}`];
this.subscriptions[subscriptionName][subscriptionId] = callback; this.subscriptions[subscriptionId] = {
name: subscriptionName,
id: subscriptionId,
callback
};
if (!engine.isStarted) { if (!engine.isStarted) {
engine.start(); engine.start();
} else { } else {
this._sendData(subscriptionName, subscriptionId, callback, error, data); this._sendData(subscriptionId, error, data);
} }
resolve(subscriptionId); resolve(subscriptionId);
}); });
} }
unsubscribe (subscriptionName, subscriptionId) { unsubscribe (subscriptionId) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const subscription = this._validateType(subscriptionName); if (!this.subscriptions[subscriptionId]) {
reject(new Error(`Cannot find subscription ${subscriptionId}`));
if (isError(subscription)) {
reject(subscription);
return; return;
} }
if (!this.subscriptions[subscriptionName][subscriptionId]) { delete this.subscriptions[subscriptionId];
reject(new Error(`Cannot find subscription ${subscriptionId} for type ${subscriptionName}`));
return;
}
delete this.subscriptions[subscriptionName][subscriptionId];
resolve(); resolve();
}); });
} }
_sendData (subscriptionName, subscriptionId, callback, error, data) { _sendData (subscriptionId, error, data) {
const { callback } = this.subscriptions[subscriptionId];
try { try {
callback(error, data); callback(error, data);
} catch (error) { } catch (error) {
console.error(`Unable to update callback for ${subscriptionName}, subscriptionId ${subscriptionId}`, error); console.error(`Unable to update callback for subscriptionId ${subscriptionId}`, error);
this.unsubscribe(subscriptionName, subscriptionId); this.unsubscribe(subscriptionId);
} }
} }
_updateSubscriptions = (subscriptionName, error, data) => { _updateSubscriptions = (subscriptionName, error, data) => {
if (!this.subscriptions[subscriptionName]) { const subscriptions = this.subscriptions
throw new Error(`Cannot find entry point for subscriptions of type ${subscriptionName}`); .filter(subscription => subscription.name === subscriptionName);
}
this.values[subscriptionName] = { error, data }; this.values[subscriptionName] = { error, data };
Object.keys(this.subscriptions[subscriptionName]).forEach((subscriptionId) => {
const callback = this.subscriptions[subscriptionName][subscriptionId];
this._sendData(subscriptionName, subscriptionId, callback, error, data); subscriptions
.forEach((subscription) => {
this._sendData(subscription.id, error, data);
}); });
} }
} }

View File

@ -20,6 +20,7 @@ import Manager, { events } from './manager';
function newStub () { function newStub () {
const start = () => manager._updateSubscriptions(manager.__test, null, 'test'); const start = () => manager._updateSubscriptions(manager.__test, null, 'test');
const manager = new Manager({ const manager = new Manager({
transport: { transport: {
isConnected: true isConnected: true
@ -53,7 +54,7 @@ describe('api/subscriptions/manager', () => {
describe('constructor', () => { describe('constructor', () => {
it('sets up the subscription types & defaults', () => { it('sets up the subscription types & defaults', () => {
expect(Object.keys(manager.subscriptions)).to.deep.equal(Object.keys(events)); expect(manager.subscriptions).to.be.an.array;
expect(Object.keys(manager.values)).to.deep.equal(Object.keys(events)); expect(Object.keys(manager.values)).to.deep.equal(Object.keys(events));
}); });
}); });
@ -74,6 +75,7 @@ describe('api/subscriptions/manager', () => {
manager.__test = eventName; manager.__test = eventName;
cb = sinon.stub(); cb = sinon.stub();
sinon.spy(engine, 'start'); sinon.spy(engine, 'start');
return manager return manager
.subscribe(eventName, cb) .subscribe(eventName, cb)
.then((_subscriptionId) => { .then((_subscriptionId) => {
@ -86,7 +88,7 @@ describe('api/subscriptions/manager', () => {
}); });
it('returns a subscriptionId', () => { it('returns a subscriptionId', () => {
expect(subscriptionId).to.be.ok; expect(subscriptionId).to.be.a.number;
}); });
it('calls the subscription callback with updated values', () => { it('calls the subscription callback with updated values', () => {
@ -95,4 +97,38 @@ describe('api/subscriptions/manager', () => {
}); });
}); });
}); });
describe('unsubscriptions', () => {
Object
.keys(events)
.filter((eventName) => eventName.indexOf('_') !== -1)
.forEach((eventName) => {
const { module } = events[eventName];
let engine;
let cb;
describe(eventName, () => {
beforeEach(() => {
engine = manager[`_${module}`];
manager.__test = eventName;
cb = sinon.stub();
sinon.spy(engine, 'start');
return manager
.subscribe(eventName, cb)
.then((_subscriptionId) => {
manager.unsubscribe(_subscriptionId);
})
.then(() => {
manager._updateSubscriptions(manager.__test, null, 'test2');
});
});
it('does not call the callback after unsibscription', () => {
expect(cb).to.have.been.calledWith(null, 'test');
expect(cb).to.not.have.been.calledWith(null, 'test2');
});
});
});
});
}); });

View File

@ -50,7 +50,7 @@ class TxHash extends Component {
const { api } = this.context; const { api } = this.context;
const { subscriptionId } = this.state; const { subscriptionId } = this.state;
api.unsubscribe('eth_blockNumber', subscriptionId); api.unsubscribe(subscriptionId);
} }
render () { render () {

View File

@ -87,7 +87,7 @@ class Contract extends Component {
const { api } = this.context; const { api } = this.context;
const { subscriptionId, blockSubscriptionId, contract } = this.state; const { subscriptionId, blockSubscriptionId, contract } = this.state;
api.unsubscribe('eth_blockNumber', blockSubscriptionId); api.unsubscribe(blockSubscriptionId);
contract.unsubscribe(subscriptionId); contract.unsubscribe(subscriptionId);
} }