money 6.5.1 → 6.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,274 +2,256 @@ require 'spec_helper'
2
2
  require 'json'
3
3
  require 'yaml'
4
4
 
5
- describe Money::Bank::VariableExchange do
6
-
7
- describe "#initialize" do
8
- context "without &block" do
9
- let(:bank) {
10
- Money::Bank::VariableExchange.new.tap do |bank|
11
- bank.add_rate('USD', 'EUR', 1.33)
5
+ class Money
6
+ module Bank
7
+ describe VariableExchange do
8
+
9
+ describe "#initialize" do
10
+ context "without &block" do
11
+ let(:bank) {
12
+ VariableExchange.new.tap do |bank|
13
+ bank.add_rate('USD', 'EUR', 1.33)
14
+ end
15
+ }
16
+
17
+ describe '#store' do
18
+ it 'defaults to Memory store' do
19
+ expect(bank.store).to be_a(Money::RatesStore::Memory)
20
+ end
21
+ end
22
+
23
+ describe 'custom store' do
24
+ let(:custom_store) { Object.new }
25
+
26
+ let(:bank) { VariableExchange.new(custom_store) }
27
+
28
+ it 'sets #store to be custom store' do
29
+ expect(bank.store).to eql(custom_store)
30
+ end
31
+ end
32
+
33
+ describe "#exchange_with" do
34
+ it "accepts str" do
35
+ expect { bank.exchange_with(Money.new(100, 'USD'), 'EUR') }.to_not raise_exception
36
+ end
37
+
38
+ it "accepts currency" do
39
+ expect { bank.exchange_with(Money.new(100, 'USD'), Currency.wrap('EUR')) }.to_not raise_exception
40
+ end
41
+
42
+ it "exchanges one currency to another" do
43
+ expect(bank.exchange_with(Money.new(100, 'USD'), 'EUR')).to eq Money.new(133, 'EUR')
44
+ end
45
+
46
+ it "truncates extra digits" do
47
+ expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR')).to eq Money.new(13, 'EUR')
48
+ end
49
+
50
+ it "raises an UnknownCurrency exception when an unknown currency is requested" do
51
+ expect { bank.exchange_with(Money.new(100, 'USD'), 'BBB') }.to raise_exception(Currency::UnknownCurrency)
52
+ end
53
+
54
+ it "raises an UnknownRate exception when an unknown rate is requested" do
55
+ expect { bank.exchange_with(Money.new(100, 'USD'), 'JPY') }.to raise_exception(UnknownRate)
56
+ end
57
+
58
+ #it "rounds the exchanged result down" do
59
+ # bank.add_rate("USD", "EUR", 0.788332676)
60
+ # bank.add_rate("EUR", "YEN", 122.631477)
61
+ # expect(bank.exchange_with(Money.new(10_00, "USD"), "EUR")).to eq Money.new(788, "EUR")
62
+ # expect(bank.exchange_with(Money.new(500_00, "EUR"), "YEN")).to eq Money.new(6131573, "YEN")
63
+ #end
64
+
65
+ it "accepts a custom truncation method" do
66
+ proc = Proc.new { |n| n.ceil }
67
+ expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR', &proc)).to eq Money.new(14, 'EUR')
68
+ end
69
+
70
+ it 'works with big numbers' do
71
+ amount = 10**20
72
+ expect(bank.exchange_with(Money.usd(amount), :EUR)).to eq Money.eur(1.33 * amount)
73
+ end
74
+ end
12
75
  end
13
- }
14
76
 
15
- describe "#exchange_with" do
16
- it "accepts str" do
17
- expect { bank.exchange_with(Money.new(100, 'USD'), 'EUR') }.to_not raise_exception
77
+ context "with &block" do
78
+ let(:bank) {
79
+ proc = Proc.new { |n| n.ceil }
80
+ VariableExchange.new(&proc).tap do |bank|
81
+ bank.add_rate('USD', 'EUR', 1.33)
82
+ end
83
+ }
84
+
85
+ describe "#exchange_with" do
86
+ it "uses the stored truncation method" do
87
+ expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR')).to eq Money.new(14, 'EUR')
88
+ end
89
+
90
+ it "accepts a custom truncation method" do
91
+ proc = Proc.new { |n| n.ceil + 1 }
92
+ expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR', &proc)).to eq Money.new(15, 'EUR')
93
+ end
94
+ end
18
95
  end
96
+ end
19
97
 
20
- it "accepts currency" do
21
- expect { bank.exchange_with(Money.new(100, 'USD'), Money::Currency.wrap('EUR')) }.to_not raise_exception
98
+ describe "#add_rate" do
99
+ it 'delegates to store#add_rate' do
100
+ expect(subject.store).to receive(:add_rate).with('USD', 'EUR', 1.25).and_return 1.25
101
+ expect(subject.add_rate('USD', 'EUR', 1.25)).to eql 1.25
22
102
  end
23
103
 
24
- it "exchanges one currency to another" do
25
- expect(bank.exchange_with(Money.new(100, 'USD'), 'EUR')).to eq Money.new(133, 'EUR')
26
- end
104
+ it "adds rates with correct ISO codes" do
105
+ expect(subject.store).to receive(:add_rate).with('USD', 'EUR', 0.788332676)
106
+ subject.add_rate("USD", "EUR", 0.788332676)
27
107
 
28
- it "truncates extra digits" do
29
- expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR')).to eq Money.new(13, 'EUR')
108
+ expect(subject.store).to receive(:add_rate).with('EUR', 'JPY', 122.631477)
109
+ subject.add_rate("EUR", "YEN", 122.631477)
30
110
  end
31
111
 
32
- it "raises an UnknownCurrency exception when an unknown currency is requested" do
33
- expect { bank.exchange_with(Money.new(100, 'USD'), 'BBB') }.to raise_exception(Money::Currency::UnknownCurrency)
112
+ it "treats currency names case-insensitively" do
113
+ subject.add_rate("usd", "eur", 1)
114
+ expect(subject.get_rate('USD', 'EUR')).to eq 1
34
115
  end
116
+ end
35
117
 
36
- it "raises an UnknownRate exception when an unknown rate is requested" do
37
- expect { bank.exchange_with(Money.new(100, 'USD'), 'JPY') }.to raise_exception(Money::Bank::UnknownRate)
118
+ describe "#set_rate" do
119
+ it 'delegates to store#add_rate' do
120
+ expect(subject.store).to receive(:add_rate).with('USD', 'EUR', 1.25).and_return 1.25
121
+ expect(subject.set_rate('USD', 'EUR', 1.25)).to eql 1.25
38
122
  end
39
123
 
40
- #it "rounds the exchanged result down" do
41
- # bank.add_rate("USD", "EUR", 0.788332676)
42
- # bank.add_rate("EUR", "YEN", 122.631477)
43
- # expect(bank.exchange_with(Money.new(10_00, "USD"), "EUR")).to eq Money.new(788, "EUR")
44
- # expect(bank.exchange_with(Money.new(500_00, "EUR"), "YEN")).to eq Money.new(6131573, "YEN")
45
- #end
124
+ it "sets a rate" do
125
+ subject.set_rate('USD', 'EUR', 1.25)
126
+ expect(subject.store.get_rate('USD', 'EUR')).to eq 1.25
127
+ end
46
128
 
47
- it "accepts a custom truncation method" do
48
- proc = Proc.new { |n| n.ceil }
49
- expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR', &proc)).to eq Money.new(14, 'EUR')
129
+ it "raises an UnknownCurrency exception when an unknown currency is passed" do
130
+ expect { subject.set_rate('AAA', 'BBB', 1.25) }.to raise_exception(Currency::UnknownCurrency)
50
131
  end
51
132
  end
52
- end
53
133
 
54
- context "with &block" do
55
- let(:bank) {
56
- proc = Proc.new { |n| n.ceil }
57
- Money::Bank::VariableExchange.new(&proc).tap do |bank|
58
- bank.add_rate('USD', 'EUR', 1.33)
134
+ describe "#get_rate" do
135
+ it "returns a rate" do
136
+ subject.set_rate('USD', 'EUR', 1.25)
137
+ expect(subject.get_rate('USD', 'EUR')).to eq 1.25
59
138
  end
60
- }
61
139
 
62
- describe "#exchange_with" do
63
- it "uses the stored truncation method" do
64
- expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR')).to eq Money.new(14, 'EUR')
140
+ it "raises an UnknownCurrency exception when an unknown currency is passed" do
141
+ expect { subject.get_rate('AAA', 'BBB') }.to raise_exception(Currency::UnknownCurrency)
65
142
  end
66
143
 
67
- it "accepts a custom truncation method" do
68
- proc = Proc.new { |n| n.ceil + 1 }
69
- expect(bank.exchange_with(Money.new(10, 'USD'), 'EUR', &proc)).to eq Money.new(15, 'EUR')
144
+ it "delegates options to store, options are a no-op" do
145
+ expect(subject.store).to receive(:get_rate).with('USD', 'EUR')
146
+ subject.get_rate('USD', 'EUR', :without_mutex => true)
70
147
  end
71
148
  end
72
- end
73
- end
74
149
 
75
- describe "#add_rate" do
76
- it "adds rates correctly" do
77
- subject.add_rate("USD", "EUR", 0.788332676)
78
- subject.add_rate("EUR", "YEN", 122.631477)
150
+ describe "#export_rates" do
151
+ before :each do
152
+ subject.set_rate('USD', 'EUR', 1.25)
153
+ subject.set_rate('USD', 'JPY', 2.55)
79
154
 
80
- expect(subject.instance_variable_get(:@rates)['USD_TO_EUR']).to eq 0.788332676
81
- expect(subject.instance_variable_get(:@rates)['EUR_TO_JPY']).to eq 122.631477
82
- end
83
-
84
- it "treats currency names case-insensitively" do
85
- subject.add_rate("usd", "eur", 1)
86
- expect(subject.instance_variable_get(:@rates)['USD_TO_EUR']).to eq 1
87
- end
88
- end
89
-
90
- describe "#set_rate" do
91
- it "sets a rate" do
92
- subject.set_rate('USD', 'EUR', 1.25)
93
- expect(subject.instance_variable_get(:@rates)['USD_TO_EUR']).to eq 1.25
94
- end
95
-
96
- it "raises an UnknownCurrency exception when an unknown currency is passed" do
97
- expect { subject.set_rate('AAA', 'BBB', 1.25) }.to raise_exception(Money::Currency::UnknownCurrency)
98
- end
99
-
100
- it "uses a mutex by default" do
101
- expect(subject.instance_variable_get(:@mutex)).to receive(:synchronize)
102
- subject.set_rate('USD', 'EUR', 1.25)
103
- end
104
-
105
- it "doesn't use mutex if requested not to" do
106
- expect(subject.instance_variable_get(:@mutex)).not_to receive(:synchronize)
107
- subject.set_rate('USD', 'EUR', 1.25, :without_mutex => true)
108
- end
109
- end
110
-
111
- describe "#get_rate" do
112
- it "returns a rate" do
113
- subject.set_rate('USD', 'EUR', 1.25)
114
- expect(subject.get_rate('USD', 'EUR')).to eq 1.25
115
- end
155
+ @rates = { "USD_TO_EUR" => 1.25, "USD_TO_JPY" => 2.55 }
156
+ end
116
157
 
117
- it "raises an UnknownCurrency exception when an unknown currency is passed" do
118
- expect { subject.get_rate('AAA', 'BBB') }.to raise_exception(Money::Currency::UnknownCurrency)
119
- end
158
+ context "with format == :json" do
159
+ it "should return rates formatted as json" do
160
+ json = subject.export_rates(:json)
161
+ expect(JSON.load(json)).to eq @rates
162
+ end
163
+ end
120
164
 
121
- it "uses a mutex by default" do
122
- expect(subject.instance_variable_get(:@mutex)).to receive(:synchronize)
123
- subject.get_rate('USD', 'EUR')
124
- end
165
+ context "with format == :ruby" do
166
+ it "should return rates formatted as ruby objects" do
167
+ expect(Marshal.load(subject.export_rates(:ruby))).to eq @rates
168
+ end
169
+ end
125
170
 
126
- it "doesn't use mutex if requested not to" do
127
- expect(subject.instance_variable_get(:@mutex)).not_to receive(:synchronize)
128
- subject.get_rate('USD', 'EUR', :without_mutex => true)
129
- end
130
- end
171
+ context "with format == :yaml" do
172
+ it "should return rates formatted as yaml" do
173
+ yaml = subject.export_rates(:yaml)
174
+ expect(YAML.load(yaml)).to eq @rates
175
+ end
176
+ end
131
177
 
132
- describe "#export_rates" do
133
- before :each do
134
- subject.set_rate('USD', 'EUR', 1.25)
135
- subject.set_rate('USD', 'JPY', 2.55)
178
+ context "with unknown format" do
179
+ it "raises Money::Bank::UnknownRateFormat" do
180
+ expect { subject.export_rates(:foo)}.to raise_error UnknownRateFormat
181
+ end
182
+ end
136
183
 
137
- @rates = { "USD_TO_EUR" => 1.25, "USD_TO_JPY" => 2.55 }
138
- end
184
+ context "with :file provided" do
185
+ it "writes rates to file" do
186
+ f = double('IO')
187
+ expect(File).to receive(:open).with('null', 'w').and_yield(f)
188
+ expect(f).to receive(:write).with(JSON.dump(@rates))
139
189
 
140
- context "with format == :json" do
141
- it "should return rates formatted as json" do
142
- json = subject.export_rates(:json)
143
- expect(JSON.load(json)).to eq @rates
144
- end
145
- end
190
+ subject.export_rates(:json, 'null')
191
+ end
192
+ end
146
193
 
147
- context "with format == :ruby" do
148
- it "should return rates formatted as ruby objects" do
149
- expect(Marshal.load(subject.export_rates(:ruby))).to eq @rates
150
- end
151
- end
194
+ it "delegates execution to store, options are a no-op" do
195
+ expect(subject.store).to receive(:transaction)
196
+ subject.export_rates(:yaml, nil, :foo => 1)
197
+ end
152
198
 
153
- context "with format == :yaml" do
154
- it "should return rates formatted as yaml" do
155
- yaml = subject.export_rates(:yaml)
156
- expect(YAML.load(yaml)).to eq @rates
157
199
  end
158
- end
159
200
 
160
- context "with unknown format" do
161
- it "raises Money::Bank::UnknownRateFormat" do
162
- expect { subject.export_rates(:foo)}.to raise_error Money::Bank::UnknownRateFormat
163
- end
164
- end
201
+ describe "#import_rates" do
202
+ context "with format == :json" do
203
+ it "loads the rates provided" do
204
+ s = '{"USD_TO_EUR":1.25,"USD_TO_JPY":2.55}'
205
+ subject.import_rates(:json, s)
206
+ expect(subject.get_rate('USD', 'EUR')).to eq 1.25
207
+ expect(subject.get_rate('USD', 'JPY')).to eq 2.55
208
+ end
209
+ end
165
210
 
166
- context "with :file provided" do
167
- it "writes rates to file" do
168
- f = double('IO')
169
- expect(File).to receive(:open).with('null', 'w').and_yield(f)
170
- expect(f).to receive(:write).with(JSON.dump(@rates))
211
+ context "with format == :ruby" do
212
+ it "loads the rates provided" do
213
+ s = Marshal.dump({"USD_TO_EUR"=>1.25,"USD_TO_JPY"=>2.55})
214
+ subject.import_rates(:ruby, s)
215
+ expect(subject.get_rate('USD', 'EUR')).to eq 1.25
216
+ expect(subject.get_rate('USD', 'JPY')).to eq 2.55
217
+ end
218
+ end
171
219
 
172
- subject.export_rates(:json, 'null')
173
- end
174
- end
220
+ context "with format == :yaml" do
221
+ it "loads the rates provided" do
222
+ s = "--- \nUSD_TO_EUR: 1.25\nUSD_TO_JPY: 2.55\n"
223
+ subject.import_rates(:yaml, s)
224
+ expect(subject.get_rate('USD', 'EUR')).to eq 1.25
225
+ expect(subject.get_rate('USD', 'JPY')).to eq 2.55
226
+ end
227
+ end
175
228
 
176
- it "uses a mutex by default" do
177
- expect(subject.instance_variable_get(:@mutex)).to receive(:synchronize)
178
- subject.export_rates(:yaml)
179
- end
229
+ context "with unknown format" do
230
+ it "raises Money::Bank::UnknownRateFormat" do
231
+ expect { subject.import_rates(:foo, "")}.to raise_error UnknownRateFormat
232
+ end
233
+ end
180
234
 
181
- it "doesn't use mutex if requested not to" do
182
- expect(subject.instance_variable_get(:@mutex)).not_to receive(:synchronize)
183
- subject.export_rates(:yaml, nil, :without_mutex => true)
184
- end
185
- end
235
+ it "delegates execution to store#transaction" do
236
+ expect(subject.store).to receive(:transaction)
237
+ s = "--- \nUSD_TO_EUR: 1.25\nUSD_TO_JPY: 2.55\n"
238
+ subject.import_rates(:yaml, s, :foo => 1)
239
+ end
186
240
 
187
- describe "#import_rates" do
188
- context "with format == :json" do
189
- it "loads the rates provided" do
190
- s = '{"USD_TO_EUR":1.25,"USD_TO_JPY":2.55}'
191
- subject.import_rates(:json, s)
192
- expect(subject.get_rate('USD', 'EUR')).to eq 1.25
193
- expect(subject.get_rate('USD', 'JPY')).to eq 2.55
194
241
  end
195
- end
196
242
 
197
- context "with format == :ruby" do
198
- it "loads the rates provided" do
199
- s = Marshal.dump({"USD_TO_EUR"=>1.25,"USD_TO_JPY"=>2.55})
200
- subject.import_rates(:ruby, s)
201
- expect(subject.get_rate('USD', 'EUR')).to eq 1.25
202
- expect(subject.get_rate('USD', 'JPY')).to eq 2.55
203
- end
204
- end
243
+ describe "#marshal_dump" do
244
+ it "does not raise an error" do
245
+ expect { Marshal.dump(subject) }.to_not raise_error
246
+ end
205
247
 
206
- context "with format == :yaml" do
207
- it "loads the rates provided" do
208
- s = "--- \nUSD_TO_EUR: 1.25\nUSD_TO_JPY: 2.55\n"
209
- subject.import_rates(:yaml, s)
210
- expect(subject.get_rate('USD', 'EUR')).to eq 1.25
211
- expect(subject.get_rate('USD', 'JPY')).to eq 2.55
212
- end
213
- end
248
+ it "works with Marshal.load" do
249
+ bank = Marshal.load(Marshal.dump(subject))
214
250
 
215
- context "with unknown format" do
216
- it "raises Money::Bank::UnknownRateFormat" do
217
- expect { subject.import_rates(:foo, "")}.to raise_error Money::Bank::UnknownRateFormat
251
+ expect(bank.rates).to eq subject.rates
252
+ expect(bank.rounding_method).to eq subject.rounding_method
253
+ end
218
254
  end
219
255
  end
220
-
221
- it "uses a mutex by default" do
222
- expect(subject.instance_variable_get(:@mutex)).to receive(:synchronize)
223
- s = "--- \nUSD_TO_EUR: 1.25\nUSD_TO_JPY: 2.55\n"
224
- subject.import_rates(:yaml, s)
225
- end
226
-
227
- it "doesn't use mutex if requested not to" do
228
- expect(subject.instance_variable_get(:@mutex)).not_to receive(:synchronize)
229
- s = "--- \nUSD_TO_EUR: 1.25\nUSD_TO_JPY: 2.55\n"
230
- subject.import_rates(:yaml, s, :without_mutex => true)
231
- end
232
- end
233
-
234
- describe "#rate_key_for" do
235
- it "accepts str/str" do
236
- expect { subject.send(:rate_key_for, 'USD', 'EUR')}.to_not raise_exception
237
- end
238
-
239
- it "accepts currency/str" do
240
- expect { subject.send(:rate_key_for, Money::Currency.wrap('USD'), 'EUR')}.to_not raise_exception
241
- end
242
-
243
- it "accepts str/currency" do
244
- expect { subject.send(:rate_key_for, 'USD', Money::Currency.wrap('EUR'))}.to_not raise_exception
245
- end
246
-
247
- it "accepts currency/currency" do
248
- expect { subject.send(:rate_key_for, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR'))}.to_not raise_exception
249
- end
250
-
251
- it "returns a hashkey based on the passed arguments" do
252
- expect(subject.send(:rate_key_for, 'USD', 'EUR')).to eq 'USD_TO_EUR'
253
- expect(subject.send(:rate_key_for, Money::Currency.wrap('USD'), 'EUR')).to eq 'USD_TO_EUR'
254
- expect(subject.send(:rate_key_for, 'USD', Money::Currency.wrap('EUR'))).to eq 'USD_TO_EUR'
255
- expect(subject.send(:rate_key_for, Money::Currency.wrap('USD'), Money::Currency.wrap('EUR'))).to eq 'USD_TO_EUR'
256
- end
257
-
258
- it "raises a Money::Currency::UnknownCurrency exception when an unknown currency is passed" do
259
- expect { subject.send(:rate_key_for, 'AAA', 'BBB')}.to raise_exception(Money::Currency::UnknownCurrency)
260
- end
261
- end
262
-
263
- describe "#marshal_dump" do
264
- it "does not raise an error" do
265
- expect { Marshal.dump(subject) }.to_not raise_error
266
- end
267
-
268
- it "works with Marshal.load" do
269
- bank = Marshal.load(Marshal.dump(subject))
270
-
271
- expect(bank.rates).to eq subject.rates
272
- expect(bank.rounding_method).to eq subject.rounding_method
273
- end
274
256
  end
275
257
  end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Money::Currency::Loader do
5
+ class CurrencyLoader
6
+ include Money::Currency::Loader
7
+ end
8
+
9
+ let(:loader) { CurrencyLoader.new }
10
+
11
+ it "returns a currency table hash" do
12
+ expect(loader.load_currencies).to be_a Hash
13
+ end
14
+
15
+ it "parse currency_iso.json & currency_non_iso.json & currency_backwards_compatible.json" do
16
+ expect(loader).to receive(:parse_currency_file).exactly(3).times.and_return({})
17
+
18
+ loader.load_currencies
19
+ end
20
+ end