vacuum 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.md +11 -113
  2. data/lib/vacuum/request.rb +66 -0
  3. data/lib/vacuum/version.rb +1 -1
  4. data/lib/vacuum.rb +5 -38
  5. data/test/request_test.rb +18 -0
  6. metadata +24 -96
  7. data/lib/vacuum/endpoint/base.rb +0 -58
  8. data/lib/vacuum/endpoint/mws.rb +0 -59
  9. data/lib/vacuum/endpoint/product_advertising.rb +0 -34
  10. data/lib/vacuum/mws.rb +0 -8
  11. data/lib/vacuum/product_advertising.rb +0 -7
  12. data/lib/vacuum/request/base.rb +0 -109
  13. data/lib/vacuum/request/mws.rb +0 -24
  14. data/lib/vacuum/request/product_advertising.rb +0 -101
  15. data/lib/vacuum/request/signature/authentication.rb +0 -32
  16. data/lib/vacuum/request/signature/builder.rb +0 -70
  17. data/lib/vacuum/request/utils.rb +0 -24
  18. data/lib/vacuum/response/base.rb +0 -57
  19. data/lib/vacuum/response/mws.rb +0 -7
  20. data/lib/vacuum/response/product_advertising.rb +0 -19
  21. data/lib/vacuum/response/utils.rb +0 -48
  22. data/spec/fixtures/product_advertising +0 -1
  23. data/spec/spec_helper.rb +0 -15
  24. data/spec/support/shared_examples/endpoint.rb +0 -43
  25. data/spec/support/shared_examples/request.rb +0 -142
  26. data/spec/support/shared_examples/response.rb +0 -51
  27. data/spec/vacuum/endpoint/base_spec.rb +0 -19
  28. data/spec/vacuum/endpoint/mws_spec.rb +0 -47
  29. data/spec/vacuum/endpoint/product_advertising_spec.rb +0 -25
  30. data/spec/vacuum/request/base_spec.rb +0 -22
  31. data/spec/vacuum/request/mws_spec.rb +0 -26
  32. data/spec/vacuum/request/product_advertising_spec.rb +0 -118
  33. data/spec/vacuum/request/signature/authentication_spec.rb +0 -30
  34. data/spec/vacuum/request/signature/builder_spec.rb +0 -76
  35. data/spec/vacuum/request/utils_spec.rb +0 -23
  36. data/spec/vacuum/response/base_spec.rb +0 -38
  37. data/spec/vacuum/response/product_advertising_spec.rb +0 -57
  38. data/spec/vacuum/response/utils_spec.rb +0 -42
@@ -1,142 +0,0 @@
1
- shared_examples 'a request' do
2
- describe '#connection' do
3
- let(:middleware) do
4
- request.connection.builder.handlers
5
- end
6
-
7
- it 'returns a Faraday Connection' do
8
- request.connection.should be_a Faraday::Connection
9
- end
10
-
11
- it 'adds Signature Authentication to middleware stack' do
12
- middleware.should include Vacuum::Request::Signature::Authentication
13
- end
14
-
15
- it 'yields a builder' do
16
- klass = Class.new Faraday::Middleware
17
- request.connection do |builder|
18
- builder.use klass
19
- end
20
- middleware.should include klass
21
- end
22
- end
23
-
24
- describe '#endpoint' do
25
- it 'returns an AWS API endpoint' do
26
- request.endpoint.should be_a Vacuum::Endpoint::Base
27
- end
28
- end
29
-
30
- describe '#build' do
31
- it 'merges passed key and value pairs into the parameters' do
32
- request.build 'Key' => 'value'
33
- request.parameters['Key'].should eql 'value'
34
- end
35
-
36
- it 'casts Symbol keys to camel-cased String' do
37
- request.build :foo_bar => 'value'
38
- request.parameters.should have_key 'FooBar'
39
- end
40
-
41
- it 'does not modify String keys' do
42
- request.build 'foo_bar' => 'value'
43
- request.parameters.should have_key 'foo_bar'
44
- end
45
-
46
- it 'casts values to String' do
47
- request.build 'Key' => 1
48
- request.parameters['Key'].should eql '1'
49
- end
50
-
51
- it 'concatenates Array values with a comma' do
52
- request.build 'Key' => ['foo', 'bar']
53
- request.parameters['Key'].should eql 'foo,bar'
54
- end
55
-
56
- it 'returns self' do
57
- request.build({}).should eql request
58
- end
59
- end
60
-
61
- describe '#build!' do
62
- it 'clears existing parameters' do
63
- request.build 'Key' => 'value'
64
- request.build!.parameters.should_not have_key 'Key'
65
- end
66
- end
67
-
68
- describe '#configure' do
69
- it 'configures the AWS API endpoint' do
70
- request.configure do |config|
71
- config.locale = 'JP'
72
- end
73
- request.endpoint.locale.should eql 'JP'
74
- end
75
- end
76
-
77
- describe '#get' do
78
- context 'given an implemented url' do
79
- before do
80
- request.stub!(:url).and_return Addressable::URI.parse 'http://example.com'
81
- end
82
-
83
- it 'returns a Response' do
84
- request.get.should be_a Vacuum::Response::Base
85
- end
86
- end
87
- end
88
-
89
- describe '#get!' do
90
- let(:response_class) do
91
- Vacuum::Response.const_get request.send(:class_basename)
92
- end
93
-
94
- context 'when response is bad' do
95
- let(:mock_response) do
96
- body = <<-XML.gsub!(/>\s+</, '><').strip!
97
- <?xml version=\"1.0\" ?>
98
- <ErrorResponse>
99
- <Error>
100
- <Code>RequestThrottled</Code>
101
- <Message>Request from 192.168.0.1 is throttled.</Message>
102
- </Error>
103
- <RequestID>123</RequestID>
104
- </ErrorResponse>
105
- XML
106
-
107
- response_class.new body, 503
108
- end
109
-
110
- before do
111
- request.stub!(:get).and_return mock_response
112
- end
113
-
114
- it 'raises a Bad Response error' do
115
- expect do
116
- request.get!
117
- end.to raise_error Vacuum::BadResponse, '503 RequestThrottled'
118
- end
119
- end
120
-
121
- context 'when response is OK' do
122
- let(:mock_response) do
123
- response_class.new('', 200)
124
- end
125
-
126
- before do
127
- request.stub!(:get).and_return mock_response
128
- end
129
-
130
- it 'returns the response' do
131
- request.get!.should eql mock_response
132
- end
133
- end
134
- end
135
-
136
- describe '#parameters' do
137
- it 'includes default parameters' do
138
- request.parameters.should have_key 'AWSAccessKeyId'
139
- end
140
-
141
- end
142
- end
@@ -1,51 +0,0 @@
1
- shared_examples 'a response' do
2
- let(:child_name) do
3
- response.xml.children.first.name
4
- end
5
-
6
- describe '#find' do
7
- it 'returns an Array of matches' do
8
- response.find(child_name).should_not be_empty
9
- end
10
-
11
- it 'yields matches to a block' do
12
- yielded = false
13
- response.find(child_name) { yielded = true }
14
- yielded.should be_true
15
- end
16
-
17
- it 'is aliased to []' do
18
- response.find(child_name).should eql response[child_name]
19
- end
20
- end
21
-
22
- describe '#to_hash' do
23
- it 'casts response to a hash' do
24
- response.to_hash.should be_a Hash
25
- end
26
- end
27
-
28
- describe '#valid?' do
29
- context 'when HTTP status is OK' do
30
- it 'returns true' do
31
- response.should be_valid
32
- end
33
- end
34
-
35
- context 'when HTTP status is not OK' do
36
- before do
37
- response.code = 403
38
- end
39
-
40
- it 'returns false' do
41
- response.should_not be_valid
42
- end
43
- end
44
- end
45
-
46
- describe '#xml' do
47
- it 'returns a Nokogiri document' do
48
- response.xml.should be_an_instance_of Nokogiri::XML::Document
49
- end
50
- end
51
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Endpoint
5
- describe Base do
6
- let(:endpoint) do
7
- described_class.new
8
- end
9
-
10
- it_behaves_like 'an endpoint'
11
-
12
- describe '#host' do
13
- it 'is not implemented' do
14
- expect { endpoint.host }.to raise_error NotImplementedError
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,47 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Endpoint
5
- describe MWS do
6
- let(:endpoint) do
7
- described_class.new
8
- end
9
-
10
- describe '#host' do
11
- it 'returns a host' do
12
- endpoint.host.should match /amazon/
13
- end
14
- end
15
-
16
- describe '#marketplace' do
17
- it 'requires marketplace ID to have been set' do
18
- expect { endpoint.marketplace }.to raise_error MissingMarketplace
19
- end
20
- end
21
-
22
- describe '#seller' do
23
- it 'requires seller ID to have been set' do
24
- expect { endpoint.seller }.to raise_error MissingSeller
25
- end
26
- end
27
-
28
- describe '#path' do
29
- context 'when API type is set to Products' do
30
- before do
31
- endpoint.api = :products
32
- end
33
-
34
- it 'returns a URL path' do
35
- endpoint.path.should match %r{/\w+/\w+}
36
- end
37
- end
38
-
39
- context 'when API type is not implemented' do
40
- it 'raises a Not Implemented Error' do
41
- expect { endpoint.path }.to raise_error NotImplementedError
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,25 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Endpoint
5
- describe ProductAdvertising do
6
- let(:endpoint) do
7
- described_class.new
8
- end
9
-
10
- it_behaves_like 'an endpoint'
11
-
12
- describe '#host' do
13
- it 'returns a host' do
14
- endpoint.host.should match /amazon/
15
- end
16
- end
17
-
18
- describe '#tag' do
19
- it 'requires tag to have been set' do
20
- expect { endpoint.tag }.to raise_error MissingTag
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,22 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Request
5
- describe Base do
6
- let(:request) do
7
- described_class.new do |config|
8
- config.key = 'key'
9
- config.secret = 'secret'
10
- end
11
- end
12
-
13
- it_behaves_like 'a request'
14
-
15
- describe '#url' do
16
- it 'is not implemented' do
17
- expect { request.url }.to raise_error NotImplementedError
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,26 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Request
5
- describe MWS do
6
- let(:request) do
7
- described_class.new do |config|
8
- config.key = 'key'
9
- config.marketplace = 'marketplace'
10
- config.secret = 'secret'
11
- config.seller = 'seller'
12
- end
13
- end
14
-
15
- context 'when API type is set to Products' do
16
- before do
17
- request.configure do |config|
18
- config.api = :products
19
- end
20
- end
21
-
22
- it_behaves_like 'a request'
23
- end
24
- end
25
- end
26
- end
@@ -1,118 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Request
5
- describe ProductAdvertising do
6
- let(:mock_response) do
7
- Response::ProductAdvertising.new '', 200
8
- end
9
-
10
- let(:request) do
11
- described_class.new do |config|
12
- config.key = 'key'
13
- config.secret = 'secret'
14
- config.tag = 'tag'
15
- end
16
- end
17
-
18
- it_behaves_like 'a request'
19
-
20
- describe '#look_up' do
21
- before do
22
- request.stub!(:get).and_return mock_response
23
- end
24
-
25
- let(:parameters) do
26
- request.parameters
27
- end
28
-
29
- context 'given no items' do
30
- it 'raises an error' do
31
- expect { request.look_up }.to raise_error ArgumentError
32
- end
33
- end
34
-
35
- context 'given up to 10 items' do
36
- before do
37
- request.look_up *((1..10).to_a << { :foo => 'bar' })
38
- end
39
-
40
- it 'builds a single-batch query' do
41
- parameters['ItemId'].split(',').should =~ (1..10).map(&:to_s)
42
- end
43
-
44
- it 'takes parameters' do
45
- parameters['Foo'].should eql 'bar'
46
- end
47
- end
48
-
49
- context 'given 11 to to 20 items' do
50
- before do
51
- request.look_up *((1..20).to_a << {
52
- :foo => 'bar',
53
- :version => 'baz'
54
- })
55
- end
56
-
57
- it 'builds a multi-batch query' do
58
- first = parameters['ItemLookup.1.ItemId'].split(',')
59
- second = parameters['ItemLookup.2.ItemId'].split(',')
60
- (first + second).should =~ (1..20).map(&:to_s)
61
- end
62
-
63
- it 'takes parameters' do
64
- parameters['ItemLookup.Shared.Foo'].should eql 'bar'
65
- end
66
-
67
- it 'overrides version' do
68
- parameters['Version'].should eql 'baz'
69
- end
70
- end
71
-
72
- context 'given over 20 items' do
73
- it 'raises an error' do
74
- expect { request.look_up *(1..21) }.to raise_error ArgumentError
75
- end
76
- end
77
- end
78
-
79
- describe '#search' do
80
- let(:parameters) do
81
- request.parameters
82
- end
83
-
84
- before do
85
- request.stub!(:get).and_return mock_response
86
- end
87
-
88
- context 'when given a search index and a keyword' do
89
- before do
90
- request.search :foo, 'bar'
91
- end
92
-
93
- it 'builds a keyword search' do
94
- parameters['Keywords'].should eql 'bar'
95
- end
96
-
97
- it 'sets the search index' do
98
- parameters['SearchIndex'].should eql 'Foo'
99
- end
100
- end
101
-
102
- context 'when given a search index and parameters' do
103
- before do
104
- request.search(:foo, :bar => 'baz')
105
- end
106
-
107
- it 'sets the parameters' do
108
- parameters['Bar'].should eql 'baz'
109
- end
110
-
111
- it 'sets the search index' do
112
- parameters['SearchIndex'].should eql 'Foo'
113
- end
114
- end
115
- end
116
- end
117
- end
118
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Request
5
- module Signature
6
- describe Authentication do
7
- let(:middleware) do
8
- described_class.new lambda { |env| env }, 'secret'
9
- end
10
-
11
- def result
12
- env = { :url => 'http:://example.com/foo?Baz=2&Bar=1' }
13
- middleware.call env
14
- end
15
-
16
- it 'sorts the query values' do
17
- result[:url].query.should match /^Bar/
18
- end
19
-
20
- it 'timestamps the request' do
21
- result[:url].query.should include 'Timestamp'
22
- end
23
-
24
- it 'signs the request' do
25
- result[:url].query.should include 'Signature'
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,76 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Request
5
- module Signature
6
- describe Builder do
7
- let :url do
8
- Addressable::URI.parse 'http://example.com/foo?bar=1'
9
- end
10
-
11
- let :builder do
12
- described_class.new env, 'secret'
13
- end
14
-
15
- let :env do
16
- { :method => :get, :url => url }
17
- end
18
-
19
- describe '#method' do
20
- it 'returns an HTTP method' do
21
- builder.method.should eql 'GET'
22
- end
23
- end
24
-
25
- describe '#sign' do
26
- it 'signs the request' do
27
- builder.sign
28
- builder.url.query.should include 'Signature='
29
- end
30
- end
31
-
32
- describe '#signature' do
33
- after do
34
- builder.signature
35
- end
36
-
37
- it 'generates an HMAC-SHA signature' do
38
- OpenSSL::HMAC.should_receive(:digest).and_return 'secret'
39
- end
40
-
41
- it 'base64-encodes generated signature' do
42
- Base64.should_receive(:encode64).and_return 'a string'
43
- end
44
- end
45
-
46
- describe '#sort_query' do
47
- it 'sorts query values' do
48
- url.query = 'baz=0&bar=1'
49
- builder.sort_query
50
- builder.url.query.should eql 'bar=1&baz=0'
51
- end
52
- end
53
-
54
- describe '#string_to_sign' do
55
- it 'concatenates the request method, host, path, and query' do
56
- expected_string = %w(GET example.com /foo bar=1).join "\n"
57
- builder.string_to_sign.should eql expected_string
58
- end
59
- end
60
-
61
- describe '#timestamp' do
62
- it 'timestamps the request' do
63
- builder.timestamp
64
- builder.url.query.should include 'Timestamp='
65
- end
66
- end
67
-
68
- describe '#url' do
69
- it 'returns the request URL' do
70
- builder.url.should be_an Addressable::URI
71
- end
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Request
5
- describe Utils do
6
- describe '.camelize' do
7
- it 'camelizes an underscored String' do
8
- Utils.camelize('foo_bar').should eql 'FooBar'
9
- end
10
- end
11
-
12
- describe '.encode' do
13
- it 'encodes reserved characters' do
14
- Utils.encode(',').should eql '%2C'
15
- end
16
-
17
- it 'does not encode unreserved characters' do
18
- Utils.encode('~').should eql '~'
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Response
5
- describe Base do
6
- let(:body) do
7
- '<?xml version="1.0" ?>
8
- <children>
9
- <child>
10
- <name>foo</name>
11
- </child>
12
- <child>
13
- <name>bar</name>
14
- </child>
15
- </children>'.gsub />\s+</, '><'
16
- end
17
-
18
- let(:response) do
19
- described_class.new body, '200'
20
- end
21
-
22
- it_behaves_like 'a response'
23
-
24
- describe '#[]' do
25
- it 'returns an array of matches' do
26
- response.find('child').should_not be_empty
27
- end
28
-
29
- it 'yields matches to a block' do
30
- names = response.find('child') do |child|
31
- child['name']
32
- end
33
- names.should =~ %w(foo bar)
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,57 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Vacuum
4
- module Response
5
- describe ProductAdvertising do
6
- let(:response) do
7
- path = File.expand_path('../../../fixtures/product_advertising', __FILE__)
8
- body = File.read path
9
-
10
- described_class.new body, '200'
11
- end
12
-
13
- it_behaves_like 'a response'
14
-
15
- context 'when Amazon returns errors' do
16
- before do
17
- response.body = <<-EOF.gsub!(/>\s+</, '><').strip!
18
- <?xml version=\"1.0\" ?>
19
- <Response xmlns="http://example.com">
20
- <Errors>
21
- <Error>foo</Error>
22
- </Errors>
23
- </Response>
24
- EOF
25
- end
26
-
27
- describe '#errors' do
28
- it 'returns an Array of errors' do
29
- response.errors.should =~ ['foo']
30
- end
31
- end
32
- end
33
-
34
- describe '#has_errors?' do
35
- context 'when response does not contain any errors' do
36
- before do
37
- response.stub!(:errors).and_return([])
38
- end
39
-
40
- it 'returns false' do
41
- response.should_not have_errors
42
- end
43
- end
44
-
45
- context 'when response contains errors' do
46
- before do
47
- response.stub!(:errors).and_return([1])
48
- end
49
-
50
- it 'returns true' do
51
- response.should have_errors
52
- end
53
- end
54
- end
55
- end
56
- end
57
- end