/
transaction.test.js
134 lines (105 loc) · 3.82 KB
/
transaction.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
const Transaction = require('./transaction');
const Wallet = require('./index');
const { verifySignature } = require('../util');
describe('Transaction', () => {
let transaction, senderWallet, recipient, amount;
beforeEach(() => {
senderWallet = new Wallet();
recipient = 'recipient-public-key';
amount = 50;
transaction = new Transaction({ senderWallet, recipient, amount });
});
it('has an `id`', () => {
expect(transaction).toHaveProperty('id');
});
describe('outputMap', () => {
it('has an `outputMap`', () => {
expect(transaction).toHaveProperty('outputMap');
});
it('outputs the amount to the recipient', () => {
expect(transaction.outputMap[recipient]).toEqual(amount);
});
it('outputs the remaining balance for the `senderWallet`', () => {
expect(transaction.outputMap[senderWallet.publicKey])
.toEqual(senderWallet.balance - amount);
});
});
describe('input', () => {
it('has an `input`', () => {
expect(transaction).toHaveProperty('input');
});
it('has a `timestamp` in the input', () => {
});
it('sets the `amount` to the `senderWawllet` balance', () => {
expect(transaction.input.amount).toEqual(senderWallet.balance);
});
it('sets the `address` to the `senderWallet` publicKey', () => {
expect(transaction.input.address).toEqual(senderWallet.publicKey);
});
it('signs the input', () => {
expect(
verifySignature({
publicKey: senderWallet.publicKey,
data: transaction.outputMap,
signature: transaction.input.signature
})
).toBe(true);
});
});
describe('validTransaction', () => {
let errorMock;
beforeEach(() => {
errorMock = jest.fn();
global.console.error = errorMock;
});
describe('when the transaction is valid', () => {
it('returns true', () => {
expect(Transaction.validTransaction(transaction)).toBe(true);
});
});
describe('when the transaction is invalid', () => {
describe('and a transaction outputMap value is invalid', () => {
it('returns false and logs an error', () => {
transaction.outputMap[senderWallet.publicKey] = 999999;
expect(Transaction.validTransaction(transaction)).toBe(false);
expect(errorMock).toHaveBeenCalled();
});
});
describe('and a transaction input Signature is invalid', () => {
it('returns false and logs an error', () => {
transaction.input.signature = new Wallet().sign('data');
expect(Transaction.validTransaction(transaction)).toBe(false);
expect(errorMock).toHaveBeenCalled();
});
});
});
});
describe('update()', () => {
let originalSignature, originalSenderOutput, nextRecipient, nextAmount;
beforeEach(() => {
originalSignature = transaction.input.signature;
originalSenderOutput = transaction.outputMap[senderWallet.publicKey];
nextRecipient = 'next-recipient';
nextAmount = 50;
transaction.update({
senderWallet, recipient: nextRecipient, amount: nextAmount
});
});
it('outputs the amount to the next recipient', () => {
expect(transaction.outputMap[nextRecipient]).toEqual(nextAmount);
});
it('subtracts the amount from the original sender output amount', () => {
expect(transaction.outputMap[senderWallet.publicKey])
.toEqual(originalSenderOutput - nextAmount);
});
it('maintains a total output that matches the input amount', () => {
expect(
Object.values(transaction.outputMap)
.reduce((total, outputAmount) => total+outputAmount)
).toEqual(transaction.input.amount);
});
it('re-signs the transaction', () => {
expect(transaction.input.signature).not.toEqual(originalSignature);
});
});
});