money-open-exchange-rates 0.7.0 → 1.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +4 -0
- data/History.md +123 -0
- data/LICENSE +1 -1
- data/README.md +170 -29
- data/lib/money/bank/open_exchange_rates_bank.rb +194 -70
- data/lib/open_exchange_rates_bank/version.rb +1 -1
- data/test/data/access_restricted_error.json +6 -0
- data/test/data/app_id_inactive.json +1 -0
- data/test/integration/Gemfile +4 -0
- data/test/integration/Gemfile.lock +11 -13
- data/test/integration/api.rb +6 -1
- data/test/open_exchange_rates_bank_test.rb +285 -134
- data/test/test_helper.rb +10 -2
- metadata +41 -34
@@ -1,31 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
4
|
|
5
|
+
# rubocop:disable Metrics/BlockLength
|
3
6
|
describe Money::Bank::OpenExchangeRatesBank do
|
4
7
|
subject { Money::Bank::OpenExchangeRatesBank.new }
|
5
8
|
let(:oer_url) { Money::Bank::OpenExchangeRatesBank::OER_URL }
|
6
9
|
let(:oer_historical_url) do
|
7
10
|
Money::Bank::OpenExchangeRatesBank::OER_HISTORICAL_URL
|
8
11
|
end
|
9
|
-
let(:
|
10
|
-
|
11
|
-
Money::Bank::OpenExchangeRatesBank::SECURE_OER_HISTORICAL_URL
|
12
|
+
let(:default_source) do
|
13
|
+
Money::Bank::OpenExchangeRatesBank::OE_SOURCE
|
12
14
|
end
|
13
15
|
|
14
16
|
let(:temp_cache_path) do
|
15
17
|
data_file('tmp.json')
|
16
18
|
end
|
19
|
+
let(:temp_cache_pathname) do
|
20
|
+
Pathname.new('test/data/tmp.json')
|
21
|
+
end
|
17
22
|
let(:oer_latest_path) do
|
18
23
|
data_file('latest.json')
|
19
24
|
end
|
20
25
|
let(:oer_historical_path) do
|
21
26
|
data_file('2015-01-01.json')
|
22
27
|
end
|
28
|
+
let(:oer_access_restricted_error_path) do
|
29
|
+
data_file('access_restricted_error.json')
|
30
|
+
end
|
31
|
+
let(:oer_app_id_inactive_error_path) do
|
32
|
+
data_file('app_id_inactive.json')
|
33
|
+
end
|
23
34
|
|
24
35
|
describe 'exchange' do
|
25
36
|
before do
|
26
37
|
add_to_webmock(subject)
|
27
38
|
subject.cache = temp_cache_path
|
28
|
-
subject.
|
39
|
+
subject.update_rates
|
29
40
|
end
|
30
41
|
|
31
42
|
after do
|
@@ -35,12 +46,12 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
35
46
|
describe 'without rates' do
|
36
47
|
it 'able to exchange a money to its own currency even without rates' do
|
37
48
|
money = Money.new(0, 'USD')
|
38
|
-
subject.exchange_with(money, 'USD').must_equal money
|
49
|
+
_(subject.exchange_with(money, 'USD')).must_equal money
|
39
50
|
end
|
40
51
|
|
41
52
|
it "raise if it can't find an exchange rate" do
|
42
53
|
money = Money.new(0, 'USD')
|
43
|
-
proc { subject.exchange_with(money, 'SSP') }
|
54
|
+
_(proc { subject.exchange_with(money, 'SSP') })
|
44
55
|
.must_raise Money::Bank::UnknownRate
|
45
56
|
end
|
46
57
|
end
|
@@ -52,22 +63,33 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
52
63
|
|
53
64
|
it 'should be able to exchange money from USD to a known exchange rate' do
|
54
65
|
money = Money.new(100, 'USD')
|
55
|
-
subject.exchange_with(money, 'BBD').must_equal Money.new(200, 'BBD')
|
66
|
+
_(subject.exchange_with(money, 'BBD')).must_equal Money.new(200, 'BBD')
|
56
67
|
end
|
57
68
|
|
58
69
|
it 'should be able to exchange money from a known exchange rate to USD' do
|
59
70
|
money = Money.new(200, 'BBD')
|
60
|
-
subject.exchange_with(money, 'USD').must_equal Money.new(100, 'USD')
|
71
|
+
_(subject.exchange_with(money, 'USD')).must_equal Money.new(100, 'USD')
|
61
72
|
end
|
62
73
|
|
63
74
|
it 'should be able to exchange money when direct rate is unknown' do
|
64
75
|
money = Money.new(100, 'BBD')
|
65
|
-
subject.exchange_with(money, 'BMD').must_equal Money.new(50, 'BMD')
|
76
|
+
_(subject.exchange_with(money, 'BMD')).must_equal Money.new(50, 'BMD')
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should be able to handle non integer rates' do
|
80
|
+
money = Money.new(100, 'BBD')
|
81
|
+
_(subject.exchange_with(money, 'TJS')).must_equal Money.new(250, 'TJS')
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should raise if it can't find an currency" do
|
85
|
+
money = Money.new(0, 'USD')
|
86
|
+
_(proc { subject.exchange_with(money, 'PLP') })
|
87
|
+
.must_raise Money::Currency::UnknownCurrency
|
66
88
|
end
|
67
89
|
|
68
90
|
it "should raise if it can't find an exchange rate" do
|
69
91
|
money = Money.new(0, 'USD')
|
70
|
-
proc { subject.exchange_with(money, 'SSP') }
|
92
|
+
_(proc { subject.exchange_with(money, 'SSP') })
|
71
93
|
.must_raise Money::Bank::UnknownRate
|
72
94
|
end
|
73
95
|
end
|
@@ -80,10 +102,25 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
80
102
|
subject.update_rates
|
81
103
|
end
|
82
104
|
|
105
|
+
it 'should raise AccessRestricted error when restricted by oer' do
|
106
|
+
subject.cache = nil
|
107
|
+
filepath = oer_access_restricted_error_path
|
108
|
+
subject.stubs(:api_response).returns File.read(filepath)
|
109
|
+
_(proc { subject.update_rates }).must_raise Money::Bank::AccessRestricted
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should raise AppIdInactive error when restricted by oer' do
|
113
|
+
subject.cache = nil
|
114
|
+
filepath = oer_app_id_inactive_error_path
|
115
|
+
subject.stubs(:api_response).returns File.read(filepath)
|
116
|
+
_(proc { subject.update_rates }).must_raise Money::Bank::AppIdInactive
|
117
|
+
end
|
118
|
+
|
83
119
|
it 'should update itself with exchange rates from OpenExchangeRates' do
|
84
120
|
subject.oer_rates.keys.each do |currency|
|
85
121
|
next unless Money::Currency.find(currency)
|
86
|
-
|
122
|
+
|
123
|
+
_(subject.get_rate('USD', currency)).must_be :>, 0
|
87
124
|
end
|
88
125
|
end
|
89
126
|
|
@@ -101,7 +138,7 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
101
138
|
Money::Currency.register(wtf)
|
102
139
|
subject.add_rate('USD', 'WTF', 2)
|
103
140
|
subject.add_rate('WTF', 'USD', 2)
|
104
|
-
subject.exchange_with(5000.to_money('WTF'), 'USD').cents.wont_equal 0
|
141
|
+
_(subject.exchange_with(5000.to_money('WTF'), 'USD').cents).wont_equal 0
|
105
142
|
end
|
106
143
|
|
107
144
|
# in response to #4
|
@@ -120,22 +157,51 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
120
157
|
rate = 13.7603
|
121
158
|
subject.add_rate('USD', 'BTC', 1 / 13.7603)
|
122
159
|
subject.add_rate('BTC', 'USD', rate)
|
123
|
-
subject.exchange_with(100.to_money('BTC'), 'USD').cents
|
160
|
+
_(subject.exchange_with(100.to_money('BTC'), 'USD').cents)
|
161
|
+
.must_equal 137_603
|
124
162
|
end
|
125
163
|
end
|
126
164
|
|
127
165
|
describe 'App ID' do
|
166
|
+
describe 'nil' do
|
167
|
+
before do
|
168
|
+
subject.app_id = nil
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should raise an error if no App ID is set' do
|
172
|
+
_(proc { subject.update_rates }).must_raise Money::Bank::NoAppId
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'empty' do
|
177
|
+
before do
|
178
|
+
subject.app_id = ''
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should raise an error if no App ID is set' do
|
182
|
+
_(proc { subject.update_rates }).must_raise Money::Bank::NoAppId
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '#cache' do
|
128
188
|
before do
|
129
|
-
subject.
|
189
|
+
subject.app_id = TEST_APP_ID
|
130
190
|
end
|
131
191
|
|
132
|
-
it '
|
133
|
-
|
192
|
+
it 'support Pathname object' do
|
193
|
+
subject.cache = temp_cache_pathname
|
194
|
+
subject.stubs(:api_response).returns File.read(oer_latest_path)
|
195
|
+
subject.update_rates
|
196
|
+
subject.expects(:read_from_url).never
|
197
|
+
subject.update_rates
|
134
198
|
end
|
135
199
|
|
136
|
-
|
137
|
-
|
138
|
-
|
200
|
+
it 'raise InvalidCache when the arg is not known' do
|
201
|
+
subject.cache = Array
|
202
|
+
add_to_webmock(subject)
|
203
|
+
_(proc { subject.update_rates }).must_raise Money::Bank::InvalidCache
|
204
|
+
end
|
139
205
|
end
|
140
206
|
|
141
207
|
describe 'no cache' do
|
@@ -145,12 +211,9 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
145
211
|
end
|
146
212
|
|
147
213
|
it 'should get from url' do
|
214
|
+
subject.expects(:save_cache).never
|
148
215
|
subject.update_rates
|
149
|
-
subject.oer_rates.wont_be_empty
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'should raise an error if invalid path is given to save_rates' do
|
153
|
-
proc { subject.save_rates }.must_raise Money::Bank::InvalidCache
|
216
|
+
_(subject.oer_rates).wont_be_empty
|
154
217
|
end
|
155
218
|
end
|
156
219
|
|
@@ -158,70 +221,36 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
158
221
|
before do
|
159
222
|
subject.app_id = TEST_APP_ID
|
160
223
|
end
|
224
|
+
let(:default_options) do
|
225
|
+
'&show_alternative=false&prettyprint=true'
|
226
|
+
end
|
227
|
+
let(:source_url) do
|
228
|
+
"#{oer_url}#{subject.date}?app_id=#{TEST_APP_ID}#{default_options}"
|
229
|
+
end
|
161
230
|
|
162
231
|
describe 'historical' do
|
163
232
|
before do
|
164
233
|
subject.date = '2015-01-01'
|
165
234
|
end
|
166
235
|
|
167
|
-
|
168
|
-
"#{oer_historical_url}#{subject.date}.json?app_id=#{TEST_APP_ID}"
|
169
|
-
|
170
|
-
|
171
|
-
def historical_secure_url
|
172
|
-
"#{oer_historical_secure_url}#{subject.date}.json?app_id=#{TEST_APP_ID}"
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'should use the non-secure http url if secure_connection is nil' do
|
176
|
-
subject.secure_connection = nil
|
177
|
-
subject.source_url.must_equal historical_url
|
178
|
-
subject.source_url.must_include 'http://'
|
179
|
-
subject.source_url.must_include "/api/historical/#{subject.date}.json"
|
180
|
-
end
|
181
|
-
|
182
|
-
it 'should use the non-secure http url if secure_connection is false' do
|
183
|
-
subject.secure_connection = false
|
184
|
-
subject.source_url.must_equal historical_url
|
185
|
-
subject.source_url.must_include 'http://'
|
186
|
-
subject.source_url.must_include "/api/historical/#{subject.date}.json"
|
236
|
+
let(:historical_url) do
|
237
|
+
"#{oer_historical_url}#{subject.date}.json?app_id=#{TEST_APP_ID}" \
|
238
|
+
"#{default_options}"
|
187
239
|
end
|
188
240
|
|
189
|
-
it 'should use the secure https url
|
190
|
-
subject.
|
191
|
-
subject.source_url.
|
192
|
-
subject.
|
193
|
-
subject.source_url.must_include
|
241
|
+
it 'should use the secure https url' do
|
242
|
+
_(subject.source_url).must_equal historical_url
|
243
|
+
_(subject.source_url).must_include 'https://'
|
244
|
+
exp_url = "/api/historical/#{subject.date}.json"
|
245
|
+
_(subject.source_url).must_include exp_url
|
194
246
|
end
|
195
247
|
end
|
196
248
|
|
197
249
|
describe 'latest' do
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
def source_secure_url
|
203
|
-
"#{oer_secure_url}?app_id=#{TEST_APP_ID}"
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'should use the non-secure http url if secure_connection is nil' do
|
207
|
-
subject.secure_connection = nil
|
208
|
-
subject.source_url.must_equal source_url
|
209
|
-
subject.source_url.must_include 'http://'
|
210
|
-
subject.source_url.must_include '/api/latest.json'
|
211
|
-
end
|
212
|
-
|
213
|
-
it 'should use the non-secure http url if secure_connection is false' do
|
214
|
-
subject.secure_connection = false
|
215
|
-
subject.source_url.must_equal source_url
|
216
|
-
subject.source_url.must_include 'http://'
|
217
|
-
subject.source_url.must_include '/api/latest.json'
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'should use the secure https url if secure_connection is true' do
|
221
|
-
subject.secure_connection = true
|
222
|
-
subject.source_url.must_equal source_secure_url
|
223
|
-
subject.source_url.must_include 'https://'
|
224
|
-
subject.source_url.must_include '/api/latest.json'
|
250
|
+
it 'should use the secure https url' do
|
251
|
+
_(subject.source_url).must_equal source_url
|
252
|
+
_(subject.source_url).must_include 'https://'
|
253
|
+
_(subject.source_url).must_include '/api/latest.json'
|
225
254
|
end
|
226
255
|
end
|
227
256
|
end
|
@@ -232,48 +261,43 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
232
261
|
add_to_webmock(subject)
|
233
262
|
end
|
234
263
|
|
235
|
-
it 'should
|
236
|
-
subject.update_rates
|
237
|
-
subject.oer_rates.wont_be_empty
|
238
|
-
end
|
239
|
-
|
240
|
-
it 'should raise an error if invalid path is given to save_rates' do
|
241
|
-
proc { subject.save_rates }.must_raise Money::Bank::InvalidCache
|
264
|
+
it 'should raise an error if invalid path is given to update_rates' do
|
265
|
+
_(proc { subject.update_rates }).must_raise Money::Bank::InvalidCache
|
242
266
|
end
|
243
267
|
end
|
244
268
|
|
245
269
|
describe 'using proc for cache' do
|
246
270
|
before do
|
247
271
|
@global_rates = nil
|
248
|
-
subject.cache = proc
|
272
|
+
subject.cache = proc do |v|
|
249
273
|
if v
|
250
274
|
@global_rates = v
|
251
275
|
else
|
252
276
|
@global_rates
|
253
277
|
end
|
254
|
-
|
278
|
+
end
|
255
279
|
add_to_webmock(subject)
|
280
|
+
subject.update_rates
|
256
281
|
end
|
257
282
|
|
258
283
|
it 'should get from url normally' do
|
259
|
-
subject.
|
260
|
-
subject.oer_rates.wont_be_empty
|
284
|
+
_(subject.oer_rates).wont_be_empty
|
261
285
|
end
|
262
286
|
|
263
287
|
it 'should save from url and get from cache' do
|
264
|
-
|
265
|
-
|
266
|
-
dont_allow(subject).source_url
|
288
|
+
_(@global_rates).wont_be_empty
|
289
|
+
subject.expects(:source_url).never
|
267
290
|
subject.update_rates
|
268
|
-
subject.oer_rates.wont_be_empty
|
291
|
+
_(subject.oer_rates).wont_be_empty
|
269
292
|
end
|
270
293
|
end
|
271
294
|
|
272
|
-
describe '
|
295
|
+
describe '#refresh_rates' do
|
273
296
|
before do
|
274
|
-
|
297
|
+
subject.app_id = TEST_APP_ID
|
275
298
|
subject.cache = temp_cache_path
|
276
|
-
subject.
|
299
|
+
subject.stubs(:api_response).returns File.read(oer_latest_path)
|
300
|
+
subject.update_rates
|
277
301
|
end
|
278
302
|
|
279
303
|
after do
|
@@ -281,74 +305,124 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
281
305
|
end
|
282
306
|
|
283
307
|
it 'should allow update after save' do
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
308
|
+
subject.refresh_rates
|
309
|
+
# rubocop:disable Style/RescueStandardError
|
310
|
+
rescue
|
311
|
+
# rubocop:enable Style/RescueStandardError
|
312
|
+
assert false, 'Should allow updating after saving'
|
289
313
|
end
|
290
314
|
|
291
315
|
it 'should not break an existing file if save fails to read' do
|
292
316
|
initial_size = File.read(temp_cache_path).size
|
293
|
-
|
294
|
-
subject.
|
295
|
-
File.open(temp_cache_path).read.size.must_equal initial_size
|
317
|
+
subject.stubs(:api_response).returns ''
|
318
|
+
subject.refresh_rates
|
319
|
+
_(File.open(temp_cache_path).read.size).must_equal initial_size
|
296
320
|
end
|
297
321
|
|
298
322
|
it 'should not break an existing file if save returns json without rates' do
|
299
323
|
initial_size = File.read(temp_cache_path).size
|
300
|
-
|
301
|
-
subject.
|
302
|
-
File.open(temp_cache_path).read.size.must_equal initial_size
|
324
|
+
subject.stubs(:api_response).returns '{"error": "An error"}'
|
325
|
+
subject.refresh_rates
|
326
|
+
_(File.open(temp_cache_path).read.size).must_equal initial_size
|
303
327
|
end
|
304
328
|
|
305
329
|
it 'should not break an existing file if save returns a invalid json' do
|
306
330
|
initial_size = File.read(temp_cache_path).size
|
307
|
-
|
308
|
-
subject.
|
309
|
-
File.open(temp_cache_path).read.size.must_equal initial_size
|
331
|
+
subject.stubs(:api_response).returns '{invalid_json: "An error"}'
|
332
|
+
subject.refresh_rates
|
333
|
+
_(File.open(temp_cache_path).read.size).must_equal initial_size
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
describe '#rates_timestamp' do
|
338
|
+
before do
|
339
|
+
add_to_webmock(subject)
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'should be now when not updated from api' do
|
343
|
+
_(subject.rates_timestamp).must_be :>, Time.at(1_414_008_044)
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'should be set on update_rates' do
|
347
|
+
subject.update_rates
|
348
|
+
_(subject.rates_timestamp).must_equal Time.at(1_414_008_044)
|
310
349
|
end
|
311
350
|
end
|
312
351
|
|
313
352
|
describe '#expire_rates' do
|
314
353
|
before do
|
315
354
|
add_to_webmock(subject)
|
316
|
-
|
355
|
+
# see test/data/latest.json +4
|
356
|
+
subject.rates_timestamp = 1_414_008_044
|
357
|
+
@ttl_in_seconds = 1000
|
358
|
+
subject.ttl_in_seconds = @ttl_in_seconds
|
317
359
|
@old_usd_eur_rate = 0.655
|
318
|
-
# see test/latest.json +52
|
360
|
+
# see test/data/latest.json +52
|
319
361
|
@new_usd_eur_rate = 0.79085
|
320
362
|
subject.add_rate('USD', 'EUR', @old_usd_eur_rate)
|
321
|
-
|
322
|
-
subject.
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
363
|
+
@global_rates = nil
|
364
|
+
subject.cache = proc do |v|
|
365
|
+
if v
|
366
|
+
@global_rates = v
|
367
|
+
else
|
368
|
+
@global_rates
|
369
|
+
end
|
370
|
+
end
|
327
371
|
end
|
328
372
|
|
329
373
|
describe 'when the ttl has expired' do
|
330
374
|
it 'should update the rates' do
|
331
|
-
subject.
|
332
|
-
|
333
|
-
|
334
|
-
|
375
|
+
Timecop.freeze(subject.rates_timestamp) do
|
376
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @old_usd_eur_rate
|
377
|
+
end
|
378
|
+
Timecop.freeze(subject.rates_timestamp + (@ttl_in_seconds + 1)) do
|
379
|
+
_(subject.get_rate('USD', 'EUR')).wont_equal @old_usd_eur_rate
|
380
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @new_usd_eur_rate
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
it 'should save rates' do
|
385
|
+
Timecop.freeze(subject.rates_timestamp) do
|
386
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @old_usd_eur_rate
|
387
|
+
end
|
388
|
+
Timecop.freeze(subject.rates_timestamp + (@ttl_in_seconds + 1)) do
|
389
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @new_usd_eur_rate
|
390
|
+
_(@global_rates).wont_be_empty
|
335
391
|
end
|
336
392
|
end
|
337
393
|
|
338
394
|
it 'updates the next expiration time' do
|
339
|
-
Timecop.freeze(
|
340
|
-
exp_time =
|
395
|
+
Timecop.freeze(subject.rates_timestamp + (@ttl_in_seconds + 1)) do
|
396
|
+
exp_time = subject.rates_timestamp + @ttl_in_seconds
|
341
397
|
subject.expire_rates
|
342
|
-
subject.rates_expiration.must_equal exp_time
|
398
|
+
_(subject.rates_expiration).must_equal exp_time
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
describe '#force_refresh_rate_on_expire' do
|
403
|
+
it 'should save rates and force refresh' do
|
404
|
+
subject.force_refresh_rate_on_expire = true
|
405
|
+
Timecop.freeze(subject.rates_timestamp) do
|
406
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @old_usd_eur_rate
|
407
|
+
end
|
408
|
+
Timecop.freeze(Time.now + 1001) do
|
409
|
+
@global_rates = []
|
410
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @new_usd_eur_rate
|
411
|
+
_(@global_rates).wont_be_empty
|
412
|
+
end
|
343
413
|
end
|
344
414
|
end
|
345
415
|
end
|
346
416
|
|
347
417
|
describe 'when the ttl has not expired' do
|
348
|
-
it 'not
|
418
|
+
it 'should not update the rates' do
|
349
419
|
exp_time = subject.rates_expiration
|
350
|
-
subject.
|
351
|
-
|
420
|
+
Timecop.freeze(subject.rates_timestamp) do
|
421
|
+
subject.expects(:update_rates).never
|
422
|
+
subject.expects(:refresh_rates_expiration).never
|
423
|
+
subject.expire_rates
|
424
|
+
_(subject.rates_expiration).must_equal exp_time
|
425
|
+
end
|
352
426
|
end
|
353
427
|
end
|
354
428
|
end
|
@@ -356,31 +430,108 @@ describe Money::Bank::OpenExchangeRatesBank do
|
|
356
430
|
describe 'historical' do
|
357
431
|
before do
|
358
432
|
add_to_webmock(subject)
|
359
|
-
# see test/latest.json +52
|
433
|
+
# see test/data/latest.json +52
|
360
434
|
@latest_usd_eur_rate = 0.79085
|
361
|
-
|
435
|
+
@latest_chf_eur_rate = 0.830792859
|
436
|
+
# see test/data/2015-01-01.json +52
|
362
437
|
@old_usd_eur_rate = 0.830151
|
438
|
+
@old_chf_eur_rate = 0.832420177
|
363
439
|
subject.update_rates
|
364
440
|
end
|
365
441
|
|
366
442
|
it 'should be different than the latest' do
|
367
|
-
subject.get_rate('USD', 'EUR').must_equal @latest_usd_eur_rate
|
443
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @latest_usd_eur_rate
|
444
|
+
subject.date = '2015-01-01'
|
445
|
+
add_to_webmock(subject, oer_historical_path)
|
446
|
+
subject.update_rates
|
447
|
+
_(subject.get_rate('USD', 'EUR')).must_equal @old_usd_eur_rate
|
448
|
+
end
|
449
|
+
|
450
|
+
it 'should update cross courses' do
|
451
|
+
_(subject.get_rate('CHF', 'EUR').round(9).to_f)
|
452
|
+
.must_equal @latest_chf_eur_rate
|
368
453
|
subject.date = '2015-01-01'
|
369
454
|
add_to_webmock(subject, oer_historical_path)
|
370
455
|
subject.update_rates
|
371
|
-
subject.get_rate('
|
456
|
+
_(subject.get_rate('CHF', 'EUR').round(9).to_f)
|
457
|
+
.must_equal @old_chf_eur_rate
|
372
458
|
end
|
373
459
|
end
|
374
460
|
|
375
461
|
describe 'source currency' do
|
376
462
|
it 'should be changed when a known currency is given' do
|
377
|
-
|
378
|
-
subject.source
|
463
|
+
source = 'EUR'
|
464
|
+
subject.source = source
|
465
|
+
_(subject.source).must_equal source
|
466
|
+
_(subject.source_url).must_include "base=#{source}"
|
379
467
|
end
|
380
468
|
|
381
469
|
it 'should use USD when given unknown currency' do
|
382
|
-
|
383
|
-
subject.source
|
470
|
+
source = 'invalid'
|
471
|
+
subject.source = source
|
472
|
+
_(subject.source).must_equal default_source
|
473
|
+
_(subject.source_url).wont_include "base=#{default_source}"
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
describe 'prettyprint' do
|
478
|
+
describe 'when no value given' do
|
479
|
+
before do
|
480
|
+
subject.prettyprint = nil
|
481
|
+
end
|
482
|
+
|
483
|
+
it 'should return the default value' do
|
484
|
+
_(subject.prettyprint).must_equal true
|
485
|
+
end
|
486
|
+
|
487
|
+
it 'should include prettyprint param as true' do
|
488
|
+
_(subject.source_url).must_include 'prettyprint=true'
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
describe 'when value is given' do
|
493
|
+
before do
|
494
|
+
subject.prettyprint = false
|
495
|
+
end
|
496
|
+
|
497
|
+
it 'should return the value' do
|
498
|
+
_(subject.prettyprint).must_equal false
|
499
|
+
end
|
500
|
+
|
501
|
+
it 'should include prettyprint param as false' do
|
502
|
+
_(subject.source_url).must_include 'prettyprint=false'
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
describe 'show alternative' do
|
508
|
+
describe 'when no value given' do
|
509
|
+
before do
|
510
|
+
subject.show_alternative = nil
|
511
|
+
end
|
512
|
+
|
513
|
+
it 'should return the default value' do
|
514
|
+
_(subject.show_alternative).must_equal false
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'should include show_alternative param as false' do
|
518
|
+
_(subject.source_url).must_include 'show_alternative=false'
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
describe 'when value is given' do
|
523
|
+
before do
|
524
|
+
subject.show_alternative = true
|
525
|
+
end
|
526
|
+
|
527
|
+
it 'should return the value' do
|
528
|
+
_(subject.show_alternative).must_equal true
|
529
|
+
end
|
530
|
+
|
531
|
+
it 'should include show_alternative param as true' do
|
532
|
+
_(subject.source_url).must_include 'show_alternative=true'
|
533
|
+
end
|
384
534
|
end
|
385
535
|
end
|
386
536
|
end
|
537
|
+
# rubocop:enable Metrics/BlockLength
|
data/test/test_helper.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start
|
6
|
+
rescue LoadError
|
7
|
+
warn 'simplecov not loaded'
|
8
|
+
end
|
9
|
+
|
2
10
|
require 'minitest/autorun'
|
3
|
-
require '
|
11
|
+
require 'mocha/minitest'
|
4
12
|
require 'webmock/minitest'
|
5
13
|
require 'money/bank/open_exchange_rates_bank'
|
6
14
|
require 'monetize'
|
7
15
|
require 'timecop'
|
8
16
|
|
9
|
-
TEST_APP_ID = 'TEST_APP_ID'
|
17
|
+
TEST_APP_ID = 'TEST_APP_ID'
|
10
18
|
|
11
19
|
def data_file(file)
|
12
20
|
File.expand_path(File.join(File.dirname(__FILE__), 'data', file))
|