Browse Source

improved testing of tx history pagination

activeAddress
Ivan Socolsky 10 years ago
parent
commit
ffe05c7fc7
  1. 73
      lib/server.js
  2. 92
      test/integration/server.js

73
lib/server.js

@ -926,6 +926,10 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
var self = this; var self = this;
function decorate(txs, addresses, proposals) { function decorate(txs, addresses, proposals) {
var indexedAddresses = _.indexBy(addresses, 'address');
var indexedProposals = _.indexBy(proposals, 'txid');
function sum(items, isMine, isChange) { function sum(items, isMine, isChange) {
var filter = {}; var filter = {};
if (_.isBoolean(isMine)) filter.isMine = isMine; if (_.isBoolean(isMine)) filter.isMine = isMine;
@ -936,48 +940,64 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
}, 0); }, 0);
}; };
var indexedAddresses = _.indexBy(addresses, 'address'); function classify(items) {
var indexedProposals = _.indexBy(proposals, 'txid'); return _.map(items, function(item) {
_.each(txs, function(tx) {
_.each(tx.inputs.concat(tx.outputs), function(item) {
var address = indexedAddresses[item.address]; var address = indexedAddresses[item.address];
item.isMine = !!address; return {
item.isChange = address ? address.isChange : false; address: item.address,
amount: item.amount,
isMine: !!address,
isChange: address ? address.isChange : false,
}
}); });
};
var amountIn = sum(tx.inputs, true); return _.map(txs, function(tx) {
var amountOut = sum(tx.outputs, true, false); var inputs = classify(tx.inputs);
var amountOutChange = sum(tx.outputs, true, true); var outputs = classify(tx.outputs);
var amount;
var amountIn = sum(inputs, true);
var amountOut = sum(outputs, true, false);
var amountOutChange = sum(outputs, true, true);
var amount, action, addressTo;
if (amountIn == (amountOut + amountOutChange + (amountIn > 0 ? tx.fees : 0))) { if (amountIn == (amountOut + amountOutChange + (amountIn > 0 ? tx.fees : 0))) {
tx.action = 'moved';
amount = amountOut; amount = amountOut;
action = 'moved';
} else { } else {
amount = amountIn - amountOut - amountOutChange - (amountIn > 0 ? tx.fees : 0); amount = amountIn - amountOut - amountOutChange - (amountIn > 0 ? tx.fees : 0);
tx.action = amount > 0 ? 'sent' : 'received'; action = amount > 0 ? 'sent' : 'received';
} }
tx.amount = Math.abs(amount); amount = Math.abs(amount);
if (tx.action == 'sent' || tx.action == 'moved') { if (action == 'sent' || action == 'moved') {
tx.addressTo = tx.outputs[0].address; addressTo = outputs[0].address;
}; };
delete tx.inputs; var newTx = {
delete tx.outputs; txid: tx.txid,
action: action,
amount: amount,
fees: tx.fees,
time: tx.time,
addressTo: addressTo,
confirmations: tx.confirmations,
};
var proposal = indexedProposals[tx.txid]; var proposal = indexedProposals[tx.txid];
if (proposal) { if (proposal) {
tx.proposalId = proposal.id; newTx.proposalId = proposal.id;
tx.creatorName = proposal.creatorName; newTx.creatorName = proposal.creatorName;
tx.message = proposal.message; newTx.message = proposal.message;
tx.actions = _.map(proposal.actions, function(action) { newTx.actions = _.map(proposal.actions, function(action) {
return _.pick(action, ['createdOn', 'type', 'copayerId', 'copayerName', 'comment']); return _.pick(action, ['createdOn', 'type', 'copayerId', 'copayerName', 'comment']);
}); });
// tx.sentTs = proposal.sentTs; // newTx.sentTs = proposal.sentTs;
// tx.merchant = proposal.merchant; // newTx.merchant = proposal.merchant;
//tx.paymentAckMemo = proposal.paymentAckMemo; //newTx.paymentAckMemo = proposal.paymentAckMemo;
} }
return newTx;
}); });
}; };
@ -1024,8 +1044,7 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
var proposals = res[0]; var proposals = res[0];
var txs = res[1]; var txs = res[1];
decorate(txs, addresses, proposals); txs = paginate(decorate(txs, addresses, proposals));
txs = paginate(txs);
return cb(null, txs); return cb(null, txs);
}); });

92
test/integration/server.js

@ -2345,54 +2345,66 @@ describe('Copay server', function() {
}); });
}); });
}); });
describe('Pagination', function() { it('should get various paginated tx history', function(done) {
beforeEach(function() { var testCases = [{
server._normalizeTxHistory = sinon.stub().returnsArg(0); opts: {
var timestamps = [10, 50, 30, 40, 20];
var txs = _.map(timestamps, function(ts, idx) {
return {
txid: (idx + 1).toString(),
confirmations: ts / 10,
fees: 100,
time: ts,
inputs: [{
address: 'external',
amount: 500,
}],
outputs: [{
address: mainAddresses[0].address,
amount: 200,
}],
};
});
helpers.stubHistory(txs);
});
it('should get paginated tx history', function(done) {
server.getTxHistory({
minTs: 15, minTs: 15,
maxTs: 45, maxTs: 45,
}, function(err, txs) { },
should.not.exist(err); expected: [20, 30, 40],
should.exist(txs); }, {
txs.length.should.equal(3); opts: {
_.pluck(txs, 'time').should.deep.equal([20, 30, 40]);
done();
});
});
it('should get paginated tx history with limit', function(done) {
server.getTxHistory({
minTs: 15, minTs: 15,
maxTs: 45, maxTs: 45,
limit: 2, limit: 2,
}, function(err, txs) { },
expected: [20, 30],
}, {
opts: {
maxTs: 35,
},
expected: [10, 20, 30],
}, {
opts: {
minTs: 15,
},
expected: [20, 30, 40, 50],
}, {
opts: {
minTs: 15,
limit: 3,
},
expected: [20, 30, 40],
}];
server._normalizeTxHistory = sinon.stub().returnsArg(0);
var timestamps = [10, 50, 30, 40, 20];
var txs = _.map(timestamps, function(ts, idx) {
return {
txid: (idx + 1).toString(),
confirmations: ts / 10,
fees: 100,
time: ts,
inputs: [{
address: 'external',
amount: 500,
}],
outputs: [{
address: mainAddresses[0].address,
amount: 200,
}],
};
});
helpers.stubHistory(txs);
async.each(testCases, function(testCase, next) {
server.getTxHistory(testCase.opts, function(err, txs) {
should.not.exist(err); should.not.exist(err);
should.exist(txs); should.exist(txs);
txs.length.should.equal(2); _.pluck(txs, 'time').should.deep.equal(testCase.expected);
_.pluck(txs, 'time').should.deep.equal([20, 30]); next();
done();
}); });
}); }, done);
}); });
}); });
}); });

Loading…
Cancel
Save