Improved tests
This commit is contained in:
parent
70446c5ee7
commit
2c53bc073e
4 changed files with 281 additions and 142 deletions
|
|
@ -129,7 +129,7 @@ TxProposal.fromObj = function(o, forceOpts) {
|
||||||
forceOpts = forceOpts || {};
|
forceOpts = forceOpts || {};
|
||||||
|
|
||||||
|
|
||||||
if (forceOpts){
|
if (forceOpts) {
|
||||||
o.builderObj.opts = o.builderObj.opts || {};
|
o.builderObj.opts = o.builderObj.opts || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,6 +232,10 @@ TxProposal.prototype.mergeBuilder = function(incoming) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TxProposal.prototype.getSeen = function(copayerId) {
|
||||||
|
return this.seenBy[copayerId];
|
||||||
|
};
|
||||||
|
|
||||||
TxProposal.prototype.setSeen = function(copayerId) {
|
TxProposal.prototype.setSeen = function(copayerId) {
|
||||||
if (!this.seenBy[copayerId])
|
if (!this.seenBy[copayerId])
|
||||||
this.seenBy[copayerId] = Date.now();
|
this.seenBy[copayerId] = Date.now();
|
||||||
|
|
|
||||||
|
|
@ -341,7 +341,6 @@ Wallet.prototype._checkSentTx = function(ntxid, cb) {
|
||||||
|
|
||||||
this.blockchain.getTransaction(txid, function(err, tx) {
|
this.blockchain.getTransaction(txid, function(err, tx) {
|
||||||
if (err) return cb(false);
|
if (err) return cb(false);
|
||||||
txp.setSent(tx.txid);
|
|
||||||
cb(ret);
|
cb(ret);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -370,21 +369,26 @@ Wallet.prototype._onTxProposal = function(senderId, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m) {
|
if (m) {
|
||||||
if (m.hasChanged) {
|
if (!m.txp.getSeen(this.getMyCopayerId())) {
|
||||||
m.txp.setSeen(this.getMyCopayerId());
|
m.txp.setSeen(this.getMyCopayerId());
|
||||||
this.sendSeen(m.ntxid);
|
this.sendSeen(m.ntxid);
|
||||||
var tx = m.txp.builder.build();
|
}
|
||||||
if (tx.isComplete()) {
|
|
||||||
this._checkSentTx(m.ntxid, function(ret) {
|
var tx = m.txp.builder.build();
|
||||||
if (ret) {
|
if (tx.isComplete()) {
|
||||||
self.emit('txProposalsUpdated');
|
this._checkSentTx(m.ntxid, function(ret) {
|
||||||
self.store();
|
if (ret) {
|
||||||
}
|
m.txp.setSent(m.mtxid);
|
||||||
});
|
self.emit('txProposalsUpdated');
|
||||||
} else {
|
self.store();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (m.hasChanged) {
|
||||||
this.sendTxProposal(m.ntxid);
|
this.sendTxProposal(m.ntxid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('txProposalsUpdated');
|
this.emit('txProposalsUpdated');
|
||||||
this.store();
|
this.store();
|
||||||
}
|
}
|
||||||
|
|
@ -1125,9 +1129,8 @@ Wallet.prototype.getTxProposals = function() {
|
||||||
var txp = this.txProposals.getTxProposal(ntxid, copayers);
|
var txp = this.txProposals.getTxProposal(ntxid, copayers);
|
||||||
txp.signedByUs = txp.signedBy[this.getMyCopayerId()] ? true : false;
|
txp.signedByUs = txp.signedBy[this.getMyCopayerId()] ? true : false;
|
||||||
txp.rejectedByUs = txp.rejectedBy[this.getMyCopayerId()] ? true : false;
|
txp.rejectedByUs = txp.rejectedBy[this.getMyCopayerId()] ? true : false;
|
||||||
if (this.totalCopayers - txp.rejectCount < this.requiredCopayers) {
|
txp.finallyRejected = this.totalCopayers - txp.rejectCount < this.requiredCopayers;
|
||||||
txp.finallyRejected = true;
|
txp.isPending = !txp.finallyRejected && !txp.sentTxid;
|
||||||
}
|
|
||||||
|
|
||||||
if (!txp.readonly || txp.finallyRejected || txp.sentTs) {
|
if (!txp.readonly || txp.finallyRejected || txp.sentTs) {
|
||||||
ret.push(txp);
|
ret.push(txp);
|
||||||
|
|
@ -1423,9 +1426,7 @@ Wallet.prototype.receivePaymentRequest = function(options, pr, cb) {
|
||||||
expires: expires,
|
expires: expires,
|
||||||
memo: memo || 'This server would like some BTC from you.',
|
memo: memo || 'This server would like some BTC from you.',
|
||||||
payment_url: payment_url,
|
payment_url: payment_url,
|
||||||
merchant_data: merchant_data
|
merchant_data: merchant_data ? merchant_data.toString('hex') : null
|
||||||
? merchant_data.toString('hex')
|
|
||||||
: null
|
|
||||||
},
|
},
|
||||||
signature: sig.toString('hex'),
|
signature: sig.toString('hex'),
|
||||||
ca: trust.caName,
|
ca: trust.caName,
|
||||||
|
|
@ -2106,41 +2107,34 @@ Wallet.prototype.removeTxWithSpentInputs = function(cb) {
|
||||||
|
|
||||||
cb = cb || function() {};
|
cb = cb || function() {};
|
||||||
|
|
||||||
var txps = [];
|
var txps = _.where(this.getTxProposals(), {
|
||||||
var maxRejectCount = this.maxRejectCount();
|
isPending: true
|
||||||
for (var ntxid in this.txProposals.txps) {
|
});
|
||||||
var txp = this.txProposals.txps[ntxid];
|
var inputs = _.flatten(_.map(txps, function(txp) {
|
||||||
txp.ntxid = ntxid;
|
return _.map(txp.builder.utxos, function(utxo) {
|
||||||
if (txp.isPending(maxRejectCount)) {
|
return {
|
||||||
txps.push(txp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var inputs = [];
|
|
||||||
txps.forEach(function(txp) {
|
|
||||||
txp.builder.utxos.forEach(function(utxo) {
|
|
||||||
inputs.push({
|
|
||||||
ntxid: txp.ntxid,
|
ntxid: txp.ntxid,
|
||||||
txid: utxo.txid,
|
txid: utxo.txid,
|
||||||
vout: utxo.vout
|
vout: utxo.vout,
|
||||||
});
|
};
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
|
|
||||||
if (inputs.length === 0)
|
if (inputs.length === 0)
|
||||||
return;
|
return cb();
|
||||||
|
|
||||||
|
|
||||||
var proposalsChanged = false;
|
var proposalsChanged = false;
|
||||||
this.blockchain.getUnspent(this.getAddressesStr(), function(err, unspentList) {
|
this.blockchain.getUnspent(this.getAddressesStr(), function(err, unspentList) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
unspentList.forEach(function(unspent) {
|
_.each(unspentList, function(unspent) {
|
||||||
inputs.forEach(function(input) {
|
_.each(inputs, function(input) {
|
||||||
input.unspent = input.unspent || (input.txid === unspent.txid && input.vout === unspent.vout);
|
input.unspent = input.unspent || (input.txid === unspent.txid && input.vout === unspent.vout);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
inputs.forEach(function(input) {
|
_.each(inputs, function(input) {
|
||||||
if (!input.unspent) {
|
if (!input.unspent) {
|
||||||
proposalsChanged = true;
|
proposalsChanged = true;
|
||||||
self.txProposals.deleteOne(input.ntxid);
|
self.txProposals.deleteOne(input.ntxid);
|
||||||
|
|
@ -2152,7 +2146,7 @@ Wallet.prototype.removeTxWithSpentInputs = function(cb) {
|
||||||
self.store();
|
self.store();
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(null);
|
return cb();
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ angular.module('copayApp.services')
|
||||||
notification.info('Transaction Update', $filter('translate')('A transaction was rejected by') + ' ' + user);
|
notification.info('Transaction Update', $filter('translate')('A transaction was rejected by') + ' ' + user);
|
||||||
break;
|
break;
|
||||||
case 'corrupt':
|
case 'corrupt':
|
||||||
notification.error('Transaction Error', $filter('translate')('Received corrupt transaction from') + ' ' + user);
|
notification.error('Transaction Error', $filter('translate')('Received corrupt transaction from') + ' ' + user);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -177,8 +177,6 @@ angular.module('copayApp.services')
|
||||||
if (!w) return root.onErrorDigest();
|
if (!w) return root.onErrorDigest();
|
||||||
if (!w.isReady()) return;
|
if (!w.isReady()) return;
|
||||||
|
|
||||||
w.removeTxWithSpentInputs();
|
|
||||||
|
|
||||||
$rootScope.balanceByAddr = {};
|
$rootScope.balanceByAddr = {};
|
||||||
$rootScope.updatingBalance = true;
|
$rootScope.updatingBalance = true;
|
||||||
|
|
||||||
|
|
@ -232,12 +230,9 @@ angular.module('copayApp.services')
|
||||||
return txs.push(null);
|
return txs.push(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myCopayerId != i.creator && !i.finallyRejected && !i.sentTs && !i.rejectedByUs && !i.signedByUs) {
|
if (i.isPending && myCopayerId != i.creator && !i.rejectedByUs && !i.signedByUs) {
|
||||||
pendingForUs++;
|
pendingForUs++;
|
||||||
}
|
}
|
||||||
if (!i.finallyRejected && !i.sentTs) {
|
|
||||||
i.isPending = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!opts.pending == !!i.isPending) {
|
if (!!opts.pending == !!i.isPending) {
|
||||||
var tx = i.builder.build();
|
var tx = i.builder.build();
|
||||||
|
|
@ -262,6 +257,8 @@ angular.module('copayApp.services')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
w.removeTxWithSpentInputs();
|
||||||
|
|
||||||
$rootScope.txs = txs;
|
$rootScope.txs = txs;
|
||||||
$rootScope.txsOpts = opts;
|
$rootScope.txsOpts = opts;
|
||||||
if ($rootScope.pendingTxCount < pendingForUs) {
|
if ($rootScope.pendingTxCount < pendingForUs) {
|
||||||
|
|
|
||||||
|
|
@ -864,76 +864,76 @@ describe('Wallet model', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeTxWithSpentInputs', function() {
|
describe('removeTxWithSpentInputs', function() {
|
||||||
|
var w;
|
||||||
|
var utxos;
|
||||||
|
beforeEach(function() {
|
||||||
|
w = cachedCreateW2();
|
||||||
|
w.txProposals.deleteOne = sinon.spy();
|
||||||
|
utxos = [{
|
||||||
|
txid: 'txid0',
|
||||||
|
vout: 'vout1',
|
||||||
|
}, {
|
||||||
|
txid: 'txid0',
|
||||||
|
vout: 'vout2',
|
||||||
|
}];
|
||||||
|
});
|
||||||
it('should remove pending TxProposal with spent inputs', function(done) {
|
it('should remove pending TxProposal with spent inputs', function(done) {
|
||||||
var w = cachedCreateW2();
|
var txp = {
|
||||||
var utxo = createUTXO(w);
|
ntxid: 'txid1',
|
||||||
chai.expect(w.getTxProposals().length).to.equal(0);
|
isPending: true,
|
||||||
w.blockchain.fixUnspent(utxo);
|
builder: {
|
||||||
w.createTx(toAddress, amountSatStr, null, function(err, ntxid) {
|
utxos: [utxos[0]],
|
||||||
w.sendTxProposal(ntxid);
|
}
|
||||||
chai.expect(w.getTxProposals().length).to.equal(1);
|
};
|
||||||
|
w.getTxProposals = sinon.stub().returns([txp]);
|
||||||
// Inputs are still available, txp still valid
|
w.blockchain.getUnspent = sinon.stub().yields(null, utxos);
|
||||||
w.removeTxWithSpentInputs();
|
w.removeTxWithSpentInputs(function() {
|
||||||
chai.expect(w.getTxProposals().length).to.equal(1);
|
w.txProposals.deleteOne.called.should.be.false;
|
||||||
|
w.blockchain.getUnspent = sinon.stub().yields(null, []);
|
||||||
// Simulate input spent. txp should be removed from txps list
|
w.removeTxWithSpentInputs(function() {
|
||||||
w.blockchain.fixUnspent([]);
|
w.txProposals.deleteOne.calledWith('txid1').should.be.true;
|
||||||
w.removeTxWithSpentInputs();
|
done();
|
||||||
chai.expect(w.getTxProposals().length).to.equal(0);
|
});
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove pending TxProposal with at least 1 spent input', function(done) {
|
it('should remove pending TxProposal with at least 1 spent input', function(done) {
|
||||||
var w = cachedCreateW2();
|
var txp = {
|
||||||
var utxo = [createUTXO(w)[0], createUTXO(w)[0]];
|
ntxid: 'txid1',
|
||||||
utxo[0].amount = 80000;
|
isPending: true,
|
||||||
utxo[1].amount = 80000;
|
builder: {
|
||||||
utxo[1].vout = 1;
|
utxos: utxos,
|
||||||
chai.expect(w.getTxProposals().length).to.equal(0);
|
}
|
||||||
w.blockchain.fixUnspent(utxo);
|
};
|
||||||
w.createTx(toAddress, '100000', null, function(err, ntxid) {
|
w.getTxProposals = sinon.stub().returns([txp]);
|
||||||
w.sendTxProposal(ntxid);
|
w.blockchain.getUnspent = sinon.stub().yields(null, utxos);
|
||||||
chai.expect(w.getTxProposals().length).to.equal(1);
|
w.removeTxWithSpentInputs(function() {
|
||||||
|
w.txProposals.deleteOne.called.should.be.false;
|
||||||
// Inputs are still available, txp still valid
|
w.blockchain.getUnspent = sinon.stub().yields(null, [utxos[0]]);
|
||||||
w.removeTxWithSpentInputs();
|
w.removeTxWithSpentInputs(function() {
|
||||||
chai.expect(w.getTxProposals().length).to.equal(1);
|
w.txProposals.deleteOne.calledWith('txid1').should.be.true;
|
||||||
|
done();
|
||||||
// Simulate 1 input spent. txp should be removed from txps list
|
});
|
||||||
w.blockchain.fixUnspent([utxo[0]]);
|
|
||||||
w.removeTxWithSpentInputs();
|
|
||||||
chai.expect(w.getTxProposals().length).to.equal(0);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not remove complete TxProposal', function(done) {
|
it('should not remove complete TxProposal', function(done) {
|
||||||
var w = cachedCreateW2();
|
var txp = {
|
||||||
var utxo = createUTXO(w);
|
ntxid: 'txid1',
|
||||||
chai.expect(w.getTxProposals().length).to.equal(0);
|
isPending: false,
|
||||||
w.blockchain.fixUnspent(utxo);
|
builder: {
|
||||||
w.createTx(toAddress, amountSatStr, null, function(err, ntxid) {
|
utxos: [utxos[0]],
|
||||||
w.sendTxProposal(ntxid);
|
}
|
||||||
chai.expect(w.getTxProposals().length).to.equal(1);
|
};
|
||||||
|
w.getTxProposals = sinon.stub().returns([txp]);
|
||||||
// Inputs are still available, txp still valid
|
w.blockchain.getUnspent = sinon.stub().yields(null, utxos);
|
||||||
w.removeTxWithSpentInputs();
|
w.removeTxWithSpentInputs(function() {
|
||||||
chai.expect(w.getTxProposals().length).to.equal(1);
|
w.txProposals.deleteOne.called.should.be.false;
|
||||||
|
w.blockchain.getUnspent = sinon.stub().yields(null, []);
|
||||||
// Simulate input spent. txp should be removed from txps list
|
w.removeTxWithSpentInputs(function() {
|
||||||
w.blockchain.fixUnspent([]);
|
w.txProposals.deleteOne.called.should.be.false;
|
||||||
var txp = w.txProposals.get(ntxid);
|
done();
|
||||||
sinon.stub(txp, 'isPending', function() {
|
});
|
||||||
return false;
|
|
||||||
})
|
|
||||||
w.removeTxWithSpentInputs();
|
|
||||||
chai.expect(w.getTxProposals().length).to.equal(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -1425,60 +1425,204 @@ describe('Wallet model', function() {
|
||||||
|
|
||||||
|
|
||||||
describe('_onTxProposal', function() {
|
describe('_onTxProposal', function() {
|
||||||
var testValidate = function(response, result, done) {
|
var w;
|
||||||
|
beforeEach(function() {
|
||||||
|
w = cachedCreateW();
|
||||||
|
w._getKeyMap = sinon.stub();
|
||||||
|
w.sendSeen = sinon.spy();
|
||||||
|
w.sendTxProposal = sinon.spy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle corrupt tx', function(done) {
|
||||||
|
var data = {
|
||||||
|
txProposal: {
|
||||||
|
dummy: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
w.txProposals.merge = sinon.stub().throws(new Error('test error'));
|
||||||
|
|
||||||
var w = cachedCreateW();
|
|
||||||
var spy = sinon.spy();
|
var spy = sinon.spy();
|
||||||
w.on('txProposalEvent', spy);
|
w.on('txProposalEvent', spy);
|
||||||
w.on('txProposalEvent', function(e) {
|
w.on('txProposalEvent', function(e) {
|
||||||
e.type.should.equal(result);
|
e.type.should.equal('corrupt');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
// txp.prototype.getId = function() {return 'aa'};
|
|
||||||
var txp = {
|
|
||||||
dummy: 1
|
|
||||||
};
|
|
||||||
var txp = {
|
|
||||||
'txProposal': txp
|
|
||||||
};
|
|
||||||
|
|
||||||
var s1 = sinon.stub(w, '_getKeyMap', function() {
|
w._onTxProposal('senderID', data);
|
||||||
return {
|
spy.called.should.be.true;
|
||||||
1: 2
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
var s2 = sinon.stub(w.txProposals, 'merge', function() {
|
|
||||||
if (response == 0)
|
|
||||||
throw new Error('test error');
|
|
||||||
|
|
||||||
return {
|
|
||||||
ntxid: 1,
|
|
||||||
txp: {
|
|
||||||
setCopayers: function() {
|
|
||||||
return ['oeoe'];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
new: response == 1
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
w._onTxProposal('senderID', txp);
|
|
||||||
spy.callCount.should.equal(1);
|
|
||||||
s1.restore();
|
|
||||||
s2.restore();
|
|
||||||
};
|
|
||||||
|
|
||||||
it('should handle corrupt', function(done) {
|
|
||||||
testValidate(0, 'corrupt', done);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle new', function(done) {
|
it('should handle new', function(done) {
|
||||||
testValidate(1, 'new', done);
|
var data = {
|
||||||
});
|
txProposal: {
|
||||||
it('should handle signed', function(done) {
|
dummy: 1,
|
||||||
testValidate(2, 'signed', done);
|
},
|
||||||
|
};
|
||||||
|
var txp = {
|
||||||
|
getSeen: sinon.stub().returns(false),
|
||||||
|
setSeen: sinon.spy(),
|
||||||
|
setCopayers: sinon.spy(),
|
||||||
|
builder: {
|
||||||
|
build: sinon.stub().returns({
|
||||||
|
isComplete: sinon.stub().returns(false),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
w.txProposals.merge = sinon.stub().returns({
|
||||||
|
ntxid: 1,
|
||||||
|
txp: txp,
|
||||||
|
new: true,
|
||||||
|
hasChanged: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
var spy1 = sinon.spy();
|
||||||
|
var spy2 = sinon.spy();
|
||||||
|
w.on('txProposalEvent', spy1);
|
||||||
|
w.on('txProposalsUpdated', spy2);
|
||||||
|
w.on('txProposalEvent', function(e) {
|
||||||
|
e.type.should.equal('new');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
w._onTxProposal('senderID', data);
|
||||||
|
spy1.called.should.be.true;
|
||||||
|
spy2.called.should.be.true;
|
||||||
|
txp.setSeen.calledOnce.should.be.true;
|
||||||
|
w.sendSeen.calledOnce.should.be.true;
|
||||||
|
w.sendTxProposal.calledOnce.should.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle signed', function(done) {
|
||||||
|
var data = {
|
||||||
|
txProposal: {
|
||||||
|
dummy: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var txp = {
|
||||||
|
getSeen: sinon.stub().returns(true),
|
||||||
|
setSeen: sinon.spy(),
|
||||||
|
setCopayers: sinon.stub().returns(['new copayer']),
|
||||||
|
builder: {
|
||||||
|
build: sinon.stub().returns({
|
||||||
|
isComplete: sinon.stub().returns(false),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
w.txProposals.merge = sinon.stub().returns({
|
||||||
|
ntxid: 1,
|
||||||
|
txp: txp,
|
||||||
|
new: false,
|
||||||
|
hasChanged: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
var spy1 = sinon.spy();
|
||||||
|
var spy2 = sinon.spy();
|
||||||
|
w.on('txProposalEvent', spy1);
|
||||||
|
w.on('txProposalsUpdated', spy2);
|
||||||
|
w.on('txProposalEvent', function(e) {
|
||||||
|
e.type.should.equal('signed');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
w._onTxProposal('senderID', data);
|
||||||
|
spy1.called.should.be.true;
|
||||||
|
spy2.called.should.be.true;
|
||||||
|
txp.setSeen.calledOnce.should.be.false;
|
||||||
|
w.sendSeen.calledOnce.should.be.false;
|
||||||
|
w.sendTxProposal.calledOnce.should.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mark as broadcast when complete', function(done) {
|
||||||
|
var data = {
|
||||||
|
txProposal: {
|
||||||
|
dummy: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var txp = {
|
||||||
|
getSeen: sinon.stub().returns(true),
|
||||||
|
setCopayers: sinon.stub().returns(['new copayer']),
|
||||||
|
setSent: sinon.spy(),
|
||||||
|
builder: {
|
||||||
|
build: sinon.stub().returns({
|
||||||
|
isComplete: sinon.stub().returns(true),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
w.txProposals.merge = sinon.stub().returns({
|
||||||
|
ntxid: 1,
|
||||||
|
txp: txp,
|
||||||
|
new: false,
|
||||||
|
hasChanged: true,
|
||||||
|
});
|
||||||
|
w._checkSentTx = sinon.stub().yields(true);
|
||||||
|
|
||||||
|
w._onTxProposal('senderID', data);
|
||||||
|
txp.setSent.calledOnce.should.be.true;
|
||||||
|
w.sendTxProposal.called.should.be.false;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only mark as broadcast if found in the blockchain', function(done) {
|
||||||
|
var data = {
|
||||||
|
txProposal: {
|
||||||
|
dummy: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var txp = {
|
||||||
|
getSeen: sinon.stub().returns(true),
|
||||||
|
setCopayers: sinon.stub().returns(['new copayer']),
|
||||||
|
setSent: sinon.spy(),
|
||||||
|
builder: {
|
||||||
|
build: sinon.stub().returns({
|
||||||
|
isComplete: sinon.stub().returns(true),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
w.txProposals.merge = sinon.stub().returns({
|
||||||
|
ntxid: 1,
|
||||||
|
txp: txp,
|
||||||
|
new: false,
|
||||||
|
hasChanged: true,
|
||||||
|
});
|
||||||
|
w._checkSentTx = sinon.stub().yields(false);
|
||||||
|
|
||||||
|
w._onTxProposal('senderID', data);
|
||||||
|
txp.setSent.called.should.be.false;
|
||||||
|
w.sendTxProposal.called.should.be.false;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should resend when not complete only if changed', function(done) {
|
||||||
|
var data = {
|
||||||
|
txProposal: {
|
||||||
|
dummy: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var txp = {
|
||||||
|
getSeen: sinon.stub().returns(true),
|
||||||
|
setCopayers: sinon.stub().returns(['new copayer']),
|
||||||
|
builder: {
|
||||||
|
build: sinon.stub().returns({
|
||||||
|
isComplete: sinon.stub().returns(false),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
w.txProposals.merge = sinon.stub().returns({
|
||||||
|
ntxid: 1,
|
||||||
|
txp: txp,
|
||||||
|
new: false,
|
||||||
|
hasChanged: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
w._onTxProposal('senderID', data);
|
||||||
|
w.sendTxProposal.called.should.be.false;
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue