battlenet 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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