indix 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c30a8ec0c8134ae18fe904a480b1ff2d33dcbc9a
4
+ data.tar.gz: 844fb6b2e8a2c29fbb82ca40971c239f8f6a060a
5
+ SHA512:
6
+ metadata.gz: 6d2f71b18a055c4f60d2d34bbfc44752d332b91beef580288e1beac3fca347dfadaa52b10acbca4bf4d918c969b6f244560bf94862532ee0267ed68194452bdb
7
+ data.tar.gz: 22bbb43dc66ec2fc96a9974c72869629e80ca237132079db5bb966dba7d4cf37a81a2c5a33d485c3333df51aea2b25967b36549c61613599a3912fb840922173
@@ -0,0 +1,48 @@
1
+ # Indix
2
+
3
+ Offical Ruby Wrapper for Indix API
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'indix'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install indix
18
+
19
+ ## Usage
20
+
21
+ Require the Gem:
22
+
23
+ require 'indix'
24
+
25
+ Configure Indix client with the app_id and app_key provided to you
26
+
27
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
28
+
29
+ or
30
+
31
+ Indix::Config.app_id = '12345'
32
+ Indix::Config.app_key = '12345abcde'
33
+
34
+ Call the API endpoints
35
+
36
+ Indix::Stores.search('amazon')
37
+ Indix::Products.search(query: 'nike', store_id: 1234)
38
+
39
+ Use the response
40
+
41
+ products_response = Indix::Products.search(query: 'nike')
42
+ puts products_response.count
43
+ puts products_response.products[0].id
44
+ puts products_response.products[0].offers_count
45
+
46
+
47
+
48
+
@@ -0,0 +1,38 @@
1
+ require 'httpclient'
2
+ require 'cgi'
3
+ require 'json'
4
+ require 'hashie'
5
+
6
+ require 'indix/resource'
7
+ Dir[File.join(File.dirname(__FILE__), 'indix', '*.rb')].each { |lib| require lib }
8
+
9
+ class String
10
+
11
+ # borrowed from ActiveSupport
12
+ def underscore
13
+ word = self.dup
14
+ word.gsub!(/::/, '/')
15
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
16
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
17
+ word.tr!("-", "_")
18
+ word.downcase!
19
+ word
20
+ end
21
+ end
22
+
23
+ class Mash < ::Hashie::Mash
24
+
25
+ # rubify keys
26
+ def convert_key(key)
27
+ key.to_s.underscore
28
+ end
29
+
30
+ def count
31
+ if self['count']
32
+ self['count']
33
+ else
34
+ super
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,13 @@
1
+ module Indix
2
+ class Brands
3
+ extend Indix::Resource
4
+
5
+ # Get the brands matching the query text
6
+ #
7
+ # @param query [String]
8
+ # @return [Mash] an array containing each matching brand's Id and name
9
+ def self.search(query)
10
+ get('/brands', {:query => query})
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Indix
2
+ class Categories
3
+ extend Indix::Resource
4
+
5
+ # Get all categories
6
+ #
7
+ # @return [Mash] an array containing each category's Id, name, Id path and name path
8
+ def self.all
9
+ get('/categories')
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,55 @@
1
+ module Indix
2
+
3
+ #Thrown when app_id or app_key missing
4
+ ConfigurationError = Class.new StandardError
5
+
6
+ #Thrown when the arguments passed do not confirm to pre-conditions
7
+ ArgumentError = Class.new StandardError
8
+
9
+ #Thrown when the API has received too many requests from this client in a given amount of time
10
+ LimitExceededError = Class.new StandardError
11
+
12
+ #Thrown when app_id or app_key passed are invalid
13
+ AuthenticationError = Class.new StandardError
14
+
15
+ #Thrown when the app_id/app_key is not authorized to access a resource
16
+ UnauthorizedAccessError = Class.new StandardError
17
+
18
+ module Config
19
+
20
+ module_function
21
+
22
+ # Sets the app_id
23
+ def app_id=(app_id)
24
+ @app_id = app_id
25
+ end
26
+
27
+ # Sets the app_key
28
+ def app_key=(app_key)
29
+ @app_key = app_key
30
+ end
31
+
32
+ def app_id
33
+ if @app_id
34
+ @app_id
35
+ else
36
+ raise ConfigurationError.new "Cannot complete request. Please provide app_id first"
37
+ end
38
+ end
39
+
40
+ def app_key
41
+ if @app_key
42
+ @app_key
43
+ else
44
+ raise ConfigurationError.new "Cannot complete request. Please provide app_key first"
45
+ end
46
+ end
47
+
48
+ # Set app_id and app_key
49
+ def setup(options={})
50
+ options.map do |k,v|
51
+ send("#{k}=", v)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,15 @@
1
+ module Indix
2
+ class Offers
3
+ extend Indix::Resource
4
+
5
+ # Get the offers for a product at a store
6
+ #
7
+ # @param product_id [String]
8
+ # @param store_id [Fixnum]
9
+ # @return [Mash] an object containing the count and offers array
10
+ def self.find(product_id, store_id)
11
+ request_params = {:storeId => store_id}
12
+ get("/products/#{product_id}/offers", request_params)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Indix
2
+ class Prices
3
+ extend Indix::Resource
4
+
5
+ # Get the prices for a product at a store
6
+ #
7
+ # @param product_id [String]
8
+ # @param store_id [Fixnum]
9
+ # @return [Mash] an object containing a few product details like the store, brand etc and an array of prices and recorded time
10
+ def self.find(product_id, store_id)
11
+ request_params = {:storeId => store_id}
12
+ get("/products/#{product_id}/prices", request_params)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,65 @@
1
+ module Indix
2
+ class Products
3
+ extend Indix::Resource
4
+
5
+ # Get the products that match the search criteria
6
+ #
7
+ # @param query [String]
8
+ # @param upc [String]
9
+ # @param mpn [String]
10
+ # @param sku [String]
11
+ # @param url [String] product URL
12
+ # @param stores [String] (Comma seperated list of store Ids)
13
+ # @param brands [String](Comma seperated list of brand Ids)
14
+ # @param category_id [Fixnum]
15
+ # @param start_price [BigDecimal]
16
+ # @param end_price [BigDecimal]
17
+ # @param availability [String] Possible values: 'IN_STOCK', 'OUT_OF_STOCK'
18
+ # @param price_history_available [Boolean]
19
+ # @param offers_count [Fixnum] Minimum number of offers the matched product should have
20
+ # @param price_change [String] Possible values: 'PRICE_INCREASED', 'PRICE_DECREASED'
21
+ # @param sort_by [String] Possible values: 'PRICE_LOW_TO_HIGH', 'PRICE_HIGH_TO_LOW', 'MOST_RECENT'
22
+ # @param page_number [Fixnum]
23
+
24
+ # @return [Mash] an object containing the count, products array and page_number
25
+ def self.search(query: nil, upc: nil, mpn: nil, sku: nil, url: nil, stores: nil, brands: nil, category_id: nil,
26
+ start_price: nil, end_price: nil, availability: nil, price_history_available: nil, offers_count: nil, price_change: nil, sort_by: nil, page_number: 1)
27
+ request_params = {}
28
+ request_params[:query] = query unless query.nil?
29
+ request_params[:upc] = upc unless upc.nil?
30
+ request_params[:mpn] = mpn unless mpn.nil?
31
+ request_params[:sku] = sku unless sku.nil?
32
+ request_params[:url] = url unless url.nil?
33
+ request_params[:storeId] = stores unless stores.nil?
34
+ request_params[:brandId] = brands unless brands.nil?
35
+ request_params[:categoryId] = category_id unless category_id.nil?
36
+
37
+ raise Indix::ArgumentError.new('Atleast one required parameter should be passed') if request_params.empty?
38
+
39
+ request_params[:startPrice] = start_price unless start_price.nil?
40
+ request_params[:endPrice] = end_price unless end_price.nil?
41
+ request_params[:availability] = availability unless availability.nil?
42
+ request_params[:priceHistoryAvailable] = price_history_available unless price_history_available.nil?
43
+ request_params[:offersCount] = offers_count unless offers_count.nil?
44
+ request_params[:priceChange] = price_change unless price_change.nil?
45
+ request_params[:sortBy] = sort_by unless sort_by.nil?
46
+ request_params[:pageNumber] = page_number
47
+
48
+ get("/products", request_params)
49
+ end
50
+
51
+ # Get the details of a product
52
+ #
53
+ # @param product_id [String]
54
+ # @param view [Fixnum] (Optional) Possible values: 'offers', 'offers_catalog' and 'catalog'
55
+ # @params page_number [Fixnum] Use to paginate through the offers array
56
+ #
57
+ # @return [Mash] an object containing the product details like the store, brand etc and an array of offers (presence depends on the view type) and page_number
58
+ def self.find(id, view: nil, page_number: 1)
59
+ request_params = {}
60
+ request_params[:view] = view unless view.nil?
61
+ request_params[:pageNumber] = page_number
62
+ get("/products/#{id}", request_params)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,64 @@
1
+ require 'httpclient'
2
+ require 'json'
3
+ require 'cgi'
4
+
5
+ module Indix
6
+ module Resource
7
+
8
+ def base_uri
9
+ @base_uri ||= 'https://api.indix.com/v1'
10
+ end
11
+
12
+ def client
13
+ @client ||= HTTPClient.new
14
+ end
15
+
16
+ def get(path, params = {})
17
+ params[:app_id] = Indix::Config.app_id
18
+ params[:app_key] = Indix::Config.app_key
19
+
20
+ # no need to escape params as httpclient does it anyways
21
+ target = base_uri + path
22
+ client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
23
+ response = client.get(target, :query => params)
24
+ if response.status == 200
25
+ content = JSON.parse(response.content)
26
+ data = content["response"]
27
+ data = to_hashie(data)
28
+ elsif response.status == 401
29
+ raise AuthenticationError.new('Cannot complete request. Authentication failed. Please provide a valid app_id and app_key')
30
+ elsif response.status == 402
31
+ raise UnauthorizedAccessError.new('Cannot complete request. Not authorized to access this resource')
32
+ elsif response.status == 429
33
+ raise LimitExceededError.new('Too many requests')
34
+ else
35
+ raise StandardError.new('Cannot complete request. Response Code: ' + response.status.to_s + ' Response Body: ' + response.content)
36
+ end
37
+
38
+ end
39
+
40
+ private
41
+
42
+ def to_hashie(json)
43
+ if json.is_a? Array
44
+ json.collect! { |x| x.is_a?(Hash) ? Mash.new(x) : x }
45
+ else
46
+ Mash.new(json)
47
+ end
48
+ end
49
+
50
+ def can_escape(value)
51
+ case value
52
+ when Fixnum
53
+ return false
54
+ when TrueClass
55
+ return false
56
+ when FalseClass
57
+ return false
58
+ end
59
+ true
60
+ end
61
+ end
62
+ end
63
+
64
+
@@ -0,0 +1,13 @@
1
+ module Indix
2
+ class Stores
3
+ extend Indix::Resource
4
+
5
+ # Get the stores matching the query text
6
+ #
7
+ # @param query [String]
8
+ # @return [Mash] an array containing each matching store's Id and name
9
+ def self.search(query)
10
+ get('/stores', {:query => query})
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Indix
2
+ VERSION = "1.0"
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Brands do
4
+
5
+ describe "Brands Search API" do
6
+ it "must succeed when valid parameters are passed" do
7
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/brands', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :query => 'wal'}}).returns(mock_response('brands'))
8
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
9
+ brands = Indix::Brands.search('wal')
10
+ brands.length.must_equal 10
11
+ brands[0].id.must_equal "6715"
12
+ brands[0].name.must_equal "Walgreens"
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Categories do
4
+
5
+ describe "Categories export API" do
6
+ it "must succeed when valid parameters are passed" do
7
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/categories', {:query => {:app_id=>'12345', :app_key=>'12345abcde'}}).returns(mock_response('categories'))
8
+
9
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
10
+ categories = Indix::Categories.all
11
+ categories.length.must_equal 9
12
+ categories[0].id.must_equal 10001
13
+ categories[0].name.must_equal "Apparel"
14
+ categories[6].id.must_equal 10019
15
+ categories[6].name.must_equal "Home Care"
16
+ categories[6].name_path.must_equal "Grocery, Health & Personal Care > Home Care"
17
+ categories[6].id_path.must_equal "10018 > 10019"
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Config do
4
+
5
+ describe "Request to Indix API" do
6
+ it "must fail when no app_id or app_key is configured" do
7
+ Indix::Config.app_id = nil
8
+ Indix::Config.app_key = nil
9
+ lambda {Indix::Brands.search('wal')}.must_raise Indix::ConfigurationError
10
+ end
11
+ end
12
+
13
+ describe "Indix API configuration" do
14
+ it "must be properly setup" do
15
+ Indix::Config.setup({:app_id => 'abc12345', :app_key => 'abcd1234567890'})
16
+ Indix::Config.app_id.must_equal 'abc12345'
17
+ Indix::Config.app_key.must_equal 'abcd1234567890'
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Offers do
4
+ describe "Store Offers API" do
5
+ it "must return proper response when a valid product_id and store_id are passed" do
6
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products/01aec3dc861c642805cb4be5784e2521/offers', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :storeId => 57}}).returns(mock_response('offers'))
7
+
8
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
9
+ store_offer_response = Indix::Offers.find('01aec3dc861c642805cb4be5784e2521', 57)
10
+ store_offer_response.count.must_equal 1
11
+ store_offer_response.offers.count.must_equal 1
12
+ store_offer_response.offers[0].id.must_equal '01aec3dc861c642805cb4be5784e2521'
13
+ store_offer_response.offers[0].title.must_equal 'Nike Revolution 2 Wolf Grey/Cool Grey/Volt/Black'
14
+ store_offer_response.offers[0].store_id.must_equal 57
15
+ store_offer_response.offers[0].store_name.must_equal 'Zappos.com'
16
+ store_offer_response.offers[0].brand_id.must_equal 5572
17
+ store_offer_response.offers[0].brand_name.must_equal 'Nike'
18
+ store_offer_response.offers[0].product_url.must_equal 'http://www.zappos.com/nike-revolution-2-dark-grey-cool-grey-total-crimson-hyper-blue'
19
+ store_offer_response.offers[0].image_url.must_equal 'http://www.zappos.com/images/z/2/0/8/4/1/6/2084160-p-DETAILED.jpg'
20
+ store_offer_response.offers[0].category_id_path.must_equal '10003 > 11200 > 11211'
21
+ store_offer_response.offers[0].category_name_path.must_equal 'Shoes & Accessories > Shoes > Men\'s Shoes'
22
+ store_offer_response.offers[0].upc.must_equal 'NA'
23
+ store_offer_response.offers[0].sku.must_equal '8064765'
24
+ store_offer_response.offers[0].mpn.must_equal 'NA'
25
+ store_offer_response.offers[0].price.list_price.must_equal 55
26
+ store_offer_response.offers[0].price.sale_price.must_equal 55
27
+ store_offer_response.offers[0].cart_price.must_equal false
28
+ store_offer_response.offers[0].last_recorded_at.must_equal 1399287717330
29
+ store_offer_response.offers[0].price_history_available.must_equal true
30
+ store_offer_response.offers[0].availability.must_equal 'In Stock'
31
+ store_offer_response.offers[0].buy_box_winner.must_equal false
32
+ store_offer_response.offers[0].add_on_item.must_equal false
33
+ store_offer_response.offers[0].new_offers.must_equal 0
34
+ store_offer_response.offers[0].used_offers.must_equal 0
35
+ store_offer_response.offers[0].refurbished_offers.must_equal 0
36
+ store_offer_response.offers[0].user_ratings.must_equal 0
37
+ store_offer_response.offers[0].average_rating.must_equal 0
38
+ store_offer_response.offers[0].max_rating.must_equal 0
39
+ store_offer_response.offers[0].sales_rank.must_equal 0
40
+ store_offer_response.offers[0].tags.count.must_equal 15
41
+ store_offer_response.offers[0].tags[0].must_equal 'nike'
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Prices do
4
+ describe "Price History API" do
5
+ it "must return proper response when a valid product_id and store_id are passed" do
6
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products/01aec3dc861c642805cb4be5784e2521/prices', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :storeId => 57}}).returns(mock_response('prices'))
7
+
8
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
9
+ price_history_response = Indix::Prices.find('01aec3dc861c642805cb4be5784e2521', 57)
10
+ price_history_response.id.must_equal '01aec3dc861c642805cb4be5784e2521'
11
+ price_history_response.store_id.must_equal 57
12
+ price_history_response.brand_id.must_equal 5572
13
+ price_history_response.category_id.must_equal 11211
14
+ price_history_response.price_history.count.must_equal 8
15
+ price_history_response.price_history[0].sale_price.must_equal 55
16
+ price_history_response.price_history[0].list_price.must_equal 55
17
+ price_history_response.price_history[0].recorded_at.must_equal 1398729599999
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Products do
4
+
5
+ describe "Products Search API" do
6
+ it "must fail when no required parameters are passed" do
7
+ lambda {Indix::Products.search()}.must_raise Indix::ArgumentError
8
+ end
9
+
10
+ it "must return proper response when a valid query is passed" do
11
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :query => 'nike', :pageNumber => 1}}).returns(mock_response('products'))
12
+
13
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
14
+ products_response = Indix::Products.search(query: 'nike')
15
+ products_response.count.must_equal 2010
16
+ products_response.products.length.must_equal 10
17
+ products_response.products[0].id.must_equal '01aec3dc861c642805cb4be5784e2521'
18
+ products_response.products[0].title.must_equal 'Nike Revolution 2 Wolf Grey/Cool Grey/Volt/Black'
19
+ products_response.products[0].brand_id.must_equal 5572
20
+ products_response.products[0].brand_name.must_equal 'Nike'
21
+ products_response.products[0].image_url.must_equal 'http://www.zappos.com/images/z/2/0/8/4/1/6/2084160-p-DETAILED.jpg'
22
+ products_response.products[0].category_id_path.must_equal '10003 > 11200 > 11211'
23
+ products_response.products[0].category_name_path.must_equal 'Shoes & Accessories > Shoes > Men\'s Shoes'
24
+ products_response.products[0].upc.must_equal 'NA'
25
+ products_response.products[0].mpn.must_equal 'NA'
26
+ products_response.products[0].store_count.must_equal 1
27
+ products_response.products[0].offers_count.must_equal 1
28
+ products_response.products[0].offers_price_range.must_equal '55.0-55.0'
29
+ end
30
+
31
+ it "must return proper response when a valid upc is passed" do
32
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :upc => 81732301143, :pageNumber => 1}}).returns(mock_response('products'))
33
+
34
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
35
+ products_response = Indix::Products.search(upc: 81732301143)
36
+ products_response.count.must_equal 2010
37
+ products_response.products.length.must_equal 10
38
+ end
39
+
40
+ it "must return proper response when a valid sku is passed" do
41
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :sku => 486053, :pageNumber => 1}}).returns(mock_response('products'))
42
+
43
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
44
+ products_response = Indix::Products.search(sku: 486053)
45
+ products_response.count.must_equal 2010
46
+ products_response.products.length.must_equal 10
47
+ end
48
+
49
+ it "must return proper response when a valid mpn is passed" do
50
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :mpn => '5217TZG', :pageNumber => 1}}).returns(mock_response('products'))
51
+
52
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
53
+ products_response = Indix::Products.search(mpn: '5217TZG')
54
+ products_response.count.must_equal 2010
55
+ products_response.products.length.must_equal 10
56
+ end
57
+
58
+ it "must return proper response when valid store_id, brand_id and category_id are passed" do
59
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :storeId => 123, :brandId => 234, :categoryId => 345, :pageNumber => 1}}).returns(mock_response('products'))
60
+
61
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
62
+ products_response = Indix::Products.search(stores: 123, brands: 234, category_id: 345)
63
+ products_response.count.must_equal 2010
64
+ products_response.products.length.must_equal 10
65
+ end
66
+
67
+ it "must return proper response when valid store_id, price_change, price_history_available and availability are passed" do
68
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :storeId => 123, :priceChange => 'PRICE_DECREASED', :availability => 'IN_STOCK', :priceHistoryAvailable => true, :pageNumber => 1}}).returns(mock_response('products'))
69
+
70
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
71
+ products_response = Indix::Products.search(stores: 123, price_change: 'PRICE_DECREASED', availability: 'IN_STOCK', price_history_available: true)
72
+ products_response.count.must_equal 2010
73
+ products_response.products.length.must_equal 10
74
+ end
75
+
76
+ it "must return proper response when valid query, start_price, end_rice, sort_by and page_number are passed" do
77
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :query => 'nike', :startPrice => 100, :endPrice => 200, :sortBy => 'PRICE_LOW_TO_HIGH', :pageNumber => 2}}).returns(mock_response('products'))
78
+
79
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
80
+ products_response = Indix::Products.search(query: 'nike', start_price: 100, end_price: 200, sort_by: 'PRICE_LOW_TO_HIGH', page_number: 2)
81
+ products_response.count.must_equal 2010
82
+ products_response.products.length.must_equal 10
83
+ end
84
+
85
+ it "must return proper response when valid url and offers_count are passed" do
86
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :url => 'www.google.com', :offersCount => 5, :pageNumber => 1}}).returns(mock_response('products'))
87
+
88
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
89
+ products_response = Indix::Products.search(url: 'www.google.com', offers_count: 5)
90
+ products_response.count.must_equal 2010
91
+ products_response.products.length.must_equal 10
92
+ end
93
+ end
94
+
95
+ describe "Products Details API" do
96
+ it "must return proper response when a valid product_id is passed" do
97
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products/12345', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :pageNumber => 1}}).returns(mock_response('product'))
98
+
99
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
100
+ product = Indix::Products.find(12345)
101
+ product.id.must_equal '01aec3dc861c642805cb4be5784e2521'
102
+ product.title.must_equal 'Nike Revolution 2 Wolf Grey/Cool Grey/Volt/Black'
103
+ product.brand_id.must_equal 5572
104
+ product.brand_name.must_equal 'Nike'
105
+ product.image_url.must_equal 'http://www.zappos.com/images/z/2/0/8/4/1/6/2084160-p-DETAILED.jpg'
106
+ product.category_id_path.must_equal '10003 > 11200 > 11211'
107
+ product.category_name_path.must_equal 'Shoes & Accessories > Shoes > Men\'s Shoes'
108
+ product.upc.must_equal 'NA'
109
+ product.offers_count.must_equal 1
110
+ product.offers.count.must_equal 1
111
+ product.offers[0].id.must_equal '01aec3dc861c642805cb4be5784e2521'
112
+ product.offers[0].title.must_equal 'Nike Revolution 2 Wolf Grey/Cool Grey/Volt/Black'
113
+ product.offers[0].store_id.must_equal 57
114
+ product.offers[0].store_name.must_equal 'Zappos.com'
115
+ product.offers[0].product_url.must_equal 'http://www.zappos.com/nike-revolution-2-dark-grey-cool-grey-total-crimson-hyper-blue'
116
+ product.offers[0].image_url.must_equal 'http://www.zappos.com/images/z/2/0/8/4/1/6/2084160-p-DETAILED.jpg'
117
+ product.offers[0].sku.must_equal '8064765'
118
+ product.offers[0].mpn.must_equal 'NA'
119
+ product.offers[0].last_recorded_at.must_equal 1399287717330
120
+ product.offers[0].tags.count.must_equal 15
121
+ product.offers[0].tags[0].must_equal 'nike'
122
+ product.offers[0].price.list_price.must_equal 55
123
+ product.offers[0].price.sale_price.must_equal 55
124
+ product.offers[0].cart_price.must_equal false
125
+ product.offers[0].price_history_available.must_equal true
126
+ product.offers[0].availability.must_equal 'In Stock'
127
+ product.offers[0].buy_box_winner.must_equal false
128
+ product.offers[0].add_on_item.must_equal false
129
+ product.offers[0].new_offers.must_equal 0
130
+ product.offers[0].used_offers.must_equal 0
131
+ product.offers[0].refurbished_offers.must_equal 0
132
+ product.offers[0].user_ratings.must_equal 0
133
+ product.offers[0].average_rating.must_equal 0
134
+ product.offers[0].max_rating.must_equal 0
135
+ product.offers[0].sales_rank.must_equal 0
136
+ product.offers[0].attributes.count.must_equal 8
137
+ product.offers[0].attributes.keys[0].must_equal 'liningmaterial'
138
+ product.offers[0].attributes[:liningmaterial].must_equal 'Fabric'
139
+ end
140
+
141
+ it "must return proper response when a valid product_id, view and page_number are passed" do
142
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/products/12345', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :view => 'offers', :pageNumber => 2}}).returns(mock_response('product'))
143
+
144
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
145
+ product = Indix::Products.find(12345, view: 'offers', page_number: 2)
146
+ product.id.must_equal '01aec3dc861c642805cb4be5784e2521'
147
+ end
148
+ end
149
+
150
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Resource do
4
+
5
+ before do
6
+ @object = Object.new
7
+ @object.extend(Indix::Resource)
8
+ end
9
+
10
+ it "must throw AuthenticationError when the API returns 401" do
11
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/categories', {:query => {:app_id=>'12345', :app_key=>'12345abcde'}}).returns(mock_authentication_error_response())
12
+
13
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
14
+ lambda {Indix::Categories.all}.must_raise Indix::AuthenticationError
15
+ end
16
+
17
+ it "must throw LimitExceededError when the API returns 429" do
18
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/categories', {:query => {:app_id=>'12345', :app_key=>'12345abcde'}}).returns(mock_limit_exceeded_response())
19
+
20
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
21
+ lambda {Indix::Categories.all}.must_raise Indix::LimitExceededError
22
+ end
23
+
24
+ it "must throw UnauthorizedAccessError when the API returns 402" do
25
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/categories', {:query => {:app_id=>'12345', :app_key=>'12345abcde'}}).returns(mock_unauthorized_response())
26
+
27
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
28
+ lambda {Indix::Categories.all}.must_raise Indix::UnauthorizedAccessError
29
+ end
30
+
31
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Indix::Stores do
4
+
5
+ describe "Stores Search API" do
6
+ it "must succeed when valid parameters are passed" do
7
+ HTTPClient.any_instance.stubs(:get).with('https://api.indix.com/v1/stores', {:query => {:app_id=>'12345', :app_key=>'12345abcde', :query => 'wal'}}).returns(mock_response('stores'))
8
+
9
+ Indix::Config.setup({:app_id => '12345', :app_key => '12345abcde'})
10
+ stores = Indix::Stores.search('wal')
11
+ stores.length.must_equal 5
12
+ stores[2].id.must_equal "95"
13
+ stores[2].name.must_equal "Walgreens"
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,32 @@
1
+ require 'indix'
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
4
+ require 'httpclient'
5
+ require 'mocha/mini_test'
6
+
7
+ def fixture_path
8
+ @path ||= File.expand_path('../fixtures', __FILE__)
9
+ end
10
+
11
+ def mock_response(request_type)
12
+ content = File.read(File.open(fixture_path + '/' + request_type + '.json'))
13
+ http_message = HTTP::Message.new_response(content)
14
+ end
15
+
16
+ def mock_authentication_error_response
17
+ http_message = HTTP::Message.new_response('{"status":401,"message":"Authentication error"')
18
+ http_message.status = 401
19
+ http_message
20
+ end
21
+
22
+ def mock_limit_exceeded_response
23
+ http_message = HTTP::Message.new_response('{"status":429,"message":"Too many requests"')
24
+ http_message.status = 429
25
+ http_message
26
+ end
27
+
28
+ def mock_unauthorized_response
29
+ http_message = HTTP::Message.new_response('{"status":402,"message":"Unauthorized"')
30
+ http_message.status = 402
31
+ http_message
32
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: indix
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - indix
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-28 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.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
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: httpclient
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.4.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 2.3.4.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: hashie
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 2.0.5
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 2.0.5
83
+ description: Official Ruby wrapper for Indix API
84
+ email:
85
+ - support@indix.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - README.md
91
+ - lib/indix.rb
92
+ - lib/indix/brands.rb
93
+ - lib/indix/prices.rb
94
+ - lib/indix/version.rb
95
+ - lib/indix/config.rb
96
+ - lib/indix/offers.rb
97
+ - lib/indix/categories.rb
98
+ - lib/indix/products.rb
99
+ - lib/indix/resource.rb
100
+ - lib/indix/stores.rb
101
+ - spec/lib/indix/categories_spec.rb
102
+ - spec/lib/indix/prices_spec.rb
103
+ - spec/lib/indix/config_spec.rb
104
+ - spec/lib/indix/stores_spec.rb
105
+ - spec/lib/indix/products_spec.rb
106
+ - spec/lib/indix/offers_spec.rb
107
+ - spec/lib/indix/resource_spec.rb
108
+ - spec/lib/indix/brands_spec.rb
109
+ - spec/spec_helper.rb
110
+ homepage: http://www.indix.com
111
+ licenses: []
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.1.9
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Official Ruby wrapper for Indix API
133
+ test_files:
134
+ - spec/lib/indix/categories_spec.rb
135
+ - spec/lib/indix/prices_spec.rb
136
+ - spec/lib/indix/config_spec.rb
137
+ - spec/lib/indix/stores_spec.rb
138
+ - spec/lib/indix/products_spec.rb
139
+ - spec/lib/indix/offers_spec.rb
140
+ - spec/lib/indix/resource_spec.rb
141
+ - spec/lib/indix/brands_spec.rb
142
+ - spec/spec_helper.rb
143
+ has_rdoc: