halcyon_api 0.0.5

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.
@@ -0,0 +1,249 @@
1
+ require 'spec_helper'
2
+
3
+ describe HalcyonAPI::Client, vcr: true do
4
+ let(:valid_api_key) { 'valid_api_key' }
5
+ let(:client) { subject.new(valid_api_key) }
6
+ let(:cached_matches) { let_cassette('matches') { client.matches } }
7
+ let(:cached_players) { cached_matches.included.select { |i| i.type == 'player' }}
8
+
9
+ it 'validates the region' do
10
+ expect { subject.new('API KEY', 'QQ') }.to raise_error HalcyonAPI::RegionNameError
11
+ end
12
+
13
+ describe 'metadata' do
14
+ it 'returns an error with an invalid API key' do
15
+ VCR.use_cassette('api_key', record: :new_episodes) do
16
+ response = subject.new('invalid-api-key').samples
17
+ expects_error_response(response, 401)
18
+ end
19
+ end
20
+
21
+ it 'returns success and API rate limit information' do
22
+ VCR.use_cassette('samples', record: :new_episodes) do
23
+ response = client.samples
24
+
25
+ expects_success_response(response)
26
+ expects_presence(response, :data)
27
+ expect(response.rate_limit).to be_a(Integer)
28
+ expect(response.rate_remaining).to be_a(Integer)
29
+ expect(response.rate_reset).to be_a(Integer)
30
+ end
31
+ end
32
+
33
+ it 'supports multiple regions' do
34
+ VCR.use_cassette('samples', record: :new_episodes) do
35
+ %w(eu sa ea sg).each do |region|
36
+ response = subject.new(valid_api_key, region).samples
37
+ expects_success_response(response)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '#status' do
44
+ it 'returns a status object' do
45
+ VCR.use_cassette('status') do
46
+ response = client.status
47
+
48
+ expects_success_response(response)
49
+ expects_presence(response, :data)
50
+ expect(response.data.type).to be_a(String)
51
+ expect(response.data.id).to be_a(String)
52
+ expect(response.data.attributes.releasedAt).to be_a(String)
53
+ expect(response.data.attributes.version).to be_a(String)
54
+ end
55
+ end
56
+ end
57
+
58
+ describe '#players' do
59
+ it 'returns an array of players with a valid name' do
60
+ VCR.use_cassette('players', record: :new_episodes) do
61
+ valid_names = cached_players[0, 2].map { |p| p.attributes.name }
62
+ response = client.players(*valid_names)
63
+
64
+ expects_success_response(response)
65
+ expects_presence(response, :data, :links, :meta)
66
+ expect(response.data).to be_a(Array)
67
+ expect(response.data.length).to be > 0
68
+ end
69
+ end
70
+
71
+ it 'returns error with an valid name' do
72
+ VCR.use_cassette('players', record: :new_episodes) do
73
+ response = client.players('TheRealKrul')
74
+ expects_error_response(response)
75
+ end
76
+ end
77
+ end
78
+
79
+ describe '#player' do
80
+ it 'returns a player with a valid ID' do
81
+ VCR.use_cassette('player', record: :new_episodes) do
82
+ cached_player_id = cached_players.first.id
83
+ response = client.player(cached_player_id)
84
+
85
+ player = response.data
86
+
87
+ expects_success_response(response)
88
+ expects_presence(response, :data, :links, :meta)
89
+
90
+ expect(player.type).to eq 'player'
91
+ expect(player.id).to eq cached_player_id
92
+ expect(player.attributes.createdAt).to be_a(String)
93
+ expect(player.attributes.name).to be_a(String)
94
+ expect(player.attributes.shardId).to be_a(String)
95
+ expect(player.attributes.stats.level).to be_a(Integer)
96
+ expect(player.attributes.stats.lifetimeGold).to be_a(Float)
97
+ expect(player.attributes.stats.lossStreak).to be_a(Integer)
98
+ expect(player.attributes.stats.played).to be_a(Integer)
99
+ expect(player.attributes.stats.played_ranked).to be_a(Integer)
100
+ expect(player.attributes.stats.winStreak).to be_a(Integer)
101
+ expect(player.attributes.stats.wins).to be_a(Integer)
102
+ expect(player.attributes.stats.xp).to be_a(Integer)
103
+ expect(player.attributes.titleId).to be_a(String)
104
+ end
105
+ end
106
+
107
+ it 'returns an error with an invalid ID' do
108
+ VCR.use_cassette('players', record: :new_episodes) do
109
+ response = client.player('invalid-id')
110
+ expects_error_response(response)
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '#matches' do
116
+ it 'returns an array of matches' do
117
+ VCR.use_cassette('matches', record: :new_episodes) do
118
+ response = client.matches
119
+
120
+ expects_success_response(response)
121
+ expects_presence(response, :data, :included, :links, :meta)
122
+ expect(response.data).to be_a(Array)
123
+ expect(response.data.length).to be > 0
124
+ end
125
+ end
126
+
127
+ it 'returns the number of matches specified by a filter' do
128
+ VCR.use_cassette('matches', record: :new_episodes) do
129
+ response = client.matches('page[limit]' => 1)
130
+
131
+ expects_success_response(response)
132
+ expects_presence(response, :data, :included, :links, :meta)
133
+ expect(response.data).to be_a(Array)
134
+ expect(response.data.length).to eq 1
135
+ end
136
+ end
137
+
138
+ it 'returns an array of matches with valid player name filter' do
139
+ player_name = cached_players.first.attributes.name
140
+ VCR.use_cassette('matches', record: :new_episodes) do
141
+ response = client.matches('filter[playerNames]' => player_name)
142
+
143
+ expects_success_response(response)
144
+ expects_presence(response, :data, :included, :links, :meta)
145
+ expect(response.data).to be_a(Array)
146
+ expect(response.data.length).to be > 0
147
+ end
148
+ end
149
+
150
+ it 'returns an error with invalid player name filter' do
151
+ VCR.use_cassette('matches', record: :new_episodes) do
152
+ response = client.matches('filter[playerNames]' => 'TheRealKrul')
153
+ expects_error_response(response)
154
+ end
155
+ end
156
+ end
157
+
158
+ describe '#match' do
159
+ it 'returns a match with a valid ID' do
160
+ VCR.use_cassette('match', record: :new_episodes) do
161
+ cached_match_id = cached_matches.data.first.id
162
+ response = client.match(cached_match_id)
163
+ game_match = response.data
164
+
165
+ expects_success_response(response)
166
+ expects_presence(response, :data, :included, :links, :meta)
167
+ expect(game_match.type).to eq 'match'
168
+ expect(game_match.id).to eq cached_match_id
169
+ expect(game_match.attributes.createdAt).to be_a(String)
170
+ expect(game_match.attributes.duration).to be_a(Integer)
171
+ expect(game_match.attributes.gameMode).to be_a(String)
172
+ expect(game_match.attributes.patchVersion).to be_a(String)
173
+ expect(game_match.attributes.shardId).to be_a(String)
174
+ expect(game_match.attributes.stats.endGameReason).to be_a(String)
175
+ expect(game_match.attributes.stats.queue).to be_a(String)
176
+ expect(game_match.attributes.titleId).to be_a(String)
177
+ expect(game_match.relationships.assets.data).to be_a(Array)
178
+ expect(game_match.relationships.assets.data[0].type).to be_a(String)
179
+ expect(game_match.relationships.assets.data[0].id).to be_a(String)
180
+ expect(game_match.relationships.rosters.data).to be_a(Array)
181
+ expect(game_match.relationships.rosters.data.length).to be_a(Integer)
182
+ expect(game_match.relationships.rounds.data).to be_a(Array)
183
+ expect(game_match.relationships.rounds.data.length).to be_a(Integer)
184
+ end
185
+ end
186
+
187
+ it 'returns an error with an invalid ID' do
188
+ VCR.use_cassette('match', record: :new_episodes) do
189
+ response = client.match('invalid-id')
190
+ expects_error_response(response)
191
+ end
192
+ end
193
+ end
194
+
195
+ describe '#telemetry' do
196
+ it 'returns telemetry data for a valid URL' do
197
+ VCR.use_cassette('telemetry', record: :new_episodes) do
198
+ response = client.telemetry('https://gl-prod-us-east-1.s3.amazonaws.com/assets/semc-vainglory/na/2017/03/28/03/07/b0bb7faf-1363-11e7-b11e-0242ac110006-telemetry.json')
199
+
200
+ expects_success_response(response)
201
+ expect(response.data).to be_a Array
202
+ expect(response.data[0].time).to be_a(String)
203
+ expect(response.data[0].type).to be_a(String)
204
+ expect(response.data[0].payload.Team).to be_a(String)
205
+ expect(response.data[0].payload.Actor).to be_a(String)
206
+ end
207
+ end
208
+ end
209
+
210
+ describe '#teams' do
211
+ it 'raises error' do
212
+ expect { client.teams }.to raise_error(NotImplementedError)
213
+ end
214
+ end
215
+
216
+ describe '#team' do
217
+ it 'raises error' do
218
+ expect { client.team('team_id') }.to raise_error(NotImplementedError)
219
+ end
220
+ end
221
+
222
+ describe '#link' do
223
+ it 'raises error' do
224
+ expect { client.link('link_id') }.to raise_error(NotImplementedError)
225
+ end
226
+ end
227
+
228
+ def expects_presence(obj, *attrs)
229
+ attrs.each do |attr_name|
230
+ expect(obj.send(attr_name)).to_not be_nil
231
+ end
232
+ end
233
+
234
+ def expects_success_response(response)
235
+ expect(response.code).to eq 200
236
+ expect(response.success?).to be true
237
+ end
238
+
239
+ def expects_error_response(response, response_code = 404)
240
+ expect(response.code).to eq response_code
241
+ expect(response.success?).to be false
242
+ end
243
+
244
+ def let_cassette(cassette_name)
245
+ VCR.use_cassette(cassette_name, record: :new_episodes) do
246
+ yield
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe HalcyonAPI::Region do
4
+ describe '#abbreviation' do
5
+ it 'returns the short name' do
6
+ region = subject.new('ea')
7
+ expect(region.abbreviation).to eq region.short_name
8
+ end
9
+ end
10
+
11
+ describe '#eql?' do
12
+ let(:region) { HalcyonAPI::Region['na'] }
13
+
14
+ it 'returns TRUE when all attributes match' do
15
+ expect(region.eql?(HalcyonAPI::Region.new('na'))).to be true
16
+ end
17
+
18
+ it 'returns FALSE when any attribute does not match' do
19
+ expect(region.eql?(HalcyonAPI::Region.new('eu'))).to be false
20
+ end
21
+ end
22
+
23
+ describe '.new' do
24
+ it 'instantiates a Region from the DB matching the identifier' do
25
+ expect(subject.new('North America')).to be_an_instance_of(subject)
26
+ end
27
+
28
+ it 'find a region by short name (abbreviation)' do
29
+ expect(subject.new('eu')).to be_an_instance_of(subject)
30
+ end
31
+
32
+ it 'raises an error when region identifier not found' do
33
+ expect { subject.new('QQ') }.to raise_error HalcyonAPI::RegionNameError
34
+ end
35
+ end
36
+
37
+ describe '.find' do
38
+ it 'aliases .new' do
39
+ expect(subject.find('na')).to eql subject.new('na')
40
+ end
41
+ end
42
+
43
+ describe '.[]' do
44
+ it 'aliases .new' do
45
+ expect(subject['na']).to eql subject.new('na')
46
+ end
47
+ end
48
+
49
+ describe '.valid_short_name?' do
50
+ it 'returns TRUE when the short name is found' do
51
+ expect(subject.valid_short_name?('tournament-sa')).to be true
52
+ end
53
+
54
+ it 'returns FALSE when the short name is not found' do
55
+ expect(subject.valid_short_name?('QQ')).to be false
56
+ end
57
+ end
58
+
59
+ describe '.detect_region_info' do
60
+ it 'returns an Array of region data when identifier is found' do
61
+ region_info = subject.detect_region_info('na')
62
+ expect(region_info).to be_an_instance_of(Array)
63
+ end
64
+
65
+ it 'returns nil when identifier is not found' do
66
+ region_info = subject.detect_region_info('QQ')
67
+ expect(region_info).to be_nil
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe HalcyonAPI do
4
+ it 'allows instantiation of a Client' do
5
+ client = subject.new('API_KEY')
6
+ expect(client).to be_an_instance_of(subject::Client)
7
+ end
8
+ end
@@ -0,0 +1,117 @@
1
+ require 'webmock/rspec'
2
+ require 'vcr'
3
+ require 'rspec'
4
+ require 'support/klasses'
5
+ require 'simplecov'
6
+ require 'halcyon_api'
7
+
8
+ VCR.configure do |config|
9
+ config.cassette_library_dir = "spec/cassettes"
10
+ config.hook_into :webmock
11
+ end
12
+
13
+ SimpleCov.start
14
+
15
+ # This file was generated by the `rspec --init` command. Conventionally, all
16
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
17
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
18
+ # this file to always be loaded, without a need to explicitly require it in any
19
+ # files.
20
+ #
21
+ # Given that it is always loaded, you are encouraged to keep this file as
22
+ # light-weight as possible. Requiring heavyweight dependencies from this file
23
+ # will add to the boot time of your test suite on EVERY test run, even for an
24
+ # individual file that may not need all of that loaded. Instead, consider making
25
+ # a separate helper file that requires the additional dependencies and performs
26
+ # the additional setup, and require it from the spec files that actually need
27
+ # it.
28
+ #
29
+ # The `.rspec` file also contains a few flags that are not defaults but that
30
+ # users commonly want.
31
+ #
32
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
33
+ RSpec.configure do |config|
34
+ # rspec-expectations config goes here. You can use an alternate
35
+ # assertion/expectation library such as wrong or the stdlib/minitest
36
+ # assertions if you prefer.
37
+ config.expect_with :rspec do |expectations|
38
+ # This option will default to `true` in RSpec 4. It makes the `description`
39
+ # and `failure_message` of custom matchers include text for helper methods
40
+ # defined using `chain`, e.g.:
41
+ # be_bigger_than(2).and_smaller_than(4).description
42
+ # # => "be bigger than 2 and smaller than 4"
43
+ # ...rather than:
44
+ # # => "be bigger than 2"
45
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
46
+ end
47
+
48
+ # rspec-mocks config goes here. You can use an alternate test double
49
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
50
+ config.mock_with :rspec do |mocks|
51
+ # Prevents you from mocking or stubbing a method that does not exist on
52
+ # a real object. This is generally recommended, and will default to
53
+ # `true` in RSpec 4.
54
+ mocks.verify_partial_doubles = true
55
+ end
56
+
57
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
58
+ # have no way to turn it off -- the option exists only for backwards
59
+ # compatibility in RSpec 3). It causes shared context metadata to be
60
+ # inherited by the metadata hash of host groups and examples, rather than
61
+ # triggering implicit auto-inclusion in groups with matching metadata.
62
+ config.shared_context_metadata_behavior = :apply_to_host_groups
63
+
64
+ # The settings below are suggested to provide a good initial experience
65
+ # with RSpec, but feel free to customize to your heart's content.
66
+ =begin
67
+ # This allows you to limit a spec run to individual examples or groups
68
+ # you care about by tagging them with `:focus` metadata. When nothing
69
+ # is tagged with `:focus`, all examples get run. RSpec also provides
70
+ # aliases for `it`, `describe`, and `context` that include `:focus`
71
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
72
+ config.filter_run_when_matching :focus
73
+
74
+ # Allows RSpec to persist some state between runs in order to support
75
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
76
+ # you configure your source control system to ignore this file.
77
+ config.example_status_persistence_file_path = "spec/examples.txt"
78
+
79
+ # Limits the available syntax to the non-monkey patched syntax that is
80
+ # recommended. For more details, see:
81
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
82
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
83
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
84
+ config.disable_monkey_patching!
85
+
86
+ # This setting enables warnings. It's recommended, but in some cases may
87
+ # be too noisy due to issues in dependencies.
88
+ config.warnings = true
89
+
90
+ # Many RSpec users commonly either run the entire suite or an individual
91
+ # file, and it's useful to allow more verbose output when running an
92
+ # individual spec file.
93
+ if config.files_to_run.one?
94
+ # Use the documentation formatter for detailed output,
95
+ # unless a formatter has already been configured
96
+ # (e.g. via a command-line flag).
97
+ config.default_formatter = 'doc'
98
+ end
99
+
100
+ # Print the 10 slowest examples and example groups at the
101
+ # end of the spec run, to help surface which specs are running
102
+ # particularly slow.
103
+ config.profile_examples = 10
104
+
105
+ # Run specs in random order to surface order dependencies. If you find an
106
+ # order dependency and want to debug it, you can fix the order by providing
107
+ # the seed, which is printed after each run.
108
+ # --seed 1234
109
+ config.order = :random
110
+
111
+ # Seed global randomization in this process using the `--seed` CLI option.
112
+ # Setting this allows you to use `--seed` to deterministically reproduce
113
+ # test failures related to randomization by passing the same `--seed` value
114
+ # as the one that triggered the failure.
115
+ Kernel.srand config.seed
116
+ =end
117
+ end
@@ -0,0 +1,18 @@
1
+ module KlassExampleGroup
2
+ def self.included(base)
3
+ base.instance_eval do
4
+ # Make the class available as `subject` in your examples:
5
+ subject { Object.const_get(self.class.top_level_description) }
6
+ end
7
+ end
8
+ end
9
+
10
+
11
+ RSpec.configure do |config|
12
+ # Tag service specs with `:service` metadata or put them in the spec/services dir
13
+ config.define_derived_metadata(:file_path => %r{/spec/lib/}) do |metadata|
14
+ metadata[:type] = :klass
15
+ end
16
+
17
+ config.include KlassExampleGroup, type: :klass
18
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: halcyon_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Ethan Tang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: webmock
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: vcr
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.14'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.14'
69
+ - !ruby/object:Gem::Dependency
70
+ name: codeclimate-test-reporter
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ description: A Ruby libary wrapper for the Vainglory API
84
+ email:
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - ".gitignore"
90
+ - ".rspec"
91
+ - ".rubocop.yml"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - LICENSE
95
+ - README.md
96
+ - halcyon_api.gemspec
97
+ - lib/halcyon_api.rb
98
+ - lib/halcyon_api/client.rb
99
+ - lib/halcyon_api/region.rb
100
+ - lib/halcyon_api/version.rb
101
+ - spec/cassettes/api_key.yml
102
+ - spec/cassettes/match.yml
103
+ - spec/cassettes/matches.yml
104
+ - spec/cassettes/player.yml
105
+ - spec/cassettes/players.yml
106
+ - spec/cassettes/samples.yml
107
+ - spec/cassettes/status.yml
108
+ - spec/cassettes/telemetry.yml
109
+ - spec/lib/halcyon_api/client_spec.rb
110
+ - spec/lib/halcyon_api/region_spec.rb
111
+ - spec/lib/halcyon_api_spec.rb
112
+ - spec/spec_helper.rb
113
+ - spec/support/klasses.rb
114
+ homepage: https://github.com/shikatadev/halcyon_api
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '2.0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.7.4
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Vainglory API
138
+ test_files:
139
+ - spec/cassettes/api_key.yml
140
+ - spec/cassettes/match.yml
141
+ - spec/cassettes/matches.yml
142
+ - spec/cassettes/player.yml
143
+ - spec/cassettes/players.yml
144
+ - spec/cassettes/samples.yml
145
+ - spec/cassettes/status.yml
146
+ - spec/cassettes/telemetry.yml
147
+ - spec/lib/halcyon_api/client_spec.rb
148
+ - spec/lib/halcyon_api/region_spec.rb
149
+ - spec/lib/halcyon_api_spec.rb
150
+ - spec/spec_helper.rb
151
+ - spec/support/klasses.rb