Merge pull request #759 from cmgustavo/bug/01-amount-input

Bug/01 amount input
This commit is contained in:
Matias Alejo Garcia 2014-06-26 22:47:56 -03:00
commit 4467ae270f
7 changed files with 136 additions and 44 deletions

View File

@ -635,3 +635,9 @@ ul.pagination li.current a:hover, ul.pagination li.current a:focus {
color:white; color:white;
} }
.input-note {
margin-top: -10px;
display: block;
margin-bottom: 1rem;
}

View File

@ -696,7 +696,6 @@
<div class="row collapse"> <div class="row collapse">
<label for="amount">Amount <label for="amount">Amount
<small ng-hide="!sendForm.amount.$pristine">required</small> <small ng-hide="!sendForm.amount.$pristine">required</small>
<i class="fi-arrow-up" title="Send all funds" ng-click="topAmount()"></i>
<small class="is-valid" ng-show="!sendForm.amount.$invalid && !sendForm.amount.$pristine">Valid</small> <small class="is-valid" ng-show="!sendForm.amount.$invalid && !sendForm.amount.$pristine">Valid</small>
<small class="has-error" ng-show="sendForm.amount.$invalid && !sendForm.amount.$pristine && !notEnoughAmount"> <small class="has-error" ng-show="sendForm.amount.$invalid && !sendForm.amount.$pristine && !notEnoughAmount">
Not valid Not valid
@ -706,9 +705,14 @@
<div class="small-9 columns"> <div class="small-9 columns">
<input type="number" id="amount" ng-disabled="loading" <input type="number" id="amount" ng-disabled="loading"
name="amount" placeholder="Amount" ng-model="amount" name="amount" placeholder="Amount" ng-model="amount"
min="1" max="10000000000" enough-amount required min="0.0001" max="10000000000" enough-amount required
autocomplete="off" autocomplete="off"
> >
<a class="small input-note" title="Send all funds"
ng-show="$root.availableBalance > 0"
ng-click="topAmount(sendForm)">
Use all funds ({{getAvailableAmount()}} {{$root.unitName}})
</a>
</div> </div>
<div class="small-3 columns"> <div class="small-3 columns">
<span class="postfix">{{$root.unitName}}</span> <span class="postfix">{{$root.unitName}}</span>
@ -720,13 +724,13 @@
Total amount for this transaction: Total amount for this transaction:
</small> </small>
<div class="totalAmount"> <div class="totalAmount">
<b>{{amount + defaultFee |number}}</b> {{$root.unitName}} <b>{{amount + defaultFee |number:4}}</b> {{$root.unitName}}
<small> <small>
{{ ((amount + defaultFee) * unitToBtc) |number}} BTC {{ ((amount + defaultFee) * unitToBtc) |number:4}} BTC
</small> </small>
</div> </div>
<small> <small>
Including fee of {{defaultFee|number}} {{$root.unitName}} Including fee of {{defaultFee |number:4}} {{$root.unitName}}
</small> </small>
</div> </div>
</div> </div>

View File

@ -267,8 +267,12 @@ angular.module('copayApp.controllers').controller('SendController',
}); });
}; };
$scope.topAmount = function() { $scope.getAvailableAmount = function() {
var maxSat = ($rootScope.availableBalance * config.unitToSatoshi).toFixed(0) - bitcore.TransactionBuilder.FEE_PER_1000B_SAT; return ((($rootScope.availableBalance * config.unitToSatoshi).toFixed(0) - bitcore.TransactionBuilder.FEE_PER_1000B_SAT) / config.unitToSatoshi);
$scope.amount = maxSat / config.unitToSatoshi; };
$scope.topAmount = function(form) {
$scope.amount = $scope.getAvailableAmount();
form.amount.$pristine = false;
}; };
}); });

View File

@ -40,12 +40,12 @@ angular.module('copayApp.directives')
.directive('enoughAmount', ['$rootScope', .directive('enoughAmount', ['$rootScope',
function($rootScope) { function($rootScope) {
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var feeSat = bitcore.TransactionBuilder.FEE_PER_1000B_SAT; var feeSat = Number(bitcore.TransactionBuilder.FEE_PER_1000B_SAT);
return { return {
require: 'ngModel', require: 'ngModel',
link: function(scope, element, attrs, ctrl) { link: function(scope, element, attrs, ctrl) {
var val = function(value) { var val = function(value) {
var availableBalanceNum = ($rootScope.availableBalance * config.unitToSatoshi).toFixed(0); var availableBalanceNum = Number(($rootScope.availableBalance * config.unitToSatoshi).toFixed(0));
var vNum = Number((value * config.unitToSatoshi).toFixed(0)) + feeSat; var vNum = Number((value * config.unitToSatoshi).toFixed(0)) + feeSat;
if (typeof vNum == "number" && vNum > 0) { if (typeof vNum == "number" && vNum > 0) {
if (availableBalanceNum < vNum) { if (availableBalanceNum < vNum) {

View File

@ -282,10 +282,23 @@ describe("Unit: Controllers", function() {
}); });
describe('Send Controller', function() { describe('Send Controller', function() {
var sendCtrl; var sendCtrl, form;
beforeEach(inject(function($controller, $rootScope) { beforeEach(inject(function($compile, $rootScope, $controller) {
scope = $rootScope.$new(); scope = $rootScope.$new();
$rootScope.availableBalance = 123456; $rootScope.availableBalance = 123456;
var element = angular.element(
'<form name="form">' +
'<input type="number" id="amount" name="amount" placeholder="Amount" ng-model="amount" min="0.0001" max="10000000" enough-amount required>' +
'</form>'
);
scope.model = {
amount: null
};
$compile(element)(scope);
scope.$digest();
form = scope.form;
sendCtrl = $controller('SendController', { sendCtrl = $controller('SendController', {
$scope: scope, $scope: scope,
$modal: {}, $modal: {},
@ -296,8 +309,15 @@ describe("Unit: Controllers", function() {
expect(scope.isMobile).not.to.equal(null); expect(scope.isMobile).not.to.equal(null);
}); });
it('should autotop balance correctly', function() { it('should autotop balance correctly', function() {
scope.topAmount(); scope.topAmount(form);
form.amount.$setViewValue(123356);
expect(scope.amount).to.equal(123356); expect(scope.amount).to.equal(123356);
expect(form.amount.$invalid).to.equal(false);
expect(form.amount.$pristine).to.equal(false);
});
it('should return available amount', function() {
var amount = scope.getAvailableAmount();
expect(amount).to.equal(123356);
}); });
}); });

View File

@ -8,6 +8,10 @@ describe("Unit: Testing Directives", function() {
beforeEach(module('copayApp.directives')); beforeEach(module('copayApp.directives'));
beforeEach(function() {
config.unitToSatoshi = 100;
config.unitName = 'bits';
});
describe('Check config', function() { describe('Check config', function() {
it('unit should be set to BITS in config.js', function() { it('unit should be set to BITS in config.js', function() {
@ -43,41 +47,89 @@ describe("Unit: Testing Directives", function() {
}); });
describe('Validate Amount', function() { describe('Validate Amount', function() {
beforeEach(inject(function($compile, $rootScope) { describe('Unit: bits', function() {
$scope = $rootScope; beforeEach(inject(function($compile, $rootScope) {
$rootScope.availableBalance = 1000; $scope = $rootScope;
var element = angular.element( $rootScope.availableBalance = 1000;
'<form name="form">' + var element = angular.element(
'<input type="number" id="amount" name="amount" placeholder="Amount" ng-model="amount" min="0.0001" max="10000000" enough-amount required>' + '<form name="form">' +
'</form>' '<input type="number" id="amount" name="amount" placeholder="Amount" ng-model="amount" min="0.0001" max="10000000" enough-amount required>' +
); '</form>'
$scope.model = { );
amount: null $scope.model = {
}; amount: null
$compile(element)($scope); };
$scope.$digest(); $compile(element)($scope);
form = $scope.form; $scope.$digest();
})); form = $scope.form;
}));
it('should validate', function() {
form.amount.$setViewValue(100);
expect(form.amount.$invalid).to.equal(false);
form.amount.$setViewValue(800);
expect(form.amount.$invalid).to.equal(false);
form.amount.$setViewValue(900);
expect($scope.notEnoughAmount).to.equal(null);
});
it('should not validate', function() {
form.amount.$setViewValue(0);
it('should validate', function() { expect(form.amount.$invalid).to.equal(true);
form.amount.$setViewValue(100); form.amount.$setViewValue(9999999999);
expect(form.amount.$invalid).to.equal(false); expect(form.amount.$invalid).to.equal(true);
form.amount.$setViewValue(900); form.amount.$setViewValue(901);
expect(form.amount.$invalid).to.equal(false); expect(form.amount.$invalid).to.equal(true);
form.amount.$setViewValue(1000);
expect(form.amount.$invalid).to.equal(true);
form.amount.$setViewValue(901);
expect($scope.notEnoughAmount).to.equal(true);
});
}); });
it('should not validate', function() { describe('Unit: BTC', function() {
form.amount.$setViewValue(0); beforeEach(inject(function($compile, $rootScope) {
expect(form.amount.$invalid).to.equal(true); config.unitToSatoshi = 100000000;
form.amount.$setViewValue(9999999999); config.unitName = 'BTC';
expect(form.amount.$invalid).to.equal(true); $scope = $rootScope;
form.amount.$setViewValue(901); $rootScope.availableBalance = 0.04;
expect(form.amount.$invalid).to.equal(true); var element = angular.element(
form.amount.$setViewValue(1000); '<form name="form">' +
expect(form.amount.$invalid).to.equal(true); '<input type="number" id="amount" name="amount" placeholder="Amount" ng-model="amount" min="0.0001" max="10000000" enough-amount required>' +
'</form>'
);
$scope.model = {
amount: null
};
$compile(element)($scope);
$scope.$digest();
form = $scope.form;
}));
it('should validate', function() {
form.amount.$setViewValue(0.01);
expect($scope.notEnoughAmount).to.equal(null);
expect(form.amount.$invalid).to.equal(false);
form.amount.$setViewValue(0.039);
expect($scope.notEnoughAmount).to.equal(null);
expect(form.amount.$invalid).to.equal(false);
});
it('should not validate', function() {
form.amount.$setViewValue(0.03999);
expect($scope.notEnoughAmount).to.equal(true);
expect(form.amount.$invalid).to.equal(true);
form.amount.$setViewValue(0);
expect(form.amount.$invalid).to.equal(true);
form.amount.$setViewValue(0.0);
expect(form.amount.$invalid).to.equal(true);
form.amount.$setViewValue(0.05);
expect($scope.notEnoughAmount).to.equal(true);
expect(form.amount.$invalid).to.equal(true);
});
}); });
}); });
describe('Contact directive', function() { describe('Contact directive', function() {

View File

@ -5,7 +5,13 @@
// //
var sinon = require('sinon'); var sinon = require('sinon');
beforeEach(function() {
config.unitToSatoshi = 100;
config.unitName = 'bits';
});
describe('Check config', function() { describe('Check config', function() {
it('unit should be set to BITS in config.js', function() { it('unit should be set to BITS in config.js', function() {
expect(config.unitToSatoshi).to.equal(100); expect(config.unitToSatoshi).to.equal(100);
expect(config.unitName).to.equal('bits'); expect(config.unitName).to.equal('bits');