battlenet 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .rvmrc
6
+ .yardoc/*
7
+ doc/*
@@ -0,0 +1,10 @@
1
+ --readme README.md
2
+ --markup markdown
3
+ --markup-provider redcarpet
4
+ --title "Battlenet Documentation"
5
+ --private
6
+ lib/**/*.rb
7
+ -
8
+ README.md
9
+ CHANGELOG.md
10
+ LICENSE
@@ -0,0 +1,8 @@
1
+ ## v1.1.0
2
+
3
+ * Added quest resource
4
+ * Added character achievements and guild achievements data resources
5
+
6
+ ## v1.0.0
7
+
8
+ * Initial release version
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in battlenet.gemspec
4
4
  gemspec
5
+
6
+ group :documentation do
7
+ gem "yard"
8
+ gem "redcarpet"
9
+ gem "github-markup"
10
+ end
data/README.md CHANGED
@@ -48,10 +48,12 @@ Configuring
48
48
  Failing Silently
49
49
  ----------------
50
50
 
51
- By default, if Battlenet receives a non-200 response from the Battle.net API, it will throw an exception. You can turn this behavior off via the `fail_silently` attribute:
51
+ By default, if Battlenet receives a 4xx or 5xx response from the Battle.net API, it will throw a `Battlent::ApiException`. You can turn this behavior off via the `fail_silently` attribute:
52
52
 
53
53
  Battlenet.fail_silently = true
54
54
 
55
+ The exception will have its `code` attribute set to the HTTP status code returned from the API; if the response included a JSON response with the `reason` field set, the exception will have a `reason` attribute set to this string. You can also access the raw response via the `response` attribute.
56
+
55
57
  Localization
56
58
  ------------
57
59
 
@@ -81,6 +83,62 @@ If you would like to contribute to the project, please feel free to do so. Just
81
83
 
82
84
  Please do not change the contents of the `VERSION` file, or if you do, do so in a separate commit so that I can cherry-pick around it.
83
85
 
86
+ Setting Up the Development Environment
87
+ --------------------------------------
88
+
89
+ The development environment is managed with Bundler.
90
+
91
+ To install just the gems you need to hack on Battlenet and run the specs, run
92
+
93
+ bundle install --without documentation
94
+
95
+ To install all development gems, including the ones used to generate documentation, run
96
+
97
+ bundle install
98
+
99
+ To run the specs, run
100
+
101
+ bundle exec rake
102
+
103
+ Writing an Integration Test
104
+ ---------------------------
105
+
106
+ High-level integration testing against the Community Platform API is handled via VCR. After the first time running a spec that hits the API, VCR saves the HTTP response in a fixture file and uses this file to run against in the future.
107
+
108
+ Here's an example (the character integration specs):
109
+
110
+ it "fetches character data" do
111
+ VCR.use_cassette('character_mortawa') do
112
+ character = api.character 'nazjatar', 'mortawa'
113
+ character['level'].should == 85
114
+ end
115
+ end
116
+
117
+ it "fetches additional character data" do
118
+ VCR.use_cassette('character_mortawa_titles') do
119
+ character = api.character 'nazjatar', 'mortawa', :fields => 'titles'
120
+ character['titles'].find { |t| t['selected'] == true }['name'].should == "Twilight Vanquisher %s"
121
+ end
122
+ end
123
+
124
+ it "fetches characters with non-ASCII characters in their name" do
125
+ VCR.use_cassette('character_nonstandard_name') do
126
+ character = api.character 'nazjatar', 'Hikô'
127
+ character['level'].should == 85
128
+ end
129
+ end
130
+
131
+ You should always wrap tests that hit the actual API in the `VCR.use_cassette` block, and the resulting fixture file should be checked in with your test.
132
+
133
+ Building the Documentation
134
+ --------------------------
135
+
136
+ If you have the necessary gems installed (defined in the `documentation` group in the Gemfile), you can easily generate the documentation via
137
+
138
+ yard
139
+
140
+ The generated documentation can be found in `doc/`; open `doc/index.html` to view it.
141
+
84
142
  License
85
143
  =======
86
144
 
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ require 'bundler'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
4
  task :default => :spec
5
+ task :test => :spec
5
6
 
6
7
  Bundler::GemHelper.install_tasks
7
8
  RSpec::Core::RakeTask.new(:spec) do |t|
@@ -1,11 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
- version = File.read(File.expand_path('./VERSION')).strip
4
+ require 'battlenet/version'
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "battlenet"
8
- s.version = version
8
+ s.version = Battlenet::VERSION
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.authors = ["Brandon Tilley"]
11
11
  s.email = ["brandon@brandontilley.com"]
@@ -1,100 +1 @@
1
- require 'httparty'
2
- require 'battlenet/authentication'
3
- require 'battlenet/modules/character'
4
- require 'battlenet/modules/guild'
5
- require 'battlenet/modules/realm'
6
- require 'battlenet/modules/auction'
7
- require 'battlenet/modules/item'
8
- require 'battlenet/modules/recipe'
9
- require 'battlenet/modules/quest'
10
- require 'battlenet/modules/arena'
11
- require 'battlenet/modules/data'
12
-
13
- class Battlenet
14
- include HTTParty
15
-
16
- include Battlenet::Character
17
- include Battlenet::Guild
18
- include Battlenet::Realm
19
- include Battlenet::Auction
20
- include Battlenet::Item
21
- include Battlenet::Recipe
22
- include Battlenet::Quest
23
- include Battlenet::Arena
24
- include Battlenet::Data
25
-
26
- class << self
27
- attr_accessor :fail_silently
28
- attr_accessor :locale
29
- end
30
-
31
- @fail_silently = false
32
- @locale = nil
33
-
34
- def initialize(region = :us, public = nil, private = nil)
35
- @public = public
36
- @private = private
37
-
38
- @proto = @public && @private ? "https://" : "http://"
39
- @endpoint = '/api/wow'
40
- @domain = case region
41
- when :us
42
- 'us.battle.net'
43
- when :eu
44
- 'eu.battle.net'
45
- when :kr
46
- 'kr.battle.net'
47
- when :tw
48
- 'tw.battle.net'
49
- when :cn
50
- 'battlenet.com.cn'
51
- else
52
- raise "Invalid region: #{region.to_s}"
53
- end
54
-
55
- @base_uri = "#{@proto}#{@domain}#{@endpoint}"
56
- self.class.base_uri @base_uri
57
- end
58
-
59
- def fullpath(path)
60
- "#{@endpoint}#{path}"
61
- end
62
-
63
- def get(path, params = {})
64
- make_request :get, path, params
65
- end
66
-
67
- def make_request(verb, path, params = {})
68
- options = {}
69
- headers = {}
70
-
71
- if @public && @private
72
- now = Time.now
73
- signed = sign_request verb, path, now
74
- headers.merge!({
75
- "Authorization" => "BNET #{@public}:#{signed}",
76
- "Date" => now.httpdate
77
- })
78
- end
79
-
80
- options[:headers] = headers unless headers.empty?
81
- options[:query] = params unless params.empty?
82
-
83
- if Battlenet.locale
84
- options[:query] ||= {}
85
- options[:query].merge!({ :locale => Battlenet.locale })
86
- end
87
-
88
- response = self.class.send(verb, path, options)
89
-
90
- if response.code != 200 && Battlenet.fail_silently == false
91
- raise "Non-200 response: #{response.code}, #{response.body}"
92
- end
93
- response
94
- end
95
-
96
- def sign_request(verb, path, time)
97
- auth = Battlenet::Authentication.new @private
98
- auth.sign verb, fullpath(path), time
99
- end
100
- end
1
+ require 'battlenet/battlenet'
@@ -0,0 +1,184 @@
1
+ require 'httparty'
2
+ require 'battlenet/authentication'
3
+ require 'battlenet/exceptions/api_exception'
4
+ require 'battlenet/modules/character'
5
+ require 'battlenet/modules/guild'
6
+ require 'battlenet/modules/realm'
7
+ require 'battlenet/modules/auction'
8
+ require 'battlenet/modules/item'
9
+ require 'battlenet/modules/recipe'
10
+ require 'battlenet/modules/quest'
11
+ require 'battlenet/modules/arena'
12
+ require 'battlenet/modules/data'
13
+
14
+ # Battlenet exposes the Blizzard Battle.net Community Platform API via an
15
+ # easy-to-use interface.
16
+ #
17
+ # The main API class includes several Modules that define methods for collecting
18
+ # specific API data. See the documentation for `Battlenet::Modules` for a list of
19
+ # these modules.
20
+ #
21
+ # Specific details about the information returned from the API can be found at Blizzard's
22
+ # [official Community Platform API documentation](https://blizzard.github.com/api-wow-docs/).
23
+ #
24
+ # @example Return basic information about a character named Cyaga from the US realm Nazjatar
25
+ #
26
+ # api = Battlenet.new :us
27
+ # char = api.character 'Nazjatar', 'Cyaga'
28
+ # char['level']
29
+ # # => 85
30
+ #
31
+ # @example Return additional information about a character
32
+ #
33
+ # api = Battlenet.new :us
34
+ # char = api.character 'Nazjatar', 'Cyaga', :fields => 'titles'
35
+ # selected_title = char['titles'].find { |t| t['selected'] == true }
36
+ # selected_title['name']
37
+ # # => "%s, Guardian of Cenarius"
38
+ #
39
+ # @see Battlenet::Modules
40
+ #
41
+ # @author Brandon Tilley <brandon@brandontilley.com>
42
+ class Battlenet
43
+
44
+ # `Battlenet::Modules` is a namespace for modules that define methods that
45
+ # retrieve data from the Community Platform API. Methods for retrieving information
46
+ # about related resources are grouped in the same sub-Module. See documentation for
47
+ # the individual Modules for more information about the methods contained within.
48
+ module Modules; end
49
+
50
+ include HTTParty
51
+
52
+ include Battlenet::Modules::Character
53
+ include Battlenet::Modules::Guild
54
+ include Battlenet::Modules::Realm
55
+ include Battlenet::Modules::Auction
56
+ include Battlenet::Modules::Item
57
+ include Battlenet::Modules::Recipe
58
+ include Battlenet::Modules::Quest
59
+ include Battlenet::Modules::Arena
60
+ include Battlenet::Modules::Data
61
+
62
+ class << self
63
+ # Whether or not to raise exceptions on error responses from the API endpoint.
64
+ # A value of `false` causes exceptions to be raised. Defaults to `false`.
65
+ #
66
+ # @return [boolean]
67
+ attr_accessor :fail_silently
68
+
69
+ # The locale to use for API calls. Defaults to `nil`, which makes requests with
70
+ # no `locale` parameter set.
71
+ #
72
+ # @return [String|nil]
73
+ attr_accessor :locale
74
+ end
75
+
76
+ @fail_silently = false
77
+ @locale = nil
78
+
79
+ # Creates a new instance of the Battlenet API.
80
+ #
81
+ # @param region [Symbol] the region to perform API calls against.
82
+ # @param public [String|nil] the public key to use when signing requests
83
+ # @param private [String|nil] the private key to use when signing requests
84
+ def initialize(region = :us, public = nil, private = nil)
85
+ @public = public
86
+ @private = private
87
+
88
+ @proto = @public && @private ? "https://" : "http://"
89
+ @endpoint = '/api/wow'
90
+ @domain = case region
91
+ when :us
92
+ 'us.battle.net'
93
+ when :eu
94
+ 'eu.battle.net'
95
+ when :kr
96
+ 'kr.battle.net'
97
+ when :tw
98
+ 'tw.battle.net'
99
+ when :cn
100
+ 'battlenet.com.cn'
101
+ else
102
+ raise "Invalid region: #{region.to_s}"
103
+ end
104
+
105
+ @base_uri = "#{@proto}#{@domain}#{@endpoint}"
106
+ self.class.base_uri @base_uri
107
+ end
108
+
109
+ # Signs and performs an HTTP GET request. The request is only signed if a public and private
110
+ # key were provided during object instantiation.
111
+ #
112
+ # @param path (see #make_request)
113
+ # @param params (see #make_request)
114
+ # @return (see #make_request)
115
+ # @raise (see #make_request)
116
+ # @see (see #make_request)
117
+ def get(path, params = {})
118
+ make_request :get, path, params
119
+ end
120
+
121
+ private
122
+
123
+ # Returns the full URI for the given path based on the API endpoint set (varies by region).
124
+ #
125
+ # @return [String] the full URI for the path
126
+ def fullpath(path)
127
+ "#{@endpoint}#{path}"
128
+ end
129
+
130
+ # Signs and performs an HTTP request. The request is only signed if a public and private
131
+ # key were provided during object instantiation.
132
+ #
133
+ # @param verb [Symbol] the HTTP verb to perform
134
+ # @param path [String] the path to GET
135
+ # @param params [Hash] options to be turned into query string parameters
136
+ # @return [Object] the response object from HTTParty
137
+ # @raise Battlenet::ApiException if the response has a 4xx or 5xx response and `Battlenet.fail_silently` is `false`
138
+ # @see #process_response
139
+ # @see http://rubydoc.info/github/jnunemaker/httparty/master/HTTParty/Response
140
+ # @private
141
+ def make_request(verb, path, params = {})
142
+ options = {}
143
+ headers = {}
144
+
145
+ if @public && @private
146
+ now = Time.now
147
+ signed = sign_request verb, path, now
148
+ headers.merge!({
149
+ "Authorization" => "BNET #{@public}:#{signed}",
150
+ "Date" => now.httpdate
151
+ })
152
+ end
153
+
154
+ options[:headers] = headers unless headers.empty?
155
+ options[:query] = params unless params.empty?
156
+
157
+ if Battlenet.locale
158
+ options[:query] ||= {}
159
+ options[:query].merge!({ :locale => Battlenet.locale })
160
+ end
161
+
162
+ response = self.class.send(verb, path, options)
163
+ process_response response
164
+ end
165
+
166
+ def process_response(response)
167
+ if response.code.to_s =~ /^(4|5)/ && Battlenet.fail_silently == false
168
+ raise Battlenet::ApiException.new(response)
169
+ end
170
+ response
171
+ end
172
+
173
+ # Signs an HTTP request.
174
+ #
175
+ # @param verb [Symbol] the HTTP verb for the request being signed
176
+ # @param path [String] the path for the rquest being signed
177
+ # @param time [Time] the time to use when signing the request
178
+ # @return [String] value to be used as the final portion of the `Authorization` HTTP header
179
+ # @see Battlenet::Authentication
180
+ def sign_request(verb, path, time)
181
+ auth = Battlenet::Authentication.new @private
182
+ auth.sign verb, fullpath(path), time
183
+ end
184
+ end
@@ -0,0 +1,11 @@
1
+ class Battlenet
2
+ class ApiException < Exception
3
+ attr_accessor :response, :code, :reason
4
+
5
+ def initialize(response)
6
+ @response = response
7
+ @code = response.code
8
+ @reason = response['reason'] || nil
9
+ end
10
+ end
11
+ end
@@ -1,13 +1,15 @@
1
1
  require 'uri'
2
2
 
3
3
  class Battlenet
4
- module Arena
5
- def arena(realm, size, name, options = {})
6
- realm = URI.escape realm
7
- size = URI.escape size
8
- name = URI.escape name
4
+ module Modules
5
+ module Arena
6
+ def arena(realm, size, name, options = {})
7
+ realm = URI.escape realm
8
+ size = URI.escape size
9
+ name = URI.escape name
9
10
 
10
- get "/arena/#{realm}/#{size}/#{name}", options
11
+ get "/arena/#{realm}/#{size}/#{name}", options
12
+ end
11
13
  end
12
14
  end
13
15
  end
@@ -1,18 +1,20 @@
1
1
  require 'uri'
2
2
 
3
3
  class Battlenet
4
- module Auction
5
- def auction(realm, options = {})
6
- realm = URI.escape realm
4
+ module Modules
5
+ module Auction
6
+ def auction(realm, options = {})
7
+ realm = URI.escape realm
7
8
 
8
- get "/auction/data/#{realm}", options
9
- end
9
+ get "/auction/data/#{realm}", options
10
+ end
10
11
 
11
- def auction_data(realm, options = {})
12
- data = auction(realm, options)
13
- files = data["files"].first
14
- url = files["url"]
15
- get url
12
+ def auction_data(realm, options = {})
13
+ data = auction(realm, options)
14
+ files = data["files"].first
15
+ url = files["url"]
16
+ get url
17
+ end
16
18
  end
17
19
  end
18
20
  end
@@ -1,12 +1,14 @@
1
1
  require 'uri'
2
2
 
3
3
  class Battlenet
4
- module Character
5
- def character(realm, name, options = {})
6
- realm = URI.escape realm
7
- name = URI.escape name
4
+ module Modules
5
+ module Character
6
+ def character(realm, name, options = {})
7
+ realm = URI.escape realm
8
+ name = URI.escape name
8
9
 
9
- get "/character/#{realm}/#{name}", options
10
+ get "/character/#{realm}/#{name}", options
11
+ end
10
12
  end
11
13
  end
12
14
  end
@@ -1,31 +1,33 @@
1
1
  class Battlenet
2
- module Data
3
- def character_races(options = {})
4
- get "/data/character/races", options
5
- end
2
+ module Modules
3
+ module Data
4
+ def character_races(options = {})
5
+ get "/data/character/races", options
6
+ end
6
7
 
7
- def character_classes(options = {})
8
- get "/data/character/classes", options
9
- end
8
+ def character_classes(options = {})
9
+ get "/data/character/classes", options
10
+ end
10
11
 
11
- def guild_rewards(options = {})
12
- get "/data/guild/rewards", options
13
- end
12
+ def guild_rewards(options = {})
13
+ get "/data/guild/rewards", options
14
+ end
14
15
 
15
- def guild_perks(options = {})
16
- get "/data/guild/perks", options
17
- end
16
+ def guild_perks(options = {})
17
+ get "/data/guild/perks", options
18
+ end
18
19
 
19
- def item_classes(options = {})
20
- get "/data/item/classes", options
21
- end
20
+ def item_classes(options = {})
21
+ get "/data/item/classes", options
22
+ end
22
23
 
23
- def character_achievements(options = {})
24
- get "/data/character/achievements", options
25
- end
24
+ def character_achievements(options = {})
25
+ get "/data/character/achievements", options
26
+ end
26
27
 
27
- def guild_achievements(options = {})
28
- get "/data/guild/achievements", options
28
+ def guild_achievements(options = {})
29
+ get "/data/guild/achievements", options
30
+ end
29
31
  end
30
32
  end
31
33
  end
@@ -1,12 +1,14 @@
1
1
  require 'uri'
2
2
 
3
3
  class Battlenet
4
- module Guild
5
- def guild(realm, name, options = {})
6
- realm = URI.escape realm
7
- name = URI.escape name
4
+ module Modules
5
+ module Guild
6
+ def guild(realm, name, options = {})
7
+ realm = URI.escape realm
8
+ name = URI.escape name
8
9
 
9
- get "/guild/#{realm}/#{name}", options
10
+ get "/guild/#{realm}/#{name}", options
11
+ end
10
12
  end
11
13
  end
12
14
  end
@@ -1,7 +1,9 @@
1
1
  class Battlenet
2
- module Item
3
- def item(id, options = {})
4
- get "/item/#{id}", options
2
+ module Modules
3
+ module Item
4
+ def item(id, options = {})
5
+ get "/item/#{id}", options
6
+ end
5
7
  end
6
8
  end
7
9
  end
@@ -1,7 +1,9 @@
1
1
  class Battlenet
2
- module Quest
3
- def quest(id, options = {})
4
- get "/quest/#{id}", options
2
+ module Modules
3
+ module Quest
4
+ def quest(id, options = {})
5
+ get "/quest/#{id}", options
6
+ end
5
7
  end
6
8
  end
7
9
  end
@@ -1,7 +1,9 @@
1
1
  class Battlenet
2
- module Realm
3
- def realm(options = {})
4
- get "/realm/status", options
2
+ module Modules
3
+ module Realm
4
+ def realm(options = {})
5
+ get "/realm/status", options
6
+ end
5
7
  end
6
8
  end
7
9
  end
@@ -1,7 +1,9 @@
1
1
  class Battlenet
2
- module Recipe
3
- def recipe(id, options = {})
4
- get "/recipe/#{id}", options
2
+ module Modules
3
+ module Recipe
4
+ def recipe(id, options = {})
5
+ get "/recipe/#{id}", options
6
+ end
5
7
  end
6
8
  end
7
9
  end
@@ -0,0 +1,3 @@
1
+ class Battlenet
2
+ VERSION = "1.3.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://us.battle.net:80/api/wow/item/1234567890
6
+ body:
7
+ headers:
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 404
11
+ message: Not Found
12
+ headers:
13
+ date:
14
+ - Mon, 30 Jan 2012 18:44:15 GMT
15
+ server:
16
+ - Apache
17
+ x-frame-options:
18
+ - SAMEORIGIN
19
+ content-length:
20
+ - '61'
21
+ vary:
22
+ - Accept-Encoding
23
+ content-type:
24
+ - application/json;charset=utf-8
25
+ body: ! '{"status":"nok", "reason": "unable to get item information."}'
26
+ http_version: '1.1'
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'battlenet'
3
2
 
4
- describe Battlenet::Arena do
3
+ describe Battlenet::Modules::Arena do
5
4
  let(:api) { Battlenet.new }
6
5
 
7
6
  it "fetches arena data" do
@@ -1,9 +1,6 @@
1
- # "{\r\n\"realm\":{\"name\":\"Nazjatar\",\"slug\":\"nazjatar\"},\r\n\"alliance\":{\"auctions\":[\r\n\t{\"auc\":1329311139,\"item\":42989,\"owner\":\"Price\",\"bid\":15000000,
2
-
3
1
  require 'spec_helper'
4
- require 'battlenet'
5
2
 
6
- describe Battlenet::Auction do
3
+ describe Battlenet::Modules::Auction do
7
4
  let(:api) { Battlenet.new }
8
5
 
9
6
  it "fetches auction data" do
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
- require 'battlenet'
5
4
 
6
- describe Battlenet::Character do
5
+ describe Battlenet::Modules::Character do
7
6
  let(:api) { Battlenet.new }
8
7
 
9
8
  it "fetches character data" do
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'battlenet'
3
2
 
4
- describe Battlenet::Data do
3
+ describe Battlenet::Modules::Data do
5
4
  let(:api) { Battlenet.new }
6
5
 
7
6
  it "fetches character races data" do
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Battlenet::ApiException do
4
+ let(:api) { Battlenet.new }
5
+
6
+ it "raises an exception with the reason and code set" do
7
+ VCR.use_cassette('not_found') do
8
+ begin
9
+ item = api.item '1234567890'
10
+ rescue Battlenet::ApiException => e
11
+ e.code.should == 404
12
+ e.reason.should == 'unable to get item information.'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'battlenet'
3
2
 
4
- describe Battlenet::Guild do
3
+ describe Battlenet::Modules::Guild do
5
4
  let(:api) { Battlenet.new }
6
5
 
7
6
  it "fetches guild data" do
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'battlenet'
3
2
 
4
- describe Battlenet::Item do
3
+ describe Battlenet::Modules::Item do
5
4
  let(:api) { Battlenet.new }
6
5
 
7
6
  it "fetches item data" do
@@ -1,7 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
- require 'battlenet'
5
4
 
6
5
  describe Battlenet do
7
6
  let(:api) { Battlenet.new }
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'battlenet'
3
2
 
4
- describe Battlenet::Quest do
3
+ describe Battlenet::Modules::Quest do
5
4
  let(:api) { Battlenet.new }
6
5
 
7
6
  it "fetches quest data" do
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
- require 'battlenet'
5
4
 
6
- describe Battlenet::Realm do
5
+ describe Battlenet::Modules::Realm do
7
6
  let(:api) { Battlenet.new }
8
7
 
9
8
  it "fetches realm data" do
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'battlenet'
3
2
 
4
- describe Battlenet::Recipe do
3
+ describe Battlenet::Modules::Recipe do
5
4
  let(:api) { Battlenet.new }
6
5
 
7
6
  it "fetches recipe data" do
@@ -1,3 +1,5 @@
1
+ require 'battlenet'
2
+
1
3
  require 'timecop'
2
4
  require 'vcr'
3
5
 
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'battlenet/authentication'
3
2
 
4
3
  describe Battlenet::Authentication do
5
4
  let(:auth) { Battlenet::Authentication.new 'private' }
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'battlenet'
3
- require 'battlenet/authentication'
4
2
 
5
3
  describe Battlenet do
6
4
  before(:each) do
@@ -36,34 +34,17 @@ describe Battlenet do
36
34
  end
37
35
  end
38
36
 
39
- context "#fullpath" do
40
- it "returns the full path for the resource" do
41
- api = Battlenet.new
42
- api.instance_variable_set(:@endpoint, "/test/testing")
43
- api.fullpath("/thetest").should == "/test/testing/thetest"
44
- end
45
- end
46
-
47
37
  context "#get" do
48
38
  let(:api) { Battlenet.new :us }
49
39
 
50
- it "delegates to #make_request" do
51
- api.should_receive(:make_request).with(:get, '/test', {})
52
- api.get '/test'
53
- end
54
- end
55
-
56
- context "#make_request" do
57
- let(:api) { Battlenet.new :us }
58
-
59
40
  it "delegates to HTTParty" do
60
41
  Battlenet.should_receive(:get).with('/test', {})
61
- api.make_request :get, '/test'
42
+ api.get '/test'
62
43
  end
63
44
 
64
45
  it "passes query string parameters to HTTParty" do
65
46
  Battlenet.should_receive(:get).with('/test', {:query => {:fields => 'talents'}})
66
- api.make_request :get, '/test', :fields => 'talents'
47
+ api.get '/test', :fields => 'talents'
67
48
  end
68
49
 
69
50
  context "when the locale is set" do
@@ -77,7 +58,7 @@ describe Battlenet do
77
58
 
78
59
  it "adds the locale parameter to the query string" do
79
60
  Battlenet.should_receive(:get).with('/test', {:query => {:fields => 'talents', :locale => 'es_ES'}})
80
- api.make_request :get, '/test', :fields => 'talents'
61
+ api.get '/test', :fields => 'talents'
81
62
  end
82
63
  end
83
64
 
@@ -94,20 +75,41 @@ describe Battlenet do
94
75
 
95
76
  it "signs the request if the public and private key are present" do
96
77
  api.should_receive(:sign_request).with(:get, '/test', Time.now)
97
- api.make_request :get, '/test'
78
+ api.get '/test'
98
79
  end
99
80
 
100
81
  it "sets the Authorization and Date headers" do
101
82
  Battlenet::Authentication.any_instance.stub(:sign).and_return("signature")
102
83
  Battlenet.should_receive(:get).with('/test', :headers => { "Authorization" => "BNET public:signature", "Date" => Time.now.httpdate })
103
- api.make_request :get, '/test'
84
+ api.get '/test'
104
85
  end
105
86
  end
106
87
 
107
- context "when the response does not have a 200 status code" do
88
+ context "when the public and private key are set" do
89
+ let(:api) { Battlenet.new :us, 'public', 'private' }
90
+
108
91
  before(:each) do
109
- response = mock(:response).as_null_object
110
- response.should_receive(:code).at_least(:once).and_return(500)
92
+ Timecop.freeze
93
+ end
94
+
95
+ after(:each) do
96
+ Timecop.return
97
+ end
98
+
99
+ it "signs the request using the full path" do
100
+ api.instance_variable_set(:@endpoint, "/tester/testing")
101
+ auth = mock(:auth)
102
+ Battlenet::Authentication.should_receive(:new).with('private').and_return(auth)
103
+ auth.should_receive(:sign).with(:get, '/tester/testing/test', Time.now)
104
+ api.get '/test'
105
+ end
106
+ end
107
+
108
+ context "when the response does not have a status code indicating success" do
109
+ before(:each) do
110
+ response = stub(:response).as_null_object
111
+ response.stub(:code).and_return(500)
112
+ response.stub(:[]).with('reason').and_return('Server Error')
111
113
  Battlenet.should_receive(:get).and_return(response)
112
114
  end
113
115
 
@@ -115,7 +117,16 @@ describe Battlenet do
115
117
  it "throws an exception" do
116
118
  lambda {
117
119
  api.get '/test'
118
- }.should raise_error
120
+ }.should raise_error(Battlenet::ApiException)
121
+ end
122
+
123
+ it "throws an exception with the code and reason set" do
124
+ begin
125
+ api.get '/test'
126
+ rescue Battlenet::ApiException => ex
127
+ ex.code.should == 500
128
+ ex.reason.should == 'Server Error'
129
+ end
119
130
  end
120
131
  end
121
132
 
@@ -132,23 +143,4 @@ describe Battlenet do
132
143
  end
133
144
  end
134
145
  end
135
-
136
- context "#sign_request" do
137
- let(:api) { Battlenet.new :us, 'public', 'private' }
138
-
139
- before(:each) do
140
- Timecop.freeze
141
- end
142
-
143
- after(:each) do
144
- Timecop.return
145
- end
146
-
147
- it "delegates to a Battlenet::Authentication" do
148
- auth = mock(:auth)
149
- Battlenet::Authentication.should_receive(:new).with('private').and_return(auth)
150
- auth.should_receive(:sign).with(:get, api.fullpath('/test'), Time.now)
151
- api.sign_request :get, '/test', Time.now
152
- end
153
- end
154
146
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Battlenet::ApiException do
4
+ let(:response) do
5
+ resp = stub(:response)
6
+ resp.stub(:code).and_return(500)
7
+ resp.stub(:[]).with('reason').and_return('Bad Juju!')
8
+ resp
9
+ end
10
+ let(:ex) { Battlenet::ApiException.new(response) }
11
+
12
+ it "gives access to the response" do
13
+ ex.response.should == response
14
+ end
15
+
16
+ it "has a status code based on the HTTP response code" do
17
+ ex.code.should == 500
18
+ end
19
+
20
+ it "has a reason based on the response" do
21
+ ex.reason.should == 'Bad Juju!'
22
+ end
23
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: battlenet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-19 00:00:00.000000000 Z
12
+ date: 2012-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70242126812520 !ruby/object:Gem::Requirement
16
+ requirement: &70256286926140 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70242126812520
24
+ version_requirements: *70256286926140
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70242126811520 !ruby/object:Gem::Requirement
27
+ requirement: &70256286925340 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70242126811520
35
+ version_requirements: *70256286925340
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: timecop
38
- requirement: &70242126810420 !ruby/object:Gem::Requirement
38
+ requirement: &70256286924780 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70242126810420
46
+ version_requirements: *70256286924780
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: vcr
49
- requirement: &70242126808840 !ruby/object:Gem::Requirement
49
+ requirement: &70256286924040 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70242126808840
57
+ version_requirements: *70256286924040
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: webmock
60
- requirement: &70242126807740 !ruby/object:Gem::Requirement
60
+ requirement: &70256286923360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70242126807740
68
+ version_requirements: *70256286923360
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: httparty
71
- requirement: &70242126806520 !ruby/object:Gem::Requirement
71
+ requirement: &70256286922380 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70242126806520
79
+ version_requirements: *70256286922380
80
80
  description: Easily consume Blizzard's Community Platform API.
81
81
  email:
82
82
  - brandon@brandontilley.com
@@ -85,14 +85,17 @@ extensions: []
85
85
  extra_rdoc_files: []
86
86
  files:
87
87
  - .gitignore
88
+ - .yardopts
89
+ - CHANGELOG.md
88
90
  - Gemfile
89
91
  - LICENSE
90
92
  - README.md
91
93
  - Rakefile
92
- - VERSION
93
94
  - battlenet.gemspec
94
95
  - lib/battlenet.rb
95
96
  - lib/battlenet/authentication.rb
97
+ - lib/battlenet/battlenet.rb
98
+ - lib/battlenet/exceptions/api_exception.rb
96
99
  - lib/battlenet/modules/arena.rb
97
100
  - lib/battlenet/modules/auction.rb
98
101
  - lib/battlenet/modules/character.rb
@@ -102,6 +105,7 @@ files:
102
105
  - lib/battlenet/modules/quest.rb
103
106
  - lib/battlenet/modules/realm.rb
104
107
  - lib/battlenet/modules/recipe.rb
108
+ - lib/battlenet/version.rb
105
109
  - spec/fixtures/cassettes/arena_fun_and_profit.yml
106
110
  - spec/fixtures/cassettes/auction_data.yml
107
111
  - spec/fixtures/cassettes/auction_files.yml
@@ -119,6 +123,7 @@ files:
119
123
  - spec/fixtures/cassettes/guild_rl_bl_members.yml
120
124
  - spec/fixtures/cassettes/item_classes.yml
121
125
  - spec/fixtures/cassettes/item_hooooooooooo.yml
126
+ - spec/fixtures/cassettes/not_found.yml
122
127
  - spec/fixtures/cassettes/quest.yml
123
128
  - spec/fixtures/cassettes/realm.yml
124
129
  - spec/fixtures/cassettes/recipe.yml
@@ -126,6 +131,7 @@ files:
126
131
  - spec/integration/auction_spec.rb
127
132
  - spec/integration/character_spec.rb
128
133
  - spec/integration/data_spec.rb
134
+ - spec/integration/exception_spec.rb
129
135
  - spec/integration/guild_spec.rb
130
136
  - spec/integration/item_spec.rb
131
137
  - spec/integration/locale_spec.rb
@@ -135,6 +141,7 @@ files:
135
141
  - spec/spec_helper.rb
136
142
  - spec/unit/battlenet_authentication_spec.rb
137
143
  - spec/unit/battlenet_spec.rb
144
+ - spec/unit/exceptions/api_exception_spec.rb
138
145
  homepage: ''
139
146
  licenses: []
140
147
  post_install_message:
@@ -149,7 +156,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
156
  version: '0'
150
157
  segments:
151
158
  - 0
152
- hash: -61764017107044446
159
+ hash: -4028223274569724096
153
160
  required_rubygems_version: !ruby/object:Gem::Requirement
154
161
  none: false
155
162
  requirements:
@@ -158,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
165
  version: '0'
159
166
  segments:
160
167
  - 0
161
- hash: -61764017107044446
168
+ hash: -4028223274569724096
162
169
  requirements: []
163
170
  rubyforge_project:
164
171
  rubygems_version: 1.8.10
@@ -183,6 +190,7 @@ test_files:
183
190
  - spec/fixtures/cassettes/guild_rl_bl_members.yml
184
191
  - spec/fixtures/cassettes/item_classes.yml
185
192
  - spec/fixtures/cassettes/item_hooooooooooo.yml
193
+ - spec/fixtures/cassettes/not_found.yml
186
194
  - spec/fixtures/cassettes/quest.yml
187
195
  - spec/fixtures/cassettes/realm.yml
188
196
  - spec/fixtures/cassettes/recipe.yml
@@ -190,6 +198,7 @@ test_files:
190
198
  - spec/integration/auction_spec.rb
191
199
  - spec/integration/character_spec.rb
192
200
  - spec/integration/data_spec.rb
201
+ - spec/integration/exception_spec.rb
193
202
  - spec/integration/guild_spec.rb
194
203
  - spec/integration/item_spec.rb
195
204
  - spec/integration/locale_spec.rb
@@ -199,3 +208,5 @@ test_files:
199
208
  - spec/spec_helper.rb
200
209
  - spec/unit/battlenet_authentication_spec.rb
201
210
  - spec/unit/battlenet_spec.rb
211
+ - spec/unit/exceptions/api_exception_spec.rb
212
+ has_rdoc:
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.2.0