iex-ruby-client 1.2.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.env.sample +2 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop_todo.yml +0 -8
  5. data/CHANGELOG.md +27 -0
  6. data/Gemfile +1 -0
  7. data/README.md +237 -18
  8. data/RELEASING.md +3 -3
  9. data/lib/iex/api.rb +8 -1
  10. data/lib/iex/api/client.rb +15 -2
  11. data/lib/iex/api/config/client.rb +52 -0
  12. data/lib/iex/api/config/logger.rb +35 -0
  13. data/lib/iex/cloud/connection.rb +2 -1
  14. data/lib/iex/endpoints/advanced_stats.rb +11 -0
  15. data/lib/iex/endpoints/balance_sheet.rb +13 -0
  16. data/lib/iex/endpoints/cash_flow.rb +13 -0
  17. data/lib/iex/endpoints/fx.rb +13 -0
  18. data/lib/iex/endpoints/historial_prices.rb +30 -0
  19. data/lib/iex/endpoints/key_stat.rb +14 -0
  20. data/lib/iex/endpoints/ref_data.rb +6 -1
  21. data/lib/iex/errors.rb +3 -1
  22. data/lib/iex/errors/invalid_symbols_list.rb +14 -0
  23. data/lib/iex/errors/stat_not_found_error.rb +13 -0
  24. data/lib/iex/resources.rb +5 -0
  25. data/lib/iex/resources/advanced_stats.rb +84 -0
  26. data/lib/iex/resources/balance_sheet.rb +60 -0
  27. data/lib/iex/resources/cash_flow.rb +43 -0
  28. data/lib/iex/resources/currency_rate.rb +9 -0
  29. data/lib/iex/resources/historical_prices.rb +31 -0
  30. data/lib/iex/resources/income.rb +2 -0
  31. data/lib/iex/resources/news.rb +3 -0
  32. data/lib/iex/resources/resource.rb +12 -0
  33. data/lib/iex/version.rb +1 -1
  34. data/script/console +9 -0
  35. data/spec/fixtures/iex/advanced_stats/invalid.yml +50 -0
  36. data/spec/fixtures/iex/advanced_stats/msft.yml +57 -0
  37. data/spec/fixtures/iex/balance_sheet/invalid.yml +50 -0
  38. data/spec/fixtures/iex/balance_sheet/msft.yml +56 -0
  39. data/spec/fixtures/iex/cash_flow/invalid.yml +50 -0
  40. data/spec/fixtures/iex/cash_flow/msft.yml +56 -0
  41. data/spec/fixtures/iex/fx/invalid.yml +83 -0
  42. data/spec/fixtures/iex/fx/latest.yml +85 -0
  43. data/spec/fixtures/iex/fx/latest_one_symbol.yml +85 -0
  44. data/spec/fixtures/iex/historical_prices/abcd.yml +56 -0
  45. data/spec/fixtures/iex/historical_prices/invalid.yml +50 -0
  46. data/spec/fixtures/iex/historical_prices/invalid_date.yml +50 -0
  47. data/spec/fixtures/iex/historical_prices/invalid_range.yml +47 -0
  48. data/spec/fixtures/iex/historical_prices/msft.yml +79 -0
  49. data/spec/fixtures/iex/historical_prices/msft_5d.yml +61 -0
  50. data/spec/fixtures/iex/historical_prices/msft_date_and_chart_by_day.yml +57 -0
  51. data/spec/fixtures/iex/historical_prices/msft_specific_date_trimmed.yml +445 -0
  52. data/spec/fixtures/iex/income/msft.yml +54 -51
  53. data/spec/fixtures/iex/key_stat/individual.yml +60 -0
  54. data/spec/fixtures/iex/key_stat/invalid_stat.yml +60 -0
  55. data/spec/fixtures/iex/key_stat/invalid_symbol.yml +50 -0
  56. data/spec/fixtures/iex/ref-data/exchange_symbols.yml +1926 -0
  57. data/spec/iex/client_spec.rb +91 -13
  58. data/spec/iex/config/client_spec.rb +49 -0
  59. data/spec/iex/config/logger_spec.rb +46 -0
  60. data/spec/iex/endpoints/advanced_stats_spec.rb +110 -0
  61. data/spec/iex/endpoints/balance_sheet_spec.rb +80 -0
  62. data/spec/iex/endpoints/cash_flow_spec.rb +59 -0
  63. data/spec/iex/endpoints/fx_spec.rb +48 -0
  64. data/spec/iex/endpoints/historical_prices_spec.rb +206 -0
  65. data/spec/iex/endpoints/income_spec.rb +31 -29
  66. data/spec/iex/endpoints/key_stat_spec.rb +43 -0
  67. data/spec/iex/endpoints/news_spec.rb +3 -0
  68. data/spec/iex/endpoints/ref_data_spec.rb +57 -12
  69. data/spec/iex/resources/resource_spec.rb +36 -0
  70. data/spec/spec_helper.rb +3 -3
  71. metadata +78 -6
  72. data/lib/iex/api/config.rb +0 -47
  73. data/spec/iex/config_spec.rb +0 -22
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Endpoints::FX do
4
+ include_context 'client'
5
+
6
+ context 'known symbol', vcr: { cassette_name: 'fx/latest_one_symbol' } do
7
+ subject do
8
+ client.fx_latest('USDCAD')
9
+ end
10
+ it 'retrieves a list of CurrencyRates' do
11
+ expect(subject.length).to eq 1
12
+
13
+ expect(subject[0].symbol).to eq 'USDCAD'
14
+ expect(subject[0].rate).to eq 1.25674
15
+ expect(subject[0].timestamp).to eq Date.strptime('1627045829.863', '%s')
16
+ end
17
+ end
18
+
19
+ context 'known symbols', vcr: { cassette_name: 'fx/latest' } do
20
+ subject do
21
+ client.fx_latest(%w[USDCAD USDGBP USDJPY])
22
+ end
23
+ it 'retrieves a list of CurrencyRates' do
24
+ expect(subject.length).to eq 3
25
+
26
+ expect(subject[0].symbol).to eq 'USDCAD'
27
+ expect(subject[0].rate).to eq 1.25674
28
+ expect(subject[0].timestamp).to eq Date.strptime('1627045829.863', '%s')
29
+
30
+ expect(subject[1].symbol).to eq 'USDGBP'
31
+ expect(subject[1].rate).to eq 0.7262111386264443
32
+ expect(subject[1].timestamp).to eq Date.strptime('1627045780.863', '%s')
33
+
34
+ expect(subject[2].symbol).to eq 'USDJPY'
35
+ expect(subject[2].rate).to eq 110.426
36
+ expect(subject[2].timestamp).to eq Date.strptime('1627045825.365', '%s')
37
+ end
38
+ end
39
+
40
+ context 'invalid symbol', vcr: { cassette_name: 'fx/invalid' } do
41
+ subject do
42
+ client.fx_latest(%w[INVALID])
43
+ end
44
+ it 'fails with InvalidSymbolsList' do
45
+ expect { subject }.to raise_error IEX::Errors::InvalidSymbolsList, 'Invalid symbol list: INVALID'
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe IEX::Resources::HistorialPrices do
6
+ include_context 'client'
7
+
8
+ context 'known symbol' do
9
+ context 'with valid params' do
10
+ context 'with defaults', vcr: { cassette_name: 'historical_prices/msft' } do
11
+ subject do
12
+ client.historical_prices('MSFT')
13
+ end
14
+ let(:historical_price) { subject.first }
15
+
16
+ it 'retrieves historical prices' do
17
+ expect(subject.size).to eq 23
18
+ expect(historical_price.date).to eq '2020-10-07'
19
+ expect(historical_price.open).to eq 207.06
20
+ expect(historical_price.open_dollar).to eq '$207.06'
21
+ expect(historical_price.close).to eq 209.83
22
+ expect(historical_price.close_dollar).to eq '$209.83'
23
+ expect(historical_price.high).to eq 210.11
24
+ expect(historical_price.high_dollar).to eq '$210.11'
25
+ expect(historical_price.low).to eq 206.72
26
+ expect(historical_price.low_dollar).to eq '$206.72'
27
+ expect(historical_price.volume).to eq 25_681_054
28
+ expect(historical_price.u_open).to eq 207.06
29
+ expect(historical_price.u_open_dollar).to eq '$207.06'
30
+ expect(historical_price.u_close).to eq 209.83
31
+ expect(historical_price.u_close_dollar).to eq '$209.83'
32
+ expect(historical_price.u_low).to eq 206.72
33
+ expect(historical_price.u_low_dollar).to eq '$206.72'
34
+ expect(historical_price.u_high).to eq 210.11
35
+ expect(historical_price.u_high_dollar).to eq '$210.11'
36
+ expect(historical_price.u_volume).to eq 25_681_054
37
+ expect(historical_price.change).to eq 0
38
+ expect(historical_price.change_percent).to eq 0
39
+ expect(historical_price.change_percent_s).to eq '+0.00%'
40
+ expect(historical_price.label).to eq 'Oct 7'
41
+ expect(historical_price.change_over_time).to eq 0
42
+ expect(historical_price.change_over_time_s).to eq '+0.00%'
43
+ end
44
+ end
45
+
46
+ context 'with a valid range provided', vcr: { cassette_name: 'historical_prices/msft_5d' } do
47
+ subject { client.historical_prices('MSFT', range: '5d') }
48
+ let(:historical_price) { subject.last }
49
+
50
+ it 'retrieves historical prices' do
51
+ expect(subject.size).to eq 5
52
+ expect(historical_price.date).to eq '2020-11-10'
53
+ expect(historical_price.open).to eq 214.50
54
+ expect(historical_price.open_dollar).to eq '$214.50'
55
+ expect(historical_price.close).to eq 211.01
56
+ expect(historical_price.close_dollar).to eq '$211.01'
57
+ expect(historical_price.high).to eq 216.50
58
+ expect(historical_price.high_dollar).to eq '$216.50'
59
+ expect(historical_price.low).to eq 209.72
60
+ expect(historical_price.low_dollar).to eq '$209.72'
61
+ expect(historical_price.volume).to eq 44_045_120
62
+ expect(historical_price.u_open).to eq 214.50
63
+ expect(historical_price.u_open_dollar).to eq '$214.50'
64
+ expect(historical_price.u_close).to eq 211.01
65
+ expect(historical_price.u_close_dollar).to eq '$211.01'
66
+ expect(historical_price.u_low).to eq 209.72
67
+ expect(historical_price.u_low_dollar).to eq '$209.72'
68
+ expect(historical_price.u_high).to eq 216.50
69
+ expect(historical_price.u_high_dollar).to eq '$216.50'
70
+ expect(historical_price.u_volume).to eq 44_045_120
71
+ expect(historical_price.change).to eq(-7.38)
72
+ expect(historical_price.change_percent).to eq(-3.3793)
73
+ expect(historical_price.change_percent_s).to eq '-3.38%'
74
+ expect(historical_price.label).to eq 'Nov 10'
75
+ expect(historical_price.change_over_time).to eq(-0.024863)
76
+ expect(historical_price.change_over_time_s).to eq '-0.02%'
77
+ end
78
+ end
79
+
80
+ context 'with a range provided for a specific date (passed as a Date object) and chartByDay param',
81
+ vcr: { cassette_name: 'historical_prices/msft_date_and_chart_by_day' } do
82
+ options = { range: 'date', date: Date.parse('2020-11-10'), chartByDay: 'true' }
83
+ subject { client.historical_prices('MSFT', options) }
84
+ let(:historical_price) { subject.first }
85
+
86
+ it 'retrieves historical prices' do
87
+ expect(subject.size).to eq 1
88
+ expect(historical_price.date).to eq '2020-11-10'
89
+ expect(historical_price.open).to eq 214.50
90
+ expect(historical_price.open_dollar).to eq '$214.50'
91
+ expect(historical_price.close).to eq 211.01
92
+ expect(historical_price.close_dollar).to eq '$211.01'
93
+ expect(historical_price.high).to eq 216.50
94
+ expect(historical_price.high_dollar).to eq '$216.50'
95
+ expect(historical_price.low).to eq 209.72
96
+ expect(historical_price.low_dollar).to eq '$209.72'
97
+ expect(historical_price.volume).to eq 44_045_120
98
+ expect(historical_price.u_open).to eq 214.50
99
+ expect(historical_price.u_open_dollar).to eq '$214.50'
100
+ expect(historical_price.u_close).to eq 211.01
101
+ expect(historical_price.u_close_dollar).to eq '$211.01'
102
+ expect(historical_price.u_low).to eq 209.72
103
+ expect(historical_price.u_low_dollar).to eq '$209.72'
104
+ expect(historical_price.u_high).to eq 216.50
105
+ expect(historical_price.u_high_dollar).to eq '$216.50'
106
+ expect(historical_price.u_volume).to eq 44_045_120
107
+ expect(historical_price.change).to eq(-7.38)
108
+ expect(historical_price.change_percent).to eq(-3.3793)
109
+ expect(historical_price.change_percent_s).to eq '-3.38%'
110
+ expect(historical_price.label).to eq 'Nov 10'
111
+ expect(historical_price.change_over_time).to eq(-0.033793)
112
+ expect(historical_price.change_over_time_s).to eq '-0.03%'
113
+ end
114
+ end
115
+
116
+ context 'with a range provided for a specific date (passed as a string) and chartByDay param',
117
+ vcr: { cassette_name: 'historical_prices/msft_date_and_chart_by_day' } do
118
+ options = { range: 'date', date: '20201110', chartByDay: 'true' }
119
+ subject { client.historical_prices('MSFT', options) }
120
+ let(:historical_price) { subject.first }
121
+
122
+ it 'retrieves historical prices' do
123
+ expect(subject.size).to eq 1
124
+ expect(historical_price.date).to eq '2020-11-10'
125
+ expect(historical_price.open).to eq 214.50
126
+ expect(historical_price.open_dollar).to eq '$214.50'
127
+ expect(historical_price.close).to eq 211.01
128
+ expect(historical_price.close_dollar).to eq '$211.01'
129
+ expect(historical_price.high).to eq 216.50
130
+ expect(historical_price.high_dollar).to eq '$216.50'
131
+ expect(historical_price.low).to eq 209.72
132
+ expect(historical_price.low_dollar).to eq '$209.72'
133
+ expect(historical_price.volume).to eq 44_045_120
134
+ expect(historical_price.u_open).to eq 214.50
135
+ expect(historical_price.u_open_dollar).to eq '$214.50'
136
+ expect(historical_price.u_close).to eq 211.01
137
+ expect(historical_price.u_close_dollar).to eq '$211.01'
138
+ expect(historical_price.u_low).to eq 209.72
139
+ expect(historical_price.u_low_dollar).to eq '$209.72'
140
+ expect(historical_price.u_high).to eq 216.50
141
+ expect(historical_price.u_high_dollar).to eq '$216.50'
142
+ expect(historical_price.u_volume).to eq 44_045_120
143
+ expect(historical_price.change).to eq(-7.38)
144
+ expect(historical_price.change_percent).to eq(-3.3793)
145
+ expect(historical_price.change_percent_s).to eq '-3.38%'
146
+ expect(historical_price.label).to eq 'Nov 10'
147
+ expect(historical_price.change_over_time).to eq(-0.033793)
148
+ expect(historical_price.change_over_time_s).to eq '-0.03%'
149
+ end
150
+ end
151
+ end
152
+
153
+ context 'with invalid params' do
154
+ context 'with an invalid range', vcr: { cassette_name: 'historical_prices/invalid_range' } do
155
+ subject { client.historical_prices('MSFT', range: 'invalid') }
156
+
157
+ it 'fails with ArgumentError' do
158
+ expect { subject }.to raise_error IEX::Errors::PermissionDeniedError
159
+ end
160
+ end
161
+
162
+ context "with a range as 'date' but without a date param" do
163
+ subject { client.historical_prices('MSFT', range: 'date') }
164
+
165
+ it 'fails with ArgumentError' do
166
+ expect { subject }.to raise_error ArgumentError
167
+ end
168
+ end
169
+
170
+ context "with a range as 'date' but without chartByDay query param" do
171
+ subject { client.historical_prices('MSFT', range: 'date', date: Date.parse('2020-11-10')) }
172
+
173
+ it 'fails with ArgumentError' do
174
+ expect { subject }.to raise_error ArgumentError
175
+ end
176
+ end
177
+
178
+ context "with a range as 'date' but without date as a Date object that is incorrectly formatted",
179
+ vcr: { cassette_name: 'historical_prices/invalid_date' } do
180
+ subject { client.historical_prices('MSFT', range: 'date', date: '2020-11-10', chartByDay: 'true') }
181
+
182
+ it 'fails with ArgumentError' do
183
+ expect { subject }.to raise_error IEX::Errors::ClientError
184
+ end
185
+ end
186
+ end
187
+ end
188
+
189
+ context 'no result', vcr: { cassette_name: 'historical_prices/abcd' } do
190
+ subject do
191
+ client.historical_prices('abcd')
192
+ end
193
+ it 'returns empty array' do
194
+ expect(subject).to eq []
195
+ end
196
+ end
197
+
198
+ context 'invalid symbol', vcr: { cassette_name: 'historical_prices/invalid' } do
199
+ subject do
200
+ client.historical_prices('INVALID')
201
+ end
202
+ it 'fails with SymbolNotFoundError' do
203
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
204
+ end
205
+ end
206
+ end
@@ -14,36 +14,38 @@ describe IEX::Resources::Income do
14
14
 
15
15
  it 'retrieves income statement' do
16
16
  expect(subject.size).to eq 1
17
- expect(income.report_date).to eq '2019-03-31'
18
- expect(income.total_revenue).to eq 30_505_000_000
19
- expect(income.total_revenue_dollar).to eq '$30,505,000,000'
20
- expect(income.cost_of_revenue).to eq 10_170_000_000
21
- expect(income.cost_of_revenue_dollar).to eq '$10,170,000,000'
22
- expect(income.gross_profit).to eq 20_335_000_000
23
- expect(income.gross_profit_dollar).to eq '$20,335,000,000'
24
- expect(income.research_and_development).to eq 4_316_000_000
25
- expect(income.research_and_development_dollar).to eq '$4,316,000,000'
26
- expect(income.selling_general_and_admin).to eq 5_744_000_000
27
- expect(income.selling_general_and_admin_dollar).to eq '$5,744,000,000'
28
- expect(income.operating_expense).to eq 20_230_000_000
29
- expect(income.operating_expense_dollar).to eq '$20,230,000,000'
30
- expect(income.operating_income).to eq 10_275_000_000
31
- expect(income.operating_income_dollar).to eq '$10,275,000,000'
32
- expect(income.other_income_expense_net).to eq 211_000_000
33
- expect(income.other_income_expense_net_dollar).to eq '$211,000,000'
34
- expect(income.ebit_dollar).to eq '$10,275,000,000'
35
- expect(income.ebit).to eq 10_275_000_000
36
- expect(income.interest_income).to eq 671_000_000
37
- expect(income.interest_income_dollar).to eq '$671,000,000'
38
- expect(income.pretax_income).to eq 10_486_000_000
39
- expect(income.pretax_income_dollar).to eq '$10,486,000,000'
40
- expect(income.income_tax).to eq 1_677_000_000
41
- expect(income.income_tax_dollar).to eq '$1,677,000,000'
17
+ expect(income.report_date).to eq '2020-09-30'
18
+ expect(income.fiscal_date).to eq '2020-09-30'
19
+ expect(income.currency).to eq 'USD'
20
+ expect(income.total_revenue).to eq 37_154_000_000
21
+ expect(income.total_revenue_dollar).to eq '$37,154,000,000'
22
+ expect(income.cost_of_revenue).to eq 11_002_000_000
23
+ expect(income.cost_of_revenue_dollar).to eq '$11,002,000,000'
24
+ expect(income.gross_profit).to eq 26_152_000_000
25
+ expect(income.gross_profit_dollar).to eq '$26,152,000,000'
26
+ expect(income.research_and_development).to eq 4_926_000_000
27
+ expect(income.research_and_development_dollar).to eq '$4,926,000,000'
28
+ expect(income.selling_general_and_admin).to eq 5_350_000_000
29
+ expect(income.selling_general_and_admin_dollar).to eq '$5,350,000,000'
30
+ expect(income.operating_expense).to eq 21_278_000_000
31
+ expect(income.operating_expense_dollar).to eq '$21,278,000,000'
32
+ expect(income.operating_income).to eq 15_876_000_000
33
+ expect(income.operating_income_dollar).to eq '$15,876,000,000'
34
+ expect(income.other_income_expense_net).to eq 248_000_000
35
+ expect(income.other_income_expense_net_dollar).to eq '$248,000,000'
36
+ expect(income.ebit).to eq 15_876_000_000
37
+ expect(income.ebit_dollar).to eq '$15,876,000,000'
38
+ expect(income.interest_income).to eq 589_000_000
39
+ expect(income.interest_income_dollar).to eq '$589,000,000'
40
+ expect(income.pretax_income).to eq 16_124_000_000
41
+ expect(income.pretax_income_dollar).to eq '$16,124,000,000'
42
+ expect(income.income_tax).to eq 2_231_000_000
43
+ expect(income.income_tax_dollar).to eq '$2,231,000,000'
42
44
  expect(income.minority_interest).to eq 0
43
- expect(income.net_income).to eq 8_809_000_000
44
- expect(income.net_income_dollar).to eq '$8,809,000,000'
45
- expect(income.net_income_basic).to eq 8_809_000_000
46
- expect(income.net_income_basic_dollar).to eq '$8,809,000,000'
45
+ expect(income.net_income).to eq 13_893_000_000
46
+ expect(income.net_income_dollar).to eq '$13,893,000,000'
47
+ expect(income.net_income_basic).to eq 13_893_000_000
48
+ expect(income.net_income_basic_dollar).to eq '$13,893,000,000'
47
49
  end
48
50
  end
49
51
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Endpoints::KeyStat do
4
+ include_context 'client'
5
+
6
+ let(:stat) { 'ttmDividendRate' }
7
+ let(:symbol) { 'VTI' }
8
+
9
+ context 'when asking for a single stat', vcr: { cassette_name: 'key_stat/individual' } do
10
+ subject { client.key_stat(symbol, stat) }
11
+
12
+ it 'returns that stat in the type provided by the API' do
13
+ expect(subject).to be_within(0.0001).of(2.7887)
14
+ end
15
+ end
16
+
17
+ context 'invalid symbol', vcr: { cassette_name: 'key_stat/invalid_symbol' } do
18
+ subject { client.key_stat('INVALID', stat) }
19
+
20
+ it 'fails with SymbolNotFoundError' do
21
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
22
+ end
23
+ end
24
+
25
+ context 'invalid stat', vcr: { cassette_name: 'key_stat/invalid_stat' } do
26
+ subject { client.key_stat(symbol, 'INVALID') }
27
+
28
+ it 'fails with StatNotFoundError' do
29
+ expect { subject }.to raise_error IEX::Errors::StatNotFoundError, 'Stat INVALID Not Found'
30
+ end
31
+
32
+ it 'keeps the API response so it can be used if caught' do
33
+ response = begin
34
+ subject
35
+ rescue IEX::Errors::StatNotFoundError => e
36
+ e.response
37
+ end
38
+
39
+ expect(response).to be_a(Hash)
40
+ expect(response).to have_key(stat)
41
+ end
42
+ end
43
+ end
@@ -14,6 +14,9 @@ describe IEX::Resources::News do
14
14
  expect(news.datetime.to_f).to eq 1_554_412_248.0
15
15
  expect(news.headline).to eq "Spotify joins Microsoft's Xbox Game Bar"
16
16
  expect(news.related).to eq(['MSFT'])
17
+ expect(news.image).to eq('https://cloud.iexapis.com/beta/news/image/b8a6ae18-ab19-42e8-b066-d9a9dc111f1f')
18
+ expect(news.paywalled).to eq(false)
19
+ expect(news.language).to eq('en')
17
20
  end
18
21
  end
19
22
  context 'with range', vcr: { cassette_name: 'news/msft_7' } do
@@ -9,8 +9,22 @@ describe IEX::Api::Client do
9
9
 
10
10
  it 'converts ISIN to IEX Cloud symbols' do
11
11
  expect(subject.count).to eq(2)
12
- expect(subject.first).to eq('exchange' => 'NAS', 'iex_id' => 'IEX_4D48333344362D52', 'region' => 'US', 'symbol' => 'AAPL')
13
- expect(subject.last).to eq('exchange' => 'ETR', 'iex_id' => 'IEX_464D46474C312D52', 'region' => 'DE', 'symbol' => 'APC-GY')
12
+ expect(subject.first).to eq('exchange' => 'NAS', 'iex_id' => 'IEX_4D48333344362D52', 'region' => 'US',
13
+ 'symbol' => 'AAPL')
14
+ expect(subject.last).to eq('exchange' => 'ETR', 'iex_id' => 'IEX_464D46474C312D52', 'region' => 'DE',
15
+ 'symbol' => 'APC-GY')
16
+ end
17
+ end
18
+
19
+ context 'graciously handle parameter as string', vcr: { cassette_name: 'ref-data/isin' } do
20
+ subject { client.ref_data_isin('US0378331005') }
21
+
22
+ it 'converts ISIN to IEX Cloud symbols' do
23
+ expect(subject.count).to eq(2)
24
+ expect(subject.first).to eq('exchange' => 'NAS', 'iex_id' => 'IEX_4D48333344362D52', 'region' => 'US',
25
+ 'symbol' => 'AAPL')
26
+ expect(subject.last).to eq('exchange' => 'ETR', 'iex_id' => 'IEX_464D46474C312D52', 'region' => 'DE',
27
+ 'symbol' => 'APC-GY')
14
28
  end
15
29
  end
16
30
 
@@ -20,20 +34,25 @@ describe IEX::Api::Client do
20
34
  it 'converts ISINs to IEX Cloud symbols mapped by ISIN' do
21
35
  expect(subject.keys).to contain_exactly('US0378331005', 'US5949181045')
22
36
 
23
- expect(subject['US0378331005'].first).to eq('exchange' => 'NAS', 'iex_id' => 'IEX_4D48333344362D52', 'region' => 'US', 'symbol' => 'AAPL')
24
- expect(subject['US0378331005'].last).to eq('exchange' => 'ETR', 'iex_id' => 'IEX_464D46474C312D52', 'region' => 'DE', 'symbol' => 'APC-GY')
37
+ expect(subject['US0378331005'].first).to eq('exchange' => 'NAS', 'iex_id' => 'IEX_4D48333344362D52',
38
+ 'region' => 'US', 'symbol' => 'AAPL')
39
+ expect(subject['US0378331005'].last).to eq('exchange' => 'ETR', 'iex_id' => 'IEX_464D46474C312D52',
40
+ 'region' => 'DE', 'symbol' => 'APC-GY')
25
41
 
26
- expect(subject['US5949181045'][0]).to eq('exchange' => 'NAS', 'iex_id' => 'IEX_5038523343322D52', 'region' => 'US', 'symbol' => 'MSFT')
27
- expect(subject['US5949181045'][1]).to eq('exchange' => 'ETR', 'iex_id' => 'IEX_4C42583859482D52', 'region' => 'DE', 'symbol' => 'MSF-GY')
28
- expect(subject['US5949181045'][2]).to eq('exchange' => 'BRU', 'iex_id' => 'IEX_5833345950432D52', 'region' => 'BE', 'symbol' => 'MSF-BB')
42
+ expect(subject['US5949181045'][0]).to eq('exchange' => 'NAS', 'iex_id' => 'IEX_5038523343322D52',
43
+ 'region' => 'US', 'symbol' => 'MSFT')
44
+ expect(subject['US5949181045'][1]).to eq('exchange' => 'ETR', 'iex_id' => 'IEX_4C42583859482D52',
45
+ 'region' => 'DE', 'symbol' => 'MSF-GY')
46
+ expect(subject['US5949181045'][2]).to eq('exchange' => 'BRU', 'iex_id' => 'IEX_5833345950432D52',
47
+ 'region' => 'BE', 'symbol' => 'MSF-BB')
29
48
  end
49
+ end
30
50
 
31
- context 'with wrong ISIN', vcr: { cassette_name: 'ref-data/wrong_isin_mapped' } do
32
- subject { client.ref_data_isin(%w[WRONG12345], mapped: true) }
51
+ context 'with wrong ISIN', vcr: { cassette_name: 'ref-data/wrong_isin_mapped' } do
52
+ subject { client.ref_data_isin(%w[WRONG12345], mapped: true) }
33
53
 
34
- it 'returns nil value for given ISIN' do
35
- expect(subject).to eq('WRONG12345' => nil)
36
- end
54
+ it 'returns nil value for given ISIN' do
55
+ expect(subject).to eq('WRONG12345' => nil)
37
56
  end
38
57
  end
39
58
  end
@@ -63,4 +82,30 @@ describe IEX::Api::Client do
63
82
  end
64
83
  end
65
84
  end
85
+
86
+ describe '#ref_data_symbols_for_exchange', vcr: { cassette_name: 'ref-data/exchange_symbols' } do
87
+ subject { client.ref_data_symbols_for_exchange('TSX') }
88
+
89
+ it 'retrieves all symbols' do
90
+ expect(subject.count).to eq 1869
91
+ end
92
+
93
+ context 'first symbol' do
94
+ subject { client.ref_data_symbols_for_exchange('TSX').first }
95
+ it 'retrieves a symbol data' do
96
+ expect(subject.symbol).to eq 'A-CV'
97
+ expect(subject.exchange).to eq 'TSX'
98
+ expect(subject.name).to eq 'Armor Minerals Inc'
99
+ expect(subject.date).to eq Date.parse('2021-05-14')
100
+ expect(subject.enabled).to eq true
101
+ expect(subject.enabled?).to eq true
102
+ expect(subject.type).to eq 'cs'
103
+ expect(subject.region).to eq 'CA'
104
+ expect(subject.currency).to eq 'CAD'
105
+ expect(subject.iex_id).to eq 'IEX_4656374258322D52'
106
+ expect(subject.figi).to eq 'BBG000V98LH2'
107
+ expect(subject.cik).to eq '0001682145'
108
+ end
109
+ end
110
+ end
66
111
  end