From 3a4bb56c26458126de83839916e3723300496f89 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 4 Jun 2014 18:10:47 -0300 Subject: [PATCH 1/5] update to socket.io 1.0, adds connection error warnings --- bower.json | 3 ++- index.html | 12 +++++++++++- js/controllers/header.js | 30 ++++++++++++++++++++++++++---- js/services/controllerUtils.js | 20 +++++++++++++++++++- js/services/notifications.js | 2 +- js/services/socket.js | 21 ++++++++++++++++----- 6 files changed, 75 insertions(+), 13 deletions(-) diff --git a/bower.json b/bower.json index 977836dc4..fbb7cb541 100644 --- a/bower.json +++ b/bower.json @@ -19,6 +19,7 @@ "file-saver": "*", "qrcode-decoder-js": "*", "bitcore": "~0.1.19", - "angular-moment": "~0.7.1" + "angular-moment": "~0.7.1", + "socket.io-client": ">=1.0.0" } } diff --git a/index.html b/index.html index fc5d3ecb9..18c0a0585 100644 --- a/index.html +++ b/index.html @@ -82,6 +82,16 @@ +
+
+
+ Error connecting to Insight server. Check + you settings and Internet connection. + Trying to reconnect... +
+
+
+
@@ -782,7 +792,7 @@ on supported browsers please check http://www.w - + diff --git a/js/controllers/header.js b/js/controllers/header.js index c33362952..a93b344ce 100644 --- a/js/controllers/header.js +++ b/js/controllers/header.js @@ -33,14 +33,28 @@ angular.module('copayApp.controllers').controller('HeaderController', } }); + // Initialize alert notification (not show when init wallet) $rootScope.txAlertCount = 0; - $rootScope.$watch('txAlertCount', function(txAlertCount) { - if (txAlertCount && txAlertCount > 0) { - $notification.info('New Transaction', ($rootScope.txAlertCount == 1) ? 'You have a pending transaction proposal' : 'You have ' + $rootScope.txAlertCount + ' pending transaction proposals', txAlertCount); - } + + $rootScope.$watch('blockChainStatus', function(status) { + var h = config.blockchain.host + ':' + config.blockchain.port; + if (status === 'error') + $rootScope.insightError = 1; + else + if (status === 'restored') { + $rootScope.insightError = 0; + $rootScope.$flashMessage = { + type: 'success', + message: 'Networking Restored', + }; + } }); + + // Init socket handlers (with no wallet yet) + controllerUtils.setSocketHandlers(); + $rootScope.$watch('receivedFund', function(receivedFund) { if (receivedFund) { var currentAddr; @@ -59,6 +73,14 @@ angular.module('copayApp.controllers').controller('HeaderController', } }); + $rootScope.$watch('txAlertCount', function(txAlertCount) { + if (txAlertCount && txAlertCount > 0) { + $notification.info('New Transaction', ($rootScope.txAlertCount == 1) ? 'You have a pending transaction proposal' : 'You have ' + $rootScope.txAlertCount + ' pending transaction proposals', txAlertCount); + } + }); + + + $scope.isActive = function(item) { if (item.link && item.link.replace('#','') == $location.path()) { return true; diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js index e65e8c62a..013ede6b1 100644 --- a/js/services/controllerUtils.js +++ b/js/services/controllerUtils.js @@ -174,12 +174,30 @@ angular.module('copayApp.services') $rootScope.pendingTxCount = pendingForUs; }; + root._setCommError = function(e) { + $rootScope.blockChainStatus='error'; + }; + + + root._clearCommError = function(e) { + if ($rootScope.blockChainStatus==='error') + $rootScope.blockChainStatus='restored'; + }; + root.setSocketHandlers = function() { + if (!Socket.sysEventsSet) { + Socket.sysOn('error', root._setCommError); + Socket.sysOn('reconnect_error', root._setCommError); + Socket.sysOn('reconnect_failed', root._setCommError); + Socket.sysOn('connect', root._clearCommError); + Socket.sysOn('reconnect', root._clearCommError); + Socket.sysEventsSet=true; + } if (!$rootScope.wallet) return; var currentAddrs= Socket.getListeners(); var addrs = $rootScope.wallet.getAddressesStr(); - + var newAddrs=[]; for(var i in addrs){ var a=addrs[i]; diff --git a/js/services/notifications.js b/js/services/notifications.js index f38a370e6..c37aee391 100644 --- a/js/services/notifications.js +++ b/js/services/notifications.js @@ -10,7 +10,7 @@ angular.module('notifications', []). info: { duration: 5000, enabled: true }, funds: { duration: 5000, enabled: true }, warning: { duration: 5000, enabled: true }, - error: { duration: 5000, enabled: true }, + error: { duration: 1e10, enabled: true }, success: { duration: 5000, enabled: true }, progress: { duration: 0, enabled: true }, custom: { duration: 35000, enabled: true }, diff --git a/js/services/socket.js b/js/services/socket.js index 1642309c2..54609a3c9 100644 --- a/js/services/socket.js +++ b/js/services/socket.js @@ -4,9 +4,9 @@ angular.module('copayApp.services').factory('Socket', function($rootScope) { var listeners = []; var url = 'http://' + config.socket.host + ':' + config.socket.port; - var socket = io.connect(url, { - 'reconnect': true, - 'reconnection delay': 500, + var socket = io(url, { + 'reconnection': true, + 'reconnectionDelay': 500, }); return { @@ -17,7 +17,6 @@ angular.module('copayApp.services').factory('Socket', callback.apply(socket, args); }); }; - socket.on(event, wrappedCallback); if (event !== 'connect') { listeners.push({ @@ -26,9 +25,21 @@ angular.module('copayApp.services').factory('Socket', }); } }, + sysOn: function(event, callback) { + var wrappedCallback = function() { + var args = arguments; + $rootScope.$apply(function() { + callback.apply(socket, args); + }); + }; + socket.io.on(event, wrappedCallback); + }, getListeners: function() { var ret = {}; - var addrList = listeners.map(function(i) {return i.event;}); + + var addrList = listeners + .map(function(i) {return i.event;}); + for (var i in addrList) { ret[addrList[i]] = 1; } From bfa5d4ac51c62bdfc52f156cafde453cb4b19a36 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 4 Jun 2014 20:17:45 -0300 Subject: [PATCH 2/5] add tests for Socket service --- index.html | 2 +- karma.conf.js | 2 +- test/unit/services/servicesSpec.js | 34 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 18c0a0585..573e7cc74 100644 --- a/index.html +++ b/index.html @@ -792,7 +792,7 @@ on supported browsers please check http://www.w - + diff --git a/karma.conf.js b/karma.conf.js index 8331b8672..b8e423fbe 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -33,7 +33,7 @@ module.exports = function(config) { 'lib/crypto-js/rollups/pbkdf2.js', 'lib/crypto-js/rollups/aes.js', 'lib/file-saver/FileSaver.js', - 'lib/socket.io.js', + 'lib/socket.io-client/socket.io.js', 'lib/sjcl.js', 'lib/ios-imagefile-megapixel/megapix-image.js', 'lib/qrcode-decoder-js/lib/qrcode-decoder.min.js', diff --git a/test/unit/services/servicesSpec.js b/test/unit/services/servicesSpec.js index fbb8f6c2d..63485bbeb 100644 --- a/test/unit/services/servicesSpec.js +++ b/test/unit/services/servicesSpec.js @@ -9,6 +9,40 @@ describe("Unit: Testing Services", function() { expect(Socket).not.to.equal(null); })); + + it('Socket should support #on', inject(function(Socket) { + expect(Socket.on).to.be.a('function'); + })); + + + it('Socket should support #sysOn', inject(function(Socket) { + expect(Socket.sysOn).to.be.a('function'); + })) + + + it('Socket should add handlers with #on', inject(function(Socket) { + Socket.on('a', function (){}); + Socket.on('b', function (){}); + Socket.sysOn('c', function (){}); + var ret = Socket.getListeners(); + expect(ret.a).to.be.equal(1); + expect(ret.b).to.be.equal(1); + expect(Object.keys(ret)).to.have.length(2); + })); + + it('Socket should support #removeAllListeners', inject(function(Socket) { + Socket.on('a', function (){}); + Socket.on('b', function (){}); + Socket.sysOn('c', function (){}); + var ret = Socket.getListeners(); + expect(Object.keys(ret)).to.have.length(2); + Socket.removeAllListeners(); + ret = Socket.getListeners(); + expect(Object.keys(ret)).to.have.length(0); + })); + + + it('should contain a walletFactory service', inject(function(walletFactory) { expect(walletFactory).not.to.equal(null); })); From a7cba1197afabf2afd07a66192655566b2d87cb1 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 4 Jun 2014 23:11:18 -0300 Subject: [PATCH 3/5] add karma test for controller and service --- js/controllers/header.js | 4 +- test/unit/controllers/controllersSpec.js | 103 ++++++++++++++++++++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/js/controllers/header.js b/js/controllers/header.js index a93b344ce..152fba89f 100644 --- a/js/controllers/header.js +++ b/js/controllers/header.js @@ -25,12 +25,12 @@ angular.module('copayApp.controllers').controller('HeaderController', var toInt = function (s) { return parseInt(s); }; var latestVersion = data[0].name.replace('v', '').split('.').map(toInt); var currentVersion = copay.version.split('.').map(toInt); - if (currentVersion[0] < latestVersion[0]){ $scope.updateVersion = 'error'; } else if (currentVersion[0] == latestVersion[0] && currentVersion[1] < latestVersion[1]) { $scope.updateVersion = 'info'; - } + } else + $scope.updateVersion = 'ok'; }); diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index 0209a1cbc..0b8cdd20f 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -1,7 +1,7 @@ // // test/unit/controllers/controllersSpec.js // -describe("Unit: Testing Controllers", function() { +describe("Unit: Controllers", function() { var scope; @@ -48,4 +48,105 @@ describe("Unit: Testing Controllers", function() { expect(scope.blockchain_txs).to.be.empty; }); }); + + describe("Unit: Header Controller", function() { + beforeEach(module('notifications')); + beforeEach(module('copayApp.services')); + beforeEach(module('copayApp.controllers')); + + var scope, $httpBackendOut; +// + var GH = 'https://api.github.com/repos/bitpay/copay/tags'; + beforeEach(inject(function($controller, $injector) { + $httpBackend = $injector.get('$httpBackend'); + $httpBackend.when('GET', GH) + .respond( [{ + name: "v100.1.6", + zipball_url: "https://api.github.com/repos/bitpay/copay/zipball/v0.0.6", + tarball_url: "https://api.github.com/repos/bitpay/copay/tarball/v0.0.6", + commit: { + sha: "ead7352bf2eca705de58d8b2f46650691f2bc2c7", + url: "https://api.github.com/repos/bitpay/copay/commits/ead7352bf2eca705de58d8b2f46650691f2bc2c7" + } + }]); + })); + + var rootScope; + beforeEach(inject(function($controller, $rootScope) { + rootScope = $rootScope; + scope = $rootScope.$new(); + headerCtrl = $controller('HeaderController', { + $scope: scope, + }); + })); + + + afterEach(function() { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); + + it('should have a txAlertCount', function() { + expect(scope.txAlertCount).equal(0); + $httpBackend.flush(); + }); + + it('should hit github for version', function() { + $httpBackend.expectGET(GH); + scope.$apply(); + $httpBackend.flush(); + }); + + it('should check version ', function() { + $httpBackend.expectGET(GH); + scope.$apply(); + $httpBackend.flush(); + expect(scope.updateVersion).equal('error'); + }); + + it('should check blockChainStatus', function() { + $httpBackend.expectGET(GH); + $httpBackend.flush(); + rootScope.blockChainStatus='error'; + scope.$apply(); + expect(rootScope.insightError).equal(1); + rootScope.blockChainStatus='ok'; + scope.$apply(); + expect(rootScope.insightError).equal(1); + rootScope.blockChainStatus='restored'; + scope.$apply(); + expect(rootScope.insightError).equal(0); + }); + }); + }); +// +// it('should have a BackupController controller', function() { +// expect(copayApp.Backupcontroller).not.to.equal(null); +// }); +// +// it('should have a HeaderController controller', function() { +// expect(copayApp.HeaderController).not.to.equal(null); +// }); +// +// it('should have a SendController controller', function() { +// expect(copayApp.SendController).not.to.equal(null); +// }); +// +// it('should have a SetupController controller', function() { +// expect(copayApp.SetupController).not.to.equal(null); +// }); +// +// it('should have a SigninController controller', function() { +// expect(copayApp.SigninController).not.to.equal(null); +// console.log('[controllersSpec.js.30:copayApp:]',copayApp); //TODO +// }); +// +// it('should have a TransactionsController controller', function() { +// expect(copayApp.TransactionsController).not.to.equal(null); +// }); +// +// beforeEach(angular.mock.module('copay.walletFactory')); +// it('should display a link to create a new wallet if no wallets in localStorage', inject(function(walletFactory) { +// expect(walletFactory.storage.getWalletIds()).to.be.empty; +// })); From 9c24b45f4c521bdafa0ca5d6fce68b0f5e36c8fe Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 4 Jun 2014 23:47:22 -0300 Subject: [PATCH 4/5] fix in updateVersion with tests --- css/main.css | 4 ++++ index.html | 6 +++--- js/controllers/header.js | 7 +++---- test/unit/controllers/controllersSpec.js | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/css/main.css b/css/main.css index 4a8a810fc..4aa24fbfa 100644 --- a/css/main.css +++ b/css/main.css @@ -603,6 +603,10 @@ ul.pagination li.current a:hover, ul.pagination li.current a:focus { background: #16A085; } +.alert-box a { + color:white; +} + @media only screen and (max-width: 40em) { #main, .header-content { diff --git a/index.html b/index.html index 573e7cc74..78e789e05 100644 --- a/index.html +++ b/index.html @@ -75,9 +75,9 @@
-
- A newer version of Copay is now available, please update your wallet to a latest version. - Please check Copay.io. +
+ A newer version of Copay is now available ({{updateVersion.version}}), please update your wallet. + Check Copay.io for details.
diff --git a/js/controllers/header.js b/js/controllers/header.js index 152fba89f..66acd9080 100644 --- a/js/controllers/header.js +++ b/js/controllers/header.js @@ -26,11 +26,10 @@ angular.module('copayApp.controllers').controller('HeaderController', var latestVersion = data[0].name.replace('v', '').split('.').map(toInt); var currentVersion = copay.version.split('.').map(toInt); if (currentVersion[0] < latestVersion[0]){ - $scope.updateVersion = 'error'; + $scope.updateVersion = {class: 'error', version:data[0].name}; } else if (currentVersion[0] == latestVersion[0] && currentVersion[1] < latestVersion[1]) { - $scope.updateVersion = 'info'; - } else - $scope.updateVersion = 'ok'; + $scope.updateVersion = {class: 'info', version:data[0].name}; + } }); diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index 0b8cdd20f..a2aeabac3 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -101,7 +101,8 @@ describe("Unit: Controllers", function() { $httpBackend.expectGET(GH); scope.$apply(); $httpBackend.flush(); - expect(scope.updateVersion).equal('error'); + expect(scope.updateVersion.class).equal('error'); + expect(scope.updateVersion.version).equal('v100.1.6'); }); it('should check blockChainStatus', function() { From 1a1b235aef72d6feb186d3282d073958fc826d60 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 5 Jun 2014 00:15:42 -0300 Subject: [PATCH 5/5] updates with @cmgustavo comments --- test/unit/controllers/controllersSpec.js | 36 +----------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index a2aeabac3..a610c7ced 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -50,12 +50,7 @@ describe("Unit: Controllers", function() { }); describe("Unit: Header Controller", function() { - beforeEach(module('notifications')); - beforeEach(module('copayApp.services')); - beforeEach(module('copayApp.controllers')); - var scope, $httpBackendOut; -// var GH = 'https://api.github.com/repos/bitpay/copay/tags'; beforeEach(inject(function($controller, $injector) { $httpBackend = $injector.get('$httpBackend'); @@ -121,33 +116,4 @@ describe("Unit: Controllers", function() { }); }); -// -// it('should have a BackupController controller', function() { -// expect(copayApp.Backupcontroller).not.to.equal(null); -// }); -// -// it('should have a HeaderController controller', function() { -// expect(copayApp.HeaderController).not.to.equal(null); -// }); -// -// it('should have a SendController controller', function() { -// expect(copayApp.SendController).not.to.equal(null); -// }); -// -// it('should have a SetupController controller', function() { -// expect(copayApp.SetupController).not.to.equal(null); -// }); -// -// it('should have a SigninController controller', function() { -// expect(copayApp.SigninController).not.to.equal(null); -// console.log('[controllersSpec.js.30:copayApp:]',copayApp); //TODO -// }); -// -// it('should have a TransactionsController controller', function() { -// expect(copayApp.TransactionsController).not.to.equal(null); -// }); -// -// beforeEach(angular.mock.module('copay.walletFactory')); -// it('should display a link to create a new wallet if no wallets in localStorage', inject(function(walletFactory) { -// expect(walletFactory.storage.getWalletIds()).to.be.empty; -// })); +