sucker 1.1.4 → 1.2.0
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.
- data/README.md +13 -19
- data/lib/sucker.rb +4 -4
- data/lib/sucker/parameters.rb +28 -0
- data/lib/sucker/request.rb +100 -88
- data/lib/sucker/response.rb +10 -0
- data/lib/sucker/version.rb +1 -1
- data/spec/fixtures/cassette_library/{unit → spec}/sucker/request.yml +4 -4
- data/spec/fixtures/cassette_library/spec/sucker/response.yml +26 -0
- data/spec/sucker/parameters_spec.rb +61 -0
- data/spec/sucker/request_spec.rb +276 -0
- data/spec/{unit/sucker → sucker}/response_spec.rb +39 -60
- data/spec/{unit/sucker_spec.rb → sucker_spec.rb} +0 -4
- data/spec/support/vcr.rb +0 -1
- metadata +69 -114
- data/spec/fixtures/cassette_library/integration/alternate_versions.yml +0 -26
- data/spec/fixtures/cassette_library/integration/errors.yml +0 -26
- data/spec/fixtures/cassette_library/integration/france.yml +0 -26
- data/spec/fixtures/cassette_library/integration/images.yml +0 -26
- data/spec/fixtures/cassette_library/integration/item_lookup/multiple.yml +0 -26
- data/spec/fixtures/cassette_library/integration/item_lookup/single.yml +0 -26
- data/spec/fixtures/cassette_library/integration/item_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/japan.yml +0 -26
- data/spec/fixtures/cassette_library/integration/keyword_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/kindle.yml +0 -26
- data/spec/fixtures/cassette_library/integration/kindle_2.yml +0 -26
- data/spec/fixtures/cassette_library/integration/multiple_locales.yml +0 -151
- data/spec/fixtures/cassette_library/integration/power_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/related_items/child.yml +0 -26
- data/spec/fixtures/cassette_library/integration/related_items/parent.yml +0 -26
- data/spec/fixtures/cassette_library/integration/seller_listings_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/twenty_items.yml +0 -26
- data/spec/fixtures/cassette_library/unit/sucker/response.yml +0 -26
- data/spec/integration/alternate_versions_spec.rb +0 -35
- data/spec/integration/errors_spec.rb +0 -40
- data/spec/integration/france_spec.rb +0 -42
- data/spec/integration/images_spec.rb +0 -41
- data/spec/integration/item_lookup_spec.rb +0 -71
- data/spec/integration/item_search_spec.rb +0 -41
- data/spec/integration/japan_spec.rb +0 -35
- data/spec/integration/keyword_search_spec.rb +0 -33
- data/spec/integration/kindle_spec.rb +0 -55
- data/spec/integration/multiple_locales_spec.rb +0 -70
- data/spec/integration/power_search_spec.rb +0 -41
- data/spec/integration/related_items_spec.rb +0 -53
- data/spec/integration/seller_listing_search_spec.rb +0 -32
- data/spec/integration/twenty_items_spec.rb +0 -49
- data/spec/unit/sucker/request_spec.rb +0 -282
data/lib/sucker/version.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
- !ruby/struct:VCR::HTTPInteraction
|
3
3
|
request: !ruby/struct:VCR::Request
|
4
4
|
method: :get
|
5
|
-
uri: http://ecs.amazonaws.com:80/onca/xml?AWSAccessKeyId=key&AssociateTag=&Service=AWSECommerceService&Signature=
|
5
|
+
uri: http://ecs.amazonaws.com:80/onca/xml?AWSAccessKeyId=key&AssociateTag=&Service=AWSECommerceService&Signature=5sbmkIO1PqtCCUH0Ih9Fx/3q9ER1FuXk2UPFLlISrIQ=&Timestamp=2011-01-17T15:20:03Z&Version=2010-11-01
|
6
6
|
body:
|
7
7
|
headers:
|
8
8
|
response: !ruby/struct:VCR::Response
|
@@ -11,13 +11,13 @@
|
|
11
11
|
message: OK
|
12
12
|
headers:
|
13
13
|
date:
|
14
|
-
-
|
14
|
+
- Mon, 17 Jan 2011 15:20:05 GMT
|
15
15
|
server:
|
16
16
|
- Server
|
17
17
|
x-amz-id-1:
|
18
|
-
-
|
18
|
+
- 1218DXHJBXZ5J480J8QM
|
19
19
|
x-amz-id-2:
|
20
|
-
-
|
20
|
+
- SJpoXux3oMHHhZyjDxwhVVy8JrcptMTdzE1nK8SxSm0=
|
21
21
|
nncoection:
|
22
22
|
- close
|
23
23
|
- close
|
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://ecs.amazonaws.com:80/onca/xml?AWSAccessKeyId=0ZVSQ33MDFPQS8H2PM02&AssociateTag=&IdType=ASIN&ItemId=0816614024,0143105825&Operation=ItemLookup&Service=AWSECommerceService&Signature=mb2SRZUnxqPRrI4SdOLZqkCmm5HjXE2Urd0PIr/vzWU=&Timestamp=2011-01-17T15:20:11Z&Version=2010-11-01
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
response: !ruby/struct:VCR::Response
|
9
|
+
status: !ruby/struct:VCR::ResponseStatus
|
10
|
+
code: 200
|
11
|
+
message: OK
|
12
|
+
headers:
|
13
|
+
date:
|
14
|
+
- Mon, 17 Jan 2011 15:20:12 GMT
|
15
|
+
server:
|
16
|
+
- Server
|
17
|
+
content-type:
|
18
|
+
- text/xml;charset=UTF-8
|
19
|
+
vary:
|
20
|
+
- Accept-Encoding,User-Agent
|
21
|
+
nncoection:
|
22
|
+
- close
|
23
|
+
transfer-encoding:
|
24
|
+
- chunked
|
25
|
+
body: "<?xml version=\"1.0\" ?><ItemLookupResponse xmlns=\"http://webservices.amazon.com/AWSECommerceService/2010-11-01\"><OperationRequest><RequestId>c5f72c52-3206-4a9f-a30f-a58e1a5f4445</RequestId><Arguments><Argument Name=\"Operation\" Value=\"ItemLookup\"></Argument><Argument Name=\"Service\" Value=\"AWSECommerceService\"></Argument><Argument Name=\"Signature\" Value=\"mb2SRZUnxqPRrI4SdOLZqkCmm5HjXE2Urd0PIr/vzWU=\"></Argument><Argument Name=\"AssociateTag\"></Argument><Argument Name=\"Version\" Value=\"2010-11-01\"></Argument><Argument Name=\"ItemId\" Value=\"0816614024,0143105825\"></Argument><Argument Name=\"IdType\" Value=\"ASIN\"></Argument><Argument Name=\"AWSAccessKeyId\" Value=\"0ZVSQ33MDFPQS8H2PM02\"></Argument><Argument Name=\"Timestamp\" Value=\"2011-01-17T15:20:11Z\"></Argument></Arguments><RequestProcessingTime>0.0103990000000000</RequestProcessingTime></OperationRequest><Items><Request><IsValid>True</IsValid><ItemLookupRequest><Condition>New</Condition><DeliveryMethod>Ship</DeliveryMethod><IdType>ASIN</IdType><MerchantId>Amazon</MerchantId><OfferPage>1</OfferPage><ItemId>0816614024</ItemId><ItemId>0143105825</ItemId><ResponseGroup>Small</ResponseGroup><ReviewPage>1</ReviewPage><ReviewSort>-SubmissionDate</ReviewSort><VariationPage>All</VariationPage></ItemLookupRequest></Request><Item><ASIN>0816614024</ASIN><DetailPageURL>http://www.amazon.com/Thousand-Plateaus-Schizophrenia-Gilles-Deleuze/dp/0816614024%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0816614024</DetailPageURL><ItemLinks><ItemLink><Description>Technical Details</Description><URL>http://www.amazon.com/Thousand-Plateaus-Schizophrenia-Gilles-Deleuze/dp/tech-data/0816614024%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0816614024</URL></ItemLink><ItemLink><Description>Add To Baby Registry</Description><URL>http://www.amazon.com/gp/registry/baby/add-item.html%3Fasin.0%3D0816614024%26SubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0816614024</URL></ItemLink><ItemLink><Description>Add To Wedding Registry</Description><URL>http://www.amazon.com/gp/registry/wedding/add-item.html%3Fasin.0%3D0816614024%26SubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0816614024</URL></ItemLink><ItemLink><Description>Add To Wishlist</Description><URL>http://www.amazon.com/gp/registry/wishlist/add-item.html%3Fasin.0%3D0816614024%26SubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0816614024</URL></ItemLink><ItemLink><Description>Tell A Friend</Description><URL>http://www.amazon.com/gp/pdp/taf/0816614024%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0816614024</URL></ItemLink><ItemLink><Description>All Customer Reviews</Description><URL>http://www.amazon.com/review/product/0816614024%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0816614024</URL></ItemLink><ItemLink><Description>All Offers</Description><URL>http://www.amazon.com/gp/offer-listing/0816614024%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0816614024</URL></ItemLink></ItemLinks><ItemAttributes><Author>Gilles Deleuze</Author><Creator Role=\"Contributor\">Felix Guattari</Creator><Manufacturer>Univ Of Minnesota Press</Manufacturer><ProductGroup>Book</ProductGroup><Title>Thousand Plateaus: Capitalism and Schizophrenia</Title></ItemAttributes></Item><Item><ASIN>0143105825</ASIN><DetailPageURL>http://www.amazon.com/Anti-Oedipus-Capitalism-Schizophrenia-Penguin-Classics/dp/0143105825%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0143105825</DetailPageURL><ItemLinks><ItemLink><Description>Technical Details</Description><URL>http://www.amazon.com/Anti-Oedipus-Capitalism-Schizophrenia-Penguin-Classics/dp/tech-data/0143105825%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0143105825</URL></ItemLink><ItemLink><Description>Add To Baby Registry</Description><URL>http://www.amazon.com/gp/registry/baby/add-item.html%3Fasin.0%3D0143105825%26SubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0143105825</URL></ItemLink><ItemLink><Description>Add To Wedding Registry</Description><URL>http://www.amazon.com/gp/registry/wedding/add-item.html%3Fasin.0%3D0143105825%26SubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0143105825</URL></ItemLink><ItemLink><Description>Add To Wishlist</Description><URL>http://www.amazon.com/gp/registry/wishlist/add-item.html%3Fasin.0%3D0143105825%26SubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0143105825</URL></ItemLink><ItemLink><Description>Tell A Friend</Description><URL>http://www.amazon.com/gp/pdp/taf/0143105825%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0143105825</URL></ItemLink><ItemLink><Description>All Customer Reviews</Description><URL>http://www.amazon.com/review/product/0143105825%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0143105825</URL></ItemLink><ItemLink><Description>All Offers</Description><URL>http://www.amazon.com/gp/offer-listing/0143105825%3FSubscriptionId%3D0ZVSQ33MDFPQS8H2PM02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D0143105825</URL></ItemLink></ItemLinks><ItemAttributes><Author>Gilles Deleuze</Author><Author>Felix Guattari</Author><Creator Role=\"Translator\">Robert Hurley</Creator><Creator Role=\"Translator\">Mark Seem</Creator><Creator Role=\"Introduction\">Mark Seem</Creator><Creator Role=\"Translator\">Helen Lane</Creator><Creator Role=\"Preface\">Michel Foucault</Creator><Manufacturer>Penguin Classics</Manufacturer><ProductGroup>Book</ProductGroup><Title>Anti-Oedipus: Capitalism and Schizophrenia (Penguin Classics)</Title></ItemAttributes></Item></Items></ItemLookupResponse>"
|
26
|
+
http_version: "1.1"
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Sucker
|
4
|
+
describe Parameters do
|
5
|
+
let(:parameters) do
|
6
|
+
Parameters.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "is a Hash" do
|
10
|
+
Parameters.ancestors.should include Hash
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when initialized" do
|
14
|
+
it "sets `Service`" do
|
15
|
+
parameters.should have_key "Service"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "sets `Version`" do
|
19
|
+
parameters.should have_key "Version"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "set `Timestamp`" do
|
23
|
+
parameters.should have_key "Timestamp"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#normalize" do
|
28
|
+
it "casts keys to string" do
|
29
|
+
parameters[:Foo] = 0
|
30
|
+
normalized = parameters.normalize
|
31
|
+
|
32
|
+
normalized.should have_key "Foo"
|
33
|
+
normalized.should_not have_key :foo
|
34
|
+
end
|
35
|
+
|
36
|
+
it "camelizes keys" do
|
37
|
+
parameters["foo_bar"] = 0
|
38
|
+
normalized = parameters.normalize
|
39
|
+
|
40
|
+
normalized.should have_key "FooBar"
|
41
|
+
normalized.should_not have_key "foo_bar"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "casts numeric values to string" do
|
45
|
+
parameters["Foo"] = 1
|
46
|
+
parameters.normalize["Foo"].should eql "1"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "converts array values to string" do
|
50
|
+
parameters["Foo"] = ['bar', 'baz']
|
51
|
+
parameters.normalize["Foo"].should eql 'bar,baz'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#timestamp" do
|
56
|
+
it "generates a timestamp" do
|
57
|
+
parameters.send(:timestamp).should match /^\d+-\d+-\d+T\d+:\d+:\d+Z$/
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Sucker
|
4
|
+
describe Request do
|
5
|
+
use_vcr_cassette "spec/sucker/request", :record => :new_episodes
|
6
|
+
|
7
|
+
let(:worker) do
|
8
|
+
Sucker.new(
|
9
|
+
:locale => :us,
|
10
|
+
:key => "key",
|
11
|
+
:secret => "secret")
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#<<" do
|
15
|
+
it "merges a hash into the existing parameters" do
|
16
|
+
worker << { "foo" => "bar" }
|
17
|
+
worker.parameters["foo"].should eql "bar"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#version=" do
|
22
|
+
it "sets the Amazon API version" do
|
23
|
+
worker.version = "foo"
|
24
|
+
worker.parameters["Version"].should eql "foo"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#associate_tag" do
|
29
|
+
it "returns the associate tag for the current locale" do
|
30
|
+
worker.instance_variable_set(:@associate_tags, { :us => 'foo-bar'})
|
31
|
+
|
32
|
+
worker.associate_tag.should eql 'foo-bar'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns blank if no associate tag is set for the current locale" do
|
36
|
+
worker.associate_tag.should be_blank
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#associate_tag=" do
|
41
|
+
it "sets the associate tag for the current locale" do
|
42
|
+
worker.associate_tag = "foo-bar"
|
43
|
+
associate_tags = worker.instance_variable_get(:@associate_tags)
|
44
|
+
|
45
|
+
associate_tags.keys.size.should eql 1
|
46
|
+
associate_tags[:us].should eql 'foo-bar'
|
47
|
+
worker.associate_tag.should eql 'foo-bar'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#associate_tags=" do
|
52
|
+
it "sets associate tags for the locales" do
|
53
|
+
tags = {
|
54
|
+
:us => 'foo',
|
55
|
+
:uk => 'bar',
|
56
|
+
:de => 'baz',
|
57
|
+
:ca => 'foo',
|
58
|
+
:fr => 'bar',
|
59
|
+
:jp => 'baz' }
|
60
|
+
worker.associate_tags = tags
|
61
|
+
|
62
|
+
worker.instance_variable_get(:@associate_tags).should eql tags
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#curl_opts" do
|
67
|
+
it "returns options for curl" do
|
68
|
+
worker.curl_opts.should be_an_instance_of Hash
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when given a block" do
|
72
|
+
|
73
|
+
it "yields options for curl" do
|
74
|
+
worker.curl_opts { |c| c.interface = "eth1" }
|
75
|
+
|
76
|
+
worker.curl_opts[:interface].should eql "eth1"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#get" do
|
82
|
+
context "when no argument is passed" do
|
83
|
+
it "returns a response" do
|
84
|
+
worker.get.class.ancestors.should include Response
|
85
|
+
end
|
86
|
+
|
87
|
+
it "sets options on curl" do
|
88
|
+
easy = mock
|
89
|
+
easy.should_receive(:interface=).once.with("eth1")
|
90
|
+
Curl::Easy.stub!(:perform).and_yield(easy)
|
91
|
+
Response.should_receive(:new).once
|
92
|
+
|
93
|
+
worker.curl_opts { |c| c.interface = 'eth1' }
|
94
|
+
worker.get
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when one argument is passed" do
|
99
|
+
context "when the argument is is `:all`" do
|
100
|
+
it "queries all locales" do
|
101
|
+
locales = worker.send(:locales)
|
102
|
+
worker.should_receive(:get_multi).with(locales)
|
103
|
+
worker.get(:all)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when the argument is not `:all`" do
|
108
|
+
it "sets current locale to to the argument" do
|
109
|
+
worker.should_receive(:locale=).with(:uk)
|
110
|
+
worker.get(:uk)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "calls itself with no argument" do
|
114
|
+
worker.class.send :alias_method, :get_original, :get
|
115
|
+
worker.should_receive(:get).with(no_args())
|
116
|
+
worker.get_original(:uk)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when multiple arguments are passed" do
|
122
|
+
it "queries multiple locales" do
|
123
|
+
worker.should_receive(:get_multi).with([:us, :uk])
|
124
|
+
worker.get(:us, :uk)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "#key" do
|
130
|
+
it "returns the Amazon AWS access key for the current locale" do
|
131
|
+
worker.instance_variable_set(:@keys, { :us => 'foo' })
|
132
|
+
|
133
|
+
worker.key.should eql 'foo'
|
134
|
+
end
|
135
|
+
|
136
|
+
it "raises an argument error if key is missing" do
|
137
|
+
worker.instance_variable_get(:@keys)[:us] = nil
|
138
|
+
expect do
|
139
|
+
worker.key
|
140
|
+
end.to raise_error 'AWS access key missing'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "#key=" do
|
145
|
+
it "sets a global Amazon AWS access key" do
|
146
|
+
worker.key = "foo"
|
147
|
+
keys = worker.instance_variable_get(:@keys)
|
148
|
+
|
149
|
+
keys.size.should eql Request::HOSTS.size
|
150
|
+
keys.values.uniq.should eql ["foo"]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "#keys=" do
|
155
|
+
it "sets distinct Amazon AWS access keys for the locales" do
|
156
|
+
keys = {
|
157
|
+
:us => 'foo',
|
158
|
+
:uk => 'bar',
|
159
|
+
:de => 'baz',
|
160
|
+
:ca => 'foo',
|
161
|
+
:fr => 'bar',
|
162
|
+
:jp => 'baz' }
|
163
|
+
worker.keys = keys
|
164
|
+
|
165
|
+
worker.instance_variable_get(:@keys).should eql keys
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#locale" do
|
170
|
+
it "returns the current locale" do
|
171
|
+
worker.locale.should eql :us
|
172
|
+
end
|
173
|
+
|
174
|
+
it "raises an argument error if locale is not set" do
|
175
|
+
worker.instance_variable_set(:@locale, nil)
|
176
|
+
expect do
|
177
|
+
worker.locale
|
178
|
+
end.to raise_error 'Locale not set'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#locale=" do
|
183
|
+
it "sets the current locale" do
|
184
|
+
worker.locale= :uk
|
185
|
+
worker.locale.should eql :uk
|
186
|
+
end
|
187
|
+
|
188
|
+
it "raises an argument error if locale is invalid" do
|
189
|
+
expect do
|
190
|
+
worker.locale= :br
|
191
|
+
end.to raise_error 'Invalid locale'
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# private
|
196
|
+
|
197
|
+
describe "#build_query" do
|
198
|
+
let(:query) do
|
199
|
+
worker.send(:build_query)
|
200
|
+
end
|
201
|
+
|
202
|
+
it "canonicalizes query" do
|
203
|
+
query.should match /Service=([^&]+)&Timestamp=([^&]+)&Version=([^&]+)/
|
204
|
+
end
|
205
|
+
|
206
|
+
it "includes a timestamp" do
|
207
|
+
query.should include 'Timestamp'
|
208
|
+
end
|
209
|
+
|
210
|
+
it "sorts query" do
|
211
|
+
worker.parameters["A"] = "foo"
|
212
|
+
query.should match /^A=foo/
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "#build_signed_query" do
|
217
|
+
let(:query) { worker.send(:build_signed_query) }
|
218
|
+
|
219
|
+
it "includes the key for the current locale" do
|
220
|
+
worker.key = 'foo'
|
221
|
+
query.should include 'AWSAccessKeyId=foo'
|
222
|
+
end
|
223
|
+
|
224
|
+
it "includes the associate tag for the current locale" do
|
225
|
+
worker.associate_tag = 'foo'
|
226
|
+
query.should include 'AssociateTag=foo'
|
227
|
+
end
|
228
|
+
|
229
|
+
it "returns a signed query string" do
|
230
|
+
query = worker.send :build_signed_query
|
231
|
+
query.should include 'Signature='
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "#escape" do
|
236
|
+
it "URL-encodes a string" do
|
237
|
+
worker.send(:escape, 'foo,bar').should eql "foo%2Cbar"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "#get_multi" do
|
242
|
+
it "returns an array of responses" do
|
243
|
+
responses = worker.send(:get_multi, [:us, :uk])
|
244
|
+
|
245
|
+
responses.should be_an_instance_of Array
|
246
|
+
responses.each { |resp| resp.should be_an_instance_of Response }
|
247
|
+
end
|
248
|
+
|
249
|
+
context "when given a block" do
|
250
|
+
it "yields responses" do
|
251
|
+
locales = worker.send(:locales)
|
252
|
+
count = 0
|
253
|
+
worker.send(:get_multi, locales) do |resp|
|
254
|
+
resp.should be_an_instance_of Response
|
255
|
+
count += 1
|
256
|
+
end
|
257
|
+
|
258
|
+
count.should eql locales.size
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "#host" do
|
264
|
+
it "returns a host" do
|
265
|
+
worker.locale = "fr"
|
266
|
+
worker.send(:host).should eql "ecs.amazonaws.fr"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe "#uri" do
|
271
|
+
it "returns the URI with which to query Amazon" do
|
272
|
+
worker.send(:uri).should be_an_instance_of URI::HTTP
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
@@ -2,10 +2,8 @@
|
|
2
2
|
require "spec_helper"
|
3
3
|
|
4
4
|
module Sucker
|
5
|
-
|
6
5
|
describe Response do
|
7
|
-
|
8
|
-
use_vcr_cassette "unit/sucker/response", :record => :new_episodes
|
6
|
+
use_vcr_cassette "spec/sucker/response", :record => :new_episodes
|
9
7
|
|
10
8
|
let(:asins) { ["0816614024", "0143105825"] }
|
11
9
|
|
@@ -17,13 +15,11 @@ module Sucker
|
|
17
15
|
worker << {
|
18
16
|
"Operation" => "ItemLookup",
|
19
17
|
"IdType" => "ASIN",
|
20
|
-
"ResponseGroup" => ["ItemAttributes", "OfferFull"],
|
21
18
|
"ItemId" => asins }
|
22
19
|
worker.get
|
23
20
|
end
|
24
21
|
|
25
22
|
describe ".new" do
|
26
|
-
|
27
23
|
it "initializes the response body" do
|
28
24
|
response.body.should be_an_instance_of String
|
29
25
|
end
|
@@ -39,43 +35,10 @@ module Sucker
|
|
39
35
|
it "initializes the request URI" do
|
40
36
|
response.uri.should be_an_instance_of String
|
41
37
|
end
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "#xml" do
|
46
|
-
|
47
|
-
it "returns a Nokogiri document" do
|
48
|
-
response.xml.should be_an_instance_of Nokogiri::XML::Document
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "#find" do
|
54
|
-
|
55
|
-
context "when there are matches" do
|
56
|
-
|
57
|
-
it "returns an array of matching nodes" do
|
58
|
-
node = response.find("ItemAttributes")
|
59
|
-
node.map { |book| book["ISBN"] }.should eql asins
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
context "when there are no matches" do
|
65
|
-
|
66
|
-
it "returns an empty array" do
|
67
|
-
node = response.find("Foo")
|
68
|
-
node.should eql []
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
38
|
end
|
74
39
|
|
75
40
|
describe "#each" do
|
76
|
-
|
77
41
|
context "when a block is given" do
|
78
|
-
|
79
42
|
it "yields each match to a block" do
|
80
43
|
has_yielded = false
|
81
44
|
|
@@ -86,51 +49,70 @@ module Sucker
|
|
86
49
|
|
87
50
|
has_yielded.should be_true
|
88
51
|
end
|
89
|
-
|
90
52
|
end
|
91
53
|
|
92
54
|
context "when no block is given" do
|
93
|
-
|
94
55
|
it "raises error" do
|
95
56
|
expect do
|
96
57
|
response.each("ItemAttributes")
|
97
58
|
end.to raise_error(LocalJumpError)
|
98
59
|
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when response contains errors" do
|
64
|
+
before do
|
65
|
+
response.body = "<?xml version=\"1.0\" ?><ItemLookupResponse xmlns=\"http://webservices.amazon.com/AWSECommerceService/2010-09-01\"><Errors><Error>foo</Error><Error>bar</Error></Errors>"
|
66
|
+
end
|
99
67
|
|
68
|
+
describe "#errors" do
|
69
|
+
it "returns an array of errors" do
|
70
|
+
response.errors.count.should eql 2
|
71
|
+
end
|
100
72
|
end
|
101
73
|
|
74
|
+
describe "#has_errors?" do
|
75
|
+
it "returns true if the response has errors" do
|
76
|
+
response.should have_errors
|
77
|
+
end
|
78
|
+
end
|
102
79
|
end
|
103
80
|
|
81
|
+
describe "#find" do
|
82
|
+
context "when there are matches" do
|
104
83
|
|
105
|
-
|
84
|
+
it "returns an array of matching nodes" do
|
85
|
+
response.find("ASIN").should eql asins
|
86
|
+
end
|
87
|
+
end
|
106
88
|
|
107
|
-
context "when
|
89
|
+
context "when there are no matches" do
|
90
|
+
it "returns an empty array" do
|
91
|
+
node = response.find("Foo")
|
92
|
+
node.should eql []
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
108
96
|
|
97
|
+
describe "#map" do
|
98
|
+
context "when a block is given" do
|
109
99
|
it "yields each match to a block and maps returned values" do
|
110
|
-
|
111
|
-
eans = response.map("ItemAttributes") { |item| item["EAN"] }
|
100
|
+
titles = response.map("ItemAttributes") { |item| item["Title"] }
|
112
101
|
|
113
|
-
|
114
|
-
eans.each { |ean| ean.match(/^[0-9]{13}$/).should be_true }
|
102
|
+
titles.count.should eql 2
|
115
103
|
end
|
116
|
-
|
117
104
|
end
|
118
105
|
|
119
106
|
context "when no block is given" do
|
120
|
-
|
121
107
|
it "raises error" do
|
122
108
|
expect do
|
123
109
|
response.map("ItemAttributes")
|
124
110
|
end.to raise_error(LocalJumpError)
|
125
111
|
end
|
126
|
-
|
127
112
|
end
|
128
|
-
|
129
113
|
end
|
130
114
|
|
131
|
-
|
132
115
|
describe "#to_hash" do
|
133
|
-
|
134
116
|
it "returns a hash" do
|
135
117
|
response.to_hash.should be_an_instance_of Hash
|
136
118
|
end
|
@@ -154,30 +136,27 @@ module Sucker
|
|
154
136
|
response.body = "<Title>スティーブ・ジョブズ 驚異のプレゼン―人々を惹きつける18の法則</Title>"
|
155
137
|
response.to_hash["Title"].should eql "スティーブ・ジョブズ 驚異のプレゼン―人々を惹きつける18の法則"
|
156
138
|
end
|
157
|
-
|
158
139
|
end
|
159
140
|
|
160
141
|
describe "#valid?" do
|
161
|
-
|
162
142
|
context "when HTTP status is OK" do
|
163
|
-
|
164
143
|
it "returns true" do
|
165
144
|
response.should be_valid
|
166
145
|
end
|
167
|
-
|
168
146
|
end
|
169
147
|
|
170
148
|
context "when HTTP status is not OK" do
|
171
|
-
|
172
149
|
it "returns false" do
|
173
150
|
response.code = 403
|
174
151
|
response.should_not be_valid
|
175
152
|
end
|
176
|
-
|
177
153
|
end
|
178
|
-
|
179
154
|
end
|
180
155
|
|
156
|
+
describe "#xml" do
|
157
|
+
it "returns a Nokogiri document" do
|
158
|
+
response.xml.should be_an_instance_of Nokogiri::XML::Document
|
159
|
+
end
|
160
|
+
end
|
181
161
|
end
|
182
|
-
|
183
162
|
end
|