savon 2.17.3 → 3.0.0.rc1

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.
data/lib/savon/header.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "akami"
4
3
  require "gyoku"
5
4
  require "securerandom"
6
5
 
7
6
  module Savon
8
7
  class Header
8
+
9
9
  def initialize(globals, locals)
10
- @gyoku_options = { key_converter: globals[:convert_request_keys_to] }
10
+ @gyoku_options = { :key_converter => globals[:convert_request_keys_to] }
11
11
 
12
12
  @wsse_auth = locals[:wsse_auth].nil? ? globals[:wsse_auth] : locals[:wsse_auth]
13
13
  @wsse_timestamp = locals[:wsse_timestamp].nil? ? globals[:wsse_timestamp] : locals[:wsse_timestamp]
@@ -41,7 +41,7 @@ module Savon
41
41
 
42
42
  def build_header
43
43
  header =
44
- if global_header.is_a?(Hash) && local_header.is_a?(Hash)
44
+ if global_header.kind_of?(Hash) && local_header.kind_of?(Hash)
45
45
  global_header.merge(local_header)
46
46
  elsif local_header
47
47
  local_header
@@ -58,17 +58,16 @@ module Savon
58
58
  end
59
59
 
60
60
  def build_wsa_header
61
- return '' unless @globals[:use_wsa_headers]
62
-
63
- convert_to_xml({
64
- 'wsa:Action' => @locals[:soap_action],
65
- 'wsa:To' => @globals[:endpoint],
66
- 'wsa:MessageID' => "urn:uuid:#{SecureRandom.uuid}"
67
- })
61
+ return '' unless @globals[:use_wsa_headers]
62
+ convert_to_xml({
63
+ 'wsa:Action' => @locals[:soap_action],
64
+ 'wsa:To' => @globals[:endpoint],
65
+ 'wsa:MessageID' => "urn:uuid:#{SecureRandom.uuid}"
66
+ })
68
67
  end
69
68
 
70
69
  def convert_to_xml(hash_or_string)
71
- if hash_or_string.is_a? Hash
70
+ if hash_or_string.kind_of? Hash
72
71
  Gyoku.xml(hash_or_string, gyoku_options)
73
72
  else
74
73
  hash_or_string.to_s
@@ -79,11 +78,12 @@ module Savon
79
78
  wsse = Akami.wsse
80
79
  wsse.credentials(*wsse_auth) if wsse_auth
81
80
  wsse.timestamp = wsse_timestamp if wsse_timestamp
82
- if wsse_signature&.have_document?
81
+ if wsse_signature && wsse_signature.have_document?
83
82
  wsse.signature = wsse_signature
84
83
  end
85
84
 
86
85
  wsse
87
86
  end
87
+
88
88
  end
89
89
  end
@@ -2,26 +2,26 @@
2
2
 
3
3
  module Savon
4
4
  class HTTPError < Error
5
+
5
6
  def self.present?(http)
6
- http.error?
7
+ !http.success?
7
8
  end
8
9
 
9
- def initialize(transport_response)
10
- @transport_response = transport_response
10
+ def initialize(http)
11
+ @http = http
11
12
  end
12
13
 
13
- def http
14
- @transport_response
15
- end
14
+ attr_reader :http
16
15
 
17
16
  def to_s
18
- String.new("HTTP error (#{http.code})").tap do |str_error|
19
- str_error << ": #{http.body}" unless http.body.empty?
17
+ String.new("HTTP error (#{@http.status})").tap do |str_error|
18
+ str_error << ": #{@http.body}" unless @http.body.empty?
20
19
  end
21
20
  end
22
21
 
23
22
  def to_hash
24
- { code: http.code, headers: http.headers, body: http.body }
23
+ { :code => @http.status, :headers => @http.headers, :body => @http.body }
25
24
  end
25
+
26
26
  end
27
27
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "nokogiri"
4
3
 
5
4
  module Savon
6
5
  class LogMessage
6
+
7
7
  def initialize(message, filters = [], pretty_print = false)
8
8
  @message = message
9
9
  @filters = filters
@@ -46,7 +46,8 @@ module Savon
46
46
  end
47
47
 
48
48
  def nokogiri_options
49
- @pretty_print ? { indent: 2 } : { save_with: Nokogiri::XML::Node::SaveOptions::AS_XML }
49
+ @pretty_print ? { :indent => 2 } : { :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML }
50
50
  end
51
+
51
52
  end
52
53
  end
data/lib/savon/message.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "savon/qualified_message"
4
3
  require "gyoku"
5
4
 
6
5
  module Savon
7
6
  class Message
7
+
8
8
  def initialize(message_tag, namespace_identifier, types, used_namespaces, message, element_form_default, key_converter, unwrap)
9
9
  @message_tag = message_tag
10
10
  @namespace_identifier = namespace_identifier
@@ -18,20 +18,21 @@ module Savon
18
18
  end
19
19
 
20
20
  def to_s
21
- return @message.to_s unless @message.is_a? Hash
21
+ return @message.to_s unless @message.kind_of? Hash
22
22
 
23
23
  if @element_form_default == :qualified
24
24
  @message = QualifiedMessage.new(@types, @used_namespaces, @key_converter).to_hash(@message, [@message_tag.to_s])
25
25
  end
26
26
 
27
27
  gyoku_options = {
28
- element_form_default: @element_form_default,
29
- namespace: @namespace_identifier,
30
- key_converter: @key_converter,
31
- unwrap: @unwrap
28
+ :element_form_default => @element_form_default,
29
+ :namespace => @namespace_identifier,
30
+ :key_converter => @key_converter,
31
+ :unwrap => @unwrap
32
32
  }
33
33
 
34
34
  Gyoku.xml(@message, gyoku_options)
35
35
  end
36
+
36
37
  end
37
38
  end
@@ -1,18 +1,11 @@
1
1
  # frozen_string_literal: true
2
-
3
- require "httpi"
4
- require "savon/transport/response"
2
+ require "faraday"
5
3
 
6
4
  module Savon
7
- # A single test expectation set up by Savon's mock interface.
8
- # One expectation covers one operation call in one test.
9
- #
10
- # Records the expected operation name and message, captures what was
11
- # actually called, and either returns a synthetic response or raises
12
- # an error on mismatch.
13
5
  class MockExpectation
6
+
14
7
  def initialize(operation_name)
15
- @expected = { operation_name: operation_name }
8
+ @expected = { :operation_name => operation_name }
16
9
  @actual = nil
17
10
  end
18
11
 
@@ -22,15 +15,15 @@ module Savon
22
15
  end
23
16
 
24
17
  def returns(response)
25
- response = { code: 200, headers: {}, body: response } if response.is_a?(String)
18
+ response = { :code => 200, :headers => {}, :body => response } if response.kind_of?(String)
26
19
  @response = response
27
20
  self
28
21
  end
29
22
 
30
- def actual(operation_name, _builder, _globals, locals)
23
+ def actual(operation_name, builder, globals, locals)
31
24
  @actual = {
32
- operation_name: operation_name,
33
- message: locals[:message]
25
+ :operation_name => operation_name,
26
+ :message => locals[:message]
34
27
  }
35
28
  end
36
29
 
@@ -44,49 +37,42 @@ module Savon
44
37
  verify_message!
45
38
  end
46
39
 
47
- # Builds and returns a Transport::Response from the configured response hash.
48
- #
49
- # @return [Transport::Response]
50
- # @raise [ExpectationError] if no response was configured for this expectation
51
40
  def response!
52
41
  unless @response
53
42
  raise ExpectationError, "This expectation was not set up with a response."
54
43
  end
55
-
56
- Transport::Response.new(@response[:code], @response[:headers], @response[:body])
44
+ env = Faraday::Env.from(status: @response[:code], response_headers: @response[:headers], response_body: @response[:body])
45
+ Faraday::Response.new(env)
57
46
  end
58
47
 
59
48
  private
60
49
 
61
50
  def verify_operation_name!
62
- return if @expected[:operation_name] == @actual[:operation_name]
63
-
64
- raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation.\n" \
65
- "Received a request to the #{@actual[:operation_name].inspect} operation instead."
51
+ unless @expected[:operation_name] == @actual[:operation_name]
52
+ raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation.\n" \
53
+ "Received a request to the #{@actual[:operation_name].inspect} operation instead."
54
+ end
66
55
  end
67
56
 
68
57
  def verify_message!
69
58
  return if @expected[:message].eql? :any
59
+ unless equals_except_any(@expected[:message], @actual[:message])
60
+ expected_message = " with this message: #{@expected[:message].inspect}" if @expected[:message]
61
+ expected_message ||= " with no message."
70
62
 
71
- return if equals_except_any(@expected[:message], @actual[:message])
63
+ actual_message = " with this message: #{@actual[:message].inspect}" if @actual[:message]
64
+ actual_message ||= " with no message."
72
65
 
73
- expected_message = " with this message: #{@expected[:message].inspect}" if @expected[:message]
74
- expected_message ||= " with no message."
75
-
76
- actual_message = " with this message: #{@actual[:message].inspect}" if @actual[:message]
77
- actual_message ||= " with no message."
78
-
79
- raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation\n#{expected_message}\n" \
80
- "Received a request to the #{@actual[:operation_name].inspect} operation\n#{actual_message}"
66
+ raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation\n#{expected_message}\n" \
67
+ "Received a request to the #{@actual[:operation_name].inspect} operation\n#{actual_message}"
68
+ end
81
69
  end
82
70
 
83
71
  def equals_except_any(msg_expected, msg_real)
84
- # === allows RSpec matchers (e.g. include(:key)) to be used as expected values
85
- return true if msg_expected === msg_real # rubocop:disable Style/CaseEquality
86
- return false if msg_expected.nil? || msg_real.nil? # If both are nil has returned true
87
-
72
+ return true if msg_expected === msg_real
73
+ return false if (msg_expected.nil? || msg_real.nil?) # If both are nil has returned true
88
74
  msg_expected.each do |key, expected_value|
89
- next if expected_value == :any && msg_real.include?(key)
75
+ next if (expected_value == :any && msg_real.include?(key))
90
76
  return false if expected_value != msg_real[key]
91
77
  end
92
78
  true
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "savon/mock"
4
3
 
5
4
  module Savon
6
5
  module SpecHelper
6
+
7
7
  class Interface
8
+
8
9
  def mock!
9
10
  Savon.observers << self
10
11
  end
@@ -26,12 +27,14 @@ module Savon
26
27
  def notify(operation_name, builder, globals, locals)
27
28
  expectation = expectations.shift
28
29
 
29
- raise ExpectationError, "Unexpected request to the #{operation_name.inspect} operation." unless expectation
30
-
31
- expectation.actual(operation_name, builder, globals, locals)
30
+ if expectation
31
+ expectation.actual(operation_name, builder, globals, locals)
32
32
 
33
- expectation.verify!
34
- expectation.response!
33
+ expectation.verify!
34
+ expectation.response!
35
+ else
36
+ raise ExpectationError, "Unexpected request to the #{operation_name.inspect} operation."
37
+ end
35
38
  rescue ExpectationError
36
39
  @expectations.clear
37
40
  raise
@@ -39,12 +42,12 @@ module Savon
39
42
 
40
43
  def verify!
41
44
  return if expectations.empty?
42
-
43
45
  expectations.each(&:verify!)
44
46
  rescue ExpectationError
45
47
  @expectations.clear
46
48
  raise
47
49
  end
50
+
48
51
  end
49
52
 
50
53
  def savon
@@ -55,5 +58,6 @@ module Savon
55
58
  super if defined? super
56
59
  savon.verify!
57
60
  end
61
+
58
62
  end
59
63
  end
data/lib/savon/mock.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Savon
4
3
  class ExpectationError < StandardError; end
5
4
  end
data/lib/savon/model.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Savon
4
3
  module Model
4
+
5
5
  def self.extended(base)
6
6
  base.setup
7
7
  end
@@ -28,30 +28,26 @@ module Savon
28
28
 
29
29
  # Defines a class-level SOAP operation.
30
30
  def define_class_operation(operation)
31
- method_name = operation_method_name(operation)
32
-
33
- class_operation_module.define_method(method_name) do |locals = {}|
34
- client.call operation, locals
35
- end
31
+ class_operation_module.module_eval %{
32
+ def #{StringUtils.snakecase(operation.to_s)}(locals = {})
33
+ client.call #{operation.inspect}, locals
34
+ end
35
+ }
36
36
  end
37
37
 
38
38
  # Defines an instance-level SOAP operation.
39
39
  def define_instance_operation(operation)
40
- method_name = operation_method_name(operation)
41
-
42
- instance_operation_module.define_method(method_name) do |locals = {}|
43
- self.class.public_send(method_name, locals)
44
- end
45
- end
46
-
47
- # Returns the generated Ruby method name for a SOAP operation.
48
- def operation_method_name(operation)
49
- StringUtils.snakecase(operation.to_s).to_sym
40
+ instance_operation_module.module_eval %{
41
+ def #{StringUtils.snakecase(operation.to_s)}(locals = {})
42
+ self.class.#{StringUtils.snakecase(operation.to_s)} locals
43
+ end
44
+ }
50
45
  end
51
46
 
52
47
  # Class methods.
53
48
  def class_operation_module
54
- @class_operation_module ||= Module.new do
49
+ @class_operation_module ||= Module.new {
50
+
55
51
  def client(globals = {})
56
52
  @client ||= Savon::Client.new(globals)
57
53
  rescue InitializationError
@@ -64,22 +60,26 @@ module Savon
64
60
 
65
61
  def raise_initialization_error!
66
62
  raise InitializationError,
67
- "Expected the model to be initialized with either a WSDL document or the SOAP endpoint and target namespace options.\n" \
68
- "Make sure to setup the model by calling the .client class method before calling the .global method.\n\n" \
69
- "client(wsdl: '/Users/me/project/service.wsdl') # to use a local WSDL document\n" \
70
- "client(wsdl: 'http://example.com?wsdl') # to use a remote WSDL document\n" \
71
- "client(endpoint: 'http://example.com', namespace: 'http://v1.example.com') # if you don't have a WSDL document"
63
+ "Expected the model to be initialized with either a WSDL document or the SOAP endpoint and target namespace options.\n" \
64
+ "Make sure to setup the model by calling the .client class method before calling the .global method.\n\n" \
65
+ "client(wsdl: '/Users/me/project/service.wsdl') # to use a local WSDL document\n" \
66
+ "client(wsdl: 'http://example.com?wsdl') # to use a remote WSDL document\n" \
67
+ "client(endpoint: 'http://example.com', namespace: 'http://v1.example.com') # if you don't have a WSDL document"
72
68
  end
73
- end.tap { |mod| extend(mod) }
69
+
70
+ }.tap { |mod| extend(mod) }
74
71
  end
75
72
 
76
73
  # Instance methods.
77
74
  def instance_operation_module
78
- @instance_operation_module ||= Module.new do
75
+ @instance_operation_module ||= Module.new {
76
+
79
77
  def client
80
78
  self.class.client
81
79
  end
82
- end.tap { |mod| include(mod) }
80
+
81
+ }.tap { |mod| include(mod) }
83
82
  end
83
+
84
84
  end
85
85
  end