peddler 1.2.0 → 1.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.
- checksums.yaml +4 -4
- data/README.md +50 -28
- data/lib/mws.rb +2 -0
- data/lib/mws/cart_information/client.rb +7 -6
- data/lib/mws/customer_information/client.rb +6 -6
- data/lib/mws/feeds/client.rb +8 -8
- data/lib/mws/finances/client.rb +6 -6
- data/lib/mws/fulfillment_inbound_shipment/client.rb +41 -40
- data/lib/mws/fulfillment_inventory/client.rb +3 -3
- data/lib/mws/fulfillment_outbound_shipment/client.rb +18 -18
- data/lib/mws/merchant_fulfillment.rb +1 -0
- data/lib/mws/merchant_fulfillment/client.rb +88 -0
- data/lib/mws/off_amazon_payments/client.rb +203 -202
- data/lib/mws/orders/client.rb +6 -6
- data/lib/mws/products/client.rb +38 -38
- data/lib/mws/recommendations/client.rb +4 -4
- data/lib/mws/reports/client.rb +19 -17
- data/lib/mws/sellers/client.rb +2 -2
- data/lib/mws/subscriptions/client.rb +22 -22
- data/lib/mws/webstore/client.rb +8 -8
- data/lib/peddler/client.rb +7 -7
- data/lib/peddler/flat_file_parser.rb +1 -1
- data/lib/peddler/marketplace.rb +2 -2
- data/lib/peddler/operation.rb +7 -12
- data/lib/peddler/vcr_matcher.rb +5 -3
- data/lib/peddler/version.rb +2 -1
- data/test/helper.rb +11 -2
- data/test/integration/test_fulfillment_inbound_shipment.rb +1 -1
- data/test/integration/test_merchant_fulfillment.rb +11 -0
- data/test/integration/test_orders.rb +20 -0
- data/test/unit/mws/test_merchant_fulfillment_client.rb +83 -0
- data/test/unit/peddler/test_client.rb +12 -10
- data/test/unit/peddler/test_vcr_matcher.rb +3 -3
- data/test/vcr_cassettes/MerchantFulfillment.yml +195 -0
- data/test/vcr_cassettes/Orders.yml +1902 -5
- metadata +10 -2
data/lib/mws/webstore/client.rb
CHANGED
@@ -13,7 +13,7 @@ module MWS
|
|
13
13
|
# that your Webstore tracks, can help you determine how many notifications
|
14
14
|
# were converted into sales.
|
15
15
|
class Client < ::Peddler::Client
|
16
|
-
version
|
16
|
+
version '2014-09-01'
|
17
17
|
path "/Webstore/#{version}/"
|
18
18
|
|
19
19
|
# Lists subscription counts of subscriptions in a specified state,
|
@@ -21,8 +21,8 @@ module MWS
|
|
21
21
|
#
|
22
22
|
# @see http://docs.developer.amazonservices.com/en_US/webstore/Webstore_ListSubscriptionsCount.html
|
23
23
|
# @overload list_subscriptions_count(subscription_state, opts = { marketplace_id: primary_marketplace_id })
|
24
|
-
# @param
|
25
|
-
# @param
|
24
|
+
# @param [String] subscription_state
|
25
|
+
# @param [Hash] opts
|
26
26
|
# @option opts [String] :marketplace_id
|
27
27
|
# @option opts [String, #iso8601] :date_range_start
|
28
28
|
# @option opts [String, #iso8601] :date_range_end
|
@@ -43,7 +43,7 @@ module MWS
|
|
43
43
|
# Lists the next page of subscription counts
|
44
44
|
#
|
45
45
|
# @see http://docs.developer.amazonservices.com/en_US/webstore/Webstore_ListSubscriptionsCountByNextToken.html
|
46
|
-
# @param
|
46
|
+
# @param [String] next_token
|
47
47
|
# @return [Peddler::XMLParser]
|
48
48
|
def list_subscriptions_count_by_next_token(next_token)
|
49
49
|
operation('ListSubscriptionsCountByNextToken')
|
@@ -57,10 +57,10 @@ module MWS
|
|
57
57
|
#
|
58
58
|
# @see http://docs.developer.amazonservices.com/en_US/webstore/Webstore_ListSubscriptionsCount.html
|
59
59
|
# @overload get_subscription_details(seller_sku, subscription_state, date_range_start, opts = { marketplace_id: marketplace_id })
|
60
|
-
# @param
|
61
|
-
# @param
|
62
|
-
# @param
|
63
|
-
# @param
|
60
|
+
# @param [String] seller_sku
|
61
|
+
# @param [String] subscription_state
|
62
|
+
# @param [String, #iso8601] date_range_start
|
63
|
+
# @param [Hash] opts
|
64
64
|
# @option opts [String] :marketplace_id
|
65
65
|
# @option opts [String, #iso8601] :date_range_end
|
66
66
|
# @return [Peddler::XMLParser]
|
data/lib/peddler/client.rb
CHANGED
@@ -25,7 +25,7 @@ module Peddler
|
|
25
25
|
# @return [String]
|
26
26
|
attr_reader :body
|
27
27
|
|
28
|
-
|
28
|
+
alias configure tap
|
29
29
|
|
30
30
|
def_delegators :marketplace, :host, :encoding
|
31
31
|
|
@@ -57,8 +57,8 @@ module Peddler
|
|
57
57
|
end
|
58
58
|
|
59
59
|
# Sets an error handler
|
60
|
-
# @yieldparam
|
61
|
-
# @yieldparam
|
60
|
+
# @yieldparam [Excon::Request] request
|
61
|
+
# @yieldparam [Excon::Response] response
|
62
62
|
def on_error(&blk)
|
63
63
|
@error_handler = blk
|
64
64
|
end
|
@@ -77,7 +77,7 @@ module Peddler
|
|
77
77
|
|
78
78
|
# Creates a new client instance
|
79
79
|
#
|
80
|
-
# @param
|
80
|
+
# @param [Hash] opts
|
81
81
|
# @option opts [String] :primary_marketplace_id
|
82
82
|
# @option opts [String] :merchant_id
|
83
83
|
# @option opts [String] :aws_access_key_id
|
@@ -155,8 +155,8 @@ module Peddler
|
|
155
155
|
end
|
156
156
|
|
157
157
|
# Sets an error handler
|
158
|
-
# @yieldparam
|
159
|
-
# @yieldparam
|
158
|
+
# @yieldparam [Excon::Request] request
|
159
|
+
# @yieldparam [Excon::Response] response
|
160
160
|
def on_error(&blk)
|
161
161
|
@error_handler = blk
|
162
162
|
end
|
@@ -224,7 +224,7 @@ module Peddler
|
|
224
224
|
|
225
225
|
def deprecate_error_handler_arguments(e)
|
226
226
|
if error_handler.parameters.size == 2
|
227
|
-
warn
|
227
|
+
warn '[DEPRECATION] Error handler now expects exception as argument.'
|
228
228
|
[e.request, e.response]
|
229
229
|
else
|
230
230
|
[e]
|
@@ -6,7 +6,7 @@ module Peddler
|
|
6
6
|
# @api private
|
7
7
|
class FlatFileParser < SimpleDelegator
|
8
8
|
# http://stackoverflow.com/questions/8073920/importing-csv-quoting-error-is-driving-me-nuts
|
9
|
-
OPTIONS = { col_sep: "\t", quote_char: "\x00", headers: true }
|
9
|
+
OPTIONS = { col_sep: "\t", quote_char: "\x00", headers: true }.freeze
|
10
10
|
|
11
11
|
attr_reader :content, :summary, :encoding
|
12
12
|
|
data/lib/peddler/marketplace.rb
CHANGED
@@ -13,14 +13,14 @@ module Peddler
|
|
13
13
|
'A1VC38T7YXB528' => 'mws.amazonservices.jp',
|
14
14
|
'A1AM78C64UM0Y8' => 'mws.amazonservices.com.mx',
|
15
15
|
'ATVPDKIKX0DER' => 'mws.amazonservices.com'
|
16
|
-
}
|
16
|
+
}.freeze
|
17
17
|
|
18
18
|
BadId = Class.new(StandardError)
|
19
19
|
|
20
20
|
attr_reader :id
|
21
21
|
|
22
22
|
def initialize(id)
|
23
|
-
@id = id
|
23
|
+
@id = id || fail(BadId, 'missing MarketplaceId')
|
24
24
|
end
|
25
25
|
|
26
26
|
def host
|
data/lib/peddler/operation.rb
CHANGED
@@ -21,20 +21,15 @@ module Peddler
|
|
21
21
|
self
|
22
22
|
end
|
23
23
|
|
24
|
-
def store(key, val)
|
24
|
+
def store(key, val, parent: '')
|
25
25
|
key = camelize(key) if key.is_a?(Symbol)
|
26
|
+
key = "#{parent}.#{key}" unless parent.empty?
|
26
27
|
|
27
|
-
if val.respond_to?(:iso8601)
|
28
|
-
|
29
|
-
elsif val.is_a?(Struct)
|
30
|
-
val = val.to_h
|
31
|
-
end
|
28
|
+
val = val.iso8601 if val.respond_to?(:iso8601)
|
29
|
+
val = val.to_h if val.is_a?(Struct)
|
32
30
|
|
33
31
|
if val.is_a?(Hash)
|
34
|
-
val.each
|
35
|
-
subkey = camelize(subkey) if subkey.is_a?(Symbol)
|
36
|
-
store([key, subkey].join('.'), subval)
|
37
|
-
end
|
32
|
+
val.each { |keyval| store(*keyval, parent: key) }
|
38
33
|
else
|
39
34
|
__getobj__.store(key, val)
|
40
35
|
end
|
@@ -45,7 +40,7 @@ module Peddler
|
|
45
40
|
self
|
46
41
|
end
|
47
42
|
|
48
|
-
|
43
|
+
alias add update
|
49
44
|
|
50
45
|
private
|
51
46
|
|
@@ -53,7 +48,7 @@ module Peddler
|
|
53
48
|
sym
|
54
49
|
.to_s
|
55
50
|
.split('_')
|
56
|
-
.map { |token| token ==
|
51
|
+
.map { |token| token == 'sku' ? 'SKU' : token.capitalize }
|
57
52
|
.join
|
58
53
|
end
|
59
54
|
end
|
data/lib/peddler/vcr_matcher.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
module Peddler
|
2
|
+
# A custom matcher that can be used to record MWS interactions when
|
3
|
+
# integration-testing
|
2
4
|
class VCRMatcher
|
3
5
|
TRANSIENT_PARAMS = %w(
|
4
6
|
Signature Timestamp StartDate CreatedAfter QueryStartDateTime
|
5
|
-
)
|
7
|
+
).freeze
|
6
8
|
|
7
9
|
SELLER_PARAMS = %w(
|
8
10
|
AWSAccessKeyId SellerId
|
9
|
-
)
|
11
|
+
).freeze
|
10
12
|
|
11
13
|
class << self
|
12
14
|
def call(*requests)
|
@@ -14,7 +16,7 @@ module Peddler
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def ignored_params
|
17
|
-
@ignored_params ||= TRANSIENT_PARAMS
|
19
|
+
@ignored_params ||= TRANSIENT_PARAMS.dup
|
18
20
|
end
|
19
21
|
|
20
22
|
def ignore_seller!
|
data/lib/peddler/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'simplecov'
|
2
2
|
require 'coveralls'
|
3
|
-
require 'peddler/vcr_matcher'
|
4
3
|
|
5
4
|
SimpleCov.formatters = [
|
6
5
|
SimpleCov::Formatter::HTMLFormatter,
|
@@ -9,10 +8,11 @@ SimpleCov.formatters = [
|
|
9
8
|
|
10
9
|
SimpleCov.start do
|
11
10
|
add_filter '/test/'
|
12
|
-
minimum_coverage(99.62)
|
13
11
|
end
|
14
12
|
|
13
|
+
require 'dig_rb'
|
15
14
|
require 'minitest/autorun'
|
15
|
+
require 'peddler/vcr_matcher'
|
16
16
|
require 'yaml'
|
17
17
|
require 'vcr'
|
18
18
|
begin
|
@@ -71,6 +71,8 @@ VCR.configure do |c|
|
|
71
71
|
c.hook_into :excon
|
72
72
|
c.cassette_library_dir = 'test/vcr_cassettes'
|
73
73
|
|
74
|
+
::Peddler::VCRMatcher.ignore_seller!
|
75
|
+
|
74
76
|
# HTTP errors are not Peddler's concern, so ignore them to ease development.
|
75
77
|
c.before_record do |interaction|
|
76
78
|
code = interaction.response.status.code
|
@@ -85,5 +87,12 @@ VCR.configure do |c|
|
|
85
87
|
Accounts.each do |account|
|
86
88
|
c.filter_sensitive_data('MERCHANT_ID') { account['merchant_id'] }
|
87
89
|
c.filter_sensitive_data('AWS_ACCESS_KEY_ID') { account['aws_access_key_id'] }
|
90
|
+
c.before_record do |interaction|
|
91
|
+
%w(
|
92
|
+
BuyerName BuyerEmail Name AddressLine1 PostalCode Phone Amount
|
93
|
+
).each do |key|
|
94
|
+
interaction.response.body.gsub!(/<#{key}>[^<]+</, "<#{key}>FILTERED<")
|
95
|
+
end
|
96
|
+
end
|
88
97
|
end
|
89
98
|
end
|
@@ -24,7 +24,7 @@ class TestFulfillmentInboundShipment < IntegrationTest
|
|
24
24
|
|
25
25
|
def test_handles_large_requests
|
26
26
|
address = Address.new('John', '1 Main St', 'New York', 'NY', '10001', 'US')
|
27
|
-
items = 100
|
27
|
+
items = Array.new(100) { |i| Item.new(i, 1) }
|
28
28
|
clients.each do |client|
|
29
29
|
res = client.create_inbound_shipment_plan(address, items)
|
30
30
|
assert_equal 200, res.status
|
@@ -2,6 +2,26 @@ require 'helper'
|
|
2
2
|
require 'mws/orders'
|
3
3
|
|
4
4
|
class TestOrders < IntegrationTest
|
5
|
+
def test_gets_orders
|
6
|
+
clients.each do |client|
|
7
|
+
order_ids = client
|
8
|
+
.list_orders(
|
9
|
+
created_after: Date.new(2015),
|
10
|
+
max_results_per_page: 5
|
11
|
+
)
|
12
|
+
.parse
|
13
|
+
.dig('Orders', 'Order')
|
14
|
+
.map { |order| order['AmazonOrderId'] }
|
15
|
+
|
16
|
+
orders = client
|
17
|
+
.get_order(*order_ids)
|
18
|
+
.parse
|
19
|
+
.dig('Orders', 'Order')
|
20
|
+
|
21
|
+
assert_equal order_ids.count, orders.count
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
5
25
|
def test_gets_service_status
|
6
26
|
clients.each do |client|
|
7
27
|
res = client.get_service_status
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'mws/merchant_fulfillment/client'
|
3
|
+
|
4
|
+
class TestMWSMerchantFulfillmentClient < MiniTest::Test
|
5
|
+
def setup
|
6
|
+
@client = MWS::MerchantFulfillment::Client.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_gets_eligible_shipping_services
|
10
|
+
operation = {
|
11
|
+
'Action' => 'GetEligibleShippingServices',
|
12
|
+
'ShipmentRequestDetails.Id' => '123',
|
13
|
+
'ShipmentRequestDetails.Foo.Bar' => 'baz'
|
14
|
+
}
|
15
|
+
|
16
|
+
@client.stub(:run, nil) do
|
17
|
+
shipment_request_details = {
|
18
|
+
id: '123',
|
19
|
+
foo: { bar: 'baz' }
|
20
|
+
}
|
21
|
+
@client.get_eligible_shipping_services(shipment_request_details)
|
22
|
+
end
|
23
|
+
|
24
|
+
assert_equal operation, @client.operation
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_creates_shipment
|
28
|
+
operation = {
|
29
|
+
'Action' => 'CreateShipment',
|
30
|
+
'ShipmentRequestDetails.Id' => '123',
|
31
|
+
'ShipmentRequestDetails.Foo.Bar' => 'baz',
|
32
|
+
'ShippingServiceId' => 'FOO'
|
33
|
+
}
|
34
|
+
|
35
|
+
@client.stub(:run, nil) do
|
36
|
+
shipment_request_details = {
|
37
|
+
id: '123',
|
38
|
+
foo: { bar: 'baz' }
|
39
|
+
}
|
40
|
+
@client.create_shipment(shipment_request_details, 'FOO')
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_equal operation, @client.operation
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_gets_shipment
|
47
|
+
operation = {
|
48
|
+
'Action' => 'GetShipment',
|
49
|
+
'ShipmentId' => '123'
|
50
|
+
}
|
51
|
+
|
52
|
+
@client.stub(:run, nil) do
|
53
|
+
@client.get_shipment('123')
|
54
|
+
end
|
55
|
+
|
56
|
+
assert_equal operation, @client.operation
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_cancels_shipment
|
60
|
+
operation = {
|
61
|
+
'Action' => 'CancelShipment',
|
62
|
+
'ShipmentId' => '123'
|
63
|
+
}
|
64
|
+
|
65
|
+
@client.stub(:run, nil) do
|
66
|
+
@client.cancel_shipment('123')
|
67
|
+
end
|
68
|
+
|
69
|
+
assert_equal operation, @client.operation
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_gets_service_status
|
73
|
+
operation = {
|
74
|
+
'Action' => 'GetServiceStatus'
|
75
|
+
}
|
76
|
+
|
77
|
+
@client.stub(:run, nil) do
|
78
|
+
@client.get_service_status
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_equal operation, @client.operation
|
82
|
+
end
|
83
|
+
end
|
@@ -51,11 +51,11 @@ class TestPeddlerClient < MiniTest::Test
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def test_params_include_seller_id
|
54
|
-
assert @klass.params.key?(
|
54
|
+
assert @klass.params.key?('SellerId')
|
55
55
|
end
|
56
56
|
|
57
57
|
def test_params_include_auth_token
|
58
|
-
@klass.params.key?(
|
58
|
+
@klass.params.key?('MWSAuthToken')
|
59
59
|
end
|
60
60
|
|
61
61
|
def test_configures
|
@@ -114,9 +114,8 @@ class TestPeddlerClient < MiniTest::Test
|
|
114
114
|
assert_equal @body, chunks
|
115
115
|
end
|
116
116
|
|
117
|
-
|
118
|
-
|
119
|
-
class << instrumentor
|
117
|
+
class Instrumentor
|
118
|
+
class << self
|
120
119
|
attr_accessor :events
|
121
120
|
|
122
121
|
def instrument(name, params = {})
|
@@ -124,11 +123,14 @@ class TestPeddlerClient < MiniTest::Test
|
|
124
123
|
yield if block_given?
|
125
124
|
end
|
126
125
|
end
|
127
|
-
instrumentor.events = {}
|
128
126
|
|
129
|
-
@
|
127
|
+
@events = {}
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_request_preserves_user_agent
|
131
|
+
@client.defaults.update(instrumentor: Instrumentor)
|
130
132
|
@client.run
|
131
|
-
headers =
|
133
|
+
headers = Instrumentor.events['excon.request'][:headers]
|
132
134
|
|
133
135
|
assert headers.key?('User-Agent')
|
134
136
|
end
|
@@ -214,8 +216,8 @@ class TestPeddlerClient < MiniTest::Test
|
|
214
216
|
|
215
217
|
def test_deprecated_marketplace_id_accessor
|
216
218
|
refute_nil @client.marketplace_id
|
217
|
-
@client.marketplace_id =
|
218
|
-
assert_equal
|
219
|
+
@client.marketplace_id = '123'
|
220
|
+
assert_equal '123', @client.marketplace_id
|
219
221
|
assert_equal @client.primary_marketplace_id, @client.marketplace_id
|
220
222
|
end
|
221
223
|
end
|
@@ -17,20 +17,20 @@ class TestPeddlerVCRMatcher < MiniTest::Test
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_matches_recorded_post_with_body
|
20
|
-
client.body =
|
20
|
+
client.body = 'content'
|
21
21
|
client.run
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_wont_match_unrecorded_post_with_different_query_and_same_body
|
25
25
|
client.operation.add(foo: 'bar')
|
26
|
-
client.body =
|
26
|
+
client.body = 'content'
|
27
27
|
assert_raises(VCR::Errors::UnhandledHTTPRequestError) do
|
28
28
|
client.run
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_wont_match_unrecorded_post_with_same_query_and_different_body
|
33
|
-
client.body =
|
33
|
+
client.body = 'other content'
|
34
34
|
assert_raises(VCR::Errors::UnhandledHTTPRequestError) do
|
35
35
|
client.run
|
36
36
|
end
|