money 3.5.5 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,142 @@
1
+ require "spec_helper"
2
+
3
+ describe "Money core extensions" do
4
+
5
+ describe Numeric do
6
+ describe "#to_money" do
7
+ it "should work" do
8
+ money = 1234.to_money
9
+ money.cents.should == 1234_00
10
+ money.currency.should == Money.default_currency
11
+
12
+ money = 100.37.to_money
13
+ money.cents.should == 100_37
14
+ money.currency.should == Money.default_currency
15
+
16
+ money = BigDecimal.new('1234').to_money
17
+ money.cents.should == 1234_00
18
+ money.currency.should == Money.default_currency
19
+ end
20
+
21
+ it "should accept optional currency" do
22
+ 1234.to_money('USD').should == Money.new(123400, 'USD')
23
+ 1234.to_money('EUR').should == Money.new(123400, 'EUR')
24
+ end
25
+
26
+ it "should respect :subunit_to_unit currency property" do
27
+ 10.to_money('USD').should == Money.new(10_00, 'USD')
28
+ 10.to_money('TND').should == Money.new(10_000, 'TND')
29
+ 10.to_money('CLP').should == Money.new(10, 'CLP')
30
+ end
31
+
32
+ specify "#issue/15" do
33
+ amount = 555.55.to_money
34
+ amount.should == Money.new(55555)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe String do
40
+ describe "#to_money" do
41
+
42
+ StringToMoney = {
43
+ "20.15" => Money.new(20_15) ,
44
+ "100" => Money.new(100_00) ,
45
+ "100.37" => Money.new(100_37) ,
46
+ "100,37" => Money.new(100_37) ,
47
+ "100 000" => Money.new(100_000_00) ,
48
+ "100,000.00" => Money.new(100_000_00) ,
49
+ "1,000" => Money.new(1_000_00) ,
50
+ "-1,000" => Money.new(-1_000_00) ,
51
+ "1,000.5" => Money.new(1_000_50) ,
52
+ "1,000.51" => Money.new(1_000_51) ,
53
+ "1,000.505" => Money.new(1_000_51) ,
54
+ "1,000.504" => Money.new(1_000_50) ,
55
+ "1,000.0000" => Money.new(1_000_00) ,
56
+ "1,000.5000" => Money.new(1_000_50) ,
57
+ "1,000.5099" => Money.new(1_000_51) ,
58
+ "1.550" => Money.new(1_55) ,
59
+ "25." => Money.new(25_00) ,
60
+ ".75" => Money.new(75) ,
61
+
62
+ "100 USD" => Money.new(100_00, "USD") ,
63
+ "-100 USD" => Money.new(-100_00, "USD") ,
64
+ "100 EUR" => Money.new(100_00, "EUR") ,
65
+ "100.37 EUR" => Money.new(100_37, "EUR") ,
66
+ "100,37 EUR" => Money.new(100_37, "EUR") ,
67
+ "100,000.00 USD" => Money.new(100_000_00, "USD") ,
68
+ "100.000,00 EUR" => Money.new(100_000_00, "EUR") ,
69
+ "1,000 USD" => Money.new(1_000_00, "USD") ,
70
+ "-1,000 USD" => Money.new(-1_000_00, "USD") ,
71
+ "1,000.5500 USD" => Money.new(1_000_55, "USD") ,
72
+ "-1,000.6500 USD" => Money.new(-1_000_65, "USD") ,
73
+ "1.550 USD" => Money.new(1_55, "USD") ,
74
+
75
+ "USD 100" => Money.new(100_00, "USD") ,
76
+ "EUR 100" => Money.new(100_00, "EUR") ,
77
+ "EUR 100.37" => Money.new(100_37, "EUR") ,
78
+ "CAD -100.37" => Money.new(-100_37, "CAD") ,
79
+ "EUR 100,37" => Money.new(100_37, "EUR") ,
80
+ "EUR -100,37" => Money.new(-100_37, "EUR") ,
81
+ "USD 100,000.00" => Money.new(100_000_00, "USD") ,
82
+ "EUR 100.000,00" => Money.new(100_000_00, "EUR") ,
83
+ "USD 1,000" => Money.new(1_000_00, "USD") ,
84
+ "USD -1,000" => Money.new(-1_000_00, "USD") ,
85
+ "USD 1,000.9000" => Money.new(1_000_90, "USD") ,
86
+ "USD -1,000.090" => Money.new(-1_000_09, "USD") ,
87
+ "USD 1.5500" => Money.new(1_55, "USD") ,
88
+
89
+ "$100 USD" => Money.new(100_00, "USD") ,
90
+ "$1,194.59 USD" => Money.new(1_194_59, "USD") ,
91
+ "$-1,955 USD" => Money.new(-1_955_00, "USD") ,
92
+ "$1,194.5900 USD" => Money.new(1_194_59, "USD") ,
93
+ "$-1,955.000 USD" => Money.new(-1_955_00, "USD") ,
94
+ "$1.99000 USD" => Money.new(1_99, "USD") ,
95
+ }
96
+
97
+ specify "it should work" do
98
+ StringToMoney.each do |string, money|
99
+ string.to_money.should == money
100
+ end
101
+ end
102
+
103
+ it "should coerce input to string" do
104
+ Money.parse(20, "USD").should == Money.new(20_00, "USD")
105
+ end
106
+
107
+ it "should accept optional currency" do
108
+ "10.10".to_money('USD').should == Money.new(1010, 'USD')
109
+ "10.10".to_money('EUR').should == Money.new(1010, 'EUR')
110
+ "10.10 USD".to_money('USD').should == Money.new(1010, 'USD')
111
+ end
112
+
113
+ it "should raise error if optional currency doesn't match string currency" do
114
+ lambda{ "10.10 USD".to_money('EUR') }.should raise_error(/Mismatching Currencies/)
115
+ end
116
+
117
+ it "should ignore unrecognized data" do
118
+ "hello 2000 world".to_money.should == Money.new(2000_00)
119
+ end
120
+
121
+ it "should respect :subunit_to_unit currency property" do
122
+ "1".to_money("USD").should == Money.new(1_00, "USD")
123
+ "1".to_money("TND").should == Money.new(1_000, "TND")
124
+ "1".to_money("CLP").should == Money.new(1, "CLP")
125
+ "1.5".to_money("KWD").cents.should == 1500
126
+ end
127
+ end
128
+
129
+ describe "#to_currency" do
130
+ it "should convert string to Currency" do
131
+ "USD".to_currency.should == Money::Currency.new(:usd)
132
+ "EUR".to_currency.should == Money::Currency.new(:eur)
133
+ end
134
+
135
+ it "should raise Money::Currency::UnknownCurrency with unknown Currency" do
136
+ lambda { "XXX".to_currency }.should raise_error(Money::Currency::UnknownCurrency)
137
+ lambda { " ".to_currency }.should raise_error(Money::Currency::UnknownCurrency)
138
+ end
139
+ end
140
+ end
141
+
142
+ end
@@ -0,0 +1,128 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Money::Currency do
6
+
7
+ specify "#initialize should lookup data from TABLE" do
8
+ with_custom_definitions do
9
+ Money::Currency::TABLE[:usd] = {:priority => 1, :iso_code => "USD", :name => "United States Dollar", :symbol => "$", :subunit => "Cent", :subunit_to_unit => 100, :decimal_mark => ".", :thousands_separator => ","}
10
+ Money::Currency::TABLE[:eur] = {:priority => 2, :iso_code => "EUR", :name => "Euro", :symbol => "€", :subunit => "Cent", :subunit_to_unit => 100, :decimal_mark => ".", :thousands_separator => ","}
11
+
12
+ currency = Money::Currency.new("USD")
13
+ currency.id.should == :usd
14
+ currency.priority.should == 1
15
+ currency.iso_code.should == "USD"
16
+ currency.name.should == "United States Dollar"
17
+ currency.decimal_mark.should == "."
18
+ currency.separator.should == "."
19
+ currency.thousands_separator.should == ","
20
+ currency.delimiter.should == ","
21
+ end
22
+ end
23
+
24
+ specify "#initialize should raise UnknownMoney::Currency with unknown currency" do
25
+ lambda { Money::Currency.new("xxx") }.should raise_error(Money::Currency::UnknownCurrency, /xxx/)
26
+ end
27
+
28
+ specify "#== should return true if self === other" do
29
+ currency = Money::Currency.new(:eur)
30
+ currency.should == currency
31
+ end
32
+
33
+ specify "#== should return true if the id is equal" do
34
+ Money::Currency.new(:eur).should == Money::Currency.new(:eur)
35
+ Money::Currency.new(:eur).should_not == Money::Currency.new(:usd)
36
+ end
37
+
38
+ specify "#eql? should return true if #== returns true" do
39
+ Money::Currency.new(:eur).eql?(Money::Currency.new(:eur)).should be true
40
+ Money::Currency.new(:eur).eql?(Money::Currency.new(:usd)).should be false
41
+ end
42
+
43
+ specify "#hash should return the same value for equal objects" do
44
+ Money::Currency.new(:eur).hash.should == Money::Currency.new(:eur).hash
45
+ Money::Currency.new(:eur).hash.should_not == Money::Currency.new(:usd).hash
46
+ end
47
+
48
+ specify "#hash can be used to return the intersection of Currency object arrays" do
49
+ intersection = [Money::Currency.new(:eur), Money::Currency.new(:usd)] & [Money::Currency.new(:eur)]
50
+ intersection.should == [Money::Currency.new(:eur)]
51
+ end
52
+
53
+ specify "#<=> should compare objects by priority" do
54
+ Money::Currency.new(:cad).should > Money::Currency.new(:usd)
55
+ Money::Currency.new(:usd).should < Money::Currency.new(:eur)
56
+ end
57
+
58
+ specify "#to_s" do
59
+ Money::Currency.new(:usd).to_s.should == "USD"
60
+ Money::Currency.new(:eur).to_s.should == "EUR"
61
+ end
62
+
63
+ specify "#inspect" do
64
+ Money::Currency.new(:usd).inspect.should ==
65
+ %Q{#<Money::Currency id: usd, priority: 1, symbol_first: true, thousands_separator: ,, html_entity: $, decimal_mark: ., name: United States Dollar, symbol: $, subunit_to_unit: 100, iso_code: USD, subunit: Cent>}
66
+ end
67
+
68
+
69
+ specify "#self.find should return currency matching given id" do
70
+ with_custom_definitions do
71
+ Money::Currency::TABLE[:usd] = { :priority => 1, :iso_code => "USD", :name => "United States Dollar", :symbol => "$", :subunit => "Cent", :subunit_to_unit => 100, :decimal_mark => ".", :thousands_separator => "," }
72
+ Money::Currency::TABLE[:eur] = { :priority => 2, :iso_code => "EUR", :name => "Euro", :symbol => "€", :subunit => "Cent", :subunit_to_unit => 100, :decimal_mark => ".", :thousands_separator => "," }
73
+
74
+ expected = Money::Currency.new(:eur)
75
+ Money::Currency.find(:eur).should == expected
76
+ Money::Currency.find(:EUR).should == expected
77
+ Money::Currency.find("eur").should == expected
78
+ Money::Currency.find("EUR").should == expected
79
+ end
80
+ end
81
+
82
+ specify "#self.find should return nil unless currency matching given id" do
83
+ with_custom_definitions do
84
+ Money::Currency::TABLE[:usd] = { :position => 1, :iso_code => "USD", :name => "United States Dollar", :symbol => "$", :subunit => "Cent", :subunit_to_unit => 100, :decimal_mark => ".", :thousands_separator => "," }
85
+ Money::Currency::TABLE[:eur] = { :position => 2, :iso_code => "EUR", :name => "Euro", :symbol => "€", :subunit => "Cent", :subunit_to_unit => 100, :decimal_mark => ".", :thousands_separator => "," }
86
+
87
+ expected = Money::Currency.new(:eur)
88
+ Money::Currency.find(:eur).should == expected
89
+ Money::Currency.find(:EUR).should == expected
90
+ Money::Currency.find("eur").should == expected
91
+ Money::Currency.find("EUR").should == expected
92
+ end
93
+ end
94
+
95
+ specify "#self.wrap should return nil if object is nil" do
96
+ Money::Currency.wrap(nil).should == nil
97
+ Money::Currency.wrap(Money::Currency.new(:usd)).should == Money::Currency.new(:usd)
98
+ Money::Currency.wrap(:usd).should == Money::Currency.new(:usd)
99
+ end
100
+
101
+
102
+ def with_custom_definitions(&block)
103
+ begin
104
+ old = Money::Currency::TABLE.dup
105
+ Money::Currency::TABLE.clear
106
+ yield
107
+ ensure
108
+ silence_warnings do
109
+ Money::Currency.const_set("TABLE", old)
110
+ end
111
+ end
112
+ end
113
+
114
+ # Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
115
+ #
116
+ # silence_warnings do
117
+ # value = noisy_call # no warning voiced
118
+ # end
119
+ #
120
+ # noisy_call # warning voiced
121
+ def silence_warnings
122
+ old_verbose, $VERBOSE = $VERBOSE, nil
123
+ yield
124
+ ensure
125
+ $VERBOSE = old_verbose
126
+ end
127
+
128
+ end
@@ -0,0 +1,1268 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Money do
6
+
7
+ describe "#new" do
8
+ it "rounds the given cents to an integer" do
9
+ Money.new(1.00, "USD").cents.should == 1
10
+ Money.new(1.01, "USD").cents.should == 1
11
+ Money.new(1.50, "USD").cents.should == 2
12
+ end
13
+
14
+ it "is associated to the singleton instance of Bank::VariableExchange by default" do
15
+ Money.new(0).bank.should be_equal(Money::Bank::VariableExchange.instance)
16
+ end
17
+
18
+ end
19
+
20
+ describe "#cents" do
21
+ it "returns the amount of cents passed to the constructor" do
22
+ Money.new(200_00, "USD").cents.should == 200_00
23
+ end
24
+
25
+ it "stores cents as an integer regardless of what is passed into the constructor" do
26
+ [ Money.new(100), 1.to_money, 1.00.to_money, BigDecimal('1.00').to_money ].each do |m|
27
+ m.cents.should == 100
28
+ m.cents.should be_an_instance_of(Fixnum)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#dollars" do
34
+ it "gets cents as dollars" do
35
+ Money.new_with_dollars(1).should == Money.new(100)
36
+ Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
37
+ Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
38
+ end
39
+
40
+ it "should respect :subunit_to_unit currency property" do
41
+ Money.new(1_00, "USD").dollars.should == 1
42
+ Money.new(1_000, "TND").dollars.should == 1
43
+ Money.new(1, "CLP").dollars.should == 1
44
+ end
45
+
46
+ it "should not loose precision" do
47
+ Money.new(100_37).dollars.should == 100.37
48
+ Money.new_with_dollars(100.37).dollars.should == 100.37
49
+ end
50
+ end
51
+
52
+ specify "#currency returns the currency passed to the constructor" do
53
+ Money.new(200_00, "USD").currency.should == Money::Currency.new("USD")
54
+ end
55
+
56
+ specify "#currency_string returns the iso_code of the currency object" do
57
+ Money.new(200_00, "USD").currency_as_string.should == Money::Currency.new("USD").to_s
58
+ Money.new(200_00, "USD").currency_as_string.should == "USD"
59
+ Money.new(200_00, "EUR").currency_as_string.should == "EUR"
60
+ Money.new(200_00, "YEN").currency_as_string.should == "YEN"
61
+ end
62
+
63
+ specify "#currency_string= set the currency object using the provided string" do
64
+ obj = Money.new(200_00, "USD")
65
+ obj.currency_as_string = "EUR"
66
+ obj.currency.should == Money::Currency.new("EUR")
67
+ obj.currency_as_string = "YEN"
68
+ obj.currency.should == Money::Currency.new("YEN")
69
+ obj.currency_as_string = "USD"
70
+ obj.currency.should == Money::Currency.new("USD")
71
+ end
72
+
73
+ specify "#zero? returns whether the amount is 0" do
74
+ Money.new(0, "USD").should be_zero
75
+ Money.new(0, "EUR").should be_zero
76
+ Money.new(1, "USD").should_not be_zero
77
+ Money.new(10, "YEN").should_not be_zero
78
+ Money.new(-1, "EUR").should_not be_zero
79
+ end
80
+
81
+ specify "#nonzero? returns whether the amount is not 0" do
82
+ Money.new(0, "USD").should_not be_nonzero
83
+ Money.new(0, "EUR").should_not be_nonzero
84
+ Money.new(1, "USD").should be_nonzero
85
+ Money.new(10, "YEN").should be_nonzero
86
+ Money.new(-1, "EUR").should be_nonzero
87
+ end
88
+
89
+ specify "#nonzero? has the same return-value semantics as Numeric#nonzero?" do
90
+ Money.new(0, "USD").nonzero?.should be_nil
91
+
92
+ money = Money.new(1, "USD")
93
+ money.nonzero?.should be_equal(money)
94
+ end
95
+
96
+ specify "#exchange_to exchanges the amount via its exchange bank" do
97
+ money = Money.new(100_00, "USD")
98
+ money.bank.should_receive(:exchange_with).with(Money.new(100_00, Money::Currency.new("USD")), Money::Currency.new("EUR")).and_return(Money.new(200_00, Money::Currency.new('EUR')))
99
+ money.exchange_to("EUR")
100
+ end
101
+
102
+ specify "#exchange_to exchanges the amount properly" do
103
+ money = Money.new(100_00, "USD")
104
+ money.bank.should_receive(:exchange_with).with(Money.new(100_00, Money::Currency.new("USD")), Money::Currency.new("EUR")).and_return(Money.new(200_00, Money::Currency.new('EUR')))
105
+ money.exchange_to("EUR").should == Money.new(200_00, "EUR")
106
+ end
107
+
108
+ specify "#== returns true if and only if their amount and currency are equal" do
109
+ Money.new(1_00, "USD").should == Money.new(1_00, "USD")
110
+ Money.new(1_00, "USD").should_not == Money.new(1_00, "EUR")
111
+ Money.new(1_00, "USD").should_not == Money.new(2_00, "USD")
112
+ Money.new(1_00, "USD").should_not == Money.new(99_00, "EUR")
113
+ end
114
+
115
+ specify "#== can be used to compare with a String money value" do
116
+ Money.new(1_00, "USD").should == "1.00"
117
+ Money.new(1_00, "USD").should_not == "2.00"
118
+ Money.new(1_00, "GBP").should_not == "1.00"
119
+ end
120
+
121
+ specify "#== can be used to compare with a Numeric money value" do
122
+ Money.new(1_00, "USD").should == 1
123
+ Money.new(1_57, "USD").should == 1.57
124
+ Money.new(1_00, "USD").should_not == 2
125
+ Money.new(1_00, "GBP").should_not == 1
126
+ end
127
+
128
+ specify "#== can be used to compare with an object that responds to #to_money" do
129
+ klass = Class.new do
130
+ def initialize(money)
131
+ @money = money
132
+ end
133
+
134
+ def to_money
135
+ @money
136
+ end
137
+ end
138
+
139
+ Money.new(1_00, "USD").should == klass.new(Money.new(1_00, "USD"))
140
+ Money.new(2_50, "USD").should == klass.new(Money.new(2_50, "USD"))
141
+ Money.new(2_50, "USD").should_not == klass.new(Money.new(3_00, "USD"))
142
+ Money.new(1_00, "GBP").should_not == klass.new(Money.new(1_00, "USD"))
143
+ end
144
+
145
+ specify "#== returns false if used to compare with an object that doesn't respond to #to_money" do
146
+ Money.new(1_00, "USD").should_not == Object.new
147
+ Money.new(1_00, "USD").should_not == Class
148
+ Money.new(1_00, "USD").should_not == Kernel
149
+ Money.new(1_00, "USD").should_not == /foo/
150
+ Money.new(1_00, "USD").should_not == nil
151
+ end
152
+
153
+ specify "#eql? returns true if and only if their amount and currency are equal" do
154
+ Money.new(1_00, "USD").eql?(Money.new(1_00, "USD")).should be true
155
+ Money.new(1_00, "USD").eql?(Money.new(1_00, "EUR")).should be false
156
+ Money.new(1_00, "USD").eql?(Money.new(2_00, "USD")).should be false
157
+ Money.new(1_00, "USD").eql?(Money.new(99_00, "EUR")).should be false
158
+ end
159
+
160
+ specify "#eql? can be used to compare with a String money value" do
161
+ Money.new(1_00, "USD").eql?("1.00").should be true
162
+ Money.new(1_00, "USD").eql?("2.00").should be false
163
+ Money.new(1_00, "GBP").eql?("1.00").should be false
164
+ end
165
+
166
+ specify "#eql? can be used to compare with a Numeric money value" do
167
+ Money.new(1_00, "USD").eql?(1).should be true
168
+ Money.new(1_57, "USD").eql?(1.57).should be true
169
+ Money.new(1_00, "USD").eql?(2).should be false
170
+ Money.new(1_00, "GBP").eql?(1).should be false
171
+ end
172
+
173
+ specify "#eql? can be used to compare with an object that responds to #to_money" do
174
+ klass = Class.new do
175
+ def initialize(money)
176
+ @money = money
177
+ end
178
+
179
+ def to_money
180
+ @money
181
+ end
182
+ end
183
+
184
+ Money.new(1_00, "USD").eql?(klass.new(Money.new(1_00, "USD"))).should be true
185
+ Money.new(2_50, "USD").eql?(klass.new(Money.new(2_50, "USD"))).should be true
186
+ Money.new(2_50, "USD").eql?(klass.new(Money.new(3_00, "USD"))).should be false
187
+ Money.new(1_00, "GBP").eql?(klass.new(Money.new(1_00, "USD"))).should be false
188
+ end
189
+
190
+ specify "#eql? returns false if used to compare with an object that doesn't respond to #to_money" do
191
+ Money.new(1_00, "USD").eql?(Object.new).should be false
192
+ Money.new(1_00, "USD").eql?(Class).should be false
193
+ Money.new(1_00, "USD").eql?(Kernel).should be false
194
+ Money.new(1_00, "USD").eql?(/foo/).should be false
195
+ Money.new(1_00, "USD").eql?(nil).should be false
196
+ end
197
+
198
+ specify "#hash should return the same value for equal objects" do
199
+ Money.new(1_00, :eur).hash.should == Money.new(1_00, :eur).hash
200
+ Money.new(2_00, :usd).hash.should == Money.new(2_00, :usd).hash
201
+ Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :eur).hash
202
+ Money.new(1_00, :eur).hash.should_not == Money.new(1_00, :usd).hash
203
+ Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :usd).hash
204
+ end
205
+
206
+ specify "#hash can be used to return the intersection of Money object arrays" do
207
+ intersection = [Money.new(1_00, :eur), Money.new(1_00, :usd)] & [Money.new(1_00, :eur)]
208
+ intersection.should == [Money.new(1_00, :eur)]
209
+ end
210
+
211
+ specify "#<=> can be used to compare with a String money value" do
212
+ (Money.new(1_00) <=> "1.00").should == 0
213
+ (Money.new(1_00) <=> ".99").should > 0
214
+ (Money.new(1_00) <=> "2.00").should < 0
215
+ end
216
+
217
+ specify "#<=> can be used to compare with a Numeric money value" do
218
+ (Money.new(1_00) <=> 1).should == 0
219
+ (Money.new(1_00) <=> 0.99).should > 0
220
+ (Money.new(1_00) <=> 2.00).should < 0
221
+ end
222
+
223
+ specify "#<=> can be used to compare with an object that responds to #to_money" do
224
+ klass = Class.new do
225
+ def initialize(money)
226
+ @money = money
227
+ end
228
+
229
+ def to_money
230
+ @money
231
+ end
232
+ end
233
+
234
+ (Money.new(1_00) <=> klass.new(Money.new(1_00))).should == 0
235
+ (Money.new(1_00) <=> klass.new(Money.new(99))).should > 0
236
+ (Money.new(1_00) <=> klass.new(Money.new(2_00))).should < 0
237
+ end
238
+
239
+ specify "#<=> raises ArgumentError when used to compare with an object that doesn't respond to #to_money" do
240
+ expected_message = /Comparison .+ failed/
241
+ lambda{ Money.new(1_00) <=> Object.new }.should raise_error(ArgumentError, expected_message)
242
+ lambda{ Money.new(1_00) <=> Class }.should raise_error(ArgumentError, expected_message)
243
+ lambda{ Money.new(1_00) <=> Kernel }.should raise_error(ArgumentError, expected_message)
244
+ lambda{ Money.new(1_00) <=> /foo/ }.should raise_error(ArgumentError, expected_message)
245
+ end
246
+
247
+ describe "#*" do
248
+ it "should multiply current money amount by the multiplier while retaining the currency" do
249
+ (Money.new(1_00, "USD") * 10).should == Money.new(10_00, "USD")
250
+ end
251
+
252
+ it "should multiply Money by Fixnum and returns Money" do
253
+ ts = [
254
+ {:a => Money.new( 10, :USD), :b => 4, :c => Money.new( 40, :USD)},
255
+ {:a => Money.new( 10, :USD), :b => -4, :c => Money.new(-40, :USD)},
256
+ {:a => Money.new(-10, :USD), :b => 4, :c => Money.new(-40, :USD)},
257
+ {:a => Money.new(-10, :USD), :b => -4, :c => Money.new( 40, :USD)},
258
+ ]
259
+ ts.each do |t|
260
+ (t[:a] * t[:b]).should == t[:c]
261
+ end
262
+ end
263
+
264
+ it "should not multiply Money by Money (same currency)" do
265
+ lambda { Money.new( 10, :USD) * Money.new( 4, :USD) }.should raise_error(ArgumentError)
266
+ end
267
+
268
+ it "should not multiply Money by Money (different currency)" do
269
+ lambda { Money.new( 10, :USD) * Money.new( 4, :EUR) }.should raise_error(ArgumentError)
270
+ end
271
+ end
272
+
273
+ describe "#/" do
274
+ it "divides current money amount by the divisor while retaining the currency" do
275
+ (Money.new(10_00, "USD") / 10).should == Money.new(1_00, "USD")
276
+ end
277
+
278
+ it "divides Money by Fixnum and returns Money" do
279
+ ts = [
280
+ {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
281
+ {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-4, :USD)},
282
+ {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-4, :USD)},
283
+ {:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
284
+ ]
285
+ ts.each do |t|
286
+ (t[:a] / t[:b]).should == t[:c]
287
+ end
288
+ end
289
+
290
+ it "divides Money by Money (same currency) and returns Float" do
291
+ ts = [
292
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => 3.25},
293
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => -3.25},
294
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => -3.25},
295
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => 3.25},
296
+ ]
297
+ ts.each do |t|
298
+ (t[:a] / t[:b]).should == t[:c]
299
+ end
300
+ end
301
+
302
+ it "divides Money by Money (different currency) and returns Float" do
303
+ ts = [
304
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => 1.625},
305
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => -1.625},
306
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => -1.625},
307
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => 1.625},
308
+ ]
309
+ ts.each do |t|
310
+ t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
311
+ (t[:a] / t[:b]).should == t[:c]
312
+ end
313
+ end
314
+ end
315
+
316
+ specify "#div -> money / fixnum" do
317
+ ts = [
318
+ {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
319
+ {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-4, :USD)},
320
+ {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-4, :USD)},
321
+ {:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
322
+ ]
323
+ ts.each do |t|
324
+ t[:a].div(t[:b]).should == t[:c]
325
+ end
326
+ end
327
+
328
+ specify "#div -> money / money (same currency)" do
329
+ ts = [
330
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => 3.25},
331
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => -3.25},
332
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => -3.25},
333
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => 3.25},
334
+ ]
335
+ ts.each do |t|
336
+ t[:a].div(t[:b]).should == t[:c]
337
+ end
338
+ end
339
+
340
+ specify "#div -> money / money (different currency)" do
341
+ ts = [
342
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => 1.625},
343
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => -1.625},
344
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => -1.625},
345
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => 1.625},
346
+ ]
347
+ ts.each do |t|
348
+ t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
349
+ t[:a].div(t[:b]).should == t[:c]
350
+ end
351
+ end
352
+
353
+ specify "#divmod -> money `divmod` fixnum" do
354
+ ts = [
355
+ {:a => Money.new( 13, :USD), :b => 4, :c => [Money.new( 3, :USD), Money.new( 1, :USD)]},
356
+ {:a => Money.new( 13, :USD), :b => -4, :c => [Money.new(-4, :USD), Money.new(-3, :USD)]},
357
+ {:a => Money.new(-13, :USD), :b => 4, :c => [Money.new(-4, :USD), Money.new( 3, :USD)]},
358
+ {:a => Money.new(-13, :USD), :b => -4, :c => [Money.new( 3, :USD), Money.new(-1, :USD)]},
359
+ ]
360
+ ts.each do |t|
361
+ t[:a].divmod(t[:b]).should == t[:c]
362
+ end
363
+ end
364
+
365
+ specify "#divmod -> money `divmod` money (same currency)" do
366
+ ts = [
367
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => [ 3, Money.new( 1, :USD)]},
368
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => [-4, Money.new(-3, :USD)]},
369
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => [-4, Money.new( 3, :USD)]},
370
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => [ 3, Money.new(-1, :USD)]},
371
+ ]
372
+ ts.each do |t|
373
+ t[:a].divmod(t[:b]).should == t[:c]
374
+ end
375
+ end
376
+
377
+ specify "#divmod -> money `divmod` money (different currency)" do
378
+ ts = [
379
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => [ 1, Money.new( 5, :USD)]},
380
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => [-2, Money.new(-3, :USD)]},
381
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => [-2, Money.new( 3, :USD)]},
382
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => [ 1, Money.new(-5, :USD)]},
383
+ ]
384
+ ts.each do |t|
385
+ t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
386
+ t[:a].divmod(t[:b]).should == t[:c]
387
+ end
388
+ end
389
+
390
+ specify "#modulo -> money `modulo` fixnum" do
391
+ ts = [
392
+ {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
393
+ {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
394
+ {:a => Money.new(-13, :USD), :b => 4, :c => Money.new( 3, :USD)},
395
+ {:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
396
+ ]
397
+ ts.each do |t|
398
+ t[:a].modulo(t[:b]).should == t[:c]
399
+ end
400
+ end
401
+
402
+ specify "#modulo -> money `modulo` money (same currency)" do
403
+ ts = [
404
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
405
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-3, :USD)},
406
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 3, :USD)},
407
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
408
+ ]
409
+ ts.each do |t|
410
+ t[:a].modulo(t[:b]).should == t[:c]
411
+ end
412
+ end
413
+
414
+ specify "#modulo -> money `modulo` money (different currency)" do
415
+ ts = [
416
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
417
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-3, :USD)},
418
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 3, :USD)},
419
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
420
+ ]
421
+ ts.each do |t|
422
+ t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
423
+ t[:a].modulo(t[:b]).should == t[:c]
424
+ end
425
+ end
426
+
427
+ specify "#% -> money % fixnum" do
428
+ ts = [
429
+ {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
430
+ {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
431
+ {:a => Money.new(-13, :USD), :b => 4, :c => Money.new( 3, :USD)},
432
+ {:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
433
+ ]
434
+ ts.each do |t|
435
+ (t[:a] % t[:b]).should == t[:c]
436
+ end
437
+ end
438
+
439
+ specify "#% -> money % money (same currency)" do
440
+ ts = [
441
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
442
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-3, :USD)},
443
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 3, :USD)},
444
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
445
+ ]
446
+ ts.each do |t|
447
+ (t[:a] % t[:b]).should == t[:c]
448
+ end
449
+ end
450
+
451
+ specify "#% -> money % money (different currency)" do
452
+ ts = [
453
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
454
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-3, :USD)},
455
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 3, :USD)},
456
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
457
+ ]
458
+ ts.each do |t|
459
+ t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
460
+ (t[:a] % t[:b]).should == t[:c]
461
+ end
462
+ end
463
+
464
+ specify "#remainder -> money `remainder` fixnum" do
465
+ ts = [
466
+ {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
467
+ {:a => Money.new( 13, :USD), :b => -4, :c => Money.new( 1, :USD)},
468
+ {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-1, :USD)},
469
+ {:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
470
+ ]
471
+ ts.each do |t|
472
+ t[:a].remainder(t[:b]).should == t[:c]
473
+ end
474
+ end
475
+
476
+ specify "#remainder -> money `remainder` money (same currency)" do
477
+ ts = [
478
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
479
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new( 1, :USD)},
480
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new(-1, :USD)},
481
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
482
+ ]
483
+ ts.each do |t|
484
+ t[:a].remainder(t[:b]).should == t[:c]
485
+ end
486
+ end
487
+
488
+ specify "#remainder -> money `remainder` money (different currency)" do
489
+ ts = [
490
+ {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
491
+ {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new( 5, :USD)},
492
+ {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new(-5, :USD)},
493
+ {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
494
+ ]
495
+ ts.each do |t|
496
+ t[:b].should_receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
497
+ t[:a].remainder(t[:b]).should == t[:c]
498
+ end
499
+ end
500
+
501
+ specify "#abs correctly returns the absolute value as a new Money object" do
502
+ n = Money.new(-1, :USD)
503
+ n.abs.should == Money.new( 1, :USD)
504
+ n.should == Money.new(-1, :USD)
505
+ end
506
+
507
+ specify "Money.format brute force :subunit_to_unit = 1" do
508
+ ("0".."9").each do |amt|
509
+ amt.to_money("VUV").format(:symbol => false).should == amt
510
+ end
511
+ ("-1".."-9").each do |amt|
512
+ amt.to_money("VUV").format(:symbol => false).should == amt
513
+ end
514
+ "1000".to_money("VUV").format(:symbol => false).should == "1,000"
515
+ "-1000".to_money("VUV").format(:symbol => false).should == "-1,000"
516
+ end
517
+
518
+ specify "Money.format brute force :subunit_to_unit = 5" do
519
+ ("0.0".."9.4").each do |amt|
520
+ next if amt[-1].to_i > 4
521
+ amt.to_money("MGA").format(:symbol => false).should == amt
522
+ end
523
+ ("-0.1".."-9.4").each do |amt|
524
+ next if amt[-1].to_i > 4
525
+ amt.to_money("MGA").format(:symbol => false).should == amt
526
+ end
527
+ "1000.0".to_money("MGA").format(:symbol => false).should == "1,000.0"
528
+ "-1000.0".to_money("MGA").format(:symbol => false).should == "-1,000.0"
529
+ end
530
+
531
+ specify "Money.format brute force :subunit_to_unit = 10" do
532
+ ("0.0".."9.9").each do |amt|
533
+ amt.to_money("VND").format(:symbol => false).should == amt.to_s.gsub(/\./, ",")
534
+ end
535
+ ("-0.1".."-9.9").each do |amt|
536
+ amt.to_money("VND").format(:symbol => false).should == amt.to_s.gsub(/\./, ",")
537
+ end
538
+ "1000.0".to_money("VND").format(:symbol => false).should == "1.000,0"
539
+ "-1000.0".to_money("VND").format(:symbol => false).should == "-1.000,0"
540
+ end
541
+
542
+ specify "Money.format brute force :subunit_to_unit = 100" do
543
+ ("0.00".."9.99").each do |amt|
544
+ amt.to_money("USD").format(:symbol => false).should == amt
545
+ end
546
+ ("-0.01".."-9.99").each do |amt|
547
+ amt.to_money("USD").format(:symbol => false).should == amt
548
+ end
549
+ "1000.00".to_money("USD").format(:symbol => false).should == "1,000.00"
550
+ "-1000.00".to_money("USD").format(:symbol => false).should == "-1,000.00"
551
+ end
552
+
553
+ specify "Money.format brute force :subunit_to_unit = 1000" do
554
+ ("0.000".."9.999").each do |amt|
555
+ amt.to_money("IQD").format(:symbol => false).should == amt
556
+ end
557
+ ("-0.001".."-9.999").each do |amt|
558
+ amt.to_money("IQD").format(:symbol => false).should == amt
559
+ end
560
+ "1000.000".to_money("IQD").format(:symbol => false).should == "1,000.000"
561
+ "-1000.000".to_money("IQD").format(:symbol => false).should == "-1,000.000"
562
+ end
563
+
564
+ specify "Money.to_s works" do
565
+ Money.new(10_00).to_s.should == "10.00"
566
+ Money.new(400_08).to_s.should == "400.08"
567
+ Money.new(-237_43).to_s.should == "-237.43"
568
+ end
569
+
570
+ specify "Money.to_s should respect :subunit_to_unit currency property" do
571
+ Money.new(10_00, "BHD").to_s.should == "1.000"
572
+ Money.new(10_00, "CNY").to_s.should == "10.00"
573
+ end
574
+
575
+ specify "Money.to_s shouldn't have decimal when :subunit_to_unit is 1" do
576
+ Money.new(10_00, "CLP").to_s.should == "1000"
577
+ end
578
+
579
+ specify "Money.to_s should work with :subunit_to_unit == 5" do
580
+ Money.new(10_00, "MGA").to_s.should == "200.0"
581
+ end
582
+
583
+ specify "Money.to_s should respect :decimal_mark" do
584
+ Money.new(10_00, "BRL").to_s.should == "10,00"
585
+ end
586
+
587
+ specify "Money.to_f works" do
588
+ Money.new(10_00).to_f.should == 10.0
589
+ end
590
+
591
+ specify "Money.to_f should respect :subunit_to_unit currency property" do
592
+ Money.new(10_00, "BHD").to_f.should == 1.0
593
+ end
594
+
595
+ specify "#symbol works as documented" do
596
+ currency = Money::Currency.new("EUR")
597
+ currency.should_receive(:symbol).and_return("€")
598
+ Money.empty(currency).symbol.should == "€"
599
+
600
+ currency = Money::Currency.new("EUR")
601
+ currency.should_receive(:symbol).and_return(nil)
602
+ Money.empty(currency).symbol.should == "¤"
603
+ end
604
+
605
+ {
606
+ :thousands_separator => { :default => ",", :other => "." },
607
+ :decimal_mark => { :default => ".", :other => "," }
608
+ }.each do |method, options|
609
+ describe "##{method}" do
610
+ context "without I18n" do
611
+ it "works as documented" do
612
+ Money.empty("USD").send(method).should == options[:default]
613
+ Money.empty("EUR").send(method).should == options[:other]
614
+ Money.empty("BRL").send(method).should == options[:other]
615
+ end
616
+ end
617
+
618
+ if Object.const_defined?("I18n")
619
+ context "with I18n" do
620
+ before :all do
621
+ reset_i18n
622
+ store_number_formats(:en, method => options[:default])
623
+ store_number_formats(:de, method => options[:other])
624
+ end
625
+
626
+ it "looks up #{method} for current locale" do
627
+ I18n.locale = :en
628
+ Money.empty("USD").send(method).should == options[:default]
629
+ I18n.locale = :de
630
+ Money.empty("USD").send(method).should == options[:other]
631
+ end
632
+
633
+ it "fallbacks to default behaviour for missing translations" do
634
+ I18n.locale = :de
635
+ Money.empty("USD").send(method).should == options[:other]
636
+ I18n.locale = :fr
637
+ Money.empty("USD").send(method).should == options[:default]
638
+ end
639
+
640
+ after :all do
641
+ reset_i18n
642
+ end
643
+ end
644
+ else
645
+ puts "can't test ##{method} with I18n because it isn't loaded"
646
+ end
647
+ end
648
+ end
649
+
650
+ describe "#format" do
651
+ it "returns the monetary value as a string" do
652
+ Money.ca_dollar(100).format.should == "$1.00"
653
+ Money.new(40008).format.should == "$400.08"
654
+ end
655
+
656
+ it "should respect :subunit_to_unit currency property" do
657
+ Money.new(10_00, "BHD").format.should == "ب.د1.000"
658
+ end
659
+
660
+ it "doesn't display a decimal when :subunit_to_unit is 1" do
661
+ Money.new(10_00, "CLP").format.should == "$1.000"
662
+ end
663
+
664
+ it "respects the thousands_separator and decimal_mark defaults" do
665
+ one_thousand = Proc.new do |currency|
666
+ Money.new(1000_00, currency).format
667
+ end
668
+
669
+ # Pounds
670
+ one_thousand["GBP"].should == "£1,000.00"
671
+
672
+ # Dollars
673
+ one_thousand["USD"].should == "$1,000.00"
674
+ one_thousand["CAD"].should == "$1,000.00"
675
+ one_thousand["AUD"].should == "$1,000.00"
676
+ one_thousand["NZD"].should == "$1,000.00"
677
+ one_thousand["ZWD"].should == "$1,000.00"
678
+
679
+ # Yen
680
+ one_thousand["JPY"].should == "¥1,000.00"
681
+ one_thousand["CNY"].should == "¥1,000.00"
682
+
683
+ # Euro
684
+ one_thousand["EUR"].should == "1.000,00 €"
685
+
686
+ # Rupees
687
+ one_thousand["INR"].should == "₨1,000.00"
688
+ one_thousand["NPR"].should == "₨1,000.00"
689
+ one_thousand["SCR"].should == "1,000.00 ₨"
690
+ one_thousand["LKR"].should == "1,000.00 ₨"
691
+
692
+ # Brazilian Real
693
+ one_thousand["BRL"].should == "R$ 1.000,00"
694
+
695
+ # Other
696
+ one_thousand["SEK"].should == "kr1,000.00"
697
+ one_thousand["GHC"].should == "₵1,000.00"
698
+ end
699
+
700
+ describe "if the monetary value is 0" do
701
+ before :each do
702
+ @money = Money.us_dollar(0)
703
+ end
704
+
705
+ it "returns 'free' when :display_free is true" do
706
+ @money.format(:display_free => true).should == 'free'
707
+ end
708
+
709
+ it "returns '$0.00' when :display_free is false or not given" do
710
+ @money.format.should == '$0.00'
711
+ @money.format(:display_free => false).should == '$0.00'
712
+ @money.format(:display_free => nil).should == '$0.00'
713
+ end
714
+
715
+ it "returns the value specified by :display_free if it's a string-like object" do
716
+ @money.format(:display_free => 'gratis').should == 'gratis'
717
+ end
718
+ end
719
+
720
+ specify "#format(:with_currency => true) works as documented" do
721
+ Money.ca_dollar(100).format(:with_currency => true).should == "$1.00 CAD"
722
+ Money.us_dollar(85).format(:with_currency => true).should == "$0.85 USD"
723
+ end
724
+
725
+ specify "#format(:no_cents => true) works as documented" do
726
+ Money.ca_dollar(100).format(:no_cents => true).should == "$1"
727
+ Money.ca_dollar(599).format(:no_cents => true).should == "$5"
728
+ Money.ca_dollar(570).format(:no_cents => true, :with_currency => true).should == "$5 CAD"
729
+ Money.ca_dollar(39000).format(:no_cents => true).should == "$390"
730
+ end
731
+
732
+ specify "#format(:no_cents => true) should respect :subunit_to_unit currency property" do
733
+ Money.new(10_00, "BHD").format(:no_cents => true).should == "ب.د1"
734
+ end
735
+
736
+ specify "#format(:symbol => a symbol string) uses the given value as the money symbol" do
737
+ Money.new(100, "GBP").format(:symbol => "£").should == "£1.00"
738
+ end
739
+
740
+ specify "#format(:symbol => true) returns symbol based on the given currency code" do
741
+ one = Proc.new do |currency|
742
+ Money.new(100, currency).format(:symbol => true)
743
+ end
744
+
745
+ # Pounds
746
+ one["GBP"].should == "£1.00"
747
+
748
+ # Dollars
749
+ one["USD"].should == "$1.00"
750
+ one["CAD"].should == "$1.00"
751
+ one["AUD"].should == "$1.00"
752
+ one["NZD"].should == "$1.00"
753
+ one["ZWD"].should == "$1.00"
754
+
755
+ # Yen
756
+ one["JPY"].should == "¥1.00"
757
+ one["CNY"].should == "¥1.00"
758
+
759
+ # Euro
760
+ one["EUR"].should == "1,00 €"
761
+
762
+ # Rupees
763
+ one["INR"].should == "₨1.00"
764
+ one["NPR"].should == "₨1.00"
765
+ one["SCR"].should == "1.00 ₨"
766
+ one["LKR"].should == "1.00 ₨"
767
+
768
+ # Brazilian Real
769
+ one["BRL"].should == "R$ 1,00"
770
+
771
+ # Other
772
+ one["SEK"].should == "kr1.00"
773
+ one["GHC"].should == "₵1.00"
774
+ end
775
+
776
+ specify "#format(:symbol => true) returns $ when currency code is not recognized" do
777
+ currency = Money::Currency.new("EUR")
778
+ currency.should_receive(:symbol).and_return(nil)
779
+ Money.new(100, currency).format(:symbol => true).should == "1,00 ¤"
780
+ end
781
+
782
+ specify "#format(:symbol => some non-Boolean value that evaluates to true) returns symbol based on the given currency code" do
783
+ Money.new(100, "GBP").format(:symbol => true).should == "£1.00"
784
+ Money.new(100, "EUR").format(:symbol => true).should == "1,00 €"
785
+ Money.new(100, "SEK").format(:symbol => true).should == "kr1.00"
786
+ end
787
+
788
+ specify "#format with :symbol == "", nil or false returns the amount without a symbol" do
789
+ money = Money.new(100, "GBP")
790
+ money.format(:symbol => "").should == "1.00"
791
+ money.format(:symbol => nil).should == "1.00"
792
+ money.format(:symbol => false).should == "1.00"
793
+ end
794
+
795
+ specify "#format without :symbol assumes that :symbol is set to true" do
796
+ money = Money.new(100)
797
+ money.format.should == "$1.00"
798
+
799
+ money = Money.new(100, "GBP")
800
+ money.format.should == "£1.00"
801
+
802
+ money = Money.new(100, "EUR")
803
+ money.format.should == "1,00 €"
804
+ end
805
+
806
+ specify "#format(:decimal_mark => a decimal_mark string) works as documented" do
807
+ Money.us_dollar(100).format(:decimal_mark => ",").should == "$1,00"
808
+ end
809
+
810
+ specify "#format will default decimal_mark to '.' if currency isn't recognized" do
811
+ Money.new(100, "ZWD").format.should == "$1.00"
812
+ end
813
+
814
+ specify "#format(:separator => a separator string) works as documented" do
815
+ Money.us_dollar(100).format(:separator => ",").should == "$1,00"
816
+ end
817
+
818
+ specify "#format(:thousands_separator => a thousands_separator string) works as documented" do
819
+ Money.us_dollar(100000).format(:thousands_separator => ".").should == "$1.000.00"
820
+ Money.us_dollar(200000).format(:thousands_separator => "").should == "$2000.00"
821
+ end
822
+
823
+ specify "#format(:thousands_separator => false or nil) works as documented" do
824
+ Money.us_dollar(100000).format(:thousands_separator => false).should == "$1000.00"
825
+ Money.us_dollar(200000).format(:thousands_separator => nil).should == "$2000.00"
826
+ end
827
+
828
+ specify "#format(:delimiter => a delimiter string) works as documented" do
829
+ Money.us_dollar(100000).format(:delimiter => ".").should == "$1.000.00"
830
+ Money.us_dollar(200000).format(:delimiter => "").should == "$2000.00"
831
+ end
832
+
833
+ specify "#format(:delimiter => false or nil) works as documented" do
834
+ Money.us_dollar(100000).format(:delimiter => false).should == "$1000.00"
835
+ Money.us_dollar(200000).format(:delimiter => nil).should == "$2000.00"
836
+ end
837
+
838
+ specify "#format will default thousands_separator to ',' if currency isn't recognized" do
839
+ Money.new(100000, "ZWD").format.should == "$1,000.00"
840
+ end
841
+
842
+ specify "#format(:html => true) works as documented" do
843
+ string = Money.ca_dollar(570).format(:html => true, :with_currency => true)
844
+ string.should == "$5.70 <span class=\"currency\">CAD</span>"
845
+ end
846
+
847
+ it "should insert commas into the result if the amount is sufficiently large" do
848
+ Money.us_dollar(1_000_000_000_12).format.should == "$1,000,000,000.12"
849
+ Money.us_dollar(1_000_000_000_12).format(:no_cents => true).should == "$1,000,000,000"
850
+ end
851
+
852
+ it "inserts thousands separator into the result if the amount is sufficiently large and the currency symbol is at the end" do
853
+ Money.euro(1_234_567_12).format.should == "1.234.567,12 €"
854
+ Money.euro(1_234_567_12).format(:no_cents => true).should == "1.234.567 €"
855
+ end
856
+
857
+ it "inserts currency symbol before the amount when :symbol_position is set to :before" do
858
+ Money.euro(1_234_567_12).format(:symbol_position => :before).should == "€1.234.567,12"
859
+ end
860
+
861
+ it "inserts currency symbol after the amount when :symbol_position is set to :after" do
862
+ Money.us_dollar(1_000_000_000_12).format(:symbol_position => :after).should == "1,000,000,000.12 $"
863
+ end
864
+ end
865
+
866
+
867
+ describe "Money.empty" do
868
+ it "Money.empty creates a new Money object of 0 cents" do
869
+ Money.empty.should == Money.new(0)
870
+ end
871
+ end
872
+
873
+ describe "Money.ca_dollar" do
874
+ it "creates a new Money object of the given value in CAD" do
875
+ Money.ca_dollar(50).should == Money.new(50, "CAD")
876
+ end
877
+ end
878
+
879
+ describe "Money.us_dollar" do
880
+ it "creates a new Money object of the given value in USD" do
881
+ Money.us_dollar(50).should == Money.new(50, "USD")
882
+ end
883
+ end
884
+
885
+ describe "Money.euro" do
886
+ it "creates a new Money object of the given value in EUR" do
887
+ Money.euro(50).should == Money.new(50, "EUR")
888
+ end
889
+ end
890
+
891
+
892
+ describe "Money.new_with_dollars" do
893
+ it "converts given amount to cents" do
894
+ Money.new_with_dollars(1).should == Money.new(100)
895
+ Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
896
+ Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
897
+ end
898
+
899
+ it "should respect :subunit_to_unit currency property" do
900
+ Money.new_with_dollars(1, "USD").should == Money.new(1_00, "USD")
901
+ Money.new_with_dollars(1, "TND").should == Money.new(1_000, "TND")
902
+ Money.new_with_dollars(1, "CLP").should == Money.new(1, "CLP")
903
+ end
904
+
905
+ it "should not loose precision" do
906
+ Money.new_with_dollars(1234).cents.should == 1234_00
907
+ Money.new_with_dollars(100.37).cents.should == 100_37
908
+ Money.new_with_dollars(BigDecimal.new('1234')).cents.should == 1234_00
909
+ end
910
+
911
+ it "accepts a currency options" do
912
+ m = Money.new_with_dollars(1)
913
+ m.currency.should == Money.default_currency
914
+
915
+ m = Money.new_with_dollars(1, Money::Currency.wrap("EUR"))
916
+ m.currency.should == Money::Currency.wrap("EUR")
917
+
918
+ m = Money.new_with_dollars(1, "EUR")
919
+ m.currency.should == Money::Currency.wrap("EUR")
920
+ end
921
+
922
+ it "accepts a bank options" do
923
+ m = Money.new_with_dollars(1)
924
+ m.bank.should == Money.default_bank
925
+
926
+ m = Money.new_with_dollars(1, "EUR", bank = Object.new)
927
+ m.bank.should == bank
928
+ end
929
+
930
+ it "is associated to the singleton instance of Bank::VariableExchange by default" do
931
+ Money.new_with_dollars(0).bank.should be_equal(Money::Bank::VariableExchange.instance)
932
+ end
933
+ end
934
+
935
+ describe "Money.from_string" do
936
+ it "converts given amount to cents" do
937
+ Money.from_string("1").should == Money.new(1_00)
938
+ Money.from_string("1").should == Money.new(1_00, "USD")
939
+ Money.from_string("1", "EUR").should == Money.new(1_00, "EUR")
940
+ end
941
+
942
+ it "should respect :subunit_to_unit currency property" do
943
+ Money.from_string("1", "USD").should == Money.new(1_00, "USD")
944
+ Money.from_string("1", "TND").should == Money.new(1_000, "TND")
945
+ Money.from_string("1", "CLP").should == Money.new(1, "CLP")
946
+ end
947
+
948
+ it "accepts a currency options" do
949
+ m = Money.from_string("1")
950
+ m.currency.should == Money.default_currency
951
+
952
+ m = Money.from_string("1", Money::Currency.wrap("EUR"))
953
+ m.currency.should == Money::Currency.wrap("EUR")
954
+
955
+ m = Money.from_string("1", "EUR")
956
+ m.currency.should == Money::Currency.wrap("EUR")
957
+ end
958
+ end
959
+
960
+ describe "Money.from_fixnum" do
961
+ it "converts given amount to cents" do
962
+ Money.from_fixnum(1).should == Money.new(1_00)
963
+ Money.from_fixnum(1).should == Money.new(1_00, "USD")
964
+ Money.from_fixnum(1, "EUR").should == Money.new(1_00, "EUR")
965
+ end
966
+
967
+ it "should respect :subunit_to_unit currency property" do
968
+ Money.from_fixnum(1, "USD").should == Money.new(1_00, "USD")
969
+ Money.from_fixnum(1, "TND").should == Money.new(1_000, "TND")
970
+ Money.from_fixnum(1, "CLP").should == Money.new(1, "CLP")
971
+ end
972
+
973
+ it "accepts a currency options" do
974
+ m = Money.from_fixnum(1)
975
+ m.currency.should == Money.default_currency
976
+
977
+ m = Money.from_fixnum(1, Money::Currency.wrap("EUR"))
978
+ m.currency.should == Money::Currency.wrap("EUR")
979
+
980
+ m = Money.from_fixnum(1, "EUR")
981
+ m.currency.should == Money::Currency.wrap("EUR")
982
+ end
983
+ end
984
+
985
+ describe "Money.from_float" do
986
+ it "converts given amount to cents" do
987
+ Money.from_float(1.2).should == Money.new(1_20)
988
+ Money.from_float(1.2).should == Money.new(1_20, "USD")
989
+ Money.from_float(1.2, "EUR").should == Money.new(1_20, "EUR")
990
+ end
991
+
992
+ it "should respect :subunit_to_unit currency property" do
993
+ Money.from_float(1.2, "USD").should == Money.new(1_20, "USD")
994
+ Money.from_float(1.2, "TND").should == Money.new(1_200, "TND")
995
+ Money.from_float(1.2, "CLP").should == Money.new(1, "CLP")
996
+ end
997
+
998
+ it "accepts a currency options" do
999
+ m = Money.from_float(1.2)
1000
+ m.currency.should == Money.default_currency
1001
+
1002
+ m = Money.from_float(1.2, Money::Currency.wrap("EUR"))
1003
+ m.currency.should == Money::Currency.wrap("EUR")
1004
+
1005
+ m = Money.from_float(1.2, "EUR")
1006
+ m.currency.should == Money::Currency.wrap("EUR")
1007
+ end
1008
+ end
1009
+
1010
+ describe "Money.from_bigdecimal" do
1011
+ it "converts given amount to cents" do
1012
+ Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00)
1013
+ Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00, "USD")
1014
+ Money.from_bigdecimal(BigDecimal.new("1"), "EUR").should == Money.new(1_00, "EUR")
1015
+ end
1016
+
1017
+ it "should respect :subunit_to_unit currency property" do
1018
+ Money.from_bigdecimal(BigDecimal.new("1"), "USD").should == Money.new(1_00, "USD")
1019
+ Money.from_bigdecimal(BigDecimal.new("1"), "TND").should == Money.new(1_000, "TND")
1020
+ Money.from_bigdecimal(BigDecimal.new("1"), "CLP").should == Money.new(1, "CLP")
1021
+ end
1022
+
1023
+ it "accepts a currency options" do
1024
+ m = Money.from_bigdecimal(BigDecimal.new("1"))
1025
+ m.currency.should == Money.default_currency
1026
+
1027
+ m = Money.from_bigdecimal(BigDecimal.new("1"), Money::Currency.wrap("EUR"))
1028
+ m.currency.should == Money::Currency.wrap("EUR")
1029
+
1030
+ m = Money.from_bigdecimal(BigDecimal.new("1"), "EUR")
1031
+ m.currency.should == Money::Currency.wrap("EUR")
1032
+ end
1033
+ end
1034
+
1035
+ describe "Money.from_numeric" do
1036
+ it "converts given amount to cents" do
1037
+ Money.from_numeric(1).should == Money.new(1_00)
1038
+ Money.from_numeric(1.0).should == Money.new(1_00)
1039
+ Money.from_numeric(BigDecimal.new("1")).should == Money.new(1_00)
1040
+ end
1041
+
1042
+ it "should raise ArgumentError with unsupported argument" do
1043
+ lambda { Money.from_numeric("100") }.should raise_error(ArgumentError)
1044
+ end
1045
+
1046
+ it "should optimize workload" do
1047
+ Money.should_receive(:from_fixnum).with(1, "USD").and_return(Money.new(1_00, "USD"))
1048
+ Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
1049
+ Money.should_receive(:from_bigdecimal).with(BigDecimal.new("1.0"), "USD").and_return(Money.new(1_00, "USD"))
1050
+ Money.from_numeric(1.0, "USD").should == Money.new(1_00, "USD")
1051
+ end
1052
+
1053
+ it "should respect :subunit_to_unit currency property" do
1054
+ Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
1055
+ Money.from_numeric(1, "TND").should == Money.new(1_000, "TND")
1056
+ Money.from_numeric(1, "CLP").should == Money.new(1, "CLP")
1057
+ end
1058
+
1059
+ it "accepts a bank option" do
1060
+ Money.from_numeric(1).should == Money.new(1_00)
1061
+ Money.from_numeric(1).should == Money.new(1_00, "USD")
1062
+ Money.from_numeric(1, "EUR").should == Money.new(1_00, "EUR")
1063
+ end
1064
+
1065
+ it "accepts a currency options" do
1066
+ m = Money.from_numeric(1)
1067
+ m.currency.should == Money.default_currency
1068
+
1069
+ m = Money.from_numeric(1, Money::Currency.wrap("EUR"))
1070
+ m.currency.should == Money::Currency.wrap("EUR")
1071
+
1072
+ m = Money.from_numeric(1, "EUR")
1073
+ m.currency.should == Money::Currency.wrap("EUR")
1074
+ end
1075
+ end
1076
+
1077
+ describe "split" do
1078
+ specify "#split needs at least one party" do
1079
+ lambda {Money.us_dollar(1).split(0)}.should raise_error(ArgumentError)
1080
+ lambda {Money.us_dollar(1).split(-1)}.should raise_error(ArgumentError)
1081
+ end
1082
+
1083
+
1084
+ specify "#gives 1 cent to both people if we start with 2" do
1085
+ Money.us_dollar(2).split(2).should == [Money.us_dollar(1), Money.us_dollar(1)]
1086
+ end
1087
+
1088
+ specify "#split may distribute no money to some parties if there isnt enough to go around" do
1089
+ Money.us_dollar(2).split(3).should == [Money.us_dollar(1), Money.us_dollar(1), Money.us_dollar(0)]
1090
+ end
1091
+
1092
+ specify "#split does not lose pennies" do
1093
+ Money.us_dollar(5).split(2).should == [Money.us_dollar(3), Money.us_dollar(2)]
1094
+ end
1095
+
1096
+ specify "#split a dollar" do
1097
+ moneys = Money.us_dollar(100).split(3)
1098
+ moneys[0].cents.should == 34
1099
+ moneys[1].cents.should == 33
1100
+ moneys[2].cents.should == 33
1101
+ end
1102
+ end
1103
+
1104
+ describe "allocation" do
1105
+ specify "#allocate takes no action when one gets all" do
1106
+ Money.us_dollar(005).allocate([1]).should == [Money.us_dollar(5)]
1107
+ end
1108
+
1109
+ specify "#allocate keeps currencies intact" do
1110
+ Money.ca_dollar(005).allocate([1]).should == [Money.ca_dollar(5)]
1111
+ end
1112
+
1113
+ specify "#allocate does not loose pennies" do
1114
+ moneys = Money.us_dollar(5).allocate([0.3,0.7])
1115
+ moneys[0].should == Money.us_dollar(2)
1116
+ moneys[1].should == Money.us_dollar(3)
1117
+ end
1118
+
1119
+ specify "#allocate does not loose pennies" do
1120
+ moneys = Money.us_dollar(100).allocate([0.333,0.333, 0.333])
1121
+ moneys[0].cents.should == 34
1122
+ moneys[1].cents.should == 33
1123
+ moneys[2].cents.should == 33
1124
+ end
1125
+
1126
+ specify "#allocate requires total to be less then 1" do
1127
+ lambda { Money.us_dollar(0.05).allocate([0.5,0.6]) }.should raise_error(ArgumentError)
1128
+ end
1129
+ end
1130
+
1131
+ describe "Money.add_rate" do
1132
+ it "saves rate into current bank" do
1133
+ Money.add_rate("EUR", "USD", 10)
1134
+ Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
1135
+ end
1136
+ end
1137
+
1138
+
1139
+ # Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
1140
+ #
1141
+ # silence_warnings do
1142
+ # value = noisy_call # no warning voiced
1143
+ # end
1144
+ #
1145
+ # noisy_call # warning voiced
1146
+ def silence_warnings
1147
+ old_verbose, $VERBOSE = $VERBOSE, nil
1148
+ yield
1149
+ ensure
1150
+ $VERBOSE = old_verbose
1151
+ end
1152
+
1153
+ end
1154
+
1155
+ describe "Actions involving two Money objects" do
1156
+ describe "if the other Money object has the same currency" do
1157
+ specify "#<=> compares the two object amounts" do
1158
+ (Money.new(1_00, "USD") <=> Money.new(1_00, "USD")).should == 0
1159
+ (Money.new(1_00, "USD") <=> Money.new(99, "USD")).should > 0
1160
+ (Money.new(1_00, "USD") <=> Money.new(2_00, "USD")).should < 0
1161
+ end
1162
+
1163
+ specify "#+ adds other amount to current amount and returns a Money while retaining the currency" do
1164
+ (Money.new(10_00, "USD") + Money.new(90, "USD")).should == Money.new(10_90, "USD")
1165
+ end
1166
+
1167
+ specify "#- subtracts other amount from current amount and returns a Money while retaining the currency" do
1168
+ (Money.new(10_00, "USD") - Money.new(90, "USD")).should == Money.new(9_10, "USD")
1169
+ end
1170
+
1171
+ specify "#* should raise ArgumentError" do
1172
+ lambda { Money.new(10_00, "USD") * Money.new(2, "USD") }.should raise_error(ArgumentError)
1173
+ end
1174
+
1175
+ specify "#/ divides current amount by other amount and returns a Float" do
1176
+ (Money.new(10_00, "USD") / Money.new(100_00, "USD")).should == 0.1
1177
+ end
1178
+ end
1179
+
1180
+ describe "if the other Money object has a different currency" do
1181
+ specify "#<=> converts other object amount to current currency, then compares the two object amounts" do
1182
+ target = Money.new(200_00, "EUR")
1183
+ target.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(300_00, "USD"))
1184
+ (Money.new(100_00, "USD") <=> target).should < 0
1185
+
1186
+ target = Money.new(200_00, "EUR")
1187
+ target.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(100_00, "USD"))
1188
+ (Money.new(100_00, "USD") <=> target).should == 0
1189
+
1190
+ target = Money.new(200_00, "EUR")
1191
+ target.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(99_00, "USD"))
1192
+ (Money.new(100_00, "USD") <=> target).should > 0
1193
+ end
1194
+
1195
+ specify "#+ converts other object amount to current currency, then adds other amount to current amount and returns a Money" do
1196
+ other = Money.new(90, "EUR")
1197
+ other.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(9_00, "USD"))
1198
+ (Money.new(10_00, "USD") + other).should == Money.new(19_00, "USD")
1199
+ end
1200
+
1201
+ specify "#- converts other object amount to current currency, then subtracts other amount from current amount and returns a Money" do
1202
+ other = Money.new(90, "EUR")
1203
+ other.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(9_00, "USD"))
1204
+ (Money.new(10_00, "USD") - other).should == Money.new(1_00, "USD")
1205
+ end
1206
+
1207
+ specify "#* should raise ArgumentError" do
1208
+ lambda { Money.new(10_00, "USD") * Money.new(10, "EUR") }.should raise_error(ArgumentError)
1209
+ end
1210
+
1211
+ specify "#/ converts other object amount to current currency, then divides current amount by other amount and returns a Float" do
1212
+ other = Money.new(1000, "EUR")
1213
+ other.should_receive(:exchange_to).with(Money::Currency.new("USD")).and_return(Money.new(100_00, "USD"))
1214
+ (Money.new(10_00, "USD") / other).should == 0.1
1215
+ end
1216
+ end
1217
+ end
1218
+
1219
+
1220
+ describe "Money.parse" do
1221
+
1222
+ it "should be able to parse european-formatted inputs under 10EUR" do
1223
+ five_ninety_five = Money.new(595, 'EUR')
1224
+
1225
+ Money.parse('EUR 5,95').should == five_ninety_five
1226
+ #TODO: try and handle these
1227
+ #Money.parse('€5,95').should == five_ninety_five
1228
+ #Money.parse('&#036;5.95').should == five_ninety_five
1229
+ end
1230
+
1231
+ it "should be able to parse european-formatted inputs with multiple thousands-seperators" do
1232
+ Money.parse('EUR 1.234.567,89').should == Money.new(123456789, 'EUR')
1233
+ Money.parse('EUR 1.111.234.567,89').should == Money.new(111123456789, 'EUR')
1234
+ end
1235
+
1236
+ it "should be able to parse USD-formatted inputs under $10" do
1237
+ five_ninety_five = Money.new(595, 'USD')
1238
+
1239
+ Money.parse(5.95).should == five_ninety_five
1240
+ Money.parse('5.95').should == five_ninety_five
1241
+ Money.parse('$5.95').should == five_ninety_five
1242
+ Money.parse("\n $5.95 \n").should == five_ninety_five
1243
+ Money.parse('$ 5.95').should == five_ninety_five
1244
+ Money.parse('$5.95 ea.').should == five_ninety_five
1245
+ Money.parse('$5.95, each').should == five_ninety_five
1246
+ end
1247
+
1248
+ it "should be able to parse USD-formatted inputs with multiple thousands-seperators" do
1249
+ Money.parse('1,234,567.89').should == Money.new(123456789, 'USD')
1250
+ Money.parse('1,111,234,567.89').should == Money.new(111123456789, 'USD')
1251
+ end
1252
+
1253
+ it "should not return a price if there is a price range" do
1254
+ lambda {Money.parse('$5.95-10.95')}.should raise_error ArgumentError
1255
+ lambda {Money.parse('$5.95 - 10.95')}.should raise_error ArgumentError
1256
+ lambda {Money.parse('$5.95 - $10.95')}.should raise_error ArgumentError
1257
+ end
1258
+
1259
+ it "should not return a price for completely invalid input" do
1260
+ # TODO: shouldn't these throw an error instead of being considered
1261
+ # equal to $0.0?
1262
+ empty_price = Money.new(0, 'USD')
1263
+
1264
+ Money.parse(nil).should == empty_price
1265
+ Money.parse('hellothere').should == empty_price
1266
+ Money.parse('').should == empty_price
1267
+ end
1268
+ end