gun_broker 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +132 -0
- data/Rakefile +7 -0
- data/gun_broker.gemspec +25 -0
- data/lib/gun_broker.rb +26 -0
- data/lib/gun_broker/api.rb +82 -0
- data/lib/gun_broker/category.rb +25 -0
- data/lib/gun_broker/error.rb +8 -0
- data/lib/gun_broker/item.rb +17 -0
- data/lib/gun_broker/user.rb +41 -0
- data/lib/gun_broker/version.rb +3 -0
- data/spec/fixtures/authenticate.json +1 -0
- data/spec/fixtures/categories.json +1 -0
- data/spec/fixtures/category.json +1 -0
- data/spec/fixtures/deauthenticate.json +1 -0
- data/spec/fixtures/empty.json +1 -0
- data/spec/fixtures/item.json +1 -0
- data/spec/fixtures/items.json +1 -0
- data/spec/fixtures/not_authorized.json +1 -0
- data/spec/gun_broker/api_spec.rb +91 -0
- data/spec/gun_broker/category_spec.rb +81 -0
- data/spec/gun_broker/item_spec.rb +19 -0
- data/spec/gun_broker/user_spec.rb +175 -0
- data/spec/gun_broker_spec.rb +23 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/fixtures.rb +11 -0
- data/spec/support/headers.rb +14 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5f1909c07880bf70fd3f4c385c456168ae2409e5
|
4
|
+
data.tar.gz: c11c711ae5950ba9d3c7a3cb18618d3dde0977ea
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 49b71a28c539403d802d1be79ae5960bb41cfec1a6e8c8e980e75785686221b3722a4bca874d90fea7fdb74ba7e9657b4504bfd938ccfadf21cb5604d579f9b2
|
7
|
+
data.tar.gz: 4cc1b3c0eedf8b3cc18d0e00aa7951a5e6401f1d0b176d80f54174b575d69b57efcbd5060c2f20be6e0018e35de9649b4de6dd97604e1316fbf61d68afab3106
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
gun_broker
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p481
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Dale Campbell
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
# GunBroker
|
2
|
+
|
3
|
+
GunBroker.com API Ruby library.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'gun_broker'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install gun_broker
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Developer Token
|
24
|
+
|
25
|
+
You **must** set a developer key obtained from GunBroker.com in order to use this library.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
GunBroker.dev_key = 'your-sekret-dev-key'
|
29
|
+
```
|
30
|
+
|
31
|
+
### GunBroker::User
|
32
|
+
|
33
|
+
Authentication requires a `username` and an 'auth options' hash that requires **at least** a `password`
|
34
|
+
*or* `token`. If a password is given, you must call `User#authenticate!` to obtain an access token.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# By username/password:
|
38
|
+
user = GunBroker::User.new('username', password: 'sekret-password')
|
39
|
+
user.authenticate!
|
40
|
+
user.token # => 'user-access-token'
|
41
|
+
|
42
|
+
# Or with an existing Access Token:
|
43
|
+
user = GunBroker::User.new('username', token: 'user-access-token')
|
44
|
+
# No need to call #authenticate! since we already have an access token.
|
45
|
+
user.token # => 'user-access-token'
|
46
|
+
```
|
47
|
+
|
48
|
+
Once the User has an access token, you can then grab all of their items (listings). All items methods
|
49
|
+
return an array of `GunBroker::Item` instances.
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
user.items # => [GunBroker::Item, ...]
|
53
|
+
user.unsold_items # => [GunBroker::Item, ...]
|
54
|
+
user.sold_items # => [GunBroker::Item, ...]
|
55
|
+
```
|
56
|
+
|
57
|
+
### GunBroker::Item
|
58
|
+
|
59
|
+
Represents an item (listing) on GunBroker. The `Item#id` method returns the value of the `itemID` attribute
|
60
|
+
from the response. All other attributes can be accessed through the `Item#[]` method.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
item.id # => '1234567'
|
64
|
+
item['title'] # => 'Super Awesome Scope'
|
65
|
+
```
|
66
|
+
|
67
|
+
### GunBroker::Category
|
68
|
+
|
69
|
+
Returns GunBroker category responses. To get an array of all categories, call `Category#all()`.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
GunBroker::Category.all
|
73
|
+
# => [GunBroker::Category, ...]
|
74
|
+
```
|
75
|
+
|
76
|
+
You can also pass an optional parent category ID, to only return subcategories of the given parent.
|
77
|
+
For example, if the 'Firearms' category has an ID of '123', get all Firearm subcategories like this:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
firearms = '123' # ID of the Firearms Category
|
81
|
+
GunBroker::Category.all(firearms)
|
82
|
+
# => [GunBroker::Category, ...]
|
83
|
+
```
|
84
|
+
|
85
|
+
Much like GunBroker::Item, the `Category#id` method returns the `categoryID` attribute from the response.
|
86
|
+
All other attributes can be accessed with `Category#[]`.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
category.id # => '123'
|
90
|
+
category['categoryName'] # => 'Firearms'
|
91
|
+
```
|
92
|
+
|
93
|
+
### GunBroker::API
|
94
|
+
|
95
|
+
If you need to access an API endpoint not yet supported, you can use `GunBroker::API` directly. Currently
|
96
|
+
supported HTTP methods are `GET`, `DELETE`, and `POST`, with each having a corresponding method on the
|
97
|
+
`GunBroker::API` class.
|
98
|
+
|
99
|
+
Each method requires a `path` and accepts optional `params` and `headers` hashes. If making a `GET` request,
|
100
|
+
the `params` will be URL params; if making a `POST` request, the `params` will be turned into JSON and set
|
101
|
+
as the request body.
|
102
|
+
|
103
|
+
You can also set HTTP headers by passing a hash as the third argument. Headers will **always** contain:
|
104
|
+
|
105
|
+
* `Content-Type: application/json`
|
106
|
+
* `X-DevKey: your-sekret-dev-key`
|
107
|
+
|
108
|
+
The response will be parsed JSON (hash).
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
GunBroker::API.get('/some/resource')
|
112
|
+
# => { 'name' => 'resource', 'foo' => 'bar' }
|
113
|
+
|
114
|
+
GunBroker::API.post('/some/resource', { name: 'some data' })
|
115
|
+
|
116
|
+
# No params, but some headers:
|
117
|
+
GunBroker::API.delete('/some/resource', {}, { 'X-TestHeader' => 'FooBar' })
|
118
|
+
```
|
119
|
+
|
120
|
+
### Error Handling
|
121
|
+
|
122
|
+
Methods that require authorization (with an access token) will raise a `GunBroker::Error::NotAuthorized`
|
123
|
+
exception if the token isn't valid. Otherwise, if there is some other issue with the request (namely,
|
124
|
+
the response status code is not in the `2xx` range), a `GunBroker::Error::RequestError` will be raised.
|
125
|
+
|
126
|
+
## Contributing
|
127
|
+
|
128
|
+
1. Fork it ( https://github.com/ammoready/gun_broker/fork )
|
129
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
130
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
131
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
132
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/gun_broker.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gun_broker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gun_broker"
|
8
|
+
spec.version = GunBroker::VERSION
|
9
|
+
spec.authors = ["Dale Campbell"]
|
10
|
+
spec.email = ["oshuma@gmail.com"]
|
11
|
+
spec.summary = %q{GunBroker.com API Ruby library.}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.1"
|
24
|
+
spec.add_development_dependency "webmock", "~> 1.20"
|
25
|
+
end
|
data/lib/gun_broker.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'gun_broker/version'
|
2
|
+
|
3
|
+
require 'gun_broker/api'
|
4
|
+
require 'gun_broker/category'
|
5
|
+
require 'gun_broker/error'
|
6
|
+
require 'gun_broker/item'
|
7
|
+
require 'gun_broker/user'
|
8
|
+
|
9
|
+
module GunBroker
|
10
|
+
|
11
|
+
def self.dev_key=(dev_key)
|
12
|
+
@@dev_key = dev_key
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.dev_key
|
16
|
+
raise 'GunBroker developer key not set.' unless dev_key_present?
|
17
|
+
@@dev_key
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def self.dev_key_present?
|
23
|
+
defined?(@@dev_key) && !@@dev_key.nil? && !@@dev_key.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
module GunBroker
|
5
|
+
class API
|
6
|
+
|
7
|
+
GUNBROKER_API = 'https://api.gunbroker.com/v1'
|
8
|
+
|
9
|
+
def initialize(path, params = {}, headers = {})
|
10
|
+
raise "Path must start with '/': #{path}" unless path.start_with?('/')
|
11
|
+
|
12
|
+
@path = path
|
13
|
+
@params = params
|
14
|
+
@headers = headers
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.delete(*args)
|
18
|
+
new(*args).delete!
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.get(*args)
|
22
|
+
new(*args).get!
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.post(*args)
|
26
|
+
new(*args).post!
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete!
|
30
|
+
request = Net::HTTP::Delete.new(uri)
|
31
|
+
response = get_response(request)
|
32
|
+
handle_response(response)
|
33
|
+
end
|
34
|
+
|
35
|
+
def get!
|
36
|
+
uri.query = URI.encode_www_form(@params)
|
37
|
+
|
38
|
+
request = Net::HTTP::Get.new(uri)
|
39
|
+
response = get_response(request)
|
40
|
+
handle_response(response)
|
41
|
+
end
|
42
|
+
|
43
|
+
def post!
|
44
|
+
request = Net::HTTP::Post.new(uri)
|
45
|
+
request.body = @params.to_json
|
46
|
+
|
47
|
+
response = get_response(request)
|
48
|
+
handle_response(response)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def get_response(request)
|
54
|
+
request['Content-Type'] = 'application/json'
|
55
|
+
request['X-DevKey'] = GunBroker.dev_key
|
56
|
+
|
57
|
+
@headers.each { |header, value| request[header] = value }
|
58
|
+
|
59
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
60
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
61
|
+
http.ssl_version = :SSLv3
|
62
|
+
http.request(request)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def handle_response(response)
|
67
|
+
case response
|
68
|
+
when Net::HTTPOK, Net::HTTPSuccess
|
69
|
+
JSON.parse(response.body)
|
70
|
+
when Net::HTTPUnauthorized
|
71
|
+
raise GunBroker::Error::NotAuthorized.new(response)
|
72
|
+
else
|
73
|
+
raise GunBroker::Error::RequestError.new(response)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def uri
|
78
|
+
@uri ||= URI([GUNBROKER_API, @path].join)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GunBroker
|
2
|
+
class Category
|
3
|
+
|
4
|
+
# The top-level category ID.
|
5
|
+
ROOT_CATEGORY_ID = 0
|
6
|
+
|
7
|
+
def self.all(parent = ROOT_CATEGORY_ID)
|
8
|
+
response = GunBroker::API.get('/Categories', { 'ParentCategoryID' => parent })
|
9
|
+
response['results'].map { |attrs| new(attrs) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.find(category_id)
|
13
|
+
new(GunBroker::API.get("/Categories/#{category_id}"))
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(attrs = {})
|
17
|
+
@attrs = attrs
|
18
|
+
end
|
19
|
+
|
20
|
+
def id
|
21
|
+
@attrs['categoryID']
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module GunBroker
|
2
|
+
class User
|
3
|
+
|
4
|
+
attr_reader :username
|
5
|
+
attr_reader :token
|
6
|
+
|
7
|
+
def initialize(username, auth_options = {})
|
8
|
+
@username = username
|
9
|
+
@password = auth_options[:password] || auth_options['password']
|
10
|
+
@token = auth_options[:token] || auth_options['token']
|
11
|
+
end
|
12
|
+
|
13
|
+
def authenticate!
|
14
|
+
response = GunBroker::API.post('/Users/AccessToken', { username: @username, password: @password })
|
15
|
+
@token = response['accessToken']
|
16
|
+
end
|
17
|
+
|
18
|
+
# Sends a DELETE request to deactivate the current access token.
|
19
|
+
def deauthenticate!
|
20
|
+
GunBroker::API.delete('/Users/AccessToken', {}, { 'X-AccessToken' => @token })
|
21
|
+
@token = nil
|
22
|
+
true # Explicit `true` so this method won't return the `nil` set above.
|
23
|
+
end
|
24
|
+
|
25
|
+
def items
|
26
|
+
response = GunBroker::API.get('/Items', { 'SellerName' => @username }, { 'X-AccessToken' => @token })
|
27
|
+
response['results'].map { |result| GunBroker::Item.new(result) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def unsold_items
|
31
|
+
response = GunBroker::API.get('/ItemsUnsold', {}, { 'X-AccessToken' => @token })
|
32
|
+
response['results'].map { |result| GunBroker::Item.new(result) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def sold_items
|
36
|
+
response = GunBroker::API.get('/ItemsSold', {}, { 'X-AccessToken' => @token })
|
37
|
+
response['results'].map { |result| GunBroker::Item.new(result) }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"accessToken":"test-user-access-token"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"count":29,"pageIndex":1,"pageSize":25,"results":[{"categoryID":851,"categoryName":"Firearms","canContainItems":false,"description":"Modern Firearms are defined by the ATF as firearms built after 1898. All items listed in this category must be modern firearms. Firearm parts, ammunition, and accessories have their own categories and must be listed there. Items which meet the Collectible firearms, including antiques, commemoratives, and firearms which meet the ATF definition of a 'Curio and Relic' may be listed in the Collectible Firearms category.","categoryPath":{"id":0,"name":"All","child":{"id":851,"name":"Firearms","child":null}},"subCategories":[{"categoryId":978,"categoryName":"Pistols","hasSubCategories":true},{"categoryId":979,"categoryName":"Rifles","hasSubCategories":true},{"categoryId":980,"categoryName":"Shotguns","hasSubCategories":true},{"categoryId":2330,"categoryName":"Cowboy Action Shooting","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=851","verb":"GET","title":"Search for items in Firearms"}]},{"categoryID":982,"categoryName":"Gun Parts","canContainItems":false,"description":"Any type of firearm parts or accessories should be listed here.","categoryPath":{"id":0,"name":"All","child":{"id":982,"name":"Gun Parts","child":null}},"subCategories":[{"categoryId":983,"categoryName":"Other Gun Accessories & Parts","hasSubCategories":false},{"categoryId":1017,"categoryName":"Scopes & Gun Optics","hasSubCategories":true},{"categoryId":3013,"categoryName":"Gun Holsters & Gun Leather","hasSubCategories":false},{"categoryId":3014,"categoryName":"Gun Cases & Gun Storage","hasSubCategories":false},{"categoryId":3031,"categoryName":"Gun Cleaning Kits & Gun Cleaning Supplies","hasSubCategories":false},{"categoryId":3035,"categoryName":"Gun Parts Kits","hasSubCategories":false},{"categoryId":3036,"categoryName":"Gun Sights","hasSubCategories":false},{"categoryId":3037,"categoryName":"Shotgun Parts","hasSubCategories":true},{"categoryId":3038,"categoryName":"Pistol Parts","hasSubCategories":true},{"categoryId":3039,"categoryName":"Rifle Parts","hasSubCategories":true},{"categoryId":3040,"categoryName":"1911 Parts","hasSubCategories":false},{"categoryId":3041,"categoryName":"TC Contender Barrels & Parts","hasSubCategories":false},{"categoryId":3042,"categoryName":"SKS Parts","hasSubCategories":false},{"categoryId":3043,"categoryName":"AK47 Parts","hasSubCategories":false},{"categoryId":3044,"categoryName":"AR15 Parts","hasSubCategories":false},{"categoryId":3045,"categoryName":"Glock Parts","hasSubCategories":false},{"categoryId":3046,"categoryName":"HK Parts","hasSubCategories":false},{"categoryId":3074,"categoryName":"Gun Safes & Trigger Locks","hasSubCategories":false},{"categoryId":3097,"categoryName":"Gunsmithing Tools & Gunsmith Supplies","hasSubCategories":false},{"categoryId":4011,"categoryName":"Shooting Glasses & Hearing Protection","hasSubCategories":false},{"categoryId":4013,"categoryName":"Shooting Targets","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=982","verb":"GET","title":"Search for items in Gun Parts"}]},{"categoryID":1012,"categoryName":"Ammunition","canContainItems":false,"description":"This category is for ready-to-shoot ammunition for firearms. Reloading supplies such as bullets, brass, primers, etc belong in the Reloading : Supplies category, not here. Clips, magazines, ammo belts, and equipment to carry or load ammunition have their own categories and should not be listed here.","categoryPath":{"id":0,"name":"All","child":{"id":1012,"name":"Ammunition","child":null}},"subCategories":[{"categoryId":3017,"categoryName":"Rifle Ammunition","hasSubCategories":false},{"categoryId":3018,"categoryName":"Pistol Ammunition","hasSubCategories":false},{"categoryId":3019,"categoryName":"Shotgun Shells","hasSubCategories":false},{"categoryId":3020,"categoryName":"Other Ammunition","hasSubCategories":false},{"categoryId":3030,"categoryName":"Vintage Ammo","hasSubCategories":false},{"categoryId":3053,"categoryName":"Ammo Storage","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=1012","verb":"GET","title":"Search for items in Ammunition"}]},{"categoryID":3094,"categoryName":"Black Powder & Muzzleloaders","canContainItems":false,"description":"","categoryPath":{"id":0,"name":"All","child":{"id":3094,"name":"Black Powder & Muzzleloaders","child":null}},"subCategories":[{"categoryId":3095,"categoryName":"Black Powder Pistols & Muzzleloader Pistols","hasSubCategories":false},{"categoryId":3096,"categoryName":"Black Powder Rifles & Muzzleloader Rifles","hasSubCategories":false},{"categoryId":4030,"categoryName":"Muzzleloader Supplies & Black Powder Parts","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=3094","verb":"GET","title":"Search for items in Black Powder & Muzzleloaders"}]},{"categoryID":2338,"categoryName":"Class 3 Firearms, NFA & Destructive Devices","canContainItems":false,"description":"All types of federally restricted firearms, including machine guns, destructive devices, and silencers","categoryPath":{"id":0,"name":"All","child":{"id":2338,"name":"Class 3 Firearms, NFA & Destructive Devices","child":null}},"subCategories":[{"categoryId":2326,"categoryName":"Machine Guns","hasSubCategories":false},{"categoryId":3098,"categoryName":"Class 3 Parts & Accessories","hasSubCategories":false},{"categoryId":3099,"categoryName":"Silencers & Suppressed Firearms","hasSubCategories":false},{"categoryId":3100,"categoryName":"Destructive Devices","hasSubCategories":false},{"categoryId":4031,"categoryName":"Short Barrel Rifles (SBR)","hasSubCategories":false},{"categoryId":4032,"categoryName":"Any Other Weapon (AOW)","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=2338","verb":"GET","title":"Search for items in Class 3 Firearms, NFA & Destructive Devices"}]},{"categoryID":1014,"categoryName":"Collectible Firearms","canContainItems":false,"description":"Items listed in the Collectible Firearms category must be a firearm. Parts and accessories for Collectible Firearms may be listed in Collectible Firearms : Collectible Parts / Accessories provided the item being listed is itself a collectible piece. Non-collectible parts and accessories should be listed in the most appropriate Firearm Parts or Firearm Accessories category.","categoryPath":{"id":0,"name":"All","child":{"id":1014,"name":"Collectible Firearms","child":null}},"subCategories":[{"categoryId":2322,"categoryName":"Antique Guns","hasSubCategories":false},{"categoryId":2323,"categoryName":"Curios & Relics","hasSubCategories":false},{"categoryId":2324,"categoryName":"Muzzleloading Collectibles","hasSubCategories":false},{"categoryId":3012,"categoryName":"Other Collectible Guns","hasSubCategories":false},{"categoryId":3047,"categoryName":"Commemorative Guns","hasSubCategories":false},{"categoryId":3061,"categoryName":"Collectible Gun Parts & Accessories","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=1014","verb":"GET","title":"Search for items in Collectible Firearms"}]},{"categoryID":1013,"categoryName":"Air Guns","canContainItems":false,"description":"Only air guns should be listed in this category. Air guns include AirSoft, paintball, BB guns, pellet guns, adult air rifles and pistols, CO2-powered rifles and pistols, and any other type of air or compressed gas powered gun. Air gun parts, supplies, and accessories should be listed in the Air Guns : Supplies / Accessories / Other category.","categoryPath":{"id":0,"name":"All","child":{"id":1013,"name":"Air Guns","child":null}},"subCategories":[{"categoryId":3048,"categoryName":"Airsoft","hasSubCategories":false},{"categoryId":3049,"categoryName":"Air Pistols","hasSubCategories":false},{"categoryId":3050,"categoryName":"Air Rifles","hasSubCategories":false},{"categoryId":3051,"categoryName":"Paintball Guns","hasSubCategories":false},{"categoryId":3052,"categoryName":"Air Gun Accessories","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=1013","verb":"GET","title":"Search for items in Air Guns"}]},{"categoryID":1016,"categoryName":"Ammunition Reloading","canContainItems":false,"description":"Equipment and supplies for reloading ammunition should be listed here. ","categoryPath":{"id":0,"name":"All","child":{"id":1016,"name":"Ammunition Reloading","child":null}},"subCategories":[{"categoryId":3015,"categoryName":"Reloading Equipment","hasSubCategories":false},{"categoryId":3016,"categoryName":"Reloading Supplies","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=1016","verb":"GET","title":"Search for items in Ammunition Reloading"}]},{"categoryID":984,"categoryName":"Archery & Bow Hunting","canContainItems":false,"description":"This category is for bows, crossbows, and bow hunting supplies and accessories.","categoryPath":{"id":0,"name":"All","child":{"id":984,"name":"Archery & Bow Hunting","child":null}},"subCategories":[{"categoryId":3054,"categoryName":"Bows","hasSubCategories":false},{"categoryId":3055,"categoryName":"Crossbows","hasSubCategories":false},{"categoryId":3056,"categoryName":"Archery Supplies","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=984","verb":"GET","title":"Search for items in Archery & Bow Hunting"}]},{"categoryID":2329,"categoryName":"Books, Videos & Literature","canContainItems":false,"description":"This category is for books, magazines (the kind you read, not the kind you load!), CD-ROM based books or information, videos or DVDs, and any other kind of gun-related reading or viewing materials.","categoryPath":{"id":0,"name":"All","child":{"id":2329,"name":"Books, Videos & Literature","child":null}},"subCategories":[{"categoryId":3057,"categoryName":"Books","hasSubCategories":false},{"categoryId":3058,"categoryName":"Videos & DVDs","hasSubCategories":false},{"categoryId":3059,"categoryName":"Magazines","hasSubCategories":false},{"categoryId":3060,"categoryName":"CD-ROMS","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=2329","verb":"GET","title":"Search for items in Books, Videos & Literature"}]},{"categoryID":2332,"categoryName":"Charity Gun Auctions","canContainItems":false,"description":"Charity auctions are reserved for charitable organizations or for auctioning off items in which the proceeds will be donated to a charitable cause. Items cannot be listed in this category without the assistance of the auction site. To list an item here please contact auction site tech support by clicking <a href=\"/Support/\">Contact Us</a> from the bottom of any auction site page.","categoryPath":{"id":0,"name":"All","child":{"id":2332,"name":"Charity Gun Auctions","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=2332","verb":"GET","title":"Search for items in Charity Gun Auctions"}]},{"categoryID":3000,"categoryName":"Clothing, Bags & Wearables","canContainItems":false,"description":"Any type of clothing, jewelry, hats, bags, backpacks, and other wearable items must be listed here. The only exceptions are items that would be better listed in Collectibles, like collectible pins, badges, etc.","categoryPath":{"id":0,"name":"All","child":{"id":3000,"name":"Clothing, Bags & Wearables","child":null}},"subCategories":[{"categoryId":3062,"categoryName":"Coats & Jackets","hasSubCategories":false},{"categoryId":3064,"categoryName":"Pants & Coveralls","hasSubCategories":false},{"categoryId":3065,"categoryName":"Gloves","hasSubCategories":false},{"categoryId":3066,"categoryName":"Watches & Jewelry","hasSubCategories":false},{"categoryId":3069,"categoryName":"Eyewear","hasSubCategories":false},{"categoryId":3070,"categoryName":"Hats & Headwear","hasSubCategories":false},{"categoryId":3071,"categoryName":"Belts & Belt Buckles","hasSubCategories":false},{"categoryId":3072,"categoryName":"Other Clothing","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=3000","verb":"GET","title":"Search for items in Clothing, Bags & Wearables"}]},{"categoryID":3001,"categoryName":"Collectibles & Militaria","canContainItems":false,"description":"Any type of non-firearm collectible items related to firearms or hunting may be listed here. This includes war collectibles, souvenirs, logo merchandise, and catalogs. If the item is a firearm, either modern or antique, it must be placed in either the Collectible Firearms or Modern Firearms categories.","categoryPath":{"id":0,"name":"All","child":{"id":3001,"name":"Collectibles & Militaria","child":null}},"subCategories":[{"categoryId":1015,"categoryName":"Other Military Collectibles","hasSubCategories":false},{"categoryId":3005,"categoryName":"Old West Collectibles","hasSubCategories":false},{"categoryId":3006,"categoryName":"Civil War Collectibles","hasSubCategories":false},{"categoryId":3007,"categoryName":"WW1 & WW2 Collectibles","hasSubCategories":false},{"categoryId":3009,"categoryName":"Souvenirs","hasSubCategories":false},{"categoryId":3010,"categoryName":"Other Collectibles","hasSubCategories":false},{"categoryId":3021,"categoryName":"Badges & Insignias","hasSubCategories":false},{"categoryId":3028,"categoryName":"Logo Merchandise","hasSubCategories":false},{"categoryId":3073,"categoryName":"Flags","hasSubCategories":false},{"categoryId":3109,"categoryName":"Collectible Coins","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=3001","verb":"GET","title":"Search for items in Collectibles & Militaria"}]},{"categoryID":2334,"categoryName":"Domain Names","canContainItems":true,"description":"Internet domain names","categoryPath":{"id":0,"name":"All","child":{"id":2334,"name":"Domain Names","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=2334","verb":"GET","title":"Search for items in Domain Names"}]},{"categoryID":3004,"categoryName":"Everything Else","canContainItems":true,"description":"Anything that does not fit cleanly into any other category should be listed here.","categoryPath":{"id":0,"name":"All","child":{"id":3004,"name":"Everything Else","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=3004","verb":"GET","title":"Search for items in Everything Else"}]},{"categoryID":4040,"categoryName":"Fishing Tackle","canContainItems":false,"description":"This is the general area for everything related to fishing. GunBroker.com has places for freshwater, saltwater and fly fishing equipment and tackle of all kinds. You can even buy and sell collectible and vintage fishing tackle, rods and reels.","categoryPath":{"id":0,"name":"All","child":{"id":4040,"name":"Fishing Tackle","child":null}},"subCategories":[{"categoryId":4041,"categoryName":"Fishing Collectibles","hasSubCategories":false},{"categoryId":4042,"categoryName":"Fish Finders","hasSubCategories":false},{"categoryId":4043,"categoryName":"Fly Fishing Tackle","hasSubCategories":true},{"categoryId":4044,"categoryName":"Freshwater Fishing Tackle","hasSubCategories":true},{"categoryId":4045,"categoryName":"Saltwater Fishing","hasSubCategories":true},{"categoryId":4046,"categoryName":"Terminal Tackle","hasSubCategories":false},{"categoryId":4047,"categoryName":"Tackle Storage","hasSubCategories":false},{"categoryId":4048,"categoryName":"Other General Fishing","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=4040","verb":"GET","title":"Search for items in Fishing Tackle"}]},{"categoryID":901,"categoryName":"Furniture & Cabinets","canContainItems":true,"description":"Furniture, including gun storage cabinets, display cases, and stand-up safes should be listed here.","categoryPath":{"id":0,"name":"All","child":{"id":901,"name":"Furniture & Cabinets","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=901","verb":"GET","title":"Search for items in Furniture & Cabinets"}]},{"categoryID":3002,"categoryName":"Hunting Gear","canContainItems":false,"description":"This category is for all hunting gear that is not better suited for another category, such as tree stands, scents, traps, and other hunting equipment. Firearms may not be listed here; firearms must be listed in the Modern Firearms category. ","categoryPath":{"id":0,"name":"All","child":{"id":3002,"name":"Hunting Gear","child":null}},"subCategories":[{"categoryId":4000,"categoryName":"Animal Traps","hasSubCategories":false},{"categoryId":4001,"categoryName":"Bags & Packs","hasSubCategories":false},{"categoryId":4002,"categoryName":"Camo Clothing & Accessories","hasSubCategories":false},{"categoryId":4003,"categoryName":"Game Feed & Feeders","hasSubCategories":false},{"categoryId":4004,"categoryName":"Game Cameras","hasSubCategories":false},{"categoryId":4005,"categoryName":"Hunting Dog Supplies","hasSubCategories":false},{"categoryId":4006,"categoryName":"Hunting Scents & Deer Lure","hasSubCategories":false},{"categoryId":4007,"categoryName":"Tree Stands","hasSubCategories":false},{"categoryId":4008,"categoryName":"Hunting Accessories","hasSubCategories":false},{"categoryId":4009,"categoryName":"Hunting Decoys","hasSubCategories":false},{"categoryId":4010,"categoryName":"Game Calls","hasSubCategories":false},{"categoryId":4065,"categoryName":"Scent Elimination","hasSubCategories":false},{"categoryId":4066,"categoryName":"GPS","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=3002","verb":"GET","title":"Search for items in Hunting Gear"}]},{"categoryID":3029,"categoryName":"Hunting Trips & Safaris","canContainItems":true,"description":"This category is for hunting or fishing trips, vacations, and excursions.","categoryPath":{"id":0,"name":"All","child":{"id":3029,"name":"Hunting Trips & Safaris","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=3029","verb":"GET","title":"Search for items in Hunting Trips & Safaris"}]},{"categoryID":2328,"categoryName":"Knives & Swords","canContainItems":false,"description":"All knives, swords, axes, pocket knives, bayonets, machetes, and other bladed items must be listed here. Knives may not be listed in any other category, with the sole exceptions of bayonets which may be listed in the Collectible Firearms : Collectible Parts & Accessories category provided the bayonet is a collectible and attaches to a collectible firearm.","categoryPath":{"id":0,"name":"All","child":{"id":2328,"name":"Knives & Swords","child":null}},"subCategories":[{"categoryId":3075,"categoryName":"Collectible Knives","hasSubCategories":false},{"categoryId":3076,"categoryName":"Daggers","hasSubCategories":false},{"categoryId":3077,"categoryName":"Hunting Knives","hasSubCategories":false},{"categoryId":3078,"categoryName":"Automatic Knives","hasSubCategories":false},{"categoryId":3079,"categoryName":"Pocket Knives","hasSubCategories":false},{"categoryId":3080,"categoryName":"Swords & Axes","hasSubCategories":false},{"categoryId":3081,"categoryName":"Bayonets","hasSubCategories":false},{"categoryId":3082,"categoryName":"Fixed Blade Knives","hasSubCategories":false},{"categoryId":3111,"categoryName":"Knife Accessories","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=2328","verb":"GET","title":"Search for items in Knives & Swords"}]},{"categoryID":3003,"categoryName":"Land & Leases","canContainItems":true,"description":"Property for sale, rent, or lease should be listed here. ","categoryPath":{"id":0,"name":"All","child":{"id":3003,"name":"Land & Leases","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=3003","verb":"GET","title":"Search for items in Land & Leases"}]},{"categoryID":900,"categoryName":"Non-Firing Replica Guns","canContainItems":true,"description":"The category includes non-firing replica guns (full size or miniature), guns that shoot blanks, or de-militarized firearms. The important distinction is that none of these items can shoot live ammunition nor can be converted to do so and are therefore not subject to FFL transfer.","categoryPath":{"id":0,"name":"All","child":{"id":900,"name":"Non-Firing Replica Guns","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=900","verb":"GET","title":"Search for items in Non-Firing Replica Guns"}]},{"categoryID":902,"categoryName":"Non-Lethal Weapons","canContainItems":true,"description":"This category is for non-lethal self-defense items, such as pepper spray, stun guns, tasers, and other non-firearm items.","categoryPath":{"id":0,"name":"All","child":{"id":902,"name":"Non-Lethal Weapons","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=902","verb":"GET","title":"Search for items in Non-Lethal Weapons"}]},{"categoryID":2335,"categoryName":"Services","canContainItems":false,"description":"Gunsmithing services, including repair and customizing","categoryPath":{"id":0,"name":"All","child":{"id":2335,"name":"Services","child":null}},"subCategories":[{"categoryId":3092,"categoryName":"Taxidermy Services","hasSubCategories":false},{"categoryId":3093,"categoryName":"Gunsmithing","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=2335","verb":"GET","title":"Search for items in Services"}]},{"categoryID":9001,"categoryName":"Staff Picks","canContainItems":true,"description":"Picks that we think are the best items or the coolest items to have.","categoryPath":{"id":0,"name":"All","child":{"id":9001,"name":"Staff Picks","child":null}},"subCategories":[],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=9001","verb":"GET","title":"Search for items in Staff Picks"}]}],"links":[{"rel":"next","href":"https://api.gunbroker.com/v1/Categories?PageIndex=2","verb":"GET","title":"next"}]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"categoryID":851,"categoryName":"Firearms","canContainItems":false,"description":"Modern Firearms are defined by the ATF as firearms built after 1898. All items listed in this category must be modern firearms. Firearm parts, ammunition, and accessories have their own categories and must be listed there. Items which meet the Collectible firearms, including antiques, commemoratives, and firearms which meet the ATF definition of a 'Curio and Relic' may be listed in the Collectible Firearms category.","categoryPath":{"id":0,"name":"All","child":{"id":851,"name":"Firearms","child":null}},"subCategories":[{"categoryId":978,"categoryName":"Pistols","hasSubCategories":true},{"categoryId":979,"categoryName":"Rifles","hasSubCategories":true},{"categoryId":980,"categoryName":"Shotguns","hasSubCategories":true},{"categoryId":2330,"categoryName":"Cowboy Action Shooting","hasSubCategories":false}],"links":[{"rel":"search","href":"https://api.gunbroker.com/v1/items?Categories=851","verb":"GET","title":"Search for items in Firearms"}]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"userMessage": "Access token deleted.", "developerMessage": "Access token deleted.", "links": []}
|
@@ -0,0 +1 @@
|
|
1
|
+
[]
|
@@ -0,0 +1 @@
|
|
1
|
+
{"itemID":465370483,"bidIncrement":0.0,"bids":0,"buyer":null,"cashDiscount":0.0,"categoryID":3032,"categoryName":"Rifle Stocks","collectsSalesTax":false,"condition":{"1":"Factory New"},"currentBid":0.0,"description":"The Magpul STR (Storage/Type Restricted) is a drop-in replacement buttstock for AR15/M4 carbines using mil-spec sized receiver extension tubes. A storage-capable version of the CTR®, the STR has improved cheek weld and two water resistant battery tubes on a compact, reinforced polymer A-frame design. A shielded operation lever and supplemental friction locking system prevent accidental operation and minimize excessive stock movement for enhanced weapon stability and accuracy.","eligibleForImmediateCheckout":false,"endingDate":"2015-02-25T15:37:19Z","fixedPrice":49.99,"hasBuyNow":false,"buyNowPrice":0.0,"hasColor":false,"hasQuickLook":false,"hasPictures":true,"hasReserve":false,"hasReserveBeenMet":false,"hasStarted":true,"hasWinningBid":false,"isActive":true,"isCurrentUserHighBidder":false,"isFeaturedItem":false,"isfflRequired":false,"isFixedPrice":true,"isHighlighted":false,"isShowCaseItem":false,"isTitleBoldface":false,"isWatching":false,"inspectionPeriod":{"1":"AS IS - No refund or exchange"},"itemCharacteristics":[],"location":"Taylors, SC 29687","minimumBid":0.0,"paymentMethods":{"512":"PayPal"},"pictures":["http://pics.gunbroker.com/GB/465370000/465370483/pix789199977.jpg"],"quantity":3,"relistedAsItemID":0,"salesTaxes":[],"seller":{"userID":2266088,"username":"dangerangell","feedbackRating":"C(2)","isffl":false,"isVerified":true},"serialNumber":"","shippingClassCosts":{},"shippingClassesSupported":{"32":"Priority"},"sku":"","startingBid":0.00,"startingDate":"2015-01-26T15:37:19Z","subTitle":"","thumbnailURL":"http://pics.gunbroker.com/GB/465370000/465370483/thumb.jpg","timeLeft":"P26DT14H17M15S","title":"Magpul STR Carbine Stock Mil Spec Black","titleColor":"#000000","upc":"","viewCounter":15,"weight":null,"weightUnit":{"1":"Pounds"},"whoPaysForShipping":{"1":"See item description","4":"Buyer pays actual shipping cost"},"willShipInternational":false,"links":[{"rel":"fixedprice","href":"https://api.gunbroker.com/v1/fixedprice","verb":"POST","title":"Purchase"},{"rel":"watch","href":"https://api.gunbroker.com/v1/itemswatched","verb":"POST","title":"Add to Watch List"},{"rel":"feedback","href":"https://api.gunbroker.com/v1/feedback/summary/2266088","verb":"GET","title":"Feedback"},{"rel":"question","href":"https://api.gunbroker.com/v1/messages/askuser","verb":"POST","title":"Ask a question"},{"rel":"sellersitems","href":"https://api.gunbroker.com/v1/items?IncludeSellers=2266088","verb":"GET","title":"View Seller's Items"},{"rel":"share","href":"http://www.gunbroker.com/Auction/ViewItem.aspx?Item=465370483","verb":"GET","title":"Check out what I found on GunBroker.com!"}]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"count":1,"pageIndex":1,"pageSize":25,"results":[{"itemID":465370483,"bids":0,"eligibleForImmediateCheckout":false,"endingDate":"2015-02-25T15:37:19Z","isFeaturedItem":false,"isFixedPrice":true,"isHighlighted":false,"isShowCaseItem":false,"isTitleBoldface":false,"hasBuyNow":false,"hasColor":false,"hasQuickLook":false,"hasPictures":true,"hasReserve":false,"hasReserveBeenMet":false,"highBidderID":0,"quantity":3,"price":49.9900,"serialNumber":"","sku":"","subTitle":"","thumbnailURL":"http://pics.gunbroker.com/GB/465370000/465370483/thumb.jpg","timeLeft":"P26DT18H52M28S","title":"Magpul STR Carbine Stock Mil Spec Black","titleColor":"#000000","links":[{"rel":"self","href":"https://api.gunbroker.com/v1/items/465370483","verb":"GET","title":"465370483"}]}],"categoryCounts":[{"id":3032,"name":"Rifle Stocks","count":1}],"links":[{"rel":"share","href":"http://www.gunbroker.com/All/BI.aspx?IncludeSellers=2266088&PageSize=25","verb":"GET","title":"Check out what I found on GunBroker.com!"}]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"userMessage":"Unauthorized","developerMessage":"Unauthorized","links":[]}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GunBroker::API do
|
4
|
+
|
5
|
+
let(:token) { 'test-user-access-token' }
|
6
|
+
|
7
|
+
let(:path) { '/some/resource' }
|
8
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, path].join }
|
9
|
+
|
10
|
+
before(:all) do
|
11
|
+
GunBroker.dev_key = 'test-dev-key'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has a GUNBROKER_API constant' do
|
15
|
+
expect(GunBroker::API::GUNBROKER_API).not_to be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
context '.delete' do
|
19
|
+
context 'on success' do
|
20
|
+
it 'returns JSON parsed response' do
|
21
|
+
stub_request(:delete, endpoint)
|
22
|
+
.with(headers: headers('X-AccessToken' => token))
|
23
|
+
.to_return(body: response_fixture('deauthenticate'))
|
24
|
+
|
25
|
+
response = GunBroker::API.delete(path, {}, headers('X-AccessToken' => token))
|
26
|
+
expect(response).to eq(JSON.parse(response_fixture('deauthenticate')))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'on failure' do
|
31
|
+
it 'raises an exception' do
|
32
|
+
stub_request(:delete, endpoint)
|
33
|
+
.with(headers: headers('X-AccessToken' => token))
|
34
|
+
.to_return(body: response_fixture('empty'), status: 500)
|
35
|
+
|
36
|
+
api = GunBroker::API.new(path, {}, headers('X-AccessToken' => token))
|
37
|
+
expect { api.delete! }.to raise_error(GunBroker::Error::RequestError)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context '.get' do
|
43
|
+
context 'on success' do
|
44
|
+
it 'returns JSON parsed response' do
|
45
|
+
stub_request(:get, endpoint)
|
46
|
+
.with(query: { 'SellerName' => 'test-user' })
|
47
|
+
.to_return(body: response_fixture('items'))
|
48
|
+
|
49
|
+
response = GunBroker::API.get(path, { 'SellerName' => 'test-user' })
|
50
|
+
expect(response).to eq(JSON.parse(response_fixture('items')))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'on failure' do
|
55
|
+
it 'raises an exception' do
|
56
|
+
stub_request(:get, endpoint)
|
57
|
+
.to_return(body: response_fixture('empty'), status: 500)
|
58
|
+
|
59
|
+
api = GunBroker::API.new(path)
|
60
|
+
expect { api.get! }.to raise_error(GunBroker::Error::RequestError)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context '.post' do
|
66
|
+
context 'on success' do
|
67
|
+
it 'returns JSON parsed response' do
|
68
|
+
stub_request(:post, endpoint)
|
69
|
+
.with(
|
70
|
+
headers: headers,
|
71
|
+
body: { username: 'test-user' }
|
72
|
+
)
|
73
|
+
.to_return(body: response_fixture('authenticate'))
|
74
|
+
|
75
|
+
response = GunBroker::API.post(path, { username: 'test-user' }, headers)
|
76
|
+
expect(response).to eq(JSON.parse(response_fixture('authenticate')))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'on failure' do
|
81
|
+
it 'raises an exception' do
|
82
|
+
stub_request(:post, endpoint)
|
83
|
+
.to_return(body: response_fixture('empty'), status: 500)
|
84
|
+
|
85
|
+
api = GunBroker::API.new(path)
|
86
|
+
expect { api.post! }.to raise_error(GunBroker::Error::RequestError)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GunBroker::Category do
|
4
|
+
|
5
|
+
let(:attrs) { JSON.parse(response_fixture('category')) }
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
GunBroker.dev_key = 'test-dev-key'
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'has a ROOT_CATEGORY_ID constant' do
|
12
|
+
expect(GunBroker::Category::ROOT_CATEGORY_ID).not_to be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should have an #id' do
|
16
|
+
category = GunBroker::Category.new(attrs)
|
17
|
+
expect(category.id).to eq(attrs['categoryID'])
|
18
|
+
end
|
19
|
+
|
20
|
+
context '.all' do
|
21
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, '/Categories'].join }
|
22
|
+
|
23
|
+
context 'on success' do
|
24
|
+
it 'returns all categories' do
|
25
|
+
stub_request(:get, endpoint)
|
26
|
+
.with(
|
27
|
+
headers: headers,
|
28
|
+
query: { 'ParentCategoryID' => GunBroker::Category::ROOT_CATEGORY_ID }
|
29
|
+
)
|
30
|
+
.to_return(body: response_fixture('categories'))
|
31
|
+
|
32
|
+
categories = GunBroker::Category.all
|
33
|
+
expect(categories).not_to be_empty
|
34
|
+
expect(categories.first).to be_a(GunBroker::Category)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'on failure' do
|
39
|
+
it 'should raise a GunBroker::Error::RequestError exception' do
|
40
|
+
stub_request(:get, endpoint)
|
41
|
+
.with(
|
42
|
+
headers: headers,
|
43
|
+
query: { 'ParentCategoryID' => GunBroker::Category::ROOT_CATEGORY_ID }
|
44
|
+
)
|
45
|
+
.to_return(body: response_fixture('not_authorized'), status: 401)
|
46
|
+
|
47
|
+
expect { GunBroker::Category.all }.to raise_error(GunBroker::Error::NotAuthorized)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context '.find' do
|
53
|
+
let(:attrs) { JSON.parse(response_fixture('category')) }
|
54
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, "/Categories/#{attrs['categoryID']}"].join }
|
55
|
+
|
56
|
+
context 'on success' do
|
57
|
+
it 'returns the Category' do
|
58
|
+
stub_request(:get, endpoint)
|
59
|
+
.with(headers: headers)
|
60
|
+
.to_return(body: response_fixture('category'))
|
61
|
+
|
62
|
+
id = attrs['categoryID']
|
63
|
+
category = GunBroker::Category.find(id)
|
64
|
+
expect(category).to be_a(GunBroker::Category)
|
65
|
+
expect(category.id).to eq(id)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'on failure' do
|
70
|
+
it 'should raise a GunBroker::Error::RequestError exception' do
|
71
|
+
stub_request(:get, endpoint)
|
72
|
+
.with(headers: headers)
|
73
|
+
.to_return(body: response_fixture('not_authorized'), status: 401)
|
74
|
+
|
75
|
+
id = attrs['categoryID']
|
76
|
+
expect { GunBroker::Category.find(id) }.to raise_error(GunBroker::Error::NotAuthorized)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GunBroker::Item do
|
4
|
+
|
5
|
+
let(:attrs) { JSON.parse(response_fixture('item')) }
|
6
|
+
|
7
|
+
it 'should have an #id' do
|
8
|
+
item = GunBroker::Item.new(attrs)
|
9
|
+
expect(item.id).to eq(attrs['itemID'])
|
10
|
+
end
|
11
|
+
|
12
|
+
context '#[]' do
|
13
|
+
it 'should return the value from @attrs' do
|
14
|
+
item = GunBroker::Item.new(attrs)
|
15
|
+
attrs.each { |k, v| expect(item[k]).to eq(v) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GunBroker::User do
|
4
|
+
let(:username) { 'test-user' }
|
5
|
+
let(:password) { 'sekret-passw0rd' }
|
6
|
+
let(:token) { 'test-user-access-token' }
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
GunBroker.dev_key = 'test-dev-key'
|
10
|
+
end
|
11
|
+
|
12
|
+
context '#initialize' do
|
13
|
+
context 'auth_options' do
|
14
|
+
it 'should accept a password' do
|
15
|
+
user = GunBroker::User.new(username, password: password)
|
16
|
+
expect(user.instance_variable_get(:@username)).to eq(username)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should accept an access token' do
|
20
|
+
user = GunBroker::User.new(username, token: token)
|
21
|
+
expect(user.token).to eq(token)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context '#authenticate!' do
|
27
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, '/Users/AccessToken'].join }
|
28
|
+
|
29
|
+
context 'on success' do
|
30
|
+
it 'should set the access token' do
|
31
|
+
stub_request(:post, endpoint)
|
32
|
+
.with(
|
33
|
+
headers: headers,
|
34
|
+
body: { username: username, password: password },
|
35
|
+
)
|
36
|
+
.to_return(body: { 'accessToken' => token }.to_json)
|
37
|
+
|
38
|
+
user = GunBroker::User.new(username, password: password)
|
39
|
+
user.authenticate!
|
40
|
+
|
41
|
+
expect(user.token).to eq(token)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'on failure' do
|
46
|
+
it 'should raise a GunBroker::Error::NotAuthorized exception' do
|
47
|
+
stub_request(:post, endpoint)
|
48
|
+
.with(
|
49
|
+
headers: headers,
|
50
|
+
body: { username: username, password: password }
|
51
|
+
).to_return(body: response_fixture('not_authorized'), status: 401)
|
52
|
+
|
53
|
+
user = GunBroker::User.new(username, password: password)
|
54
|
+
expect { user.authenticate! }.to raise_error(GunBroker::Error::NotAuthorized)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context '#deauthenticate!' do
|
60
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, '/Users/AccessToken'].join }
|
61
|
+
|
62
|
+
context 'on success' do
|
63
|
+
it 'should deactivate the current access token' do
|
64
|
+
user = GunBroker::User.new(username, token: token)
|
65
|
+
|
66
|
+
stub_request(:delete, endpoint)
|
67
|
+
.with(headers: headers)
|
68
|
+
.to_return(body: response_fixture('deauthenticate'))
|
69
|
+
|
70
|
+
expect(user.deauthenticate!).to eq(true)
|
71
|
+
expect(user.token).to be_nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'on failure' do
|
76
|
+
it 'should raise an exception' do
|
77
|
+
user = GunBroker::User.new(username, token: token)
|
78
|
+
|
79
|
+
stub_request(:delete, endpoint)
|
80
|
+
.with(headers: headers)
|
81
|
+
.to_return(body: response_fixture('not_authorized'), status: 401)
|
82
|
+
|
83
|
+
expect { user.deauthenticate! }.to raise_error(GunBroker::Error::NotAuthorized)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context '#items' do
|
89
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, '/Items'].join }
|
90
|
+
|
91
|
+
context 'on success' do
|
92
|
+
it 'returns the User items' do
|
93
|
+
stub_request(:get, endpoint)
|
94
|
+
.with(
|
95
|
+
headers: headers('X-AccessToken' => token),
|
96
|
+
query: { 'SellerName' => username }
|
97
|
+
)
|
98
|
+
.to_return(body: response_fixture('items'))
|
99
|
+
|
100
|
+
user = GunBroker::User.new(username, token: token)
|
101
|
+
expect(user.items).not_to be_empty
|
102
|
+
expect(user.items.first).to be_a(GunBroker::Item)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'on failure' do
|
107
|
+
it 'should raise an exception' do
|
108
|
+
stub_request(:get, endpoint)
|
109
|
+
.with(
|
110
|
+
headers: headers('X-AccessToken' => token),
|
111
|
+
query: { 'SellerName' => username }
|
112
|
+
)
|
113
|
+
.to_return(body: response_fixture('not_authorized'), status: 401)
|
114
|
+
|
115
|
+
user = GunBroker::User.new(username, token: token)
|
116
|
+
expect { user.items }.to raise_error(GunBroker::Error::NotAuthorized)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context '#unsold_items' do
|
122
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, '/ItemsUnsold'].join }
|
123
|
+
|
124
|
+
context 'on success' do
|
125
|
+
it 'returns unsold Items' do
|
126
|
+
stub_request(:get, endpoint)
|
127
|
+
.with(headers: headers('X-AccessToken' => token))
|
128
|
+
.to_return(body: response_fixture('items'))
|
129
|
+
|
130
|
+
user = GunBroker::User.new(username, token: token)
|
131
|
+
expect(user.unsold_items).not_to be_empty
|
132
|
+
expect(user.unsold_items.first).to be_a(GunBroker::Item)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'on failure' do
|
137
|
+
it 'raises an exception' do
|
138
|
+
stub_request(:get, endpoint)
|
139
|
+
.with(headers: headers('X-AccessToken' => token))
|
140
|
+
.to_return(body: response_fixture('not_authorized'), status: 401)
|
141
|
+
|
142
|
+
user = GunBroker::User.new(username, token: token)
|
143
|
+
expect { user.unsold_items }.to raise_error(GunBroker::Error::NotAuthorized)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context '#sold_items' do
|
149
|
+
let(:endpoint) { [GunBroker::API::GUNBROKER_API, '/ItemsSold'].join }
|
150
|
+
|
151
|
+
context 'on success' do
|
152
|
+
it 'returns sold Items' do
|
153
|
+
stub_request(:get, endpoint)
|
154
|
+
.with(headers: headers('X-AccessToken' => token))
|
155
|
+
.to_return(body: response_fixture('items'))
|
156
|
+
|
157
|
+
user = GunBroker::User.new(username, token: token)
|
158
|
+
expect(user.sold_items).not_to be_empty
|
159
|
+
expect(user.sold_items.first).to be_a(GunBroker::Item)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'on failure' do
|
164
|
+
it 'raises an exception' do
|
165
|
+
stub_request(:get, endpoint)
|
166
|
+
.with(headers: headers('X-AccessToken' => token))
|
167
|
+
.to_return(body: response_fixture('not_authorized'), status: 401)
|
168
|
+
|
169
|
+
user = GunBroker::User.new(username, token: token)
|
170
|
+
expect { user.sold_items }.to raise_error(GunBroker::Error::NotAuthorized)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GunBroker do
|
4
|
+
|
5
|
+
it 'has a VERSION' do
|
6
|
+
expect(GunBroker::VERSION).to be_a(String)
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'dev_key' do
|
10
|
+
let(:key) { 'foo' }
|
11
|
+
|
12
|
+
it 'sets @@dev_key' do
|
13
|
+
GunBroker.dev_key = key
|
14
|
+
expect(GunBroker.class_variable_get(:@@dev_key)).to eq(key)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns @@dev_key' do
|
18
|
+
GunBroker.dev_key = key
|
19
|
+
expect(GunBroker.dev_key).to eq(key)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
|
4
|
+
Dir['./spec/support/**/*.rb'].each { |support| require support }
|
5
|
+
|
6
|
+
require 'gun_broker'
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.include GunBroker::Test::Fixtures
|
10
|
+
config.include GunBroker::Test::Headers
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gun_broker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dale Campbell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.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.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: webmock
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.20'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.20'
|
69
|
+
description: ''
|
70
|
+
email:
|
71
|
+
- oshuma@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .rspec
|
78
|
+
- .ruby-gemset
|
79
|
+
- .ruby-version
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE.txt
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- gun_broker.gemspec
|
85
|
+
- lib/gun_broker.rb
|
86
|
+
- lib/gun_broker/api.rb
|
87
|
+
- lib/gun_broker/category.rb
|
88
|
+
- lib/gun_broker/error.rb
|
89
|
+
- lib/gun_broker/item.rb
|
90
|
+
- lib/gun_broker/user.rb
|
91
|
+
- lib/gun_broker/version.rb
|
92
|
+
- spec/fixtures/authenticate.json
|
93
|
+
- spec/fixtures/categories.json
|
94
|
+
- spec/fixtures/category.json
|
95
|
+
- spec/fixtures/deauthenticate.json
|
96
|
+
- spec/fixtures/empty.json
|
97
|
+
- spec/fixtures/item.json
|
98
|
+
- spec/fixtures/items.json
|
99
|
+
- spec/fixtures/not_authorized.json
|
100
|
+
- spec/gun_broker/api_spec.rb
|
101
|
+
- spec/gun_broker/category_spec.rb
|
102
|
+
- spec/gun_broker/item_spec.rb
|
103
|
+
- spec/gun_broker/user_spec.rb
|
104
|
+
- spec/gun_broker_spec.rb
|
105
|
+
- spec/spec_helper.rb
|
106
|
+
- spec/support/fixtures.rb
|
107
|
+
- spec/support/headers.rb
|
108
|
+
homepage: ''
|
109
|
+
licenses:
|
110
|
+
- MIT
|
111
|
+
metadata: {}
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 2.4.1
|
129
|
+
signing_key:
|
130
|
+
specification_version: 4
|
131
|
+
summary: GunBroker.com API Ruby library.
|
132
|
+
test_files:
|
133
|
+
- spec/fixtures/authenticate.json
|
134
|
+
- spec/fixtures/categories.json
|
135
|
+
- spec/fixtures/category.json
|
136
|
+
- spec/fixtures/deauthenticate.json
|
137
|
+
- spec/fixtures/empty.json
|
138
|
+
- spec/fixtures/item.json
|
139
|
+
- spec/fixtures/items.json
|
140
|
+
- spec/fixtures/not_authorized.json
|
141
|
+
- spec/gun_broker/api_spec.rb
|
142
|
+
- spec/gun_broker/category_spec.rb
|
143
|
+
- spec/gun_broker/item_spec.rb
|
144
|
+
- spec/gun_broker/user_spec.rb
|
145
|
+
- spec/gun_broker_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
- spec/support/fixtures.rb
|
148
|
+
- spec/support/headers.rb
|