danconia 0.2.5 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +104 -0
- data/.travis.yml +4 -0
- data/Gemfile.lock +40 -17
- data/README.md +16 -2
- data/bin/console +7 -0
- data/danconia.gemspec +5 -1
- data/examples/bna.rb +35 -0
- data/examples/currency_layer.rb +8 -4
- data/examples/fixed_rates.rb +1 -3
- data/examples/single_currency.rb +2 -3
- data/lib/danconia.rb +6 -4
- data/lib/danconia/currency.rb +2 -2
- data/lib/danconia/exchange.rb +47 -0
- data/lib/danconia/exchanges/bna.rb +61 -0
- data/lib/danconia/exchanges/currency_layer.rb +14 -2
- data/lib/danconia/exchanges/fixed_rates.rb +2 -4
- data/lib/danconia/integrations/active_record.rb +13 -14
- data/lib/danconia/money.rb +25 -24
- data/lib/danconia/pair.rb +15 -0
- data/lib/danconia/stores/active_record.rb +29 -6
- data/lib/danconia/stores/in_memory.rb +4 -9
- data/lib/danconia/version.rb +1 -1
- data/spec/danconia/exchanges/bna_spec.rb +36 -0
- data/spec/danconia/exchanges/currency_layer_spec.rb +28 -33
- data/spec/danconia/exchanges/exchange_spec.rb +54 -0
- data/spec/danconia/exchanges/fixtures/bna/home.html +124 -0
- data/spec/danconia/exchanges/fixtures/currency_layer/failure.json +7 -0
- data/spec/danconia/exchanges/fixtures/currency_layer/success.json +8 -0
- data/spec/danconia/integrations/active_record_spec.rb +25 -5
- data/spec/danconia/money_spec.rb +57 -15
- data/spec/danconia/stores/active_record_spec.rb +81 -15
- data/spec/danconia/stores/in_memory_spec.rb +18 -0
- data/spec/spec_helper.rb +2 -1
- metadata +67 -9
- data/lib/danconia/exchanges/exchange.rb +0 -31
- data/spec/danconia/exchanges/fixed_rates_spec.rb +0 -30
@@ -0,0 +1,54 @@
|
|
1
|
+
module Danconia
|
2
|
+
module Exchanges
|
3
|
+
describe Exchange do
|
4
|
+
context 'rate' do
|
5
|
+
it 'returns the exchange rate value for the supplied currencies' do
|
6
|
+
exchange = fake_exchange('USDEUR' => 3, 'USDARS' => 4)
|
7
|
+
expect(exchange.rate('USD', 'EUR')).to eq 3
|
8
|
+
expect(exchange.rate('USD', 'ARS')).to eq 4
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'if the direct conversion is not found, tries to find the inverse' do
|
12
|
+
exchange = fake_exchange('USDEUR' => 3)
|
13
|
+
expect(exchange.rate('EUR', 'USD')).to be_within(0.00001).of(1.0 / 3)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'if not direct nor inverse conversion is found, tries to convert through USD' do
|
17
|
+
exchange = fake_exchange('USDEUR' => 3, 'USDARS' => 6)
|
18
|
+
expect(exchange.rate('EUR', 'ARS')).to be_within(0.00001).of 2
|
19
|
+
expect(exchange.rate('ARS', 'EUR')).to be_within(0.00001).of 0.5
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'pairs can have a different common currency' do
|
23
|
+
exchange = fake_exchange('EURARS' => 3, 'BRLARS' => 1.5)
|
24
|
+
expect(exchange.rate('EUR', 'ARS')).to eq 3
|
25
|
+
expect(exchange.rate('ARS', 'EUR')).to be_within(0.00001).of(1.0 / 3)
|
26
|
+
expect(exchange.rate('BRL', 'ARS')).to eq 1.5
|
27
|
+
expect(exchange.rate('EUR', 'BRL')).to eq 3 / 1.5
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises an error if the conversion cannot be made' do
|
31
|
+
expect { fake_exchange({}).rate('USD', 'EUR') }.to raise_error Errors::ExchangeRateNotFound
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should allow to pass options to filter the rates' do
|
35
|
+
exchange = Class.new(Exchange) do
|
36
|
+
def rates type:
|
37
|
+
case type
|
38
|
+
when 'divisa' then {'USDARS' => 7}
|
39
|
+
when 'billete' then {'USDARS' => 8}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end.new
|
43
|
+
|
44
|
+
expect(exchange.rate('USD', 'ARS', type: 'divisa')).to eq 7
|
45
|
+
expect(exchange.rate('USD', 'ARS', type: 'billete')).to eq 8
|
46
|
+
end
|
47
|
+
|
48
|
+
def fake_exchange(rates)
|
49
|
+
FixedRates.new(rates: rates)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="es" class="pc">
|
3
|
+
|
4
|
+
<body>
|
5
|
+
<div id="rightHome">
|
6
|
+
<div class="col-md-3">
|
7
|
+
<div class="tabSmall">
|
8
|
+
<ul class="nav nav-tabs">
|
9
|
+
|
10
|
+
<li class="active"><a href="#billetes" data-toggle="tab">Cotización Billetes</a>
|
11
|
+
<div class="arrow"></div>
|
12
|
+
</li>
|
13
|
+
<li><a href="#divisas" data-toggle="tab">Cotización Divisas</a>
|
14
|
+
<div class="arrow"></div>
|
15
|
+
</li>
|
16
|
+
</ul>
|
17
|
+
|
18
|
+
<div class="tab-content">
|
19
|
+
|
20
|
+
<div class="tab-pane fade in active" id="billetes">
|
21
|
+
|
22
|
+
<table class="table cotizacion">
|
23
|
+
<thead>
|
24
|
+
<tr>
|
25
|
+
<th class="fechaCot">1/9/2020</th>
|
26
|
+
<th>Compra</th>
|
27
|
+
<th>Venta</th>
|
28
|
+
</tr>
|
29
|
+
</thead>
|
30
|
+
<tbody>
|
31
|
+
|
32
|
+
<tr>
|
33
|
+
<td class="tit">Dolar U.S.A</td>
|
34
|
+
<td>73,2500</td>
|
35
|
+
<td>78,2500</td>
|
36
|
+
</tr>
|
37
|
+
<tr>
|
38
|
+
<td class="tit">Euro</td>
|
39
|
+
<td>84,0000</td>
|
40
|
+
<td>89,0000</td>
|
41
|
+
</tr>
|
42
|
+
<tr>
|
43
|
+
<td class="tit">Real *</td>
|
44
|
+
<td>1250,0000</td>
|
45
|
+
<td>1450,0000</td>
|
46
|
+
</tr>
|
47
|
+
|
48
|
+
</tbody>
|
49
|
+
</table>
|
50
|
+
<a href="#" class="link-cotizacion" data-toggle="modal" data-target="#modalHistorico" id="buttonHistoricoBilletes">Ver histórico</a>
|
51
|
+
<div class="legal">Hora Actualización: 10:40</div>
|
52
|
+
<div class="legal">(*) cotización cada 100 unidades.</div>
|
53
|
+
|
54
|
+
</div>
|
55
|
+
|
56
|
+
<div class="tab-pane fade" id="divisas">
|
57
|
+
<table class="table cotizacion">
|
58
|
+
<thead>
|
59
|
+
<tr>
|
60
|
+
<th class="fechaCot">31/8/2020</th>
|
61
|
+
<th>Compra</th>
|
62
|
+
<th>Venta</th>
|
63
|
+
</tr>
|
64
|
+
</thead>
|
65
|
+
<tbody>
|
66
|
+
|
67
|
+
<tr>
|
68
|
+
<td class="tit">Dolar U.S.A</td>
|
69
|
+
<td>73.9800</td>
|
70
|
+
<td>74.1800</td>
|
71
|
+
</tr>
|
72
|
+
<tr>
|
73
|
+
<td class="tit">Libra Esterlina</td>
|
74
|
+
<td>98.8743</td>
|
75
|
+
<td>99.3641</td>
|
76
|
+
</tr>
|
77
|
+
<tr>
|
78
|
+
<td class="tit">Euro</td>
|
79
|
+
<td>88.2581</td>
|
80
|
+
<td>88.6822</td>
|
81
|
+
</tr>
|
82
|
+
<tr>
|
83
|
+
<td class="tit">Franco Suizos *</td>
|
84
|
+
<td>8188.4905</td>
|
85
|
+
<td>8221.8519</td>
|
86
|
+
</tr>
|
87
|
+
<tr>
|
88
|
+
<td class="tit">YENES *</td>
|
89
|
+
<td>69.8238</td>
|
90
|
+
<td>70.1124</td>
|
91
|
+
</tr>
|
92
|
+
<tr>
|
93
|
+
<td class="tit">Dolares Canadienses *</td>
|
94
|
+
<td>5675.3160</td>
|
95
|
+
<td>5698.6457</td>
|
96
|
+
</tr>
|
97
|
+
<tr>
|
98
|
+
<td class="tit">Coronas Danesas *</td>
|
99
|
+
<td>1184.4394</td>
|
100
|
+
<td>1195.0806</td>
|
101
|
+
</tr>
|
102
|
+
<tr>
|
103
|
+
<td class="tit">Coronas Noruegas *</td>
|
104
|
+
<td>845.1963</td>
|
105
|
+
<td>854.8381</td>
|
106
|
+
</tr>
|
107
|
+
<tr>
|
108
|
+
<td class="tit">Coronas Suecas *</td>
|
109
|
+
<td>853.8596</td>
|
110
|
+
<td>863.8369</td>
|
111
|
+
</tr>
|
112
|
+
|
113
|
+
</tbody>
|
114
|
+
</table>
|
115
|
+
<a href="#" class="link-cotizacion" data-toggle="modal" data-target="#modalHistorico" id="buttonHistoricoMonedas">Ver histórico</a>
|
116
|
+
<div class="legal">(*) cotización cada 100 unidades.</div>
|
117
|
+
<div class="legal leyenda">El tipo de cambio de cierre de divisa es suministrado al público a fines informativos, como referencia de la cotización de la divisa en el mercado mayorista al final de cada día.</div>
|
118
|
+
</div>
|
119
|
+
</div>
|
120
|
+
</div>
|
121
|
+
</div>
|
122
|
+
</body>
|
123
|
+
|
124
|
+
</html>
|
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
module Danconia
|
4
2
|
describe Integrations::ActiveRecord, active_record: true do
|
5
3
|
context 'single currency' do
|
6
4
|
it 'setter' do
|
7
|
-
expect(Product.new(price: 1.536).read_attribute
|
8
|
-
expect(Product.new(price: nil).read_attribute
|
9
|
-
expect(Product.new(price: Money(3)).read_attribute
|
5
|
+
expect(Product.new(price: 1.536).read_attribute(:price)).to eq 1.54
|
6
|
+
expect(Product.new(price: nil).read_attribute(:price)).to eq nil
|
7
|
+
expect(Product.new(price: Money(3)).read_attribute(:price)).to eq 3
|
10
8
|
end
|
11
9
|
|
12
10
|
it 'getter' do
|
@@ -34,6 +32,28 @@ module Danconia
|
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
35
|
+
context 'exchange options support' do
|
36
|
+
let(:exchange) do
|
37
|
+
Class.new(Exchange) do
|
38
|
+
def rates rate_type:
|
39
|
+
case rate_type
|
40
|
+
when 'divisa' then {'USDARS' => 7}
|
41
|
+
when 'billete' then {'USDARS' => 8}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end.new
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows to specify options that will be pass to the exchange when exchanging to other currencies' do
|
48
|
+
klass = Class.new(ActiveRecord::Base) do
|
49
|
+
self.table_name = 'products'
|
50
|
+
money :price, rate_type: 'divisa'
|
51
|
+
end
|
52
|
+
|
53
|
+
expect(klass.new(price: Money(10, 'USD')).price.exchange_to('ARS', exchange: exchange)).to eq Money(70, 'ARS')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
37
57
|
class Product < ActiveRecord::Base
|
38
58
|
money :price, :tax, :discount, :cost
|
39
59
|
end
|
data/spec/danconia/money_spec.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
module Danconia
|
4
2
|
describe Money do
|
5
3
|
context 'instantiation' do
|
@@ -39,16 +37,15 @@ module Danconia
|
|
39
37
|
end
|
40
38
|
|
41
39
|
it 'should exchange the other currency if it is different' do
|
42
|
-
|
40
|
+
m1 = Money(1, 'ARS', exchange_opts: {exchange: fake_exchange(rate: 4)})
|
41
|
+
expect(m1 + Money(1, 'USD')).to eq Money(5, 'ARS')
|
43
42
|
end
|
44
43
|
|
45
44
|
it 'should return a new object with the same options' do
|
46
|
-
|
47
|
-
m1 = Money(4, decimals: 3, exchange: e)
|
45
|
+
m1 = Money(4, decimals: 3)
|
48
46
|
m2 = m1 * 2
|
49
47
|
expect(m2).to_not eql m1
|
50
48
|
expect(m2.decimals).to eq 3
|
51
|
-
expect(m2.exchange).to eq e
|
52
49
|
end
|
53
50
|
|
54
51
|
it 'round should return a money object with the same currency' do
|
@@ -72,7 +69,7 @@ module Danconia
|
|
72
69
|
end
|
73
70
|
|
74
71
|
it 'should exchange to the source currency if they differ' do
|
75
|
-
TestHelpers.with_rates 'USDARS' => 4 do |
|
72
|
+
TestHelpers.with_rates 'USDARS' => 4 do |_config|
|
76
73
|
expect(Money(3, 'ARS') < Money(1, 'USD')).to be true
|
77
74
|
expect(Money(4, 'ARS') < Money(1, 'USD')).to be false
|
78
75
|
end
|
@@ -121,17 +118,30 @@ module Danconia
|
|
121
118
|
end
|
122
119
|
|
123
120
|
context 'exchange_to' do
|
124
|
-
it 'should use
|
125
|
-
expect(Money(2, 'USD', exchange: fake_exchange(rate: 3)).exchange_to('ARS')).to eq Money(6, 'ARS')
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'should use the default exchange if not set' do
|
121
|
+
it 'should use a default exchange if not overriden' do
|
129
122
|
TestHelpers.with_rates 'USDEUR' => 3, 'USDARS' => 4 do
|
130
123
|
expect(Money(2, 'USD').exchange_to('EUR')).to eq Money(6, 'EUR')
|
131
124
|
expect(Money(2, 'USD').exchange_to('ARS')).to eq Money(8, 'ARS')
|
132
125
|
end
|
133
126
|
end
|
134
127
|
|
128
|
+
it 'should allow to pass the exchange to the instance' do
|
129
|
+
m = Money(2, 'USD', exchange_opts: {exchange: fake_exchange(rate: 3)})
|
130
|
+
expect(m.exchange_to('ARS')).to eq Money(6, 'ARS')
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should allow to pass the exchange when converting' do
|
134
|
+
expect(Money(2, 'USD').exchange_to('ARS', exchange: fake_exchange(rate: 4))).to eq Money(8, 'ARS')
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'when overriding the exchange, should preserve it in the new instances' do
|
138
|
+
m1 = Money(1, 'USD').exchange_to('ARS', exchange: fake_exchange(rate: 2))
|
139
|
+
m2 = m1 + Money(3, 'USD')
|
140
|
+
m3 = m2 * Money(1, 'USD')
|
141
|
+
expect(m2).to eq Money(8, 'ARS')
|
142
|
+
expect(m3).to eq Money(16, 'ARS')
|
143
|
+
end
|
144
|
+
|
135
145
|
it 'if no rate if found should raise error' do
|
136
146
|
expect { Money(2, 'USD').exchange_to('ARS') }.to raise_error Errors::ExchangeRateNotFound
|
137
147
|
end
|
@@ -141,8 +151,8 @@ module Danconia
|
|
141
151
|
end
|
142
152
|
|
143
153
|
it 'should return a new object with the same opts' do
|
144
|
-
m1 = Money(1, 'USD', decimals: 0
|
145
|
-
m2 = m1.exchange_to('ARS')
|
154
|
+
m1 = Money(1, 'USD', decimals: 0)
|
155
|
+
m2 = m1.exchange_to('ARS', exchange: fake_exchange(rate: 3))
|
146
156
|
expect(m2).to_not eql m1
|
147
157
|
expect(m2.decimals).to eq 0
|
148
158
|
expect(m1).to eq Money(1, 'USD')
|
@@ -152,6 +162,38 @@ module Danconia
|
|
152
162
|
expect(Money(1, 'USD').exchange_to('')).to eq Money(1, 'USD')
|
153
163
|
expect(Money(1, 'ARS').exchange_to('')).to eq Money(1, 'ARS')
|
154
164
|
end
|
165
|
+
|
166
|
+
context 'opts' do
|
167
|
+
let(:exchange) do
|
168
|
+
Class.new(Exchange) do
|
169
|
+
def rates opts
|
170
|
+
case opts[:type]
|
171
|
+
when 'divisa' then {'USDARS' => 7}
|
172
|
+
when 'billete' then {'USDARS' => 8}
|
173
|
+
else {}
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end.new
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'allows to specify opts to pass to the exchange (filters for example)' do
|
180
|
+
expect(Money(1, 'USD').exchange_to('ARS', type: 'divisa', exchange: exchange)).to eq Money(7, 'ARS')
|
181
|
+
expect { Money(1, 'USD').exchange_to('ARS', exchange: exchange) }.to raise_error Errors::ExchangeRateNotFound
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should be preserved after operations' do
|
185
|
+
m1 = Money(1, 'USD').exchange_to('ARS', type: 'divisa', exchange: exchange)
|
186
|
+
m2 = m1 + Money(2, 'USD')
|
187
|
+
|
188
|
+
expect(m2).to eq Money(21, 'ARS')
|
189
|
+
expect(m1 < Money(2, 'USD')).to eq true
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should use the instance exchange_opts by default' do
|
193
|
+
m = Money(1, 'USD', exchange_opts: {exchange: exchange, type: 'billete'})
|
194
|
+
expect(m.exchange_to('ARS')).to eq Money(8, 'ARS')
|
195
|
+
end
|
196
|
+
end
|
155
197
|
end
|
156
198
|
|
157
199
|
context 'default_currency?' do
|
@@ -178,7 +220,7 @@ module Danconia
|
|
178
220
|
end
|
179
221
|
|
180
222
|
def fake_exchange args = {}
|
181
|
-
double '
|
223
|
+
double 'Danconia::Exchange', args.reverse_merge(rate: nil)
|
182
224
|
end
|
183
225
|
end
|
184
226
|
end
|
@@ -1,31 +1,97 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
module Danconia
|
4
2
|
module Stores
|
5
3
|
describe ActiveRecord, active_record: true do
|
4
|
+
before do
|
5
|
+
::ActiveRecord::Schema.define do
|
6
|
+
create_table :exchange_rates do |t|
|
7
|
+
t.string :pair, limit: 6
|
8
|
+
t.decimal :rate, precision: 12, scale: 6
|
9
|
+
t.string :rate_type
|
10
|
+
t.date :date
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
context 'save_rates' do
|
7
16
|
it 'should create or update the rates' do
|
8
17
|
ExchangeRate.create! pair: 'USDEUR', rate: 2
|
9
|
-
|
10
|
-
expect
|
18
|
+
|
19
|
+
expect do
|
20
|
+
subject.save_rates [{pair: 'USDEUR', rate: 3}, {pair: 'USDARS', rate: 4}]
|
21
|
+
end.to change { ExchangeRate.count }.by 1
|
22
|
+
|
23
|
+
expect(subject.rates).to match [
|
24
|
+
include(pair: 'USDEUR', rate: 3),
|
25
|
+
include(pair: 'USDARS', rate: 4)
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'allows to specify other keys to use as unique' do
|
30
|
+
store = ActiveRecord.new(unique_keys: %i[pair rate_type])
|
31
|
+
store.save_rates [
|
32
|
+
{pair: 'USDARS', rate: 3, rate_type: 'billetes'},
|
33
|
+
{pair: 'USDARS', rate: 4, rate_type: 'divisas'}
|
34
|
+
]
|
35
|
+
store.save_rates [
|
36
|
+
{pair: 'USDARS', rate: 33, rate_type: 'billetes'}
|
37
|
+
]
|
38
|
+
expect(subject.rates).to match [
|
39
|
+
include(pair: 'USDARS', rate: 33, rate_type: 'billetes'),
|
40
|
+
include(pair: 'USDARS', rate: 4, rate_type: 'divisas')
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'ignores fields not present in the database table' do
|
45
|
+
subject.save_rates [{pair: 'USDEUR', rate: 3, non_existant: 'ignoreme'}]
|
11
46
|
end
|
12
47
|
end
|
13
48
|
|
14
|
-
context '
|
15
|
-
it '
|
49
|
+
context 'rates' do
|
50
|
+
it 'returns an array like the one it received' do
|
16
51
|
ExchangeRate.create! pair: 'USDEUR', rate: 2
|
17
|
-
|
18
|
-
|
52
|
+
ExchangeRate.create! pair: 'USDARS', rate: 40
|
53
|
+
|
54
|
+
expect(subject.rates).to match [
|
55
|
+
include(pair: 'USDEUR', rate: 2),
|
56
|
+
include(pair: 'USDARS', rate: 40)
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'allows to pass filters' do
|
61
|
+
store = ActiveRecord.new(unique_keys: %i[pair date])
|
62
|
+
store.save_rates [
|
63
|
+
{pair: 'USDEUR', rate: 10, date: Date.new(2020, 1, 1)},
|
64
|
+
{pair: 'USDEUR', rate: 20, date: Date.new(2020, 1, 2)},
|
65
|
+
{pair: 'USDEUR', rate: 30, date: Date.new(2020, 1, 3)}
|
66
|
+
]
|
67
|
+
|
68
|
+
expect(store.rates.size).to eq 3
|
69
|
+
expect(store.rates(date: Date.new(2020, 1, 2))).to match [include(rate: 20)]
|
19
70
|
end
|
20
71
|
end
|
21
72
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
73
|
+
context 'special date field' do
|
74
|
+
let(:store) do
|
75
|
+
store = ActiveRecord.new(unique_keys: %i[pair date], date_field: :date)
|
76
|
+
store.save_rates [
|
77
|
+
{pair: 'USDEUR', rate: 10, date: Date.new(2000, 1, 1)},
|
78
|
+
{pair: 'USDEUR', rate: 20, date: Date.new(2000, 1, 2)},
|
79
|
+
{pair: 'USDEUR', rate: 30, date: Date.new(2000, 1, 4)}
|
80
|
+
]
|
81
|
+
store
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'calling #rates with a particular date when there are rates for that date' do
|
85
|
+
expect(store.rates(date: Date.new(2000, 1, 2))).to match [include(rate: 20)]
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'calling #rates with a particular date when there are not rates for that date should return the previous' do
|
89
|
+
expect(store.rates(date: Date.new(2000, 1, 3))).to match [include(rate: 20)]
|
90
|
+
expect(store.rates(date: Date.new(1999, 12, 31))).to eq []
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'calling #rates without a particular date, uses today' do
|
94
|
+
expect(store.rates).to match [include(rate: 30)]
|
29
95
|
end
|
30
96
|
end
|
31
97
|
end
|