friendly_shipping 0.5 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop-relaxed.yml +3 -4
  3. data/.rubocop.yml +9 -0
  4. data/CHANGELOG.md +29 -0
  5. data/friendly_shipping.gemspec +12 -12
  6. data/lib/friendly_shipping/api_failure.rb +2 -15
  7. data/lib/friendly_shipping/http_client.rb +16 -9
  8. data/lib/friendly_shipping/request.rb +7 -1
  9. data/lib/friendly_shipping/services/ship_engine/bad_request_handler.rb +15 -3
  10. data/lib/friendly_shipping/services/ups.rb +9 -1
  11. data/lib/friendly_shipping/services/ups/parse_address_classification_response.rb +5 -2
  12. data/lib/friendly_shipping/services/ups/parse_address_validation_response.rb +5 -2
  13. data/lib/friendly_shipping/services/ups/parse_city_state_lookup_response.rb +5 -2
  14. data/lib/friendly_shipping/services/ups/parse_rate_response.rb +5 -1
  15. data/lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb +5 -1
  16. data/lib/friendly_shipping/services/ups/parse_shipment_confirm_response.rb +5 -1
  17. data/lib/friendly_shipping/services/ups/parse_time_in_transit_response.rb +5 -1
  18. data/lib/friendly_shipping/services/ups/parse_void_shipment_response.rb +5 -1
  19. data/lib/friendly_shipping/services/ups/parse_xml_response.rb +16 -7
  20. data/lib/friendly_shipping/services/ups_freight.rb +44 -13
  21. data/lib/friendly_shipping/services/ups_freight/generate_delivery_options_hash.rb +21 -0
  22. data/lib/friendly_shipping/services/ups_freight/generate_document_options_hash.rb +28 -0
  23. data/lib/friendly_shipping/services/ups_freight/generate_email_options_hash.rb +25 -0
  24. data/lib/friendly_shipping/services/ups_freight/generate_freight_rate_request_hash.rb +2 -10
  25. data/lib/friendly_shipping/services/ups_freight/generate_freight_ship_request_hash.rb +81 -0
  26. data/lib/friendly_shipping/services/ups_freight/generate_location_hash.rb +5 -2
  27. data/lib/friendly_shipping/services/ups_freight/generate_pickup_options_hash.rb +21 -0
  28. data/lib/friendly_shipping/services/ups_freight/generate_pickup_request_hash.rb +31 -0
  29. data/lib/friendly_shipping/services/ups_freight/label_delivery_options.rb +29 -0
  30. data/lib/friendly_shipping/services/ups_freight/label_document_options.rb +56 -0
  31. data/lib/friendly_shipping/services/ups_freight/label_email_options.rb +40 -0
  32. data/lib/friendly_shipping/services/ups_freight/label_item_options.rb +10 -0
  33. data/lib/friendly_shipping/services/ups_freight/label_options.rb +37 -0
  34. data/lib/friendly_shipping/services/ups_freight/label_package_options.rb +10 -0
  35. data/lib/friendly_shipping/services/ups_freight/label_pickup_options.rb +29 -0
  36. data/lib/friendly_shipping/services/ups_freight/parse_freight_label_response.rb +57 -0
  37. data/lib/friendly_shipping/services/ups_freight/parse_freight_rate_response.rb +29 -32
  38. data/lib/friendly_shipping/services/ups_freight/parse_shipment_document.rb +24 -0
  39. data/lib/friendly_shipping/services/ups_freight/pickup_request_options.rb +29 -0
  40. data/lib/friendly_shipping/services/ups_freight/rates_options.rb +3 -6
  41. data/lib/friendly_shipping/services/ups_freight/restful_api_error_handler.rb +30 -0
  42. data/lib/friendly_shipping/services/ups_freight/shipment_document.rb +21 -0
  43. data/lib/friendly_shipping/services/ups_freight/shipment_information.rb +35 -0
  44. data/lib/friendly_shipping/services/usps.rb +1 -0
  45. data/lib/friendly_shipping/services/usps/parse_address_validation_response.rb +5 -1
  46. data/lib/friendly_shipping/services/usps/parse_city_state_lookup_response.rb +5 -1
  47. data/lib/friendly_shipping/services/usps/parse_rate_response.rb +5 -2
  48. data/lib/friendly_shipping/services/usps/parse_time_in_transit_response.rb +6 -2
  49. data/lib/friendly_shipping/services/usps/parse_xml_response.rb +15 -5
  50. data/lib/friendly_shipping/services/usps/rate_estimate_options.rb +1 -1
  51. data/lib/friendly_shipping/services/usps/rate_estimate_package_options.rb +4 -1
  52. data/lib/friendly_shipping/services/usps/serialize_rate_request.rb +11 -5
  53. data/lib/friendly_shipping/services/usps/shipping_methods.rb +4 -4
  54. data/lib/friendly_shipping/version.rb +1 -1
  55. metadata +74 -39
  56. data/lib/friendly_shipping/services/ups_freight/generate_ups_security_hash.rb +0 -23
  57. data/lib/friendly_shipping/services/ups_freight/parse_json_response.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7033f8bf845a41a0cefa6899a465fd78a85077ff565c7c30f67d04f20708ff6
4
- data.tar.gz: 2c5207e0139608d78b7c65b6f273b9dc222bc750bc47e587147e8f486c908b43
3
+ metadata.gz: 774450d05e80ad658e9ab8d29ea372b142dca9b712bdf37f3baf4b5faa68d4c0
4
+ data.tar.gz: 1fc8c87b5812e0b31d2f74ff57e24887e0b4ec7b916b3f34371631bac8b897c9
5
5
  SHA512:
6
- metadata.gz: 00d7ce8fe1d737b482d71a6ff96195a82dc70b94c7784291c9cc18eb2f71ca529dadf33900a7f5aef223a4f89a3b1297403d7bc352dd9e8255c139b11b7351c1
7
- data.tar.gz: 7a7746f0c59dfcd03d2a330142f106cfe3c0fc7b82628859691d28c0dbd27e3d7584670c44f3509780271aaaf44fbd83551d0e1415ac14807d9ec2578891ab95
6
+ metadata.gz: 1d9f8099888cebd49a1c7fcfec69ddeb4170e04bea8d0a3ed0b0c5dcce9d413606b0386ae2034784563dfa628dd5d3b927f9250ef40a6431e28462238476a9e7
7
+ data.tar.gz: 6cac63b02a0f637f68fca0948bb8fa59361b8d13a3752d9de0a9a2cb55ec6aaf9654d89ee9530c0b11e2b81b44b928097defe17acfabe1a92c4635c9f9ab0ad2
@@ -133,6 +133,9 @@ Style/WordArray:
133
133
  Enabled: false
134
134
  StyleGuide: https://relaxed.ruby.style/#stylewordarray
135
135
 
136
+ Layout/LineLength:
137
+ Enabled: false
138
+
136
139
  Lint/AmbiguousRegexpLiteral:
137
140
  Enabled: false
138
141
  StyleGuide: https://relaxed.ruby.style/#lintambiguousregexpliteral
@@ -156,9 +159,6 @@ Metrics/ModuleLength:
156
159
  Metrics/CyclomaticComplexity:
157
160
  Enabled: false
158
161
 
159
- Metrics/LineLength:
160
- Enabled: false
161
-
162
162
  Metrics/MethodLength:
163
163
  Enabled: false
164
164
 
@@ -167,4 +167,3 @@ Metrics/ParameterLists:
167
167
 
168
168
  Metrics/PerceivedComplexity:
169
169
  Enabled: false
170
-
@@ -6,3 +6,12 @@ inherit_from:
6
6
 
7
7
  Metrics/BlockLength:
8
8
  Enabled: false
9
+
10
+ Style/HashEachMethods:
11
+ Enabled: true
12
+
13
+ Style/HashTransformKeys:
14
+ Enabled: true
15
+
16
+ Style/HashTransformValues:
17
+ Enabled: true
@@ -4,6 +4,35 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.6.1] - 2020-03-11
8
+
9
+ - Add Content-Type header to UPS Freight API requests, fixing "Name too long" 500 error responses
10
+
11
+ ## [0.6.0] - 2020-03-11
12
+
13
+ - Changelog additions missed in previous release
14
+
15
+ ## [0.5.3] - 2020-03-11
16
+
17
+ - UPS Service: Add support for shipping labels / bills of lading (#92)
18
+ - UPS/USPS Services: Return ApiFailure instead of a string for failed API responses (#95)
19
+ - UPS/USPS Services: Refactor ApiFailure to subclass ApiResponse (#96)
20
+
21
+ ## [0.5.2] - 2020-01-31
22
+
23
+ ### Added
24
+ - USPS Service: Added rectangular boolean to rate options class (#89)
25
+ - USPS Service: Added readable body to request class (#88)
26
+
27
+ ### Removed
28
+ - USPS Service: Drop deprecated rectangular container (#89)
29
+
30
+ ## [0.5.1] - 2020-01-28
31
+
32
+ ### Changed
33
+ - USPS Service: Rename "Package Services" shipping method (#85)
34
+ - Documentation updates (#86)
35
+
7
36
  ## [0.5] - 2020-01-24
8
37
 
9
38
  ### Removed
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.summary = "An integration layer for shipping services"
14
14
  spec.description = "Allows you to quote or ship a Physical::Shipment object"
15
- spec.homepage = "https://github.com/friendly_cart/friendly_shipping"
15
+ spec.homepage = "https://github.com/friendlycart/friendly_shipping"
16
16
  spec.license = "MIT"
17
17
 
18
18
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -24,21 +24,21 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_runtime_dependency "data_uri", "~> 0.0.3"
26
26
  spec.add_runtime_dependency "dry-monads", "~> 1.0"
27
- spec.add_runtime_dependency "money", ">= 6.0.0"
28
- spec.add_runtime_dependency "nokogiri", ">= 1.6"
29
- spec.add_runtime_dependency "physical", ">= 0.4.4"
27
+ spec.add_runtime_dependency "money", "~> 6.0"
28
+ spec.add_runtime_dependency "nokogiri", "~> 1.6"
29
+ spec.add_runtime_dependency "physical", "~> 0.4", ">= 0.4.4"
30
30
  spec.add_runtime_dependency "rest-client", "~> 2.0"
31
31
  spec.required_ruby_version = '>= 2.5'
32
32
 
33
- spec.add_development_dependency "bundler"
34
- spec.add_development_dependency "dotenv"
33
+ spec.add_development_dependency "bundler", ">= 1.17", "< 3"
34
+ spec.add_development_dependency "dotenv", "~> 2.7"
35
35
  spec.add_development_dependency "factory_bot", "~> 5.0"
36
- spec.add_development_dependency "pry"
37
- spec.add_development_dependency "rake", "~> 10.0"
36
+ spec.add_development_dependency "pry", "~> 0.12"
37
+ spec.add_development_dependency "rake", ">= 12.3.3"
38
38
  spec.add_development_dependency "rspec", "~> 3.0"
39
39
  spec.add_development_dependency "rspec_junit_formatter", "~> 0.4"
40
- spec.add_development_dependency "rubocop"
41
- spec.add_development_dependency "simplecov"
42
- spec.add_development_dependency "vcr"
43
- spec.add_development_dependency "webmock"
40
+ spec.add_development_dependency "rubocop", ">= 0.80", "< 1"
41
+ spec.add_development_dependency "simplecov", "~> 0.17"
42
+ spec.add_development_dependency "vcr", "~> 5.0"
43
+ spec.add_development_dependency "webmock", "~> 3.6"
44
44
  end
@@ -1,21 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FriendlyShipping
4
- class ApiFailure
5
- attr_reader :failure, :original_request, :original_response
6
-
7
- # @param [Object] failure The API failure
8
- # @param [FriendlyShipping::Request] original_request The HTTP request (when debugging is enabled)
9
- # @param [FriendlyShipping::Response] original_response The HTTP response (when debugging is enabled)
10
- def initialize(failure, original_request:, original_response:)
11
- @failure = failure
12
-
13
- # We do not want to attach debugging information in every single response to save memory in production
14
- return unless original_request&.debug
15
-
16
- @original_request = original_request
17
- @original_response = original_response
18
- end
4
+ class ApiFailure < ApiResult
5
+ alias_method :failure, :data
19
6
 
20
7
  def to_s
21
8
  failure.to_s
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'dry/monads/result'
4
+ require 'friendly_shipping/api_failure'
4
5
  require 'rest-client'
5
6
 
6
7
  module FriendlyShipping
@@ -21,19 +22,19 @@ module FriendlyShipping
21
22
 
22
23
  Success(convert_to_friendly_response(http_response))
23
24
  rescue ::RestClient::Exception => e
24
- error_handler.call(e)
25
+ error_handler.call(e, original_request: request, original_response: e.response)
25
26
  end
26
27
 
27
- def post(friendly_shipping_request)
28
+ def post(request)
28
29
  http_response = ::RestClient.post(
29
- friendly_shipping_request.url,
30
- friendly_shipping_request.body,
31
- friendly_shipping_request.headers
30
+ request.url,
31
+ request.body,
32
+ request.headers
32
33
  )
33
34
 
34
35
  Success(convert_to_friendly_response(http_response))
35
36
  rescue ::RestClient::Exception => e
36
- error_handler.call(e)
37
+ error_handler.call(e, original_request: request, original_response: e.response)
37
38
  end
38
39
 
39
40
  def put(request)
@@ -45,13 +46,19 @@ module FriendlyShipping
45
46
 
46
47
  Success(convert_to_friendly_response(http_response))
47
48
  rescue ::RestClient::Exception => e
48
- error_handler.call(e)
49
+ error_handler.call(e, original_request: request, original_response: e.response)
49
50
  end
50
51
 
51
52
  private
52
53
 
53
- def wrap_in_failure(error)
54
- Failure(error)
54
+ def wrap_in_failure(error, original_request: nil, original_response: nil)
55
+ Failure(
56
+ ApiFailure.new(
57
+ error,
58
+ original_request: original_request,
59
+ original_response: original_response
60
+ )
61
+ )
55
62
  end
56
63
 
57
64
  def convert_to_friendly_response(http_response)
@@ -6,13 +6,19 @@ module FriendlyShipping
6
6
 
7
7
  # @param [String] url The HTTP request URL
8
8
  # @param [String] body The HTTP request body
9
+ # # @param [String] readable_body Human-readable HTTP request body
9
10
  # @param [Hash] headers The HTTP request headers
10
11
  # @param [Boolean] debug Whether to debug the request
11
- def initialize(url:, body: nil, headers: {}, debug: false)
12
+ def initialize(url:, body: nil, readable_body: nil, headers: {}, debug: false)
12
13
  @url = url
13
14
  @body = body
15
+ @readable_body = readable_body
14
16
  @headers = headers
15
17
  @debug = debug
16
18
  end
19
+
20
+ def readable_body
21
+ @readable_body.presence || @body
22
+ end
17
23
  end
18
24
  end
@@ -8,11 +8,23 @@ module FriendlyShipping
8
8
  class BadRequestHandler
9
9
  extend Dry::Monads::Result::Mixin
10
10
 
11
- def self.call(error)
11
+ def self.call(error, original_request: nil, original_response: nil)
12
12
  if error.http_code == 400
13
- Failure(BadRequest.new(error))
13
+ Failure(
14
+ ApiFailure.new(
15
+ BadRequest.new(error),
16
+ original_request: original_request,
17
+ original_response: original_response
18
+ )
19
+ )
14
20
  else
15
- Failure(error)
21
+ Failure(
22
+ ApiFailure.new(
23
+ error,
24
+ original_request: original_request,
25
+ original_response: original_response
26
+ )
27
+ )
16
28
  end
17
29
  end
18
30
  end
@@ -74,6 +74,7 @@ module FriendlyShipping
74
74
  request = FriendlyShipping::Request.new(
75
75
  url: url,
76
76
  body: access_request_xml + rate_request_xml,
77
+ readable_body: rate_request_xml,
77
78
  debug: debug
78
79
  )
79
80
 
@@ -84,7 +85,7 @@ module FriendlyShipping
84
85
 
85
86
  # Get timing information for a shipment
86
87
  # @param [Physical::Shipment] shipment The shipment we want to estimate timings for
87
- # @param [FriendlyShipping::Services::Ups::TimingOptions] Options for this call
88
+ # @param [FriendlyShipping::Services::Ups::TimingOptions] options Options for this call
88
89
  def timings(shipment, options:, debug: false)
89
90
  time_in_transit_request_xml = SerializeTimeInTransitRequest.call(
90
91
  shipment: shipment,
@@ -95,6 +96,7 @@ module FriendlyShipping
95
96
  request = FriendlyShipping::Request.new(
96
97
  url: time_in_transit_url,
97
98
  body: access_request_xml + time_in_transit_request_xml,
99
+ readable_body: time_in_transit_request_xml,
98
100
  debug: debug
99
101
  )
100
102
 
@@ -114,6 +116,7 @@ module FriendlyShipping
114
116
  ship_confirm_request = FriendlyShipping::Request.new(
115
117
  url: ship_confirm_url,
116
118
  body: access_request_xml + ship_confirm_request_xml,
119
+ readable_body: ship_confirm_request_xml,
117
120
  debug: debug
118
121
  )
119
122
 
@@ -132,6 +135,7 @@ module FriendlyShipping
132
135
  ship_accept_request = FriendlyShipping::Request.new(
133
136
  url: ship_accept_url,
134
137
  body: access_request_xml + ship_accept_request_xml,
138
+ readable_body: ship_accept_request_xml,
135
139
  debug: debug
136
140
  )
137
141
 
@@ -153,6 +157,7 @@ module FriendlyShipping
153
157
  request = FriendlyShipping::Request.new(
154
158
  url: url,
155
159
  body: access_request_xml + address_validation_request_xml,
160
+ readable_body: address_validation_request_xml,
156
161
  debug: debug
157
162
  )
158
163
 
@@ -170,6 +175,7 @@ module FriendlyShipping
170
175
  request = FriendlyShipping::Request.new(
171
176
  url: url,
172
177
  body: access_request_xml + address_validation_request_xml,
178
+ readable_body: address_validation_request_xml,
173
179
  debug: debug
174
180
  )
175
181
 
@@ -188,6 +194,7 @@ module FriendlyShipping
188
194
  request = FriendlyShipping::Request.new(
189
195
  url: url,
190
196
  body: access_request_xml + city_state_lookup_request_xml,
197
+ readable_body: city_state_lookup_request_xml,
191
198
  debug: debug
192
199
  )
193
200
 
@@ -202,6 +209,7 @@ module FriendlyShipping
202
209
  request = FriendlyShipping::Request.new(
203
210
  url: url,
204
211
  body: access_request_xml + void_request_xml,
212
+ readable_body: void_request_xml,
205
213
  debug: debug
206
214
  )
207
215
  client.post(request).bind do |response|
@@ -7,8 +7,11 @@ module FriendlyShipping
7
7
  extend Dry::Monads::Result::Mixin
8
8
 
9
9
  def self.call(request:, response:)
10
- parsing_result = ParseXMLResponse.call(response.body, 'AddressValidationResponse')
11
-
10
+ parsing_result = ParseXMLResponse.call(
11
+ request: request,
12
+ response: response,
13
+ expected_root_tag: 'AddressValidationResponse'
14
+ )
12
15
  parsing_result.bind do |xml|
13
16
  address_type = xml.at('AddressClassification/Description')&.text&.downcase
14
17
  Success(
@@ -7,8 +7,11 @@ module FriendlyShipping
7
7
  extend Dry::Monads::Result::Mixin
8
8
 
9
9
  def self.call(request:, response:)
10
- parsing_result = ParseXMLResponse.call(response.body, 'AddressValidationResponse')
11
-
10
+ parsing_result = ParseXMLResponse.call(
11
+ request: request,
12
+ response: response,
13
+ expected_root_tag: 'AddressValidationResponse'
14
+ )
12
15
  parsing_result.bind do |xml|
13
16
  if xml.at('NoCandidatesIndicator')
14
17
  Failure(
@@ -7,8 +7,11 @@ module FriendlyShipping
7
7
  extend Dry::Monads::Result::Mixin
8
8
 
9
9
  def self.call(request:, response:, location:)
10
- parsing_result = ParseXMLResponse.call(response.body, 'AddressValidationResponse')
11
-
10
+ parsing_result = ParseXMLResponse.call(
11
+ request: request,
12
+ response: response,
13
+ expected_root_tag: 'AddressValidationResponse'
14
+ )
12
15
  parsing_result.fmap do |xml|
13
16
  FriendlyShipping::ApiResult.new(
14
17
  [
@@ -9,7 +9,11 @@ module FriendlyShipping
9
9
  class ParseRateResponse
10
10
  class << self
11
11
  def call(request:, response:, shipment:)
12
- parsing_result = ParseXMLResponse.call(response.body, 'RatingServiceSelectionResponse')
12
+ parsing_result = ParseXMLResponse.call(
13
+ request: request,
14
+ response: response,
15
+ expected_root_tag: 'RatingServiceSelectionResponse'
16
+ )
13
17
  parsing_result.fmap do |xml|
14
18
  FriendlyShipping::ApiResult.new(
15
19
  build_rates(xml, shipment),
@@ -11,7 +11,11 @@ module FriendlyShipping
11
11
 
12
12
  class << self
13
13
  def call(request:, response:)
14
- parsing_result = ParseXMLResponse.call(response.body, 'ShipmentAcceptResponse')
14
+ parsing_result = ParseXMLResponse.call(
15
+ request: request,
16
+ response: response,
17
+ expected_root_tag: 'ShipmentAcceptResponse'
18
+ )
15
19
  parsing_result.fmap do |xml|
16
20
  FriendlyShipping::ApiResult.new(
17
21
  build_labels(xml),
@@ -7,7 +7,11 @@ module FriendlyShipping
7
7
  class Ups
8
8
  class ParseShipmentConfirmResponse
9
9
  def self.call(request:, response:)
10
- parsing_result = ParseXMLResponse.call(response.body, 'ShipmentConfirmResponse')
10
+ parsing_result = ParseXMLResponse.call(
11
+ request: request,
12
+ response: response,
13
+ expected_root_tag: 'ShipmentConfirmResponse'
14
+ )
11
15
  parsing_result.fmap do |xml|
12
16
  FriendlyShipping::ApiResult.new(
13
17
  xml.root.at('ShipmentDigest').text,
@@ -5,7 +5,11 @@ module FriendlyShipping
5
5
  class Ups
6
6
  class ParseTimeInTransitResponse
7
7
  def self.call(request:, response:)
8
- parsing_result = ParseXMLResponse.call(response.body, 'TimeInTransitResponse')
8
+ parsing_result = ParseXMLResponse.call(
9
+ request: request,
10
+ response: response,
11
+ expected_root_tag: 'TimeInTransitResponse'
12
+ )
9
13
  parsing_result.fmap do |xml|
10
14
  origin_country_code = xml.at('TransitResponse/TransitFrom/AddressArtifactFormat/CountryCode').text
11
15
  timings = xml.root.xpath('//TransitResponse/ServiceSummary').map do |service_summary|
@@ -7,7 +7,11 @@ module FriendlyShipping
7
7
  class Ups
8
8
  class ParseVoidShipmentResponse
9
9
  def self.call(request:, response:)
10
- parsing_result = ParseXMLResponse.call(response.body, 'VoidShipmentResponse')
10
+ parsing_result = ParseXMLResponse.call(
11
+ request: request,
12
+ response: response,
13
+ expected_root_tag: 'VoidShipmentResponse'
14
+ )
11
15
  parsing_result.fmap do |xml|
12
16
  FriendlyShipping::ApiResult.new(
13
17
  xml.root.at('ResponseStatusDescription').text,
@@ -8,19 +8,18 @@ module FriendlyShipping
8
8
  SUCCESSFUL_RESPONSE_STATUS_CODE = '1'
9
9
 
10
10
  class << self
11
- def call(response_body, expected_root_tag)
12
- xml = Nokogiri.XML(response_body, &:strict)
11
+ def call(request:, response:, expected_root_tag:)
12
+ xml = Nokogiri.XML(response.body, &:strict)
13
13
 
14
14
  if xml.root.nil? || xml.root.name != expected_root_tag
15
- Failure('Invalid document')
16
- end
17
- if request_successful?(xml)
15
+ wrap_failure('Invalid document', request, response)
16
+ elsif request_successful?(xml)
18
17
  Success(xml)
19
18
  else
20
- Failure(error_message(xml))
19
+ wrap_failure(error_message(xml), request, response)
21
20
  end
22
21
  rescue Nokogiri::XML::SyntaxError => e
23
- Failure(e)
22
+ wrap_failure(e, request, response)
24
23
  end
25
24
 
26
25
  private
@@ -34,6 +33,16 @@ module FriendlyShipping
34
33
  desc = xml.root.at_xpath('Response/Error/ErrorDescription')&.text
35
34
  [status, desc].compact.join(": ").presence || 'UPS could not process the request.'
36
35
  end
36
+
37
+ def wrap_failure(failure, request, response)
38
+ Failure(
39
+ FriendlyShipping::ApiFailure.new(
40
+ failure,
41
+ original_request: request,
42
+ original_response: response
43
+ )
44
+ )
45
+ end
37
46
  end
38
47
  end
39
48
  end