indix 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.
@@ -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: