asin 0.3.0 → 0.4.0.beta1

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