newegg-api 1.0.1
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/Gemfile +3 -0
- data/Gemfile.lock +53 -0
- data/LICENSE +22 -0
- data/README.md +144 -0
- data/Rakefile +7 -0
- data/lib/newegg.rb +13 -0
- data/lib/newegg/api.rb +430 -0
- data/lib/newegg/category.rb +26 -0
- data/lib/newegg/error.rb +5 -0
- data/lib/newegg/explorer.rb +20 -0
- data/lib/newegg/store.rb +35 -0
- data/lib/newegg/version.rb +3 -0
- data/newegg-api.gemspec +47 -0
- data/spec/api_spec.rb +150 -0
- data/spec/category_spec.rb +28 -0
- data/spec/newegg_spec.rb +20 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/store_spec.rb +31 -0
- metadata +165 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8a027adfba6fc335a04a7c9ddddb9319fae3ec1e
|
4
|
+
data.tar.gz: 9e2e4f48ff6025d23140c8b6cbfdeee783cd22be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 32c2e3aca2be907f1c3fb21b754d10fb940bb9eff0e1276879e52294d05183c61781d900bc777c0eb2e985c6e94981ca8c0ac324d5f400c7d2507a452c7e4a7d
|
7
|
+
data.tar.gz: b4fa8f313692e20cd929272912c650324b43c615f84db7b1d65d7d60d4e2f001fe6c2b58de987e38b15107754f58347060393022d3531f4219a1575a4ca2c66f
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
newegg-api (1.0.1)
|
5
|
+
faraday (~> 0.8)
|
6
|
+
json (~> 1.7)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
colorize (0.5.8)
|
12
|
+
coveralls (0.6.7)
|
13
|
+
colorize
|
14
|
+
multi_json (~> 1.3)
|
15
|
+
rest-client
|
16
|
+
simplecov (>= 0.7)
|
17
|
+
thor
|
18
|
+
diff-lcs (1.1.3)
|
19
|
+
fakeweb (1.3.0)
|
20
|
+
faraday (0.8.7)
|
21
|
+
multipart-post (~> 1.1)
|
22
|
+
json (1.8.0)
|
23
|
+
mime-types (1.23)
|
24
|
+
multi_json (1.4.0)
|
25
|
+
multipart-post (1.2.0)
|
26
|
+
rake (10.0.4)
|
27
|
+
rest-client (1.6.7)
|
28
|
+
mime-types (>= 1.16)
|
29
|
+
rspec (2.12.0)
|
30
|
+
rspec-core (~> 2.12.0)
|
31
|
+
rspec-expectations (~> 2.12.0)
|
32
|
+
rspec-mocks (~> 2.12.0)
|
33
|
+
rspec-core (2.12.1)
|
34
|
+
rspec-expectations (2.12.0)
|
35
|
+
diff-lcs (~> 1.1.3)
|
36
|
+
rspec-mocks (2.12.0)
|
37
|
+
simplecov (0.7.1)
|
38
|
+
multi_json (~> 1.0)
|
39
|
+
simplecov-html (~> 0.7.1)
|
40
|
+
simplecov-html (0.7.1)
|
41
|
+
thor (0.18.1)
|
42
|
+
|
43
|
+
PLATFORMS
|
44
|
+
ruby
|
45
|
+
x86-mingw32
|
46
|
+
|
47
|
+
DEPENDENCIES
|
48
|
+
coveralls (~> 0.6)
|
49
|
+
fakeweb (~> 1.3)
|
50
|
+
newegg-api!
|
51
|
+
rake (~> 10.0.4)
|
52
|
+
rspec (~> 2.11)
|
53
|
+
simplecov
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Chris Magnacca
|
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,144 @@
|
|
1
|
+
# Newegg Api Gem
|
2
|
+
|
3
|
+
A Ruby Wrapper for the Newegg Mobile API
|
4
|
+
|
5
|
+
[](https://api.travis-ci.org/chrismagnacca/newegg-api.png)
|
6
|
+
|
7
|
+
[](https://coveralls.io/r/chrismagnacca/newegg-api)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'newegg-api', :git => 'git://github.com/chrismagnacca/newegg-api.git'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Lastly, require the gem as such:
|
20
|
+
```ruby
|
21
|
+
require 'newegg'
|
22
|
+
```
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
|
26
|
+
#### Obtain Store Information
|
27
|
+
```ruby
|
28
|
+
Newegg.stores #=> Array<Newegg::Store>
|
29
|
+
```
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
Newegg::Store #=> Class Instance Variables
|
33
|
+
title, # store title
|
34
|
+
store_department, # store department name
|
35
|
+
store_id, # store id
|
36
|
+
show_see_all_deals, # boolean if store contains deals
|
37
|
+
categories # array of category ids
|
38
|
+
```
|
39
|
+
|
40
|
+
|
41
|
+
#### Obtain Categories for a Store
|
42
|
+
```ruby
|
43
|
+
Newegg.categories(store_id) #=> Array<Newegg::Category>
|
44
|
+
```
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
Newegg::Category #=> Class Instance Variables
|
48
|
+
description, # description of the returned Category
|
49
|
+
category_type, # category type
|
50
|
+
category_id, # category id
|
51
|
+
store_id, # store id
|
52
|
+
show_see_all_deals, # boolean if category contains deals
|
53
|
+
node_id # node id
|
54
|
+
```
|
55
|
+
|
56
|
+
#### Navigate through Categories
|
57
|
+
```ruby
|
58
|
+
Newegg.navigate(store_id, category_id, node_id) #=> Array<Newegg::Category>
|
59
|
+
```
|
60
|
+
|
61
|
+
#### Search for Products (all arguments optional)
|
62
|
+
```ruby
|
63
|
+
Newegg.search(store_id: STORE_ID, category_id: CAT_ID, sub_category_id: SUB_CAT_ID, node_id: NODE_ID, page_number: 1, sort: "FEATURED", keywords: KEYWORDS) #=> json
|
64
|
+
```
|
65
|
+
```json
|
66
|
+
{
|
67
|
+
"NavigationContentList" => [
|
68
|
+
{"TitleItem" => {"Description" => "Useful Links", "NavigationItemList" => [{...}]},
|
69
|
+
{"TitleItem" => {"Description" => "Price", "NavigationItemList" => [{...}]},
|
70
|
+
{"TitleItem" => {"Description" => "Manufacturer", "NavigationItemList" => [{...}]},
|
71
|
+
{"TitleItem" => {"Description" => "Type", "NavigationItemList" => [{...}]},
|
72
|
+
{"TitleItem" => {"Description" => "Color", "NavigationItemList" => [{...}]},
|
73
|
+
{"TitleItem" => {"Description" => "Case Material", "NavigationItemList" => [{...}]},
|
74
|
+
{"TitleItem" => {"Description" => "With Power Supply", "NavigationItemList" => [{...}]},
|
75
|
+
{"TitleItem" => {"Description" => "Power Supply", "NavigationItemList" => [{...}]},
|
76
|
+
{"TitleItem" => {"Description" => "With Side Panel Window", "NavigationItemList" => [{...}]},
|
77
|
+
{"TitleItem" => {"Description" => "External 5.25\" Drive Bays", "NavigationItemList" => [{...}]},
|
78
|
+
{"TitleItem" => {"Description" => "External 3.5\" Drive Bays", "NavigationItemList" => [{...}]},
|
79
|
+
{"TitleItem" => {"Description" => "Power Supply Mounted", "NavigationItemList" => [{...}]},
|
80
|
+
{"TitleItem" => {"Description" => "Internal 3.5\" Drive Bays", "NavigationItemList" => [{...}]},
|
81
|
+
{"TitleItem" => {"Description" => "Front Ports", "NavigationItemList" => [{...}]},
|
82
|
+
{"TitleItem" => {"Description" => "80mm Fans", "NavigationItemList" => [{...}]},
|
83
|
+
{"TitleItem" => {"Description" => "120mm Fans", "NavigationItemList" => [{...}]},
|
84
|
+
{"TitleItem" => {"Description" => "250mm Fans", "NavigationItemList" => [{...}]},
|
85
|
+
{"TitleItem" => {"Description" => "Side Air duct", "NavigationItemList" => [{...}]},
|
86
|
+
{"TitleItem" => {"Description" => "Expansion Slots", "NavigationItemList" => [{...}]}
|
87
|
+
],
|
88
|
+
|
89
|
+
"RelatedLinkList" => nil,
|
90
|
+
|
91
|
+
"CoremetricsInfo" => {"CategoryID" => "2010090007", ...}
|
92
|
+
|
93
|
+
"IsAllComboBundle" => false,
|
94
|
+
"CanBeCompare" => true,
|
95
|
+
"MasterComboStoreId" => 0,
|
96
|
+
"SubCategoryId" => 7,
|
97
|
+
"HasDeactivatedItems" => false,
|
98
|
+
"HasHasSimilarItems" => false,
|
99
|
+
"SearchProvider" => 0,
|
100
|
+
"SearchResultType" => 0,
|
101
|
+
"ProductListItems" => [
|
102
|
+
{"Title" => "Antec Three Hundred Illusion Black Steel ATX Mid Tower Computer Case", ...},
|
103
|
+
{"Title" => "COOLER MASTER HAF X RC-942-KKN1 Black Steel/ Plastic ATX Full Tower Computer Case", ...}
|
104
|
+
{"Title" => "Thermaltake VL84301W2Z V3 Black Edition with 430W Power Supply ATX Mid Tower Computer Case", ...}
|
105
|
+
],
|
106
|
+
"PaginationInfo" => {"TotalCount" => 572,
|
107
|
+
"PageSize" => 20,
|
108
|
+
"PageNumber" => 1,
|
109
|
+
"PageCount" => 0}
|
110
|
+
}
|
111
|
+
```
|
112
|
+
#### Retrieve Product Specifications
|
113
|
+
```ruby
|
114
|
+
Newegg.specifications(item_number)
|
115
|
+
```
|
116
|
+
|
117
|
+
```json
|
118
|
+
{
|
119
|
+
"NeweggItemNumber": "N82E16811147107",
|
120
|
+
"Title": "Rosewill BLACKHAWK Gaming ATX Mid Tower Computer Case, come with Five Fans, window side panel, top HDD dock ",
|
121
|
+
"SpecificationGroupList": [
|
122
|
+
{
|
123
|
+
"GroupName": "Model", "SpecificationPairList":
|
124
|
+
[{"Key": "Brand", "Value": "Rosewill"},
|
125
|
+
{"Key": "Model","Value": "BlackHawk"}]
|
126
|
+
}
|
127
|
+
{"GroupName": "Spec", "SpecificationPairList": [{..}]},
|
128
|
+
{"GroupName": "Expansion", "SpecificationPairList": [{..}]},
|
129
|
+
{"GroupName": "Front Ports", "SpecificationPairList": [{..}]},
|
130
|
+
{"GroupName": "Cooling System", "SpecificationPairList": [{..}]},
|
131
|
+
{"GroupName": "Physical Spec", "SpecificationPairList": [{..}]},
|
132
|
+
{"GroupName": "Features", "SpecificationPairList": [{..}]},
|
133
|
+
]
|
134
|
+
}
|
135
|
+
```
|
136
|
+
####
|
137
|
+
|
138
|
+
## Contributing
|
139
|
+
|
140
|
+
1. Fork it
|
141
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
142
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
143
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
144
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/newegg.rb
ADDED
data/lib/newegg/api.rb
ADDED
@@ -0,0 +1,430 @@
|
|
1
|
+
module Newegg
|
2
|
+
class Api
|
3
|
+
UserAgents = {
|
4
|
+
iPhone: 'Newegg iPhone App / 4.3.1',
|
5
|
+
Android: 'Newegg Android App / 3.3.3'
|
6
|
+
}
|
7
|
+
DefaultUserAgent = :iPhone
|
8
|
+
|
9
|
+
attr_accessor :conn, :_stores, :_categories, :_id
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
self._stores = []
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# retrieve an active connection or establish a new connection
|
17
|
+
#
|
18
|
+
# @ returns [Faraday::Connection] conn to the web service
|
19
|
+
#
|
20
|
+
def connection
|
21
|
+
self.conn ||= Faraday.new(:url => 'http://www.ows.newegg.com') do |faraday|
|
22
|
+
faraday.request :url_encoded # form-encode POST params
|
23
|
+
faraday.response :logger # log requests to STDOUT
|
24
|
+
|
25
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# retrieve and populate a list of available stores
|
31
|
+
#
|
32
|
+
def stores
|
33
|
+
return self._stores if not self._stores.empty?
|
34
|
+
response = api_get("Stores.egg")
|
35
|
+
stores = JSON.parse(response.body)
|
36
|
+
stores.each do |store|
|
37
|
+
self._stores << Newegg::Store.new(store['Title'], store['StoreDepa'], store['StoreID'], store['ShowSeeAllDeals'])
|
38
|
+
end
|
39
|
+
self._stores
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# retrieve and populate list of categories for a given store_id
|
44
|
+
#
|
45
|
+
# @param [Integer] store_id of the store
|
46
|
+
#
|
47
|
+
def categories(store_id)
|
48
|
+
return [] if store_id.nil?
|
49
|
+
|
50
|
+
response = api_get("Stores.egg", "Categories", store_id)
|
51
|
+
categories = JSON.parse(response.body)
|
52
|
+
categories = categories.collect do |category|
|
53
|
+
Newegg::Category.new(category['Description'], category['CategoryType'], category['CategoryID'],
|
54
|
+
category['StoreID'], category['ShowSeeAllDeals'], category['NodeId'])
|
55
|
+
end
|
56
|
+
|
57
|
+
categories
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# retrieves information necessary to search for products, given the store_id, category_id, node_id
|
62
|
+
#
|
63
|
+
# @param [Integer] store_id of the store
|
64
|
+
# @param [Integer] category_id of the store
|
65
|
+
# @param [Integer] node_id of the store
|
66
|
+
#
|
67
|
+
def navigate(store_id, category_id, node_id)
|
68
|
+
response = api_get("Stores.egg", "Navigation", "#{store_id}/#{category_id}/#{node_id}")
|
69
|
+
categories = JSON.parse(response.body)
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# retrieves store content
|
74
|
+
#
|
75
|
+
def store_content(store_id, category_id = -1, node_id = -1, store_type = 4, page_number = 1)
|
76
|
+
params = {
|
77
|
+
'storeId' => store_id,
|
78
|
+
'categoryId' => category_id,
|
79
|
+
'nodeId' => node_id,
|
80
|
+
'storeType' => store_type,
|
81
|
+
'pageNumber' => page_number
|
82
|
+
}
|
83
|
+
JSON.parse(api_get('Stores.egg', 'Content', nil, params).body)
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# retrieves stores
|
88
|
+
#
|
89
|
+
def shop_all_navigation
|
90
|
+
JSON.parse(api_get('Store.egg', 'ShopAllNavigation').body)
|
91
|
+
end
|
92
|
+
|
93
|
+
def shop_more_navigation
|
94
|
+
JSON.parse(api_get('Store.egg', 'MoreNavigation').body)
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# retrieves information necessary to search for products, given the store_id, category_id, node_id
|
99
|
+
#
|
100
|
+
# @param [Integer] store_id of the store
|
101
|
+
# @param [Integer] category_id of the store
|
102
|
+
# @param [Integer] node_id of the store
|
103
|
+
# @param [Integer] store_type of the store
|
104
|
+
#
|
105
|
+
def store_navigate(store_id, category_id = -1, node_id = -1, store_type = 4)
|
106
|
+
params = {
|
107
|
+
'storeId' => store_id,
|
108
|
+
'categoryId' => category_id,
|
109
|
+
'nodeId' => node_id,
|
110
|
+
'storeType' => store_type
|
111
|
+
}
|
112
|
+
JSON.parse(api_get('Store.egg', 'storeNavigation', nil, params).body)
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# retrieves a single page of products given a query specified by an options hash. See options below.
|
117
|
+
# node_id, page_number, and an optional sorting method
|
118
|
+
#
|
119
|
+
# @param [Integer] store_id, from @api.navigation, returned as StoreID
|
120
|
+
# @param [Integer] category_id from @api.navigation, returned as CategoryType
|
121
|
+
# @param [Integer] sub_category_id from @api.navigation, returned as CategoryID
|
122
|
+
# @param [Integer] node_id from @api.navigation, returned as NodeId
|
123
|
+
# @param [Integer] page_number of the paginated search results, returned as PaginationInfo from search
|
124
|
+
# @param [String] sort style of the returned search results, default is FEATURED (can also be RATING, PRICE, PRICED, REVIEWS)
|
125
|
+
# @param [String] keywords
|
126
|
+
#
|
127
|
+
def search(options={})
|
128
|
+
options = {store_id: -1, category_id: -1, sub_category_id: -1, node_id: -1, page_number: 1, sort: "FEATURED",
|
129
|
+
keywords: ""}.merge(options)
|
130
|
+
request = {
|
131
|
+
'IsUPCCodeSearch' => false,
|
132
|
+
'IsSubCategorySearch' => options[:sub_category_id] > 0,
|
133
|
+
'isGuideAdvanceSearch' => false,
|
134
|
+
'StoreDepaId' => options[:store_id],
|
135
|
+
'CategoryId' => options[:category_id],
|
136
|
+
'SubCategoryId' => options[:sub_category_id],
|
137
|
+
'NodeId' => options[:node_id],
|
138
|
+
'BrandId' => -1,
|
139
|
+
'NValue' => "",
|
140
|
+
'Keyword' => options[:keywords],
|
141
|
+
'Sort' => options[:sort],
|
142
|
+
'PageNumber' => options[:page_number]
|
143
|
+
}
|
144
|
+
|
145
|
+
JSON.parse(api_post("Search.egg", "Advanced", request).body, {quirks_mode: true})
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# retrieves a single page of products given a query specified by an options hash. See options below.
|
150
|
+
#
|
151
|
+
# @param [Array] brand_list
|
152
|
+
# @param [Array] search_properties
|
153
|
+
# @param [String] keyword
|
154
|
+
# @param [String] max_price
|
155
|
+
# @param [String] min_price
|
156
|
+
# @param [String] nvalue
|
157
|
+
# @param [Array] product_type
|
158
|
+
# @param [Integer] page_number
|
159
|
+
# @param [Integer] node_id
|
160
|
+
# @param [Integer] category_id
|
161
|
+
# @param [Integer] brand_id
|
162
|
+
# @param [Integer] store_id
|
163
|
+
# @param [Integer] store_type
|
164
|
+
# @param [Integer] sub_category_id
|
165
|
+
#
|
166
|
+
def query(options={})
|
167
|
+
options = {brand_list: [], search_properties: [], keyword: '', max_price:'', min_price: '', nvalue: '', product_type: [],
|
168
|
+
page_number: 1, node_id: -1, category_id: -1, brand_id: -1, store_id: -1, store_type: -1, sub_category_id: -1}.merge(options)
|
169
|
+
request = {
|
170
|
+
'BrandList' => options[:brand_list],
|
171
|
+
'SearchProperties' => options[:search_properties],
|
172
|
+
'Keyword' => options[:keyword],
|
173
|
+
'MaxPrice' => options[:max_price],
|
174
|
+
'MinPrice' => options[:min_price],
|
175
|
+
'NValue' => options[:nvalue],
|
176
|
+
'ProductType' => options[:product_type],
|
177
|
+
'PageNumber' => options[:page_number],
|
178
|
+
'NodeId' => options[:node_id],
|
179
|
+
'CategoryId' => options[:category_id],
|
180
|
+
'BrandId' => options[:brand_id],
|
181
|
+
'StoreId' => options[:store_id],
|
182
|
+
'StoreType' => options[:store_type],
|
183
|
+
'SubCategoryId' => options[:sub_category_id]
|
184
|
+
}
|
185
|
+
|
186
|
+
JSON.parse(api_post('Search.egg', 'Query', request).body, {quirks_mode: true})
|
187
|
+
end
|
188
|
+
|
189
|
+
#
|
190
|
+
# retrieve power search content given an category
|
191
|
+
#
|
192
|
+
# @param [Integer] category_id
|
193
|
+
#
|
194
|
+
def power_search_content(category_id)
|
195
|
+
JSON.parse(api_get('PowerSearchContent.egg', '0', "#{category_id}/-1").body)
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
# retrieves a single page of products given a query specified by an options hash. See options below.
|
200
|
+
#
|
201
|
+
# @param [Array] search_properties
|
202
|
+
# @param [Integer] page_number of the paginated power search results
|
203
|
+
# @param [Array] product_type
|
204
|
+
# @param [String] min_price
|
205
|
+
# @param [String] nvalues
|
206
|
+
# @param [String] srch_in_desc
|
207
|
+
# @param [Array] brand_list
|
208
|
+
# @param [String] max_price
|
209
|
+
#
|
210
|
+
def power_search(search_properties, options={})
|
211
|
+
options = {page_number: 1, product_type: [], min_price: '', nvalues: '', srch_in_desc: '',
|
212
|
+
brand_list: [], max_price: ''}.merge(options)
|
213
|
+
request = {
|
214
|
+
'PageNumber' => options[:page_number],
|
215
|
+
'ProductType' => options[:product_type],
|
216
|
+
'SearchProperties' => search_properties,
|
217
|
+
'MinPrice' => options[:min_price],
|
218
|
+
'NValues' => options[:nvalues],
|
219
|
+
'SrchInDesc' => options[:srch_in_desc],
|
220
|
+
'BrandList' => options[:brand_list],
|
221
|
+
'MaxPrice' => options[:max_price]
|
222
|
+
}
|
223
|
+
|
224
|
+
JSON.parse(api_post('PowerSearch.egg', nil, request).body, {quirks_mode: true})
|
225
|
+
end
|
226
|
+
|
227
|
+
#
|
228
|
+
# retrieve related keywords given an keyword
|
229
|
+
#
|
230
|
+
# @param [String] item_number of the product
|
231
|
+
#
|
232
|
+
def keywords(keyword)
|
233
|
+
JSON.parse(api_get('AutoKeywords.egg', nil, nil, keyword: keyword).body)
|
234
|
+
end
|
235
|
+
|
236
|
+
#
|
237
|
+
# retrieve product details given an item number
|
238
|
+
#
|
239
|
+
# @param [String] item_number of the product
|
240
|
+
#
|
241
|
+
def details(item_number)
|
242
|
+
JSON.parse(api_get('Products.egg', item_number, 'ProductDetails').body)
|
243
|
+
end
|
244
|
+
|
245
|
+
#
|
246
|
+
# retrieve product information given an item number
|
247
|
+
#
|
248
|
+
# @param [String] item_number of the product
|
249
|
+
#
|
250
|
+
def specifications(item_number)
|
251
|
+
JSON.parse(api_get("Products.egg", item_number, "Specification").body)
|
252
|
+
end
|
253
|
+
|
254
|
+
#
|
255
|
+
# retrieve product combo deals given an item number
|
256
|
+
#
|
257
|
+
# @param [String] item_number of the product
|
258
|
+
# @param [Integer] sub_category
|
259
|
+
# @param [Integer] sort_field
|
260
|
+
# @param [Integer] page_number
|
261
|
+
#
|
262
|
+
def combo_deals(item_number, options={})
|
263
|
+
options = {sub_category: -1, sort_field: 0, page_number: 1}.merge(options)
|
264
|
+
params = {
|
265
|
+
'SubCategory' => options[:sub_category],
|
266
|
+
'SortField' => options[:sort_field],
|
267
|
+
'PageNumber' => options[:page_number]
|
268
|
+
}
|
269
|
+
JSON.parse(api_get('Products.egg', item_number, 'ComboDeals', params).body)
|
270
|
+
end
|
271
|
+
|
272
|
+
#
|
273
|
+
# retrieve product reviews given an item number
|
274
|
+
#
|
275
|
+
# @param [String] item_number of the product
|
276
|
+
# @param [Integer] page_number
|
277
|
+
# @param [String] time
|
278
|
+
# @param [String] rating default All (can also be 5, 4, 3, 2, 1)
|
279
|
+
# @param [String] sort default 'date posted' (can also be 'most helpful', 'highest rated', 'lowest rated', 'ownership')
|
280
|
+
#
|
281
|
+
def reviews(item_number, page_number = 1, options={})
|
282
|
+
options = {time: 'all', rating: 'All', sort: 'date posted'}.merge(options)
|
283
|
+
params = {
|
284
|
+
'filter.time' => options[:time],
|
285
|
+
'filter.rating' => options[:rating],
|
286
|
+
'sort' => options[:sort]
|
287
|
+
}
|
288
|
+
JSON.parse(api_get('Products.egg', item_number, "Reviewsinfo/#{page_number}", params).body)
|
289
|
+
end
|
290
|
+
|
291
|
+
#
|
292
|
+
# retrieve tracking country
|
293
|
+
#
|
294
|
+
def country
|
295
|
+
JSON.parse(api_get('Tracking.egg', 'Country').body)
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# retrieve shopping guide config
|
300
|
+
#
|
301
|
+
def shopping_guide
|
302
|
+
JSON.parse(api_get('Configurations.egg', 'ShoppingGuideConfig').body)
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# retrieve iphone client config
|
307
|
+
#
|
308
|
+
def client_config
|
309
|
+
JSON.parse(api_get('Configurations.egg', 'IphoneClient').body)
|
310
|
+
end
|
311
|
+
|
312
|
+
#
|
313
|
+
# retrieve exclusive deal item
|
314
|
+
#
|
315
|
+
def exclusive_deals
|
316
|
+
JSON.parse(api_get('Promotions.egg', 'ExclusiveDeals').body)
|
317
|
+
end
|
318
|
+
|
319
|
+
#
|
320
|
+
# retrieve daily deal
|
321
|
+
#
|
322
|
+
def daily_deal
|
323
|
+
JSON.parse(api_get('Promotions.egg', 'DailyDeal').body)
|
324
|
+
end
|
325
|
+
|
326
|
+
#
|
327
|
+
# retrieve spotlight item
|
328
|
+
#
|
329
|
+
def spotlight
|
330
|
+
JSON.parse(api_get('Promotions.egg', 'Spotlight').body)
|
331
|
+
end
|
332
|
+
|
333
|
+
#
|
334
|
+
# retrieve spotlights
|
335
|
+
#
|
336
|
+
def spotlights
|
337
|
+
JSON.parse(api_get('Promotions.egg', 'Spotlights').body)
|
338
|
+
end
|
339
|
+
|
340
|
+
#
|
341
|
+
# retrieve shell shocker items
|
342
|
+
#
|
343
|
+
def shell_shockers
|
344
|
+
JSON.parse(api_get('Promotions.egg', 'ShellShockers').body)
|
345
|
+
end
|
346
|
+
|
347
|
+
#
|
348
|
+
# retrieve new shell shocker items
|
349
|
+
#
|
350
|
+
def shell_shockers_new
|
351
|
+
JSON.parse(api_get('Promotions.egg', 'NewShellShocker').body)
|
352
|
+
end
|
353
|
+
|
354
|
+
#
|
355
|
+
# retrieve banners
|
356
|
+
#
|
357
|
+
def banners
|
358
|
+
JSON.parse(api_get('Promotions.egg', 'Banners').body)
|
359
|
+
end
|
360
|
+
|
361
|
+
private
|
362
|
+
|
363
|
+
#
|
364
|
+
# GET: {controller}/{action}/{id}/
|
365
|
+
#
|
366
|
+
# @param [String] controller
|
367
|
+
# @param [optional, String] action
|
368
|
+
# @param [optional, String] id
|
369
|
+
#
|
370
|
+
def api_get(controller, action = nil, id = nil, params = {})
|
371
|
+
uri = String.new
|
372
|
+
|
373
|
+
if action && id
|
374
|
+
uri = "/#{controller}/#{action}/#{id}"
|
375
|
+
elsif action
|
376
|
+
uri = "/#{controller}/#{action}/"
|
377
|
+
else
|
378
|
+
uri = "/#{controller}/"
|
379
|
+
end
|
380
|
+
|
381
|
+
response = self.connection.get(uri, params) do |request|
|
382
|
+
request.headers['Content-Type'] = 'application/json'
|
383
|
+
request.headers['Accept'] = 'application/json'
|
384
|
+
request.headers['User-Agent'] = UserAgents[DefaultUserAgent]
|
385
|
+
end
|
386
|
+
|
387
|
+
case code = response.status.to_i
|
388
|
+
when 400..499
|
389
|
+
raise(Newegg::NeweggClientError, "error, #{code}: #{response.inspect}")
|
390
|
+
when 500..599
|
391
|
+
raise(Newegg::NeweggServerError, "error, #{code}: #{response.inspect}")
|
392
|
+
else
|
393
|
+
response
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
#
|
398
|
+
# POST: {controller}/{action}/
|
399
|
+
#
|
400
|
+
# @param [String] controller
|
401
|
+
# @param [String] action
|
402
|
+
# @param [Hash] opts
|
403
|
+
#
|
404
|
+
def api_post(controller, action = nil, opts={})
|
405
|
+
uri = String.new
|
406
|
+
if action
|
407
|
+
uri = "/#{controller}/#{action}/"
|
408
|
+
else
|
409
|
+
uri = "/#{controller}/"
|
410
|
+
end
|
411
|
+
response = self.connection.post do |request|
|
412
|
+
request.url uri
|
413
|
+
request.headers['Content-Type'] = 'application/json'
|
414
|
+
request.headers['Accept'] = 'application/json'
|
415
|
+
request.headers['User-Agent'] = UserAgents[DefaultUserAgent]
|
416
|
+
request.body = opts.to_json
|
417
|
+
end
|
418
|
+
|
419
|
+
case code = response.status.to_i
|
420
|
+
when 400..499
|
421
|
+
raise(Newegg::NeweggClientError, "error, #{code}: #{response.inspect}")
|
422
|
+
when 500..599
|
423
|
+
raise(Newegg::NeweggServerError, "error, #{code}: #{response.inspect}")
|
424
|
+
else
|
425
|
+
response
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
end
|
430
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Newegg
|
2
|
+
class Category < Api
|
3
|
+
attr_accessor :description, :category_type, :category_id, :store_id, :show_see_all_deals, :node_id
|
4
|
+
|
5
|
+
def initialize(description, category_type, category_id, store_id, show_see_all_deals, node_id)
|
6
|
+
self.description = description
|
7
|
+
self.category_type = category_type
|
8
|
+
self.category_id = category_id
|
9
|
+
self.store_id = store_id
|
10
|
+
self.show_see_all_deals = show_see_all_deals
|
11
|
+
self.node_id = node_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_h
|
15
|
+
@h ||= {
|
16
|
+
:description => description,
|
17
|
+
:category_type => category_type,
|
18
|
+
:category_id => category_id,
|
19
|
+
:store_id => store_id,
|
20
|
+
:node_id => node_id
|
21
|
+
}.freeze
|
22
|
+
@h
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/newegg/error.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Newegg
|
2
|
+
module Explorer
|
3
|
+
require 'newegg/api'
|
4
|
+
|
5
|
+
def api
|
6
|
+
@api ||= Api.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(method, *args, &block)
|
10
|
+
return self.api.send(method) if args.empty?
|
11
|
+
self.api.send(method, *args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def respond_to?(method)
|
15
|
+
return true if (self.methods.include?(method) || self.instance_methods.include?(method))
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/lib/newegg/store.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Newegg
|
2
|
+
class Store < Api
|
3
|
+
attr_accessor :title, :store_department, :store_id, :show_see_all_deals, :categories
|
4
|
+
|
5
|
+
def initialize(title, store_department, store_id, show_see_all_deals)
|
6
|
+
self.title = title
|
7
|
+
self.store_department = store_department
|
8
|
+
self.store_id = store_id
|
9
|
+
self.show_see_all_deals = show_see_all_deals
|
10
|
+
self.categories = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_categories(newegg = Newegg)
|
14
|
+
self.categories = newegg.categories(self.store_id).freeze if self.categories.empty?
|
15
|
+
self.categories
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_h(newegg = Newegg)
|
19
|
+
@h ||= begin
|
20
|
+
categories_hash = []
|
21
|
+
get_categories(newegg).each do |c|
|
22
|
+
categories_hash << c.to_h
|
23
|
+
end
|
24
|
+
{
|
25
|
+
:title => title,
|
26
|
+
:store_department => store_department,
|
27
|
+
:store_id => store_id,
|
28
|
+
:show_see_all_deals => show_see_all_deals,
|
29
|
+
:categories => categories_hash
|
30
|
+
}.freeze
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/newegg-api.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/newegg/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = %q{newegg-api}
|
6
|
+
spec.version = Newegg::VERSION
|
7
|
+
|
8
|
+
spec.authors = ['Chris Magnacca']
|
9
|
+
spec.email = %w{'chrismagnacca@gmail.com'}
|
10
|
+
spec.description = %q{this gem allows the usage of the newegg.com api to ascertain product information.}
|
11
|
+
spec.summary = %q{newegg's json api}
|
12
|
+
spec.homepage = %q{http://github.com/chrismagnacca/newegg-api}
|
13
|
+
|
14
|
+
spec.files = %w{
|
15
|
+
Gemfile
|
16
|
+
Gemfile.lock
|
17
|
+
LICENSE
|
18
|
+
README.md
|
19
|
+
Rakefile
|
20
|
+
lib/
|
21
|
+
lib/newegg.rb
|
22
|
+
lib/newegg/api.rb
|
23
|
+
lib/newegg/category.rb
|
24
|
+
lib/newegg/error.rb
|
25
|
+
lib/newegg/store.rb
|
26
|
+
lib/newegg/explorer.rb
|
27
|
+
lib/newegg/version.rb
|
28
|
+
spec/api_spec.rb
|
29
|
+
spec/category_spec.rb
|
30
|
+
spec/spec_helper.rb
|
31
|
+
spec/newegg_spec.rb
|
32
|
+
spec/store_spec.rb
|
33
|
+
newegg-api.gemspec
|
34
|
+
}
|
35
|
+
|
36
|
+
spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
37
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
38
|
+
|
39
|
+
spec.require_paths = ['lib']
|
40
|
+
spec.add_dependency(%q<json>,['~>1.7'])
|
41
|
+
spec.add_dependency(%q<faraday>,['~>0.8'])
|
42
|
+
spec.add_development_dependency(%q<simplecov>)
|
43
|
+
spec.add_development_dependency(%q<fakeweb>,['~>1.3'])
|
44
|
+
spec.add_development_dependency(%q<rspec>,['~>2.11'])
|
45
|
+
spec.add_development_dependency(%q<rake>, ['~>10.0.4'])
|
46
|
+
spec.add_development_dependency(%q<coveralls>, ['~>0.6'])
|
47
|
+
end
|
data/spec/api_spec.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Newegg::Api do
|
4
|
+
before(:each) do
|
5
|
+
@api = Newegg::Api.new
|
6
|
+
FakeWeb.clean_registry
|
7
|
+
end
|
8
|
+
|
9
|
+
it %q{throws an error when response is 404} do
|
10
|
+
FakeWeb.register_uri(:get, "http://www.ows.newegg.com/Stores.egg/", :status => ["404", "Not Found"])
|
11
|
+
lambda {
|
12
|
+
@api.send(:api_get, "Stores.egg")
|
13
|
+
}.should raise_error Newegg::NeweggClientError
|
14
|
+
end
|
15
|
+
|
16
|
+
it %q{throws an error when response is 404} do
|
17
|
+
FakeWeb.register_uri(:get, %r{http://www.ows.newegg.com/Stores.egg/}, :status => ["500", "Server Error"])
|
18
|
+
lambda {
|
19
|
+
@api.send(:api_get, "Stores.egg")
|
20
|
+
}.should raise_error Newegg::NeweggServerError
|
21
|
+
end
|
22
|
+
|
23
|
+
it %q{should return an array of Newegg::Store for Newegg::Api.stores} do
|
24
|
+
@api.stores.each do |store|
|
25
|
+
store.class.should eq(Newegg::Store)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "categories()" do
|
30
|
+
subject { @api.categories(store_id) }
|
31
|
+
context "with a valid store_id" do
|
32
|
+
let(:store_id) { 1 }
|
33
|
+
it "should return the correct categories" do
|
34
|
+
categories = {
|
35
|
+
'Backup Devices & Media' => 2,
|
36
|
+
'Barebone / Mini Computers' => 3,
|
37
|
+
'CD / DVD / Blu-Ray Burners & Media' => 10,
|
38
|
+
'Computer Accessories' => 1,
|
39
|
+
'Computer Cases' => 9,
|
40
|
+
'CPUs / Processors' => 34,
|
41
|
+
'Fans & PC Cooling' => 11,
|
42
|
+
'Flash Memory & Readers' => 324,
|
43
|
+
'Hard Drives' => 15,
|
44
|
+
'Headsets, Speakers, & Soundcards' => 37,
|
45
|
+
'Input Devices' => 29,
|
46
|
+
'Keyboards & Mice' => 234,
|
47
|
+
'Memory' => 17,
|
48
|
+
'Monitors' => 19,
|
49
|
+
'Motherboards' => 20,
|
50
|
+
'Networking' => 281,
|
51
|
+
'Power Protection' => 314,
|
52
|
+
'Power Supplies' => 32,
|
53
|
+
'Printers / Scanners & Supplies' => 33,
|
54
|
+
'Projectors' => 343,
|
55
|
+
'Servers & Workstations' => 271,
|
56
|
+
'SSDs' => 119,
|
57
|
+
'Video Cards & Video Devices' => 38
|
58
|
+
}
|
59
|
+
|
60
|
+
expect(subject.length).to eq(categories.length)
|
61
|
+
expect(subject.collect{|c| c.description}).to match_array categories.keys
|
62
|
+
expect(subject.collect{|c| c.category_id}).to match_array categories.values
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return the same categories after multiple calls" do
|
66
|
+
orig_cats = subject.dup
|
67
|
+
@api.categories(@api.stores.last.store_id)
|
68
|
+
new_cats = @api.categories(store_id)
|
69
|
+
expect(orig_cats.collect{|c| c.description}).to match_array new_cats.collect{|c| c.description}
|
70
|
+
expect(orig_cats.collect{|c| c.category_id}).to match_array new_cats.collect{|c| c.category_id}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "with an invalid store_id" do
|
75
|
+
let(:store_id) { 23123 }
|
76
|
+
it "should return an empty array" do
|
77
|
+
expect(subject).to be_empty
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "with a nil store_id" do
|
82
|
+
let(:store_id) { nil }
|
83
|
+
it "should return an empty array" do
|
84
|
+
expect(subject).to be_empty
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it %q{should return an array of Newegg::Category for Newegg::Api.stores[index].categories} do
|
90
|
+
@api.stores.each do |store|
|
91
|
+
store.categories.each do |category|
|
92
|
+
category.class.should eq(Newegg::Category)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it %q{should return a stores categories for Newegg::Api.stores[index].categories} do
|
98
|
+
@api.stores.first.categories.should_not be_nil
|
99
|
+
@api.stores.last.categories.should_not be_nil
|
100
|
+
end
|
101
|
+
|
102
|
+
it %q{returns success for retrieve(store_id, category_id, node_id)} do
|
103
|
+
response = {"Description" => "Backup Devices & Media", "CategoryType" => 0, "CategoryID" => 2, "StoreID" => 1, "ShowSeeAllDeals" => true, "NodeId" => 6642}
|
104
|
+
@api.navigate(response["StoreID"], response["CategoryID"], response["NodeId"]).should_not be_nil
|
105
|
+
end
|
106
|
+
|
107
|
+
it %q{returns success for search(store_id, category_id, sub_category_id, node_id)} do
|
108
|
+
response ={"Description" => "Computer Cases", "CategoryType" => 1, "CategoryID" => 7, "StoreID" => 1, "ShowSeeAllDeals" => false, "NodeId" => 7583}
|
109
|
+
@api.search(store_id: response["StoreID"], category_id: response["CategoryType"], sub_category_id: response["CategoryID"], node_id: response["NodeId"], page_number: 1)['PaginationInfo']['TotalCount'].should be > 0
|
110
|
+
end
|
111
|
+
|
112
|
+
it %q{throws error for search(store_id, category_id, sub_category_id, node_id} do
|
113
|
+
FakeWeb.register_uri(:post, %r{http://www.ows.newegg.com/Search.egg/Advanced}, :status => ["404", "Not Found"])
|
114
|
+
response = {"Description" => "Computer Cases", "CategoryType" => 1, "CategoryID" => 7, "StoreID" => 1, "ShowSeeAllDeals" => false, "NodeId" => 7583}
|
115
|
+
lambda {
|
116
|
+
@api.search(store_id: response["StoreID"], category_id: response["CategoryType"], sub_category_id: response["CategoryID"], node_id: response["NodeId"], page_number: 1)
|
117
|
+
}.should raise_error Newegg::NeweggClientError
|
118
|
+
end
|
119
|
+
|
120
|
+
it %q{throws error for search(store_id, category_id, sub_category_id, node_id} do
|
121
|
+
FakeWeb.register_uri(:post, %r{http://www.ows.newegg.com/Search.egg/Advanced}, :status => ["500", "Server"])
|
122
|
+
response = {"Description" => "Computer Cases", "CategoryType" => 1, "CategoryID" => 7, "StoreID" => 1, "ShowSeeAllDeals" => false, "NodeId" => 7583}
|
123
|
+
lambda {
|
124
|
+
@api.search(store_id: response["StoreID"], category_id: response["CategoryType"], sub_category_id: response["CategoryID"], node_id: response["NodeId"], page_number: 1)
|
125
|
+
}.should raise_error Newegg::NeweggServerError
|
126
|
+
end
|
127
|
+
|
128
|
+
it %q{returns success for search(keywords)} do
|
129
|
+
expect(@api.search(keywords: "gtx 770")['PaginationInfo']['TotalCount']).to be > 0
|
130
|
+
end
|
131
|
+
|
132
|
+
it %q{returns nil for a NULL search result} do
|
133
|
+
expect(@api.search()).to be_nil
|
134
|
+
end
|
135
|
+
|
136
|
+
it %q{returns success for specifications} do
|
137
|
+
response = {"NeweggItemNumber"=>"N82E16823114051",
|
138
|
+
"Title"=>"RAZER BlackWidow Chroma RZ03-01220200-R3U1 USB Wired Gaming RGB Mechanical Keyboard",
|
139
|
+
"SpecificationGroupList"=> [{
|
140
|
+
"GroupName"=>"Model", "SpecificationPairList"=>[{
|
141
|
+
"Key"=>"Brand", "Value"=>"RAZER"}, {"Key"=>"Name", "Value"=>"BlackWidow Chroma"}, {"Key"=>"Model", "Value"=>"RZ03-01220200-R3U1"}]}, {"GroupName"=>"Spec", "SpecificationPairList"=>[{
|
142
|
+
"Key"=>"Keyboard Interface", "Value"=>"USB"}, {"Key"=>"Design Style", "Value"=>"Gaming"}, {"Key"=>"Mechanical Keyboard", "Value"=>"Yes"}, {"Key"=>"Type", "Value"=>"Wired"}]
|
143
|
+
}]}
|
144
|
+
specs = @api.specifications("N82E16823114051")
|
145
|
+
expect(specs['SpecificationGroupList'].length).to eq(response['SpecificationGroupList'].length)
|
146
|
+
res_group_names = response['SpecificationGroupList'].collect{|s| s['GroupName']}
|
147
|
+
specs['SpecificationGroupList'].each{|s| expect(res_group_names).to include s['GroupName']}
|
148
|
+
end
|
149
|
+
|
150
|
+
end #end Newegg::Api
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Newegg::Category do
|
4
|
+
|
5
|
+
it %q{should return a Newegg::Category for Newegg::Category.new(description, category_type, category_id, store_id, show_see_all_deals, node_id)} do
|
6
|
+
description = "Backup Devices & Media"
|
7
|
+
category_type = 0
|
8
|
+
category_id = 2
|
9
|
+
store_id = 1
|
10
|
+
show_see_all_deals = true
|
11
|
+
node_id = 6642
|
12
|
+
|
13
|
+
category = Newegg::Category.new(description, category_type, category_id, store_id, show_see_all_deals, node_id)
|
14
|
+
|
15
|
+
category.description.should eq("Backup Devices & Media")
|
16
|
+
category.category_type.should eq(0)
|
17
|
+
category.store_id.should eq(1)
|
18
|
+
category.show_see_all_deals.should eq(true)
|
19
|
+
category.node_id.should eq(6642)
|
20
|
+
end
|
21
|
+
|
22
|
+
it %q{should return category information when .to_h is called on a Newegg::Category} do
|
23
|
+
category = Newegg.categories(Newegg.stores.first.store_id)
|
24
|
+
response = {:title=>"Computer Hardware", :store_department=>"ComputerHardware", :store_id=>1, :show_see_all_deals=>true, :categories=>[{:description=>"Backup Devices & Media", :category_type=>0, :category_id=>2, :store_id=>1, :node_id=>6642}, {:description=>"Barebone / Mini Computers", :category_type=>0, :category_id=>3, :store_id=>1, :node_id=>6668}, {:description=>"CD / DVD / Blu-Ray Burners & Media", :category_type=>0, :category_id=>10, :store_id=>1, :node_id=>6646}, {:description=>"Computer Accessories", :category_type=>0, :category_id=>1, :store_id=>1, :node_id=>6640}, {:description=>"Computer Cases", :category_type=>0, :category_id=>9, :store_id=>1, :node_id=>6644}, {:description=>"CPUs / Processors", :category_type=>0, :category_id=>34, :store_id=>1, :node_id=>6676}, {:description=>"Fans & PC Cooling", :category_type=>0, :category_id=>11, :store_id=>1, :node_id=>6648}, {:description=>"Flash Memory & Readers", :category_type=>0, :category_id=>324, :store_id=>1, :node_id=>6682}, {:description=>"Hard Drives", :category_type=>0, :category_id=>15, :store_id=>1, :node_id=>6670}, {:description=>"Headsets, Speakers, & Soundcards", :category_type=>0, :category_id=>37, :store_id=>1, :node_id=>6660}, {:description=>"Input Devices", :category_type=>0, :category_id=>29, :store_id=>1, :node_id=>6666}, {:description=>"Keyboards & Mice", :category_type=>0, :category_id=>234, :store_id=>1, :node_id=>6690}, {:description=>"Memory", :category_type=>0, :category_id=>17, :store_id=>1, :node_id=>6650}, {:description=>"Monitors", :category_type=>0, :category_id=>19, :store_id=>1, :node_id=>6652}, {:description=>"Motherboards", :category_type=>0, :category_id=>20, :store_id=>1, :node_id=>6654}, {:description=>"Networking", :category_type=>0, :category_id=>281, :store_id=>1, :node_id=>6688}, {:description=>"Power Protection", :category_type=>0, :category_id=>314, :store_id=>1, :node_id=>6674}, {:description=>"Power Supplies", :category_type=>0, :category_id=>32, :store_id=>1, :node_id=>6656}, {:description=>"Printers / Scanners & Supplies", :category_type=>0, :category_id=>33, :store_id=>1, :node_id=>6664}, {:description=>"Projectors", :category_type=>0, :category_id=>343, :store_id=>1, :node_id=>6686}, {:description=>"Servers & Workstations", :category_type=>0, :category_id=>271, :store_id=>1, :node_id=>6684}, {:description=>"SSDs", :category_type=>0, :category_id=>119, :store_id=>1, :node_id=>11692}, {:description=>"Video Cards & Video Devices", :category_type=>0, :category_id=>38, :store_id=>1, :node_id=>6662}]}
|
25
|
+
Newegg.stores.first.to_h.should eq(response)
|
26
|
+
end
|
27
|
+
|
28
|
+
end #end Newegg::Category
|
data/spec/newegg_spec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Newegg do
|
4
|
+
|
5
|
+
it %q{should return stores for Newegg.stores} do
|
6
|
+
Newegg.stores.should_not be_nil
|
7
|
+
end
|
8
|
+
|
9
|
+
it %q{should respond to methods properly} do
|
10
|
+
Newegg.respond_to?(:api).should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it %q{should not respond to non-existent methods} do
|
14
|
+
Newegg.respond_to?(:wrong).should be_false
|
15
|
+
end
|
16
|
+
|
17
|
+
it %q{should pass arguments through method_missing correctly} do
|
18
|
+
Newegg.send(:categories, 1).should be_true
|
19
|
+
end
|
20
|
+
end #end Newegg
|
data/spec/spec_helper.rb
ADDED
data/spec/store_spec.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Newegg::Store do
|
4
|
+
|
5
|
+
it %q{should return a Newegg::Category for Newegg::Store.new(title, store_department, store_id, show_see_all_deals)} do
|
6
|
+
title = "Computer Hardware"
|
7
|
+
store_department = "ComputerHardware"
|
8
|
+
store_id = 1
|
9
|
+
show_see_all_deals = true
|
10
|
+
|
11
|
+
store = Newegg::Store.new(title, store_department, store_id, show_see_all_deals)
|
12
|
+
|
13
|
+
store.title.should eq("Computer Hardware")
|
14
|
+
store.store_department.should eq("ComputerHardware")
|
15
|
+
store.store_id.should eq(1)
|
16
|
+
store.show_see_all_deals.should eq(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it %q{should return store information when .to_h is called on a Newegg::Store} do
|
20
|
+
response = {:description=>"Backup Devices & Media", :category_type=>0, :category_id=>2, :store_id=>1, :node_id=>6642}
|
21
|
+
store = Newegg.stores.first
|
22
|
+
Newegg.categories(store.store_id).count.should eq(23)
|
23
|
+
Newegg.categories(store.store_id).first.to_h.should eq(response)
|
24
|
+
end
|
25
|
+
|
26
|
+
it %q{should return Newegg::Categories when .get_categories is called on a Newegg::Store} do
|
27
|
+
categories = Newegg.stores.first.get_categories
|
28
|
+
categories.should_not be_nil
|
29
|
+
categories.count.should eq(23)
|
30
|
+
end
|
31
|
+
end #end Newegg::Store
|
metadata
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: newegg-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Magnacca
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :runtime
|
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: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.8'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.8'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: simplecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: fakeweb
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.11'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.11'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 10.0.4
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 10.0.4
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: coveralls
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.6'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.6'
|
111
|
+
description: this gem allows the usage of the newegg.com api to ascertain product
|
112
|
+
information.
|
113
|
+
email:
|
114
|
+
- '''chrismagnacca@gmail.com'''
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- Gemfile
|
120
|
+
- Gemfile.lock
|
121
|
+
- LICENSE
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- lib/newegg.rb
|
125
|
+
- lib/newegg/api.rb
|
126
|
+
- lib/newegg/category.rb
|
127
|
+
- lib/newegg/error.rb
|
128
|
+
- lib/newegg/explorer.rb
|
129
|
+
- lib/newegg/store.rb
|
130
|
+
- lib/newegg/version.rb
|
131
|
+
- newegg-api.gemspec
|
132
|
+
- spec/api_spec.rb
|
133
|
+
- spec/category_spec.rb
|
134
|
+
- spec/newegg_spec.rb
|
135
|
+
- spec/spec_helper.rb
|
136
|
+
- spec/store_spec.rb
|
137
|
+
homepage: http://github.com/chrismagnacca/newegg-api
|
138
|
+
licenses: []
|
139
|
+
metadata: {}
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
requirements: []
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 2.2.2
|
157
|
+
signing_key:
|
158
|
+
specification_version: 4
|
159
|
+
summary: newegg's json api
|
160
|
+
test_files:
|
161
|
+
- spec/api_spec.rb
|
162
|
+
- spec/category_spec.rb
|
163
|
+
- spec/newegg_spec.rb
|
164
|
+
- spec/spec_helper.rb
|
165
|
+
- spec/store_spec.rb
|