sucker 1.1.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|