mws-connect 0.0.1

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 (57) hide show
  1. data/.gitignore +19 -0
  2. data/.sublime-project +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +111 -0
  6. data/Rakefile +1 -0
  7. data/lib/mws.rb +34 -0
  8. data/lib/mws/apis.rb +6 -0
  9. data/lib/mws/apis/feeds.rb +20 -0
  10. data/lib/mws/apis/feeds/api.rb +103 -0
  11. data/lib/mws/apis/feeds/distance.rb +23 -0
  12. data/lib/mws/apis/feeds/feed.rb +114 -0
  13. data/lib/mws/apis/feeds/image_listing.rb +44 -0
  14. data/lib/mws/apis/feeds/inventory.rb +77 -0
  15. data/lib/mws/apis/feeds/measurement.rb +32 -0
  16. data/lib/mws/apis/feeds/money.rb +31 -0
  17. data/lib/mws/apis/feeds/price_listing.rb +48 -0
  18. data/lib/mws/apis/feeds/product.rb +173 -0
  19. data/lib/mws/apis/feeds/sale_price.rb +31 -0
  20. data/lib/mws/apis/feeds/shipping.rb +160 -0
  21. data/lib/mws/apis/feeds/submission_info.rb +45 -0
  22. data/lib/mws/apis/feeds/submission_result.rb +87 -0
  23. data/lib/mws/apis/feeds/transaction.rb +37 -0
  24. data/lib/mws/apis/feeds/weight.rb +19 -0
  25. data/lib/mws/apis/orders.rb +23 -0
  26. data/lib/mws/connection.rb +84 -0
  27. data/lib/mws/enum.rb +81 -0
  28. data/lib/mws/errors.rb +32 -0
  29. data/lib/mws/query.rb +45 -0
  30. data/lib/mws/serializer.rb +81 -0
  31. data/lib/mws/signer.rb +20 -0
  32. data/lib/mws/utils.rb +50 -0
  33. data/mws.gemspec +25 -0
  34. data/scripts/catalog-workflow +136 -0
  35. data/spec/mws/apis/feeds/api_spec.rb +229 -0
  36. data/spec/mws/apis/feeds/distance_spec.rb +43 -0
  37. data/spec/mws/apis/feeds/feed_spec.rb +92 -0
  38. data/spec/mws/apis/feeds/image_listing_spec.rb +109 -0
  39. data/spec/mws/apis/feeds/inventory_spec.rb +135 -0
  40. data/spec/mws/apis/feeds/measurement_spec.rb +84 -0
  41. data/spec/mws/apis/feeds/money_spec.rb +43 -0
  42. data/spec/mws/apis/feeds/price_listing_spec.rb +90 -0
  43. data/spec/mws/apis/feeds/product_spec.rb +264 -0
  44. data/spec/mws/apis/feeds/shipping_spec.rb +78 -0
  45. data/spec/mws/apis/feeds/submission_info_spec.rb +111 -0
  46. data/spec/mws/apis/feeds/submission_result_spec.rb +157 -0
  47. data/spec/mws/apis/feeds/transaction_spec.rb +64 -0
  48. data/spec/mws/apis/feeds/weight_spec.rb +43 -0
  49. data/spec/mws/apis/orders_spec.rb +9 -0
  50. data/spec/mws/connection_spec.rb +331 -0
  51. data/spec/mws/enum_spec.rb +166 -0
  52. data/spec/mws/query_spec.rb +104 -0
  53. data/spec/mws/serializer_spec.rb +187 -0
  54. data/spec/mws/signer_spec.rb +67 -0
  55. data/spec/mws/utils_spec.rb +147 -0
  56. data/spec/spec_helper.rb +10 -0
  57. metadata +220 -0
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+
4
+ module Mws::Apis::Feeds
5
+
6
+ describe SubmissionInfo do
7
+
8
+ let(:submitted_node) do
9
+ Nokogiri::XML::Builder.new do
10
+ FeedSubmissionInfo {
11
+ FeedSubmissionId 5868304010
12
+ FeedType '_POST_PRODUCT_DATA_'
13
+ SubmittedDate '2012-10-16T21:19:08+00:00'
14
+ FeedProcessingStatus '_SUBMITTED_'
15
+ }
16
+ end.doc.root
17
+ end
18
+
19
+ let(:in_progress_node) do
20
+ Nokogiri::XML::Builder.new do
21
+ FeedSubmissionInfo {
22
+ FeedSubmissionId 5868304010
23
+ FeedType '_POST_PRODUCT_DATA_'
24
+ SubmittedDate '2012-10-16T21:19:08+00:00'
25
+ FeedProcessingStatus '_IN_PROGRESS_'
26
+ StartedProcessingDate '2012-10-16T21:21:35+00:00'
27
+ }
28
+ end.doc.root
29
+ end
30
+
31
+ let(:done_node) do
32
+ Nokogiri::XML::Builder.new do
33
+ FeedSubmissionInfo {
34
+ FeedSubmissionId 5868304010
35
+ FeedType '_POST_PRODUCT_DATA_'
36
+ SubmittedDate '2012-10-16T21:19:08+00:00'
37
+ FeedProcessingStatus '_DONE_'
38
+ StartedProcessingDate '2012-10-16T21:21:35+00:00'
39
+ CompletedProcessingDate '2012-10-16T21:23:40+00:00'
40
+ }
41
+ end.doc.root
42
+ end
43
+
44
+ it 'should not allow instance creation via new' do
45
+ expect { SubmissionInfo.new }.to raise_error NoMethodError
46
+ end
47
+
48
+ context '.from_xml' do
49
+
50
+ it 'should be able to create an info object in a submitted state' do
51
+ info = SubmissionInfo.from_xml submitted_node
52
+ info.id.should == "5868304010"
53
+ info.status.should == SubmissionInfo::Status.SUBMITTED.sym
54
+ info.type.should == Feed::Type.PRODUCT.sym
55
+ info.submitted.should == Time.parse('2012-10-16T21:19:08+00:00')
56
+ info.started.should be_nil
57
+ info.completed.should be_nil
58
+ end
59
+
60
+ it 'should be able to create an info object in and in progress state' do
61
+ info = SubmissionInfo.from_xml in_progress_node
62
+ info.id.should == "5868304010"
63
+ info.status.should == SubmissionInfo::Status.IN_PROGRESS.sym
64
+ info.type.should == Feed::Type.PRODUCT.sym
65
+ info.submitted.should == Time.parse('2012-10-16T21:19:08+00:00')
66
+ info.started.should == Time.parse('2012-10-16T21:21:35+00:00')
67
+ info.completed.should be_nil
68
+ end
69
+
70
+ it 'should be able to create an info object in a done state' do
71
+ info = SubmissionInfo.from_xml done_node
72
+ info.id.should == "5868304010"
73
+ info.status.should == SubmissionInfo::Status.DONE.sym
74
+ info.type.should == Feed::Type.PRODUCT.sym
75
+ info.submitted.should == Time.parse('2012-10-16T21:19:08+00:00')
76
+ info.started.should == Time.parse('2012-10-16T21:21:35+00:00')
77
+ info.completed.should == Time.parse('2012-10-16T21:23:40+00:00')
78
+ end
79
+
80
+ end
81
+
82
+ context '#==' do
83
+
84
+ it 'should be reflexive' do
85
+ a = SubmissionInfo.from_xml submitted_node
86
+ (a == a).should be true
87
+ end
88
+
89
+ it 'should be symmetric' do
90
+ a = SubmissionInfo.from_xml submitted_node
91
+ b = SubmissionInfo.from_xml submitted_node
92
+ (a == b).should == (b == a)
93
+ end
94
+
95
+ it 'should be transitive' do
96
+ a = SubmissionInfo.from_xml submitted_node
97
+ b = SubmissionInfo.from_xml submitted_node
98
+ c = SubmissionInfo.from_xml submitted_node
99
+ (a == c).should == (a == b && b == c)
100
+ end
101
+
102
+ it 'should handle comparison to nil' do
103
+ a = SubmissionInfo.from_xml submitted_node
104
+ (a == nil).should be false
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+
4
+ module Mws::Apis::Feeds
5
+
6
+ class SubmissionResult
7
+ attr_reader :responses
8
+ end
9
+
10
+ describe SubmissionResult do
11
+ let(:success_node) do
12
+ Nokogiri::XML::Builder.new do
13
+ Message {
14
+ MessageID 1
15
+ ProcessingReport {
16
+ DocumentTransactionID 5868304010
17
+ StatusCode 'Complete'
18
+ ProcessingSummary {
19
+ MessagesProcessed 1
20
+ MessagesSuccessful 1
21
+ MessagesWithError 0
22
+ MessagesWithWarning 0
23
+ }
24
+ }
25
+ }
26
+ end.doc.root
27
+ end
28
+ let(:error_node) do
29
+ Nokogiri::XML::Builder.new do
30
+ Message {
31
+ MessageID 1
32
+ ProcessingReport {
33
+ DocumentTransactionID 5868304010
34
+ StatusCode 'Complete'
35
+ ProcessingSummary {
36
+ MessagesProcessed 2
37
+ MessagesSuccessful 0
38
+ MessagesWithError 2
39
+ MessagesWithWarning 1
40
+ }
41
+ Result {
42
+ MessageID 1
43
+ ResultCode 'Error'
44
+ ResultMessageCode 8560
45
+ ResultDescription 'Result description 1'
46
+ AdditionalInfo {
47
+ SKU '3455449'
48
+ }
49
+ }
50
+ Result {
51
+ MessageID 2
52
+ ResultCode 'Error'
53
+ ResultMessageCode 5000
54
+ ResultDescription "Result description 2"
55
+ AdditionalInfo {
56
+ SKU '8744969'
57
+ }
58
+ }
59
+ Result {
60
+ MessageID 3
61
+ ResultCode 'Warning'
62
+ ResultMessageCode 5001
63
+ ResultDescription "Result description 3"
64
+ AdditionalInfo {
65
+ SKU '7844970'
66
+ }
67
+ }
68
+ }
69
+ }
70
+ end.doc.root
71
+ end
72
+
73
+ it 'should not allow instance creation via new' do
74
+ expect { SubmissionResult.new }.to raise_error NoMethodError
75
+ end
76
+
77
+ describe '.from_xml' do
78
+
79
+ it 'should be able to be constructed from valid success xml' do
80
+ result = SubmissionResult.from_xml success_node
81
+ result.transaction_id.should == '5868304010'
82
+ result.status.should == SubmissionResult::Status.COMPLETE.sym
83
+ result.messages_processed.should == 1
84
+ result.count_for(:success).should == 1
85
+ result.count_for(:error).should == 0
86
+ result.count_for(:warning).should == 0
87
+ result.responses.should be_empty
88
+ end
89
+
90
+ it 'should be able to be constructed from valid error xml' do
91
+ result = SubmissionResult.from_xml error_node
92
+ result.transaction_id.should == '5868304010'
93
+ result.status.should == SubmissionResult::Status.COMPLETE.sym
94
+ result.messages_processed.should == 2
95
+ result.count_for(:success).should == 0
96
+ result.count_for(:error).should == 2
97
+ result.count_for(:warning).should == 1
98
+ result.responses.size.should == 3
99
+
100
+ response = result.response_for 1
101
+ response.type.should == SubmissionResult::Response::Type.ERROR.sym
102
+ response.code.should == 8560
103
+ response.description == 'Result description 1'
104
+ response.additional_info.should == {
105
+ sku: '3455449'
106
+ }
107
+
108
+
109
+ response = result.response_for 2
110
+ response.type.should == SubmissionResult::Response::Type.ERROR.sym
111
+ response.code.should == 5000
112
+ response.description == 'Result description 2'
113
+ response.additional_info.should == {
114
+ sku: '8744969'
115
+ }
116
+
117
+ response = result.response_for 3
118
+ response.type.should == SubmissionResult::Response::Type.WARNING.sym
119
+ response.code.should == 5001
120
+ response.description == 'Result description 3'
121
+ response.additional_info.should == {
122
+ sku: '7844970'
123
+ }
124
+ end
125
+
126
+ end
127
+
128
+ context '#==' do
129
+
130
+ it 'should be reflexive' do
131
+ a = SubmissionResult.from_xml success_node
132
+ (a == a).should be true
133
+ end
134
+
135
+ it 'should be symmetric' do
136
+ a = SubmissionResult.from_xml success_node
137
+ b = SubmissionResult.from_xml success_node
138
+ (a == b).should == (b == a)
139
+ end
140
+
141
+ it 'should be transitive' do
142
+ a = SubmissionResult.from_xml success_node
143
+ b = SubmissionResult.from_xml success_node
144
+ c = SubmissionResult.from_xml success_node
145
+ (a == c).should == (a == b && b == c)
146
+ end
147
+
148
+ it 'should handle comparison to nil' do
149
+ a = SubmissionResult.from_xml success_node
150
+ (a == nil).should be false
151
+ end
152
+
153
+ end
154
+
155
+ end
156
+
157
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+
4
+ module Mws::Apis::Feeds
5
+
6
+ describe Transaction do
7
+
8
+ let(:submission_info) do
9
+ SubmissionInfo.from_xml(
10
+ Nokogiri::XML::Builder.new do
11
+ FeedSubmissionInfo {
12
+ FeedSubmissionId 5868304010
13
+ FeedType '_POST_PRODUCT_DATA_'
14
+ SubmittedDate '2012-10-16T21:19:08+00:00'
15
+ FeedProcessingStatus '_SUBMITTED_'
16
+ }
17
+ end.doc.root
18
+ )
19
+ end
20
+
21
+ describe '.new' do
22
+
23
+ it 'should be able to create a transaction with no items' do
24
+ transaction = Transaction.new submission_info
25
+ transaction.id.should == "5868304010"
26
+ transaction.status.should == SubmissionInfo::Status.SUBMITTED.sym
27
+ transaction.type.should == Feed::Type.PRODUCT.sym
28
+ transaction.submitted.should == Time.parse('2012-10-16T21:19:08+00:00')
29
+ transaction.items.should be_empty
30
+ end
31
+
32
+ it 'should be able to create a transaction with items' do
33
+ transaction = Transaction.new submission_info do
34
+ item 1, '12345678', :update
35
+ item 2, '87654321', :update, :main
36
+ item 3, '87654321', :delete, :other
37
+ end
38
+
39
+ transaction.items.length.should == 3
40
+
41
+ item = transaction.items[0]
42
+ item.id.should == 1
43
+ item.sku.should == '12345678'
44
+ item.operation.should == :update
45
+ item.qualifier.should be_nil
46
+
47
+ item = transaction.items[1]
48
+ item.id.should == 2
49
+ item.sku.should == '87654321'
50
+ item.operation.should == :update
51
+ item.qualifier.should == :main
52
+
53
+ item = transaction.items[2]
54
+ item.id.should == 3
55
+ item.sku.should == '87654321'
56
+ item.operation.should == :delete
57
+ item.qualifier.should == :other
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Mws::Apis::Feeds
4
+
5
+ describe Weight do
6
+
7
+ context '.new' do
8
+
9
+ it 'should default to pounds' do
10
+ weight = Weight.new 40
11
+ weight.amount.should == 40
12
+ weight.unit.should == :pounds
13
+ end
14
+
15
+ it 'should accept a valid unit override' do
16
+ weight = Weight.new 0, :ounces
17
+ weight.amount.should == 0
18
+ weight.unit.should == :ounces
19
+ end
20
+
21
+ it 'should validate the unit override' do
22
+ expect {
23
+ Weight.new 50, :cent
24
+ }.to raise_error Mws::Errors::ValidationError, "Invalid unit of measure 'cent'"
25
+ end
26
+
27
+ end
28
+
29
+ context '#to_xml' do
30
+
31
+ it 'should properly serialize to XML' do
32
+ weight = Weight.new 25, :grams
33
+ expected = Nokogiri::XML::Builder.new do
34
+ Weight 25, unitOfMeasure: 'GR'
35
+ end.doc.root.to_xml
36
+ weight.to_xml.should == expected
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ module Mws::Apis
4
+
5
+ describe Orders do
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,331 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+
4
+ module Mws
5
+
6
+ class Connection
7
+ attr_reader :scheme, :host, :merchant, :access, :secret
8
+ public :request, :response_for, :parse
9
+ end
10
+
11
+ describe Connection do
12
+
13
+ let(:defaults) {
14
+ {
15
+ merchant: 'GSWCJ4UBA31UTJ',
16
+ access: 'AYQAKIAJSCWMLYXAQ6K3',
17
+ secret: 'Ubzq/NskSrW4m5ncq53kddzBej7O7IE5Yx9drGrX'
18
+ }
19
+ }
20
+
21
+ let(:connection) {
22
+ Mws.connect(defaults)
23
+ }
24
+
25
+ context '.new' do
26
+
27
+ it 'should default scheme to https' do
28
+ connection.scheme.should == 'https'
29
+ end
30
+
31
+ it 'should accept a custom scheme' do
32
+ Connection.new(defaults.merge(scheme: 'http')).scheme.should == 'http'
33
+ end
34
+
35
+ it 'should default host to mws.amazonservices.com' do
36
+ connection.host.should == 'mws.amazonservices.com'
37
+ end
38
+
39
+ it 'should accept a custom host' do
40
+ Connection.new(defaults.merge(host: 'mws.amazonservices.uk')).host.should == 'mws.amazonservices.uk'
41
+ end
42
+
43
+ it 'should require a merchant identifier' do
44
+ expect {
45
+ Connection.new(
46
+ access: defaults[:access],
47
+ secret: defaults[:secret]
48
+ )
49
+ }.to raise_error Mws::Errors::ValidationError, 'A merchant identifier must be specified.'
50
+ end
51
+
52
+ it 'should accept a merchant identifier' do
53
+ connection.merchant.should == 'GSWCJ4UBA31UTJ'
54
+ end
55
+
56
+ it 'should require an access key' do
57
+ expect {
58
+ Connection.new(
59
+ merchant: defaults[:merchant],
60
+ secret: defaults[:secret]
61
+ )
62
+ }.to raise_error Mws::Errors::ValidationError, 'An access key must be specified.'
63
+ end
64
+
65
+ it 'should accept an access key' do
66
+ connection.access.should == 'AYQAKIAJSCWMLYXAQ6K3'
67
+ end
68
+
69
+ it 'should require a secret key' do
70
+ expect {
71
+ Connection.new(
72
+ merchant: defaults[:merchant],
73
+ access: defaults[:access]
74
+ )
75
+ }.to raise_error Mws::Errors::ValidationError, 'A secret key must be specified.'
76
+ end
77
+
78
+ it 'should accept a secret key' do
79
+ connection.secret.should == 'Ubzq/NskSrW4m5ncq53kddzBej7O7IE5Yx9drGrX'
80
+ end
81
+
82
+ end
83
+
84
+ context '#get' do
85
+
86
+ it 'should appropriately delegate to #request' do
87
+ connection.should_receive(:request).with(:get, '/foo', { market: 'ATVPDKIKX0DER' }, nil, { version: 1 })
88
+ connection.get('/foo', { market: 'ATVPDKIKX0DER' }, { version: 1 })
89
+ end
90
+
91
+ end
92
+
93
+ context '#post' do
94
+
95
+ it 'should appropriately delegate to #request' do
96
+ connection.should_receive(:request).with(:post, '/foo', { market: 'ATVPDKIKX0DER' }, 'test_body', { version: 1 })
97
+ connection.post('/foo', { market: 'ATVPDKIKX0DER' }, 'test_body', { version: 1 })
98
+ end
99
+
100
+ end
101
+
102
+ context '#request' do
103
+
104
+ it 'should construct a query, signer and make the request' do
105
+ Query.should_receive(:new).with(
106
+ action: nil,
107
+ version: nil,
108
+ merchant: 'GSWCJ4UBA31UTJ',
109
+ access: 'AYQAKIAJSCWMLYXAQ6K3',
110
+ list_pattern: nil
111
+ ).and_return('the_query')
112
+ signer = double('signer')
113
+ Signer.should_receive(:new).with(
114
+ method: :get,
115
+ host: 'mws.amazonservices.com',
116
+ path: '/foo',
117
+ secret: 'Ubzq/NskSrW4m5ncq53kddzBej7O7IE5Yx9drGrX'
118
+ ).and_return(signer)
119
+ signer.should_receive(:sign).with('the_query').and_return('the_signed_query')
120
+ connection.should_receive(:response_for).with(:get, '/foo', 'the_signed_query', nil).and_return('the_response')
121
+ connection.should_receive(:parse).with('the_response', {})
122
+ connection.request(:get, '/foo', {}, nil, {})
123
+ end
124
+
125
+ it 'should merge additional request parameters into the query' do
126
+ connection = Connection.new(
127
+ merchant: 'GSWCJ4UBA31UTJ',
128
+ access: 'AYQAKIAJSCWMLYXAQ6K3',
129
+ secret: 'Ubzq/NskSrW4m5ncq53kddzBej7O7IE5Yx9drGrX'
130
+ )
131
+ Query.should_receive(:new).with(
132
+ action: nil,
133
+ version: nil,
134
+ merchant: 'GSWCJ4UBA31UTJ',
135
+ access: 'AYQAKIAJSCWMLYXAQ6K3',
136
+ list_pattern: nil,
137
+ foo: 'bar',
138
+ baz: 'quk'
139
+ ).and_return('the_query')
140
+ signer = double('signer')
141
+ Signer.should_receive(:new).with(
142
+ method: :get,
143
+ host: 'mws.amazonservices.com',
144
+ path: '/foo',
145
+ secret: 'Ubzq/NskSrW4m5ncq53kddzBej7O7IE5Yx9drGrX'
146
+ ).and_return(signer)
147
+ signer.should_receive(:sign).with('the_query').and_return('the_signed_query')
148
+ connection.should_receive(:response_for).with(:get, '/foo', 'the_signed_query', nil).and_return('the_response')
149
+ connection.should_receive(:parse).with('the_response', {})
150
+ connection.request(:get, '/foo', { foo: 'bar', baz: 'quk' }, nil, {})
151
+ end
152
+
153
+ it 'should accept overrides to action, version and list_pattern' do
154
+ Query.should_receive(:new).with(
155
+ action: 'SubmitFeed',
156
+ version: '2009-01-01',
157
+ merchant: 'GSWCJ4UBA31UTJ',
158
+ access: 'AYQAKIAJSCWMLYXAQ6K3',
159
+ list_pattern: 'a_list_pattern'
160
+ ).and_return('the_query')
161
+ signer = double('signer')
162
+ Signer.should_receive(:new).with(
163
+ method: :get,
164
+ host: 'mws.amazonservices.com',
165
+ path: '/foo',
166
+ secret: 'Ubzq/NskSrW4m5ncq53kddzBej7O7IE5Yx9drGrX'
167
+ ).and_return(signer)
168
+ signer.should_receive(:sign).with('the_query').and_return('the_signed_query')
169
+ connection.should_receive(:response_for).with(:get, '/foo', 'the_signed_query', nil).and_return('the_response')
170
+ connection.should_receive(:parse).with('the_response', { action: 'SubmitFeed', version: '2009-01-01' })
171
+ connection.request(:get, '/foo', {}, nil, { action: 'SubmitFeed', version: '2009-01-01', list_pattern: 'a_list_pattern' })
172
+ end
173
+
174
+ end
175
+
176
+ context '#parse' do
177
+
178
+ it 'should parse error messages correctly' do
179
+ body = <<-XML
180
+ <?xml version="1.0"?>
181
+ <ErrorResponse xmlns="https://mws.amazonservices.com/Orders/2011-01-01">
182
+ <Error>
183
+ <Type>Sender</Type>
184
+ <Code>InvalidParameterValue</Code>
185
+ <Message>CreatedAfter or LastUpdatedAfter must be specified</Message>
186
+ </Error>
187
+ <RequestId>fb03503e-97e3-4ed1-88e9-d93f4d2111c1</RequestId>
188
+ </ErrorResponse>
189
+ XML
190
+ expect { connection.parse(body, {}) }.to raise_error do | error |
191
+ error.should be_a Errors::ServerError
192
+ error.type.should == 'Sender'
193
+ error.code.should == 'InvalidParameterValue'
194
+ error.message.should == 'CreatedAfter or LastUpdatedAfter must be specified'
195
+ error.details.should == 'None'
196
+ end
197
+ end
198
+
199
+ it 'should parse result based on custom action' do
200
+ body = <<-XML
201
+ <?xml version="1.0"?>
202
+ <ListOrdersResponse xmlns="https://mws.amazonservices.com/Orders/2011-01-01">
203
+ <ListOrdersResult>
204
+ <Orders/>
205
+ <CreatedBefore>2012-11-19T20:54:33Z</CreatedBefore>
206
+ </ListOrdersResult>
207
+ <ResponseMetadata>
208
+ <RequestId>931137cb-add7-4232-ac08-b701435c8447</RequestId>
209
+ </ResponseMetadata>
210
+ </ListOrdersResponse>
211
+ XML
212
+ result = connection.parse(body, action: 'ListOrders').name.should == 'ListOrdersResult'
213
+ end
214
+
215
+ it 'shoudl parse result base on custom xpath' do
216
+ body = <<-XML
217
+ <?xml version="1.0"?>
218
+ <ListOrdersResponse xmlns="https://mws.amazonservices.com/Orders/2011-01-01">
219
+ <ListOrdersResult>
220
+ <Orders/>
221
+ <CreatedBefore>2012-11-19T20:54:33Z</CreatedBefore>
222
+ </ListOrdersResult>
223
+ <ResponseMetadata>
224
+ <RequestId>931137cb-add7-4232-ac08-b701435c8447</RequestId>
225
+ </ResponseMetadata>
226
+ </ListOrdersResponse>
227
+ XML
228
+ result = connection.parse(body, xpath: '/ListOrdersResponse/ListOrdersResult').name.should == 'ListOrdersResult'
229
+ end
230
+
231
+ end
232
+
233
+ context '#response_for' do
234
+
235
+ it 'should properly handle a secure get request' do
236
+ response = double(:response)
237
+ response.should_receive(:body).exactly(3).times.and_return('response_body')
238
+ http = double(:http)
239
+ http.should_receive(:request) do | req |
240
+ req.should be_a Net::HTTP::Get
241
+ req.method.should == 'GET'
242
+ req.path.should == '/?foo=bar'
243
+ req['User-Agent'].should == 'MWS Connect/0.0.1 (Language=Ruby)'
244
+ req['Accept-Encoding'].should == 'text/xml'
245
+ response
246
+ end
247
+ Net::HTTP.should_receive(:start).with('mws.amazonservices.com', 443, use_ssl: true).and_yield(http)
248
+ connection.response_for(:get, '/', 'foo=bar', nil).should == 'response_body'
249
+ end
250
+
251
+ it 'should properly handle an insecure get request' do
252
+ connection = Connection.new(defaults.merge(scheme: 'http'))
253
+ response = double(:response)
254
+ response.should_receive(:body).exactly(3).times.and_return('response_body')
255
+ http = double(:http)
256
+ http.should_receive(:request) do | req |
257
+ req.should be_a Net::HTTP::Get
258
+ req.method.should == 'GET'
259
+ req.path.should == '/?foo=bar'
260
+ req['User-Agent'].should == 'MWS Connect/0.0.1 (Language=Ruby)'
261
+ req['Accept-Encoding'].should == 'text/xml'
262
+ response
263
+ end
264
+ Net::HTTP.should_receive(:start).with('mws.amazonservices.com', 80, use_ssl: false).and_yield(http)
265
+ connection.response_for(:get, '/', 'foo=bar', nil).should == 'response_body'
266
+ end
267
+
268
+ it 'should properly handle requests with transport level errors' do
269
+ response = double(:response)
270
+ response.should_receive(:body).and_return(nil)
271
+ response.should_receive(:code).and_return(500)
272
+ response.should_receive(:msg).and_return('Internal Server Error')
273
+ http = double(:http)
274
+ http.should_receive(:request) do | req |
275
+ req.should be_a Net::HTTP::Get
276
+ req.method.should == 'GET'
277
+ req.path.should == '/?foo=bar'
278
+ req['User-Agent'].should == 'MWS Connect/0.0.1 (Language=Ruby)'
279
+ req['Accept-Encoding'].should == 'text/xml'
280
+ response
281
+ end
282
+ Net::HTTP.should_receive(:start).with('mws.amazonservices.com', 443, use_ssl: true).and_yield(http)
283
+ expect { connection.response_for(:get, '/', 'foo=bar', nil) }.to raise_error do | error |
284
+ error.should be_a Errors::ServerError
285
+ error.type.should == 'Server'
286
+ error.code.should == 500
287
+ error.message.should == 'Internal Server Error'
288
+ error.detail.should == 'None'
289
+ end
290
+ end
291
+
292
+ it 'should properly handle a post without a body' do
293
+ response = double(:response)
294
+ response.should_receive(:body).exactly(3).times.and_return('response_body')
295
+ http = double(:http)
296
+ http.should_receive(:request) do | req |
297
+ req.should be_a Net::HTTP::Post
298
+ req.method.should == 'POST'
299
+ req.path.should == '/?foo=bar'
300
+ req['User-Agent'].should == 'MWS Connect/0.0.1 (Language=Ruby)'
301
+ req['Accept-Encoding'].should == 'text/xml'
302
+ response
303
+ end
304
+ Net::HTTP.should_receive(:start).with('mws.amazonservices.com', 443, use_ssl: true).and_yield(http)
305
+ connection.response_for(:post, '/', 'foo=bar', nil).should == 'response_body'
306
+ end
307
+
308
+ it 'should properly handle a post with a body' do
309
+ response = double(:response)
310
+ response.should_receive(:body).exactly(3).times.and_return('response_body')
311
+ http = double(:http)
312
+ http.should_receive(:request) do | req |
313
+ req.should be_a Net::HTTP::Post
314
+ req.method.should == 'POST'
315
+ req.path.should == '/?foo=bar'
316
+ req.content_type.should == 'text/xml'
317
+ req.body.should == 'request_body'
318
+ req['Content-MD5'] = Digest::MD5.base64digest('request_body').strip
319
+ req['User-Agent'].should == 'MWS Connect/0.0.1 (Language=Ruby)'
320
+ req['Accept-Encoding'].should == 'text/xml'
321
+ response
322
+ end
323
+ Net::HTTP.should_receive(:start).with('mws.amazonservices.com', 443, use_ssl: true).and_yield(http)
324
+ connection.response_for(:post, '/', 'foo=bar', 'request_body').should == 'response_body'
325
+ end
326
+
327
+ end
328
+
329
+ end
330
+
331
+ end