money 4.0.1 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,197 +1,210 @@
1
- # encoding: utf-8
2
-
3
- require "spec_helper"
4
-
5
- describe Money do
6
- describe "Money.parse" do
7
-
8
- it "should be able to parse european-formatted inputs under 10EUR" do
9
- five_ninety_five = Money.new(595, 'EUR')
10
-
11
- Money.parse('EUR 5,95').should == five_ninety_five
12
- #TODO: try and handle these
13
- #Money.parse('€5,95').should == five_ninety_five
14
- #Money.parse('$5.95').should == five_ninety_five
15
- end
16
-
17
- it "should be able to parse european-formatted inputs with multiple thousands-seperators" do
18
- Money.parse('EUR 1.234.567,89').should == Money.new(123456789, 'EUR')
19
- Money.parse('EUR 1.111.234.567,89').should == Money.new(111123456789, 'EUR')
20
- end
21
-
22
- it "should be able to parse USD-formatted inputs under $10" do
23
- five_ninety_five = Money.new(595, 'USD')
24
-
25
- Money.parse(5.95).should == five_ninety_five
26
- Money.parse('5.95').should == five_ninety_five
27
- Money.parse('$5.95').should == five_ninety_five
28
- Money.parse("\n $5.95 \n").should == five_ninety_five
29
- Money.parse('$ 5.95').should == five_ninety_five
30
- Money.parse('$5.95 ea.').should == five_ninety_five
31
- Money.parse('$5.95, each').should == five_ninety_five
32
- end
33
-
34
- it "should be able to parse USD-formatted inputs with multiple thousands-seperators" do
35
- Money.parse('1,234,567.89').should == Money.new(123456789, 'USD')
36
- Money.parse('1,111,234,567.89').should == Money.new(111123456789, 'USD')
37
- end
38
-
39
- it "should not return a price if there is a price range" do
40
- lambda {Money.parse('$5.95-10.95')}.should raise_error ArgumentError
41
- lambda {Money.parse('$5.95 - 10.95')}.should raise_error ArgumentError
42
- lambda {Money.parse('$5.95 - $10.95')}.should raise_error ArgumentError
43
- end
44
-
45
- it "should not return a price for completely invalid input" do
46
- # TODO: shouldn't these throw an error instead of being considered
47
- # equal to $0.0?
48
- empty_price = Money.new(0, 'USD')
49
-
50
- Money.parse(nil).should == empty_price
51
- Money.parse('hellothere').should == empty_price
52
- Money.parse('').should == empty_price
53
- end
54
- end
55
-
56
- describe "Money.from_string" do
57
- it "converts given amount to cents" do
58
- Money.from_string("1").should == Money.new(1_00)
59
- Money.from_string("1").should == Money.new(1_00, "USD")
60
- Money.from_string("1", "EUR").should == Money.new(1_00, "EUR")
61
- end
62
-
63
- it "should respect :subunit_to_unit currency property" do
64
- Money.from_string("1", "USD").should == Money.new(1_00, "USD")
65
- Money.from_string("1", "TND").should == Money.new(1_000, "TND")
66
- Money.from_string("1", "CLP").should == Money.new(1, "CLP")
67
- end
68
-
69
- it "accepts a currency options" do
70
- m = Money.from_string("1")
71
- m.currency.should == Money.default_currency
72
-
73
- m = Money.from_string("1", Money::Currency.wrap("EUR"))
74
- m.currency.should == Money::Currency.wrap("EUR")
75
-
76
- m = Money.from_string("1", "EUR")
77
- m.currency.should == Money::Currency.wrap("EUR")
78
- end
79
- end
80
-
81
- describe "Money.from_fixnum" do
82
- it "converts given amount to cents" do
83
- Money.from_fixnum(1).should == Money.new(1_00)
84
- Money.from_fixnum(1).should == Money.new(1_00, "USD")
85
- Money.from_fixnum(1, "EUR").should == Money.new(1_00, "EUR")
86
- end
87
-
88
- it "should respect :subunit_to_unit currency property" do
89
- Money.from_fixnum(1, "USD").should == Money.new(1_00, "USD")
90
- Money.from_fixnum(1, "TND").should == Money.new(1_000, "TND")
91
- Money.from_fixnum(1, "CLP").should == Money.new(1, "CLP")
92
- end
93
-
94
- it "accepts a currency options" do
95
- m = Money.from_fixnum(1)
96
- m.currency.should == Money.default_currency
97
-
98
- m = Money.from_fixnum(1, Money::Currency.wrap("EUR"))
99
- m.currency.should == Money::Currency.wrap("EUR")
100
-
101
- m = Money.from_fixnum(1, "EUR")
102
- m.currency.should == Money::Currency.wrap("EUR")
103
- end
104
- end
105
-
106
- describe "Money.from_float" do
107
- it "converts given amount to cents" do
108
- Money.from_float(1.2).should == Money.new(1_20)
109
- Money.from_float(1.2).should == Money.new(1_20, "USD")
110
- Money.from_float(1.2, "EUR").should == Money.new(1_20, "EUR")
111
- end
112
-
113
- it "should respect :subunit_to_unit currency property" do
114
- Money.from_float(1.2, "USD").should == Money.new(1_20, "USD")
115
- Money.from_float(1.2, "TND").should == Money.new(1_200, "TND")
116
- Money.from_float(1.2, "CLP").should == Money.new(1, "CLP")
117
- end
118
-
119
- it "accepts a currency options" do
120
- m = Money.from_float(1.2)
121
- m.currency.should == Money.default_currency
122
-
123
- m = Money.from_float(1.2, Money::Currency.wrap("EUR"))
124
- m.currency.should == Money::Currency.wrap("EUR")
125
-
126
- m = Money.from_float(1.2, "EUR")
127
- m.currency.should == Money::Currency.wrap("EUR")
128
- end
129
- end
130
-
131
- describe "Money.from_bigdecimal" do
132
- it "converts given amount to cents" do
133
- Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00)
134
- Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00, "USD")
135
- Money.from_bigdecimal(BigDecimal.new("1"), "EUR").should == Money.new(1_00, "EUR")
136
- end
137
-
138
- it "should respect :subunit_to_unit currency property" do
139
- Money.from_bigdecimal(BigDecimal.new("1"), "USD").should == Money.new(1_00, "USD")
140
- Money.from_bigdecimal(BigDecimal.new("1"), "TND").should == Money.new(1_000, "TND")
141
- Money.from_bigdecimal(BigDecimal.new("1"), "CLP").should == Money.new(1, "CLP")
142
- end
143
-
144
- it "accepts a currency options" do
145
- m = Money.from_bigdecimal(BigDecimal.new("1"))
146
- m.currency.should == Money.default_currency
147
-
148
- m = Money.from_bigdecimal(BigDecimal.new("1"), Money::Currency.wrap("EUR"))
149
- m.currency.should == Money::Currency.wrap("EUR")
150
-
151
- m = Money.from_bigdecimal(BigDecimal.new("1"), "EUR")
152
- m.currency.should == Money::Currency.wrap("EUR")
153
- end
154
- end
155
-
156
- describe "Money.from_numeric" do
157
- it "converts given amount to cents" do
158
- Money.from_numeric(1).should == Money.new(1_00)
159
- Money.from_numeric(1.0).should == Money.new(1_00)
160
- Money.from_numeric(BigDecimal.new("1")).should == Money.new(1_00)
161
- end
162
-
163
- it "should raise ArgumentError with unsupported argument" do
164
- lambda { Money.from_numeric("100") }.should raise_error(ArgumentError)
165
- end
166
-
167
- it "should optimize workload" do
168
- Money.should_receive(:from_fixnum).with(1, "USD").and_return(Money.new(1_00, "USD"))
169
- Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
170
- Money.should_receive(:from_bigdecimal).with(BigDecimal.new("1.0"), "USD").and_return(Money.new(1_00, "USD"))
171
- Money.from_numeric(1.0, "USD").should == Money.new(1_00, "USD")
172
- end
173
-
174
- it "should respect :subunit_to_unit currency property" do
175
- Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
176
- Money.from_numeric(1, "TND").should == Money.new(1_000, "TND")
177
- Money.from_numeric(1, "CLP").should == Money.new(1, "CLP")
178
- end
179
-
180
- it "accepts a bank option" do
181
- Money.from_numeric(1).should == Money.new(1_00)
182
- Money.from_numeric(1).should == Money.new(1_00, "USD")
183
- Money.from_numeric(1, "EUR").should == Money.new(1_00, "EUR")
184
- end
185
-
186
- it "accepts a currency options" do
187
- m = Money.from_numeric(1)
188
- m.currency.should == Money.default_currency
189
-
190
- m = Money.from_numeric(1, Money::Currency.wrap("EUR"))
191
- m.currency.should == Money::Currency.wrap("EUR")
192
-
193
- m = Money.from_numeric(1, "EUR")
194
- m.currency.should == Money::Currency.wrap("EUR")
195
- end
196
- end
197
- end
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Money, "parsing" do
6
+
7
+ describe ".parse" do
8
+ it "parses european-formatted inputs under 10EUR" do
9
+ five_ninety_five = Money.new(595, 'EUR')
10
+
11
+ Money.parse('EUR 5,95').should == five_ninety_five
12
+ #TODO: try and handle these
13
+ #Money.parse('€5,95').should == five_ninety_five
14
+ #Money.parse('$5.95').should == five_ninety_five
15
+ end
16
+
17
+ it "parses european-formatted inputs with multiple thousands-seperators" do
18
+ Money.parse('EUR 1.234.567,89').should == Money.new(123456789, 'EUR')
19
+ Money.parse('EUR 1.111.234.567,89').should == Money.new(111123456789, 'EUR')
20
+ end
21
+
22
+ it "parses USD-formatted inputs under $10" do
23
+ five_ninety_five = Money.new(595, 'USD')
24
+
25
+ Money.parse(5.95).should == five_ninety_five
26
+ Money.parse('5.95').should == five_ninety_five
27
+ Money.parse('$5.95').should == five_ninety_five
28
+ Money.parse("\n $5.95 \n").should == five_ninety_five
29
+ Money.parse('$ 5.95').should == five_ninety_five
30
+ Money.parse('$5.95 ea.').should == five_ninety_five
31
+ Money.parse('$5.95, each').should == five_ninety_five
32
+ end
33
+
34
+ it "parses USD-formatted inputs with multiple thousands-seperators" do
35
+ Money.parse('1,234,567.89').should == Money.new(123456789, 'USD')
36
+ Money.parse('1,111,234,567.89').should == Money.new(111123456789, 'USD')
37
+ end
38
+
39
+ it "does not return a price if there is a price range" do
40
+ lambda { Money.parse('$5.95-10.95') }.should raise_error ArgumentError
41
+ lambda { Money.parse('$5.95 - 10.95') }.should raise_error ArgumentError
42
+ lambda { Money.parse('$5.95 - $10.95') }.should raise_error ArgumentError
43
+ end
44
+
45
+ it "does not return a price for completely invalid input" do
46
+ # TODO: shouldn't these throw an error instead of being considered
47
+ # equal to $0.0?
48
+ empty_price = Money.new(0, 'USD')
49
+
50
+ Money.parse(nil).should == empty_price
51
+ Money.parse('hellothere').should == empty_price
52
+ Money.parse('').should == empty_price
53
+ end
54
+
55
+ it "handles negative inputs" do
56
+ five_ninety_five = Money.new(595, 'USD')
57
+
58
+ Money.parse("$-5.95").should == -five_ninety_five
59
+ Money.parse("-$5.95").should == -five_ninety_five
60
+ Money.parse("$5.95-").should == -five_ninety_five
61
+ end
62
+
63
+ it "raises ArgumentError when unable to detect polarity" do
64
+ lambda { Money.parse('-$5.95-') }.should raise_error ArgumentError
65
+ end
66
+ end
67
+
68
+ describe ".from_string" do
69
+ it "converts given amount to cents" do
70
+ Money.from_string("1").should == Money.new(1_00)
71
+ Money.from_string("1").should == Money.new(1_00, "USD")
72
+ Money.from_string("1", "EUR").should == Money.new(1_00, "EUR")
73
+ end
74
+
75
+ it "respects :subunit_to_unit currency property" do
76
+ Money.from_string("1", "USD").should == Money.new(1_00, "USD")
77
+ Money.from_string("1", "TND").should == Money.new(1_000, "TND")
78
+ Money.from_string("1", "CLP").should == Money.new(1, "CLP")
79
+ end
80
+
81
+ it "accepts a currency options" do
82
+ m = Money.from_string("1")
83
+ m.currency.should == Money.default_currency
84
+
85
+ m = Money.from_string("1", Money::Currency.wrap("EUR"))
86
+ m.currency.should == Money::Currency.wrap("EUR")
87
+
88
+ m = Money.from_string("1", "EUR")
89
+ m.currency.should == Money::Currency.wrap("EUR")
90
+ end
91
+ end
92
+
93
+ describe ".from_fixnum" do
94
+ it "converts given amount to cents" do
95
+ Money.from_fixnum(1).should == Money.new(1_00)
96
+ Money.from_fixnum(1).should == Money.new(1_00, "USD")
97
+ Money.from_fixnum(1, "EUR").should == Money.new(1_00, "EUR")
98
+ end
99
+
100
+ it "should respect :subunit_to_unit currency property" do
101
+ Money.from_fixnum(1, "USD").should == Money.new(1_00, "USD")
102
+ Money.from_fixnum(1, "TND").should == Money.new(1_000, "TND")
103
+ Money.from_fixnum(1, "CLP").should == Money.new(1, "CLP")
104
+ end
105
+
106
+ it "accepts a currency options" do
107
+ m = Money.from_fixnum(1)
108
+ m.currency.should == Money.default_currency
109
+
110
+ m = Money.from_fixnum(1, Money::Currency.wrap("EUR"))
111
+ m.currency.should == Money::Currency.wrap("EUR")
112
+
113
+ m = Money.from_fixnum(1, "EUR")
114
+ m.currency.should == Money::Currency.wrap("EUR")
115
+ end
116
+ end
117
+
118
+ describe ".from_float" do
119
+ it "converts given amount to cents" do
120
+ Money.from_float(1.2).should == Money.new(1_20)
121
+ Money.from_float(1.2).should == Money.new(1_20, "USD")
122
+ Money.from_float(1.2, "EUR").should == Money.new(1_20, "EUR")
123
+ end
124
+
125
+ it "respects :subunit_to_unit currency property" do
126
+ Money.from_float(1.2, "USD").should == Money.new(1_20, "USD")
127
+ Money.from_float(1.2, "TND").should == Money.new(1_200, "TND")
128
+ Money.from_float(1.2, "CLP").should == Money.new(1, "CLP")
129
+ end
130
+
131
+ it "accepts a currency options" do
132
+ m = Money.from_float(1.2)
133
+ m.currency.should == Money.default_currency
134
+
135
+ m = Money.from_float(1.2, Money::Currency.wrap("EUR"))
136
+ m.currency.should == Money::Currency.wrap("EUR")
137
+
138
+ m = Money.from_float(1.2, "EUR")
139
+ m.currency.should == Money::Currency.wrap("EUR")
140
+ end
141
+ end
142
+
143
+ describe ".from_bigdecimal" do
144
+ it "converts given amount to cents" do
145
+ Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00)
146
+ Money.from_bigdecimal(BigDecimal.new("1")).should == Money.new(1_00, "USD")
147
+ Money.from_bigdecimal(BigDecimal.new("1"), "EUR").should == Money.new(1_00, "EUR")
148
+ end
149
+
150
+ it "respects :subunit_to_unit currency property" do
151
+ Money.from_bigdecimal(BigDecimal.new("1"), "USD").should == Money.new(1_00, "USD")
152
+ Money.from_bigdecimal(BigDecimal.new("1"), "TND").should == Money.new(1_000, "TND")
153
+ Money.from_bigdecimal(BigDecimal.new("1"), "CLP").should == Money.new(1, "CLP")
154
+ end
155
+
156
+ it "accepts a currency options" do
157
+ m = Money.from_bigdecimal(BigDecimal.new("1"))
158
+ m.currency.should == Money.default_currency
159
+
160
+ m = Money.from_bigdecimal(BigDecimal.new("1"), Money::Currency.wrap("EUR"))
161
+ m.currency.should == Money::Currency.wrap("EUR")
162
+
163
+ m = Money.from_bigdecimal(BigDecimal.new("1"), "EUR")
164
+ m.currency.should == Money::Currency.wrap("EUR")
165
+ end
166
+ end
167
+
168
+ describe ".from_numeric" do
169
+ it "converts given amount to cents" do
170
+ Money.from_numeric(1).should == Money.new(1_00)
171
+ Money.from_numeric(1.0).should == Money.new(1_00)
172
+ Money.from_numeric(BigDecimal.new("1")).should == Money.new(1_00)
173
+ end
174
+
175
+ it "raises ArgumentError with unsupported argument" do
176
+ lambda { Money.from_numeric("100") }.should raise_error(ArgumentError)
177
+ end
178
+
179
+ it "optimizes workload" do
180
+ Money.should_receive(:from_fixnum).with(1, "USD").and_return(Money.new(1_00, "USD"))
181
+ Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
182
+ Money.should_receive(:from_bigdecimal).with(BigDecimal.new("1.0"), "USD").and_return(Money.new(1_00, "USD"))
183
+ Money.from_numeric(1.0, "USD").should == Money.new(1_00, "USD")
184
+ end
185
+
186
+ it "respects :subunit_to_unit currency property" do
187
+ Money.from_numeric(1, "USD").should == Money.new(1_00, "USD")
188
+ Money.from_numeric(1, "TND").should == Money.new(1_000, "TND")
189
+ Money.from_numeric(1, "CLP").should == Money.new(1, "CLP")
190
+ end
191
+
192
+ it "accepts a bank option" do
193
+ Money.from_numeric(1).should == Money.new(1_00)
194
+ Money.from_numeric(1).should == Money.new(1_00, "USD")
195
+ Money.from_numeric(1, "EUR").should == Money.new(1_00, "EUR")
196
+ end
197
+
198
+ it "accepts a currency options" do
199
+ m = Money.from_numeric(1)
200
+ m.currency.should == Money.default_currency
201
+
202
+ m = Money.from_numeric(1, Money::Currency.wrap("EUR"))
203
+ m.currency.should == Money::Currency.wrap("EUR")
204
+
205
+ m = Money.from_numeric(1, "EUR")
206
+ m.currency.should == Money::Currency.wrap("EUR")
207
+ end
208
+ end
209
+
210
+ end
data/spec/money_spec.rb CHANGED
@@ -1,292 +1,312 @@
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
-
74
- specify "#exchange_to exchanges the amount via its exchange bank" do
75
- money = Money.new(100_00, "USD")
76
- 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')))
77
- money.exchange_to("EUR")
78
- end
79
-
80
- specify "#exchange_to exchanges the amount properly" do
81
- money = Money.new(100_00, "USD")
82
- 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')))
83
- money.exchange_to("EUR").should == Money.new(200_00, "EUR")
84
- end
85
-
86
- specify "#hash should return the same value for equal objects" do
87
- Money.new(1_00, :eur).hash.should == Money.new(1_00, :eur).hash
88
- Money.new(2_00, :usd).hash.should == Money.new(2_00, :usd).hash
89
- Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :eur).hash
90
- Money.new(1_00, :eur).hash.should_not == Money.new(1_00, :usd).hash
91
- Money.new(1_00, :eur).hash.should_not == Money.new(2_00, :usd).hash
92
- end
93
-
94
- specify "#hash can be used to return the intersection of Money object arrays" do
95
- intersection = [Money.new(1_00, :eur), Money.new(1_00, :usd)] & [Money.new(1_00, :eur)]
96
- intersection.should == [Money.new(1_00, :eur)]
97
- end
98
-
99
-
100
- specify "Money.to_s works" do
101
- Money.new(10_00).to_s.should == "10.00"
102
- Money.new(400_08).to_s.should == "400.08"
103
- Money.new(-237_43).to_s.should == "-237.43"
104
- end
105
-
106
- specify "Money.to_s should respect :subunit_to_unit currency property" do
107
- Money.new(10_00, "BHD").to_s.should == "1.000"
108
- Money.new(10_00, "CNY").to_s.should == "10.00"
109
- end
110
-
111
- specify "Money.to_s shouldn't have decimal when :subunit_to_unit is 1" do
112
- Money.new(10_00, "CLP").to_s.should == "1000"
113
- end
114
-
115
- specify "Money.to_s should work with :subunit_to_unit == 5" do
116
- Money.new(10_00, "MGA").to_s.should == "200.0"
117
- end
118
-
119
- specify "Money.to_s should respect :decimal_mark" do
120
- Money.new(10_00, "BRL").to_s.should == "10,00"
121
- end
122
-
123
- specify "Money.to_d works" do
124
- decimal = Money.new(10_00).to_d
125
- decimal.should be_instance_of(BigDecimal)
126
- decimal.should == 10.0
127
- end
128
-
129
- specify "Money.to_d should respect :subunit_to_unit currency property" do
130
- decimal = Money.new(10_00, "BHD").to_d
131
- decimal.should be_instance_of(BigDecimal)
132
- decimal.should == 1.0
133
- end
134
-
135
- specify "Money.to_d should work with float :subunit_to_unit currency property" do
136
- money = Money.new(10_00, "BHD")
137
- money.currency.stub(:subunit_to_unit).and_return(1000.0)
138
-
139
- decimal = money.to_d
140
- decimal.should be_instance_of(BigDecimal)
141
- decimal.should == 1.0
142
- end
143
-
144
- specify "Money.to_f works" do
145
- Money.new(10_00).to_f.should == 10.0
146
- end
147
-
148
- specify "Money.to_f should respect :subunit_to_unit currency property" do
149
- Money.new(10_00, "BHD").to_f.should == 1.0
150
- end
151
-
152
- specify "#symbol works as documented" do
153
- currency = Money::Currency.new("EUR")
154
- currency.should_receive(:symbol).and_return("")
155
- Money.empty(currency).symbol.should == ""
156
-
157
- currency = Money::Currency.new("EUR")
158
- currency.should_receive(:symbol).and_return(nil)
159
- Money.empty(currency).symbol.should == "¤"
160
- end
161
-
162
- describe "Money.empty" do
163
- it "Money.empty creates a new Money object of 0 cents" do
164
- Money.empty.should == Money.new(0)
165
- end
166
- end
167
-
168
- describe "Money.ca_dollar" do
169
- it "creates a new Money object of the given value in CAD" do
170
- Money.ca_dollar(50).should == Money.new(50, "CAD")
171
- end
172
- end
173
-
174
- describe "Money.us_dollar" do
175
- it "creates a new Money object of the given value in USD" do
176
- Money.us_dollar(50).should == Money.new(50, "USD")
177
- end
178
- end
179
-
180
- describe "Money.euro" do
181
- it "creates a new Money object of the given value in EUR" do
182
- Money.euro(50).should == Money.new(50, "EUR")
183
- end
184
- end
185
-
186
-
187
- describe "Money.new_with_dollars" do
188
- it "converts given amount to cents" do
189
- Money.new_with_dollars(1).should == Money.new(100)
190
- Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
191
- Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
192
- end
193
-
194
- it "should respect :subunit_to_unit currency property" do
195
- Money.new_with_dollars(1, "USD").should == Money.new(1_00, "USD")
196
- Money.new_with_dollars(1, "TND").should == Money.new(1_000, "TND")
197
- Money.new_with_dollars(1, "CLP").should == Money.new(1, "CLP")
198
- end
199
-
200
- it "should not loose precision" do
201
- Money.new_with_dollars(1234).cents.should == 1234_00
202
- Money.new_with_dollars(100.37).cents.should == 100_37
203
- Money.new_with_dollars(BigDecimal.new('1234')).cents.should == 1234_00
204
- end
205
-
206
- it "accepts a currency options" do
207
- m = Money.new_with_dollars(1)
208
- m.currency.should == Money.default_currency
209
-
210
- m = Money.new_with_dollars(1, Money::Currency.wrap("EUR"))
211
- m.currency.should == Money::Currency.wrap("EUR")
212
-
213
- m = Money.new_with_dollars(1, "EUR")
214
- m.currency.should == Money::Currency.wrap("EUR")
215
- end
216
-
217
- it "accepts a bank options" do
218
- m = Money.new_with_dollars(1)
219
- m.bank.should == Money.default_bank
220
-
221
- m = Money.new_with_dollars(1, "EUR", bank = Object.new)
222
- m.bank.should == bank
223
- end
224
-
225
- it "is associated to the singleton instance of Bank::VariableExchange by default" do
226
- Money.new_with_dollars(0).bank.should be_equal(Money::Bank::VariableExchange.instance)
227
- end
228
- end
229
-
230
- describe "split" do
231
- specify "#split needs at least one party" do
232
- lambda {Money.us_dollar(1).split(0)}.should raise_error(ArgumentError)
233
- lambda {Money.us_dollar(1).split(-1)}.should raise_error(ArgumentError)
234
- end
235
-
236
-
237
- specify "#gives 1 cent to both people if we start with 2" do
238
- Money.us_dollar(2).split(2).should == [Money.us_dollar(1), Money.us_dollar(1)]
239
- end
240
-
241
- specify "#split may distribute no money to some parties if there isnt enough to go around" do
242
- Money.us_dollar(2).split(3).should == [Money.us_dollar(1), Money.us_dollar(1), Money.us_dollar(0)]
243
- end
244
-
245
- specify "#split does not lose pennies" do
246
- Money.us_dollar(5).split(2).should == [Money.us_dollar(3), Money.us_dollar(2)]
247
- end
248
-
249
- specify "#split a dollar" do
250
- moneys = Money.us_dollar(100).split(3)
251
- moneys[0].cents.should == 34
252
- moneys[1].cents.should == 33
253
- moneys[2].cents.should == 33
254
- end
255
- end
256
-
257
- describe "allocation" do
258
- specify "#allocate takes no action when one gets all" do
259
- Money.us_dollar(005).allocate([1.0]).should == [Money.us_dollar(5)]
260
- end
261
-
262
- specify "#allocate keeps currencies intact" do
263
- Money.ca_dollar(005).allocate([1]).should == [Money.ca_dollar(5)]
264
- end
265
-
266
- specify "#allocate does not loose pennies" do
267
- moneys = Money.us_dollar(5).allocate([0.3,0.7])
268
- moneys[0].should == Money.us_dollar(2)
269
- moneys[1].should == Money.us_dollar(3)
270
- end
271
-
272
- specify "#allocate does not loose pennies" do
273
- moneys = Money.us_dollar(100).allocate([0.333,0.333, 0.333])
274
- moneys[0].cents.should == 34
275
- moneys[1].cents.should == 33
276
- moneys[2].cents.should == 33
277
- end
278
-
279
- specify "#allocate requires total to be less then 1" do
280
- lambda { Money.us_dollar(0.05).allocate([0.5,0.6]) }.should raise_error(ArgumentError)
281
- end
282
- end
283
-
284
- describe "Money.add_rate" do
285
- it "saves rate into current bank" do
286
- Money.add_rate("EUR", "USD", 10)
287
- Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
288
- end
289
- end
290
-
291
- end
292
-
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(Money::Bank::VariableExchange.instance)
16
+ end
17
+ end
18
+
19
+ describe ".new_with_dollars" do
20
+ it "converts given amount to cents" do
21
+ Money.new_with_dollars(1).should == Money.new(100)
22
+ Money.new_with_dollars(1, "USD").should == Money.new(100, "USD")
23
+ Money.new_with_dollars(1, "EUR").should == Money.new(100, "EUR")
24
+ end
25
+
26
+ it "respects :subunit_to_unit currency property" do
27
+ Money.new_with_dollars(1, "USD").should == Money.new(1_00, "USD")
28
+ Money.new_with_dollars(1, "TND").should == Money.new(1_000, "TND")
29
+ Money.new_with_dollars(1, "CLP").should == Money.new(1, "CLP")
30
+ end
31
+
32
+ it "does not loose precision" do
33
+ Money.new_with_dollars(1234).cents.should == 1234_00
34
+ Money.new_with_dollars(100.37).cents.should == 100_37
35
+ Money.new_with_dollars(BigDecimal.new('1234')).cents.should == 1234_00
36
+ end
37
+
38
+ it "accepts optional currency" do
39
+ m = Money.new_with_dollars(1)
40
+ m.currency.should == Money.default_currency
41
+
42
+ m = Money.new_with_dollars(1, Money::Currency.wrap("EUR"))
43
+ m.currency.should == Money::Currency.wrap("EUR")
44
+
45
+ m = Money.new_with_dollars(1, "EUR")
46
+ m.currency.should == Money::Currency.wrap("EUR")
47
+ end
48
+
49
+ it "accepts optional bank" do
50
+ m = Money.new_with_dollars(1)
51
+ m.bank.should == Money.default_bank
52
+
53
+ m = Money.new_with_dollars(1, "EUR", bank = Object.new)
54
+ m.bank.should == bank
55
+ end
56
+
57
+ it "is associated to the singleton instance of Bank::VariableExchange by default" do
58
+ Money.new_with_dollars(0).bank.should be(Money::Bank::VariableExchange.instance)
59
+ end
60
+ end
61
+
62
+ describe ".empty" do
63
+ it "creates a new Money object of 0 cents" do
64
+ Money.empty.should == Money.new(0)
65
+ end
66
+ end
67
+
68
+ describe ".ca_dollar" do
69
+ it "creates a new Money object of the given value in CAD" do
70
+ Money.ca_dollar(50).should == Money.new(50, "CAD")
71
+ end
72
+ end
73
+
74
+ describe ".us_dollar" do
75
+ it "creates a new Money object of the given value in USD" do
76
+ Money.us_dollar(50).should == Money.new(50, "USD")
77
+ end
78
+ end
79
+
80
+ describe ".euro" do
81
+ it "creates a new Money object of the given value in EUR" do
82
+ Money.euro(50).should == Money.new(50, "EUR")
83
+ end
84
+ end
85
+
86
+ describe ".add_rate" do
87
+ it "saves rate into current bank" do
88
+ Money.add_rate("EUR", "USD", 10)
89
+ Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
90
+ end
91
+ end
92
+
93
+
94
+ describe "#cents" do
95
+ it "returns the amount of cents" do
96
+ Money.new(1_00).cents.should == 1_00
97
+ Money.new_with_dollars(1).cents.should == 1_00
98
+ end
99
+
100
+ it "stores cents as an integer regardless of what is passed into the constructor" do
101
+ [ Money.new(100), 1.to_money, 1.00.to_money, BigDecimal('1.00').to_money ].each do |m|
102
+ m.cents.should == 100
103
+ m.cents.should be_a(Fixnum)
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "#dollars" do
109
+ it "returns the amount of cents as dollars" do
110
+ Money.new(1_00).dollars.should == 1
111
+ Money.new_with_dollars(1).dollars.should == 1
112
+ end
113
+
114
+ it "respects :subunit_to_unit currency property" do
115
+ Money.new(1_00, "USD").dollars.should == 1
116
+ Money.new(1_000, "TND").dollars.should == 1
117
+ Money.new(1, "CLP").dollars.should == 1
118
+ end
119
+
120
+ it "does not loose precision" do
121
+ Money.new(100_37).dollars.should == 100.37
122
+ Money.new_with_dollars(100.37).dollars.should == 100.37
123
+ end
124
+ end
125
+
126
+ describe "#currency" do
127
+ it "returns the currency object" do
128
+ Money.new(1_00, "USD").currency.should == Money::Currency.new("USD")
129
+ end
130
+ end
131
+
132
+ describe "#currency_as_string" do
133
+ it "returns the iso_code of the currency object" do
134
+ Money.new(1_00, "USD").currency_as_string.should == "USD"
135
+ Money.new(1_00, "EUR").currency_as_string.should == "EUR"
136
+ end
137
+ end
138
+
139
+ describe "#currency_as_string=" do
140
+ it "sets the currency object using the provided string" do
141
+ money = Money.new(100_00, "USD")
142
+ money.currency_as_string = "EUR"
143
+ money.currency.should == Money::Currency.new("EUR")
144
+ money.currency_as_string = "YEN"
145
+ money.currency.should == Money::Currency.new("YEN")
146
+ end
147
+ end
148
+
149
+ describe "#hash=" do
150
+ it "returns the same value for equal objects" do
151
+ Money.new(1_00, "EUR").hash.should == Money.new(1_00, "EUR").hash
152
+ Money.new(2_00, "USD").hash.should == Money.new(2_00, "USD").hash
153
+ Money.new(1_00, "EUR").hash.should_not == Money.new(2_00, "EUR").hash
154
+ Money.new(1_00, "EUR").hash.should_not == Money.new(1_00, "USD").hash
155
+ Money.new(1_00, "EUR").hash.should_not == Money.new(2_00, "USD").hash
156
+ end
157
+
158
+ it "can be used to return the intersection of Money object arrays" do
159
+ intersection = [Money.new(1_00, "EUR"), Money.new(1_00, "USD")] & [Money.new(1_00, "EUR")]
160
+ intersection.should == [Money.new(1_00, "EUR")]
161
+ end
162
+ end
163
+
164
+ describe "#symbol" do
165
+ it "works as documented" do
166
+ currency = Money::Currency.new("EUR")
167
+ currency.should_receive(:symbol).and_return("€")
168
+ Money.empty(currency).symbol.should == "€"
169
+
170
+ currency = Money::Currency.new("EUR")
171
+ currency.should_receive(:symbol).and_return(nil)
172
+ Money.empty(currency).symbol.should == "¤"
173
+ end
174
+ end
175
+
176
+ describe "#to_s" do
177
+ it "works as documented" do
178
+ Money.new(10_00).to_s.should == "10.00"
179
+ Money.new(400_08).to_s.should == "400.08"
180
+ Money.new(-237_43).to_s.should == "-237.43"
181
+ end
182
+
183
+ it "respects :subunit_to_unit currency property" do
184
+ Money.new(10_00, "BHD").to_s.should == "1.000"
185
+ Money.new(10_00, "CNY").to_s.should == "10.00"
186
+ end
187
+
188
+ it "does not have decimal when :subunit_to_unit == 1" do
189
+ Money.new(10_00, "CLP").to_s.should == "1000"
190
+ end
191
+
192
+ it "does not work when :subunit_to_unit == 5" do
193
+ Money.new(10_00, "MGA").to_s.should == "200.0"
194
+ end
195
+
196
+ it "respects :decimal_mark" do
197
+ Money.new(10_00, "BRL").to_s.should == "10,00"
198
+ end
199
+ end
200
+
201
+ describe "#to_d" do
202
+ it "works as documented" do
203
+ decimal = Money.new(10_00).to_d
204
+ decimal.should be_a(BigDecimal)
205
+ decimal.should == 10.0
206
+ end
207
+
208
+ it "respects :subunit_to_unit currency property" do
209
+ decimal = Money.new(10_00, "BHD").to_d
210
+ decimal.should be_a(BigDecimal)
211
+ decimal.should == 1.0
212
+ end
213
+
214
+ it "works with float :subunit_to_unit currency property" do
215
+ money = Money.new(10_00, "BHD")
216
+ money.currency.stub(:subunit_to_unit).and_return(1000.0)
217
+
218
+ decimal = money.to_d
219
+ decimal.should be_a(BigDecimal)
220
+ decimal.should == 1.0
221
+ end
222
+ end
223
+
224
+ describe "#to_f" do
225
+ it "works as documented" do
226
+ Money.new(10_00).to_f.should == 10.0
227
+ end
228
+
229
+ it "respects :subunit_to_unit currency property" do
230
+ Money.new(10_00, "BHD").to_f.should == 1.0
231
+ end
232
+ end
233
+
234
+ describe "#to_money" do
235
+ it "works as documented" do
236
+ money = Money.new(10_00, "DKK")
237
+ money.should == money.to_money
238
+ money.should == money.to_money("DKK")
239
+ money.bank.should_receive(:exchange_with).with(Money.new(10_00, Money::Currency.new("DKK")), Money::Currency.new("EUR")).and_return(Money.new(200_00, Money::Currency.new('EUR')))
240
+ money.to_money("EUR").should == Money.new(200_00, "EUR")
241
+ end
242
+ end
243
+
244
+ describe "#exchange_to" do
245
+ it "exchanges the amount via its exchange bank" do
246
+ money = Money.new(100_00, "USD")
247
+ 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')))
248
+ money.exchange_to("EUR")
249
+ end
250
+
251
+ it "exchanges the amount properly" do
252
+ money = Money.new(100_00, "USD")
253
+ 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')))
254
+ money.exchange_to("EUR").should == Money.new(200_00, "EUR")
255
+ end
256
+ end
257
+
258
+ describe "#allocate" do
259
+ it "takes no action when one gets all" do
260
+ Money.us_dollar(005).allocate([1.0]).should == [Money.us_dollar(5)]
261
+ end
262
+
263
+ it "keeps currencies intact" do
264
+ Money.ca_dollar(005).allocate([1]).should == [Money.ca_dollar(5)]
265
+ end
266
+
267
+ it "does not loose pennies" do
268
+ moneys = Money.us_dollar(5).allocate([0.3, 0.7])
269
+ moneys[0].should == Money.us_dollar(2)
270
+ moneys[1].should == Money.us_dollar(3)
271
+ end
272
+
273
+ it "does not loose pennies" do
274
+ moneys = Money.us_dollar(100).allocate([0.333, 0.333, 0.333])
275
+ moneys[0].cents.should == 34
276
+ moneys[1].cents.should == 33
277
+ moneys[2].cents.should == 33
278
+ end
279
+
280
+ it "requires total to be less then 1" do
281
+ expect { Money.us_dollar(0.05).allocate([0.5, 0.6]) }.to raise_error(ArgumentError)
282
+ end
283
+ end
284
+
285
+ describe "#split" do
286
+ it "needs at least one party" do
287
+ expect { Money.us_dollar(1).split(0) }.to raise_error(ArgumentError)
288
+ expect { Money.us_dollar(1).split(-1) }.to raise_error(ArgumentError)
289
+ end
290
+
291
+ it "gives 1 cent to both people if we start with 2" do
292
+ Money.us_dollar(2).split(2).should == [Money.us_dollar(1), Money.us_dollar(1)]
293
+ end
294
+
295
+ it "may distribute no money to some parties if there isnt enough to go around" do
296
+ Money.us_dollar(2).split(3).should == [Money.us_dollar(1), Money.us_dollar(1), Money.us_dollar(0)]
297
+ end
298
+
299
+ it "does not lose pennies" do
300
+ Money.us_dollar(5).split(2).should == [Money.us_dollar(3), Money.us_dollar(2)]
301
+ end
302
+
303
+ it "splits a dollar" do
304
+ moneys = Money.us_dollar(100).split(3)
305
+ moneys[0].cents.should == 34
306
+ moneys[1].cents.should == 33
307
+ moneys[2].cents.should == 33
308
+ end
309
+ end
310
+
311
+ end
312
+