vacuum 0.2.2 → 0.3.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.
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