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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +50 -28
  3. data/lib/mws.rb +2 -0
  4. data/lib/mws/cart_information/client.rb +7 -6
  5. data/lib/mws/customer_information/client.rb +6 -6
  6. data/lib/mws/feeds/client.rb +8 -8
  7. data/lib/mws/finances/client.rb +6 -6
  8. data/lib/mws/fulfillment_inbound_shipment/client.rb +41 -40
  9. data/lib/mws/fulfillment_inventory/client.rb +3 -3
  10. data/lib/mws/fulfillment_outbound_shipment/client.rb +18 -18
  11. data/lib/mws/merchant_fulfillment.rb +1 -0
  12. data/lib/mws/merchant_fulfillment/client.rb +88 -0
  13. data/lib/mws/off_amazon_payments/client.rb +203 -202
  14. data/lib/mws/orders/client.rb +6 -6
  15. data/lib/mws/products/client.rb +38 -38
  16. data/lib/mws/recommendations/client.rb +4 -4
  17. data/lib/mws/reports/client.rb +19 -17
  18. data/lib/mws/sellers/client.rb +2 -2
  19. data/lib/mws/subscriptions/client.rb +22 -22
  20. data/lib/mws/webstore/client.rb +8 -8
  21. data/lib/peddler/client.rb +7 -7
  22. data/lib/peddler/flat_file_parser.rb +1 -1
  23. data/lib/peddler/marketplace.rb +2 -2
  24. data/lib/peddler/operation.rb +7 -12
  25. data/lib/peddler/vcr_matcher.rb +5 -3
  26. data/lib/peddler/version.rb +2 -1
  27. data/test/helper.rb +11 -2
  28. data/test/integration/test_fulfillment_inbound_shipment.rb +1 -1
  29. data/test/integration/test_merchant_fulfillment.rb +11 -0
  30. data/test/integration/test_orders.rb +20 -0
  31. data/test/unit/mws/test_merchant_fulfillment_client.rb +83 -0
  32. data/test/unit/peddler/test_client.rb +12 -10
  33. data/test/unit/peddler/test_vcr_matcher.rb +3 -3
  34. data/test/vcr_cassettes/MerchantFulfillment.yml +195 -0
  35. data/test/vcr_cassettes/Orders.yml +1902 -5
  36. metadata +10 -2
@@ -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 "2014-09-01"
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 subscription_state [String]
25
- # @param opts [Hash]
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 next_token [String]
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 seller_sku [String]
61
- # @param subscription_state [String]
62
- # @param date_range_start [String, #iso8601]
63
- # @param opts [Hash]
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]
@@ -25,7 +25,7 @@ module Peddler
25
25
  # @return [String]
26
26
  attr_reader :body
27
27
 
28
- alias_method :configure, :tap
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 request [Excon::Request]
61
- # @yieldparam response [Excon::Response]
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 opts [Hash]
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 request [Excon::Request]
159
- # @yieldparam response [Excon::Response]
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 "[DEPRECATION] Error handler now expects exception as argument."
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
 
@@ -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 or fail BadId, 'missing MarketplaceId'
23
+ @id = id || fail(BadId, 'missing MarketplaceId')
24
24
  end
25
25
 
26
26
  def host
@@ -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
- val = val.iso8601
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 do |subkey, subval|
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
- alias_method :add, :update
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 == "sku" ? "SKU" : token.capitalize }
51
+ .map { |token| token == 'sku' ? 'SKU' : token.capitalize }
57
52
  .join
58
53
  end
59
54
  end
@@ -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!
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Peddler
2
- VERSION = '1.2.0'
3
+ VERSION = '1.3.0'.freeze
3
4
  end
@@ -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.times.map { |count| Item.new(count, 1) }
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
@@ -0,0 +1,11 @@
1
+ require 'helper'
2
+ require 'mws/merchant_fulfillment'
3
+
4
+ class TestMerchantFulfillment < IntegrationTest
5
+ def test_gets_service_status
6
+ clients.each do |client|
7
+ res = client.get_service_status
8
+ refute_empty res.parse
9
+ end
10
+ end
11
+ end
@@ -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?("SellerId")
54
+ assert @klass.params.key?('SellerId')
55
55
  end
56
56
 
57
57
  def test_params_include_auth_token
58
- @klass.params.key?("MWSAuthToken")
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
- def test_request_preserves_user_agent
118
- instrumentor = Class.new
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
- @client.defaults.update(instrumentor: instrumentor)
127
+ @events = {}
128
+ end
129
+
130
+ def test_request_preserves_user_agent
131
+ @client.defaults.update(instrumentor: Instrumentor)
130
132
  @client.run
131
- headers = instrumentor.events['excon.request'][: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 = "123"
218
- assert_equal "123", @client.marketplace_id
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 = "content"
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 = "content"
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 = "other content"
33
+ client.body = 'other content'
34
34
  assert_raises(VCR::Errors::UnhandledHTTPRequestError) do
35
35
  client.run
36
36
  end