money 4.0.1 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+