savon 2.13.1 → 2.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -1
  3. data/lib/savon/builder.rb +4 -3
  4. data/lib/savon/model.rb +3 -3
  5. data/lib/savon/options.rb +1 -1
  6. data/lib/savon/response.rb +3 -3
  7. data/lib/savon/string_utils.rb +17 -0
  8. data/lib/savon/version.rb +1 -1
  9. data/lib/savon.rb +1 -0
  10. metadata +35 -81
  11. data/.gitignore +0 -16
  12. data/.yardopts +0 -6
  13. data/CONTRIBUTING.md +0 -42
  14. data/Gemfile +0 -8
  15. data/RELEASING.md +0 -10
  16. data/lib/savon/core_ext/string.rb +0 -30
  17. data/savon.gemspec +0 -47
  18. data/spec/fixtures/gzip/message.gz +0 -0
  19. data/spec/fixtures/response/another_soap_fault.xml +0 -14
  20. data/spec/fixtures/response/authentication.xml +0 -14
  21. data/spec/fixtures/response/empty_soap_fault.xml +0 -13
  22. data/spec/fixtures/response/f5.xml +0 -39
  23. data/spec/fixtures/response/header.xml +0 -13
  24. data/spec/fixtures/response/list.xml +0 -18
  25. data/spec/fixtures/response/multi_ref.xml +0 -39
  26. data/spec/fixtures/response/no_body.xml +0 -1
  27. data/spec/fixtures/response/soap_fault.xml +0 -8
  28. data/spec/fixtures/response/soap_fault12.xml +0 -18
  29. data/spec/fixtures/response/soap_fault_funky.xml +0 -8
  30. data/spec/fixtures/response/taxcloud.xml +0 -1
  31. data/spec/fixtures/ssl/client_cert.pem +0 -16
  32. data/spec/fixtures/ssl/client_encrypted_key.pem +0 -30
  33. data/spec/fixtures/ssl/client_encrypted_key_cert.pem +0 -24
  34. data/spec/fixtures/ssl/client_key.pem +0 -15
  35. data/spec/fixtures/wsdl/authentication.xml +0 -63
  36. data/spec/fixtures/wsdl/betfair.xml +0 -2981
  37. data/spec/fixtures/wsdl/brand.xml +0 -624
  38. data/spec/fixtures/wsdl/edialog.xml +0 -15416
  39. data/spec/fixtures/wsdl/elements_in_types.xml +0 -43
  40. data/spec/fixtures/wsdl/interhome.xml +0 -2137
  41. data/spec/fixtures/wsdl/lower_camel.xml +0 -52
  42. data/spec/fixtures/wsdl/multiple_namespaces.xml +0 -92
  43. data/spec/fixtures/wsdl/multiple_types.xml +0 -60
  44. data/spec/fixtures/wsdl/no_message_tag.xml +0 -1267
  45. data/spec/fixtures/wsdl/taxcloud.xml +0 -934
  46. data/spec/fixtures/wsdl/team_software.xml +0 -1
  47. data/spec/fixtures/wsdl/vies.xml +0 -176
  48. data/spec/fixtures/wsdl/wasmuth.xml +0 -153
  49. data/spec/integration/support/application.rb +0 -114
  50. data/spec/integration/support/server.rb +0 -85
  51. data/spec/integration/zipcode_example_spec.rb +0 -39
  52. data/spec/savon/builder_spec.rb +0 -138
  53. data/spec/savon/client_spec.rb +0 -272
  54. data/spec/savon/core_ext/string_spec.rb +0 -38
  55. data/spec/savon/features/message_tag_spec.rb +0 -62
  56. data/spec/savon/http_error_spec.rb +0 -57
  57. data/spec/savon/log_message_spec.rb +0 -51
  58. data/spec/savon/message_spec.rb +0 -61
  59. data/spec/savon/mock_spec.rb +0 -175
  60. data/spec/savon/model_spec.rb +0 -183
  61. data/spec/savon/multipart_request_spec.rb +0 -46
  62. data/spec/savon/observers_spec.rb +0 -93
  63. data/spec/savon/operation_spec.rb +0 -207
  64. data/spec/savon/options_spec.rb +0 -1154
  65. data/spec/savon/qualified_message_spec.rb +0 -102
  66. data/spec/savon/request_logger_spec.rb +0 -38
  67. data/spec/savon/request_spec.rb +0 -581
  68. data/spec/savon/response_spec.rb +0 -276
  69. data/spec/savon/soap_fault_spec.rb +0 -147
  70. data/spec/savon/softlayer_spec.rb +0 -42
  71. data/spec/spec_helper.rb +0 -31
  72. data/spec/support/adapters.rb +0 -49
  73. data/spec/support/endpoint.rb +0 -26
  74. data/spec/support/fixture.rb +0 -40
  75. data/spec/support/integration.rb +0 -10
  76. data/spec/support/stdout.rb +0 -26
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
- require "integration/support/server"
4
-
5
- RSpec.describe Savon::Message do
6
-
7
- before do
8
- @server = IntegrationServer.run
9
- end
10
-
11
- after do
12
- @server.stop
13
- end
14
-
15
- let(:client_config) {
16
- {
17
- :endpoint => @server.url(:repeat),
18
- :namespace => 'http://example.com',
19
- :log => false,
20
-
21
- :element_form_default => :qualified,
22
- :convert_request_keys_to => :camelcase,
23
-
24
- :convert_response_tags_to => nil
25
- }
26
- }
27
-
28
- let(:client) { Savon.client(client_config) }
29
-
30
- context "with a qualified message" do
31
- let(:message) {
32
- {
33
- :email_count => 3,
34
- :user_name => 'josh',
35
- :order! => [:user_name, :email_count]
36
- }
37
- }
38
-
39
- let(:converted_keys) {
40
- '<wsdl:UserName>josh</wsdl:UserName><wsdl:EmailCount>3</wsdl:EmailCount>'
41
- }
42
- it "converts request Hash keys for which there is not namespace" do
43
- response = client.call(:something, :message => message)
44
- expect(response.xml).to include(converted_keys)
45
- end
46
- end
47
-
48
- context 'use_wsa_headers' do
49
- let(:client_config) { super().merge(use_wsa_headers: true) }
50
-
51
- context 'headers' do
52
- [ 'wsa:Action', 'wsa:To', 'wsa:MessageID' ].each do |header|
53
- it "should include #{header} header" do
54
- response = client.call(:something, message: {})
55
- expect(response.xml).to include(header)
56
- end
57
- end
58
- end
59
- end
60
-
61
- end
@@ -1,175 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
- require "savon/mock/spec_helper"
4
-
5
- RSpec.describe "Savon's mock interface" do
6
- include Savon::SpecHelper
7
-
8
- before :all do
9
- savon.mock!
10
- end
11
-
12
- after :all do
13
- savon.unmock!
14
- end
15
-
16
- it "can verify a request and return a fixture response" do
17
- message = { :username => "luke", :password => "secret" }
18
- savon.expects(:authenticate).with(:message => message).returns("<fixture/>")
19
-
20
- response = new_client.call(:authenticate) do
21
- message(:username => "luke", :password => "secret")
22
- end
23
-
24
- expect(response.http.body).to eq("<fixture/>")
25
- end
26
-
27
- it "can verify a request with any parameters and return a fixture response" do
28
- message = { :username => "luke", :password => :any }
29
- savon.expects(:authenticate).with(:message => message).returns("<fixture/>")
30
-
31
- response = new_client.call(:authenticate) do
32
- message(:username => "luke", :password => "secret")
33
- end
34
-
35
- expect(response.http.body).to eq("<fixture/>")
36
- end
37
-
38
- it "accepts a Hash to specify the response code, headers and body" do
39
- soap_fault = Fixture.response(:soap_fault)
40
- response = { :code => 500, :headers => { "X-Result" => "invalid" }, :body => soap_fault }
41
-
42
- savon.expects(:authenticate).returns(response)
43
- response = new_client(:raise_errors => false).call(:authenticate)
44
-
45
- expect(response).to_not be_successful
46
- expect(response).to be_a_soap_fault
47
-
48
- expect(response.http.code).to eq(500)
49
- expect(response.http.headers).to eq("X-Result" => "invalid")
50
- expect(response.http.body).to eq(soap_fault)
51
- end
52
-
53
- it "works with multiple requests" do
54
- authentication_message = { :username => "luke", :password => "secret" }
55
- savon.expects(:authenticate).with(:message => authentication_message).returns("")
56
-
57
- find_user_message = { :by_username => "lea" }
58
- savon.expects(:find_user).with(:message => find_user_message).returns("")
59
-
60
- new_client.call(:authenticate, :message => authentication_message)
61
- new_client.call(:find_user, :message => find_user_message)
62
- end
63
-
64
- it "fails when the expected operation was not called" do
65
- # TODO: find out how to test this! [dh, 2012-12-17]
66
- #savon.expects(:authenticate)
67
- end
68
-
69
- it "fails when the return value for an expectation was not specified" do
70
- savon.expects(:authenticate)
71
-
72
- expect { new_client.call(:authenticate) }.
73
- to raise_error(Savon::ExpectationError, "This expectation was not set up with a response.")
74
- end
75
-
76
- it "fails with an unexpected request" do
77
- expect { new_client.call(:authenticate) }.
78
- to raise_error(Savon::ExpectationError, "Unexpected request to the :authenticate operation.")
79
- end
80
-
81
- it "fails with multiple requests" do
82
- authentication_message = { :username => "luke", :password => "secret" }
83
- savon.expects(:authenticate).with(:message => authentication_message).returns("")
84
-
85
- create_user_message = { :username => "lea" }
86
- savon.expects(:create_user).with(:message => create_user_message).returns("")
87
-
88
- find_user_message = { :by_username => "lea" }
89
- savon.expects(:find_user).with(:message => find_user_message).returns("")
90
-
91
- # reversed order from previous spec
92
- new_client.call(:authenticate, :message => authentication_message)
93
-
94
- expect { new_client.call(:find_user, :message => find_user_message) }.
95
- to raise_error(Savon::ExpectationError, "Expected a request to the :create_user operation.\n" \
96
- "Received a request to the :find_user operation instead.")
97
- end
98
-
99
- it "fails when the expected SOAP operation does not match the actual one" do
100
- savon.expects(:logout).returns("<fixture/>")
101
-
102
- expect { new_client.call(:authenticate) }.
103
- to raise_error(Savon::ExpectationError, "Expected a request to the :logout operation.\n" \
104
- "Received a request to the :authenticate operation instead.")
105
- end
106
-
107
- it "fails when there is no actual message to match" do
108
- message = { :username => "luke" }
109
- savon.expects(:find_user).with(:message => message).returns("<fixture/>")
110
-
111
- expect { new_client.call(:find_user) }.
112
- to raise_error(Savon::ExpectationError, "Expected a request to the :find_user operation\n" \
113
- " with this message: #{message.inspect}\n" \
114
- "Received a request to the :find_user operation\n" \
115
- " with no message.")
116
- end
117
-
118
- it "fails when there is no expect but an actual message" do
119
- savon.expects(:find_user).returns("<fixture/>")
120
- message = { :username => "luke" }
121
-
122
- expect { new_client.call(:find_user, :message => message) }.
123
- to raise_error(Savon::ExpectationError, "Expected a request to the :find_user operation\n" \
124
- " with no message.\n" \
125
- "Received a request to the :find_user operation\n" \
126
- " with this message: #{message.inspect}")
127
- end
128
-
129
- it "does not fail when any message is expected and an actual message" do
130
- savon.expects(:find_user).with(:message => :any).returns("<fixture/>")
131
- message = { :username => "luke" }
132
-
133
- expect { new_client.call(:find_user, :message => message) }.to_not raise_error
134
- end
135
-
136
- it "does not fail when any message is expected and no actual message" do
137
- savon.expects(:find_user).with(:message => :any).returns("<fixture/>")
138
-
139
- expect { new_client.call(:find_user) }.to_not raise_error
140
- end
141
-
142
- it "matchers can be used to specify the message" do
143
- savon.expects(:find_user).with(:message => include(:username)).returns("<fixture/>")
144
- message = { :username => "Han Solo", password: "querty"}
145
-
146
- expect { new_client.call(:find_user, :message => message) }.to_not raise_error
147
- end
148
-
149
- it "allows code to rescue Savon::Error and still report test failures" do
150
- message = { :username => "luke" }
151
- savon.expects(:find_user).with(:message => message).returns("<fixture/>")
152
-
153
- expect {
154
- begin
155
- new_client.call(:find_user)
156
- rescue Savon::Error => e
157
- puts "any real error (e.g. SOAP fault or HTTP error) is OK in the big picture, move on"
158
- end
159
- }.to raise_error(Savon::ExpectationError, "Expected a request to the :find_user operation\n" \
160
- " with this message: #{message.inspect}\n" \
161
- "Received a request to the :find_user operation\n" \
162
- " with no message.")
163
- end
164
-
165
- def new_client(globals = {})
166
- defaults = {
167
- :endpoint => "http://example.com",
168
- :namespace => "http://v1.example.com",
169
- :log => false
170
- }
171
-
172
- Savon.client defaults.merge(globals)
173
- end
174
-
175
- end
@@ -1,183 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
- require "integration/support/server"
4
-
5
- RSpec.describe Savon::Model do
6
-
7
- before :all do
8
- @server = IntegrationServer.run
9
- end
10
-
11
- after :all do
12
- @server.stop
13
- end
14
-
15
- describe ".client" do
16
- it "returns the memoized client" do
17
- model = Class.new {
18
- extend Savon::Model
19
- client :wsdl => Fixture.wsdl(:authentication)
20
- }
21
-
22
- expect(model.client).to be_a(Savon::Client)
23
- expect(model.client).to equal(model.client)
24
- end
25
-
26
- it "raises if the client was not initialized properly" do
27
- model = Class.new { extend Savon::Model }
28
-
29
- expect { model.client }.
30
- to raise_error(Savon::InitializationError, /^Expected the model to be initialized/)
31
- end
32
- end
33
-
34
- describe ".global" do
35
- it "sets global options" do
36
- model = Class.new {
37
- extend Savon::Model
38
-
39
- client :wsdl => Fixture.wsdl(:authentication)
40
-
41
- global :soap_version, 2
42
- global :open_timeout, 71
43
- global :wsse_auth, "luke", "secret", :digest
44
- }
45
-
46
- expect(model.client.globals[:soap_version]).to eq(2)
47
- expect(model.client.globals[:open_timeout]).to eq(71)
48
- expect(model.client.globals[:wsse_auth]).to eq(["luke", "secret", :digest])
49
- end
50
- end
51
-
52
- describe ".operations" do
53
- it "defines class methods for each operation" do
54
- model = Class.new {
55
- extend Savon::Model
56
-
57
- client :wsdl => Fixture.wsdl(:authentication)
58
- operations :authenticate
59
- }
60
-
61
- expect(model).to respond_to(:authenticate)
62
- end
63
-
64
- it "executes class-level SOAP operations" do
65
- repeat_url = @server.url(:repeat)
66
-
67
- model = Class.new {
68
- extend Savon::Model
69
-
70
- client :endpoint => repeat_url, :namespace => "http://v1.example.com"
71
- global :log, false
72
-
73
- operations :authenticate
74
- }
75
-
76
- response = model.authenticate(:xml => Fixture.response(:authentication))
77
- expect(response.body[:authenticate_response][:return]).to include(:authentication_value)
78
- end
79
-
80
- it "defines instance methods for each operation" do
81
- model = Class.new {
82
- extend Savon::Model
83
-
84
- client :wsdl => Fixture.wsdl(:authentication)
85
- operations :authenticate
86
- }
87
-
88
- model_instance = model.new
89
- expect(model_instance).to respond_to(:authenticate)
90
- end
91
-
92
- it "executes instance-level SOAP operations" do
93
- repeat_url = @server.url(:repeat)
94
-
95
- model = Class.new {
96
- extend Savon::Model
97
-
98
- client :endpoint => repeat_url, :namespace => "http://v1.example.com"
99
- global :log, false
100
-
101
- operations :authenticate
102
- }
103
-
104
- model_instance = model.new
105
- response = model_instance.authenticate(:xml => Fixture.response(:authentication))
106
- expect(response.body[:authenticate_response][:return]).to include(:authentication_value)
107
- end
108
- end
109
-
110
- it "allows to overwrite class operations" do
111
- repeat_url = @server.url(:repeat)
112
-
113
- model = Class.new {
114
- extend Savon::Model
115
- client :endpoint => repeat_url, :namespace => "http://v1.example.com"
116
- }
117
-
118
- supermodel = model.dup
119
- supermodel.operations :authenticate
120
-
121
- def supermodel.authenticate(locals = {})
122
- p "super"
123
- super
124
- end
125
-
126
- supermodel.client.expects(:call).with(:authenticate, :message => { :username => "luke", :password => "secret" })
127
- supermodel.expects(:p).with("super") # stupid, but works
128
-
129
- supermodel.authenticate(:message => { :username => "luke", :password => "secret" })
130
- end
131
-
132
- it "allows to overwrite instance operations" do
133
- repeat_url = @server.url(:repeat)
134
-
135
- model = Class.new {
136
- extend Savon::Model
137
- client :endpoint => repeat_url, :namespace => "http://v1.example.com"
138
- }
139
-
140
- supermodel = model.dup
141
- supermodel.operations :authenticate
142
- supermodel = supermodel.new
143
-
144
- def supermodel.authenticate(lcoals = {})
145
- p "super"
146
- super
147
- end
148
-
149
- supermodel.client.expects(:call).with(:authenticate, :message => { :username => "luke", :password => "secret" })
150
- supermodel.expects(:p).with("super") # stupid, but works
151
-
152
- supermodel.authenticate(:message => { :username => "luke", :password => "secret" })
153
- end
154
-
155
- describe ".all_operations" do
156
- it "should call operations with all available client operations" do
157
- model = Class.new {
158
- extend Savon::Model
159
-
160
- client :wsdl => Fixture.wsdl(:taxcloud)
161
- all_operations
162
- }
163
-
164
- [:verify_address,
165
- :lookup_for_date,
166
- :lookup,
167
- :authorized,
168
- :authorized_with_capture,
169
- :captured,
170
- :returned,
171
- :get_tic_groups,
172
- :get_ti_cs,
173
- :get_ti_cs_by_group,
174
- :add_exempt_certificate,
175
- :delete_exempt_certificate,
176
- :get_exempt_certificates].each do |method|
177
- expect(model).to respond_to(method)
178
- end
179
- end
180
-
181
- end
182
-
183
- end
@@ -1,46 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe Savon::Builder do
4
-
5
- let(:globals) { Savon::GlobalOptions.new({ :endpoint => "http://example.co", :namespace => "http://v1.example.com" }) }
6
- let(:no_wsdl) { Wasabi::Document.new }
7
-
8
- it "building multipart request from inline content" do
9
- locals = {
10
- attachments: [
11
- { filename: 'x1.xml', content: '<xml>abc1</xml>'},
12
- { filename: 'x2.xml', content: '<xml>abc2</xml>'},
13
- ]
14
- }
15
- builder = Savon::Builder.new(:operation1, no_wsdl, globals, Savon::LocalOptions.new(locals))
16
- request_body = builder.to_s
17
-
18
- expect(request_body).to include('Content-Type')
19
- expect(request_body).to match(/<[a-z]+:operation1>/)
20
-
21
- locals[:attachments].each do |attachment|
22
- expect(request_body).to match(/^Content-Location: #{attachment[:filename]}\s$/)
23
- expect(request_body).to include(Base64.encode64(attachment[:content]).strip)
24
- end
25
-
26
- end
27
-
28
- it "building multipart request from file" do
29
- locals = {
30
- attachments: {
31
- 'file.gz' => File.expand_path("../../fixtures/gzip/message.gz", __FILE__)
32
- }
33
- }
34
- builder = Savon::Builder.new(:operation1, no_wsdl, globals, Savon::LocalOptions.new(locals))
35
- request_body = builder.to_s
36
-
37
- expect(request_body).to include('Content-Type')
38
- expect(request_body).to match(/<[a-z]+:operation1>/)
39
-
40
- locals[:attachments].each do |id, file|
41
- expect(request_body).to match(/^Content-Location: #{id}\s$/)
42
- expect(request_body.gsub("\r", "")).to include(Base64.encode64(File.read(file)).strip)
43
- end
44
-
45
- end
46
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
- require "integration/support/server"
4
-
5
- RSpec.describe Savon do
6
-
7
- before :all do
8
- @server = IntegrationServer.run
9
- end
10
-
11
- after :all do
12
- @server.stop
13
- end
14
-
15
- describe ".observers" do
16
- after :each do
17
- Savon.observers.clear
18
- end
19
-
20
- it "allows to register an observer for every request" do
21
- observer = Class.new {
22
-
23
- def notify(operation_name, builder, globals, locals)
24
- @operation_name = operation_name
25
-
26
- @builder = builder
27
- @globals = globals
28
- @locals = locals
29
-
30
- # return nil to execute the request
31
- nil
32
- end
33
-
34
- attr_reader :operation_name, :builder, :globals, :locals
35
-
36
- }.new
37
-
38
- Savon.observers << observer
39
-
40
- new_client.call(:authenticate)
41
-
42
- expect(observer.operation_name).to eq(:authenticate)
43
-
44
- expect(observer.builder).to be_a(Savon::Builder)
45
- expect(observer.globals).to be_a(Savon::GlobalOptions)
46
- expect(observer.locals).to be_a(Savon::LocalOptions)
47
- end
48
-
49
- it "allows to register an observer which mocks requests" do
50
- observer = Class.new {
51
-
52
- def notify(*)
53
- # return a response to mock the request
54
- HTTPI::Response.new(201, { "X-Result" => "valid" }, "valid!")
55
- end
56
-
57
- }.new
58
-
59
- Savon.observers << observer
60
-
61
- response = new_client.call(:authenticate)
62
-
63
- expect(response.http.code).to eq(201)
64
- expect(response.http.headers).to eq("X-Result" => "valid")
65
- expect(response.http.body).to eq("valid!")
66
- end
67
-
68
- it "raises if an observer returns something other than nil or an HTTPI::Response" do
69
- observer = Class.new {
70
-
71
- def notify(*)
72
- []
73
- end
74
-
75
- }.new
76
-
77
- Savon.observers << observer
78
-
79
- expect { new_client.call(:authenticate) }.
80
- to raise_error(Savon::Error, "Observers need to return an HTTPI::Response " \
81
- "to mock the request or nil to execute the request.")
82
- end
83
- end
84
-
85
- def new_client
86
- Savon.client(
87
- :endpoint => @server.url(:repeat),
88
- :namespace => "http://v1.example.com",
89
- :log => false
90
- )
91
- end
92
-
93
- end