diff --git a/app/partials/login.jade b/app/partials/login.jade index b7bd50de51..b30d9eca80 100644 --- a/app/partials/login.jade +++ b/app/partials/login.jade @@ -11,16 +11,18 @@ div p.em-300(translate="LOGIN_BELOW") //GUID & Password fields form.ptl.form-horizontal.clearfix(role="form" autocomplete="off" novalidate) + browser-detection(result="browser") .form-group(ng-class="{'has-error': errors.uid}") label.em-500(translate="UID", for="UID_input") div - input#UID_input.form-control(type="text", ng-model="uid", ng-disabled="busy || disableLogin" name="UID_input" focus-when="!uidAvailable") + input#UID_input.form-control(type="text", ng-model="uid", ng-disabled="busy || browser.disabled" name="UID_input" focus-when="!uidAvailable") + span.help-block(ng-show="errors.uid" ui-sref="public.reminder" translate="{{ errors.uid }}") span.help-block.info.hidden-xs(translate="FIND_GUID_EXPLAIN") .form-group(ng-class="{'has-error': errors.password}") label.em-500(translate="PASSWORD", for="pass_input") div - input#pass_input.form-control(type="password", name="pass_input" ng-model="password", ng-disabled="busy || disableLogin" focus-when="uidAvailable") + input#pass_input.form-control(type="password", name="pass_input" ng-model="password", ng-disabled="busy || browser.disabled" focus-when="uidAvailable") span.help-block {{ errors.password }} .form-group(ng-show="settings.needs2FA", ng-class="{'has-error': errors.twoFactor || settings.twoFactorMethod == 3}") label.em-500 @@ -36,7 +38,7 @@ div img(ng-show="resending" src="img/spinner.gif") a(ng-click="resend()", ng-show="!resending", translate="RESEND") .mtl.flex-center.flex-end - button.button-primary(ui-ladda="busy", ng-click="login()", data-style="expand-left", ladda-translate="SIGNIN", ng-disabled="!isValid") + button.button-primary(ui-ladda="busy", ng-click="login()", data-style="expand-left", ladda-translate="SIGNIN", ng-disabled="!isValid || browser.disabled") //Wallet Recovery .ptl.flex-row.flex-between a.em-300(href="{{rootURL}}wallet-legacy/login" translate="LOGIN_TO_LEGACY") diff --git a/app/partials/recover-funds.jade b/app/partials/recover-funds.jade index b6c4fb3329..64e2c8e610 100644 --- a/app/partials/recover-funds.jade +++ b/app/partials/recover-funds.jade @@ -7,6 +7,7 @@ p(translate="RECOVER_BTC_LOST") form.ptl.form-horizontal(name="passphraseForm" autocomplete="off" ng-switch-when="1" novalidate) div + browser-detection(result="browser") .security-red.mbl.em-400.flex-center i.ti-hand-stop.mrm.h3.mvn.hidden-xs span(translate="RECOVER_FUNDS_WARNING") @@ -19,7 +20,7 @@ ng-keyup="getMnemonicLength()" ng-model="fields.mnemonic" is-valid="isValidMnemonic(fields.mnemonic)" - ng-disabled="disableSignup" + ng-disabled="browser.disabled" required) .flex-center.flex-end img(ng-show="working" src="img/spinner.gif") @@ -31,7 +32,7 @@ button.button-primary( type="submit" ng-click="nextStep()" - ng-disabled="!passphraseForm.$valid || disableSignup" + ng-disabled="!passphraseForm.$valid || browser.disabled" translate="CONTINUE") form.ptl.form-horizontal(name="recoveryForm" ng-switch-when="2") div diff --git a/app/partials/signup.jade b/app/partials/signup.jade index ad3dcef978..e63a8deb28 100644 --- a/app/partials/signup.jade +++ b/app/partials/signup.jade @@ -8,6 +8,7 @@ div autocomplete="off" novalidate) .form-group(ng-class="{'has-error': signupForm.email.$invalid && signupForm.email.$touched}") + browser-detection(result="browser") label.col-sm-4.control-label(translate="EMAIL") .col-sm-8 input.form-control( @@ -15,7 +16,7 @@ div type="email" ng-model="fields.email" required - ng-disabled="disableSignup" + ng-disabled="browser.disabled" autofocus) span.help-block div(ng-show="signupForm.email.$touched") @@ -32,7 +33,7 @@ div min-entropy="25" ng-change="fields.confirmation = ''" focus-when="fields.email.length" - ng-disabled="disableSignup" + ng-disabled="browser.disabled" required) password-entropy.help-block(password="fields.password") span.help-block @@ -47,7 +48,7 @@ div type="password" ng-model="fields.confirmation" is-valid="fields.confirmation == fields.password" - ng-disabled="disableSignup" + ng-disabled="browser.disabled" required) span.help-block div(ng-show="signupForm.confirmation.$touched") @@ -58,7 +59,7 @@ div name="agreement" type="checkbox" ng-model="fields.acceptedAgreement" - ng-disabled="disableSignup" + ng-disabled="browser.disabled" required) label.em-300.col-sm-8.accept-label.right-align | I have read and agree to the @@ -66,7 +67,7 @@ div .flex-center.flex-end.mbl.prl button.button-primary( type="submit" - ng-disabled="signupForm.$invalid || disableSignup" + ng-disabled="signupForm.$invalid || browser.disabled" translate="CONTINUE" ng-show="!working") img(ng-show="working" src="img/spinner.gif") diff --git a/assets/js/controllers/accountForm.controller.js b/assets/js/controllers/accountForm.controller.js index c13fa0ad67..8ff2b8e36f 100644 --- a/assets/js/controllers/accountForm.controller.js +++ b/assets/js/controllers/accountForm.controller.js @@ -2,7 +2,7 @@ angular .module('walletApp') .controller('AccountFormCtrl', AccountFormCtrl); -function AccountFormCtrl ($scope, Wallet, $uibModalInstance, $log, $translate, account) { +function AccountFormCtrl ($scope, Wallet, $uibModalInstance, $log, $translate, account, Alerts) { $scope.accounts = Wallet.accounts; $scope.fields = { @@ -34,7 +34,15 @@ function AccountFormCtrl ($scope, Wallet, $uibModalInstance, $log, $translate, a const cancel = () => $scope.status.busy = false; - Wallet.createAccount($scope.fields.name, success, error, cancel); + $scope.$$postDigest(() => { + if (!Wallet.my.browserCheck()) { + $scope.status.busy = false; + Alerts.displayError($translate.instant('UNSUITABLE_BROWSER'), true); + $scope.close(); + } else { + Wallet.createAccount($scope.fields.name, success, error, cancel); + } + }); }; $scope.updateAccount = () => { diff --git a/assets/js/controllers/login.controller.js b/assets/js/controllers/login.controller.js index db3d5691e8..201f0a9adb 100644 --- a/assets/js/controllers/login.controller.js +++ b/assets/js/controllers/login.controller.js @@ -41,7 +41,7 @@ function LoginCtrl ($scope, $rootScope, $location, $log, $http, Wallet, WalletNe $scope.user = Wallet.user; - $scope.disableLogin = !Wallet.checkBrowserVersion(); + $scope.browser = {disabled: true}; $scope.twoFactorCode = ''; $scope.busy = false; diff --git a/assets/js/controllers/recoverFunds.controller.js b/assets/js/controllers/recoverFunds.controller.js index 87768b875f..6ad4cf75eb 100644 --- a/assets/js/controllers/recoverFunds.controller.js +++ b/assets/js/controllers/recoverFunds.controller.js @@ -13,7 +13,7 @@ function RecoverFundsCtrl ($scope, $rootScope, $state, $timeout, $translate, $co bip39phrase: '' }; - $scope.disableSignup = !Wallet.checkBrowserVersion(); + $scope.browser = {disabled: true}; $scope.performImport = () => { $scope.working = true; @@ -59,8 +59,18 @@ function RecoverFundsCtrl ($scope, $rootScope, $state, $timeout, $translate, $co }; $scope.nextStep = () => { - $scope.currentStep++; - $scope.fields.confirmation = ''; + $scope.working = true; + $scope.$$postDigest(() => { + if (!Wallet.my.browserCheck()) { + $scope.working = false; + $scope.browser.disabled = true; + $scope.browser.msg = $translate.instant('UNSUITABLE_BROWSER'); + } else { + $scope.working = false; + $scope.currentStep++; + $scope.fields.confirmation = ''; + } + }); }; $scope.goBack = () => { diff --git a/assets/js/controllers/signup.controller.js b/assets/js/controllers/signup.controller.js index 1b7a5e8b4c..448c14858a 100644 --- a/assets/js/controllers/signup.controller.js +++ b/assets/js/controllers/signup.controller.js @@ -2,14 +2,14 @@ angular .module('walletApp') .controller('SignupCtrl', SignupCtrl); -SignupCtrl.$inject = ['$scope', '$state', '$cookies', '$filter', '$translate', '$uibModal', 'Wallet', 'Alerts', 'currency', 'languages']; +SignupCtrl.$inject = ['$scope', '$state', '$cookies', '$filter', '$translate', '$uibModal', 'Wallet', 'Alerts', 'currency', 'languages', 'MyWallet']; -function SignupCtrl ($scope, $state, $cookies, $filter, $translate, $uibModal, Wallet, Alerts, currency, languages) { +function SignupCtrl ($scope, $state, $cookies, $filter, $translate, $uibModal, Wallet, Alerts, currency, languages, MyWallet) { $scope.working = false; $scope.alerts = Alerts.alerts; $scope.status = Wallet.status; - $scope.disableSignup = !Wallet.checkBrowserVersion(); + $scope.browser = {disabled: true}; $scope.$watch('status.isLoggedIn', newValue => { if (newValue) { @@ -58,16 +58,24 @@ function SignupCtrl ($scope, $state, $cookies, $filter, $translate, $uibModal, W $scope.signup = () => { if ($scope.signupForm.$valid) { $scope.working = true; - $scope.createWallet((uid, sessionToken) => { - $scope.working = false; - if (uid != null) { - $cookies.put('uid', uid); - $cookies.put('session', sessionToken); + $scope.$$postDigest(() => { + if (!MyWallet.browserCheck()) { + $scope.browser.disabled = true; + $scope.browser.msg = $translate.instant('UNSUITABLE_BROWSER'); + $scope.working = false; + } else { + $scope.createWallet((uid, sessionToken) => { + $scope.working = false; + if (uid != null) { + $cookies.put('uid', uid); + $cookies.put('session', sessionToken); + } + if ($scope.autoReload) { + $cookies.put('password', $scope.fields.password); + } + $scope.close(''); + }); } - if ($scope.autoReload) { - $cookies.put('password', $scope.fields.password); - } - $scope.close(''); }); } }; diff --git a/assets/js/directives/browserDetection.directive.js b/assets/js/directives/browserDetection.directive.js new file mode 100644 index 0000000000..15d496906a --- /dev/null +++ b/assets/js/directives/browserDetection.directive.js @@ -0,0 +1,141 @@ + +angular + .module('walletApp') + .directive('browserDetection', directive); + +// Browser compatibility warnings: +// * Secure random number generator: https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues +// * AngularJS support (?) +// * No support before Safari 6 and equivalents based on experience + +const browsers = { + 'ie': { + name: 'Internet Explorer', + requiredVersion: 11 + }, + 'chrome': { + name: 'Chrome', + requiredVersion: 30 // Roughly the same as Webkit 537.85.17 + }, + 'firefox': { + name: 'Firefox', + requiredVersion: 21 + }, + 'opera': { + name: 'Opera', + requiredVersion: 20 // First Chromium (33) based release + } +}; + +directive.$inject = ['$q', '$translate', 'MyWallet']; + +function directive ($q, $translate, MyWallet) { + const directive = { + restrict: 'E', + replace: true, + scope: { + result: '=' // Should initially be {disabled: true} + }, + template: ` +
+

{{ result.msg }}

+

{{ result.msg }}

+
+ `, + link: link + }; + return directive; + + function link (scope, elem, attrs) { + // Unknown browser, check if it can handle the math required: + const checkUnknownBrowser = (defer) => { + if (!MyWallet.browserCheckFast()) { + $translate('UNSUITABLE_BROWSER').then((translation) => { + defer.reject({msg: translation}); + }); + } else { + $translate('UNKNOWN_BROWSER').then((translation) => { + defer.resolve({warn: true, msg: translation}); + }); + } + }; + + scope.getUserAgent = () => navigator.userAgent; + + const checkBrowserVersion = () => { + let defer = $q.defer(); + + let info = browserDetection(); + let matchingBrowser = browsers[info.browser.toLowerCase()]; + if (matchingBrowser) { // One of the known browsers listed above + let requiredVersion = matchingBrowser.requiredVersion; + if (info.version < requiredVersion) { + $translate('MINIMUM_BROWSER', {browser: matchingBrowser.name, userVersion: info.version, requiredVersion: requiredVersion}).then((translation) => { + defer.reject({msg: translation}); + }); + } else if (info.browser === 'ie') { + $translate('WARN_AGAINST_IE').then((translation) => { + defer.resolve({warn: true, msg: translation}); + }); + } else { + defer.resolve({}); + } + } else if (info.webkit) { + // 537.36 is the version referenced by modern Chrome, slightly lower + // might still be acceptable. + let minimumWebkitVersion = '537.36'; + // Patch field may be undefined: + let userVersion = [ + info.webkit.major, + info.webkit.minor, + info.webkit.patch + ].filter((x) => typeof (x) === 'number').join('.'); + if (compareVersions(userVersion, minimumWebkitVersion) === -1) { + // Webkit version too old. + if (info.browser === 'safari') { + let safariVersion = 'version'; + const safari = scope.getUserAgent().match(/version\/(\d+\.\d+)/i); + if (safari && safari.length === 2) { + safariVersion = safari[1]; + } + + // The last patch version of Safari 5 (5.1.4 - webkit 534.54.16) did + // work when last checked, but 5.1.2. does not. We increased the + // minimum Safari 6.1 to be on the safe side. + $translate('MINIMUM_BROWSER', {browser: 'Safari', userVersion: safariVersion, requiredVersion: '6.1'}).then((translation) => { + defer.reject({msg: translation}); + }); + } else { + $translate('MINIMUM_BROWSER', {browser: 'Webkit', userVersion: userVersion, requiredVersion: minimumWebkitVersion}).then((translation) => { + defer.reject({msg: translation}); + }); + } + } else { + if (info.browser === 'safari') { + defer.resolve({}); + } else { + // Unknown webkit browser: + checkUnknownBrowser(defer); + } + } + } else { + // Unknown non-webkit browser: + checkUnknownBrowser(defer); + } + return defer.promise; + }; + + scope.performCheck = () => { + checkBrowserVersion().then((res) => { + scope.result.disabled = false; + scope.result.warn = res.warn; + scope.result.msg = res.msg; + }).catch((res) => { + scope.result.disabled = true; + scope.result.msg = res.msg; + }); + }; + + scope.performCheck(); + } +} diff --git a/assets/js/services/wallet.service.js b/assets/js/services/wallet.service.js index dc15b20665..74112c0f7a 100644 --- a/assets/js/services/wallet.service.js +++ b/assets/js/services/wallet.service.js @@ -1159,68 +1159,6 @@ function Wallet ($http, $window, $timeout, $location, Alerts, MyWallet, MyBlockc wallet.my.wallet.encrypt(password, success, error, encrypting, syncing); }; - // Browser compatibility warnings: - // * Secure random number generator: https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues - // * AngularJS support (?) - // * No support before Safari 6 and equivalents based on experience - - const browsers = { - 'ie': { - browser: 'Internet Explorer', - requiredVersion: 11 - }, - 'chrome': { - browser: 'Chrome', - requiredVersion: 30 // Roughly the same as Webkit 537.85.17 - }, - 'firefox': { - browser: 'Firefox', - requiredVersion: 21 - }, - 'opera': { - browser: 'Opera', - requiredVersion: 20 // First Chromium (33) based release - } - }; - wallet.checkBrowserVersion = () => { - let info = browserDetection(); - let matchingBrowser = browsers[info.browser.toLowerCase()]; - if (matchingBrowser) { // One of the known browsers listed above - let requiredVersion = matchingBrowser.requiredVersion; - if (info.version < requiredVersion) { - $translate('MINIMUM_BROWSER', {browser: info.browser, userVersion: info.version, requiredVersion: requiredVersion}).then(Alerts.displayError); - return false; - } else if (info.browser === 'ie') { - Alerts.displayWarning('WARN_AGAINST_IE'); - return true; - } else { - return true; - } - } else if (info.webkit) { - let minimumWebkitVersion = '537.85.17'; - // Patch field may be undefined: - let userVersion = [ - info.webkit.major, - info.webkit.minor, - info.webkit.patch - ].filter((x) => typeof (x) === 'number').join('.'); - if (compareVersions(userVersion, minimumWebkitVersion) === -1) { - // Webkit version too old. - if (info.browser === 'safari') { - $translate('MINIMUM_BROWSER', {browser: 'Safari', userVersion: 'version', requiredVersion: '6.2.8'}).then(Alerts.displayError); - } else { - $translate('MINIMUM_BROWSER', {browser: 'Webkit', userVersion: info.version, requiredVersion: minimumWebkitVersion}).then(Alerts.displayError); - } - return false; - } else { - return true; - } - } else { - Alerts.displayWarning('UNKNOWN_BROWSER'); - return true; - } - }; - // Testing: only works on mock MyWallet wallet.refresh = () => { diff --git a/locales/en-human.json b/locales/en-human.json index d46c4d47d0..a8cf96ca73 100644 --- a/locales/en-human.json +++ b/locales/en-human.json @@ -369,6 +369,7 @@ "WARN_AGAINST_IE" : "We recommend that you login using a more secure browser like Chrome or Safari.", "MINIMUM_BROWSER" : "{{ browser }} {{ userVersion }} is not supported. Please install {{ browser }} {{ requiredVersion }} or newer.", "UNKNOWN_BROWSER" : "Be careful when using a browser other than Chrome, Firefox or Safari. Make sure it supports secure random number generation and offers strong protection against cross site scripting attacks or you may lose your bitcoins.", + "UNSUITABLE_BROWSER" : "Your browser is not supported", "SPONSORS" : "Sponsored Links", "BITCOIN_CURRENCY" : "Bitcoin Unit", "BITCOIN_CURRENCY_EXPLAIN": "Adjust the precision you would prefer bitcoin values to be displayed in.", diff --git a/tests/controllers/account_form_ctrl_spec.coffee b/tests/controllers/account_form_ctrl_spec.coffee index a4effaa3dd..361966b791 100644 --- a/tests/controllers/account_form_ctrl_spec.coffee +++ b/tests/controllers/account_form_ctrl_spec.coffee @@ -13,6 +13,7 @@ describe "AccountFormCtrl", -> angular.mock.inject ($injector) -> Wallet = $injector.get("Wallet") MyWallet = $injector.get("MyWallet") + Wallet.my.browserCheck = () -> true Wallet.accounts = () -> accounts @@ -68,11 +69,13 @@ describe "AccountFormCtrl", -> it "should be created", inject((Wallet) -> before = Wallet.accounts().length scope.createAccount() + scope.$digest() expect(Wallet.accounts().length).toBe(before + 1) ) it "should have a name", inject((Wallet) -> scope.createAccount() + scope.$digest() expect(Wallet.accounts()[Wallet.accounts().length - 1].label).toBe("New Account") ) diff --git a/tests/controllers/recover_funds_ctrl_spec.coffee b/tests/controllers/recover_funds_ctrl_spec.coffee index e35bf58aaf..23518960ed 100644 --- a/tests/controllers/recover_funds_ctrl_spec.coffee +++ b/tests/controllers/recover_funds_ctrl_spec.coffee @@ -1,30 +1,30 @@ describe "RecoverFundsCtrl", -> scope = undefined Wallet = undefined - MyWallet = undefined beforeEach angular.mock.module("walletApp") beforeEach -> angular.mock.inject ($injector, $rootScope, $controller) -> Wallet = $injector.get("Wallet") - MyWallet = $injector.get("MyWallet") Wallet.login = (guid, pw, success, error) -> success() - Wallet.my.recoverFromMnemonic = (email, password, mnemonic, bip39, success, error) -> + Wallet.my.recoverFromMnemonic = (email, password, mnemonic, bip39, success, error) -> success({email,password,mnemonic,bip39}) - + + Wallet.my.browserCheck = () -> true + scope = $rootScope.$new() - + $controller "RecoverFundsCtrl", $scope: scope - + scope.$digest() scope.fields = { mnemonic: 'bitcoin is not just a currency it is a way of life' } - + return return @@ -40,11 +40,12 @@ describe "RecoverFundsCtrl", -> it "should be able to increase steps", -> scope.nextStep() + scope.$digest() expect(scope.currentStep).toBe(2) it "should be able to go back steps", -> scope.goBack() - expect(scope.currentStep).toBe(0) + expect(scope.currentStep).toBe(0) describe "performImport function", -> @@ -54,4 +55,3 @@ describe "RecoverFundsCtrl", -> expect(scope.working).toBe(false) $timeout.flush() ) - diff --git a/tests/controllers/signup_controller_spec.coffee b/tests/controllers/signup_controller_spec.coffee index 0a81b4451c..fb62a8c3f7 100644 --- a/tests/controllers/signup_controller_spec.coffee +++ b/tests/controllers/signup_controller_spec.coffee @@ -9,6 +9,9 @@ describe "SignupCtrl", -> beforeEach -> angular.mock.inject ($injector, $rootScope, $controller, $compile, $templateCache) -> Wallet = $injector.get("Wallet") + + Wallet.my.browserCheck = () -> true + $state = $injector.get("$state") # This is a mock $state.params = {email: ''} @@ -54,6 +57,7 @@ describe "SignupCtrl", -> scope.$digest() scope.signup() + scope.$digest() expect(scope.createWallet).not.toHaveBeenCalled() describe "password", -> @@ -107,6 +111,8 @@ describe "SignupCtrl", -> it "should call createWallet()", -> spyOn(scope, "createWallet") scope.signup() + scope.$digest() + expect(scope.createWallet).toHaveBeenCalled() it "should not call createWallet() if validation failed", -> @@ -127,6 +133,7 @@ describe "SignupCtrl", -> it "should add uid to cookies", inject(($cookies) -> spyOn($cookies, 'put') scope.signup() + scope.$digest() expect($cookies.put).toHaveBeenCalledWith('uid', "new_guid") ) @@ -136,6 +143,7 @@ describe "SignupCtrl", -> scope.fields.password = "testing" scope.signup() + scope.$digest() expect($cookies.put).toHaveBeenCalledWith('password', "testing") ) diff --git a/tests/directives/browser-detection_spec.coffee b/tests/directives/browser-detection_spec.coffee new file mode 100644 index 0000000000..4bf1e7ada6 --- /dev/null +++ b/tests/directives/browser-detection_spec.coffee @@ -0,0 +1,124 @@ +describe "browserDetection", -> + $compile = undefined + $rootScope = undefined + element = undefined + isoScope = undefined + MyWallet = undefined + + beforeEach module("walletApp") + + beforeEach inject((_$compile_, _$rootScope_) -> + + $compile = _$compile_ + $rootScope = _$rootScope_ + + angular.mock.inject ($injector, $q) -> + MyWallet = $injector.get("MyWallet") + + MyWallet.browserCheckFast = () -> null + + return + ) + + beforeEach -> + $rootScope.browser = {disabled: true} + element = $compile("")($rootScope) + $rootScope.$digest() + isoScope = element.isolateScope() + isoScope.$digest() + + it "should have text", -> + expect(element.html()).toContain "text-warning" + + it "should be enabled for PhantomJS", -> + expect(isoScope.result.disabled).toBe(false) + + describe "performCheck()", -> + + it "should not show an error when above minimum version", -> + isoScope.performCheck() + isoScope.$digest() + expect(isoScope.result.disabled).toBe(false) + + it "should show an error when below minimum version", -> + spyOn(window, "browserDetection").and.returnValue {version: 10, browser: "Chrome"} + + isoScope.performCheck() + isoScope.$digest() + expect(isoScope.result.disabled).toBe(true) + expect(isoScope.result.msg).toEqual('MINIMUM_BROWSER|Chrome|10|30') + + it "should warn against an unknown but safe browser", -> + spyOn(MyWallet, "browserCheckFast").and.returnValue true + spyOn(window, "browserDetection").and.returnValue {version: 1, browser: "Random"} + + isoScope.performCheck() + isoScope.$digest() + expect(isoScope.result.disabled).toBe(false) + expect(isoScope.result.msg).toEqual('UNKNOWN_BROWSER') + + it "should reject an unknown unsafe browser", -> + spyOn(MyWallet, "browserCheckFast").and.returnValue false + spyOn(window, "browserDetection").and.returnValue {version: 1, browser: "Random"} + + isoScope.performCheck() + isoScope.$digest() + expect(isoScope.result.disabled).toBe(true) + expect(isoScope.result.msg).toEqual('UNSUITABLE_BROWSER') + + it "should warn against IE, but allow it", -> + spyOn(window, "browserDetection").and.returnValue {version: 11, browser: "ie"} + + isoScope.performCheck() + isoScope.$digest() + + expect(isoScope.result.disabled).toBe(false) + expect(isoScope.result.msg).toEqual('WARN_AGAINST_IE') + + describe "old Safari", -> + beforeEach -> + spyOn(window, "browserDetection").and.returnValue {version: 300, browser: "safari", webkit: {major: 200, minor: 0, patch: 0}} + spyOn(isoScope, "getUserAgent").and.returnValue "... Version/5.1.2 Safari/534.54" + + isoScope.performCheck() + isoScope.$digest() + + it "should be rejected", -> + expect(isoScope.result.disabled).toBe(true) + + it "should include Safari version in error message", -> + expect(isoScope.result.msg).toEqual("MINIMUM_BROWSER|Safari|5.1|6.1") + + it "should permit modern Safari", -> + spyOn(window, "browserDetection").and.returnValue {version: 600, browser: "safari", webkit: {major: 600, minor: 0, patch: 0}} + + isoScope.performCheck() + isoScope.$digest() + + expect(isoScope.result.disabled).toBe(false) + + it "should disallow old Webkit", -> + spyOn(window, "browserDetection").and.returnValue {version: 2, browser: "obscure", webkit: {major: 200, minor: 0, patch: 0}} + + isoScope.performCheck() + isoScope.$digest() + + expect(isoScope.result.disabled).toBe(true) + + it "should permit modern Webkit if safe", -> + spyOn(MyWallet, "browserCheckFast").and.returnValue true + spyOn(window, "browserDetection").and.returnValue {version: 2, browser: "obscure", webkit: {major: 600, minor: 0, patch: 0}} + + isoScope.performCheck() + isoScope.$digest() + + expect(isoScope.result.disabled).toBe(false) + + it "should reject modern non-Safari Webkit if unsafe", -> + spyOn(MyWallet, "browserCheckFast").and.returnValue false + spyOn(window, "browserDetection").and.returnValue {version: 2, browser: "obscure", webkit: {major: 600, minor: 0, patch: 0}} + + isoScope.performCheck() + isoScope.$digest() + + expect(isoScope.result.disabled).toBe(true) diff --git a/tests/mocks/translate_mock.coffee b/tests/mocks/translate_mock.coffee index 14791ee2fd..d6ca44c017 100644 --- a/tests/mocks/translate_mock.coffee +++ b/tests/mocks/translate_mock.coffee @@ -17,7 +17,10 @@ angular.module("pascalprecht.translate").provider "$translate", -> , {} promise.then = (callback) -> - callback(template) + res = template + for key, value of params + res += "|" + value + callback(res) return promise diff --git a/tests/services/wallet_service_spec.coffee b/tests/services/wallet_service_spec.coffee index 491a87fcd7..8310434d14 100644 --- a/tests/services/wallet_service_spec.coffee +++ b/tests/services/wallet_service_spec.coffee @@ -488,48 +488,3 @@ describe "walletServices", () -> it "should be null if not logged in", -> Wallet.status.isLoggedIn = false expect(Wallet.accounts()).toBe(null) - - describe "browser detection", -> - - beforeEach -> - spyOn(Alerts, 'displayError').and.callFake(() ->) - spyOn(Alerts, 'displayWarning').and.callFake(() ->) - - it "should not show an error when above minimum version", -> - Wallet.checkBrowserVersion() - expect(Wallet.checkBrowserVersion()).toBe(true) - expect(Alerts.displayError).not.toHaveBeenCalled() - - it "should show an error when below minimum version", -> - spyOn(window, "browserDetection").and.returnValue {version: 10, browser: "Chrome"} - - expect(Wallet.checkBrowserVersion()).toBe(false) - expect(Alerts.displayError).toHaveBeenCalledWith('MINIMUM_BROWSER') - - it "should warn against an unknown browser", -> - spyOn(window, "browserDetection").and.returnValue {version: 1, browser: "Random"} - - expect(Wallet.checkBrowserVersion()).toBe(true) - expect(Alerts.displayWarning).toHaveBeenCalledWith('UNKNOWN_BROWSER') - - it "should warn against IE, but allow it", -> - spyOn(window, "browserDetection").and.returnValue {version: 11, browser: "ie"} - - expect(Wallet.checkBrowserVersion()).toBe(true) - expect(Alerts.displayWarning).toHaveBeenCalledWith('WARN_AGAINST_IE') - - it "should disallow against old Safari", -> - spyOn(window, "browserDetection").and.returnValue {version: 300, browser: "safari", webkit: {major: 200, minor: 0, patch: 0}} - expect(Wallet.checkBrowserVersion()).toBe(false) - - it "should permit modern Safari", -> - spyOn(window, "browserDetection").and.returnValue {version: 600, browser: "safari", webkit: {major: 600, minor: 0, patch: 0}} - expect(Wallet.checkBrowserVersion()).toBe(true) - - it "should disallow old Webkit", -> - spyOn(window, "browserDetection").and.returnValue {version: 2, browser: "obscure", webkit: {major: 200, minor: 0, patch: 0}} - expect(Wallet.checkBrowserVersion()).toBe(false) - - it "should permit modern Webkit", -> - spyOn(window, "browserDetection").and.returnValue {version: 2, browser: "obscure", webkit: {major: 600, minor: 0, patch: 0}} - expect(Wallet.checkBrowserVersion()).toBe(true)