asin 0.3.0 → 0.4.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,35 +1,37 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- asin (0.3.0)
4
+ asin (0.4.0.beta1)
5
5
  crack (~> 0.1.8)
6
6
  hashie (~> 1.0.0)
7
- httpi (~> 0.7.9)
7
+ httpi (~> 0.9.2)
8
8
 
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
+ chalofa_ruby-progressbar (0.0.9.1)
12
13
  crack (0.1.8)
13
14
  diff-lcs (1.1.2)
14
- fuubar (0.0.3)
15
+ fuubar (0.0.4)
16
+ chalofa_ruby-progressbar (~> 0.0.9)
15
17
  rspec (~> 2.0)
16
18
  rspec-instafail (~> 0.1.4)
17
- ruby-progressbar (~> 0.0.9)
18
19
  hashie (1.0.0)
19
- httpclient (2.1.6.1)
20
- httpi (0.7.9)
20
+ httpclient (2.1.7.2)
21
+ httpi (0.9.2)
22
+ ntlm-http (>= 0.1.1)
21
23
  rack
22
- rack (1.2.1)
23
- rspec (2.4.0)
24
- rspec-core (~> 2.4.0)
25
- rspec-expectations (~> 2.4.0)
26
- rspec-mocks (~> 2.4.0)
27
- rspec-core (2.4.0)
28
- rspec-expectations (2.4.0)
24
+ ntlm-http (0.1.1)
25
+ rack (1.2.2)
26
+ rspec (2.5.0)
27
+ rspec-core (~> 2.5.0)
28
+ rspec-expectations (~> 2.5.0)
29
+ rspec-mocks (~> 2.5.0)
30
+ rspec-core (2.5.1)
31
+ rspec-expectations (2.5.0)
29
32
  diff-lcs (~> 1.1.2)
30
- rspec-instafail (0.1.5)
31
- rspec-mocks (2.4.0)
32
- ruby-progressbar (0.0.9)
33
+ rspec-instafail (0.1.7)
34
+ rspec-mocks (2.5.0)
33
35
 
34
36
  PLATFORMS
35
37
  ruby
@@ -37,5 +39,5 @@ PLATFORMS
37
39
  DEPENDENCIES
38
40
  asin!
39
41
  fuubar (~> 0.0.3)
40
- httpclient (~> 2.1.6.1)
41
- rspec (~> 2.4.0)
42
+ httpclient (~> 2.1.7.2)
43
+ rspec (~> 2.5.0)
@@ -2,34 +2,49 @@
2
2
 
3
3
  Status: http://stillmaintained.com/phoet/asin.png
4
4
 
5
- The gem is tested against 1.9.2, 1.9.1 and 1.8.7 (compatibility with Heroku-Bamboo-Stack[http://docs.heroku.com/stack]) and runs smoothly with Rails 3.
5
+ The gem is tested against 1.9.2 and 1.8.7 (compatibility with Heroku-Bamboo-Stack[http://docs.heroku.com/stack]) and runs smoothly with Rails 3.
6
6
 
7
7
  gem install asin
8
+ gem install httpclient # optional, see HTTPI
8
9
 
9
10
  == Configuration
10
11
 
11
- Since Version 0.2.0 ASIN provides a Rails-Style configuration.
12
-
13
- You can put this in a initializer (config/initializers/asin.rb):
12
+ Rails style initializer (config/initializers/asin.rb):
14
13
 
15
14
  ASIN::Configuration.configure do |config|
16
15
  config.secret = 'your-secret'
17
16
  config.key = 'your-key'
18
17
  end
19
18
 
20
- The old configuration syntax is still valid:
19
+ YAML style configuration:
20
+
21
+ ASIN::Configuration.configure :yaml => 'config/asin.yml'
22
+
23
+ Inline style configuration:
24
+
25
+ ASIN::Configuration.configure :secret => 'your-secret', :key => 'your-key'
26
+ # or
27
+ client.configure :secret => 'your-secret', :key => 'your-key'
28
+
29
+ == Usage
30
+
31
+ ASIN is designed as a module, so you can include it into any object you like:
21
32
 
33
+ # require and include
22
34
  require 'asin'
23
35
  include ASIN
24
36
 
25
- # use the configure method to setup your api credentials
26
- configure :secret => 'your-secret', :key => 'your-key'
37
+ # lookup an ASIN
38
+ lookup '1430218150'
27
39
 
28
- == Usage
40
+ But you can also use the +client+ method to get a client-object:
29
41
 
42
+ # just require
43
+ require 'asin'
44
+
30
45
  # create an ASIN client
31
46
  client = ASIN.client
32
-
47
+
33
48
  # lookup an item with the amazon standard identification number (asin)
34
49
  item = client.lookup '1430218150'
35
50
 
@@ -51,6 +66,39 @@ The old configuration syntax is still valid:
51
66
  item.raw.ItemAttributes.ListPrice.FormattedPrice
52
67
  => $39.99
53
68
 
69
+ There is an additional set of methods to support AWS cart operations:
70
+
71
+ #just require
72
+ require 'asin'
73
+
74
+ # create an ASIN client
75
+ client = ASIN.client
76
+
77
+ # create a cart with an item
78
+ cart = client.create_cart({:asin => '1430218150', :quantity => 1})
79
+ cart.items
80
+ => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
81
+
82
+ # get an already existing cart from a CartId and HMAC
83
+ cart = client.get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
84
+ cart.empty?
85
+ => false
86
+
87
+ # clear everything from the cart
88
+ cart = client.clear_cart(cart)
89
+ cart.empty?
90
+ => true
91
+
92
+ # add items to the cart
93
+ cart = client.add_items(cart, {:asin => '1430216263', :quantity => 2})
94
+ cart.empty?
95
+ => false
96
+
97
+ # update items in the cart
98
+ cart = client.update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
99
+ cart.saved_items
100
+ => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
101
+
54
102
  == HTTPI
55
103
 
56
104
  ASIN uses HTTPI[https://github.com/rubiii/httpi] as a HTTP-Client adapter.
@@ -64,6 +112,3 @@ As a default HTTPI uses _httpclient_ so you should add that dependency to your p
64
112
  Have a look at the RDOC[http://rdoc.info/projects/phoet/asin] for this project, if you want further information.
65
113
 
66
114
  For more information on the REST calls, have a look at the whole Amazon E-Commerce-API[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/].
67
-
68
- The code currently runs best on Ruby-1.9 due to encoding issues with the Amazon REST output (if *YOU* know how to backport this to 1.8.7, you are welcome!).
69
-
@@ -9,10 +9,10 @@ Gem::Specification.new do |s|
9
9
  s.authors = ['Peter Schröder']
10
10
  s.email = ['phoetmail@googlemail.com']
11
11
  s.homepage = 'http://github.com/phoet/asin'
12
- s.summary = 'Simple interface to Amazon Item lookup.'
13
- s.description = 'Amazon Simple INterface or whatever you want to call this.'
12
+ s.summary = 'Simple interface to AWS Lookup, Search and Cart operations.'
13
+ s.description = 'Amazon Simple INterface.'
14
14
 
15
- s.rubyforge_project = "asin"
15
+ s.rubyforge_project = "asin" # rubyforge, WTF?!
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -21,9 +21,9 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_dependency('crack', '~> 0.1.8')
23
23
  s.add_dependency('hashie', '~> 1.0.0')
24
- s.add_dependency('httpi', '~> 0.7.9')
24
+ s.add_dependency('httpi', '~> 0.9.2')
25
25
 
26
- s.add_development_dependency('httpclient', '~> 2.1.6.1')
27
- s.add_development_dependency('rspec', '~> 2.4.0')
26
+ s.add_development_dependency('httpclient', '~> 2.1.7.2')
27
+ s.add_development_dependency('rspec', '~> 2.5.0')
28
28
  s.add_development_dependency('fuubar', '~> 0.0.3')
29
29
  end
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'httpi'
2
3
  require 'crack/xml'
3
4
  require 'cgi'
@@ -5,65 +6,97 @@ require 'base64'
5
6
  require 'logger'
6
7
 
7
8
  require 'asin/item'
9
+ require 'asin/cart'
8
10
  require 'asin/version'
9
11
  require 'asin/configuration'
10
12
 
11
13
  # ASIN (Amazon Simple INterface) is a gem for easy access of the Amazon E-Commerce-API.
12
14
  # It is simple to configure and use. Since it's very small and flexible, it is easy to extend it to your needs.
13
- #
15
+ #
14
16
  # Author:: Peter Schröder (mailto:phoetmail@googlemail.com)
15
- #
16
- # ==Usage
17
- #
17
+ #
18
+ # == Usage
19
+ #
18
20
  # The ASIN module is designed as a mixin.
19
- #
21
+ #
20
22
  # require 'asin'
21
23
  # include ASIN
22
- #
24
+ #
23
25
  # In order to use the Amazon API properly, you need to be a registered user (http://aws.amazon.com).
24
- #
26
+ #
25
27
  # The registration process will give you a +secret-key+ and an +access-key+ (AWSAccessKeyId).
26
- #
28
+ #
27
29
  # Both are needed to use ASIN (see Configuration for more details):
28
- #
30
+ #
29
31
  # configure :secret => 'your-secret', :key => 'your-key'
30
- #
31
- # After configuring your environment you can call the +lookup+ method to retrieve an +Item+ via the
32
+ #
33
+ # == Search
34
+ #
35
+ # After configuring your environment you can call the +lookup+ method to retrieve an +Item+ via the
32
36
  # Amazon Standard Identification Number (ASIN):
33
- #
37
+ #
34
38
  # item = lookup '1430218150'
35
39
  # item.title
36
40
  # => "Learn Objective-C on the Mac (Learn Series)"
37
41
  #
38
42
  # OR search with fulltext/ASIN/ISBN
39
- #
43
+ #
40
44
  # items = search 'Learn Objective-C'
41
45
  # items.first.title
42
46
  # => "Learn Objective-C on the Mac (Learn Series)"
43
- #
47
+ #
44
48
  # The +Item+ uses a Hashie::Mash as its internal data representation and you can get fetched data from it:
45
- #
49
+ #
46
50
  # item.raw.ItemAttributes.ListPrice.FormattedPrice
47
51
  # => "$39.99"
48
- #
49
- # ==Further Configuration
50
- #
51
- # If you need more controll over the request that is sent to the
52
+ #
53
+ # == Further Configuration
54
+ #
55
+ # If you need more controll over the request that is sent to the
52
56
  # Amazon API (http://docs.amazonwebservices.com/AWSEcommerceService/4-0/),
53
57
  # you can override some defaults or add additional query-parameters to the REST calls:
54
- #
58
+ #
55
59
  # configure :host => 'webservices.amazon.de'
56
60
  # lookup(asin, :ResponseGroup => :Medium)
57
- #
61
+ #
62
+ # == Cart
63
+ #
64
+ # ASIN helps with AWS cart-operations.
65
+ # It currently supports the CartCreate, CartGet, CartAdd, CartModify and CartClear operations:
66
+ #
67
+ # cart = create_cart({:asin => '1430218150', :quantity => 1})
68
+ # cart.valid?
69
+ # cart.items
70
+ # => true
71
+ # => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
72
+ #
73
+ # cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
74
+ # cart.empty?
75
+ # => false
76
+ #
77
+ # cart = clear_cart(cart)
78
+ # cart.empty?
79
+ # => true
80
+ #
81
+ # cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
82
+ # cart.empty?
83
+ # => false
84
+ #
85
+ # cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
86
+ # cart.valid?
87
+ # cart.saved_items
88
+ # => true
89
+ # => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
90
+ #
58
91
  module ASIN
59
-
92
+
60
93
  DIGEST = OpenSSL::Digest::Digest.new('sha256')
61
94
  PATH = '/onca/xml'
62
95
 
63
96
  # Convenience method to create an ASIN client.
64
- #
97
+ #
65
98
  # A client is not necessary though, you can simply include the ASIN module otherwise.
66
- #
99
+ #
67
100
  def self.client
68
101
  client = Object.new
69
102
  client.extend ASIN
@@ -71,48 +104,48 @@ module ASIN
71
104
  end
72
105
 
73
106
  # Configures the basic request parameters for ASIN.
74
- #
107
+ #
75
108
  # Expects at least +secret+ and +key+ for the API call:
76
- #
109
+ #
77
110
  # configure :secret => 'your-secret', :key => 'your-key'
78
- #
111
+ #
79
112
  # See ASIN::Configuration for more infos.
80
- #
113
+ #
81
114
  def configure(options={})
82
115
  Configuration.configure(options)
83
116
  end
84
117
 
85
118
  # Performs an +ItemLookup+ REST call against the Amazon API.
86
- #
119
+ #
87
120
  # Expects an ASIN (Amazon Standard Identification Number) and returns an +Item+:
88
- #
121
+ #
89
122
  # item = lookup '1430218150'
90
123
  # item.title
91
124
  # => "Learn Objective-C on the Mac (Learn Series)"
92
- #
125
+ #
93
126
  # ==== Options:
94
- #
127
+ #
95
128
  # Additional parameters for the API call like this:
96
- #
129
+ #
97
130
  # lookup(asin, :ResponseGroup => :Medium)
98
- #
131
+ #
99
132
  def lookup(asin, params={})
100
133
  response = call(params.merge(:Operation => :ItemLookup, :ItemId => asin))
101
134
  Item.new(response['ItemLookupResponse']['Items']['Item'])
102
135
  end
103
-
136
+
104
137
  # Performs an +ItemSearch+ REST call against the Amazon API.
105
- #
138
+ #
106
139
  # Expects a search-string which can be an arbitrary array of strings (ASINs f.e.) and returns a list of +Items+:
107
- #
140
+ #
108
141
  # items = search_keywords 'Learn', 'Objective-C'
109
142
  # items.first.title
110
143
  # => "Learn Objective-C on the Mac (Learn Series)"
111
- #
144
+ #
112
145
  # ==== Options:
113
- #
146
+ #
114
147
  # Additional parameters for the API call like this:
115
- #
148
+ #
116
149
  # search_keywords('nirvana', 'never mind', :SearchIndex => :Music)
117
150
  #
118
151
  # Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
@@ -122,17 +155,17 @@ module ASIN
122
155
  response = call(params.merge(:Operation => :ItemSearch, :Keywords => keywords.join(' ')))
123
156
  (response['ItemSearchResponse']['Items']['Item'] || []).map {|item| Item.new(item)}
124
157
  end
125
-
158
+
126
159
  # Performs an +ItemSearch+ REST call against the Amazon API.
127
- #
160
+ #
128
161
  # Expects a Hash of search params where and returns a list of +Items+:
129
- #
162
+ #
130
163
  # items = search :SearchIndex => :Music
131
- #
164
+ #
132
165
  # ==== Options:
133
- #
166
+ #
134
167
  # Additional parameters for the API call like this:
135
- #
168
+ #
136
169
  # search(:Keywords => 'nirvana', :SearchIndex => :Music)
137
170
  #
138
171
  # Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
@@ -141,57 +174,154 @@ module ASIN
141
174
  response = call(params.merge(:Operation => :ItemSearch))
142
175
  (response['ItemSearchResponse']['Items']['Item'] || []).map {|item| Item.new(item)}
143
176
  end
144
-
145
- private
146
177
 
147
- def credentials_valid?
148
- !Configuration.secret.nil? && !Configuration.key.nil?
178
+ # Performs an +CartCreate+ REST call against the Amazon API.
179
+ #
180
+ # Expects one ore more Item-Hashes and returns a +Cart+:
181
+ #
182
+ # cart = create_cart({:asin => '1430218150', :quantity => 1})
183
+ #
184
+ # ==== Options:
185
+ #
186
+ # Additional parameters for the API call like this:
187
+ #
188
+ # create_cart({:asin => '1430218150', :quantity => 1}, {:asin => '1430216263', :quantity => 1, :action => :SaveForLater})
189
+ #
190
+ # Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
191
+ #
192
+ def create_cart(*items)
193
+ cart(:CartCreate, create_item_params(items))
194
+ end
195
+
196
+ # Performs an +CartGet+ REST call against the Amazon API.
197
+ #
198
+ # Expects the CartId and the HMAC to identify the returning +Cart+:
199
+ #
200
+ # cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
201
+ #
202
+ def get_cart(cart_id, hmac)
203
+ cart(:CartGet, {:CartId => cart_id, :HMAC => hmac})
149
204
  end
150
205
 
151
- def call(params)
152
- raise "you have to configure ASIN: 'configure :secret => 'your-secret', :key => 'your-key''" unless credentials_valid?
153
-
154
- log(:debug, "calling with params=#{params}")
155
- signed = create_signed_query_string(params)
156
-
157
- url = "http://#{Configuration.host}#{PATH}?#{signed}"
158
- log(:info, "performing rest call to url='#{url}'")
159
-
160
- response = HTTPI.get(url)
161
- if response.code == 200
162
- # force utf-8 chars, works only on 1.9 string
163
- resp = response.body
164
- resp = resp.force_encoding('UTF-8') if resp.respond_to? :force_encoding
165
- log(:debug, "got response='#{resp}'")
166
- Crack::XML.parse(resp)
167
- else
168
- log(:error, "got response='#{response.body}'")
169
- raise "request failed with response-code='#{response.code}'"
170
- end
206
+ # Performs an +CartAdd+ REST call against the Amazon API.
207
+ #
208
+ # Expects a +Cart+ created with +create_cart+ and one ore more Item-Hashes and returns an updated +Cart+:
209
+ #
210
+ # cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
211
+ #
212
+ # ==== Options:
213
+ #
214
+ # Additional parameters for the API call like this:
215
+ #
216
+ # add_items(cart, {:asin => '1430218150', :quantity => 1}, {:asin => '1430216263', :quantity => 1, :action => :SaveForLater})
217
+ #
218
+ # Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
219
+ #
220
+ def add_items(cart, *items)
221
+ cart(:CartAdd, create_item_params(items).merge({:CartId => cart.cart_id, :HMAC => cart.hmac}))
171
222
  end
172
223
 
173
- def create_signed_query_string(params)
174
- # nice tutorial http://cloudcarpenters.com/blog/amazon_products_api_request_signing/
175
- params[:Service] = :AWSECommerceService
176
- params[:AWSAccessKeyId] = Configuration.key
177
- # utc timestamp needed for signing
178
- params[:Timestamp] = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
179
-
180
- # signing needs to order the query alphabetically
181
- query = params.map{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.sort.join('&').gsub('+','%20')
182
-
183
- # yeah, you really need to sign the get-request not the query
184
- request_to_sign = "GET\n#{Configuration.host}\n#{PATH}\n#{query}"
185
- hmac = OpenSSL::HMAC.digest(DIGEST, Configuration.secret, request_to_sign)
186
-
187
- # don't forget to remove the newline from base64
188
- signature = CGI.escape(Base64.encode64(hmac).chomp)
189
- "#{query}&Signature=#{signature}"
224
+ # Performs an +CartModify+ REST call against the Amazon API.
225
+ #
226
+ # Expects a +Cart+ created with +create_cart+ and one ore more Item-Hashes to modify and returns an updated +Cart+:
227
+ #
228
+ # cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
229
+ #
230
+ # ==== Options:
231
+ #
232
+ # Additional parameters for the API call like this:
233
+ #
234
+ # update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
235
+ #
236
+ # Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
237
+ #
238
+ def update_items(cart, *items)
239
+ cart(:CartModify, create_item_params(items).merge({:CartId => cart.cart_id, :HMAC => cart.hmac}))
190
240
  end
191
-
192
- def log(severity, message)
193
- Configuration.logger.send severity, message if Configuration.logger
241
+
242
+ # Performs an +CartClear+ REST call against the Amazon API.
243
+ #
244
+ # Expects a +Cart+ created with +create_cart+ and returns an empty +Cart+:
245
+ #
246
+ # cart = clear_cart(cart)
247
+ #
248
+ def clear_cart(cart)
249
+ cart(:CartClear, {:CartId => cart.cart_id, :HMAC => cart.hmac})
194
250
  end
195
251
 
196
- end
252
+ private
253
+
254
+ def create_item_params(items)
255
+ keyword_mappings = {
256
+ :asin => 'ASIN',
257
+ :quantity => 'Quantity',
258
+ :cart_item_id => 'CartItemId',
259
+ :offer_listing_id => 'OfferListingId',
260
+ :action => 'Action'
261
+ }
262
+ params = {}
263
+ items.each_with_index do |item, i|
264
+ item.each do |key, value|
265
+ next unless keyword = keyword_mappings[key]
266
+ params["Item.#{i}.#{keyword}"] = value.to_s
267
+ end
268
+ end
269
+ params
270
+ end
271
+
272
+ def cart(operation, params={})
273
+ response = call(params.merge(:Operation => operation))
274
+ Cart.new(response["#{operation}Response"]['Cart'])
275
+ end
276
+
277
+
278
+ def credentials_valid?
279
+ Configuration.secret && Configuration.key
280
+ end
197
281
 
282
+ def call(params)
283
+ raise "you have to configure ASIN: 'configure :secret => 'your-secret', :key => 'your-key''" unless credentials_valid?
284
+
285
+ log(:debug, "calling with params=#{params}")
286
+ signed = create_signed_query_string(params)
287
+
288
+ url = "http://#{Configuration.host}#{PATH}?#{signed}"
289
+ log(:info, "performing rest call to url='#{url}'")
290
+
291
+ response = HTTPI.get(url)
292
+ if response.code == 200
293
+ # force utf-8 chars, works only on 1.9 string
294
+ resp = response.body
295
+ resp = resp.force_encoding('UTF-8') if resp.respond_to? :force_encoding
296
+ log(:debug, "got response='#{resp}'")
297
+ Crack::XML.parse(resp)
298
+ else
299
+ log(:error, "got response='#{response.body}'")
300
+ raise "request failed with response-code='#{response.code}'"
301
+ end
302
+ end
303
+
304
+ def create_signed_query_string(params)
305
+ # nice tutorial http://cloudcarpenters.com/blog/amazon_products_api_request_signing/
306
+ params[:Service] = :AWSECommerceService
307
+ params[:AWSAccessKeyId] = Configuration.key
308
+ # utc timestamp needed for signing
309
+ params[:Timestamp] = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
310
+
311
+ # signing needs to order the query alphabetically
312
+ query = params.map{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.sort.join('&').gsub('+','%20')
313
+
314
+ # yeah, you really need to sign the get-request not the query
315
+ request_to_sign = "GET\n#{Configuration.host}\n#{PATH}\n#{query}"
316
+ hmac = OpenSSL::HMAC.digest(DIGEST, Configuration.secret, request_to_sign)
317
+
318
+ # don't forget to remove the newline from base64
319
+ signature = CGI.escape(Base64.encode64(hmac).chomp)
320
+ "#{query}&Signature=#{signature}"
321
+ end
322
+
323
+ def log(severity, message)
324
+ Configuration.logger.send severity, message if Configuration.logger
325
+ end
326
+
327
+ end
@@ -0,0 +1,54 @@
1
+ require 'hashie'
2
+
3
+ module ASIN
4
+
5
+ # = Cart
6
+ #
7
+ # The +Cart+ class is a wrapper for the Amazon XML-REST-Response.
8
+ #
9
+ # A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
10
+ #
11
+ class Cart
12
+
13
+ attr_reader :raw
14
+
15
+ def initialize(hash)
16
+ @raw = Hashie::Mash.new(hash)
17
+ end
18
+
19
+ def cart_id
20
+ @raw.CartId
21
+ end
22
+
23
+ def hmac
24
+ @raw.HMAC
25
+ end
26
+
27
+ def url
28
+ @raw.PurchaseURL
29
+ end
30
+
31
+ def price
32
+ @raw.SubTotal.FormattedPrice
33
+ end
34
+
35
+ def items
36
+ return [] unless @raw.CartItems
37
+ @raw.CartItems.CartItem.is_a?(Array) ? @raw.CartItems.CartItem : [@raw.CartItems.CartItem]
38
+ end
39
+
40
+ def saved_items
41
+ return [] unless @raw.SavedForLaterItems
42
+ @raw.SavedForLaterItems.SavedForLaterItem.is_a?(Array) ? @raw.SavedForLaterItems.SavedForLaterItem : [@raw.SavedForLaterItems.SavedForLaterItem]
43
+ end
44
+
45
+ def valid?
46
+ @raw.Request.IsValid == 'True'
47
+ end
48
+
49
+ def empty?
50
+ @raw.CartItems.nil?
51
+ end
52
+
53
+ end
54
+ end
@@ -1,3 +1,5 @@
1
+ require "yaml"
2
+
1
3
  module ASIN
2
4
  class Configuration
3
5
  class << self
@@ -5,9 +7,9 @@ module ASIN
5
7
  attr_accessor :secret, :key, :host, :logger
6
8
 
7
9
  # Rails initializer configuration.
8
- #
10
+ #
9
11
  # Expects at least +secret+ and +key+ for the API call:
10
- #
12
+ #
11
13
  # ASIN::Configuration.configure do |config|
12
14
  # config.secret = 'your-secret'
13
15
  # config.key = 'your-key'
@@ -15,18 +17,35 @@ module ASIN
15
17
  #
16
18
  # You may pass options as a hash as well:
17
19
  #
18
- # ASIN::Configuration.configure(:secret => 'your-secret', :key => 'your-key')
19
- #
20
+ # ASIN::Configuration.configure :secret => 'your-secret', :key => 'your-key'
21
+ #
22
+ # Or configure everything using YAML:
23
+ #
24
+ # ASIN::Configuration.configure :yaml => 'config/asin.yml'
25
+ #
26
+ # ASIN::Configuration.configure :yaml => 'config/asin.yml' do |config, yml|
27
+ # config.key = yml[Rails.env]['aws_access_key']
28
+ # end
29
+ #
20
30
  # ==== Options:
21
- #
31
+ #
22
32
  # [secret] the API secret key
23
33
  # [key] the API access key
24
34
  # [host] the host, which defaults to 'webservices.amazon.com'
25
35
  # [logger] a different logger than logging to STDERR (nil for no logging)
26
- #
36
+ #
27
37
  def configure(options={})
28
38
  init_config
29
- if block_given?
39
+ if yml_path = options[:yaml] || options[:yml]
40
+ yml = File.open(yml_path) { |file| YAML.load(file) }
41
+ if block_given?
42
+ yield self, yml
43
+ else
44
+ yml.each do |key, value|
45
+ send(:"#{key}=", value)
46
+ end
47
+ end
48
+ elsif block_given?
30
49
  yield self
31
50
  else
32
51
  options.each do |key, value|
@@ -36,17 +55,22 @@ module ASIN
36
55
  self
37
56
  end
38
57
 
58
+ # Resets configuration to defaults
59
+ #
60
+ def reset
61
+ init_config(true)
62
+ end
63
+
39
64
  private
40
65
 
41
- def init_config(force=false)
42
- return if @init && !force
43
- @init = true
44
- @secret = ''
45
- @key = ''
46
- @host = 'webservices.amazon.com'
47
- @logger = Logger.new(STDERR)
48
- end
66
+ def init_config(force=false)
67
+ return if @init && !force
68
+ @init = true
69
+ @secret = ''
70
+ @key = ''
71
+ @host = 'webservices.amazon.com'
72
+ @logger = Logger.new(STDERR)
73
+ end
49
74
  end
50
75
  end
51
76
  end
52
-
@@ -3,11 +3,11 @@ require 'hashie'
3
3
  module ASIN
4
4
 
5
5
  # =Item
6
- #
6
+ #
7
7
  # The +Item+ class is a wrapper for the Amazon XML-REST-Response.
8
- #
8
+ #
9
9
  # A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
10
- #
10
+ #
11
11
  class Item
12
12
 
13
13
  attr_reader :raw
@@ -20,5 +20,5 @@ module ASIN
20
20
  @raw.ItemAttributes.Title
21
21
  end
22
22
  end
23
-
24
- end
23
+
24
+ end
@@ -1,3 +1,3 @@
1
1
  module ASIN
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0.beta1"
3
3
  end
@@ -1,42 +1,17 @@
1
1
  require "bundler"
2
2
  require "rake/rdoctask"
3
- require "rake/gempackagetask"
4
3
  require 'rspec/core/rake_task'
5
4
 
5
+ Bundler::GemHelper.install_tasks
6
+
6
7
  RSpec::Core::RakeTask.new do |t|
7
8
  t.rspec_opts = ["--format Fuubar", "--color", "-r ./spec/spec_helper.rb"]
8
9
  t.pattern = 'spec/**/*_spec.rb'
9
10
  end
10
11
 
11
- Bundler::GemHelper.install_tasks
12
-
13
- spec = eval(File.new("asin.gemspec").readlines.join("\n"))
14
-
15
- Rake::GemPackageTask.new(spec) do |pkg|
16
- pkg.need_zip = true
17
- pkg.need_tar = true
18
- end
19
-
20
12
  Rake::RDocTask.new(:rdoc_dev) do |rd|
21
13
  rd.rdoc_files.include("lib/**/*.rb", "README.rdoc")
22
14
  rd.options + ['-a', '--inline-source', '--charset=UTF-8']
23
15
  end
24
16
 
25
- desc "the test task"
26
- task :test do
27
- require 'rake/testtask'
28
- Rake::TestTask.new do |t|
29
- t.libs << "test"
30
- t.ruby_opts << "-rubygems"
31
- t.test_files = FileList['test/test_*.rb']
32
- t.verbose = true
33
- end
34
- end
35
- task :default=>:test
36
-
37
- desc "execute build on travis-ci"
38
- task :travis_ci do
39
- puts "WE LOOOOOOOOOOOOVE"
40
- Rake::Task['spec'].invoke
41
- puts "TRAVIS CI"
42
- end
17
+ task :default=>:spec
@@ -0,0 +1,4 @@
1
+ secret: 'secret_yml'
2
+ key: 'key_yml'
3
+ host: 'host_yml'
4
+ logger: 'logger_yml'
@@ -0,0 +1,159 @@
1
+ require 'spec_helper'
2
+
3
+ module ASIN
4
+ describe ASIN do
5
+
6
+ before do
7
+ ASIN::Configuration.reset
8
+ @helper = ASIN.client
9
+ @helper.configure :logger => nil
10
+
11
+ @secret = ENV['ASIN_SECRET']
12
+ @key = ENV['ASIN_KEY']
13
+ puts "configure #{@secret} and #{@key} for this test"
14
+ @helper.configure :secret => @secret, :key => @key
15
+ end
16
+
17
+ context "cart" do
18
+
19
+ it "should create a cart" do
20
+ cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1}, {:asin => OTHER_ASIN, :quantity => 2})
21
+ cart.valid?.should be(true)
22
+ cart.empty?.should be(false)
23
+ end
24
+
25
+ it "should handle item paramters" do
26
+ params = @helper.send(:create_item_params, [{:asin => 'any_asin', :quantity => 1}, {:cart_item_id => 'any_cart_item_id', :quantity => 2}, {:offer_listing_id => 'any_offer_listing_id', :quantity => 3},{:cart_item_id => 'any_cart_item_id', :action => :SaveForLater}])
27
+ params.should eql({"Item.0.ASIN"=>"any_asin", "Item.0.Quantity"=>"1", "Item.1.CartItemId"=>"any_cart_item_id", "Item.1.Quantity"=>"2", "Item.2.OfferListingId"=>"any_offer_listing_id", "Item.2.Quantity"=>"3", "Item.3.CartItemId"=>"any_cart_item_id", "Item.3.Action"=>"SaveForLater"})
28
+ end
29
+
30
+ context "with an existing cart" do
31
+
32
+ before do
33
+ @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
34
+ @cart.valid?.should be(true)
35
+ end
36
+
37
+ it "should clear a cart" do
38
+ cart = @helper.clear_cart(@cart)
39
+ cart.valid?.should be(true)
40
+ cart.empty?.should be(true)
41
+ end
42
+
43
+ it "should get a cart" do
44
+ cart = @helper.get_cart(@cart.cart_id, @cart.hmac)
45
+ cart.valid?.should be(true)
46
+ cart.empty?.should be(false)
47
+ end
48
+
49
+ it "should add items to a cart" do
50
+ cart = @helper.add_items(@cart, {:asin => OTHER_ASIN, :quantity => 2})
51
+ cart.valid?.should be(true)
52
+ cart.empty?.should be(false)
53
+ cart.items.should have(2).things
54
+ end
55
+
56
+ it "should update a cart" do
57
+ item_id = @cart.items.first.CartItemId
58
+ cart = @helper.update_items(@cart, {:cart_item_id => item_id, :action => 'SaveForLater'}, {:cart_item_id => item_id, :quantity => 7})
59
+ cart.saved_items.should have(1).things
60
+ cart.valid?.should be(true)
61
+ end
62
+
63
+ end
64
+
65
+ context Cart do
66
+
67
+ before do
68
+ @helper.configure :secret => @secret, :key => @key
69
+ @two_items = {"Request"=>
70
+ {"IsValid"=>"True",
71
+ "CartAddRequest"=>
72
+ {"CartId"=>"186-8702292-9782208",
73
+ "HMAC"=>"Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=",
74
+ "Items"=>{"Item"=>{"ASIN"=>"1430216263", "Quantity"=>"2"}}}},
75
+ "CartId"=>"186-8702292-9782208",
76
+ "HMAC"=>"Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=",
77
+ "URLEncodedHMAC"=>"Ck5MXUE%2BOQiC%2FJh8u6NhBf5FbV8%3D",
78
+ "PurchaseURL"=>
79
+ "https://www.amazon.com/gp/cart/aws-merge.html?cart-id=186-8702292-9782208%26associate-id=ws%26hmac=Ck5MXUE%2BOQiC/Jh8u6NhBf5FbV8=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False",
80
+ "SubTotal"=>
81
+ {"Amount"=>"6595", "CurrencyCode"=>"USD", "FormattedPrice"=>"$65.95"},
82
+ "CartItems"=>
83
+ {"SubTotal"=>
84
+ {"Amount"=>"6595", "CurrencyCode"=>"USD", "FormattedPrice"=>"$65.95"},
85
+ "CartItem"=>
86
+ [{"CartItemId"=>"U3CFEHHIPJNW3L",
87
+ "ASIN"=>"1430216263",
88
+ "MerchantId"=>"ATVPDKIKX0DER",
89
+ "SellerId"=>"A2R2RITDJNW1Q6",
90
+ "SellerNickname"=>"Amazon.com",
91
+ "Quantity"=>"2",
92
+ "Title"=>"Beginning iPhone Development: Exploring the iPhone SDK",
93
+ "ProductGroup"=>"Book",
94
+ "Price"=>
95
+ {"Amount"=>"1978", "CurrencyCode"=>"USD", "FormattedPrice"=>"$19.78"},
96
+ "ItemTotal"=>
97
+ {"Amount"=>"3956", "CurrencyCode"=>"USD", "FormattedPrice"=>"$39.56"}},
98
+ {"CartItemId"=>"U3G241HVLLB8N6",
99
+ "ASIN"=>"1430218150",
100
+ "MerchantId"=>"ATVPDKIKX0DER",
101
+ "SellerId"=>"A2R2RITDJNW1Q6",
102
+ "SellerNickname"=>"Amazon.com",
103
+ "Quantity"=>"1",
104
+ "Title"=>"Learn Objective-C on the Mac (Learn Series)",
105
+ "ProductGroup"=>"Book",
106
+ "Price"=>
107
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
108
+ "ItemTotal"=>
109
+ {"Amount"=>"2639",
110
+ "CurrencyCode"=>"USD",
111
+ "FormattedPrice"=>"$26.39"}}]}}
112
+ @one_item = {"Request"=>
113
+ {"IsValid"=>"True",
114
+ "CartCreateRequest"=>
115
+ {"Items"=>{"Item"=>{"ASIN"=>"1430218150", "Quantity"=>"1"}}}},
116
+ "CartId"=>"176-9182855-2326919",
117
+ "HMAC"=>"KgeVCA0YJTbuN/7Ibakrk/KnHWA=",
118
+ "URLEncodedHMAC"=>"KgeVCA0YJTbuN%2F7Ibakrk%2FKnHWA%3D",
119
+ "PurchaseURL"=>
120
+ "https://www.amazon.com/gp/cart/aws-merge.html?cart-id=176-9182855-2326919%26associate-id=ws%26hmac=KgeVCA0YJTbuN/7Ibakrk/KnHWA=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False",
121
+ "SubTotal"=>
122
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
123
+ "CartItems"=>
124
+ {"SubTotal"=>
125
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
126
+ "CartItem"=>
127
+ {"CartItemId"=>"U3G241HVLLB8N6",
128
+ "ASIN"=>"1430218150",
129
+ "MerchantId"=>"ATVPDKIKX0DER",
130
+ "SellerId"=>"A2R2RITDJNW1Q6",
131
+ "SellerNickname"=>"Amazon.com",
132
+ "Quantity"=>"1",
133
+ "Title"=>"Learn Objective-C on the Mac (Learn Series)",
134
+ "ProductGroup"=>"Book",
135
+ "Price"=>
136
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
137
+ "ItemTotal"=>
138
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"}}}}
139
+ end
140
+
141
+ it "should handle response data" do
142
+ cart = Cart.new(@two_items)
143
+ cart.valid?.should be(true)
144
+ cart.cart_id.should eql('186-8702292-9782208')
145
+ cart.hmac.should eql('Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=')
146
+ cart.url.should eql('https://www.amazon.com/gp/cart/aws-merge.html?cart-id=186-8702292-9782208%26associate-id=ws%26hmac=Ck5MXUE%2BOQiC/Jh8u6NhBf5FbV8=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False')
147
+ cart.price.should eql('$65.95')
148
+ cart.items.first.CartItemId eql('U3G241HVLLB8N6')
149
+ end
150
+
151
+ it "should handle one item" do
152
+ cart = Cart.new(@two_items)
153
+ cart.items.first.CartItemId eql('U3G241HVLLB8N6')
154
+ end
155
+
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ module ASIN
4
+ describe ASIN do
5
+ before do
6
+ ASIN::Configuration.reset
7
+ @helper = ASIN.client
8
+ @helper.configure :logger => nil
9
+
10
+ @secret = ENV['ASIN_SECRET']
11
+ @key = ENV['ASIN_KEY']
12
+ puts "configure #{@secret} and #{@key} for this test"
13
+ end
14
+
15
+ context "configuration" do
16
+ it "should fail without secret and key" do
17
+ lambda { @helper.lookup 'bla' }.should raise_error(RuntimeError)
18
+ end
19
+
20
+ it "should fail with wrong configuration key" do
21
+ lambda { @helper.configure :wrong => 'key' }.should raise_error(NoMethodError)
22
+ end
23
+
24
+ it "should not override the configuration" do
25
+ config = @helper.configure :key => 'wont get overridden'
26
+ config.key.should_not be_nil
27
+
28
+ config = @helper.configure :secret => 'is also set'
29
+ config.key.should_not be_nil
30
+ config.secret.should_not be_nil
31
+ end
32
+
33
+ it "should work with a configuration block" do
34
+ conf = ASIN::Configuration.configure do |config|
35
+ config.key = 'bla'
36
+ end
37
+ conf.key.should eql('bla')
38
+ end
39
+
40
+ it "should read configuration from yml" do
41
+ config = ASIN::Configuration.configure :yaml => 'spec/asin.yml'
42
+ config.secret.should eql('secret_yml')
43
+ config.key.should eql('key_yml')
44
+ config.host.should eql('host_yml')
45
+ config.logger.should eql('logger_yml')
46
+ end
47
+
48
+ it "should read configuration from yml with block" do
49
+ conf = ASIN::Configuration.configure :yaml => 'spec/asin.yml' do |config, yml|
50
+ config.secret = nil
51
+ config.key = yml['secret']
52
+ end
53
+ conf.secret.should be_nil
54
+ conf.key.should eql('secret_yml')
55
+ end
56
+ end
57
+
58
+ context "lookup and search" do
59
+ before do
60
+ @helper.configure :secret => @secret, :key => @key
61
+ end
62
+
63
+ it "should lookup a book" do
64
+ item = @helper.lookup(ANY_ASIN)
65
+ item.title.should =~ /Learn Objective/
66
+ end
67
+
68
+ it "should search_keywords a book with fulltext" do
69
+ items = @helper.search_keywords 'Learn', 'Objective-C'
70
+ items.should have(10).things
71
+
72
+ items.first.title.should =~ /Learn Objective/
73
+ end
74
+
75
+ it "should search_keywords never mind music" do
76
+ items = @helper.search_keywords 'nirvana', 'never mind', :SearchIndex => :Music
77
+ items.should have(9).things
78
+
79
+ items.first.title.should =~ /Nevermind/
80
+ end
81
+
82
+ it "should search music" do
83
+ items = @helper.search :SearchIndex => :Music
84
+ items.should have(0).things
85
+ end
86
+
87
+ it "should search never mind music" do
88
+ items = @helper.search :Keywords => 'nirvana', :SearchIndex => :Music
89
+ items.should have(10).things
90
+
91
+ items.first.title.should =~ /Nevermind/
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,6 +1,10 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__),'..','..','lib')
2
2
  require 'rspec'
3
3
  require 'asin'
4
+ require 'pp'
5
+
6
+ ANY_ASIN = '1430218150'
7
+ OTHER_ASIN = '1430216263'
4
8
 
5
9
  Rspec.configure do |c|
6
10
  c.mock_with :rspec
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asin
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.3.0
4
+ prerelease: 6
5
+ version: 0.4.0.beta1
6
6
  platform: ruby
7
7
  authors:
8
8
  - "Peter Schr\xC3\xB6der"
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-08 00:00:00 +01:00
13
+ date: 2011-04-12 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -43,7 +43,7 @@ dependencies:
43
43
  requirements:
44
44
  - - ~>
45
45
  - !ruby/object:Gem::Version
46
- version: 0.7.9
46
+ version: 0.9.2
47
47
  type: :runtime
48
48
  version_requirements: *id003
49
49
  - !ruby/object:Gem::Dependency
@@ -54,7 +54,7 @@ dependencies:
54
54
  requirements:
55
55
  - - ~>
56
56
  - !ruby/object:Gem::Version
57
- version: 2.1.6.1
57
+ version: 2.1.7.2
58
58
  type: :development
59
59
  version_requirements: *id004
60
60
  - !ruby/object:Gem::Dependency
@@ -65,7 +65,7 @@ dependencies:
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 2.4.0
68
+ version: 2.5.0
69
69
  type: :development
70
70
  version_requirements: *id005
71
71
  - !ruby/object:Gem::Dependency
@@ -79,7 +79,7 @@ dependencies:
79
79
  version: 0.0.3
80
80
  type: :development
81
81
  version_requirements: *id006
82
- description: Amazon Simple INterface or whatever you want to call this.
82
+ description: Amazon Simple INterface.
83
83
  email:
84
84
  - phoetmail@googlemail.com
85
85
  executables: []
@@ -92,17 +92,19 @@ files:
92
92
  - .document
93
93
  - .gitignore
94
94
  - .rvmrc
95
- - .travis.yml
96
95
  - Gemfile
97
96
  - Gemfile.lock
98
97
  - README.rdoc
99
98
  - asin.gemspec
100
99
  - lib/asin.rb
100
+ - lib/asin/cart.rb
101
101
  - lib/asin/configuration.rb
102
102
  - lib/asin/item.rb
103
103
  - lib/asin/version.rb
104
104
  - rakefile.rb
105
- - spec/asin_spec.rb
105
+ - spec/asin.yml
106
+ - spec/cart_spec.rb
107
+ - spec/search_spec.rb
106
108
  - spec/spec_helper.rb
107
109
  has_rdoc: true
108
110
  homepage: http://github.com/phoet/asin
@@ -122,16 +124,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
124
  required_rubygems_version: !ruby/object:Gem::Requirement
123
125
  none: false
124
126
  requirements:
125
- - - ">="
127
+ - - ">"
126
128
  - !ruby/object:Gem::Version
127
- version: "0"
129
+ version: 1.3.1
128
130
  requirements: []
129
131
 
130
132
  rubyforge_project: asin
131
133
  rubygems_version: 1.5.2
132
134
  signing_key:
133
135
  specification_version: 3
134
- summary: Simple interface to Amazon Item lookup.
136
+ summary: Simple interface to AWS Lookup, Search and Cart operations.
135
137
  test_files:
136
- - spec/asin_spec.rb
138
+ - spec/asin.yml
139
+ - spec/cart_spec.rb
140
+ - spec/search_spec.rb
137
141
  - spec/spec_helper.rb
@@ -1 +0,0 @@
1
- script: "rake travis_ci"
@@ -1,74 +0,0 @@
1
- describe ASIN do
2
- before do
3
- @helper = ASIN.client
4
- @helper.configure :logger => nil
5
-
6
- @secret = ENV['ASIN_SECRET']
7
- @key = ENV['ASIN_KEY']
8
- puts "configure #{@secret} and #{@key} for this test"
9
- end
10
-
11
- context "configuration" do
12
- it "should fail without secret and key" do
13
- lambda { @helper.lookup 'bla' }.should raise_error(RuntimeError)
14
- end
15
-
16
- it "should fail with wrong configuration key" do
17
- lambda { @helper.configure :wrong => 'key' }.should raise_error(NoMethodError)
18
- end
19
-
20
- it "should not override the configuration" do
21
- config = @helper.configure :key => 'wont get overridden'
22
- config.key.should_not be_nil
23
-
24
- config = @helper.configure :secret => 'is also set'
25
- config.key.should_not be_nil
26
- config.secret.should_not be_nil
27
- end
28
-
29
- it "should work with a configuration block" do
30
- config = ASIN::Configuration.configure do |config|
31
- config.key = 'bla'
32
- end
33
- config.key.should eql('bla')
34
- end
35
- end
36
-
37
- context "lookup and search" do
38
- before do
39
- @helper.configure :secret => @secret, :key => @key
40
- end
41
-
42
- it "should lookup a book" do
43
- item = @helper.lookup('1430218150')
44
- item.title.should =~ /Learn Objective/
45
- end
46
-
47
- it "should search_keywords a book with fulltext" do
48
- items = @helper.search_keywords 'Learn', 'Objective-C'
49
- items.should have(10).things
50
-
51
- items.first.title.should =~ /Learn Objective/
52
- end
53
-
54
- it "should search_keywords never mind music" do
55
- items = @helper.search_keywords 'nirvana', 'never mind', :SearchIndex => :Music
56
- items.should have(10).things
57
-
58
- items.first.title.should =~ /Nevermind/
59
- end
60
-
61
- it "should search music" do
62
- items = @helper.search :SearchIndex => :Music
63
- items.should have(0).things
64
- end
65
-
66
- it "should search never mind music" do
67
- items = @helper.search :Keywords => 'nirvana', :SearchIndex => :Music
68
- items.should have(10).things
69
-
70
- items.first.title.should =~ /Nevermind/
71
- end
72
- end
73
- end
74
-