money 6.5.1 → 6.6.0

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.
@@ -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