sucker 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -18
- data/README.md +9 -5
- data/lib/sucker.rb +0 -3
- data/lib/sucker/request.rb +96 -18
- data/lib/sucker/response.rb +20 -14
- data/lib/sucker/version.rb +1 -1
- data/spec/integration/multiple_locales_spec.rb +28 -3
- data/spec/support/vcr.rb +3 -2
- data/spec/unit/sucker/request_spec.rb +109 -29
- data/spec/unit/sucker/response_spec.rb +26 -23
- metadata +23 -137
- data/lib/sucker.rbc +0 -341
- data/lib/sucker/request.rbc +0 -2481
- data/lib/sucker/response.rbc +0 -1554
- data/lib/sucker/version.rbc +0 -130
- data/spec/fixtures/cassette_library/integration/alternate_versions.yml +0 -27
- data/spec/fixtures/cassette_library/integration/errors.yml +0 -27
- data/spec/fixtures/cassette_library/integration/france.yml +0 -27
- data/spec/fixtures/cassette_library/integration/images.yml +0 -27
- data/spec/fixtures/cassette_library/integration/item_lookup/multiple.yml +0 -27
- data/spec/fixtures/cassette_library/integration/item_lookup/single.yml +0 -27
- data/spec/fixtures/cassette_library/integration/item_search.yml +0 -27
- data/spec/fixtures/cassette_library/integration/japan.yml +0 -27
- data/spec/fixtures/cassette_library/integration/keyword_search.yml +0 -27
- data/spec/fixtures/cassette_library/integration/kindle.yml +0 -27
- data/spec/fixtures/cassette_library/integration/kindle_2.yml +0 -27
- data/spec/fixtures/cassette_library/integration/multiple_locales.yml +0 -157
- data/spec/fixtures/cassette_library/integration/power_search.yml +0 -27
- data/spec/fixtures/cassette_library/integration/related_items/child.yml +0 -27
- data/spec/fixtures/cassette_library/integration/related_items/parent.yml +0 -27
- data/spec/fixtures/cassette_library/integration/seller_listings_search.yml +0 -27
- data/spec/fixtures/cassette_library/integration/twenty_items.yml +0 -27
- data/spec/fixtures/cassette_library/unit/sucker/request.yml +0 -29
- data/spec/fixtures/cassette_library/unit/sucker/response.yml +0 -27
- data/spec/integration/alternate_versions_spec.rbc +0 -843
- data/spec/integration/errors_spec.rbc +0 -964
- data/spec/integration/france_spec.rbc +0 -1012
- data/spec/integration/images_spec.rbc +0 -1047
- data/spec/integration/item_lookup_spec.rbc +0 -1723
- data/spec/integration/item_search_spec.rbc +0 -926
- data/spec/integration/japan_spec.rbc +0 -849
- data/spec/integration/keyword_search_spec.rbc +0 -838
- data/spec/integration/kindle_spec.rbc +0 -1425
- data/spec/integration/multiple_locales_spec.rbc +0 -1090
- data/spec/integration/power_search_spec.rbc +0 -838
- data/spec/integration/related_items_spec.rbc +0 -1228
- data/spec/integration/seller_listing_search_spec.rbc +0 -852
- data/spec/integration/twenty_items_spec.rbc +0 -1166
- data/spec/spec_helper.rbc +0 -231
- data/spec/support/amazon.yml +0 -3
- data/spec/support/amazon_credentials.rbc +0 -154
- data/spec/support/asins.rbc +0 -335
- data/spec/support/vcr.rbc +0 -360
- data/spec/unit/sucker/request_spec.rbc +0 -4031
- data/spec/unit/sucker/response_spec.rbc +0 -3787
- data/spec/unit/sucker_spec.rbc +0 -299
data/CHANGELOG.md
CHANGED
@@ -1,34 +1,25 @@
|
|
1
|
-
Version 1.
|
1
|
+
Version 1.1.0
|
2
2
|
=============
|
3
3
|
|
4
|
-
|
4
|
+
* Removed Request#get!. Bloat.
|
5
|
+
* Added Request#get_all to fetch responses from all venues
|
6
|
+
simultaneously.
|
7
|
+
* Added Request#associate_tags= to set associate tags for all locales.
|
8
|
+
* Added Request#keys= to set distinct keys for locales.
|
9
|
+
* Request#get validates presence of key and locale.
|
5
10
|
|
6
|
-
|
7
|
-
|
11
|
+
Version 1.0.0
|
12
|
+
=============
|
8
13
|
|
9
14
|
* Added #each and #map to Response. #find no longer yields.
|
10
15
|
|
11
16
|
Version 1.0.0.beta4
|
12
17
|
===================
|
13
18
|
|
14
|
-
Release date: 2010-10-28
|
15
|
-
|
16
|
-
Added
|
17
|
-
-----
|
18
|
-
|
19
19
|
* Sucker::Request#get! raises an error if response is not valid.
|
20
20
|
|
21
21
|
Version 1.0.0.beta3
|
22
22
|
===================
|
23
23
|
|
24
|
-
Release date: 2010-10-25
|
25
|
-
|
26
|
-
Added
|
27
|
-
-----
|
28
|
-
|
29
24
|
* Sucker::Response#find yields to a block if given one.
|
30
|
-
|
31
|
-
Deprecated
|
32
|
-
----------
|
33
|
-
|
34
25
|
* Renamed #node to #find
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Sucker
|
2
2
|
======
|
3
3
|
|
4
|
-
Sucker is a Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on [curb](http://github.com/taf2/curb) and [the Nokogiri implementation of the XML Mini module](http://github.com/rails/rails/blob/master/activesupport/lib/active_support/xml_mini/nokogiri.rb) in Active Support. It's fast and supports __the entire API__.
|
4
|
+
Sucker is a minimal Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on [curb](http://github.com/taf2/curb) and [the Nokogiri implementation of the XML Mini module](http://github.com/rails/rails/blob/master/activesupport/lib/active_support/xml_mini/nokogiri.rb) in Active Support. It's fast and supports __the entire API__.
|
5
5
|
|
6
|
-
![
|
6
|
+
![Electrolux](http://github.com/papercavalier/sucker/raw/master/electrolux.jpg)
|
7
7
|
|
8
8
|
Examples
|
9
9
|
--------
|
@@ -43,10 +43,14 @@ Iterate over items in your item lookup.
|
|
43
43
|
|
44
44
|
response.each("Item") { |item| ... }
|
45
45
|
|
46
|
-
|
46
|
+
Map errors to a block.
|
47
47
|
|
48
48
|
errors = response.map("Error") { |error| ... }
|
49
49
|
|
50
|
+
Or simply get a hash of matching items.
|
51
|
+
|
52
|
+
items = response.find("Item")
|
53
|
+
|
50
54
|
Repeat ad infinitum.
|
51
55
|
|
52
56
|
Check my [integration specs](http://github.com/papercavalier/sucker/tree/master/spec/integration/) for more examples. See [twenty items](http://github.com/papercavalier/sucker/tree/master/spec/integration/twenty_items_spec.rb) and [multiple locales](http://github.com/papercavalier/sucker/tree/master/spec/integration/multiple_locales_spec.rb) for relatively advanced usage.
|
@@ -58,12 +62,12 @@ Stubbing
|
|
58
62
|
|
59
63
|
Use [VCR](http://github.com/myronmarston/vcr) to stub your requests.
|
60
64
|
|
61
|
-
Caveat: Match URIs on host only and create a new cassette for each query. [This is how
|
65
|
+
Caveat: Match URIs on host only and create a new cassette for each query. [This is how my VCR helper looks like.](http://github.com/papercavalier/sucker/blob/master/spec/support/vcr.rb).
|
62
66
|
|
63
67
|
Compatibility
|
64
68
|
-------------
|
65
69
|
|
66
|
-
Specs pass against Ruby 1.8.7
|
70
|
+
Specs pass against Ruby 1.8.7 and Ruby 1.9.2.
|
67
71
|
|
68
72
|
Sucker works seamlessly with or without Rails.
|
69
73
|
|
data/lib/sucker.rb
CHANGED
data/lib/sucker/request.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require "curb"
|
2
|
+
require "ostruct"
|
3
|
+
require "uri"
|
4
|
+
|
1
5
|
module Sucker #:nodoc:
|
2
6
|
|
3
7
|
# A wrapper around the API request
|
@@ -49,56 +53,125 @@ module Sucker #:nodoc:
|
|
49
53
|
self.parameters.merge!(hash)
|
50
54
|
end
|
51
55
|
|
52
|
-
#
|
56
|
+
# Returns the associate tag for the current locale
|
57
|
+
def associate_tag
|
58
|
+
@associate_tags[locale.to_sym] rescue nil
|
59
|
+
end
|
60
|
+
|
61
|
+
# Sets the associate tag for the current locale
|
53
62
|
#
|
54
63
|
# worker = Sucker.new
|
55
64
|
# worker.associate_tag = 'foo-bar'
|
56
65
|
#
|
57
66
|
def associate_tag=(token)
|
58
|
-
|
67
|
+
@associate_tags = HOSTS.keys.inject({}) do |tags, loc|
|
68
|
+
tags[loc] = token
|
69
|
+
tags
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Sets associate tags for all locales
|
74
|
+
#
|
75
|
+
# tags = {
|
76
|
+
# :us => 'foo-bar-10',
|
77
|
+
# :uk => 'foo-bar-20',
|
78
|
+
# :de => 'foo-bar-30',
|
79
|
+
# ... }
|
80
|
+
#
|
81
|
+
# worker = Sucker.new
|
82
|
+
# worker.associate_tags = tags
|
83
|
+
#
|
84
|
+
def associate_tags=(tokens)
|
85
|
+
@associate_tags = tokens
|
59
86
|
end
|
60
87
|
|
61
|
-
#
|
88
|
+
# Returns options for curl and yields them if given a block
|
62
89
|
#
|
63
90
|
# worker = Sucker.new
|
64
91
|
# worker.curl { |c| c.interface = "eth1" }
|
65
92
|
#
|
66
|
-
def
|
67
|
-
@
|
68
|
-
yield @
|
69
|
-
|
93
|
+
def curl_opts
|
94
|
+
@curl_opts ||= CurlOptions.new
|
95
|
+
yield @curl_opts if block_given?
|
96
|
+
|
97
|
+
@curl_opts.marshal_dump
|
70
98
|
end
|
71
99
|
|
72
|
-
# Performs
|
100
|
+
# Performs a request and returns a response
|
73
101
|
#
|
74
102
|
# worker = Sucker.new
|
75
103
|
# response = worker.get
|
76
104
|
#
|
77
105
|
def get
|
78
|
-
|
79
|
-
|
106
|
+
raise ArgumentError.new "Locale missing" unless locale
|
107
|
+
raise ArgumentError.new "AWS access key missing" unless key
|
108
|
+
|
109
|
+
curl = Curl::Easy.perform(uri.to_s) do |easy|
|
110
|
+
curl_opts.each { |k, v| easy.send(k, v) }
|
111
|
+
end
|
80
112
|
|
81
113
|
Response.new(curl)
|
82
114
|
end
|
83
115
|
|
84
|
-
#
|
85
|
-
|
86
|
-
|
116
|
+
# Performs a request for all locales, returns an array of responses, and
|
117
|
+
# yields them if given a block
|
118
|
+
#
|
119
|
+
# worker = Sucker.new
|
120
|
+
#
|
121
|
+
# # This blocks until all requests are complete
|
122
|
+
# responses = worker.get_all
|
123
|
+
#
|
124
|
+
# # This does not block
|
125
|
+
# worker.get_all do |response|
|
126
|
+
# process_response
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
def get_all
|
130
|
+
uris = HOSTS.keys.map do |locale|
|
131
|
+
self.locale = locale
|
132
|
+
uri.to_s
|
133
|
+
end
|
134
|
+
responses = []
|
87
135
|
|
88
|
-
|
89
|
-
|
136
|
+
Curl::Multi.get(uris, curl_opts) do |curl|
|
137
|
+
response = Response.new(curl)
|
138
|
+
yield response if block_given?
|
139
|
+
responses << response
|
90
140
|
end
|
91
141
|
|
92
|
-
|
142
|
+
responses
|
93
143
|
end
|
94
144
|
|
95
|
-
#
|
145
|
+
# Returns the AWS access key for the current locale
|
146
|
+
def key
|
147
|
+
@keys[locale.to_sym]
|
148
|
+
end
|
149
|
+
|
150
|
+
# Sets a global AWS access key ID
|
96
151
|
#
|
97
152
|
# worker = Sucker.new
|
98
153
|
# worker.key = 'foo'
|
99
154
|
#
|
100
155
|
def key=(token)
|
101
|
-
|
156
|
+
@keys = HOSTS.keys.inject({}) do |keys, locale|
|
157
|
+
keys[locale] = token
|
158
|
+
keys
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Sets distinct AWS access keys for the locales
|
163
|
+
#
|
164
|
+
# keys = {
|
165
|
+
# :us => 'foo',
|
166
|
+
# :uk => 'bar',
|
167
|
+
# :de => 'baz',
|
168
|
+
# ... }
|
169
|
+
#
|
170
|
+
# worker = Sucker.new
|
171
|
+
# worker.keys = keys
|
172
|
+
#
|
173
|
+
def keys=(tokens)
|
174
|
+
@keys = tokens
|
102
175
|
end
|
103
176
|
|
104
177
|
# Sets the Amazon API version
|
@@ -116,6 +189,8 @@ module Sucker #:nodoc:
|
|
116
189
|
def build_query
|
117
190
|
parameters.
|
118
191
|
merge(timestamp).
|
192
|
+
merge({ "AWSAccessKeyId" => key }).
|
193
|
+
merge({ "AssociateTag" => associate_tag }).
|
119
194
|
sort.
|
120
195
|
collect do |k, v|
|
121
196
|
"#{k}=" + escape(v.is_a?(Array) ? v.join(",") : v.to_s)
|
@@ -156,4 +231,7 @@ module Sucker #:nodoc:
|
|
156
231
|
{ "Timestamp" => Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ') }
|
157
232
|
end
|
158
233
|
end
|
234
|
+
|
235
|
+
# Curl options
|
236
|
+
class CurlOptions < OpenStruct; end
|
159
237
|
end
|
data/lib/sucker/response.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "active_support/xml_mini/nokogiri"
|
2
|
+
|
1
3
|
module Sucker #:nodoc:
|
2
4
|
|
3
5
|
# A Nokogiri-driven wrapper around the cURL response
|
@@ -12,19 +14,23 @@ module Sucker #:nodoc:
|
|
12
14
|
# Transaction time in seconds for request
|
13
15
|
attr_accessor :time
|
14
16
|
|
17
|
+
# The request URI
|
18
|
+
attr_accessor :uri
|
19
|
+
|
15
20
|
def initialize(curl)
|
16
21
|
self.body = curl.body_str
|
17
22
|
self.code = curl.response_code
|
18
23
|
self.time = curl.total_time
|
24
|
+
self.uri = curl.url
|
19
25
|
end
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
# A shorthand that yields each match to a block
|
28
|
+
#
|
29
|
+
# worker.get.each("Item") { |item| process(item) }
|
30
|
+
#
|
31
|
+
def each(path)
|
32
|
+
find(path).each { |e| yield e }
|
33
|
+
end
|
28
34
|
|
29
35
|
# Queries an xpath and returns an array of matching nodes
|
30
36
|
#
|
@@ -32,15 +38,15 @@ module Sucker #:nodoc:
|
|
32
38
|
# response.find("Item").each { |item| ... }
|
33
39
|
#
|
34
40
|
def find(path)
|
35
|
-
xml.xpath("//xmlns:#{path}").map { |
|
41
|
+
xml.xpath("//xmlns:#{path}").map { |e| strip_content(e.to_hash[path]) }
|
36
42
|
end
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
+
# A shorthand that yields matches to a block and collects returned values
|
45
|
+
#
|
46
|
+
# descriptions = worker.get.map("Item") { |item| build_description(item) }
|
47
|
+
#
|
48
|
+
def map(path)
|
49
|
+
find(path).map { |e| yield e }
|
44
50
|
end
|
45
51
|
|
46
52
|
def node(path) # :nodoc:
|
data/lib/sucker/version.rb
CHANGED
@@ -5,11 +5,36 @@ module Sucker
|
|
5
5
|
|
6
6
|
describe "Item lookup" do
|
7
7
|
|
8
|
-
|
8
|
+
use_vcr_cassette "integration/multiple_locales", :record => :new_episodes
|
9
9
|
|
10
|
-
|
10
|
+
context "when using Curl::Multi to search all locales simultaneously" do
|
11
11
|
|
12
|
-
it "returns matches
|
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
|
+
# Leaving this spec here for reference purposes. Use approach in above spec.
|
36
|
+
|
37
|
+
it "returns matches for all locales" do
|
13
38
|
locales = %w{us uk de ca fr jp}
|
14
39
|
|
15
40
|
params = {
|
data/spec/support/vcr.rb
CHANGED
@@ -2,10 +2,11 @@ require 'vcr'
|
|
2
2
|
|
3
3
|
VCR.config do |c|
|
4
4
|
c.cassette_library_dir = File.dirname(__FILE__) + '/../fixtures/cassette_library'
|
5
|
-
c.http_stubbing_library = :webmock
|
6
5
|
c.default_cassette_options = {
|
7
|
-
:record => :
|
6
|
+
:record => :none,
|
8
7
|
:match_requests_on => [:host] }
|
8
|
+
|
9
|
+
c.stub_with :webmock
|
9
10
|
end
|
10
11
|
|
11
12
|
RSpec.configure do |config|
|
@@ -42,60 +42,134 @@ module Sucker
|
|
42
42
|
|
43
43
|
end
|
44
44
|
|
45
|
-
describe "#associate_tag
|
45
|
+
describe "#associate_tag" do
|
46
46
|
|
47
|
-
it "
|
48
|
-
worker.
|
49
|
-
|
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
|
50
55
|
end
|
51
56
|
|
52
57
|
end
|
53
58
|
|
54
|
-
describe "#
|
59
|
+
describe "#associate_tags=" do
|
55
60
|
|
56
|
-
it "
|
57
|
-
|
61
|
+
it "sets associate tags for the locales" do
|
62
|
+
tags = {
|
63
|
+
:us => 'foo',
|
64
|
+
:uk => 'bar',
|
65
|
+
:de => 'baz',
|
66
|
+
:ca => 'foo',
|
67
|
+
:fr => 'bar',
|
68
|
+
:jp => 'baz' }
|
69
|
+
worker.associate_tags = tags
|
70
|
+
|
71
|
+
worker.instance_variable_get(:@associate_tags).should eql tags
|
58
72
|
end
|
59
73
|
|
60
|
-
|
74
|
+
end
|
61
75
|
|
62
|
-
|
63
|
-
worker.curl.interface.should be_nil
|
76
|
+
describe "#curl_opts" do
|
64
77
|
|
65
|
-
|
78
|
+
it "returns options for curl" do
|
79
|
+
worker.curl_opts.should be_an_instance_of Hash
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when given a block" do
|
66
83
|
|
67
|
-
|
84
|
+
it "yields options for curl" do
|
85
|
+
worker.curl_opts { |c| c.interface = "eth1" }
|
86
|
+
|
87
|
+
worker.curl_opts[:interface].should eql "eth1"
|
68
88
|
end
|
69
89
|
|
70
90
|
end
|
71
91
|
|
72
92
|
end
|
73
93
|
|
74
|
-
describe "#get
|
94
|
+
describe "#get" do
|
95
|
+
|
96
|
+
it "returns a response" do
|
97
|
+
worker.get.class.ancestors.should include Response
|
98
|
+
end
|
75
99
|
|
76
|
-
it "raises if
|
77
|
-
worker
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
lambda { worker.get! }.should raise_error ResponseError
|
100
|
+
it "raises an argument error if no key is provided" do
|
101
|
+
worker.key = nil
|
102
|
+
expect do
|
103
|
+
worker.get
|
104
|
+
end.to raise_error(/AWS access key missing/)
|
82
105
|
end
|
83
106
|
|
107
|
+
it "raises an argument error if no locale is provided" do
|
108
|
+
worker.locale = nil
|
109
|
+
expect do
|
110
|
+
worker.get
|
111
|
+
end.to raise_error(/Locale missing/)
|
112
|
+
end
|
84
113
|
end
|
85
114
|
|
86
|
-
describe "#
|
115
|
+
describe "#get_all" do
|
87
116
|
|
88
|
-
it "returns
|
89
|
-
worker.
|
117
|
+
it "returns an array of responses" do
|
118
|
+
responses = worker.get_all
|
119
|
+
|
120
|
+
responses.should be_an_instance_of Array
|
121
|
+
responses.each { |resp| resp.should be_an_instance_of Response }
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when given a block" do
|
125
|
+
|
126
|
+
it "yields responses" do
|
127
|
+
count = 0
|
128
|
+
worker.get_all do |resp|
|
129
|
+
resp.should be_an_instance_of Response
|
130
|
+
count += 1
|
131
|
+
end
|
132
|
+
|
133
|
+
count.should eql Request::HOSTS.size
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#key" do
|
139
|
+
|
140
|
+
it "returns the Amazon AWS access key for the current locale" do
|
141
|
+
worker.instance_variable_set(:@keys, { :us => 'foo' })
|
142
|
+
|
143
|
+
worker.key.should eql 'foo'
|
90
144
|
end
|
91
145
|
|
92
146
|
end
|
93
147
|
|
94
148
|
describe "#key=" do
|
95
149
|
|
96
|
-
it "sets
|
150
|
+
it "sets a global Amazon AWS access key" do
|
97
151
|
worker.key = "foo"
|
98
|
-
worker.
|
152
|
+
keys = worker.instance_variable_get(:@keys)
|
153
|
+
|
154
|
+
keys.size.should eql Request::HOSTS.size
|
155
|
+
keys.values.uniq.should eql ["foo"]
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "#keys=" do
|
161
|
+
|
162
|
+
it "sets distinct Amazon AWS access keys for the locales" do
|
163
|
+
keys = {
|
164
|
+
:us => 'foo',
|
165
|
+
:uk => 'bar',
|
166
|
+
:de => 'baz',
|
167
|
+
:ca => 'foo',
|
168
|
+
:fr => 'bar',
|
169
|
+
:jp => 'baz' }
|
170
|
+
worker.keys = keys
|
171
|
+
|
172
|
+
worker.instance_variable_get(:@keys).should eql keys
|
99
173
|
end
|
100
174
|
|
101
175
|
end
|
@@ -104,32 +178,38 @@ module Sucker
|
|
104
178
|
|
105
179
|
describe "#build_query" do
|
106
180
|
|
181
|
+
let(:query) { worker.send(:build_query) }
|
182
|
+
|
107
183
|
it "canonicalizes parameters" do
|
108
|
-
query = worker.send(:build_query)
|
109
184
|
query.should match /Service=([^&]+)&Timestamp=([^&]+)&Version=([^&]+)/
|
110
185
|
end
|
111
186
|
|
187
|
+
it "includes the key for the current locale" do
|
188
|
+
worker.instance_variable_set(:@keys, { :us => 'foo' })
|
189
|
+
query.should include 'AWSAccessKeyId=foo'
|
190
|
+
end
|
191
|
+
|
192
|
+
it "includes a timestamp" do
|
193
|
+
query.should include 'Timestamp='
|
194
|
+
end
|
195
|
+
|
112
196
|
it "sorts parameters" do
|
113
197
|
worker.parameters["AAA"] = "foo"
|
114
|
-
query = worker.send(:build_query)
|
115
198
|
query.should match /^AAA=foo/
|
116
199
|
end
|
117
200
|
|
118
201
|
it "converts a parameter whose value is an array to a string" do
|
119
202
|
worker.parameters["Foo"] = ["bar", "baz"]
|
120
|
-
query = worker.send(:build_query)
|
121
203
|
query.should match /Foo=bar%2Cbaz/
|
122
204
|
end
|
123
205
|
|
124
206
|
it "handles integer parameter values" do
|
125
207
|
worker.parameters["Foo"] = 1
|
126
|
-
query = worker.send(:build_query)
|
127
208
|
query.should match /Foo=1/
|
128
209
|
end
|
129
210
|
|
130
211
|
it "handles floating-point parameter values" do
|
131
212
|
worker.parameters["Foo"] = 1.0
|
132
|
-
query = worker.send(:build_query)
|
133
213
|
query.should match /Foo=1/
|
134
214
|
end
|
135
215
|
|