diff --git a/README.md b/README.md index cc73b74..f64459b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Shopsense-Ruby - Ruby interface for the ShopStyle API +# Shopsense-Ruby - Ruby interface for the POPSUGAR Shopping API -The ShopStyle API, ShopSense! For Ruby! So Great. +The POPSUGAR Shopping API, ShopSense! For Ruby! So Great. ### Description @@ -10,11 +10,14 @@ Shopsense-Ruby includes a set of convent classes and methods designed to make accessing the [ShopStyle API](https://shopsense.shopstyle.com/page/ShopSenseHome) from your Ruby application seamless. -## Installation +## Usage -Install the Ruby Gem: +Install with Bundler - $ gem install shopsense-ruby +Add the folowing to your Gemfile +``` +gem "shopsense-ruby" +``` Include it in you Ruby application: @@ -32,4 +35,4 @@ Please report any bugs found in Shopsense-Ruby [here](https://github.com/RudyCom This gem looks to serve not only as a means of elegantly access the [ShopStyle API](https://shopsense.shopstyle.com/page/ShopSenseHome) -but a means of offering a host of shopping oriented programing features! \ No newline at end of file +but a means of offering a host of shopping oriented programing features! diff --git a/Rakefile b/Rakefile index 462dd40..1fa2c0f 100644 --- a/Rakefile +++ b/Rakefile @@ -31,4 +31,4 @@ task :gh_pages do `git push origin gh-pages` end end -=end \ No newline at end of file +=end diff --git a/lib/shopsense.rb b/lib/shopsense.rb index fecc43a..4b45887 100644 --- a/lib/shopsense.rb +++ b/lib/shopsense.rb @@ -1,14 +1,14 @@ require 'net/http' -require 'yajl' +require 'cgi' =begin rdoc Shopsense is an easy to use Ruby interface for the {Shopstyle API}[https://shopsense.shopstyle.com/page/ShopSenseHome], -also known a ShopSense. The ShopStyle API is a free service from ShopStyle that pays you for sending traffic +also known a ShopSense. The ShopStyle API is a free service from ShopStyle that pays you for sending traffic to online retailers from your blog, website, or application. -The ShopStyle API allows client applications to retrieve the underlying data for all the basic elements of the -ShopStyle websites, including products, brands, retailers, categories, and looks. For ease of development, -the API is a REST-style web service, composed of simple HTTP GET requests. Data is returned to the client in -either XML or JSON formats. The API is client-language independent and easy to use from PHP, Java, JavaScript, +The ShopStyle API allows client applications to retrieve the underlying data for all the basic elements of the +ShopStyle websites, including products, brands, retailers, categories, and looks. For ease of development, +the API is a REST-style web service, composed of simple HTTP GET requests. Data is returned to the client in +either XML or JSON formats. The API is client-language independent and easy to use from PHP, Java, JavaScript, or any other modern development context. Shopsense provides a number of helpful classes and methods for integrating data aquired from the ShopStyle API into @@ -20,5 +20,4 @@ see Shopsense::API =end -require 'shopsense/client' require 'shopsense/api' diff --git a/lib/shopsense/api.rb b/lib/shopsense/api.rb index db54fc4..1655936 100644 --- a/lib/shopsense/api.rb +++ b/lib/shopsense/api.rb @@ -1,6 +1,37 @@ module Shopsense - class API < Client + API_ENDPOINTS = {1 => 'http://api.shopstyle.com/action', 2 => 'http://api.shopstyle.com/api/v2'} + FILTER_TYPES = ['Category', 'Brand', 'Retailer', 'Price', 'Discount', 'Size', 'Color'].freeze + LOOK_TYPES = ['New', 'TopRated', 'Celebrities', 'Featured'].freeze + + class HTTP < Net::HTTP + def socket_closed? + @socket && @socket.closed? + end + end + + def self.configuration + @configuration ||= {} + end + + # Shopsense.configuration = YAML.load_file('config/shopsense.yml') + def self.configuration=(conf) + @configuration = conf + end + + def self.api + @api ||= Shopsense::API.new(Shopsense.configuration) + end + + class API + + def initialize(args = {}) + @partner_id = args['partner_id'] + @unserialize = args['unserialize'].nil? ? true : args['unserialize'] + @http_keep_alive = args['http_keep_alive'].nil? ? true : args['http_keep_alive'] + @site = args['site'] || 'www.shopstyle.com' + @http_session = {} + end # Searches the shopsense API # @param [String] search_string @@ -9,84 +40,73 @@ class API < Client # The start index of results returned. # @param [Integer] num_results # The number of results to be returned. - # @return A list of Product objects. Each Product has an id, name, - # description, price, retailer, brand name, categories, images in small/medium/large, + # @return A list of Product objects. Each Product has an id, name, + # description, price, retailer, brand name, categories, images in small/medium/large, # and a URL that forwards to the retailer's site. - def search( search_string = nil, index = 0, num_results = 10) - raise "no search string provieded!" if( search_string === nil) - - fts = "fts=" + search_string.split().join( '+').to_s - min = "min=" + index.to_s - count = "count=" + num_results.to_s - args = [fts, min, count].join( '&') - - return call_api( __method__, args) + def products(opts = {}) + raise "Interface changed. Use as :query => 'search'" if opts.kind_of? String + call_api('/products', build_product_query(opts)) end + def product_by_id(product_id) + call_api('/products/' + CGI::escape(product_id.to_s)) + end - # This method returns a list of categories and product counts that describe the results + # This method returns a list of categories and product counts that describe the results # of a given product query. The query is specified using the product query parameters. # @param [String] search_string The string to be in the query. - # @return [String] A list of Category objects. Each Category has an id, name, and count + # @return [String] A list of Category objects. Each Category has an id, name, and count # of the number of query results in that category. - def get_category_histogram( search_string = nil) - raise "no search string provieded!" if( search_string === nil) - - fts = "fts=" + search_string.split().join( '+').to_s - - return call_api( __method__, fts) + def category_histogram(opts) + filter_histogram('Category', opts) end - # This method returns a list of categories and product counts that describe the results + # This method returns a list of categories and product counts that describe the results # of a given product query. The query is specified using the product query parameters. # @param [String] filter_type - # The type of filter data to return. Possible values are + # The type of filter data to return. Possible values are # Brand, Retailer, Price, Discount, Size and Color. # @param [String] search_string The string to be in the query. - # @return [String] A list of Category objects. Each Category has an id, name, and count - # of the number of query results in that category. - def get_filter_histogram( filter_type = nil, search_string = nil) - raise "no search string provieded!" if( search_string === nil) - raise "invalid filter type" if( !self.filter_types.include?( filter_type)) - - filterType = "filterType=" + filter_type.to_s - fts = "fts=" + search_string.split().join( '+').to_s - args = [filterType, fts].join( '&') - - return call_api( __method__, args) + # @return [String] A list of Filter objects of the given type. Each Filter has an id, + # name, and count of the number of results that apply to that filter. + def filter_histogram(filter_type, opts = {}) + raise "Interface changed. Use as :query => 'search'" if opts.kind_of? String + filter_types = [*filter_type] + filter_types.each do |f| + raise "invalid filter type" unless FILTER_TYPES.include?(f) + end + args = build_product_query(opts) + args[:filters] = filter_types.join(",") + args[:floor] = opts[:floor] + call_api('/products/histogram', args) end - # This method returns a list of brands that have live products. Brands that have - # very few products will be omitted. - # @return [String] A list of all Brands, with id, name, url, and synonyms of each. - def get_brands - return call_api( __method__) + # This method returns a list of the categories available to the API. + # @return A list of all categories, with id, name, and parent id. + def categories + call_api('/categories') end - # This method returns information about a particular look and its products. - # @param [Integer] look_id - # The ID number of the look. An easy way to get a look's ID is - # to go to the Stylebook page that contains the look at the ShopStyle website and - # right-click on the button that you use to edit the look. From the popup menu, select - # "Copy Link" and paste that into any text editor. The "lookId" query parameter of that - # URL is the value to use for this API method. - # @return [String] single look, with title, description, a set of tags, and a list of products. - # The products have the fields listed (see #search) - def get_look( look_id = nil) - raise "no look_id provieded!" if( look_id === nil) - - look = "look=" + look_id.to_s + # This method returns the list of canonical colors available. + # @return A list of all Colors, with id, name, and url of each. + def colors + call_api('/colors') + end - return call_api( __method__, look) + # This method returns a list of brands that have live products. Brands that have + # very few products will be omitted. + # @return A list of all Brands, with id, name, url, and synonyms of each. + def brands + call_api('/brands') end # This method returns a list of retailers that have live products. # @return [Sting] A list of all Retailers, with id, name, and url of each. - def get_retailers - return call_api( __method__) + def retailers + call_api('/retailers') end - # This method returns information about a particular user's Stylebook, the + # This method returns information about a particular user's Stylebook, the # looks within that Stylebook, and the title and description associated with each look. # @param [String] username # The username of the Stylebook owner. @@ -94,20 +114,34 @@ def get_retailers # The start index of results returned. # @param [Integer] num_results # The number of results to be returned. - # @return [String] - # A look id of the user's Stylebook, the look id of each individual look within that Stylebook, + # @return [String] + # A look id of the user's Stylebook, the look id of each individual look within that Stylebook, # and the title and description associated with each look. - def get_stylebook( user_name = nil, index = 0, num_results = 10) - raise "no user_name provieded!" if( user_name === nil) - - handle = "handle=" + user_name.to_s - min = "min=" + index.to_s - count = "count=" + num_results.to_s - args = [handle, min, count].join( '&') - - return call_api( __method__, args) + def stylebook(opts = {}) + opts = {:offset => 0, :limit => 10}.merge(opts) + args = { + :handle => opts[:username], + :min => opts[:offset], + :count => opts[:limit], + } + call_api('/apiGetStylebook', args, 1) end + # @deprecated + # This method returns information about a particular look and its products. + # @param [Integer] look_id + # The ID number of the look. An easy way to get a look's ID is + # to go to the Stylebook page that contains the look at the ShopStyle website and + # right-click on the button that you use to edit the look. From the popup menu, select + # "Copy Link" and paste that into any text editor. The "lookId" query parameter of that + # URL is the value to use for this API method. + # @return [String] single look, with title, description, a set of tags, and a list of products. + # The products have the fields listed (see #search) + def look(look_id) + call_api('/apiGetLook', {:look => look_id}, 1) + end + + # @deprecated # This method returns information about looks that match different kinds of searches. # @param [Integer] look_type # The type of search to perform. Supported values are: @@ -115,86 +149,143 @@ def get_stylebook( user_name = nil, index = 0, num_results = 10) # TopRated - Recently created looks that are highly rated. # Celebrities - Looks owned by celebrity users. # Featured - Looks from featured stylebooks. - # @param [String] username - # The username of the Stylebook owner. # @param [Integer] index # The start index of results returned. # @param [Integer] num_results # The number of results to be returned. - # @return [String] + # @return [String] # A list of looks of the given type. - def get_looks( look_type = nil, index = 0, num_results = 10) - raise "invalid filter type must be one of the following: #{self.look_types}" if( !self.look_types.include?( look_type)) - - type = "type=" + look_type.to_s - min = "min=" + index.to_s - count = "count=" + num_results.to_s - args = [type, min, count].join( '&') - - return call_api( __method__, args) + def looks(look_type, opts = {}) + opts = {:offset => 0, :limit => 10}.merge(opts) + args = { + :type => look_type, + :min => opts[:offset], + :count => opts[:limit], + } + call_api('/apiGetLooks', args, 1) end - # TODO: - # This method does not return a reponse of XML or JSON data like the other elements of the API. - # Instead, it forwards the user to the retailer's product page for a given product. It is the - # typical behavior to offer when the user clicks on a product. The apiSearch method returns URLs + # @deprecated + # This method provides a link that will redirect to the retailer product page. + # You probably won't need this as the link is also included with the product structs. + # + # This method does not return a reponse of XML or JSON data like the other elements of the API. + # Instead, it forwards the user to the retailer's product page for a given product. It is the + # typical behavior to offer when the user clicks on a product. The apiSearch method returns URLs # that call this method for each of the products it returns. # @param [Integer] - # The ID number of the product. An easy way to get a product's ID is to find the product somewhere - # in the ShopStyle UI and right-click on the product image. From the popup menu, select "Copy Link" - # ("Copy link location" or "Copy shortcut" depending on your browser) and paste that into any text + # The ID number of the product. An easy way to get a product's ID is to find the product somewhere + # in the ShopStyle UI and right-click on the product image. From the popup menu, select "Copy Link" + # ("Copy link location" or "Copy shortcut" depending on your browser) and paste that into any text # editor. The "id" query parameter of that URL is the value to use for this API method. # @return [String] # A web link to the retailer. $1 of the $0 - def visit_retailer( id) - + def visit_retailer_href(product_id) + API_ENDPOINTS[1] + "/apiVisitRetailer?pid=#{CGI::escape(@partner_id.to_s)}&id=#{CGI::escape(product_id.to_s)}" end - # This method returns the popular brands for a given category along with a sample product for the + # @deprecated + # This method returns the popular brands for a given category along with a sample product for the # brand-category combination. - # @param [String] category - # Category you want to restrict the popularity search for. This is an optional + # @param [String] category + # Category you want to restrict the popularity search for. This is an optional # parameter. If category is not supplied, all the popular brands regardless of category will be returned. - # @return [String] A list of trends in the given category. Each trend has a brand, category, url, and + # @return [String] A list of trends in the given category. Each trend has a brand, category, url, and # optionally the top-ranked product for each brand/category. - def get_trends( category = "", products = 0) - cat = "cat=" + category.to_s - products = "products=" + products.to_s - args = [cat, products].join( '&') - - return call_api( __method__, args) + def trends(opts = {}) + opts = {:include_products => true}.merge(opts) + args = { + :cat => opts[:category], + :products => opts[:include_products] ? nil : "0" + } + call_api('/apiGetTrends', args, 1) end + private + def build_product_query(opts = {}) + opts = {:offset => 0, :limit => 10}.merge(opts) + args = { + :fts => opts[:query], + :offset => opts[:offset], + :limit => opts[:limit], + :cat => opts[:category_id] + } + filters = [] + {:brand_id => "b", :retailer_id => "r", :price => "p", :sale => "d", :size => "s", :color => "c"}.each do |key,prefix| + if opts[key] + [*opts[key]].each do |value| + filters << "#{prefix}#{value}" + end + end + end + if filters.any? + args[:fl] = filters + end + if opts[:price_dropped_since] + d = opts[:price_dropped_since] + args[:pdd] = d.kind_of?(DateTime) ? d.to_time.to_i : d.to_i + end + args[:sort] = case opts[:sort_by] + when :price_lo_hi + 'PriceLoHi' + when :price_hi_lo + 'PriceHiLo' + when :recency + 'Recency' + when :popular + 'Popular' + end + args + end + # This method is used for making the http calls building off the DSL of this module. # @param [String] method # The method which is to be used in the call to Shopsense # @param [String] args # A concatenated group of arguments seperated by a an & symbol and spces substitued with a + symbol. # @return [String] A list of the data returned - def call_api( method, args = nil) - method_url = self.api_url + self.send( "#{method}_path") - pid = "pid=" + self.partner_id - format = "format=" + self.format - site = "site=" + self.site - - if( args === nil) then - uri = URI.parse( method_url.to_s + [pid, format, site].join('&').to_s) + def call_api(relative_url, args = {}, api_version = 2) + args[:pid] = @partner_id + args[:format] = 'json' + args[:site] = @site + compiled_args = args.delete_if {|k,v| v.nil? }.map {|(k,v)| + if v.kind_of? Array + v.map {|vv| "#{CGI::escape(k.to_s)}=#{CGI::escape(v.to_s)}" }.join("&") + else + "#{CGI::escape(k.to_s)}=#{CGI::escape(v.to_s)}" + end + }.join("&") + href = API_ENDPOINTS[api_version] + relative_url + "?" + compiled_args + uri = URI.parse(href) + response = http_session_for(uri).request(Net::HTTP::Get.new(uri.request_uri)) + data = response.body + if response.code.to_i > 299 || response.code.to_i < 200 + raise data + end + if @unserialize + require 'multi_json' + MultiJson.load(data, :symbolize_keys => true) else - uri = URI.parse( method_url.to_s + [pid, format, site, args].join('&').to_s) + data end + end - return Net::HTTP.get( uri) + def http_session_for(uri) + key = "#{uri.scheme}://#{uri.host}:#{uri.port}" + unless @http_session[key] && !@http_session[key].socket_closed? + http = Shopsense::HTTP.new(uri.host, uri.port) + http.use_ssl = true if uri.scheme == "https" + http.open_timeout = 2 + http.read_timeout = 10 + if @http_keep_alive + http.start + @http_session[key] = http + end + return http + end + @http_session[key] end + end end - - # @macro [new] api.index - # @param [Integer] index - # The start index of results returned. - # @macro [new] api.num_results - # @param [Integer] num_results - # The number of results to be returned. - # @macro [new] api.search_string - # @param [String] search_string - # The string to be in the query. diff --git a/lib/shopsense/client.rb b/lib/shopsense/client.rb deleted file mode 100644 index 41a9a49..0000000 --- a/lib/shopsense/client.rb +++ /dev/null @@ -1,43 +0,0 @@ -module Shopsense - class Client - def initialize( args = { }) - raise "No partner_id" if( !args.has_key?( 'partner_id')) - - attr_accessors = { - #: - 'format' => 'json', - 'site' => 'us'} - attr_accessors.each_key{ |key| (class << self; self; end).send( :attr_accessor, key.to_sym)} - - attr_readers = { - 'partner_id' => nil, - 'api_url' => 'http://api.shopstyle.com', - 'search_path' => '/action/apiSearch?', - 'get_brands_path' => '/action/apiGetBrands?', - 'get_look_path' => '/action/apiGetLook?', - 'get_looks_path' => '/action/apiGetLooks?', - 'get_retailers_path' => '/action/apiGetRetailers?', - 'get_stylebook_path' => '/action/apiGetStylebook?', - 'visit_retailers_path' => '/action/apiVisitRetailer?', - 'get_trends_path' => '/action/apiGetTrends?', - 'get_category_histogram_path' => '/action/apiGetCategoryHistogram?', - 'get_filter_histogram_path' => '/action/apiGetFilterHistogram?', - 'filter_types' => ['Brands', 'Retailer', 'Price', 'Discount', 'Size', 'Color'], - 'look_types' => ['New', 'TopRated', 'Celebrities', 'Featured'], - 'formats' => ['xml', 'json', 'json2', 'jsonvar', 'jsonvar2', 'jsonp', 'rss'], - 'sites' => ['www.shopstyle.com', 'www.shopstyle.co.uk']} - attr_readers.each_key{ |key| (class << self; self; end).send( :attr_reader, key.to_sym)} - - attr_writers = {} - attr_writers.each_key{ |key| (class << self; self; end).send( :attr_writer, key.to_sym)} - - attrs = attr_accessors.merge( attr_readers).merge( attr_writers) - attrs.each_key do |key| - attrs[ key] = args[ key] if( args.has_key?( key)) - end - - attrs.each {|key, value| instance_variable_set( "@#{key}", value)} - end - end - -end diff --git a/lib/shopsense/version.rb b/lib/shopsense/version.rb index 5f78774..78423c8 100644 --- a/lib/shopsense/version.rb +++ b/lib/shopsense/version.rb @@ -5,4 +5,4 @@ module Shopsense #pre = "" VERSION = [major, minor, tiny].compact.join('.') -end \ No newline at end of file +end diff --git a/spec/shopsense/shopsense_spec.rb b/spec/shopsense/shopsense_spec.rb index eaafcb9..9097888 100644 --- a/spec/shopsense/shopsense_spec.rb +++ b/spec/shopsense/shopsense_spec.rb @@ -1,70 +1,49 @@ require './spec/spec_helper' -require 'json' - -def rubify_string some_string - return some_string.gsub(/[A-Z]+/){ |s| '_' + s.downcase} -end +require 'yaml' describe Shopsense do - let( :test_input) {YAML.load_file( 'test/shopsense_test_config.yml')} - describe Shopsense::Client do - let( :client) {Shopsense::Client.new( test_input)} - describe "initialization of 'Client' object" do - it "passes if 'partner_id' is defined properly" do - client.partner_id.should == test_input['partner_id'] - end - it "passes if 'format' is defined properly" do - client.format.should == test_input['format'] - end - it "passes with a valid 'site'" do - client.site.should == test_input['site'] - end - it "passes if 'format' is able to be updated" do - new_format = 'xml' - client.format = new_format - client.format.should == new_format - end - end - end - + let(:test_input) { YAML.load_file('test/shopsense_test_config.yml') } + let(:partner_id) { + test_input['partner_id'] + } describe Shopsense::API do - let( :api) {Shopsense::API.new( test_input)} + let(:api) { Shopsense::API.new(test_input) } describe "search" do it "it passes if the proper data is returned" do fts = 'something' - min = 0 - count = 10 - api.search( fts, min, count).should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.search_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}&fts=#{fts}&min=#{min}&count=#{count}")) + min = 10 + count = 20 + api.products(:query => fts, :offset => min, :limit => count).should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/api/v2/products?pid=#{partner_id}&format=json&site=us&fts=#{fts}&offset=#{min}&limit=#{count}")) end end describe "get_category_histogram" do it "it passes if the proper data is returned" do fts = 'something' - api.get_category_histogram( fts).should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_category_histogram_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}&fts=#{fts}")) + api.category_histogram(:query => fts).should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/api/v2/products/histogram?pid=#{partner_id}&format=json&site=us&filters=Category&fts=#{fts}")) end end describe "get_filter_histogram" do it "it passes if the proper data is returned" do - filter_type = 'Brands' + filter_type = 'Brand' fts = 'something' - api.get_filter_histogram( filter_type, fts).should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_filter_histogram_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}&filterType=#{filter_type}&fts=#{fts}")) + api.filter_histogram(filter_type, :query => fts).should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/api/v2/products/histogram?pid=#{partner_id}&format=json&site=us&filters=#{filter_type}&fts=#{fts}")) end end describe "get_brands" do it "it passes if the proper data is returned" do - api.get_brands.should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_brands_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}")) + api.brands.should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/api/v2/brands?pid=#{partner_id}&format=json&site=us")) end end describe "get_look" do it "it passes if the proper data is returned" do look_id = 548347 - api.get_look( look_id).should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_look_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}&look=#{look_id}")) + api.look(look_id).should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/action/apiGetLook?look=#{look_id}&pid=#{partner_id}&format=json&site=us")) end end describe "get_retailers" do it "it passes if the proper data is returned" do - api.get_retailers.should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_retailers_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}")) + api.retailers.should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/api/v2/retailers?pid=#{partner_id}&format=json&site=us")) end end describe "get_stylebook" do @@ -72,7 +51,7 @@ def rubify_string some_string handle = 'KalvinTestone' min = 0 count = 10 - api.get_stylebook( handle, min, count).should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_stylebook_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}&handle=#{handle}&min=#{min}&count=#{count}")) + api.stylebook(:username => handle, :offset => min, :limit => count).should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/action/apiGetStylebook?pid=#{partner_id}&format=json&site=us&handle=#{handle}&min=#{min}&count=#{count}&handle=KalvinTestone")) end end describe "get_looks" do @@ -80,15 +59,25 @@ def rubify_string some_string look_type = 'New' min = 0 count = 10 - api.get_looks( look_type, min, count).should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_looks_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}&type=#{look_type}&min=#{min}&count=#{count}")) + api.looks(look_type, :offset => min, :limit => count).should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/action/apiGetLooks?type=#{look_type}&min=#{min}&count=#{count}&pid=#{partner_id}&format=json&site=us")) end end describe "get_trends" do it "it passes if the proper data is returned" do - category = 0 - products = 0 - api.get_trends( category, products).should == Net::HTTP.get( URI.parse( "#{api.api_url}#{api.get_trends_path}pid=#{api.partner_id}&format=#{api.format}&site=#{api.site}&cat=#{category}&products=#{products}")) + api.trends.should == Net::HTTP.get(URI.parse("http://api.shopstyle.com/action/apiGetTrends?pid=#{partner_id}&format=json&site=us")) + end + end + + describe "With native unserialization" do + let(:api) { Shopsense::API.new(test_input.merge("unserialize" => true)) } + describe "search" do + it "it passes if the proper data is returned" do + fts = 'something' + min = 10 + count = 20 + api.search(:query => fts, :offset => min, :limit => count).should have_key(:metadata) + end end end end -end \ No newline at end of file +end diff --git a/test/shopsense_test_config.yml b/test/shopsense_test_config.yml index d2d0646..5eb7714 100644 --- a/test/shopsense_test_config.yml +++ b/test/shopsense_test_config.yml @@ -1,3 +1,4 @@ partner_id: uid7849-6112293-28 format: json +unserialize: false site: www.shopstyle.com \ No newline at end of file