From 8486fe9b69ec9dd9d8828e4c445e589c6a4dac90 Mon Sep 17 00:00:00 2001 From: Matias Pando Date: Thu, 18 Dec 2014 07:13:39 -0300 Subject: [PATCH 1/5] Adding tests to TxPrpposals --- test/TxProposals.js | 95 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 19 deletions(-) diff --git a/test/TxProposals.js b/test/TxProposals.js index 13a2837e5..f01a084ae 100644 --- a/test/TxProposals.js +++ b/test/TxProposals.js @@ -11,6 +11,7 @@ var networks = bitcore.networks; var TxProposal = copay.TxProposal; var TxProposals = copay.TxProposals; +var moment = moment || require('moment'); var dummyProposal = new TxProposal({ creator: 1, @@ -34,41 +35,98 @@ describe('TxProposals', function() { describe('#fromObj', function() { it('should create an instance from an Object', function() { var txps = TxProposals.fromObj({ - networkName:'livenet', + networkName: 'livenet', walletId: '123a12', txps: [], }); should.exist(txps); txps.network.name.should.equal('livenet'); }); - it('should skip Objects with errors', function() { + it('should skip Objects with errors', function() { var txps = TxProposals.fromObj({ - networkName:'livenet', + networkName: 'livenet', walletId: '123a12', - txps: [ { a: 1 }], + txps: [{ + a: 1 + }], }); should.exist(txps); Object.keys(txps.txps).length.should.equal(0); }); }); + describe('#length', function() { + it('should return length', function() { + var txps = new TxProposals(); + txps.txps = { + a: 1, + b: 2 + }; + txps.length().should.equal(2); + }); + }); + describe('#getNtxidsSince', function() { + it('should throw illegal argument', function() { + var txps = new TxProposals(); + txps.txps = { + a: 1, + b: 2 + }; + (function() { + txps.getNtxidsSince() + }).should.throw('Illegal Argument'); + }); + it('should return keys since a date', function() { + var today = moment().toDate(); + var today_plus_1 = moment().add(1, 'day').toDate(); + var today_plus_2 = moment().add(2, 'day').toDate(); + var today_plus_3 = moment().add(3, 'day').toDate(); + + var txps = new TxProposals(); + txps.txps = [{ + id: 1, + createdTs: today + }, { + id: 2, + createdTs: today_plus_1 + }, { + id: 3, + createdTs: today_plus_2 + }]; + + txps.getNtxidsSince(today).length.should.be.equal(3); + txps.getNtxidsSince(today_plus_1).length.should.be.equal(2); + txps.getNtxidsSince(today_plus_2).length.should.be.equal(1); + txps.getNtxidsSince(today_plus_3).length.should.be.equal(0); + + }); + }); describe('#getNtxids', function() { it('should return keys', function() { var txps = new TxProposals(); - txps.txps = {a:1, b:2}; - txps.getNtxids().should.deep.equal(['a','b']); + txps.txps = { + a: 1, + b: 2 + }; + txps.getNtxids().should.deep.equal(['a', 'b']); }); }); describe('#deleteOne', function() { it('should delete specified ntxid', function() { var txps = new TxProposals(); - txps.txps = {a:1, b:2}; + txps.txps = { + a: 1, + b: 2 + }; txps.deleteOne('a'); txps.getNtxids().should.deep.equal(['b']); }); it('should fail on non-existent ntxid', function() { var txps = new TxProposals(); - txps.txps = {a:1, b:2}; - (function () { + txps.txps = { + a: 1, + b: 2 + }; + (function() { txps.deleteOne('c'); }).should.throw('Unknown TXP: c'); }); @@ -76,7 +134,7 @@ describe('TxProposals', function() { describe('#toObj', function() { it('should an object', function() { var txps = TxProposals.fromObj({ - networkName:'livenet', + networkName: 'livenet', walletId: '123a12', txps: [], }); @@ -86,28 +144,28 @@ describe('TxProposals', function() { }); it('should export txps', function() { var txps = TxProposals.fromObj({ - networkName:'livenet', + networkName: 'livenet', walletId: '123a12', txps: [], }); txps.txps = { - 'hola' : dummyProposal, - 'chau' : dummyProposal, + 'hola': dummyProposal, + 'chau': dummyProposal, }; var o = txps.toObj(); o.txps.length.should.equal(2); }); it('should filter sent txp', function() { var txps = TxProposals.fromObj({ - networkName:'livenet', + networkName: 'livenet', walletId: '123a12', txps: [], }); var d = JSON.parse(JSON.stringify(dummyProposal)); - d.sent=1; + d.sent = 1; txps.txps = { - 'hola' : dummyProposal, - 'chau' : d, + 'hola': dummyProposal, + 'chau': d, }; var o = txps.toObj(); o.txps.length.should.equal(1); @@ -117,8 +175,7 @@ describe('TxProposals', function() { it('should merge', function() { var txps = new TxProposals(); var d = dummyProposal; - txps.merge(d.toObj(),{}); + txps.merge(d.toObj(), {}); }); }); }); - From e7240748a20d27001478b961a2e6f0153fa561be Mon Sep 17 00:00:00 2001 From: Matias Pando Date: Thu, 18 Dec 2014 18:23:17 -0300 Subject: [PATCH 2/5] Adding test for Identity --- js/models/Identity.js | 19 ++++---- test/Identity.js | 106 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 13 deletions(-) diff --git a/js/models/Identity.js b/js/models/Identity.js index 84868bafd..fb3aafacc 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -109,7 +109,7 @@ Identity.create = function(opts, cb) { }); }; -Identity.prototype.resendVerificationEmail = function (cb) { +Identity.prototype.resendVerificationEmail = function(cb) { var self = this; preconditions.checkArgument(_.isFunction(cb)); @@ -152,7 +152,7 @@ Identity.open = function(opts, cb) { }); }; -Identity.prototype.verifyChecksum = function (cb) { +Identity.prototype.verifyChecksum = function(cb) { var self = this; self.storage.getItem(Identity.getKeyForEmail(self.email), function(err, data, headers) { @@ -202,11 +202,9 @@ Identity.prototype.addWallet = function(w) { */ Identity.prototype.deleteWallet = function(walletId, cb) { preconditions.checkArgument(_.isString(walletId)); - var self = this; - - self.verifyChecksum(function (err, match) { + self.verifyChecksum(function(err, match) { if (err) return cb(err); if (!match) return cb('The profile is out of sync. Please re-login to get the latest changes.'); @@ -222,6 +220,7 @@ Identity.prototype.deleteWallet = function(walletId, cb) { self.emitAndKeepAlive('walletDeleted', walletId); self.store(null, cb); }); + }); }; @@ -375,7 +374,7 @@ Identity.prototype.setBackupNeeded = function(backupNeeded) { self.backupNeeded = !!backupNeeded; - self.verifyChecksum(function (err, match) { + self.verifyChecksum(function(err, match) { if (err) return cb(err); if (!match) return cb('The profile is out of sync. Please re-login to get the latest changes.'); @@ -449,8 +448,11 @@ Identity.prototype.remove = function(opts, cb) { }; Identity.prototype._cleanUp = function() { + var self = this; + _.each(this.getWallets(), function(w) { w.close(); + delete self.wallets[w.getId()]; }); }; @@ -458,7 +460,6 @@ Identity.prototype._cleanUp = function() { * @desc Closes the wallet and disconnects all services */ Identity.prototype.close = function() { - this._cleanUp(); this.emitAndKeepAlive('closed'); }; @@ -623,10 +624,10 @@ Identity.prototype.bindWallet = function(w) { */ Identity.prototype.createWallet = function(opts, cb) { preconditions.checkArgument(cb); - + var self = this; - self.verifyChecksum(function (err, match) { + self.verifyChecksum(function(err, match) { if (err) return cb(err); if (!match) return cb('The profile is out of sync. Please re-login to get the latest changes.'); diff --git a/test/Identity.js b/test/Identity.js index 038ca7d34..8a9ee91bf 100644 --- a/test/Identity.js +++ b/test/Identity.js @@ -168,6 +168,17 @@ describe('Identity model', function() { }); }); + + describe('#openWallets', function(done) { + it('should emit noWallets', function() { + var iden = new Identity(getDefaultParams()); + sinon.spy(iden, 'emitAndKeepAlive'); + iden.openWallets(); + iden.emitAndKeepAlive.calledOnce.should.be.true; + iden.emitAndKeepAlive.getCall(0).args[0].should.equal('noWallets'); + }); + }); + describe('#remove', function(done) { it('should remove empty profile', function(done) { var storage = sinon.stub(); @@ -285,6 +296,48 @@ describe('Identity model', function() { done(); }); }); + + it('should return error because the limit has been reached', function(done) { + storage.setItem = sinon.stub().yields('OVERQUOTA'); + var w = { + toObj: sinon.stub().returns({ + key1: 'val1' + }), + getStorageKey: sinon.stub().returns('storage_key'), + getName: sinon.stub().returns('name'), + setVersion: sinon.spy(), + sizes: sinon.stub().returns(99), + getId: sinon.spy(), + }; + iden.storeWallet(w, function(err) { + should.exist(err); + err.should.be.equal('OVERQUOTA'); + done(); + }); + }); + + it('should return error', function(done) { + storage.setItem = sinon.stub().yields('UNKNOWN'); + var w = { + toObj: sinon.stub().returns({ + key1: 'val1' + }), + getStorageKey: sinon.stub().returns('storage_key'), + getName: sinon.stub().returns('name'), + setVersion: sinon.spy(), + sizes: sinon.stub().returns(99), + getId: sinon.spy(), + }; + iden.storeWallet(w, function(err) { + should.exist(err); + err.should.be.equal('UNKNOWN'); + done(); + }); + }); + + + + it('should change wallet version when storing', function(done) { storage.setItem = sinon.stub().yields(null); var w = { @@ -620,7 +673,7 @@ describe('Identity model', function() { }).should.deep.equal(w); }); - + it('should delete wallet', function(done) { iden.addWallet(w); @@ -676,7 +729,7 @@ describe('Identity model', function() { it('should include wallets', function() { iden.addWallet(w); var obj = iden.toObj(); - _.indexOf(obj.walletIds,'32').should.be.above(-1); + _.indexOf(obj.walletIds, '32').should.be.above(-1); }); it('should set version to actual version', function() { @@ -690,8 +743,53 @@ describe('Identity model', function() { iden.addWallet(w); iden.addWallet(w2); var obj = iden.toObj(); - _.indexOf(obj.walletIds,'32').should.be.above(-1); - _.indexOf(obj.walletIds,'33').should.be.above(-1); + _.indexOf(obj.walletIds, '32').should.be.above(-1); + _.indexOf(obj.walletIds, '33').should.be.above(-1); + }); + }); + + + describe('#_cleanUp', function() { + var iden, w, w2; + beforeEach(function() { + var storage = sinon.stub(); + storage.setCredentials = sinon.stub(); + storage.removeItem = sinon.stub().yields(null); + storage.clear = sinon.stub().yields(); + + var opts = { + email: 'test@test.com', + password: '123', + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + storage: storage, + }; + iden = new Identity(opts); + + w = { + getId: sinon.stub().returns('32'), + getName: sinon.stub().returns('treintaydos'), + close: sinon.stub(), + }; + w2 = { + getId: sinon.stub().returns('33'), + getName: sinon.stub().returns('treintaytres'), + close: sinon.stub(), + }; + iden.addWallet(w); + iden.addWallet(w2); + }); + + it('should close all wallets', function() { + _.size(iden.wallets).should.be.equal(2); + iden._cleanUp(); + _.size(iden.wallets).should.be.equal(0); }); }); }); From 4a6e03d51f8f4434a3a49f525feb921283fd1730 Mon Sep 17 00:00:00 2001 From: Matias Pando Date: Thu, 18 Dec 2014 19:34:30 -0300 Subject: [PATCH 3/5] Adding test for Identity --- test/Identity.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test/Identity.js b/test/Identity.js index 8a9ee91bf..77bf41065 100644 --- a/test/Identity.js +++ b/test/Identity.js @@ -791,5 +791,50 @@ describe('Identity model', function() { iden._cleanUp(); _.size(iden.wallets).should.be.equal(0); }); + + }); + + describe('#getLastFocusedWalletId', function() { + var iden, w, w2; + beforeEach(function() { + var storage = sinon.stub(); + storage.setCredentials = sinon.stub(); + storage.removeItem = sinon.stub().yields(null); + storage.clear = sinon.stub().yields(); + + var opts = { + email: 'test@test.com', + password: '123', + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + storage: storage, + }; + iden = new Identity(opts); + + w = { + getId: sinon.stub().returns('32'), + getName: sinon.stub().returns('treintaydos'), + close: sinon.stub(), + }; + w2 = { + getId: sinon.stub().returns('33'), + getName: sinon.stub().returns('treintaytres'), + close: sinon.stub(), + }; + iden.addWallet(w); + iden.addWallet(w2); + }); + + it.only('should return indefined', function() { + var a = iden.getLastFocusedWalletId(); + console.log('a', a); + }); + }); }); From 80770f9a7885b61d4f9a400fe03e55bc880ef54b Mon Sep 17 00:00:00 2001 From: Matias Pando Date: Fri, 19 Dec 2014 18:25:15 -0300 Subject: [PATCH 4/5] More tests on Identity --- test/Identity.js | 175 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 163 insertions(+), 12 deletions(-) diff --git a/test/Identity.js b/test/Identity.js index 77bf41065..995e28ac5 100644 --- a/test/Identity.js +++ b/test/Identity.js @@ -673,8 +673,6 @@ describe('Identity model', function() { }).should.deep.equal(w); }); - - it('should delete wallet', function(done) { iden.addWallet(w); iden.getWalletById('32').getName().should.equal('treintaydos'); @@ -725,20 +723,15 @@ describe('Identity model', function() { close: sinon.stub(), }; }); - it('should include wallets', function() { iden.addWallet(w); var obj = iden.toObj(); _.indexOf(obj.walletIds, '32').should.be.above(-1); }); - it('should set version to actual version', function() { var obj = iden.toObj(); obj.version.should.equal(version); }); - - - it('should include 2 wallets', function() { iden.addWallet(w); iden.addWallet(w2); @@ -795,6 +788,13 @@ describe('Identity model', function() { }); describe('#getLastFocusedWalletId', function() { + var clock; + before(function() { + clock = sinon.useFakeTimers(); + }); + after(function() { + clock.restore(); + }); var iden, w, w2; beforeEach(function() { var storage = sinon.stub(); @@ -827,14 +827,165 @@ describe('Identity model', function() { getName: sinon.stub().returns('treintaytres'), close: sinon.stub(), }; - iden.addWallet(w); - iden.addWallet(w2); + }); - it.only('should return indefined', function() { - var a = iden.getLastFocusedWalletId(); - console.log('a', a); + it('should return indefined', function() { + expect(iden.getLastFocusedWalletId()).to.be.undefined; + }); + + it('should return last focused wallet', function() { + iden.addWallet(w); + iden.addWallet(w2); + iden.updateFocusedTimestamp(w.getId()); + + iden.getLastFocusedWalletId().should.be.equal(w.getId()); + + clock.tick(1000); + + iden.updateFocusedTimestamp(w2.getId()); + iden.getLastFocusedWalletId().should.be.equal(w2.getId()); + + iden.deleteWallet(w2.getId(), function() { + iden.getLastFocusedWalletId().should.be.equal(w.getId()); + }); + }); + }); + + describe('importFromFullJson', function() { + var opts; + beforeEach(function() { + var storage = sinon.stub(); + storage.setCredentials = sinon.stub(); + storage.removeItem = sinon.stub().yields(null); + storage.clear = sinon.stub().yields(); + + opts = { + email: 'test@test.com', + password: '123', + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + storage: storage, + }; + }); + it('should throw error because json is wrong', function() { + Identity.importFromFullJson('asdfg', '1', {}, function(c) { + c.should.be.equal('BADSTR: Unable to retrieve json from string'); + }); + }); + it('should throw error because json does not have required fields', function() { + Identity.importFromFullJson('{"age":23}', '1', {}, function(c) { + c.should.be.equal('BADSTR'); + }); + }); + it('should create a profile', function() { + var json = '{"networkOpts":{"livenet":{"url":"https://insight.bitpay.com:443","transports":["polling"]},"testnet":{"url":"https://test-insight.bitpay.com:443","transports":["polling"]}},"blockchainOpts":{"livenet":{"url":"https://insight.bitpay.com:443","transports":["polling"]},"testnet":{"url":"https://test-insight.bitpay.com:443","transports":["polling"]}},"fullName":"l@l","email":"l@l","password":"1","storage":{"type":"DB","storeUrl":"https://insight.bitpay.com:443/api/email","iterations":1000,"salt":"jBbYTj8zTrOt6V","email":"l@l","password":"1","_cachedKey":"y4a352k6sM15gGag+PgQwXRdFjzi0yX6aLEGttWaeP+kbU7JeSPDUfbhhzonnQRUicJu/1IMWgDZbDJjWmrKgA=="},"walletDefaults":{"requiredCopayers":2,"totalCopayers":3,"spendUnconfirmed":true,"reconnectDelay":5000,"idleDurationMin":4,"settings":{"unitName":"bits","unitToSatoshi":100,"unitDecimals":2,"alternativeName":"US Dollar","alternativeIsoCode":"USD"}},"version":"0.8.2","walletIds":["15a3ecd34dfb7000","59220d2110461861","bfd6adad419078d9","893dc0c0a776648b","e8ee7218c6ea7f93"],"wallets":{},"focusedTimestamps":{"15a3ecd34dfb7000":1418916813711,"bfd6adad419078d9":1418835855887,"e8ee7218c6ea7f93":1418775999995,"59220d2110461861":1418835858871,"893dc0c0a776648b":1418835763680},"backupNeeded":true,"_events":{}}'; + Identity.importFromFullJson(json, '1', opts, function(err, iden) { + expect(err).to.be.null; + iden.should.not.be.null; + }); + }); }); + + describe('#closeWallet', function() { + var iden, w, w2, w3; + beforeEach(function() { + var storage = sinon.stub(); + storage.setCredentials = sinon.stub(); + storage.removeItem = sinon.stub().yields(null); + storage.clear = sinon.stub().yields(); + + var opts = { + email: 'test@test.com', + password: '123', + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + storage: storage, + }; + iden = new Identity(opts); + + w = { + getId: sinon.stub().returns('32'), + getName: sinon.stub().returns('treintaydos'), + close: sinon.stub(), + }; + w2 = { + getId: sinon.stub().returns('33'), + getName: sinon.stub().returns('treintaytres'), + close: sinon.stub(), + }; + + w3 = { + getId: sinon.stub().returns('34'), + getName: sinon.stub().returns('treintaycuatro'), + close: sinon.stub(), + }; + + iden.addWallet(w); + iden.addWallet(w2); + //do not add w3 + }); + + it('should close a Wallet', function() { + iden.closeWallet(w, function(err) { + expect(err).to.be.null; + }); + + iden.closeWallet(w3, function(err) { + expect(err).to.be.not.null; + }); + }); + + }); + + + + describe('#_checkVersion', function() { + var iden; + beforeEach(function() { + var storage = sinon.stub(); + storage.setCredentials = sinon.stub(); + storage.removeItem = sinon.stub().yields(null); + storage.clear = sinon.stub().yields(); + + var opts = { + email: 'test@test.com', + password: '123', + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + storage: storage, + }; + iden = new Identity(opts); + }); + + it('should checkVersion', function() { + + expect(iden._checkVersion()).to.be.undefined; + expect(iden._checkVersion('0.0.0')).to.be.undefined; + (function() { + console.log('b', iden._checkVersion('9.9.9')); + }).should.throw('Major difference'); + }); + }); + }); From cc701d648df8f5613c3efa54bd06c0a9ceabd6cd Mon Sep 17 00:00:00 2001 From: Matias Pando Date: Wed, 31 Dec 2014 10:35:33 -0300 Subject: [PATCH 5/5] Rebased --- test/Identity.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Identity.js b/test/Identity.js index 995e28ac5..a2a7c066e 100644 --- a/test/Identity.js +++ b/test/Identity.js @@ -406,7 +406,7 @@ describe('Identity model', function() { walletClass: walletClass, }, function(err, w1) { should.exist(w1); - + args.storage.getItem = sinon.stub().yields(null, JSON.stringify(iden)); iden.createWallet({ walletClass: walletClass, @@ -801,6 +801,7 @@ describe('Identity model', function() { storage.setCredentials = sinon.stub(); storage.removeItem = sinon.stub().yields(null); storage.clear = sinon.stub().yields(); + storage.getItem = sinon.stub(); var opts = { email: 'test@test.com',