asin 1.1.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,105 +1,10 @@
1
- # -*- coding: utf-8 -*-
2
1
  require 'httpi'
3
- require 'rexml/document'
2
+ require 'rexml/document' # https://github.com/phoet/asin/pull/23
4
3
  require 'crack/xml'
5
4
  require 'cgi'
6
5
  require 'base64'
6
+ require 'rash'
7
7
 
8
- # ASIN (Amazon Simple INterface) is a gem for easy access of the Amazon E-Commerce-API.
9
- # It is simple to configure and use. Since it's very small and flexible, it is easy to extend it to your needs.
10
- #
11
- # Author:: Peter Schröder (mailto:phoetmail@googlemail.com)
12
- #
13
- # == Usage
14
- #
15
- # The ASIN module is designed as a mixin.
16
- #
17
- # require 'asin'
18
- # include ASIN::Client
19
- #
20
- # In order to use the Amazon API properly, you need to be a registered user (http://aws.amazon.com).
21
- #
22
- # The registration process will give you a +secret-key+ and an +access-key+ (AWSAccessKeyId).
23
- # Since the latest updates to the service you will need an +associate-tag+.
24
- #
25
- # Both are needed to use ASIN (see Configuration for more details):
26
- #
27
- # configure :secret => 'your-secret', :key => 'your-key', :associate_tag => 'your-associate_tag'
28
- #
29
- # == Search
30
- #
31
- # After configuring your environment you can call the +lookup+ method to retrieve an +SimpleItem+ via the
32
- # Amazon Standard Identification Number (ASIN):
33
- #
34
- # item = lookup '1430218150'
35
- # item.first.title
36
- # => "Learn Objective-C on the Mac (Learn Series)"
37
- #
38
- # OR search with fulltext/ASIN/ISBN
39
- #
40
- # items = search 'Learn Objective-C'
41
- # items.first.title
42
- # => "Learn Objective-C on the Mac (Learn Series)"
43
- #
44
- # The +SimpleItem+ uses a Hashie::Mash as its internal data representation and you can get fetched data from it:
45
- #
46
- # item.raw.ItemAttributes.ListPrice.FormattedPrice
47
- # => "$39.99"
48
- #
49
- # == Further Configuration
50
- #
51
- # If you need more controll over the request that is sent to the
52
- # Amazon API (http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html),
53
- # you can override some defaults or add additional query-parameters to the REST calls:
54
- #
55
- # configure :host => 'webservices.amazon.de'
56
- # lookup(asin, :ResponseGroup => :Medium)
57
- #
58
- # == Cart
59
- #
60
- # ASIN helps with AWS cart-operations.
61
- # It currently supports the CartCreate, CartGet, CartAdd, CartModify and CartClear operations:
62
- #
63
- # cart = create_cart({:asin => '1430218150', :quantity => 1})
64
- # cart.valid?
65
- # cart.items
66
- # => true
67
- # => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
68
- #
69
- # cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
70
- # cart.empty?
71
- # => false
72
- #
73
- # cart = clear_cart(cart)
74
- # cart.empty?
75
- # => true
76
- #
77
- # cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
78
- # cart.empty?
79
- # => false
80
- #
81
- # cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
82
- # cart.valid?
83
- # cart.saved_items
84
- # => true
85
- # => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
86
- #
87
- # == Nodes
88
- #
89
- # In order to browse Amazon nodes, you can use +browse_node+ method:
90
- #
91
- # node = browse_node('163357')
92
- # node.node_id
93
- # => '163357'
94
- # node.name
95
- # => 'Comedy'
96
- # node.children
97
- # node.ancestors
98
- #
99
- # you can configure the +:ResponseGroup+ option to your needs:
100
- #
101
- # node = browse_node('163357', :ResponseGroup => :TopSellers)
102
- #
103
8
  module ASIN
104
9
  module Client
105
10
 
@@ -130,16 +35,10 @@ module ASIN
130
35
 
131
36
  # Performs an +ItemLookup+ REST call against the Amazon API.
132
37
  #
133
- # Expects an arbitrary number of ASIN (Amazon Standard Identification Number) and returns an array of +SimpleItem+:
38
+ # Expects an arbitrary number of ASIN (Amazon Standard Identification Number) and returns an array of item:
134
39
  #
135
40
  # item = lookup '1430218150'
136
- # item.title
137
- # => "Learn Objective-C on the Mac (Learn Series)"
138
41
  # items = lookup ['1430218150', '0439023521']
139
- # items[0].title
140
- # => "Learn Objective-C on the Mac (Learn Series)"
141
- # items[1].title
142
- # => "The Hunger Games"
143
42
  #
144
43
  # ==== Options:
145
44
  #
@@ -154,16 +53,14 @@ module ASIN
154
53
  def lookup(*asins)
155
54
  params = asins.last.is_a?(Hash) ? asins.pop : {:ResponseGroup => :Medium}
156
55
  response = call(params.merge(:Operation => :ItemLookup, :ItemId => asins.join(',')))
157
- arrayfy(response['ItemLookupResponse']['Items']['Item']).map {|item| handle_item(item)}
56
+ arrayfy(response['ItemLookupResponse']['Items']['Item']).map {|item| handle_type(item, :item)}
158
57
  end
159
58
 
160
59
  # Performs an +ItemSearch+ REST call against the Amazon API.
161
60
  #
162
- # Expects a search-string which can be an arbitrary array of strings (ASINs f.e.) and returns a list of +SimpleItem+s:
61
+ # Expects a search-string which can be an arbitrary array of strings (ASINs f.e.) and returns a list of items:
163
62
  #
164
63
  # items = search_keywords 'Learn', 'Objective-C'
165
- # items.first.title
166
- # => "Learn Objective-C on the Mac (Learn Series)"
167
64
  #
168
65
  # ==== Options:
169
66
  #
@@ -176,12 +73,12 @@ module ASIN
176
73
  def search_keywords(*keywords)
177
74
  params = keywords.last.is_a?(Hash) ? keywords.pop : {:SearchIndex => :Books, :ResponseGroup => :Medium}
178
75
  response = call(params.merge(:Operation => :ItemSearch, :Keywords => keywords.join(' ')))
179
- arrayfy(response['ItemSearchResponse']['Items']['Item']).map {|item| handle_item(item)}
76
+ arrayfy(response['ItemSearchResponse']['Items']['Item']).map {|item| handle_type(item, :item)}
180
77
  end
181
78
 
182
79
  # Performs an +ItemSearch+ REST call against the Amazon API.
183
80
  #
184
- # Expects a Hash of search params and returns a list of +SimpleItem+s:
81
+ # Expects a Hash of search params and returns a list of items:
185
82
  #
186
83
  # items = search :SearchIndex => :Music
187
84
  #
@@ -195,31 +92,31 @@ module ASIN
195
92
  #
196
93
  def search(params={:SearchIndex => :Books, :ResponseGroup => :Medium})
197
94
  response = call(params.merge(:Operation => :ItemSearch))
198
- arrayfy(response['ItemSearchResponse']['Items']['Item']).map {|item| handle_item(item)}
95
+ arrayfy(response['ItemSearchResponse']['Items']['Item']).map {|item| handle_type(item, :item)}
199
96
  end
200
97
 
201
98
  # Performs an +BrowseNodeLookup+ REST call against the Amazon API.
202
99
  #
203
- # Expects a node-id and returns a +SimpleNode+:
100
+ # Expects a node-id and returns a node:
204
101
  #
205
- # node = browse_node '163357'
102
+ # node = browse_node '17'
206
103
  #
207
104
  # ==== Options:
208
105
  #
209
106
  # Additional parameters for the API call like this:
210
107
  #
211
- # browse_node('163357', :ResponseGroup => :TopSellers)
108
+ # browse_node('17', :ResponseGroup => :TopSellers)
212
109
  #
213
110
  # Have a look at the different browse node values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html]
214
111
  #
215
112
  def browse_node(node_id, params={:ResponseGroup => :BrowseNodeInfo})
216
113
  response = call(params.merge(:Operation => :BrowseNodeLookup, :BrowseNodeId => node_id))
217
- arrayfy(response['BrowseNodeLookupResponse']['BrowseNodes']['BrowseNode']).map {|item| handle_type(item, Configuration.node_type)}
114
+ arrayfy(response['BrowseNodeLookupResponse']['BrowseNodes']['BrowseNode']).map {|item| handle_type(item, :node)}
218
115
  end
219
116
 
220
117
  # Performs an +SimilarityLookup+ REST call against the Amazon API.
221
118
  #
222
- # Expects one ore more asins and returns a list of +SimpleNode+s:
119
+ # Expects one ore more asins and returns a list of nodes:
223
120
  #
224
121
  # items = similar '1430218150'
225
122
  #
@@ -234,12 +131,12 @@ module ASIN
234
131
  def similar(*asins)
235
132
  params = asins.last.is_a?(Hash) ? asins.pop : {:SimilarityType => :Random, :ResponseGroup => :Medium}
236
133
  response = call(params.merge(:Operation => :SimilarityLookup, :ItemId => asins.join(',')))
237
- arrayfy(response['SimilarityLookupResponse']['Items']['Item']).map {|item| handle_item(item)}
134
+ arrayfy(response['SimilarityLookupResponse']['Items']['Item']).map {|item| handle_type(item, :item)}
238
135
  end
239
136
 
240
137
  # Performs an +CartCreate+ REST call against the Amazon API.
241
138
  #
242
- # Expects one ore more item-hashes and returns a +SimpleCart+:
139
+ # Expects one ore more item-hashes and returns a cart:
243
140
  #
244
141
  # cart = create_cart({:asin => '1430218150', :quantity => 1})
245
142
  #
@@ -257,7 +154,7 @@ module ASIN
257
154
 
258
155
  # Performs an +CartGet+ REST call against the Amazon API.
259
156
  #
260
- # Expects the CartId and the HMAC to identify the returning +SimpleCart+:
157
+ # Expects the CartId and the HMAC to identify the returning cart:
261
158
  #
262
159
  # cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
263
160
  #
@@ -267,7 +164,7 @@ module ASIN
267
164
 
268
165
  # Performs an +CartAdd+ REST call against the Amazon API.
269
166
  #
270
- # Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes and returns an updated +SimpleCart+:
167
+ # Expects a cart created with +create_cart+ and one ore more Item-Hashes and returns an updated cart:
271
168
  #
272
169
  # cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
273
170
  #
@@ -285,7 +182,7 @@ module ASIN
285
182
 
286
183
  # Performs an +CartModify+ REST call against the Amazon API.
287
184
  #
288
- # Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes to modify and returns an updated +SimpleCart+:
185
+ # Expects a cart created with +create_cart+ and one ore more Item-Hashes to modify and returns an updated cart:
289
186
  #
290
187
  # cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
291
188
  #
@@ -303,7 +200,7 @@ module ASIN
303
200
 
304
201
  # Performs an +CartClear+ REST call against the Amazon API.
305
202
  #
306
- # Expects a +SimpleCart+ created with +create_cart+ and returns an empty +SimpleCart+:
203
+ # Expects a cart created with +create_cart+ and returns an empty cart:
307
204
  #
308
205
  # cart = clear_cart(cart)
309
206
  #
@@ -318,19 +215,8 @@ module ASIN
318
215
  item.is_a?(Array) ? item : [item]
319
216
  end
320
217
 
321
- def handle_item(item)
322
- handle_type(item, Configuration.item_type)
323
- end
324
-
325
218
  def handle_type(data, type)
326
- if type.is_a?(Class)
327
- type.new(data)
328
- elsif type == :mash
329
- require 'hashie'
330
- Hashie::Mash.new(data)
331
- else
332
- data
333
- end
219
+ Hashie::Rash.new(data)
334
220
  end
335
221
 
336
222
  def create_item_params(items)
@@ -354,7 +240,7 @@ module ASIN
354
240
  def cart(operation, params={})
355
241
  response = call(params.merge(:Operation => operation))
356
242
  cart = response["#{operation}Response"]['Cart']
357
- handle_type(cart, Configuration.cart_type)
243
+ handle_type(cart, :cart)
358
244
  end
359
245
 
360
246
  def call(params)
@@ -23,13 +23,10 @@ module ASIN
23
23
  # [host] the host, which defaults to 'webservices.amazon.com'
24
24
  # [logger] a different logger than logging to STDERR (nil for no logging)
25
25
  # [version] a custom version of the API calls. Default is 2010-11-01
26
- # [item_type] a different class for SimpleItem, use :mash for Hashie::Mash or :raw for a plain hash
27
- # [cart_type] a different class for SimpleCart, use :mash for Hashie::Mash or :raw for a plain hash
28
- # [node_type] a different class for SimpleNode, use :mash for Hashie::Mash or :raw for a plain hash
29
26
  #
30
27
  class Configuration
31
28
  include Confiture::Configuration
32
- confiture_allowed_keys(:secret, :key, :associate_tag, :host, :version, :logger, :item_type, :cart_type, :node_type)
29
+ confiture_allowed_keys(:secret, :key, :associate_tag, :host, :version, :logger)
33
30
  confiture_mandatory_keys(:secret, :key, :associate_tag)
34
31
  confiture_defaults({
35
32
  :secret => '',
@@ -38,9 +35,6 @@ module ASIN
38
35
  :host => 'webservices.amazon.com',
39
36
  :version => '2011-08-01',
40
37
  :logger => Logger.new(STDERR),
41
- :item_type => SimpleItem,
42
- :cart_type => SimpleCart,
43
- :node_type => SimpleNode,
44
38
  })
45
39
  end
46
40
  end
@@ -1,3 +1,3 @@
1
1
  module ASIN
2
- VERSION = "1.1.2"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -94,4 +94,4 @@ http_interactions:
94
94
  new to programming. &lt;/p&gt;</Content><IsLinkSuppressed>0</IsLinkSuppressed></EditorialReview></EditorialReviews></Item></Items></ItemLookupResponse>
95
95
  http_version:
96
96
  recorded_at: Tue, 25 Sep 2012 20:04:40 GMT
97
- recorded_with: VCR 2.2.5
97
+ recorded_with: VCR 2.2.5
@@ -9,9 +9,9 @@ module ASIN
9
9
  end
10
10
 
11
11
  it "should lookup a browse_node", :vcr do
12
- item = @helper.browse_node(ANY_BROWSE_NODE_ID).first
13
- item.node_id.should eql(ANY_BROWSE_NODE_ID)
14
- item.name.should eql('Comedy')
12
+ item = @helper.browse_node(ANY_BROWSE_NODE_ID).first
13
+ expect(item.browse_node_id).to eql(ANY_BROWSE_NODE_ID)
14
+ expect(item.name).to eql('Comedy')
15
15
  end
16
16
  end
17
17
  end
@@ -11,13 +11,13 @@ module ASIN
11
11
 
12
12
  it "should create a cart", :vcr do
13
13
  cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1}, {:asin => ANY_OTHER_ASIN, :quantity => 2})
14
- cart.valid?.should be(true)
15
- cart.empty?.should be(false)
14
+ expect(cart.valid?).to be_true
15
+ expect(cart.empty?).to be_false
16
16
  end
17
17
 
18
18
  it "should handle item paramters" do
19
19
  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}])
20
- 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"})
20
+ expect(params).to 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"})
21
21
  end
22
22
 
23
23
  context "with an existing cart" do
@@ -25,124 +25,31 @@ module ASIN
25
25
  it "should clear a cart", :vcr do
26
26
  @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
27
27
  cart = @helper.clear_cart(@cart)
28
- cart.valid?.should be(true)
29
- cart.empty?.should be(true)
28
+ expect(cart.valid?).to be_true
29
+ expect(cart.empty?).to be_true
30
30
  end
31
31
 
32
32
  it "should get a cart", :vcr do
33
33
  @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
34
34
  cart = @helper.get_cart(@cart.cart_id, @cart.hmac)
35
- cart.valid?.should be(true)
36
- cart.empty?.should be(false)
35
+ expect(cart.valid?).to be_true
36
+ expect(cart.empty?).to be_false
37
37
  end
38
38
 
39
39
  it "should add items to a cart", :vcr do
40
40
  @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
41
41
  cart = @helper.add_items(@cart, {:asin => ANY_OTHER_ASIN, :quantity => 2})
42
- cart.valid?.should be(true)
43
- cart.empty?.should be(false)
44
- cart.items.should have(2).things
42
+ expect(cart.valid?).to be_true
43
+ expect(cart.empty?).to be_false
44
+ expect(cart).to have(2).items
45
45
  end
46
46
 
47
47
  it "should update a cart", :vcr do
48
48
  @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
49
- item_id = @cart.items.first.CartItemId
49
+ item_id = @cart.items.first.cart_item_id
50
50
  cart = @helper.update_items(@cart, {:cart_item_id => item_id, :action => 'SaveForLater'}, {:cart_item_id => item_id, :quantity => 7})
51
- cart.saved_items.should have(1).things
52
- cart.valid?.should be(true)
53
- end
54
-
55
- end
56
-
57
- context SimpleCart do
58
-
59
- before do
60
- @helper.configure :secret => @secret, :key => @key
61
- @two_items = {"Request"=>
62
- {"IsValid"=>"True",
63
- "CartAddRequest"=>
64
- {"CartId"=>"186-8702292-9782208",
65
- "HMAC"=>"Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=",
66
- "Items"=>{"Item"=>{"ASIN"=>"1430216263", "Quantity"=>"2"}}}},
67
- "CartId"=>"186-8702292-9782208",
68
- "HMAC"=>"Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=",
69
- "URLEncodedHMAC"=>"Ck5MXUE%2BOQiC%2FJh8u6NhBf5FbV8%3D",
70
- "PurchaseURL"=>
71
- "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",
72
- "SubTotal"=>
73
- {"Amount"=>"6595", "CurrencyCode"=>"USD", "FormattedPrice"=>"$65.95"},
74
- "CartItems"=>
75
- {"SubTotal"=>
76
- {"Amount"=>"6595", "CurrencyCode"=>"USD", "FormattedPrice"=>"$65.95"},
77
- "CartItem"=>
78
- [{"CartItemId"=>"U3CFEHHIPJNW3L",
79
- "ASIN"=>"1430216263",
80
- "MerchantId"=>"ATVPDKIKX0DER",
81
- "SellerId"=>"A2R2RITDJNW1Q6",
82
- "SellerNickname"=>"Amazon.com",
83
- "Quantity"=>"2",
84
- "Title"=>"Beginning iPhone Development: Exploring the iPhone SDK",
85
- "ProductGroup"=>"Book",
86
- "Price"=>
87
- {"Amount"=>"1978", "CurrencyCode"=>"USD", "FormattedPrice"=>"$19.78"},
88
- "ItemTotal"=>
89
- {"Amount"=>"3956", "CurrencyCode"=>"USD", "FormattedPrice"=>"$39.56"}},
90
- {"CartItemId"=>"U3G241HVLLB8N6",
91
- "ASIN"=>"1430218150",
92
- "MerchantId"=>"ATVPDKIKX0DER",
93
- "SellerId"=>"A2R2RITDJNW1Q6",
94
- "SellerNickname"=>"Amazon.com",
95
- "Quantity"=>"1",
96
- "Title"=>"Learn Objective-C on the Mac (Learn Series)",
97
- "ProductGroup"=>"Book",
98
- "Price"=>
99
- {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
100
- "ItemTotal"=>
101
- {"Amount"=>"2639",
102
- "CurrencyCode"=>"USD",
103
- "FormattedPrice"=>"$26.39"}}]}}
104
- @one_item = {"Request"=>
105
- {"IsValid"=>"True",
106
- "CartCreateRequest"=>
107
- {"Items"=>{"Item"=>{"ASIN"=>"1430218150", "Quantity"=>"1"}}}},
108
- "CartId"=>"176-9182855-2326919",
109
- "HMAC"=>"KgeVCA0YJTbuN/7Ibakrk/KnHWA=",
110
- "URLEncodedHMAC"=>"KgeVCA0YJTbuN%2F7Ibakrk%2FKnHWA%3D",
111
- "PurchaseURL"=>
112
- "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",
113
- "SubTotal"=>
114
- {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
115
- "CartItems"=>
116
- {"SubTotal"=>
117
- {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
118
- "CartItem"=>
119
- {"CartItemId"=>"U3G241HVLLB8N6",
120
- "ASIN"=>"1430218150",
121
- "MerchantId"=>"ATVPDKIKX0DER",
122
- "SellerId"=>"A2R2RITDJNW1Q6",
123
- "SellerNickname"=>"Amazon.com",
124
- "Quantity"=>"1",
125
- "Title"=>"Learn Objective-C on the Mac (Learn Series)",
126
- "ProductGroup"=>"Book",
127
- "Price"=>
128
- {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
129
- "ItemTotal"=>
130
- {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"}}}}
131
- end
132
-
133
- it "should handle response data" do
134
- cart = SimpleCart.new(@two_items)
135
- cart.valid?.should be(true)
136
- cart.cart_id.should eql('186-8702292-9782208')
137
- cart.hmac.should eql('Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=')
138
- 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')
139
- cart.price.should eql('$65.95')
140
- cart.items.first.CartItemId eql('U3G241HVLLB8N6')
141
- end
142
-
143
- it "should handle one item" do
144
- cart = SimpleCart.new(@two_items)
145
- cart.items.first.CartItemId eql('U3G241HVLLB8N6')
51
+ expect(cart).to have(1).saved_items
52
+ expect(cart.valid?).to be_true
146
53
  end
147
54
 
148
55
  end