savon 2.13.1 → 2.14.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/CHANGELOG.md +6 -1
- data/lib/savon/builder.rb +4 -3
- data/lib/savon/model.rb +3 -3
- data/lib/savon/options.rb +1 -1
- data/lib/savon/response.rb +3 -3
- data/lib/savon/string_utils.rb +17 -0
- data/lib/savon/version.rb +1 -1
- data/lib/savon.rb +1 -0
- metadata +17 -76
- data/.gitignore +0 -16
- data/.yardopts +0 -6
- data/CONTRIBUTING.md +0 -42
- data/Gemfile +0 -8
- data/RELEASING.md +0 -10
- data/lib/savon/core_ext/string.rb +0 -30
- data/savon.gemspec +0 -47
- data/spec/fixtures/gzip/message.gz +0 -0
- data/spec/fixtures/response/another_soap_fault.xml +0 -14
- data/spec/fixtures/response/authentication.xml +0 -14
- data/spec/fixtures/response/empty_soap_fault.xml +0 -13
- data/spec/fixtures/response/f5.xml +0 -39
- data/spec/fixtures/response/header.xml +0 -13
- data/spec/fixtures/response/list.xml +0 -18
- data/spec/fixtures/response/multi_ref.xml +0 -39
- data/spec/fixtures/response/no_body.xml +0 -1
- data/spec/fixtures/response/soap_fault.xml +0 -8
- data/spec/fixtures/response/soap_fault12.xml +0 -18
- data/spec/fixtures/response/soap_fault_funky.xml +0 -8
- data/spec/fixtures/response/taxcloud.xml +0 -1
- data/spec/fixtures/ssl/client_cert.pem +0 -16
- data/spec/fixtures/ssl/client_encrypted_key.pem +0 -30
- data/spec/fixtures/ssl/client_encrypted_key_cert.pem +0 -24
- data/spec/fixtures/ssl/client_key.pem +0 -15
- data/spec/fixtures/wsdl/authentication.xml +0 -63
- data/spec/fixtures/wsdl/betfair.xml +0 -2981
- data/spec/fixtures/wsdl/brand.xml +0 -624
- data/spec/fixtures/wsdl/edialog.xml +0 -15416
- data/spec/fixtures/wsdl/elements_in_types.xml +0 -43
- data/spec/fixtures/wsdl/interhome.xml +0 -2137
- data/spec/fixtures/wsdl/lower_camel.xml +0 -52
- data/spec/fixtures/wsdl/multiple_namespaces.xml +0 -92
- data/spec/fixtures/wsdl/multiple_types.xml +0 -60
- data/spec/fixtures/wsdl/no_message_tag.xml +0 -1267
- data/spec/fixtures/wsdl/taxcloud.xml +0 -934
- data/spec/fixtures/wsdl/team_software.xml +0 -1
- data/spec/fixtures/wsdl/vies.xml +0 -176
- data/spec/fixtures/wsdl/wasmuth.xml +0 -153
- data/spec/integration/support/application.rb +0 -114
- data/spec/integration/support/server.rb +0 -85
- data/spec/integration/zipcode_example_spec.rb +0 -39
- data/spec/savon/builder_spec.rb +0 -138
- data/spec/savon/client_spec.rb +0 -272
- data/spec/savon/core_ext/string_spec.rb +0 -38
- data/spec/savon/features/message_tag_spec.rb +0 -62
- data/spec/savon/http_error_spec.rb +0 -57
- data/spec/savon/log_message_spec.rb +0 -51
- data/spec/savon/message_spec.rb +0 -61
- data/spec/savon/mock_spec.rb +0 -175
- data/spec/savon/model_spec.rb +0 -183
- data/spec/savon/multipart_request_spec.rb +0 -46
- data/spec/savon/observers_spec.rb +0 -93
- data/spec/savon/operation_spec.rb +0 -207
- data/spec/savon/options_spec.rb +0 -1154
- data/spec/savon/qualified_message_spec.rb +0 -102
- data/spec/savon/request_logger_spec.rb +0 -38
- data/spec/savon/request_spec.rb +0 -581
- data/spec/savon/response_spec.rb +0 -276
- data/spec/savon/soap_fault_spec.rb +0 -147
- data/spec/savon/softlayer_spec.rb +0 -42
- data/spec/spec_helper.rb +0 -31
- data/spec/support/adapters.rb +0 -49
- data/spec/support/endpoint.rb +0 -26
- data/spec/support/fixture.rb +0 -40
- data/spec/support/integration.rb +0 -10
- data/spec/support/stdout.rb +0 -26
data/spec/savon/options_spec.rb
DELETED
@@ -1,1154 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "spec_helper"
|
3
|
-
require "integration/support/server"
|
4
|
-
require "json"
|
5
|
-
require "ostruct"
|
6
|
-
require "logger"
|
7
|
-
|
8
|
-
RSpec.describe "Options" do
|
9
|
-
|
10
|
-
before :all do
|
11
|
-
@server = IntegrationServer.run
|
12
|
-
end
|
13
|
-
|
14
|
-
after :all do
|
15
|
-
@server.stop
|
16
|
-
end
|
17
|
-
|
18
|
-
context "global: endpoint and namespace" do
|
19
|
-
it "sets the SOAP endpoint to use to allow requests without a WSDL document" do
|
20
|
-
client = new_client_without_wsdl(:endpoint => @server.url(:repeat), :namespace => "http://v1.example.com")
|
21
|
-
response = client.call(:authenticate)
|
22
|
-
|
23
|
-
# the default namespace identifier is :wsdl and contains the namespace option
|
24
|
-
expect(response.http.body).to include('xmlns:wsdl="http://v1.example.com"')
|
25
|
-
|
26
|
-
# the default namespace applies to the message tag
|
27
|
-
expect(response.http.body).to include('<wsdl:authenticate>')
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context "global :namespace_identifier" do
|
32
|
-
it "changes the default namespace identifier" do
|
33
|
-
client = new_client(:endpoint => @server.url(:repeat), :namespace_identifier => :lol)
|
34
|
-
response = client.call(:authenticate)
|
35
|
-
|
36
|
-
expect(response.http.body).to include('xmlns:lol="http://v1_0.ws.auth.order.example.com/"')
|
37
|
-
expect(response.http.body).to include("<lol:authenticate></lol:authenticate>")
|
38
|
-
end
|
39
|
-
|
40
|
-
it "ignores namespace identifier if it is nil" do
|
41
|
-
client = new_client(:endpoint => @server.url(:repeat), :namespace_identifier => nil)
|
42
|
-
response = client.call(:authenticate, :message => {:user => 'foo'})
|
43
|
-
|
44
|
-
expect(response.http.body).to include('xmlns="http://v1_0.ws.auth.order.example.com/"')
|
45
|
-
expect(response.http.body).to include("<authenticate><user>foo</user></authenticate>")
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
context "global: :no_message_tag" do
|
50
|
-
it "omits the 'message tag' encapsulation step" do
|
51
|
-
client = new_client(:endpoint => @server.url(:repeat), :no_message_tag => true,
|
52
|
-
:wsdl => Fixture.wsdl(:no_message_tag))
|
53
|
-
msg = {'extLoginData' => {'Login' => 'test.user', 'Password' => 'secret', 'FacilityID' => 1,
|
54
|
-
'ThreePLKey' => '{XXXX-XXXX-XXXX-XXXX}', 'ThreePLID' => 1},
|
55
|
-
'Items' => ['Item' => {'SKU' => '001002003A', 'CustomerID' => 1,
|
56
|
-
'InventoryMethod' => 'FIFO', 'UPC' => '001002003A'}]}
|
57
|
-
response = client.call(:create_items, :message => msg)
|
58
|
-
|
59
|
-
expect(response.http.body.scan(/<tns:extLoginData>/).count).to eq(1)
|
60
|
-
end
|
61
|
-
|
62
|
-
it "includes the 'message tag' encapsulation step" do
|
63
|
-
# This test is probably just exposing a bug while the previous
|
64
|
-
# test is using a workaround fix.
|
65
|
-
# That is just a guess though. I don't really have to properly debug the WSDL parser.
|
66
|
-
client = new_client(:endpoint => @server.url(:repeat), :no_message_tag => false,
|
67
|
-
:wsdl => Fixture.wsdl(:no_message_tag))
|
68
|
-
msg = {'extLoginData' => {'Login' => 'test.user', 'Password' => 'secret', 'FacilityID' => 1,
|
69
|
-
'ThreePLKey' => '{XXXX-XXXX-XXXX-XXXX}', 'ThreePLID' => 1},
|
70
|
-
'Items' => ['Item' => {'SKU' => '001002003A', 'CustomerID' => 1,
|
71
|
-
'InventoryMethod' => 'FIFO', 'UPC' => '001002003A'}]}
|
72
|
-
response = client.call(:create_items, :message => msg)
|
73
|
-
|
74
|
-
expect(response.http.body.scan(/<tns:extLoginData>/).count).to eq(2)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
context "global :namespaces" do
|
79
|
-
it "adds additional namespaces to the SOAP envelope" do
|
80
|
-
namespaces = { "xmlns:whatever" => "http://whatever.example.com" }
|
81
|
-
client = new_client(:endpoint => @server.url(:repeat), :namespaces => namespaces)
|
82
|
-
response = client.call(:authenticate)
|
83
|
-
|
84
|
-
expect(response.http.body).to include('xmlns:whatever="http://whatever.example.com"')
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
context 'global :follow_redirects' do
|
89
|
-
it 'sets whether or not request should follow redirects' do
|
90
|
-
client = new_client(:endpoint => @server.url, :follow_redirects => true)
|
91
|
-
|
92
|
-
HTTPI::Request.any_instance.expects(:follow_redirect=).with(true)
|
93
|
-
|
94
|
-
response = client.call(:authenticate)
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'defaults to false' do
|
98
|
-
client = new_client(:endpoint => @server.url)
|
99
|
-
|
100
|
-
HTTPI::Request.any_instance.expects(:follow_redirect=).with(false)
|
101
|
-
|
102
|
-
response = client.call(:authenticate)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context "global :proxy" do
|
107
|
-
it "sets the proxy server to use" do
|
108
|
-
proxy_url = "http://example.com"
|
109
|
-
client = new_client(:endpoint => @server.url, :proxy => proxy_url)
|
110
|
-
|
111
|
-
# TODO: find a way to integration test this [dh, 2012-12-08]
|
112
|
-
HTTPI::Request.any_instance.expects(:proxy=).with(proxy_url)
|
113
|
-
|
114
|
-
response = client.call(:authenticate)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
context "global :host" do
|
119
|
-
it "overrides the WSDL endpoint host" do
|
120
|
-
client = new_client(:wsdl => Fixture.wsdl(:no_message_tag), host: "https://example.com:8080")
|
121
|
-
|
122
|
-
request = client.build_request(:update_orders)
|
123
|
-
expect(request.url.to_s).to eq "https://example.com:8080/webserviceexternal/contracts.asmx"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
context "global :headers" do
|
128
|
-
it "sets the HTTP headers for the next request" do
|
129
|
-
client = new_client(:endpoint => @server.url(:inspect_request), :headers => { "X-Token" => "secret" })
|
130
|
-
|
131
|
-
response = client.call(:authenticate)
|
132
|
-
x_token = inspect_request(response).x_token
|
133
|
-
|
134
|
-
expect(x_token).to eq("secret")
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
context "global :open_timeout" do
|
139
|
-
it "makes the client timeout after n seconds" do
|
140
|
-
non_routable_ip = "http://192.0.2.0"
|
141
|
-
client = new_client(:endpoint => non_routable_ip, :open_timeout => 0.1)
|
142
|
-
|
143
|
-
expect { client.call(:authenticate) }.to raise_error { |error|
|
144
|
-
host_unreachable = error.kind_of? Errno::EHOSTUNREACH
|
145
|
-
net_unreachable = error.kind_of? Errno::ENETUNREACH
|
146
|
-
socket_err = error.kind_of? SocketError
|
147
|
-
if host_unreachable || net_unreachable || socket_err
|
148
|
-
warn "Warning: looks like your network may be down?!\n" +
|
149
|
-
"-> skipping spec at #{__FILE__}:#{__LINE__}"
|
150
|
-
else
|
151
|
-
# TODO: make HTTPI tag timeout errors, then depend on HTTPI::TimeoutError
|
152
|
-
# instead of a specific client error [dh, 2012-12-08]
|
153
|
-
expect(error).to be_an(HTTPClient::ConnectTimeoutError)
|
154
|
-
end
|
155
|
-
}
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
context "global :read_timeout" do
|
160
|
-
it "makes the client timeout after n seconds" do
|
161
|
-
client = new_client(:endpoint => @server.url(:timeout), :open_timeout => 0.1, :read_timeout => 0.1)
|
162
|
-
|
163
|
-
expect { client.call(:authenticate) }.
|
164
|
-
to raise_error(HTTPClient::ReceiveTimeoutError)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
context "global :encoding" do
|
169
|
-
it "changes the XML instruction" do
|
170
|
-
client = new_client(:endpoint => @server.url(:repeat), :encoding => "ISO-8859-1")
|
171
|
-
response = client.call(:authenticate)
|
172
|
-
|
173
|
-
expect(response.http.body).to match(/<\?xml version="1\.0" encoding="ISO-8859-1"\?>/)
|
174
|
-
end
|
175
|
-
|
176
|
-
it "changes the Content-Type header" do
|
177
|
-
client = new_client(:endpoint => @server.url(:inspect_request), :encoding => "ISO-8859-1")
|
178
|
-
|
179
|
-
response = client.call(:authenticate)
|
180
|
-
content_type = inspect_request(response).content_type
|
181
|
-
expect(content_type).to eq("text/xml;charset=ISO-8859-1")
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
context "global :soap_header" do
|
186
|
-
it "accepts a Hash of SOAP header information" do
|
187
|
-
client = new_client(:endpoint => @server.url(:repeat), :soap_header => { :auth_token => "secret" })
|
188
|
-
response = client.call(:authenticate)
|
189
|
-
|
190
|
-
expect(response.http.body).to include("<env:Header><authToken>secret</authToken></env:Header>")
|
191
|
-
end
|
192
|
-
|
193
|
-
it "accepts anything other than a String and calls #to_s on it" do
|
194
|
-
to_s_header = Class.new {
|
195
|
-
def to_s
|
196
|
-
"to_s_header"
|
197
|
-
end
|
198
|
-
}.new
|
199
|
-
|
200
|
-
client = new_client(:endpoint => @server.url(:repeat), :soap_header => to_s_header)
|
201
|
-
response = client.call(:authenticate)
|
202
|
-
|
203
|
-
expect(response.http.body).to include("<env:Header>to_s_header</env:Header>")
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
context "global :element_form_default" do
|
208
|
-
it "specifies whether elements should be :qualified or :unqualified" do
|
209
|
-
# qualified
|
210
|
-
client = new_client(:endpoint => @server.url(:repeat), :element_form_default => :qualified)
|
211
|
-
|
212
|
-
response = client.call(:authenticate, :message => { :user => "luke", :password => "secret" })
|
213
|
-
expect(response.http.body).to include("<tns:user>luke</tns:user>")
|
214
|
-
expect(response.http.body).to include("<tns:password>secret</tns:password>")
|
215
|
-
|
216
|
-
# unqualified
|
217
|
-
client = new_client(:endpoint => @server.url(:repeat), :element_form_default => :unqualified)
|
218
|
-
|
219
|
-
response = client.call(:authenticate, :message => { :user => "lea", :password => "top-secret" })
|
220
|
-
expect(response.http.body).to include("<user>lea</user>")
|
221
|
-
expect(response.http.body).to include("<password>top-secret</password>")
|
222
|
-
end
|
223
|
-
|
224
|
-
it "qualifies elements embedded in complex types" do
|
225
|
-
client = new_client(:endpoint => @server.url(:repeat),
|
226
|
-
:wsdl => Fixture.wsdl(:elements_in_types))
|
227
|
-
msg = {":TopLevelTransaction"=>{":Qualified"=>"A Value"}}
|
228
|
-
|
229
|
-
response = client.call(:top_level_transaction, :message => msg)
|
230
|
-
|
231
|
-
expect(response.http.body.scan(/<tns:Qualified>/).count).to eq(1)
|
232
|
-
end
|
233
|
-
|
234
|
-
end
|
235
|
-
|
236
|
-
context "global :env_namespace" do
|
237
|
-
it "when set, replaces the default namespace identifier for the SOAP envelope" do
|
238
|
-
client = new_client(:endpoint => @server.url(:repeat), :env_namespace => "soapenv")
|
239
|
-
response = client.call(:authenticate)
|
240
|
-
|
241
|
-
expect(response.http.body).to include("<soapenv:Envelope")
|
242
|
-
end
|
243
|
-
|
244
|
-
it "when not set, Savon defaults to use :env as the namespace identifier for the SOAP envelope" do
|
245
|
-
client = new_client(:endpoint => @server.url(:repeat))
|
246
|
-
response = client.call(:authenticate)
|
247
|
-
|
248
|
-
expect(response.http.body).to include("<env:Envelope")
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
context "global :soap_version" do
|
253
|
-
it "it uses the correct SOAP 1.1 namespace" do
|
254
|
-
client = new_client(:endpoint => @server.url(:repeat), :soap_version => 1)
|
255
|
-
response = client.call(:authenticate)
|
256
|
-
|
257
|
-
expect(response.http.body).to include('xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"')
|
258
|
-
end
|
259
|
-
|
260
|
-
it "it uses the correct SOAP 1.2 namespace" do
|
261
|
-
client = new_client(:endpoint => @server.url(:repeat), :soap_version => 2)
|
262
|
-
response = client.call(:authenticate)
|
263
|
-
|
264
|
-
expect(response.http.body).to include('xmlns:env="http://www.w3.org/2003/05/soap-envelope"')
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
context "global: raise_errors" do
|
269
|
-
it "when true, instructs Savon to raise SOAP fault errors" do
|
270
|
-
client = new_client(:endpoint => @server.url(:repeat), :raise_errors => true)
|
271
|
-
|
272
|
-
expect { client.call(:authenticate, :xml => Fixture.response(:soap_fault)) }.
|
273
|
-
to raise_error(Savon::SOAPFault)
|
274
|
-
|
275
|
-
begin
|
276
|
-
client.call(:authenticate, :xml => Fixture.response(:soap_fault))
|
277
|
-
rescue Savon::SOAPFault => soap_fault
|
278
|
-
# check whether the configured nori instance is used by the soap fault
|
279
|
-
expect(soap_fault.to_hash[:fault][:faultcode]).to eq("soap:Server")
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
it "when true, instructs Savon to raise HTTP errors" do
|
284
|
-
client = new_client(:endpoint => @server.url(404), :raise_errors => true)
|
285
|
-
expect { client.call(:authenticate) }.to raise_error(Savon::HTTPError)
|
286
|
-
end
|
287
|
-
|
288
|
-
it "when false, instructs Savon to not raise SOAP fault errors" do
|
289
|
-
client = new_client(:endpoint => @server.url(:repeat), :raise_errors => false)
|
290
|
-
response = client.call(:authenticate, :xml => Fixture.response(:soap_fault))
|
291
|
-
|
292
|
-
expect(response).to_not be_successful
|
293
|
-
expect(response).to be_a_soap_fault
|
294
|
-
end
|
295
|
-
|
296
|
-
it "when false, instructs Savon to not raise HTTP errors" do
|
297
|
-
client = new_client(:endpoint => @server.url(404), :raise_errors => false)
|
298
|
-
response = client.call(:authenticate)
|
299
|
-
|
300
|
-
expect(response).to_not be_successful
|
301
|
-
expect(response).to be_a_http_error
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
context "global :log" do
|
306
|
-
it "instructs Savon not to log SOAP requests and responses" do
|
307
|
-
stdout = mock_stdout {
|
308
|
-
client = new_client(:endpoint => @server.url, :log => false)
|
309
|
-
client.call(:authenticate)
|
310
|
-
}
|
311
|
-
|
312
|
-
expect(stdout.string).to be_empty
|
313
|
-
end
|
314
|
-
|
315
|
-
it "silences HTTPI as well" do
|
316
|
-
HTTPI.expects(:log=).with(false)
|
317
|
-
new_client(:log => false)
|
318
|
-
end
|
319
|
-
|
320
|
-
it "instructs Savon to log SOAP requests and responses" do
|
321
|
-
stdout = mock_stdout do
|
322
|
-
client = new_client(:endpoint => @server.url, :log => true)
|
323
|
-
client.call(:authenticate)
|
324
|
-
end
|
325
|
-
|
326
|
-
expect(stdout.string).to include("INFO -- : SOAP request")
|
327
|
-
end
|
328
|
-
|
329
|
-
it "turns HTTPI logging back on as well" do
|
330
|
-
HTTPI.expects(:log=).with(true)
|
331
|
-
new_client(:log => true)
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
context "global :logger" do
|
336
|
-
it "defaults to an instance of Ruby's standard Logger" do
|
337
|
-
logger = new_client.globals[:logger]
|
338
|
-
expect(logger).to be_a(Logger)
|
339
|
-
end
|
340
|
-
|
341
|
-
it "allows a custom logger to be set" do
|
342
|
-
custom_logger = Logger.new($stdout)
|
343
|
-
|
344
|
-
client = new_client(:logger => custom_logger, :log => true)
|
345
|
-
logger = client.globals[:logger]
|
346
|
-
|
347
|
-
expect(logger).to eq(custom_logger)
|
348
|
-
end
|
349
|
-
|
350
|
-
it "sets the logger of HTTPI as well" do
|
351
|
-
custom_logger = Logger.new($stdout)
|
352
|
-
|
353
|
-
client = new_client(:logger => custom_logger, :log => true)
|
354
|
-
|
355
|
-
expect(HTTPI.logger).to be custom_logger
|
356
|
-
end
|
357
|
-
|
358
|
-
end
|
359
|
-
|
360
|
-
context "global :log_level" do
|
361
|
-
it "allows changing the Logger's log level to :debug" do
|
362
|
-
client = new_client(:log_level => :debug)
|
363
|
-
level = client.globals[:logger].level
|
364
|
-
|
365
|
-
expect(level).to eq(0)
|
366
|
-
end
|
367
|
-
|
368
|
-
it "allows changing the Logger's log level to :info" do
|
369
|
-
client = new_client(:log_level => :info)
|
370
|
-
level = client.globals[:logger].level
|
371
|
-
|
372
|
-
expect(level).to eq(1)
|
373
|
-
end
|
374
|
-
|
375
|
-
it "allows changing the Logger's log level to :warn" do
|
376
|
-
client = new_client(:log_level => :warn)
|
377
|
-
level = client.globals[:logger].level
|
378
|
-
|
379
|
-
expect(level).to eq(2)
|
380
|
-
end
|
381
|
-
|
382
|
-
it "allows changing the Logger's log level to :error" do
|
383
|
-
client = new_client(:log_level => :error)
|
384
|
-
level = client.globals[:logger].level
|
385
|
-
|
386
|
-
expect(level).to eq(3)
|
387
|
-
end
|
388
|
-
|
389
|
-
it "allows changing the Logger's log level to :fatal" do
|
390
|
-
client = new_client(:log_level => :fatal)
|
391
|
-
level = client.globals[:logger].level
|
392
|
-
|
393
|
-
expect(level).to eq(4)
|
394
|
-
end
|
395
|
-
|
396
|
-
it "raises when the given level is not valid" do
|
397
|
-
expect { new_client(:log_level => :invalid) }.
|
398
|
-
to raise_error(ArgumentError, /Invalid log level: :invalid/)
|
399
|
-
end
|
400
|
-
end
|
401
|
-
|
402
|
-
context "global :log_headers" do
|
403
|
-
it "instructs Savon to log SOAP requests and responses headers" do
|
404
|
-
stdout = mock_stdout {
|
405
|
-
client = new_client(:endpoint => @server.url, :log => true)
|
406
|
-
client.call(:authenticate)
|
407
|
-
}
|
408
|
-
soap_header = stdout.string.include? "Content-Type"
|
409
|
-
expect(soap_header).to be true
|
410
|
-
end
|
411
|
-
|
412
|
-
it "stops Savon from logging SOAP requests and responses headers" do
|
413
|
-
stdout = mock_stdout {
|
414
|
-
client = new_client(:endpoint => @server.url, :log => true, :log_headers => false)
|
415
|
-
client.call(:authenticate)
|
416
|
-
}
|
417
|
-
soap_header = stdout.string.include? "Content-Type"
|
418
|
-
expect(soap_header).to be false
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
context "global :ssl_version" do
|
423
|
-
it "sets the SSL version to use" do
|
424
|
-
HTTPI::Auth::SSL.any_instance.expects(:ssl_version=).with(:TLSv1).twice
|
425
|
-
|
426
|
-
client = new_client(:endpoint => @server.url, :ssl_version => :TLSv1)
|
427
|
-
client.call(:authenticate)
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
context "global :ssl_min_version" do
|
432
|
-
it "sets the SSL min_version to use" do
|
433
|
-
HTTPI::Auth::SSL.any_instance.expects(:min_version=).with(:TLS1_2).twice
|
434
|
-
|
435
|
-
client = new_client(:endpoint => @server.url, :ssl_min_version => :TLS1_2)
|
436
|
-
client.call(:authenticate)
|
437
|
-
end
|
438
|
-
end
|
439
|
-
|
440
|
-
context "global :ssl_max_version" do
|
441
|
-
it "sets the SSL max_version to use" do
|
442
|
-
HTTPI::Auth::SSL.any_instance.expects(:max_version=).with(:TLS1_2).twice
|
443
|
-
|
444
|
-
client = new_client(:endpoint => @server.url, :ssl_max_version => :TLS1_2)
|
445
|
-
client.call(:authenticate)
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
context "global :ssl_verify_mode" do
|
450
|
-
it "sets the verify mode to use" do
|
451
|
-
HTTPI::Auth::SSL.any_instance.expects(:verify_mode=).with(:peer).twice
|
452
|
-
|
453
|
-
client = new_client(:endpoint => @server.url, :ssl_verify_mode => :peer)
|
454
|
-
client.call(:authenticate)
|
455
|
-
end
|
456
|
-
end
|
457
|
-
|
458
|
-
context "global :ssl_ciphers" do
|
459
|
-
it "sets the ciphers to use" do
|
460
|
-
HTTPI::Auth::SSL.any_instance.expects(:ciphers=).with(:none).twice
|
461
|
-
|
462
|
-
client = new_client(:endpoint => @server.url, :ssl_ciphers => :none)
|
463
|
-
client.call(:authenticate)
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
context "global :ssl_cert_key_file" do
|
468
|
-
it "sets the cert key file to use" do
|
469
|
-
cert_key = File.expand_path("../../fixtures/ssl/client_key.pem", __FILE__)
|
470
|
-
HTTPI::Auth::SSL.any_instance.expects(:cert_key_file=).with(cert_key).twice
|
471
|
-
|
472
|
-
client = new_client(:endpoint => @server.url, :ssl_cert_key_file => cert_key)
|
473
|
-
client.call(:authenticate)
|
474
|
-
end
|
475
|
-
end
|
476
|
-
|
477
|
-
context "global :ssl_cert_key" do
|
478
|
-
it "sets the cert key to use" do
|
479
|
-
cert_key = File.open(File.expand_path("../../fixtures/ssl/client_key.pem", __FILE__)).read
|
480
|
-
HTTPI::Auth::SSL.any_instance.expects(:cert_key=).with(cert_key).twice
|
481
|
-
|
482
|
-
client = new_client(:endpoint => @server.url, :ssl_cert_key => cert_key)
|
483
|
-
client.call(:authenticate)
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
|
488
|
-
context "global :ssl_cert_key_password" do
|
489
|
-
it "sets the encrypted cert key file password to use" do
|
490
|
-
cert_key = File.expand_path("../../fixtures/ssl/client_encrypted_key.pem", __FILE__)
|
491
|
-
cert_key_pass = "secure-password!42"
|
492
|
-
HTTPI::Auth::SSL.any_instance.expects(:cert_key_file=).with(cert_key).twice
|
493
|
-
HTTPI::Auth::SSL.any_instance.expects(:cert_key_password=).with(cert_key_pass).twice
|
494
|
-
|
495
|
-
client = new_client(:endpoint => @server.url, :ssl_cert_key_file => cert_key, :ssl_cert_key_password => cert_key_pass)
|
496
|
-
client.call(:authenticate)
|
497
|
-
end
|
498
|
-
|
499
|
-
end
|
500
|
-
|
501
|
-
context "global :ssl_cert_file" do
|
502
|
-
it "sets the cert file to use" do
|
503
|
-
cert = File.expand_path("../../fixtures/ssl/client_cert.pem", __FILE__)
|
504
|
-
HTTPI::Auth::SSL.any_instance.expects(:cert_file=).with(cert).twice
|
505
|
-
|
506
|
-
client = new_client(:endpoint => @server.url, :ssl_cert_file => cert)
|
507
|
-
client.call(:authenticate)
|
508
|
-
end
|
509
|
-
end
|
510
|
-
|
511
|
-
context "global :ssl_cert" do
|
512
|
-
it "sets the cert to use" do
|
513
|
-
cert = File.open(File.expand_path("../../fixtures/ssl/client_cert.pem", __FILE__)).read
|
514
|
-
HTTPI::Auth::SSL.any_instance.expects(:cert=).with(cert).twice
|
515
|
-
|
516
|
-
client = new_client(:endpoint => @server.url, :ssl_cert => cert)
|
517
|
-
client.call(:authenticate)
|
518
|
-
end
|
519
|
-
end
|
520
|
-
|
521
|
-
context "global :ssl_ca_cert_file" do
|
522
|
-
it "sets the ca cert file to use" do
|
523
|
-
ca_cert = File.expand_path("../../fixtures/ssl/client_cert.pem", __FILE__)
|
524
|
-
HTTPI::Auth::SSL.any_instance.expects(:ca_cert_file=).with(ca_cert).twice
|
525
|
-
|
526
|
-
client = new_client(:endpoint => @server.url, :ssl_ca_cert_file => ca_cert)
|
527
|
-
client.call(:authenticate)
|
528
|
-
end
|
529
|
-
end
|
530
|
-
|
531
|
-
context "global :ssl_ca_cert_path" do
|
532
|
-
it "sets the ca cert path to use" do
|
533
|
-
ca_cert_path = "../../fixtures/ssl"
|
534
|
-
HTTPI::Auth::SSL.any_instance.expects(:ca_cert_path=).with(ca_cert_path).twice
|
535
|
-
|
536
|
-
client = new_client(:endpoint => @server.url, :ssl_ca_cert_path => ca_cert_path)
|
537
|
-
client.call(:authenticate)
|
538
|
-
end
|
539
|
-
end
|
540
|
-
|
541
|
-
context "global :ssl_ca_cert_store" do
|
542
|
-
it "sets the cert store to use" do
|
543
|
-
cert_store = OpenSSL::X509::Store.new
|
544
|
-
HTTPI::Auth::SSL.any_instance.expects(:cert_store=).with(cert_store).twice
|
545
|
-
|
546
|
-
client = new_client(:endpoint => @server.url, :ssl_cert_store => cert_store)
|
547
|
-
client.call(:authenticate)
|
548
|
-
end
|
549
|
-
end
|
550
|
-
|
551
|
-
context "global :ssl_ca_cert" do
|
552
|
-
it "sets the ca cert file to use" do
|
553
|
-
ca_cert = File.open(File.expand_path("../../fixtures/ssl/client_cert.pem", __FILE__)).read
|
554
|
-
HTTPI::Auth::SSL.any_instance.expects(:ca_cert=).with(ca_cert).twice
|
555
|
-
|
556
|
-
client = new_client(:endpoint => @server.url, :ssl_ca_cert => ca_cert)
|
557
|
-
client.call(:authenticate)
|
558
|
-
end
|
559
|
-
end
|
560
|
-
|
561
|
-
|
562
|
-
context "global :basic_auth" do
|
563
|
-
it "sets the basic auth credentials" do
|
564
|
-
client = new_client(:endpoint => @server.url(:basic_auth), :basic_auth => ["admin", "secret"])
|
565
|
-
response = client.call(:authenticate)
|
566
|
-
|
567
|
-
expect(response.http.body).to eq("basic-auth")
|
568
|
-
end
|
569
|
-
end
|
570
|
-
|
571
|
-
context "global :digest_auth" do
|
572
|
-
it "sets the digest auth credentials" do
|
573
|
-
client = new_client(:endpoint => @server.url(:digest_auth), :digest_auth => ["admin", "secret"])
|
574
|
-
response = client.call(:authenticate)
|
575
|
-
|
576
|
-
expect(response.http.body).to eq("digest-auth")
|
577
|
-
end
|
578
|
-
end
|
579
|
-
|
580
|
-
context "global :ntlm" do
|
581
|
-
it "sets the ntlm credentials to use" do
|
582
|
-
credentials = ["admin", "secret"]
|
583
|
-
client = new_client(:endpoint => @server.url, :ntlm => credentials)
|
584
|
-
|
585
|
-
# TODO: find a way to integration test this. including an entire ntlm
|
586
|
-
# server implementation seems a bit over the top though.
|
587
|
-
HTTPI::Auth::Config.any_instance.expects(:ntlm).with(*credentials)
|
588
|
-
|
589
|
-
response = client.call(:authenticate)
|
590
|
-
end
|
591
|
-
end
|
592
|
-
|
593
|
-
context "global :filters" do
|
594
|
-
it "filters a list of XML tags from logged SOAP messages" do
|
595
|
-
captured = mock_stdout do
|
596
|
-
client = new_client(:endpoint => @server.url(:repeat), :log => true)
|
597
|
-
client.globals[:filters] << :password
|
598
|
-
|
599
|
-
message = { :username => "luke", :password => "secret" }
|
600
|
-
client.call(:authenticate, :message => message)
|
601
|
-
end
|
602
|
-
|
603
|
-
captured.rewind
|
604
|
-
messages = captured.readlines.join("\n")
|
605
|
-
|
606
|
-
expect(messages).to include("<password>***FILTERED***</password>")
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
context "global :pretty_print_xml" do
|
611
|
-
it "is a nice but expensive way to debug XML messages" do
|
612
|
-
captured = mock_stdout do
|
613
|
-
client = new_client(
|
614
|
-
:endpoint => @server.url(:repeat),
|
615
|
-
:pretty_print_xml => true,
|
616
|
-
:log => true)
|
617
|
-
client.globals[:logger].formatter = proc { |*, msg| "#{msg}\n" }
|
618
|
-
|
619
|
-
client.call(:authenticate)
|
620
|
-
end
|
621
|
-
|
622
|
-
captured.rewind
|
623
|
-
messages = captured.readlines.join("\n")
|
624
|
-
|
625
|
-
expect(messages).to match(/\n<env:Envelope/)
|
626
|
-
expect(messages).to match(/\n <env:Body/)
|
627
|
-
expect(messages).to match(/\n <tns:authenticate/)
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
|
-
context ":wsse_auth" do
|
632
|
-
let(:username) { "luke" }
|
633
|
-
let(:password) { "secret" }
|
634
|
-
let(:request) { response.http.body }
|
635
|
-
|
636
|
-
shared_examples "WSSE basic auth" do
|
637
|
-
it "adds WSSE basic auth information to the request" do
|
638
|
-
# the header and wsse security node
|
639
|
-
wsse_namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
|
640
|
-
expect(request).to include("<env:Header><wsse:Security xmlns:wsse=\"#{wsse_namespace}\">")
|
641
|
-
|
642
|
-
# split up to prevent problems with unordered Hash attributes in 1.8 [dh, 2012-12-13]
|
643
|
-
expect(request).to include("<wsse:UsernameToken")
|
644
|
-
expect(request).to include("wsu:Id=\"UsernameToken-1\"")
|
645
|
-
expect(request).to include("xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"")
|
646
|
-
|
647
|
-
# the username and password node with type attribute
|
648
|
-
expect(request).to include("<wsse:Username>#{username}</wsse:Username>")
|
649
|
-
password_text = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
|
650
|
-
expect(request).to include("<wsse:Password Type=\"#{password_text}\">#{password}</wsse:Password>")
|
651
|
-
end
|
652
|
-
end
|
653
|
-
|
654
|
-
shared_examples "WSSE digest auth" do
|
655
|
-
it "adds WSSE digest auth information to the request" do
|
656
|
-
# the header and wsse security node
|
657
|
-
wsse_namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
|
658
|
-
expect(request).to include("<env:Header><wsse:Security xmlns:wsse=\"#{wsse_namespace}\">")
|
659
|
-
|
660
|
-
# split up to prevent problems with unordered Hash attributes in 1.8 [dh, 2012-12-13]
|
661
|
-
expect(request).to include("<wsse:UsernameToken")
|
662
|
-
expect(request).to include("wsu:Id=\"UsernameToken-1\"")
|
663
|
-
expect(request).to include("xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"")
|
664
|
-
|
665
|
-
# the username node
|
666
|
-
expect(request).to include("<wsse:Username>#{username}</wsse:Username>")
|
667
|
-
|
668
|
-
# the nonce node
|
669
|
-
expect(request).to match(/<wsse:Nonce.*>.+\n?<\/wsse:Nonce>/)
|
670
|
-
|
671
|
-
# the created node with a timestamp
|
672
|
-
expect(request).to match(/<wsu:Created>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*<\/wsu:Created>/)
|
673
|
-
|
674
|
-
# the password node contains the encrypted value
|
675
|
-
password_digest = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"
|
676
|
-
expect(request).to match(/<wsse:Password Type=\"#{password_digest}\">.+<\/wsse:Password>/)
|
677
|
-
expect(request).to_not include(password)
|
678
|
-
end
|
679
|
-
end
|
680
|
-
|
681
|
-
shared_examples "no WSSE auth" do
|
682
|
-
it "does not add WSSE auth to the request" do
|
683
|
-
expect(request).not_to include("<wsse:UsernameToken")
|
684
|
-
end
|
685
|
-
end
|
686
|
-
|
687
|
-
describe "global" do
|
688
|
-
context "enabled" do
|
689
|
-
context "without digest" do
|
690
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat), :wsse_auth => [username, password]) }
|
691
|
-
let(:response) { client.call(:authenticate) }
|
692
|
-
include_examples "WSSE basic auth"
|
693
|
-
end
|
694
|
-
|
695
|
-
context "with digest" do
|
696
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat), :wsse_auth => [username, password, :digest]) }
|
697
|
-
let(:response) { client.call(:authenticate) }
|
698
|
-
include_examples "WSSE digest auth"
|
699
|
-
end
|
700
|
-
|
701
|
-
context "local override" do
|
702
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat), :wsse_auth => ["luke", "secret"]) }
|
703
|
-
|
704
|
-
context "enabled" do
|
705
|
-
let(:username) { "lea" }
|
706
|
-
let(:password) { "top-secret" }
|
707
|
-
|
708
|
-
context "without digest" do
|
709
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_auth(username, password)} }
|
710
|
-
include_examples "WSSE basic auth"
|
711
|
-
end
|
712
|
-
|
713
|
-
context "with digest" do
|
714
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_auth(username, password, :digest)} }
|
715
|
-
include_examples "WSSE digest auth"
|
716
|
-
end
|
717
|
-
end
|
718
|
-
|
719
|
-
context "disabled" do
|
720
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_auth(false)} }
|
721
|
-
include_examples "no WSSE auth"
|
722
|
-
end
|
723
|
-
|
724
|
-
context "set to nil" do
|
725
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_auth(nil)} }
|
726
|
-
include_examples "WSSE basic auth"
|
727
|
-
end
|
728
|
-
end
|
729
|
-
|
730
|
-
context "global" do
|
731
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat), :wsse_auth => [username, password, :digest]) }
|
732
|
-
let(:response) { client.call(:authenticate) }
|
733
|
-
include_examples "WSSE digest auth"
|
734
|
-
end
|
735
|
-
end
|
736
|
-
|
737
|
-
context "not enabled" do
|
738
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat)) }
|
739
|
-
|
740
|
-
describe "local" do
|
741
|
-
context "enabled" do
|
742
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_auth(username, password, :digest)} }
|
743
|
-
include_examples "WSSE digest auth"
|
744
|
-
end
|
745
|
-
|
746
|
-
context "disabled" do
|
747
|
-
let(:response) { client.call(:authenticate) { |locals| locals.wsse_auth(false)} }
|
748
|
-
include_examples "no WSSE auth"
|
749
|
-
end
|
750
|
-
|
751
|
-
context "set to nil" do
|
752
|
-
let(:response) { client.call(:authenticate) { |locals| locals.wsse_auth(nil)} }
|
753
|
-
include_examples "no WSSE auth"
|
754
|
-
end
|
755
|
-
end
|
756
|
-
end
|
757
|
-
end
|
758
|
-
end
|
759
|
-
|
760
|
-
context ":wsse_timestamp" do
|
761
|
-
let(:request) { response.http.body }
|
762
|
-
|
763
|
-
shared_examples "WSSE timestamp" do
|
764
|
-
it "adds WSSE timestamp auth information to the request" do
|
765
|
-
# the header and wsse security node
|
766
|
-
wsse_namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
|
767
|
-
expect(request).to include("<env:Header><wsse:Security xmlns:wsse=\"#{wsse_namespace}\">")
|
768
|
-
|
769
|
-
# split up to prevent problems with unordered Hash attributes in 1.8 [dh, 2012-12-13]
|
770
|
-
expect(request).to include("<wsu:Timestamp")
|
771
|
-
expect(request).to include("wsu:Id=\"Timestamp-1\"")
|
772
|
-
expect(request).to include("xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"")
|
773
|
-
|
774
|
-
# the created node with a timestamp
|
775
|
-
expect(request).to match(/<wsu:Created>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*<\/wsu:Created>/)
|
776
|
-
|
777
|
-
# the expires node with a timestamp
|
778
|
-
expect(request).to match(/<wsu:Expires>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*<\/wsu:Expires>/)
|
779
|
-
end
|
780
|
-
end
|
781
|
-
|
782
|
-
shared_examples "no WSSE timestamp" do
|
783
|
-
it "does not add WSSE timestamp to the request" do
|
784
|
-
expect(request).not_to include("<wsu:Timestamp")
|
785
|
-
end
|
786
|
-
end
|
787
|
-
|
788
|
-
describe "global" do
|
789
|
-
context "enabled" do
|
790
|
-
context "through block without arguments" do
|
791
|
-
let(:client) do
|
792
|
-
new_client(:endpoint => @server.url(:repeat)) do |globals|
|
793
|
-
globals.wsse_timestamp
|
794
|
-
end
|
795
|
-
end
|
796
|
-
let(:response) { client.call(:authenticate) }
|
797
|
-
include_examples "WSSE timestamp"
|
798
|
-
end
|
799
|
-
|
800
|
-
context "through initializer options" do
|
801
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat), :wsse_timestamp => true) }
|
802
|
-
let(:response) { client.call(:authenticate) }
|
803
|
-
include_examples "WSSE timestamp"
|
804
|
-
end
|
805
|
-
|
806
|
-
context "with local override" do
|
807
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat), :wsse_timestamp => true) }
|
808
|
-
context "enabled" do
|
809
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_timestamp} }
|
810
|
-
include_examples "WSSE timestamp"
|
811
|
-
end
|
812
|
-
context "disabled" do
|
813
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_timestamp(false) } }
|
814
|
-
include_examples "no WSSE timestamp"
|
815
|
-
end
|
816
|
-
context "set to nil" do
|
817
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_timestamp(nil) } }
|
818
|
-
include_examples "WSSE timestamp"
|
819
|
-
end
|
820
|
-
end
|
821
|
-
end
|
822
|
-
|
823
|
-
context "not enabled" do
|
824
|
-
let(:client) { new_client(:endpoint => @server.url(:repeat)) }
|
825
|
-
describe "local" do
|
826
|
-
context "enabled" do
|
827
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_timestamp} }
|
828
|
-
include_examples "WSSE timestamp"
|
829
|
-
end
|
830
|
-
context "disabled" do
|
831
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_timestamp(false) } }
|
832
|
-
include_examples "no WSSE timestamp"
|
833
|
-
end
|
834
|
-
context "set to nil" do
|
835
|
-
let(:response) { client.call(:authenticate) {|locals| locals.wsse_timestamp(nil) } }
|
836
|
-
include_examples "no WSSE timestamp"
|
837
|
-
end
|
838
|
-
end
|
839
|
-
end
|
840
|
-
end
|
841
|
-
end
|
842
|
-
|
843
|
-
context "global :strip_namespaces" do
|
844
|
-
it "can be changed to not strip any namespaces" do
|
845
|
-
client = new_client(
|
846
|
-
:endpoint => @server.url(:repeat),
|
847
|
-
:convert_response_tags_to => lambda { |tag| tag.snakecase },
|
848
|
-
:strip_namespaces => false
|
849
|
-
)
|
850
|
-
|
851
|
-
response = client.call(:authenticate, :xml => Fixture.response(:authentication))
|
852
|
-
|
853
|
-
expect(response.hash["soap:envelope"]["soap:body"]).to include("ns2:authenticate_response")
|
854
|
-
end
|
855
|
-
end
|
856
|
-
|
857
|
-
context "global :convert_request_keys_to" do
|
858
|
-
it "changes how Hash message key Symbols are translated to XML tags for the request" do
|
859
|
-
client = new_client_without_wsdl do |globals|
|
860
|
-
globals.endpoint @server.url(:repeat)
|
861
|
-
globals.namespace "http://v1.example.com"
|
862
|
-
globals.convert_request_keys_to :camelcase # or one of [:lower_camelcase, :upcase, :none]
|
863
|
-
end
|
864
|
-
|
865
|
-
response = client.call(:find_user) do |locals|
|
866
|
-
locals.message(:user_name => "luke", "pass_word" => "secret")
|
867
|
-
end
|
868
|
-
|
869
|
-
request = response.http.body
|
870
|
-
|
871
|
-
# split into multiple assertions thanks to 1.8
|
872
|
-
expect(request).to include("<wsdl:FindUser>")
|
873
|
-
expect(request).to include("<UserName>luke</UserName>")
|
874
|
-
expect(request).to include("<pass_word>secret</pass_word>")
|
875
|
-
end
|
876
|
-
end
|
877
|
-
|
878
|
-
context "global :convert_response_tags_to" do
|
879
|
-
it "changes how XML tags from the SOAP response are translated into Hash keys" do
|
880
|
-
client = new_client(:endpoint => @server.url(:repeat), :convert_response_tags_to => lambda { |tag| tag.snakecase.upcase })
|
881
|
-
response = client.call(:authenticate, :xml => Fixture.response(:authentication))
|
882
|
-
|
883
|
-
expect(response.hash["ENVELOPE"]["BODY"]).to include("AUTHENTICATE_RESPONSE")
|
884
|
-
end
|
885
|
-
|
886
|
-
it "accepts a block in the block-based interface" do
|
887
|
-
client = Savon.client do |globals|
|
888
|
-
globals.log false
|
889
|
-
globals.wsdl Fixture.wsdl(:authentication)
|
890
|
-
globals.endpoint @server.url(:repeat)
|
891
|
-
globals.convert_response_tags_to { |tag| tag.snakecase.upcase }
|
892
|
-
end
|
893
|
-
|
894
|
-
response = client.call(:authenticate) do |locals|
|
895
|
-
locals.xml Fixture.response(:authentication)
|
896
|
-
end
|
897
|
-
|
898
|
-
expect(response.hash["ENVELOPE"]["BODY"]).to include("AUTHENTICATE_RESPONSE")
|
899
|
-
end
|
900
|
-
end
|
901
|
-
|
902
|
-
context "global :convert_attributes_to" do
|
903
|
-
it "changes how XML tag attributes from the SOAP response are translated into Hash keys" do
|
904
|
-
client = new_client(:endpoint => @server.url(:repeat), :convert_attributes_to => lambda {|k,v| [k,v]})
|
905
|
-
response = client.call(:authenticate, :xml => Fixture.response(:f5))
|
906
|
-
expect(response.body[:get_agent_listen_address_response][:return][:item].first[:ipport][:address]).to eq({:"@s:type"=>"y:string"})
|
907
|
-
end
|
908
|
-
|
909
|
-
it "strips the attributes if an appropriate lambda is set" do
|
910
|
-
client = new_client(:endpoint => @server.url(:repeat), :convert_attributes_to => lambda {|k,v| []})
|
911
|
-
response = client.call(:authenticate, :xml => Fixture.response(:f5))
|
912
|
-
expect(response.body[:get_agent_listen_address_response][:return][:item].first[:ipport][:address]).to eq(nil)
|
913
|
-
end
|
914
|
-
|
915
|
-
it "accepts a block in the block-based interface" do
|
916
|
-
client = Savon.client do |globals|
|
917
|
-
globals.log false
|
918
|
-
globals.wsdl Fixture.wsdl(:authentication)
|
919
|
-
globals.endpoint @server.url(:repeat)
|
920
|
-
globals.convert_attributes_to {|k,v| [k,v]}
|
921
|
-
end
|
922
|
-
|
923
|
-
response = client.call(:authenticate) do |locals|
|
924
|
-
locals.xml Fixture.response(:f5)
|
925
|
-
end
|
926
|
-
|
927
|
-
expect(response.body[:get_agent_listen_address_response][:return][:item].first[:ipport][:address]).to eq({:"@s:type"=>"y:string"})
|
928
|
-
end
|
929
|
-
end
|
930
|
-
|
931
|
-
context 'global: :adapter' do
|
932
|
-
it 'passes option to Wasabi initializer for WSDL fetching' do
|
933
|
-
## I want to use there something similar to the next mock expectation, but I can't
|
934
|
-
## as due to how Savon sets up Wasabi::Document and Wasabi::Document initialize itself
|
935
|
-
## adapter= method is called first time with nil and second time with adapter. [Envek, 2014-05-03]
|
936
|
-
# Wasabi::Document.any_instance.expects(:adapter=).with(:fake_adapter_for_test)
|
937
|
-
client = Savon.client(
|
938
|
-
:log => false,
|
939
|
-
:wsdl => @server.url(:authentication),
|
940
|
-
:adapter => :fake_adapter_for_test,
|
941
|
-
)
|
942
|
-
operations = client.operations
|
943
|
-
expect(operations).to eq([:authenticate])
|
944
|
-
expect(FakeAdapterForTest.class_variable_get(:@@requests).size).to eq(1)
|
945
|
-
expect(FakeAdapterForTest.class_variable_get(:@@requests).first.url).to eq(URI.parse(@server.url(:authentication)))
|
946
|
-
expect(FakeAdapterForTest.class_variable_get(:@@methods)).to eq([:get])
|
947
|
-
end
|
948
|
-
|
949
|
-
it 'instructs HTTPI to use provided adapter for performing SOAP requests' do
|
950
|
-
client = new_client_without_wsdl(
|
951
|
-
:endpoint => @server.url(:repeat),
|
952
|
-
:namespace => "http://v1.example.com",
|
953
|
-
:adapter => :adapter_for_test,
|
954
|
-
)
|
955
|
-
response = client.call(:authenticate)
|
956
|
-
expect(response.http.body).to include('xmlns:wsdl="http://v1.example.com"')
|
957
|
-
expect(response.http.body).to include('<wsdl:authenticate>')
|
958
|
-
expect(AdapterForTest.class_variable_get(:@@requests).size).to eq(1)
|
959
|
-
expect(AdapterForTest.class_variable_get(:@@requests).first.url).to eq(URI.parse(@server.url(:repeat)))
|
960
|
-
expect(AdapterForTest.class_variable_get(:@@methods)).to eq([:post])
|
961
|
-
end
|
962
|
-
end
|
963
|
-
|
964
|
-
context "global and request :soap_header" do
|
965
|
-
it "merges the headers if both were provided as Hashes" do
|
966
|
-
global_soap_header = {
|
967
|
-
:global_header => { :auth_token => "secret" },
|
968
|
-
:merged => { :global => true }
|
969
|
-
}
|
970
|
-
|
971
|
-
request_soap_header = {
|
972
|
-
:request_header => { :auth_token => "secret" },
|
973
|
-
:merged => { :request => true }
|
974
|
-
}
|
975
|
-
|
976
|
-
client = new_client(:endpoint => @server.url(:repeat), :soap_header => global_soap_header)
|
977
|
-
|
978
|
-
response = client.call(:authenticate, :soap_header => request_soap_header)
|
979
|
-
request_body = response.http.body
|
980
|
-
|
981
|
-
expect(request_body).to include("<globalHeader><authToken>secret</authToken></globalHeader>")
|
982
|
-
expect(request_body).to include("<requestHeader><authToken>secret</authToken></requestHeader>")
|
983
|
-
expect(request_body).to include("<merged><request>true</request></merged>")
|
984
|
-
end
|
985
|
-
|
986
|
-
it "prefers the request over the global option if at least one of them is not a Hash" do
|
987
|
-
global_soap_header = "<global>header</global>"
|
988
|
-
request_soap_header = "<request>header</request>"
|
989
|
-
|
990
|
-
client = new_client(:endpoint => @server.url(:repeat), :soap_header => global_soap_header)
|
991
|
-
|
992
|
-
response = client.call(:authenticate, :soap_header => request_soap_header)
|
993
|
-
request_body = response.http.body
|
994
|
-
|
995
|
-
expect(request_body).to include("<env:Header><request>header</request></env:Header>")
|
996
|
-
end
|
997
|
-
end
|
998
|
-
|
999
|
-
context "request :soap_header" do
|
1000
|
-
it "accepts a Hash of SOAP header information" do
|
1001
|
-
client = new_client(:endpoint => @server.url(:repeat))
|
1002
|
-
|
1003
|
-
response = client.call(:authenticate, :soap_header => { :auth_token => "secret" })
|
1004
|
-
expect(response.http.body).to include("<env:Header><authToken>secret</authToken></env:Header>")
|
1005
|
-
end
|
1006
|
-
|
1007
|
-
it "accepts anything other than a String and calls #to_s on it" do
|
1008
|
-
to_s_header = Class.new {
|
1009
|
-
def to_s
|
1010
|
-
"to_s_header"
|
1011
|
-
end
|
1012
|
-
}.new
|
1013
|
-
|
1014
|
-
client = new_client(:endpoint => @server.url(:repeat))
|
1015
|
-
|
1016
|
-
response = client.call(:authenticate, :soap_header => to_s_header)
|
1017
|
-
expect(response.http.body).to include("<env:Header>to_s_header</env:Header>")
|
1018
|
-
end
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
context "request: message_tag" do
|
1022
|
-
it "when set, changes the SOAP message tag" do
|
1023
|
-
response = new_client(:endpoint => @server.url(:repeat)).call(:authenticate, :message_tag => :doAuthenticate)
|
1024
|
-
expect(response.http.body).to include("<tns:doAuthenticate></tns:doAuthenticate>")
|
1025
|
-
end
|
1026
|
-
|
1027
|
-
it "without it, Savon tries to get the message tag from the WSDL document" do
|
1028
|
-
response = new_client(:endpoint => @server.url(:repeat)).call(:authenticate)
|
1029
|
-
expect(response.http.body).to include("<tns:authenticate></tns:authenticate>")
|
1030
|
-
end
|
1031
|
-
|
1032
|
-
it "without the option and a WSDL, Savon defaults to Gyoku to create the name" do
|
1033
|
-
client = Savon.client(:endpoint => @server.url(:repeat), :namespace => "http://v1.example.com", :log => false)
|
1034
|
-
|
1035
|
-
response = client.call(:init_authentication)
|
1036
|
-
expect(response.http.body).to include("<wsdl:initAuthentication></wsdl:initAuthentication>")
|
1037
|
-
end
|
1038
|
-
end
|
1039
|
-
|
1040
|
-
context "request: attributes" do
|
1041
|
-
it "when set, adds the attributes to the message tag" do
|
1042
|
-
client = new_client(:endpoint => @server.url(:repeat))
|
1043
|
-
response = client.call(:authenticate, :attributes => { "Token" => "secret"})
|
1044
|
-
|
1045
|
-
expect(response.http.body).to include('<tns:authenticate Token="secret">')
|
1046
|
-
end
|
1047
|
-
end
|
1048
|
-
|
1049
|
-
context "request: soap_action" do
|
1050
|
-
it "without it, Savon tries to get the SOAPAction from the WSDL document and falls back to Gyoku" do
|
1051
|
-
client = new_client(:endpoint => @server.url(:inspect_request))
|
1052
|
-
|
1053
|
-
response = client.call(:authenticate)
|
1054
|
-
soap_action = inspect_request(response).soap_action
|
1055
|
-
expect(soap_action).to eq('"authenticate"')
|
1056
|
-
end
|
1057
|
-
|
1058
|
-
it "when set, changes the SOAPAction HTTP header" do
|
1059
|
-
client = new_client(:endpoint => @server.url(:inspect_request))
|
1060
|
-
|
1061
|
-
response = client.call(:authenticate, :soap_action => "doAuthenticate")
|
1062
|
-
soap_action = inspect_request(response).soap_action
|
1063
|
-
expect(soap_action).to eq('"doAuthenticate"')
|
1064
|
-
end
|
1065
|
-
end
|
1066
|
-
|
1067
|
-
context "request :message" do
|
1068
|
-
it "accepts a Hash which is passed to Gyoku to be converted to XML" do
|
1069
|
-
response = new_client(:endpoint => @server.url(:repeat)).call(:authenticate, :message => { :user => "luke", :password => "secret" })
|
1070
|
-
|
1071
|
-
request = response.http.body
|
1072
|
-
expect(request).to include("<user>luke</user>")
|
1073
|
-
expect(request).to include("<password>secret</password>")
|
1074
|
-
end
|
1075
|
-
|
1076
|
-
it "also accepts a String of raw XML" do
|
1077
|
-
response = new_client(:endpoint => @server.url(:repeat)).call(:authenticate, :message => "<user>lea</user><password>top-secret</password>")
|
1078
|
-
expect(response.http.body).to include("<tns:authenticate><user>lea</user><password>top-secret</password></tns:authenticate>")
|
1079
|
-
end
|
1080
|
-
end
|
1081
|
-
|
1082
|
-
context "request :xml" do
|
1083
|
-
it "accepts a String of raw XML" do
|
1084
|
-
response = new_client(:endpoint => @server.url(:repeat)).call(:authenticate, :xml => "<soap>request</soap>")
|
1085
|
-
expect(response.http.body).to eq("<soap>request</soap>")
|
1086
|
-
end
|
1087
|
-
end
|
1088
|
-
|
1089
|
-
context "request :cookies" do
|
1090
|
-
it "accepts an Array of HTTPI::Cookie objects for the next request" do
|
1091
|
-
cookies = [
|
1092
|
-
HTTPI::Cookie.new("some-cookie=choc-chip"),
|
1093
|
-
HTTPI::Cookie.new("another-cookie=ny-cheesecake")
|
1094
|
-
]
|
1095
|
-
|
1096
|
-
client = new_client(:endpoint => @server.url(:inspect_request))
|
1097
|
-
response = client.call(:authenticate, :cookies => cookies)
|
1098
|
-
|
1099
|
-
cookie = inspect_request(response).cookie
|
1100
|
-
expect(cookie.split(";")).to include(
|
1101
|
-
"some-cookie=choc-chip",
|
1102
|
-
"another-cookie=ny-cheesecake"
|
1103
|
-
)
|
1104
|
-
end
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
context "request :advanced_typecasting" do
|
1108
|
-
it "can be changed to false to disable Nori's advanced typecasting" do
|
1109
|
-
client = new_client(:endpoint => @server.url(:repeat))
|
1110
|
-
response = client.call(:authenticate, :xml => Fixture.response(:authentication), :advanced_typecasting => false)
|
1111
|
-
|
1112
|
-
expect(response.body[:authenticate_response][:return][:success]).to eq("true")
|
1113
|
-
end
|
1114
|
-
end
|
1115
|
-
|
1116
|
-
context "request :response_parser" do
|
1117
|
-
it "instructs Nori to change the response parser" do
|
1118
|
-
nori = Nori.new(:strip_namespaces => true, :convert_tags_to => lambda { |tag| tag.snakecase.to_sym })
|
1119
|
-
Nori.expects(:new).with { |options| options[:parser] == :nokogiri }.returns(nori)
|
1120
|
-
|
1121
|
-
client = new_client(:endpoint => @server.url(:repeat))
|
1122
|
-
response = client.call(:authenticate, :xml => Fixture.response(:authentication), :response_parser => :nokogiri)
|
1123
|
-
|
1124
|
-
expect(response.body).to_not be_empty
|
1125
|
-
end
|
1126
|
-
end
|
1127
|
-
|
1128
|
-
context "request :headers" do
|
1129
|
-
it "sets headers" do
|
1130
|
-
client = new_client(:endpoint => @server.url(:inspect_request))
|
1131
|
-
|
1132
|
-
response = client.call(:authenticate, :headers => { "X-Token" => "secret" })
|
1133
|
-
x_token = inspect_request(response).x_token
|
1134
|
-
|
1135
|
-
expect(x_token).to eq("secret")
|
1136
|
-
end
|
1137
|
-
end
|
1138
|
-
|
1139
|
-
def new_client(globals = {}, &block)
|
1140
|
-
globals = { :wsdl => Fixture.wsdl(:authentication), :log => false }.merge(globals)
|
1141
|
-
Savon.client(globals, &block)
|
1142
|
-
end
|
1143
|
-
|
1144
|
-
def new_client_without_wsdl(globals = {}, &block)
|
1145
|
-
globals = { :log => false }.merge(globals)
|
1146
|
-
Savon.client(globals, &block)
|
1147
|
-
end
|
1148
|
-
|
1149
|
-
def inspect_request(response)
|
1150
|
-
hash = JSON.parse(response.http.body)
|
1151
|
-
OpenStruct.new(hash)
|
1152
|
-
end
|
1153
|
-
|
1154
|
-
end
|