money 3.6.1 → 3.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +335 -319
- data/LICENSE +21 -21
- data/README.md +214 -209
- data/Rakefile +49 -49
- data/lib/money.rb +27 -27
- data/lib/money/bank/base.rb +131 -131
- data/lib/money/bank/variable_exchange.rb +252 -251
- data/lib/money/core_extensions.rb +82 -63
- data/lib/money/currency.rb +422 -415
- data/lib/money/money.rb +387 -1210
- data/lib/money/money/arithmetic.rb +246 -0
- data/lib/money/money/formatting.rb +234 -0
- data/lib/money/money/parsing.rb +350 -0
- data/money.gemspec +34 -27
- data/spec/bank/base_spec.rb +72 -72
- data/spec/bank/variable_exchange_spec.rb +238 -238
- data/spec/core_extensions_spec.rb +158 -142
- data/spec/currency_spec.rb +133 -128
- data/spec/money/arithmetic_spec.rb +479 -0
- data/spec/money/formatting_spec.rb +352 -0
- data/spec/money/parsing_spec.rb +197 -0
- data/spec/money_spec.rb +271 -1268
- data/spec/spec_helper.rb +28 -17
- metadata +33 -23
- data/lib/money.rbc +0 -170
- data/lib/money/bank/base.rbc +0 -800
- data/lib/money/bank/variable_exchange.rbc +0 -2496
- data/lib/money/core_extensions.rbc +0 -474
- data/lib/money/currency.rbc +0 -22600
- data/lib/money/money.rbc +0 -10070
- data/spec/bank/base_spec.rbc +0 -2409
- data/spec/bank/variable_exchange_spec.rbc +0 -7389
- data/spec/core_extensions_spec.rbc +0 -5215
- data/spec/currency_spec.rbc +0 -4341
- data/spec/money_spec.rbc +0 -50121
- data/spec/spec_helper.rbc +0 -346
@@ -0,0 +1,479 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Money do
|
6
|
+
specify "#zero? returns whether the amount is 0" do
|
7
|
+
Money.new(0, "USD").should be_zero
|
8
|
+
Money.new(0, "EUR").should be_zero
|
9
|
+
Money.new(1, "USD").should_not be_zero
|
10
|
+
Money.new(10, "YEN").should_not be_zero
|
11
|
+
Money.new(-1, "EUR").should_not be_zero
|
12
|
+
end
|
13
|
+
|
14
|
+
specify "#nonzero? returns whether the amount is not 0" do
|
15
|
+
Money.new(0, "USD").should_not be_nonzero
|
16
|
+
Money.new(0, "EUR").should_not be_nonzero
|
17
|
+
Money.new(1, "USD").should be_nonzero
|
18
|
+
Money.new(10, "YEN").should be_nonzero
|
19
|
+
Money.new(-1, "EUR").should be_nonzero
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "#nonzero? has the same return-value semantics as Numeric#nonzero?" do
|
23
|
+
Money.new(0, "USD").nonzero?.should be_nil
|
24
|
+
|
25
|
+
money = Money.new(1, "USD")
|
26
|
+
money.nonzero?.should be_equal(money)
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "#== returns true if and only if their amount and currency are equal" do
|
30
|
+
Money.new(1_00, "USD").should == Money.new(1_00, "USD")
|
31
|
+
Money.new(1_00, "USD").should_not == Money.new(1_00, "EUR")
|
32
|
+
Money.new(1_00, "USD").should_not == Money.new(2_00, "USD")
|
33
|
+
Money.new(1_00, "USD").should_not == Money.new(99_00, "EUR")
|
34
|
+
end
|
35
|
+
|
36
|
+
specify "#== can be used to compare with a String money value" do
|
37
|
+
Money.new(1_00, "USD").should == "1.00"
|
38
|
+
Money.new(1_00, "USD").should_not == "2.00"
|
39
|
+
Money.new(1_00, "GBP").should_not == "1.00"
|
40
|
+
end
|
41
|
+
|
42
|
+
specify "#== can be used to compare with a Numeric money value" do
|
43
|
+
Money.new(1_00, "USD").should == 1
|
44
|
+
Money.new(1_57, "USD").should == 1.57
|
45
|
+
Money.new(1_00, "USD").should_not == 2
|
46
|
+
Money.new(1_00, "GBP").should_not == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
specify "#== can be used to compare with an object that responds to #to_money" do
|
50
|
+
klass = Class.new do
|
51
|
+
def initialize(money)
|
52
|
+
@money = money
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_money
|
56
|
+
@money
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
Money.new(1_00, "USD").should == klass.new(Money.new(1_00, "USD"))
|
61
|
+
Money.new(2_50, "USD").should == klass.new(Money.new(2_50, "USD"))
|
62
|
+
Money.new(2_50, "USD").should_not == klass.new(Money.new(3_00, "USD"))
|
63
|
+
Money.new(1_00, "GBP").should_not == klass.new(Money.new(1_00, "USD"))
|
64
|
+
end
|
65
|
+
|
66
|
+
specify "#== returns false if used to compare with an object that doesn't respond to #to_money" do
|
67
|
+
Money.new(1_00, "USD").should_not == Object.new
|
68
|
+
Money.new(1_00, "USD").should_not == Class
|
69
|
+
Money.new(1_00, "USD").should_not == Kernel
|
70
|
+
Money.new(1_00, "USD").should_not == /foo/
|
71
|
+
Money.new(1_00, "USD").should_not == nil
|
72
|
+
end
|
73
|
+
|
74
|
+
specify "#eql? returns true if and only if their amount and currency are equal" do
|
75
|
+
Money.new(1_00, "USD").eql?(Money.new(1_00, "USD")).should be true
|
76
|
+
Money.new(1_00, "USD").eql?(Money.new(1_00, "EUR")).should be false
|
77
|
+
Money.new(1_00, "USD").eql?(Money.new(2_00, "USD")).should be false
|
78
|
+
Money.new(1_00, "USD").eql?(Money.new(99_00, "EUR")).should be false
|
79
|
+
end
|
80
|
+
|
81
|
+
specify "#eql? can be used to compare with a String money value" do
|
82
|
+
Money.new(1_00, "USD").eql?("1.00").should be true
|
83
|
+
Money.new(1_00, "USD").eql?("2.00").should be false
|
84
|
+
Money.new(1_00, "GBP").eql?("1.00").should be false
|
85
|
+
end
|
86
|
+
|
87
|
+
specify "#eql? can be used to compare with a Numeric money value" do
|
88
|
+
Money.new(1_00, "USD").eql?(1).should be true
|
89
|
+
Money.new(1_57, "USD").eql?(1.57).should be true
|
90
|
+
Money.new(1_00, "USD").eql?(2).should be false
|
91
|
+
Money.new(1_00, "GBP").eql?(1).should be false
|
92
|
+
end
|
93
|
+
|
94
|
+
specify "#eql? can be used to compare with an object that responds to #to_money" do
|
95
|
+
klass = Class.new do
|
96
|
+
def initialize(money)
|
97
|
+
@money = money
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_money
|
101
|
+
@money
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
Money.new(1_00, "USD").eql?(klass.new(Money.new(1_00, "USD"))).should be true
|
106
|
+
Money.new(2_50, "USD").eql?(klass.new(Money.new(2_50, "USD"))).should be true
|
107
|
+
Money.new(2_50, "USD").eql?(klass.new(Money.new(3_00, "USD"))).should be false
|
108
|
+
Money.new(1_00, "GBP").eql?(klass.new(Money.new(1_00, "USD"))).should be false
|
109
|
+
end
|
110
|
+
|
111
|
+
specify "#eql? returns false if used to compare with an object that doesn't respond to #to_money" do
|
112
|
+
Money.new(1_00, "USD").eql?(Object.new).should be false
|
113
|
+
Money.new(1_00, "USD").eql?(Class).should be false
|
114
|
+
Money.new(1_00, "USD").eql?(Kernel).should be false
|
115
|
+
Money.new(1_00, "USD").eql?(/foo/).should be false
|
116
|
+
Money.new(1_00, "USD").eql?(nil).should be false
|
117
|
+
end
|
118
|
+
|
119
|
+
specify "#<=> can be used to compare with a String money value" do
|
120
|
+
(Money.new(1_00) <=> "1.00").should == 0
|
121
|
+
(Money.new(1_00) <=> ".99").should > 0
|
122
|
+
(Money.new(1_00) <=> "2.00").should < 0
|
123
|
+
end
|
124
|
+
|
125
|
+
specify "#<=> can be used to compare with a Numeric money value" do
|
126
|
+
(Money.new(1_00) <=> 1).should == 0
|
127
|
+
(Money.new(1_00) <=> 0.99).should > 0
|
128
|
+
(Money.new(1_00) <=> 2.00).should < 0
|
129
|
+
end
|
130
|
+
|
131
|
+
specify "#<=> can be used to compare with an object that responds to #to_money" do
|
132
|
+
klass = Class.new do
|
133
|
+
def initialize(money)
|
134
|
+
@money = money
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_money
|
138
|
+
@money
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
(Money.new(1_00) <=> klass.new(Money.new(1_00))).should == 0
|
143
|
+
(Money.new(1_00) <=> klass.new(Money.new(99))).should > 0
|
144
|
+
(Money.new(1_00) <=> klass.new(Money.new(2_00))).should < 0
|
145
|
+
end
|
146
|
+
|
147
|
+
specify "#<=> raises ArgumentError when used to compare with an object that doesn't respond to #to_money" do
|
148
|
+
expected_message = /Comparison .+ failed/
|
149
|
+
lambda{ Money.new(1_00) <=> Object.new }.should raise_error(ArgumentError, expected_message)
|
150
|
+
lambda{ Money.new(1_00) <=> Class }.should raise_error(ArgumentError, expected_message)
|
151
|
+
lambda{ Money.new(1_00) <=> Kernel }.should raise_error(ArgumentError, expected_message)
|
152
|
+
lambda{ Money.new(1_00) <=> /foo/ }.should raise_error(ArgumentError, expected_message)
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "#*" do
|
156
|
+
it "should multiply current money amount by the multiplier while retaining the currency" do
|
157
|
+
(Money.new(1_00, "USD") * 10).should == Money.new(10_00, "USD")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should multiply Money by Fixnum and returns Money" do
|
161
|
+
ts = [
|
162
|
+
{:a => Money.new( 10, :USD), :b => 4, :c => Money.new( 40, :USD)},
|
163
|
+
{:a => Money.new( 10, :USD), :b => -4, :c => Money.new(-40, :USD)},
|
164
|
+
{:a => Money.new(-10, :USD), :b => 4, :c => Money.new(-40, :USD)},
|
165
|
+
{:a => Money.new(-10, :USD), :b => -4, :c => Money.new( 40, :USD)},
|
166
|
+
]
|
167
|
+
ts.each do |t|
|
168
|
+
(t[:a] * t[:b]).should == t[:c]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should not multiply Money by Money (same currency)" do
|
173
|
+
lambda { Money.new( 10, :USD) * Money.new( 4, :USD) }.should raise_error(ArgumentError)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should not multiply Money by Money (different currency)" do
|
177
|
+
lambda { Money.new( 10, :USD) * Money.new( 4, :EUR) }.should raise_error(ArgumentError)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#/" do
|
182
|
+
it "divides current money amount by the divisor while retaining the currency" do
|
183
|
+
(Money.new(10_00, "USD") / 10).should == Money.new(1_00, "USD")
|
184
|
+
end
|
185
|
+
|
186
|
+
it "divides Money by Fixnum and returns Money" do
|
187
|
+
ts = [
|
188
|
+
{:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
|
189
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-4, :USD)},
|
190
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-4, :USD)},
|
191
|
+
{:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
|
192
|
+
]
|
193
|
+
ts.each do |t|
|
194
|
+
(t[:a] / t[:b]).should == t[:c]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
it "divides Money by Money (same currency) and returns Float" do
|
199
|
+
ts = [
|
200
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => 3.25},
|
201
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => -3.25},
|
202
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => -3.25},
|
203
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => 3.25},
|
204
|
+
]
|
205
|
+
ts.each do |t|
|
206
|
+
(t[:a] / t[:b]).should == t[:c]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
it "divides Money by Money (different currency) and returns Float" do
|
211
|
+
ts = [
|
212
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => 1.625},
|
213
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => -1.625},
|
214
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => -1.625},
|
215
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => 1.625},
|
216
|
+
]
|
217
|
+
ts.each do |t|
|
218
|
+
t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
|
219
|
+
(t[:a] / t[:b]).should == t[:c]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
specify "#div -> money / fixnum" do
|
225
|
+
ts = [
|
226
|
+
{:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
|
227
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-4, :USD)},
|
228
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-4, :USD)},
|
229
|
+
{:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
|
230
|
+
]
|
231
|
+
ts.each do |t|
|
232
|
+
t[:a].div(t[:b]).should == t[:c]
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
specify "#div -> money / money (same currency)" do
|
237
|
+
ts = [
|
238
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => 3.25},
|
239
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => -3.25},
|
240
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => -3.25},
|
241
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => 3.25},
|
242
|
+
]
|
243
|
+
ts.each do |t|
|
244
|
+
t[:a].div(t[:b]).should == t[:c]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
specify "#div -> money / money (different currency)" do
|
249
|
+
ts = [
|
250
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => 1.625},
|
251
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => -1.625},
|
252
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => -1.625},
|
253
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => 1.625},
|
254
|
+
]
|
255
|
+
ts.each do |t|
|
256
|
+
t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
|
257
|
+
t[:a].div(t[:b]).should == t[:c]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
specify "#divmod -> money `divmod` fixnum" do
|
262
|
+
ts = [
|
263
|
+
{:a => Money.new( 13, :USD), :b => 4, :c => [Money.new( 3, :USD), Money.new( 1, :USD)]},
|
264
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => [Money.new(-4, :USD), Money.new(-3, :USD)]},
|
265
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => [Money.new(-4, :USD), Money.new( 3, :USD)]},
|
266
|
+
{:a => Money.new(-13, :USD), :b => -4, :c => [Money.new( 3, :USD), Money.new(-1, :USD)]},
|
267
|
+
]
|
268
|
+
ts.each do |t|
|
269
|
+
t[:a].divmod(t[:b]).should == t[:c]
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
specify "#divmod -> money `divmod` money (same currency)" do
|
274
|
+
ts = [
|
275
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => [ 3, Money.new( 1, :USD)]},
|
276
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => [-4, Money.new(-3, :USD)]},
|
277
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => [-4, Money.new( 3, :USD)]},
|
278
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => [ 3, Money.new(-1, :USD)]},
|
279
|
+
]
|
280
|
+
ts.each do |t|
|
281
|
+
t[:a].divmod(t[:b]).should == t[:c]
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
specify "#divmod -> money `divmod` money (different currency)" do
|
286
|
+
ts = [
|
287
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => [ 1, Money.new( 5, :USD)]},
|
288
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => [-2, Money.new(-3, :USD)]},
|
289
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => [-2, Money.new( 3, :USD)]},
|
290
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => [ 1, Money.new(-5, :USD)]},
|
291
|
+
]
|
292
|
+
ts.each do |t|
|
293
|
+
t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
|
294
|
+
t[:a].divmod(t[:b]).should == t[:c]
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
specify "#modulo -> money `modulo` fixnum" do
|
299
|
+
ts = [
|
300
|
+
{:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
|
301
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
|
302
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new( 3, :USD)},
|
303
|
+
{:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
|
304
|
+
]
|
305
|
+
ts.each do |t|
|
306
|
+
t[:a].modulo(t[:b]).should == t[:c]
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
specify "#modulo -> money `modulo` money (same currency)" do
|
311
|
+
ts = [
|
312
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
|
313
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-3, :USD)},
|
314
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 3, :USD)},
|
315
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
|
316
|
+
]
|
317
|
+
ts.each do |t|
|
318
|
+
t[:a].modulo(t[:b]).should == t[:c]
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
specify "#modulo -> money `modulo` money (different currency)" do
|
323
|
+
ts = [
|
324
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
|
325
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-3, :USD)},
|
326
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 3, :USD)},
|
327
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
|
328
|
+
]
|
329
|
+
ts.each do |t|
|
330
|
+
t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
|
331
|
+
t[:a].modulo(t[:b]).should == t[:c]
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
specify "#% -> money % fixnum" do
|
336
|
+
ts = [
|
337
|
+
{:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
|
338
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
|
339
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new( 3, :USD)},
|
340
|
+
{:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
|
341
|
+
]
|
342
|
+
ts.each do |t|
|
343
|
+
(t[:a] % t[:b]).should == t[:c]
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
specify "#% -> money % money (same currency)" do
|
348
|
+
ts = [
|
349
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
|
350
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-3, :USD)},
|
351
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 3, :USD)},
|
352
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
|
353
|
+
]
|
354
|
+
ts.each do |t|
|
355
|
+
(t[:a] % t[:b]).should == t[:c]
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
specify "#% -> money % money (different currency)" do
|
360
|
+
ts = [
|
361
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
|
362
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-3, :USD)},
|
363
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 3, :USD)},
|
364
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
|
365
|
+
]
|
366
|
+
ts.each do |t|
|
367
|
+
t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
|
368
|
+
(t[:a] % t[:b]).should == t[:c]
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
specify "#remainder -> money `remainder` fixnum" do
|
373
|
+
ts = [
|
374
|
+
{:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
|
375
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new( 1, :USD)},
|
376
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-1, :USD)},
|
377
|
+
{:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
|
378
|
+
]
|
379
|
+
ts.each do |t|
|
380
|
+
t[:a].remainder(t[:b]).should == t[:c]
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
specify "#remainder -> money `remainder` money (same currency)" do
|
385
|
+
ts = [
|
386
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
|
387
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new( 1, :USD)},
|
388
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new(-1, :USD)},
|
389
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
|
390
|
+
]
|
391
|
+
ts.each do |t|
|
392
|
+
t[:a].remainder(t[:b]).should == t[:c]
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
specify "#remainder -> money `remainder` money (different currency)" do
|
397
|
+
ts = [
|
398
|
+
{:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
|
399
|
+
{:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new( 5, :USD)},
|
400
|
+
{:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new(-5, :USD)},
|
401
|
+
{:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
|
402
|
+
]
|
403
|
+
ts.each do |t|
|
404
|
+
t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
|
405
|
+
t[:a].remainder(t[:b]).should == t[:c]
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
specify "#abs correctly returns the absolute value as a new Money object" do
|
410
|
+
n = Money.new(-1, :USD)
|
411
|
+
n.abs.should == Money.new( 1, :USD)
|
412
|
+
n.should == Money.new(-1, :USD)
|
413
|
+
end
|
414
|
+
|
415
|
+
describe "Actions involving two Money objects" do
|
416
|
+
describe "if the other Money object has the same currency" do
|
417
|
+
specify "#<=> compares the two object amounts" do
|
418
|
+
(Money.new(1_00, "USD") <=> Money.new(1_00, "USD")).should == 0
|
419
|
+
(Money.new(1_00, "USD") <=> Money.new(99, "USD")).should > 0
|
420
|
+
(Money.new(1_00, "USD") <=> Money.new(2_00, "USD")).should < 0
|
421
|
+
end
|
422
|
+
|
423
|
+
specify "#+ adds other amount to current amount and returns a Money while retaining the currency" do
|
424
|
+
(Money.new(10_00, "USD") + Money.new(90, "USD")).should == Money.new(10_90, "USD")
|
425
|
+
end
|
426
|
+
|
427
|
+
specify "#- subtracts other amount from current amount and returns a Money while retaining the currency" do
|
428
|
+
(Money.new(10_00, "USD") - Money.new(90, "USD")).should == Money.new(9_10, "USD")
|
429
|
+
end
|
430
|
+
|
431
|
+
specify "#* should raise ArgumentError" do
|
432
|
+
lambda { Money.new(10_00, "USD") * Money.new(2, "USD") }.should raise_error(ArgumentError)
|
433
|
+
end
|
434
|
+
|
435
|
+
specify "#/ divides current amount by other amount and returns a Float" do
|
436
|
+
(Money.new(10_00, "USD") / Money.new(100_00, "USD")).should == 0.1
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
describe "if the other Money object has a different currency" do
|
441
|
+
specify "#<=> converts other object amount to current currency, then compares the two object amounts" do
|
442
|
+
target = Money.new(200_00, "EUR")
|
443
|
+
target.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(300_00, "USD"))
|
444
|
+
(Money.new(100_00, "USD") <=> target).should < 0
|
445
|
+
|
446
|
+
target = Money.new(200_00, "EUR")
|
447
|
+
target.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(100_00, "USD"))
|
448
|
+
(Money.new(100_00, "USD") <=> target).should == 0
|
449
|
+
|
450
|
+
target = Money.new(200_00, "EUR")
|
451
|
+
target.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(99_00, "USD"))
|
452
|
+
(Money.new(100_00, "USD") <=> target).should > 0
|
453
|
+
end
|
454
|
+
|
455
|
+
specify "#+ converts other object amount to current currency, then adds other amount to current amount and returns a Money" do
|
456
|
+
other = Money.new(90, "EUR")
|
457
|
+
other.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(9_00, "USD"))
|
458
|
+
(Money.new(10_00, "USD") + other).should == Money.new(19_00, "USD")
|
459
|
+
end
|
460
|
+
|
461
|
+
specify "#- converts other object amount to current currency, then subtracts other amount from current amount and returns a Money" do
|
462
|
+
other = Money.new(90, "EUR")
|
463
|
+
other.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(9_00, "USD"))
|
464
|
+
(Money.new(10_00, "USD") - other).should == Money.new(1_00, "USD")
|
465
|
+
end
|
466
|
+
|
467
|
+
specify "#* should raise ArgumentError" do
|
468
|
+
lambda { Money.new(10_00, "USD") * Money.new(10, "EUR") }.should raise_error(ArgumentError)
|
469
|
+
end
|
470
|
+
|
471
|
+
specify "#/ converts other object amount to current currency, then divides current amount by other amount and returns a Float" do
|
472
|
+
other = Money.new(1000, "EUR")
|
473
|
+
other.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(100_00, "USD"))
|
474
|
+
(Money.new(10_00, "USD") / other).should == 0.1
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
end
|