-
Notifications
You must be signed in to change notification settings - Fork 1
/
AvailableStocks.container.test.ts
128 lines (97 loc) · 4.81 KB
/
AvailableStocks.container.test.ts
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
import { AvailableStock } from '../src/business/state/AvailableStock';
import { inject } from '../src/inject';
import { viewModel } from '../src/ui/cashBalanceAndPortfolio/AvailableStock.container';
import { Portfolio } from '../src/business/state/Portfolio';
import { CashBalance } from '../src/business/state/CashBalance';
import { UseSet } from '../src/business/state/Hooks';
describe('AvailableStockContainer', () => {
let portfolio: Portfolio;
let setPortfolio: UseSet<Portfolio> = (value: Portfolio | ((prevState: Portfolio) => Portfolio)) => {
if (typeof value === 'function') {
portfolio = value(portfolio);
} else {
portfolio = value;
}
};
beforeEach(() => {
inject({});
portfolio = new Portfolio();
});
it('enables buy button when there is enough money to buy the stock.' +
'It disables otherwise.', () => {
const ibm = new AvailableStock('IBM', 'I. B. Machines', 150.00);
// The BUY button is disabled, since we cannot buy stock when there is no money.
let vm = viewModel(ibm, portfolio, setPortfolio);
expect(vm.ifBuyDisabled).toBe(true);
// The BUY button is disabled, since we cannot buy stock that costs 150, when there is only 100.
portfolio = portfolio.withCashBalance(new CashBalance(100));
vm = viewModel(ibm, portfolio, setPortfolio);
expect(vm.ifBuyDisabled).toBe(true);
// The BUY button is enabled, as we can buy stock that costs 150 when there is exactly 150.
portfolio = portfolio.withCashBalance(new CashBalance(150));
vm = viewModel(ibm, portfolio, setPortfolio);
expect(vm.ifBuyDisabled).toBe(false);
// The BUY button is enabled, as we can buy stock that costs 150 when there is more than 150.
portfolio = portfolio.withCashBalance(new CashBalance(1000));
vm = viewModel(ibm, portfolio, setPortfolio);
expect(vm.ifBuyDisabled).toBe(false);
});
it('enables sell button when there at least 1 stock.' +
'It disables otherwise.', () => {
const ibm = new AvailableStock('IBM', 'I. B. Machines', 150.00);
const aapl = new AvailableStock('AAPL', 'Apple Inc.', 150.00);
portfolio = portfolio.withoutStocks();
let vm = viewModel(ibm, portfolio, setPortfolio);
expect(vm.ifSellDisabled).toBe(true);
// Cannot sell IBM, when there are only AAPL stocks.
portfolio = portfolio.withAddedStock(aapl, 1);
vm = viewModel(ibm, portfolio, setPortfolio);
expect(vm.ifSellDisabled).toBe(true);
// Can sell IBM, when there are IBM stocks.
portfolio = portfolio.withAddedStock(ibm, 1);
vm = viewModel(ibm, portfolio, setPortfolio);
expect(vm.ifSellDisabled).toBe(false);
});
test('Buying stock.', () => {
const ibm = new AvailableStock('IBM', 'I. B. Machines', 150.00);
// Cash balance is 1000. There are no IBM stocks.
expect(portfolio.howManyStocks(ibm.ticker)).toBe(0);
portfolio = portfolio.withCashBalance(new CashBalance(1000));
const vm = viewModel(ibm, portfolio, setPortfolio);
vm.onBuy(); // Buy 1 share of IBM stock.
// Cash balance decreased by the price of 1 IBM stock. Portfolio now contains 1 IBM stock.
expect(portfolio.cashBalance.amount).toBe(1000 - ibm.currentPrice);
expect(portfolio.howManyStocks(ibm.ticker)).toBe(1);
});
test('Buying stock without enough money. ' +
'Note: In practice this error never happens, because the BUY button is disabled.', () => {
// Set initial cash balance to 100, which is less than the price of IBM stock.
portfolio = portfolio.withCashBalance(new CashBalance(100));
const ibm = new AvailableStock('IBM', 'I. B. Machines', 150.00);
// Try to buy 1 share of IBM stock.
const vm = viewModel(ibm, portfolio, setPortfolio);
// Assert that an error is thrown.
expect(() => vm.onBuy()).toThrow('Not enough money to buy stock');
});
test('Selling stock.', () => {
const ibm = new AvailableStock('IBM', 'I. B. Machines', 150.00);
// Add 2 shares of IBM stock to the portfolio.
portfolio = portfolio.withAddedStock(ibm, 2);
// Sell 1 share of IBM stock.
const vm = viewModel(ibm, portfolio, setPortfolio);
vm.onSell();
// Cash balance has increased by the price of 1 IBM stock.
expect(portfolio.cashBalance.amount).toBe(ibm.currentPrice);
// The portfolio now contains 1 IBM stock.
expect(portfolio.howManyStocks(ibm.ticker)).toBe(1);
});
test('Selling stock that is not in the portfolio. ' +
'Note: In practice this error never happens, because the SELL button is disabled.', () => {
const ibm = new AvailableStock('IBM', 'I. B. Machines', 150.00);
// Ensure the portfolio does not contain IBM stock.
portfolio = portfolio.withoutStock(ibm.ticker);
// Try to sell 1 share of IBM stock.
const vm = viewModel(ibm, portfolio, setPortfolio);
expect(() => vm.onSell()).toThrow('Cannot sell stock you do not own');
});
});