/
vending_machine_spec.rb
234 lines (232 loc) · 6.43 KB
/
vending_machine_spec.rb
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe VendingMachine do
def insert amount_of_money
(amount_of_money / 10).times { machine.insert 10 }
end
def purchase_cola(amount = 1)
amount.times do
insert 120
machine.purchase :cola
end
end
let(:machine) { VendingMachine.new }
describe "initial state" do
subject { machine }
its(:total) { should eq 0 }
its(:sale_amount) { should eq 0 }
its(:purchasable_drink_names) { should be_empty }
it 'has 5 cola by default' do
expect(machine.stock_info[:cola][:stock]).to eq 5
end
it 'cannot purchase cola' do
expect(machine.purchasable? :cola).to be_false
end
end
describe "#insert" do
context 'when available money' do
shared_examples_for 'available money' do
it 'does not return money' do
expect(machine.insert money).to be_nil
end
it 'can insert more than once' do
2.times { expect(machine.insert money).to be_nil }
end
it 'increments total' do
expect{machine.insert money}.to change{machine.total}.from(0).to(money)
end
end
it_should_behave_like 'available money' do
let(:money) { 10 }
end
it_should_behave_like 'available money' do
let(:money) { 50 }
end
it_should_behave_like 'available money' do
let(:money) { 100 }
end
it_should_behave_like 'available money' do
let(:money) { 500 }
end
it_should_behave_like 'available money' do
let(:money) { 1000 }
end
end
context 'when unavailable money' do
shared_examples_for 'unavailable money' do
it 'returns money' do
expect(machine.insert money).to eq money
end
it 'does not increment total' do
expect{machine.insert money}.not_to change{machine.total}.from(0)
end
end
it_should_behave_like 'unavailable money' do
let(:money) { 1 }
end
it_should_behave_like 'unavailable money' do
let(:money) { 5 }
end
it_should_behave_like 'unavailable money' do
let(:money) { 2000 }
end
it_should_behave_like 'unavailable money' do
let(:money) { 5000 }
end
it_should_behave_like 'unavailable money' do
let(:money) { 10000 }
end
end
end
describe '#total' do
subject { machine.total }
before do
machine.insert 10
machine.insert 50
end
it { should eq 60 }
end
describe '#refund' do
before do
insert 120
end
it 'returns change' do
expect(machine.refund).to eq 120
end
it 'has no change after refund' do
expect{machine.refund}.to change{machine.total}.from(120).to(0)
end
end
describe '#stock_info' do
before do
machine.store Drink.cola
machine.store Drink.redbull
end
it 'has info for each drink' do
expect(machine.stock_info).to have(2).items
end
it 'returns price and stock for each drink' do
expect(machine.stock_info[:cola]).to include(price: 120, stock: 6)
expect(machine.stock_info[:redbull]).to include(price: 200, stock: 1)
end
end
describe '#purchasable?' do
subject { machine.purchasable? :cola }
context 'when stock and money are enough' do
before do
insert 120
end
it { should be_true }
end
context 'when money is not enough' do
before do
insert 110
end
it { should be_false }
end
context 'when no stock' do
before do
purchase_cola 5
insert 120
end
it { should be_false }
end
end
describe '#purchasable_drink_names' do
subject { machine.purchasable_drink_names }
before do
machine.store Drink.redbull
machine.store Drink.water
end
context 'when all drinks are purchasable' do
before do
insert 200
end
it { should have(3).items }
it { should include(:cola, :redbull, :water) }
end
context 'when not enough money for redbull' do
before do
insert 190
end
it { should have(2).items }
it { should include(:cola, :water) }
end
context 'when no stock for cola' do
before do
purchase_cola 5
insert 200
end
it { should have(2).items }
it { should include(:redbull, :water) }
end
end
describe '#purchase' do
context 'when purchasable' do
before do
insert 500
end
it 'returns drink and change' do
expect(machine.purchase :cola).to eq [Drink.cola, 500 - 120]
end
it 'has no change after purchase' do
expect{machine.purchase :cola}.to change{machine.total}.from(500).to(0)
end
it 'increases sale_amount' do
expect{machine.purchase :cola}.to change{machine.sale_amount}.from(0).to(120)
end
it 'reduces stock' do
expect{machine.purchase :cola}.to change{machine.stock_info[:cola][:stock]}.from(5).to(4)
end
end
context 'when not purchasable' do
before do
insert 110
end
it 'returns nil' do
expect(machine.purchase :cola).to be_nil
end
it 'keeps change' do
expect{machine.purchase :cola}.not_to change{machine.total}.from(110)
end
it 'does not increase sale_amount' do
expect{machine.purchase :cola}.not_to change{machine.sale_amount}.from(0)
end
it 'does not reduce stock' do
expect{machine.purchase :cola}.not_to change{machine.stock_info[:cola][:stock]}.from(5)
end
end
end
describe '#sale_amount' do
subject { machine.sale_amount }
before do
insert 200
machine.purchase :cola
machine.store Drink.redbull
insert 200
machine.purchase :redbull
end
it { should eq (120 + 200) }
end
describe '#store' do
it 'returns nil' do
expect(machine.store Drink.redbull).to be_nil
end
context 'when store new drink' do
it 'adds new stock_info' do
expect{machine.store Drink.water}.to change{machine.stock_info[:water]}.from(nil)
end
it 'increments stock' do
machine.store Drink.water
expect(machine.stock_info[:water][:stock]).to eq 1
end
end
context 'when store more' do
before do
machine.store Drink.water
end
it 'increments stock' do
expect{machine.store Drink.water}.to change{machine.stock_info[:water][:stock]}.from(1).to(2)
end
end
end
end