sucker 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README.md +13 -19
  2. data/lib/sucker.rb +4 -4
  3. data/lib/sucker/parameters.rb +28 -0
  4. data/lib/sucker/request.rb +100 -88
  5. data/lib/sucker/response.rb +10 -0
  6. data/lib/sucker/version.rb +1 -1
  7. data/spec/fixtures/cassette_library/{unit → spec}/sucker/request.yml +4 -4
  8. data/spec/fixtures/cassette_library/spec/sucker/response.yml +26 -0
  9. data/spec/sucker/parameters_spec.rb +61 -0
  10. data/spec/sucker/request_spec.rb +276 -0
  11. data/spec/{unit/sucker → sucker}/response_spec.rb +39 -60
  12. data/spec/{unit/sucker_spec.rb → sucker_spec.rb} +0 -4
  13. data/spec/support/vcr.rb +0 -1
  14. metadata +69 -114
  15. data/spec/fixtures/cassette_library/integration/alternate_versions.yml +0 -26
  16. data/spec/fixtures/cassette_library/integration/errors.yml +0 -26
  17. data/spec/fixtures/cassette_library/integration/france.yml +0 -26
  18. data/spec/fixtures/cassette_library/integration/images.yml +0 -26
  19. data/spec/fixtures/cassette_library/integration/item_lookup/multiple.yml +0 -26
  20. data/spec/fixtures/cassette_library/integration/item_lookup/single.yml +0 -26
  21. data/spec/fixtures/cassette_library/integration/item_search.yml +0 -26
  22. data/spec/fixtures/cassette_library/integration/japan.yml +0 -26
  23. data/spec/fixtures/cassette_library/integration/keyword_search.yml +0 -26
  24. data/spec/fixtures/cassette_library/integration/kindle.yml +0 -26
  25. data/spec/fixtures/cassette_library/integration/kindle_2.yml +0 -26
  26. data/spec/fixtures/cassette_library/integration/multiple_locales.yml +0 -151
  27. data/spec/fixtures/cassette_library/integration/power_search.yml +0 -26
  28. data/spec/fixtures/cassette_library/integration/related_items/child.yml +0 -26
  29. data/spec/fixtures/cassette_library/integration/related_items/parent.yml +0 -26
  30. data/spec/fixtures/cassette_library/integration/seller_listings_search.yml +0 -26
  31. data/spec/fixtures/cassette_library/integration/twenty_items.yml +0 -26
  32. data/spec/fixtures/cassette_library/unit/sucker/response.yml +0 -26
  33. data/spec/integration/alternate_versions_spec.rb +0 -35
  34. data/spec/integration/errors_spec.rb +0 -40
  35. data/spec/integration/france_spec.rb +0 -42
  36. data/spec/integration/images_spec.rb +0 -41
  37. data/spec/integration/item_lookup_spec.rb +0 -71
  38. data/spec/integration/item_search_spec.rb +0 -41
  39. data/spec/integration/japan_spec.rb +0 -35
  40. data/spec/integration/keyword_search_spec.rb +0 -33
  41. data/spec/integration/kindle_spec.rb +0 -55
  42. data/spec/integration/multiple_locales_spec.rb +0 -70
  43. data/spec/integration/power_search_spec.rb +0 -41
  44. data/spec/integration/related_items_spec.rb +0 -53
  45. data/spec/integration/seller_listing_search_spec.rb +0 -32
  46. data/spec/integration/twenty_items_spec.rb +0 -49
  47. data/spec/unit/sucker/request_spec.rb +0 -282
@@ -1,70 +0,0 @@
1
- # encoding: utf-8
2
- require "spec_helper"
3
-
4
- module Sucker
5
-
6
- describe "Item lookup" do
7
-
8
- use_vcr_cassette "integration/multiple_locales", :record => :new_episodes
9
-
10
- context "when using Curl::Multi to search all locales simultaneously" do
11
-
12
- it "returns matches for all locales" do
13
- worker = Sucker.new(
14
- :key => amazon["key"],
15
- :secret => amazon["secret"])
16
- worker << {
17
- "Operation" => "ItemLookup",
18
- "IdType" => "ASIN",
19
- "ResponseGroup" => "ItemAttributes",
20
- "ItemId" => "0816614024" }
21
-
22
- bindings = worker.get_all.map do |response|
23
- item = response.find("Item").first
24
- item["ItemAttributes"]["Binding"]
25
- end
26
-
27
- bindings.uniq.should =~ %w{ Paperback Taschenbuch Broché ペーパーバック }
28
-
29
- end
30
-
31
- end
32
-
33
- context "when using threads to search all locales simultaneously" do
34
-
35
- # Use this approach to be able to throttle requests individually.
36
-
37
- it "returns matches for all locales" do
38
- locales = %w{us uk de ca fr jp}
39
-
40
- params = {
41
- "Operation" => "ItemLookup",
42
- "IdType" => "ASIN",
43
- "ResponseGroup" => "ItemAttributes",
44
- "ItemId" => "0816614024" }
45
-
46
- threads = locales.map do |locale|
47
- Thread.new do
48
- worker = Sucker.new(
49
- :locale => locale,
50
- :key => amazon["key"],
51
- :secret => amazon["secret"])
52
- worker << params
53
- Thread.current[:response] = worker.get
54
- end
55
- end
56
-
57
- bindings = threads.map do |thread|
58
- thread.join
59
- item = thread[:response].find("Item").first
60
- item["ItemAttributes"]["Binding"]
61
- end
62
-
63
- bindings.uniq.should =~ %w{ Paperback Taschenbuch Broché ペーパーバック }
64
- end
65
-
66
- end
67
-
68
- end
69
-
70
- end
@@ -1,41 +0,0 @@
1
- require "spec_helper"
2
-
3
- # http://docs.amazonwebservices.com/AWSECommerceService/2010-09-01/DG/index.html?PowerSearchSyntax.html
4
- #
5
- # author: ambrose and binding: (abridged or large print) and pubdate: after 11-1996
6
- # subject: history and (Spain or Mexico) and not military and language: Spanish
7
- # (subject: marketing and author: kotler) or (publisher: harper and subject: "high technology")
8
- # keywords: "high tech*" and not fiction and pubdate: during 1999
9
- # isbn: 0446394319 or 0306806819 or 1567993850
10
-
11
- module Sucker
12
-
13
- describe "Power search" do
14
-
15
- use_vcr_cassette "integration/power_search", :record => :new_episodes
16
-
17
- let(:worker) do
18
- worker = Sucker.new(
19
- :locale => "us",
20
- :key => amazon["key"],
21
- :secret => amazon["secret"])
22
- worker << {
23
- "Operation" => "ItemSearch",
24
- "SearchIndex" => "Books",
25
- "Power" => "author:lacan or deleuze and not fiction",
26
- "Sort" => "relevancerank" }
27
- worker
28
- end
29
-
30
- it "returns matches" do
31
- items = worker.get.find("Item")
32
- items.size.should > 0
33
- items.each do |item|
34
- item["ItemAttributes"]["Title"].should_not be_nil
35
- end
36
-
37
- end
38
-
39
- end
40
-
41
- end
@@ -1,53 +0,0 @@
1
- require "spec_helper"
2
-
3
- module Sucker
4
-
5
- describe "Item lookup" do
6
-
7
- context "when response group includes related items" do
8
-
9
- let(:worker) do
10
- worker = Sucker.new(
11
- :locale => "us",
12
- :key => amazon["key"],
13
- :secret => amazon["secret"])
14
-
15
- worker << {
16
- "Operation" => "ItemLookup",
17
- "IdType" => "ASIN",
18
- "ResponseGroup" => ["RelatedItems"],
19
- "RelationshipType" => "AuthorityTitle" }
20
-
21
- worker
22
- end
23
-
24
- context "when item is a child" do
25
-
26
- use_vcr_cassette "integration/related_items/child", :record => :new_episodes
27
-
28
- it "finds parent and related items" do
29
- worker << { "ItemId" => "0415246334" }
30
- response = worker.get
31
- response.find("RelatedItem").size.should eql 1
32
- parent_asin = response.find("RelatedItem").first["Item"]["ASIN"]
33
- end
34
-
35
- end
36
-
37
- context "when item is a parent" do
38
-
39
- use_vcr_cassette "integration/related_items/parent", :record => :new_episodes
40
-
41
- it "finds related items" do
42
- worker << { "ItemId" => "B000ASPUES" }
43
- response = worker.get
44
- response.find("RelatedItem").size.should > 1
45
- end
46
-
47
- end
48
-
49
- end
50
-
51
- end
52
-
53
- end
@@ -1,32 +0,0 @@
1
- require "spec_helper"
2
-
3
- module Sucker
4
- describe "Seller listing search" do
5
-
6
- use_vcr_cassette "integration/seller_listings_search", :record => :new_episodes
7
-
8
- let(:listings) do
9
- worker = Sucker.new(
10
- :locale => "us",
11
- :key => amazon["key"],
12
- :secret => amazon["secret"])
13
-
14
- worker << {
15
- "Operation" => "SellerListingSearch",
16
- "SellerId" => "A2JYSO6W6KEP83" }
17
-
18
- worker.get.find("SellerListings").first
19
- end
20
-
21
- it "returns page count" do
22
- listings["TotalPages"].to_i.should be > 0
23
- end
24
-
25
- it "returns listings" do
26
- listings["SellerListing"].size.should be > 0
27
- listings["SellerListing"].first.has_key?("Price").should be_true
28
- end
29
-
30
- end
31
-
32
- end
@@ -1,49 +0,0 @@
1
- require "spec_helper"
2
-
3
- module Sucker
4
- describe "Item lookup" do
5
-
6
- context "when querying for twenty items" do
7
-
8
- use_vcr_cassette "integration/twenty_items", :record => :new_episodes
9
-
10
- let(:asins) do
11
- %w{
12
- 0816614024 0143105825 0485113600 0816616779 0942299078
13
- 0816614008 144006654X 0486400360 0486417670 087220474X
14
- 0486454398 0268018359 1604246014 184467598X 0312427182
15
- 1844674282 0745640974 0745646441 0826489540 1844672972 }
16
- end
17
-
18
- let(:items) do
19
- worker = Sucker.new(
20
- :locale => "us",
21
- :key => amazon["key"],
22
- :secret => amazon["secret"])
23
-
24
- # Prep worker
25
- worker << {
26
- "Operation" => "ItemLookup",
27
- "ItemLookup.Shared.IdType" => "ASIN",
28
- "ItemLookup.Shared.Condition" => "All",
29
- "ItemLookup.Shared.MerchantId" => "All",
30
- "ItemLookup.Shared.ResponseGroup" => "OfferFull" }
31
-
32
- # Push twenty ASINs to worker
33
- worker << {
34
- "ItemLookup.1.ItemId" => asins[0, 10],
35
- "ItemLookup.2.ItemId" => asins[10, 10] }
36
-
37
- worker.get.find("Item")
38
- end
39
-
40
- it "returns all items" do
41
- items.count.should eql 20
42
- items.map { |item| item["ASIN"] }.should eql asins
43
- end
44
-
45
- end
46
-
47
- end
48
-
49
- end
@@ -1,282 +0,0 @@
1
- require "spec_helper"
2
-
3
- module Sucker
4
-
5
- describe Request do
6
-
7
- use_vcr_cassette "unit/sucker/request", :record => :new_episodes
8
-
9
- let(:worker) do
10
- Sucker.new(
11
- :locale => "us",
12
- :key => "key",
13
- :secret => "secret")
14
- end
15
-
16
- describe ".new" do
17
-
18
- it "sets default parameters" do
19
- default_parameters = {
20
- "Service" => "AWSECommerceService",
21
- "Version" => Sucker::CURRENT_AMAZON_API_VERSION }
22
- worker.parameters.should include default_parameters
23
- end
24
-
25
- end
26
-
27
- describe "#<<" do
28
-
29
- it "merges a hash into the parameters" do
30
- worker << { "foo" => "bar" }
31
- worker.parameters["foo"].should eql "bar"
32
- end
33
-
34
- end
35
-
36
- describe "#version=" do
37
-
38
- it "sets the Amazon API version" do
39
- worker.version = "foo"
40
- worker.parameters["Version"].should eql "foo"
41
- end
42
-
43
- end
44
-
45
- describe "#associate_tag" do
46
-
47
- it "returns the associate tag for the current locale" do
48
- worker.instance_variable_set(:@associate_tags, { :us => 'foo-bar'})
49
-
50
- worker.associate_tag.should eql 'foo-bar'
51
- end
52
-
53
- it "returns nil if an associate tag is not set for the current locale" do
54
- worker.associate_tag.should eql nil
55
- end
56
-
57
- end
58
-
59
- describe "#associate_tag=" do
60
-
61
- it "sets the associate tag for the current locale" do
62
- worker.associate_tag = "foo-bar"
63
- associate_tags = worker.instance_variable_get(:@associate_tags)
64
-
65
- associate_tags.keys.size.should eql 1
66
- associate_tags[:us].should eql 'foo-bar'
67
- worker.associate_tag.should eql 'foo-bar'
68
- end
69
-
70
- end
71
-
72
- describe "#associate_tags=" do
73
-
74
- it "sets associate tags for the locales" do
75
- tags = {
76
- :us => 'foo',
77
- :uk => 'bar',
78
- :de => 'baz',
79
- :ca => 'foo',
80
- :fr => 'bar',
81
- :jp => 'baz' }
82
- worker.associate_tags = tags
83
-
84
- worker.instance_variable_get(:@associate_tags).should eql tags
85
- end
86
-
87
- end
88
-
89
- describe "#curl_opts" do
90
-
91
- it "returns options for curl" do
92
- worker.curl_opts.should be_an_instance_of Hash
93
- end
94
-
95
- context "when given a block" do
96
-
97
- it "yields options for curl" do
98
- worker.curl_opts { |c| c.interface = "eth1" }
99
-
100
- worker.curl_opts[:interface].should eql "eth1"
101
- end
102
-
103
- end
104
-
105
- end
106
-
107
- describe "#get" do
108
-
109
- it "returns a response" do
110
- worker.get.class.ancestors.should include Response
111
- end
112
-
113
- it "raises an argument error if no key is provided" do
114
- worker.key = nil
115
- expect do
116
- worker.get
117
- end.to raise_error(/AWS access key missing/)
118
- end
119
-
120
- it "raises an argument error if no locale is provided" do
121
- worker.locale = nil
122
- expect do
123
- worker.get
124
- end.to raise_error(/Locale missing/)
125
- end
126
-
127
- it "sets options on curl" do
128
- easy = mock
129
- easy.should_receive(:interface=).once.with("eth1")
130
- Curl::Easy.stub!(:perform).and_yield(easy)
131
- Response.should_receive(:new).once
132
-
133
- worker.curl_opts { |c| c.interface = 'eth1' }
134
- worker.get
135
- end
136
-
137
- end
138
-
139
- describe "#get_all" do
140
-
141
- it "returns an array of responses" do
142
- responses = worker.get_all
143
-
144
- responses.should be_an_instance_of Array
145
- responses.each { |resp| resp.should be_an_instance_of Response }
146
- end
147
-
148
- context "when given a block" do
149
-
150
- it "yields responses" do
151
- count = 0
152
- worker.get_all do |resp|
153
- resp.should be_an_instance_of Response
154
- count += 1
155
- end
156
-
157
- count.should eql Request::HOSTS.size
158
- end
159
-
160
- end
161
-
162
- end
163
-
164
- describe "#key" do
165
-
166
- it "returns the Amazon AWS access key for the current locale" do
167
- worker.instance_variable_set(:@keys, { :us => 'foo' })
168
-
169
- worker.key.should eql 'foo'
170
- end
171
-
172
- end
173
-
174
- describe "#key=" do
175
-
176
- it "sets a global Amazon AWS access key" do
177
- worker.key = "foo"
178
- keys = worker.instance_variable_get(:@keys)
179
-
180
- keys.size.should eql Request::HOSTS.size
181
- keys.values.uniq.should eql ["foo"]
182
- end
183
-
184
- end
185
-
186
- describe "#keys=" do
187
-
188
- it "sets distinct Amazon AWS access keys for the locales" do
189
- keys = {
190
- :us => 'foo',
191
- :uk => 'bar',
192
- :de => 'baz',
193
- :ca => 'foo',
194
- :fr => 'bar',
195
- :jp => 'baz' }
196
- worker.keys = keys
197
-
198
- worker.instance_variable_get(:@keys).should eql keys
199
- end
200
-
201
- end
202
-
203
- context "private methods" do
204
-
205
- describe "#build_query" do
206
-
207
- let(:query) { worker.send(:build_query) }
208
-
209
- it "canonicalizes parameters" do
210
- query.should match /Service=([^&]+)&Timestamp=([^&]+)&Version=([^&]+)/
211
- end
212
-
213
- it "includes the key for the current locale" do
214
- worker.instance_variable_set(:@keys, { :us => 'foo' })
215
- query.should include 'AWSAccessKeyId=foo'
216
- end
217
-
218
- it "includes a timestamp" do
219
- query.should include 'Timestamp='
220
- end
221
-
222
- it "sorts parameters" do
223
- worker.parameters["AAA"] = "foo"
224
- query.should match /^AAA=foo/
225
- end
226
-
227
- it "converts a parameter whose value is an array to a string" do
228
- worker.parameters["Foo"] = ["bar", "baz"]
229
- query.should match /Foo=bar%2Cbaz/
230
- end
231
-
232
- it "handles integer parameter values" do
233
- worker.parameters["Foo"] = 1
234
- query.should match /Foo=1/
235
- end
236
-
237
- it "handles floating-point parameter values" do
238
- worker.parameters["Foo"] = 1.0
239
- query.should match /Foo=1/
240
- end
241
-
242
- end
243
-
244
- describe "#host" do
245
-
246
- it "returns a host" do
247
- worker.locale = "fr"
248
- worker.send(:host).should eql "ecs.amazonaws.fr"
249
- end
250
-
251
- end
252
-
253
- describe "#build_signed_query" do
254
-
255
- it "returns a signed query string" do
256
- query = worker.send :build_signed_query
257
- query.should match /&Signature=.*/
258
- end
259
-
260
- end
261
-
262
- describe "#timestamp" do
263
-
264
- it "returns a timestamp" do
265
- worker.send(:timestamp)["Timestamp"].should match /^\d+-\d+-\d+T\d+:\d+:\d+Z$/
266
- end
267
-
268
- end
269
-
270
- describe "#uri" do
271
-
272
- it "returns the URI with which to query Amazon" do
273
- worker.send(:uri).should be_an_instance_of URI::HTTP
274
- end
275
-
276
- end
277
-
278
- end
279
-
280
- end
281
-
282
- end