iex-ruby-client 1.2.0 → 1.5.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.
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
@@ -3,6 +3,7 @@ require 'spec_helper'
3
3
  describe IEX::Api::Client do
4
4
  before do
5
5
  IEX::Api.config.reset!
6
+ IEX::Api.logger.reset!
6
7
  end
7
8
  context 'with defaults' do
8
9
  let(:client) { described_class.new }
@@ -14,7 +15,7 @@ describe IEX::Api::Client do
14
15
  expect(client.user_agent).to eq "IEX Ruby Client/#{IEX::VERSION}"
15
16
  end
16
17
  it 'sets user-agent' do
17
- expect(client.user_agent).to eq IEX::Api::Config.user_agent
18
+ expect(client.user_agent).to eq IEX::Api::Config::Client.user_agent
18
19
  expect(client.user_agent).to include IEX::VERSION
19
20
  end
20
21
  it 'caches the Faraday connection to allow persistent adapters' do
@@ -22,20 +23,24 @@ describe IEX::Api::Client do
22
23
  second = client.send(:connection)
23
24
  expect(first).to equal second
24
25
  end
25
- (IEX::Api::Config::ATTRIBUTES - [:logger]).each do |key|
26
+ it 'sets a nil logger' do
27
+ expect(client.logger.instance).to be_nil
28
+ expect(client.send(:connection).builder.handlers).not_to include(::Faraday::Response::Logger)
29
+ end
30
+ IEX::Api::Config::Client::ATTRIBUTES.each do |key|
26
31
  it "sets #{key}" do
27
- expect(client.send(key)).to eq IEX::Api::Config.send(key)
32
+ expect(client.send(key)).to eq IEX::Api::Config::Client.send(key)
28
33
  end
29
34
  end
30
35
  end
31
36
  end
32
37
  context 'with custom settings' do
33
38
  context '#initialize' do
34
- IEX::Api::Config::ATTRIBUTES.each do |key|
39
+ IEX::Api::Config::Client::ATTRIBUTES.each do |key|
35
40
  context key.to_s do
36
41
  let(:client) { described_class.new(key => 'custom') }
37
42
  it "sets #{key}" do
38
- expect(client.send(key)).to_not eq IEX::Api::Config.send(key)
43
+ expect(client.send(key)).to_not eq IEX::Api::Config::Client.send(key)
39
44
  expect(client.send(key)).to eq 'custom'
40
45
  end
41
46
  end
@@ -96,22 +101,74 @@ describe IEX::Api::Client do
96
101
  end
97
102
  end
98
103
  end
104
+
99
105
  context 'logger option' do
100
106
  let(:logger) { Logger.new(STDOUT) }
101
- before do
102
- IEX::Api.configure do |config|
103
- config.logger = logger
107
+
108
+ after { IEX::Api.logger.reset! }
109
+
110
+ context 'when assigning an instance' do
111
+ context '#initialize' do
112
+ context 'when directly assigning `logger`' do
113
+ before { IEX::Api.logger = logger }
114
+
115
+ it 'sets logger' do
116
+ expect(client.logger.instance).to eq(logger)
117
+ end
118
+
119
+ it 'creates a connection with a logger' do
120
+ expect(client.send(:connection).builder.handlers).to include ::Faraday::Response::Logger
121
+ end
122
+ end
123
+
124
+ context 'when assigning through `configure.logger`' do
125
+ it 'sets the logger' do
126
+ IEX::Api.configure.logger = logger
127
+ expect(client.logger.instance).to eq(logger)
128
+ end
129
+ end
130
+
131
+ context 'when passing in at initialization' do
132
+ it 'sets the logger' do
133
+ client = described_class.new(logger: logger)
134
+ expect(client.logger.instance).to eq(logger)
135
+ end
136
+
137
+ it 'can overwrite a set logger' do
138
+ IEX::Api.logger = logger
139
+ client = described_class.new(logger: nil)
140
+ expect(client.logger.instance).to be_nil
141
+ end
142
+ end
104
143
  end
105
144
  end
106
- context '#initialize' do
107
- it 'sets logger' do
108
- expect(client.logger).to eq logger
145
+
146
+ context 'when assigning a configuration' do
147
+ let(:opts) { { bodies: true } }
148
+ let(:proc_arg) { proc {} }
149
+
150
+ before do
151
+ IEX::Api.logger do |log_config|
152
+ log_config.instance = logger
153
+ log_config.options = opts
154
+ log_config.proc = proc_arg
155
+ end
109
156
  end
110
- it 'creates a connection with a logger' do
111
- expect(client.send(:connection).builder.handlers).to include ::Faraday::Response::Logger
157
+
158
+ context '#initialize' do
159
+ it 'sets logger' do
160
+ expect(client.logger.instance).to eq logger
161
+ expect(client.logger.options).to eq opts
162
+ expect(client.logger.proc).to eq proc_arg
163
+ end
164
+
165
+ it 'creates a connection with a logger' do
166
+ expect(client.send(:connection).builder.handlers).to include ::Faraday::Response::Logger
167
+ end
112
168
  end
113
169
  end
114
170
  end
171
+
115
172
  context 'timeout options' do
116
173
  before do
117
174
  IEX::Api.configure do |config|
@@ -131,6 +188,27 @@ describe IEX::Api::Client do
131
188
  end
132
189
  end
133
190
  end
191
+
192
+ context 'when resetting/changing configuration' do
193
+ before do
194
+ IEX::Api.configure { |config| config.user_agent = 'custom/user-agent' }
195
+ end
196
+
197
+ it 'does not reset the client' do
198
+ expect { IEX::Api.config.reset! }.not_to change(client, :user_agent).from('custom/user-agent')
199
+ end
200
+
201
+ it 'effects the next client' do
202
+ pre_config_client = described_class.new
203
+ IEX::Api.configure { |config| config.user_agent = 'custom/user-agent-2' }
204
+ expect(described_class.new.user_agent).not_to eq(pre_config_client.user_agent)
205
+ end
206
+
207
+ it 'should not allow the client to reset' do
208
+ expect { client.reset! }.to raise_error(NoMethodError)
209
+ end
210
+ end
211
+
134
212
  context 'without a token' do
135
213
  let(:client) { described_class.new }
136
214
  it 'results in an API key error', vcr: { cassette_name: 'client/access_denied' } do
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Api::Config::Client do
4
+ before do
5
+ IEX::Api.config.reset!
6
+ end
7
+ describe '#defaults' do
8
+ it 'sets endpoint' do
9
+ expect(IEX::Api.config.endpoint).to eq 'https://cloud.iexapis.com/v1'
10
+ end
11
+ end
12
+ describe '#configure' do
13
+ before do
14
+ IEX::Api.configure do |config|
15
+ config.endpoint = 'updated'
16
+ end
17
+ end
18
+ it 'sets endpoint' do
19
+ expect(IEX::Api.config.endpoint).to eq 'updated'
20
+ end
21
+ end
22
+
23
+ context 'when configuring the logger' do
24
+ after { IEX::Api.configure.logger.reset! }
25
+
26
+ let(:logger) { Logger.new(STDOUT) }
27
+
28
+ describe '#logger=' do
29
+ it 'updates IEX::Api.config correctly' do
30
+ expect do
31
+ IEX::Api.configure { |config| config.logger = logger }
32
+ end.to change(IEX::Api.config.logger, :instance).from(nil).to(logger)
33
+ end
34
+
35
+ it 'updates IEX::Api.logger correctly' do
36
+ expect do
37
+ IEX::Api.configure { |config| config.logger = logger }
38
+ end.to change(IEX::Api.logger, :instance).from(nil).to(logger)
39
+ end
40
+ end
41
+
42
+ describe '#logger' do
43
+ it 'accesses the current logger' do
44
+ expect { IEX::Api.logger = logger }
45
+ .to change(IEX::Api.config.logger, :instance).from(nil).to(logger)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Api::Config::Logger do
4
+ after { IEX::Api.logger.reset! }
5
+
6
+ describe '#defaults' do
7
+ it 'sets the default values' do
8
+ expect(IEX::Api.logger.instance).to be_nil
9
+ expect(IEX::Api.logger.options).to eq({})
10
+ expect(IEX::Api.logger.proc).to be_nil
11
+ end
12
+ end
13
+
14
+ describe '#logger' do
15
+ let(:logger_instance) { Logger.new(STDOUT) }
16
+ let(:opts) { { bodies: true } }
17
+ let(:proc_arg) { proc {} }
18
+
19
+ it 'allows setting the instance directly' do
20
+ expect { IEX::Api.logger = logger_instance }
21
+ .to change(IEX::Api::Config::Logger, :instance).to(logger_instance)
22
+ end
23
+
24
+ context 'when configuing' do
25
+ after do
26
+ expect(IEX::Api.logger.instance).to eq(logger_instance)
27
+ expect(IEX::Api.logger.options).to eq(opts)
28
+ expect(IEX::Api.logger.proc).to eq(proc_arg)
29
+ end
30
+
31
+ it 'sets via assignment' do
32
+ IEX::Api.logger.instance = logger_instance
33
+ IEX::Api.logger.options = opts
34
+ IEX::Api.logger.proc = proc_arg
35
+ end
36
+
37
+ it 'sets via block' do
38
+ IEX::Api.logger do |logger|
39
+ logger.instance = logger_instance
40
+ logger.options = opts
41
+ logger.proc = proc_arg
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Resources::AdvancedStats do
4
+ include_context 'client'
5
+
6
+ context 'general information', vcr: { cassette_name: 'advanced_stats/msft' } do
7
+ subject do
8
+ client.advanced_stats('MSFT')
9
+ end
10
+
11
+ it 'fetches advanced stats' do
12
+ expect(subject.total_cash).to eq 136_527_000_000
13
+ expect(subject.total_cash_dollars).to eq '$136,527,000,000'
14
+ expect(subject.current_debt).to eq 5_905_000_000
15
+ expect(subject.current_debt_dollars).to eq '$5,905,000,000'
16
+ expect(subject.revenue).to eq 143_015_000_000
17
+ expect(subject.revenue_dollars).to eq '$143,015,000,000'
18
+ expect(subject.gross_profit).to eq 96_937_000_000
19
+ expect(subject.gross_profit_dollar).to eq '$96,937,000,000'
20
+ expect(subject.total_revenue).to eq 143_015_000_000
21
+ expect(subject.total_revenue_dollar).to eq '$143,015,000,000'
22
+ expect(subject.ebitda).to eq 65_259_000_000
23
+ expect(subject.ebitda_dollar).to eq '$65,259,000,000'
24
+ expect(subject.revenue_per_share).to eq 18.9
25
+ expect(subject.revenue_per_share_dollars).to eq '$18'
26
+ expect(subject.revenue_per_employee).to eq 877_392.64
27
+ expect(subject.revenue_per_employee_dollar).to eq '$877,392'
28
+ expect(subject.debt_to_equity).to eq 0.69
29
+ expect(subject.profit_margin).to eq 0.3096248645247002
30
+ expect(subject.enterprise_value).to eq 1_607_892_999_000
31
+ expect(subject.enterprise_value_dollar).to eq '$1,607,892,999,000'
32
+ expect(subject.enterprise_value_to_revenue).to eq 11.24
33
+ expect(subject.price_to_sales).to eq 11.62
34
+ expect(subject.price_to_sales_dollar).to eq '$11'
35
+ expect(subject.price_to_book).to eq 13.703188252299162
36
+ expect(subject.forward_pe_ratio).to eq nil
37
+ expect(subject.peg_ratio).to eq 5.6
38
+ expect(subject.pe_high).to eq 40.49739130434783
39
+ expect(subject.week_52_high_date).to eq '2020-09-02'
40
+ expect(subject.pe_low).to eq 23.046956521739133
41
+ expect(subject.week_52_low_date).to eq '2020-03-23'
42
+ expect(subject.put_call_ratio).to eq 0.36251766583920975
43
+ end
44
+
45
+ it 'retrieves a keyStats' do
46
+ expect(subject.company_name).to eq 'Microsoft Corp.'
47
+ expect(subject.market_cap).to eq 1_621_141_983_000
48
+ expect(subject.market_cap_dollar).to eq '$1,621,141,983,000'
49
+ expect(subject.employees).to eq 163_000
50
+ end
51
+
52
+ it 'weekly stats' do
53
+ expect(subject.week_52_high).to eq 232.86
54
+ expect(subject.week_52_high_dollar).to eq '$232.86'
55
+ expect(subject.week_52_low).to eq 132.52
56
+ expect(subject.week_52_low_dollar).to eq '$132.52'
57
+ expect(subject.week_52_change).to eq 0.533539
58
+ expect(subject.week_52_change_dollar).to eq '$0.53'
59
+ end
60
+
61
+ it 'general stats' do
62
+ expect(subject.ttm_dividend_rate).to eq 2.04
63
+ expect(subject.dividend_yield).to eq 0.009522920362244423
64
+ expect(subject.ex_dividend_date).to eq '2020-08-19'
65
+ expect(subject.shares_outstanding).to eq 7_567_650_000
66
+ expect(subject.float).to eq 7_454_581_741
67
+ expect(subject.ttm_eps).to eq 5.8207
68
+ expect(subject.next_dividend_date).to eq '2020-11-18'
69
+ expect(subject.next_earnings_date).to eq '2020-10-27'
70
+ expect(subject.pe_ratio).to eq 36.88
71
+ expect(subject.beta).to eq 1.1472751624864646
72
+ expect(subject.day_200_moving_avg).to eq 187.72
73
+ expect(subject.day_50_moving_avg).to eq 212.09
74
+ end
75
+
76
+ it 'changes stats' do
77
+ expect(subject.avg_10_volume).to be 26_989_991
78
+ expect(subject.avg_30_volume).to be 31_404_571.1
79
+ expect(subject.max_change_percent).to eq 7.1248
80
+ expect(subject.year_5_change_percent).to be 3.3093
81
+ expect(subject.year_5_change_percent_s).to eq '+330.93%'
82
+ expect(subject.year_2_change_percent).to eq 1.0108
83
+ expect(subject.year_2_change_percent_s).to eq '+101.08%'
84
+ expect(subject.year_1_change_percent).to eq 0.572482
85
+ expect(subject.year_1_change_percent_s).to eq '+57.25%'
86
+ expect(subject.ytd_change_percent).to eq 0.367576
87
+ expect(subject.ytd_change_percent_s).to eq '+36.76%'
88
+ expect(subject.month_6_change_percent).to eq 0.229899
89
+ expect(subject.month_6_change_percent_s).to eq '+22.99%'
90
+ expect(subject.month_3_change_percent).to eq 0.082709
91
+ expect(subject.month_3_change_percent_s).to eq '+8.27%'
92
+ expect(subject.month_1_change_percent).to eq 0.082549
93
+ expect(subject.month_1_change_percent_s).to eq '+8.25%'
94
+ expect(subject.day_5_change_percent).to eq(-0.007859)
95
+ expect(subject.day_5_change_percent_s).to eq '-0.79%'
96
+ expect(subject.day_30_change_percent).to eq 0.025251
97
+ expect(subject.day_30_change_percent_s).to eq '+2.53%'
98
+ end
99
+ end
100
+
101
+ context 'invalid symbol', vcr: { cassette_name: 'advanced_stats/invalid' } do
102
+ subject do
103
+ client.advanced_stats('INVALID')
104
+ end
105
+
106
+ it 'fails with SymbolNotFoundError' do
107
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Resources::BalanceSheet do
4
+ include_context 'client'
5
+
6
+ context 'general information', vcr: { cassette_name: 'balance_sheet/msft' } do
7
+ subject do
8
+ client.balance_sheet('MSFT')
9
+ end
10
+ let(:balance_sheet) { subject.first }
11
+
12
+ it 'fetches balance sheet' do
13
+ expect(subject.size).to eq 1
14
+ expect(balance_sheet.report_date).to eq '2020-09-30'
15
+ expect(balance_sheet.fiscal_date).to eq '2020-09-30'
16
+ expect(balance_sheet.currency).to eq 'USD'
17
+ expect(balance_sheet.current_cash).to eq 17_205_000_000
18
+ expect(balance_sheet.current_cash_dollar).to eq '$17,205,000,000'
19
+ expect(balance_sheet.short_term_investments).to eq 120_772_000_000
20
+ expect(balance_sheet.short_term_investments_dollar).to eq '$120,772,000,000'
21
+ expect(balance_sheet.receivables).to eq 22_851_000_000
22
+ expect(balance_sheet.receivables_dollar).to eq '$22,851,000,000'
23
+ expect(balance_sheet.inventory).to eq 2_705_000_000
24
+ expect(balance_sheet.inventory_dollar).to eq '$2,705,000,000'
25
+ expect(balance_sheet.other_current_assets).to eq 13_544_000_000
26
+ expect(balance_sheet.other_current_assets_dollar).to eq '$13,544,000,000'
27
+ expect(balance_sheet.current_assets).to eq 177_077_000_000
28
+ expect(balance_sheet.current_assets_dollar).to eq '$177,077,000,000'
29
+ expect(balance_sheet.long_term_investments).to eq 3_196_000_000
30
+ expect(balance_sheet.long_term_investments_dollar).to eq '$3,196,000,000'
31
+ expect(balance_sheet.property_plant_equipment).to eq 56_974_000_000
32
+ expect(balance_sheet.property_plant_equipment_dollar).to eq '$56,974,000,000'
33
+ expect(balance_sheet.goodwill).to eq 43_890_000_000
34
+ expect(balance_sheet.goodwill_dollar).to eq '$43,890,000,000'
35
+ expect(balance_sheet.intangible_assets).to eq 6_923_000_000
36
+ expect(balance_sheet.intangible_assets_dollar).to eq '$6,923,000,000'
37
+ expect(balance_sheet.other_assets).to eq 12_941_000_000
38
+ expect(balance_sheet.other_assets_dollar).to eq '$12,941,000,000'
39
+ expect(balance_sheet.total_assets).to eq 301_001_000_000
40
+ expect(balance_sheet.total_assets_dollar).to eq '$301,001,000,000'
41
+ expect(balance_sheet.accounts_payable).to eq 12_509_000_000
42
+ expect(balance_sheet.accounts_payable_dollar).to eq '$12,509,000,000'
43
+ expect(balance_sheet.current_long_term_debt).to eq 7_093_000_000
44
+ expect(balance_sheet.current_long_term_debt_dollar).to eq '$7,093,000,000'
45
+ expect(balance_sheet.other_current_liabilities).to eq 46_326_000_000
46
+ expect(balance_sheet.other_current_liabilities_dollar).to eq '$46,326,000,000'
47
+ expect(balance_sheet.total_current_liabilities).to eq 70_056_000_000
48
+ expect(balance_sheet.total_current_liabilities_dollar).to eq '$70,056,000,000'
49
+ expect(balance_sheet.long_term_debt).to eq 74_379_000_000
50
+ expect(balance_sheet.long_term_debt_dollar).to eq '$74,379,000,000'
51
+ expect(balance_sheet.other_liabilities).to eq 32_987_000_000
52
+ expect(balance_sheet.other_liabilities_dollar).to eq '$32,987,000,000'
53
+ expect(balance_sheet.minority_interest).to eq 0
54
+ expect(balance_sheet.minority_interest_dollar).to eq '$0'
55
+ expect(balance_sheet.total_liabilities).to eq 177_609_000_000
56
+ expect(balance_sheet.total_liabilities_dollar).to eq '$177,609,000,000'
57
+ expect(balance_sheet.common_stock).to eq 7_564_000_000
58
+ expect(balance_sheet.retained_earnings).to eq 39_193_000_000
59
+ expect(balance_sheet.retained_earnings_dollar).to eq '$39,193,000,000'
60
+ expect(balance_sheet.treasury_stock).to eq nil
61
+ expect(balance_sheet.treasury_stock_dollar).to eq nil
62
+ expect(balance_sheet.capital_surplus).to eq nil
63
+ expect(balance_sheet.capital_surplus_dollar).to eq nil
64
+ expect(balance_sheet.shareholder_equity).to eq 123_392_000_000
65
+ expect(balance_sheet.shareholder_equity_dollar).to eq '$123,392,000,000'
66
+ expect(balance_sheet.net_tangible_assets).to eq 17_585_000_000
67
+ expect(balance_sheet.net_tangible_assets_dollar).to eq '$17,585,000,000'
68
+ end
69
+ end
70
+
71
+ context 'invalid symbol', vcr: { cassette_name: 'balance_sheet/invalid' } do
72
+ subject do
73
+ client.balance_sheet('INVALID')
74
+ end
75
+
76
+ it 'fails with SymbolNotFoundError' do
77
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Resources::CashFlow do
4
+ include_context 'client'
5
+
6
+ context 'general information', vcr: { cassette_name: 'cash_flow/msft' } do
7
+ subject do
8
+ client.cash_flow('MSFT')
9
+ end
10
+ let(:cash_flow) { subject.first }
11
+
12
+ it 'fetches cash flow statement' do
13
+ expect(subject.size).to eq 1
14
+ expect(cash_flow.report_date).to eq '2020-09-30'
15
+ expect(cash_flow.fiscal_date).to eq '2020-09-30'
16
+ expect(cash_flow.currency).to eq 'USD'
17
+ expect(cash_flow.net_income).to eq 13_893_000_000
18
+ expect(cash_flow.net_income_dollar).to eq '$13,893,000,000'
19
+ expect(cash_flow.depreciation).to eq 2_645_000_000
20
+ expect(cash_flow.depreciation_dollar).to eq '$2,645,000,000'
21
+ expect(cash_flow.changes_in_receivables).to eq 9_160_000_000
22
+ expect(cash_flow.changes_in_receivables_dollar).to eq '$9,160,000,000'
23
+ expect(cash_flow.changes_in_inventories).to eq(-808_000_000)
24
+ expect(cash_flow.changes_in_inventories_dollar).to eq '$-808,000,000'
25
+ expect(cash_flow.cash_change).to eq 3_629_000_000
26
+ expect(cash_flow.cash_change_dollar).to eq '$3,629,000,000'
27
+ expect(cash_flow.cash_flow).to eq 19_335_000_000
28
+ expect(cash_flow.cash_flow_dollar).to eq '$19,335,000,000'
29
+ expect(cash_flow.capital_expenditures).to eq(-4_907_000_000)
30
+ expect(cash_flow.capital_expenditures_dollar).to eq '$-4,907,000,000'
31
+ expect(cash_flow.investments).to eq 2_100_000_000
32
+ expect(cash_flow.investments_dollar).to eq '$2,100,000,000'
33
+ expect(cash_flow.investing_activity_other).to eq(-2_083_000_000)
34
+ expect(cash_flow.investing_activity_other_dollar).to eq '$-2,083,000,000'
35
+ expect(cash_flow.total_investing_cash_flows).to eq(-5_371_000_000)
36
+ expect(cash_flow.total_investing_cash_flows_dollar).to eq '$-5,371,000,000'
37
+ expect(cash_flow.dividends_paid).to eq(-3_856_000_000)
38
+ expect(cash_flow.dividends_paid_dollar).to eq '$-3,856,000,000'
39
+ expect(cash_flow.net_borrowings).to eq nil
40
+ expect(cash_flow.net_borrowings_dollar).to eq nil
41
+ expect(cash_flow.other_financing_cash_flows).to eq(-235_000_000)
42
+ expect(cash_flow.other_financing_cash_flows_dollar).to eq '$-235,000,000'
43
+ expect(cash_flow.cash_flow_financing).to eq(-10_289_000_000)
44
+ expect(cash_flow.cash_flow_financing_dollar).to eq '$-10,289,000,000'
45
+ expect(cash_flow.exchange_rate_effect).to eq(-46_000_000)
46
+ expect(cash_flow.exchange_rate_effect_dollar).to eq '$-46,000,000'
47
+ end
48
+ end
49
+
50
+ context 'invalid symbol', vcr: { cassette_name: 'cash_flow/invalid' } do
51
+ subject do
52
+ client.cash_flow('INVALID')
53
+ end
54
+
55
+ it 'fails with SymbolNotFoundError' do
56
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
57
+ end
58
+ end
59
+ end