wash_out 0.9.0 → 0.12.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/.gitignore +3 -1
- data/.travis.yml +10 -5
- data/Appraisals +16 -9
- data/Gemfile +3 -1
- data/README.md +112 -8
- data/Rakefile +15 -5
- data/app/helpers/wash_out_helper.rb +62 -25
- data/app/views/{wash_with_soap → wash_out}/document/error.builder +1 -1
- data/app/views/{wash_with_soap → wash_out}/document/response.builder +8 -3
- data/app/views/{wash_with_soap → wash_out}/document/wsdl.builder +16 -16
- data/app/views/{wash_with_soap → wash_out}/rpc/error.builder +1 -1
- data/app/views/{wash_with_soap → wash_out}/rpc/response.builder +9 -4
- data/app/views/{wash_with_soap → wash_out}/rpc/wsdl.builder +17 -17
- data/gemfiles/rails_3.2.13.gemfile +21 -0
- data/gemfiles/rails_4.0.0.gemfile +21 -0
- data/gemfiles/rails_4.1.0.gemfile +21 -0
- data/gemfiles/rails_4.2.0.gemfile +21 -0
- data/gemfiles/rails_5.0.0.beta2.gemfile +19 -0
- data/gemfiles/rails_5.0.0.gemfile +20 -0
- data/gemfiles/rails_5.1.1.gemfile +20 -0
- data/lib/wash_out/dispatcher.rb +126 -48
- data/lib/wash_out/engine.rb +1 -2
- data/lib/wash_out/model.rb +1 -1
- data/lib/wash_out/param.rb +14 -1
- data/lib/wash_out/router.rb +61 -19
- data/lib/wash_out/soap.rb +15 -3
- data/lib/wash_out/soap_config.rb +2 -0
- data/lib/wash_out/version.rb +1 -1
- data/lib/wash_out/wsse.rb +49 -23
- data/lib/wash_out.rb +35 -6
- data/spec/dummy/app/controllers/application_controller.rb +1 -1
- data/spec/dummy/config/environments/test.rb +1 -0
- data/spec/fixtures/nested_refs_to_arrays.xml +19 -0
- data/spec/fixtures/ref_to_one_array.xml +11 -0
- data/spec/fixtures/refs_to_arrays.xml +16 -0
- data/spec/lib/wash_out/dispatcher_spec.rb +135 -13
- data/spec/lib/wash_out/middleware_spec.rb +8 -8
- data/spec/lib/wash_out/param_spec.rb +43 -11
- data/spec/lib/wash_out/router_spec.rb +50 -0
- data/spec/lib/wash_out/type_spec.rb +9 -9
- data/spec/lib/wash_out_spec.rb +440 -88
- data/spec/spec_helper.rb +26 -4
- metadata +27 -16
data/spec/lib/wash_out_spec.rb
CHANGED
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
+
SIMPLE_REQUEST_XML = <<-SIMPLE_REQUEST_XML_HEREDOC
|
6
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
7
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
8
|
+
<env:Body>
|
9
|
+
<tns:answer>
|
10
|
+
<value>42</value>
|
11
|
+
</tns:answer>
|
12
|
+
</env:Body>
|
13
|
+
</env:Envelope>
|
14
|
+
SIMPLE_REQUEST_XML_HEREDOC
|
15
|
+
|
16
|
+
SIMPLE_RESPONSE_XML = <<-SIMPLE_RESPONSE_XML_HEREDOC
|
17
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
18
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false">
|
19
|
+
<soap:Body>
|
20
|
+
<tns:answerResponse>
|
21
|
+
<Value xsi:type="xsd:int">42</Value>
|
22
|
+
</tns:answerResponse>
|
23
|
+
</soap:Body>
|
24
|
+
</soap:Envelope>
|
25
|
+
SIMPLE_RESPONSE_XML_HEREDOC
|
26
|
+
|
27
|
+
|
5
28
|
describe WashOut do
|
6
29
|
|
7
30
|
let :nori do
|
@@ -12,35 +35,37 @@ describe WashOut do
|
|
12
35
|
)
|
13
36
|
end
|
14
37
|
|
15
|
-
def savon(method, message={}, &block)
|
38
|
+
def savon(method, message={}, hashify=true, &block)
|
16
39
|
message = {:value => message} unless message.is_a?(Hash)
|
17
40
|
|
18
|
-
savon
|
19
|
-
savon.call(method, :message => message)
|
41
|
+
savon = Savon::Client.new(:log => false, :wsdl => 'http://app/route/api/wsdl', &block)
|
42
|
+
result = savon.call(method, :message => message)
|
43
|
+
result = result.to_hash if hashify
|
44
|
+
result
|
20
45
|
end
|
21
46
|
|
22
47
|
def savon!(method, message={}, &block)
|
23
48
|
message = {:value => message} unless message.is_a?(Hash)
|
24
49
|
|
25
|
-
savon = Savon::Client.new(:log => true, :wsdl => 'http://app/api/wsdl', &block)
|
50
|
+
savon = Savon::Client.new(:log => true, :wsdl => 'http://app/route/api/wsdl', &block)
|
26
51
|
savon.call(method, :message => message).to_hash
|
27
52
|
end
|
28
53
|
|
29
54
|
describe "Module" do
|
30
55
|
it "includes" do
|
31
|
-
|
56
|
+
expect {
|
32
57
|
mock_controller do
|
33
58
|
# nothing
|
34
59
|
end
|
35
|
-
}.
|
60
|
+
}.not_to raise_exception
|
36
61
|
end
|
37
62
|
|
38
63
|
it "allows definition of a simple action" do
|
39
|
-
|
64
|
+
expect {
|
40
65
|
mock_controller do
|
41
66
|
soap_action "answer", :args => nil, :return => :integer
|
42
67
|
end
|
43
|
-
}.
|
68
|
+
}.not_to raise_exception
|
44
69
|
end
|
45
70
|
end
|
46
71
|
|
@@ -59,7 +84,7 @@ describe WashOut do
|
|
59
84
|
:return => { :circle2 => { :y => :integer } }
|
60
85
|
end
|
61
86
|
|
62
|
-
HTTPI.get("http://app/api/wsdl").body
|
87
|
+
HTTPI.get("http://app/route/api/wsdl").body
|
63
88
|
end
|
64
89
|
|
65
90
|
let :xml do
|
@@ -68,13 +93,13 @@ describe WashOut do
|
|
68
93
|
|
69
94
|
it "lists operations" do
|
70
95
|
operations = xml[:definitions][:binding][:operation]
|
71
|
-
operations.
|
96
|
+
expect(operations).to be_a_kind_of(Array)
|
72
97
|
|
73
|
-
operations.map{|e| e[:'@name']}.sort.
|
98
|
+
expect(operations.map{|e| e[:'@name']}.sort).to eq ['Result', 'getArea', 'rocky'].sort
|
74
99
|
end
|
75
100
|
|
76
101
|
it "defines complex types" do
|
77
|
-
wsdl.include?('<xsd:complexType name="Circle1">').
|
102
|
+
expect(wsdl.include?('<xsd:complexType name="Circle1">')).to be true
|
78
103
|
end
|
79
104
|
|
80
105
|
it "defines arrays" do
|
@@ -82,8 +107,15 @@ describe WashOut do
|
|
82
107
|
find{|x| x[:'@name'] == 'Center'}[:sequence][:element].
|
83
108
|
find{|x| x[:'@name'] == 'X'}
|
84
109
|
|
85
|
-
x[:'@min_occurs'].
|
86
|
-
x[:'@max_occurs'].
|
110
|
+
expect(x[:'@min_occurs']).to eq "0"
|
111
|
+
expect(x[:'@max_occurs']).to eq "unbounded"
|
112
|
+
expect(x[:'@nillable']).to eq "true"
|
113
|
+
end
|
114
|
+
|
115
|
+
it "adds nillable to all type definitions" do
|
116
|
+
types = xml[:definitions][:message].map { |d| d[:part] }.compact
|
117
|
+
nillable = types.map { |t| t[:"@xsi:nillable"] }
|
118
|
+
expect(nillable.all? { |v| v == "true" }).to be true
|
87
119
|
end
|
88
120
|
end
|
89
121
|
|
@@ -109,7 +141,7 @@ describe WashOut do
|
|
109
141
|
</env:Envelope>
|
110
142
|
XML
|
111
143
|
|
112
|
-
HTTPI.post("http://app/api/action", request).body.
|
144
|
+
expect(HTTPI.post("http://app/route/api/action", request).body).to eq <<-XML
|
113
145
|
<?xml version="1.0" encoding="UTF-8"?>
|
114
146
|
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false">
|
115
147
|
<soap:Body>
|
@@ -121,6 +153,56 @@ describe WashOut do
|
|
121
153
|
XML
|
122
154
|
end
|
123
155
|
|
156
|
+
it "accepts requests with no HTTP header with alias" do
|
157
|
+
mock_controller do
|
158
|
+
soap_action "answer", :as => 'whatever', :args => nil, :return => :int
|
159
|
+
def answer
|
160
|
+
render :soap => "42"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
request = <<-XML
|
165
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
166
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
167
|
+
<env:Body>
|
168
|
+
<tns:whatever>
|
169
|
+
<value>42</value>
|
170
|
+
</tns:whatever>
|
171
|
+
</env:Body>
|
172
|
+
</env:Envelope>
|
173
|
+
XML
|
174
|
+
|
175
|
+
expect(HTTPI.post("http://app/route/api/action", request).body).to eq <<-XML
|
176
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
177
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false">
|
178
|
+
<soap:Body>
|
179
|
+
<tns:whateverResponse>
|
180
|
+
<Value xsi:type="xsd:int">42</Value>
|
181
|
+
</tns:whateverResponse>
|
182
|
+
</soap:Body>
|
183
|
+
</soap:Envelope>
|
184
|
+
XML
|
185
|
+
end
|
186
|
+
|
187
|
+
it "succeeds when protect_from_forgery is enabled" do
|
188
|
+
|
189
|
+
# Enable allow_forgery_protection (affects all subsequent specs)
|
190
|
+
# Alternatively, assign in spec/dummy/config/environments/test.rb
|
191
|
+
Rails.application.config.after_initialize do
|
192
|
+
ActionController::Base.allow_forgery_protection = true
|
193
|
+
end
|
194
|
+
|
195
|
+
mock_controller do
|
196
|
+
soap_action "answer", :args => nil, :return => :int
|
197
|
+
def answer
|
198
|
+
render :soap => "42"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
expect(HTTPI.post("http://app/route/api/action", SIMPLE_REQUEST_XML).body).to eq SIMPLE_RESPONSE_XML
|
203
|
+
|
204
|
+
end
|
205
|
+
|
124
206
|
it "accept no parameters" do
|
125
207
|
mock_controller do
|
126
208
|
soap_action "answer", :args => nil, :return => :int
|
@@ -129,8 +211,8 @@ describe WashOut do
|
|
129
211
|
end
|
130
212
|
end
|
131
213
|
|
132
|
-
savon(:answer)[:answer_response][:value].
|
133
|
-
|
214
|
+
expect(savon(:answer)[:answer_response][:value]).
|
215
|
+
to eq "42"
|
134
216
|
end
|
135
217
|
|
136
218
|
it "accept insufficient parameters" do
|
@@ -141,8 +223,19 @@ describe WashOut do
|
|
141
223
|
end
|
142
224
|
end
|
143
225
|
|
144
|
-
savon(:answer)[:answer_response][:value].
|
145
|
-
|
226
|
+
expect(savon(:answer)[:answer_response][:value]).
|
227
|
+
to eq "42"
|
228
|
+
end
|
229
|
+
|
230
|
+
it "shows date in correct format" do
|
231
|
+
mock_controller do
|
232
|
+
soap_action "answer", :args => {}, :return => {:a => :date}
|
233
|
+
def answer
|
234
|
+
render :soap => {:a => DateTime.new(2000, 1, 1)}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
result = Hash.from_xml savon(:answer, {}, false).http.body
|
238
|
+
expect(result['Envelope']['Body']['answerResponse']['A']).to eq '2000-01-01T00:00:00+00:00'
|
146
239
|
end
|
147
240
|
|
148
241
|
it "accept empty parameter" do
|
@@ -152,8 +245,7 @@ describe WashOut do
|
|
152
245
|
render :soap => {:a => params[:a]}
|
153
246
|
end
|
154
247
|
end
|
155
|
-
savon(:answer, :a => '')[:answer_response][:a].
|
156
|
-
should == {:"@xsi:type"=>"xsd:string"}
|
248
|
+
expect(savon(:answer, :a => '')[:answer_response][:a]).to be_nil
|
157
249
|
end
|
158
250
|
|
159
251
|
it "accept one parameter" do
|
@@ -164,8 +256,8 @@ describe WashOut do
|
|
164
256
|
end
|
165
257
|
end
|
166
258
|
|
167
|
-
savon(:check_answer, 42)[:check_answer_response][:value].
|
168
|
-
savon(:check_answer, 13)[:check_answer_response][:value].
|
259
|
+
expect(savon(:check_answer, 42)[:check_answer_response][:value]).to be true
|
260
|
+
expect(savon(:check_answer, 13)[:check_answer_response][:value]).to be false
|
169
261
|
end
|
170
262
|
|
171
263
|
it "accept two parameters" do
|
@@ -176,7 +268,7 @@ describe WashOut do
|
|
176
268
|
end
|
177
269
|
end
|
178
270
|
|
179
|
-
savon(:funky, :a => 42, :b => 'k')[:funky_response][:value].
|
271
|
+
expect(savon(:funky, :a => 42, :b => 'k')[:funky_response][:value]).to eq '420k'
|
180
272
|
end
|
181
273
|
end
|
182
274
|
|
@@ -199,8 +291,8 @@ describe WashOut do
|
|
199
291
|
message = { :circle => { :center => { :x => 3, :y => 4 },
|
200
292
|
:radius => 5 } }
|
201
293
|
|
202
|
-
savon(:get_area, message)[:get_area_response].
|
203
|
-
|
294
|
+
expect(savon(:get_area, message)[:get_area_response]).
|
295
|
+
to eq ({ :area => (Math::PI * 25).to_s, :distance_from_o => (5.0).to_s })
|
204
296
|
end
|
205
297
|
|
206
298
|
it "accept arrays" do
|
@@ -211,7 +303,7 @@ describe WashOut do
|
|
211
303
|
},
|
212
304
|
:return => nil
|
213
305
|
def rumba
|
214
|
-
params.
|
306
|
+
expect(params).to eq({"rumbas" => [1, 2, 3]})
|
215
307
|
render :soap => nil
|
216
308
|
end
|
217
309
|
end
|
@@ -227,7 +319,7 @@ describe WashOut do
|
|
227
319
|
},
|
228
320
|
:return => nil
|
229
321
|
def rumba
|
230
|
-
params.
|
322
|
+
expect(params).to eq({})
|
231
323
|
render :soap => nil
|
232
324
|
end
|
233
325
|
end
|
@@ -242,7 +334,7 @@ describe WashOut do
|
|
242
334
|
},
|
243
335
|
:return => nil
|
244
336
|
def rumba
|
245
|
-
params.
|
337
|
+
expect(params).to eq({"nested" => {}})
|
246
338
|
render :soap => nil
|
247
339
|
end
|
248
340
|
end
|
@@ -260,12 +352,12 @@ describe WashOut do
|
|
260
352
|
},
|
261
353
|
:return => nil
|
262
354
|
def rumba
|
263
|
-
params.
|
355
|
+
expect(params).to eq({
|
264
356
|
"rumbas" => [
|
265
357
|
{"zombies" => 'suck', "puppies" => 'rock'},
|
266
358
|
{"zombies" => 'slow', "puppies" => 'fast'}
|
267
359
|
]
|
268
|
-
}
|
360
|
+
})
|
269
361
|
render :soap => nil
|
270
362
|
end
|
271
363
|
end
|
@@ -292,8 +384,15 @@ describe WashOut do
|
|
292
384
|
end
|
293
385
|
end
|
294
386
|
|
295
|
-
savon(:gogogo)[:gogogo_response].
|
296
|
-
|
387
|
+
expect(savon(:gogogo)[:gogogo_response]).
|
388
|
+
to eq({
|
389
|
+
:zoo=>"zoo",
|
390
|
+
:boo=>{
|
391
|
+
:moo=>"moo",
|
392
|
+
:doo=>"doo",
|
393
|
+
:"@xsi:type"=>"tns:Boo"
|
394
|
+
}
|
395
|
+
})
|
297
396
|
end
|
298
397
|
|
299
398
|
it "respond with arrays" do
|
@@ -306,7 +405,9 @@ describe WashOut do
|
|
306
405
|
end
|
307
406
|
end
|
308
407
|
|
309
|
-
savon(:rumba)[:rumba_response].
|
408
|
+
expect(savon(:rumba)[:rumba_response]).to eq({
|
409
|
+
:value => ["1", "2", "3"]
|
410
|
+
})
|
310
411
|
end
|
311
412
|
|
312
413
|
it "respond with complex structures inside arrays" do
|
@@ -314,55 +415,57 @@ describe WashOut do
|
|
314
415
|
soap_action "rumba",
|
315
416
|
:args => nil,
|
316
417
|
:return => {
|
317
|
-
:rumbas => [{:zombies => :string, :puppies => :string}]
|
418
|
+
:rumbas => [{:@level => :integer, :zombies => :string, :puppies => :string}]
|
318
419
|
}
|
319
420
|
def rumba
|
320
421
|
render :soap =>
|
321
422
|
{:rumbas => [
|
322
|
-
{:zombies => "suck1", :puppies => "rock1" },
|
423
|
+
{:@level => 80, :zombies => "suck1", :puppies => "rock1" },
|
323
424
|
{:zombies => "suck2", :puppies => "rock2" }
|
324
425
|
]
|
325
426
|
}
|
326
427
|
end
|
327
428
|
end
|
328
429
|
|
329
|
-
savon(:rumba)[:rumba_response].
|
430
|
+
expect(savon(:rumba)[:rumba_response]).to eq({
|
330
431
|
:rumbas => [
|
331
|
-
{:zombies => "suck1",:puppies => "rock1", :"@xsi:type"=>"tns:Rumbas"},
|
432
|
+
{:zombies => "suck1",:puppies => "rock1", :"@xsi:type"=>"tns:Rumbas", :@level => "80"},
|
332
433
|
{:zombies => "suck2", :puppies => "rock2", :"@xsi:type"=>"tns:Rumbas" }
|
333
434
|
]
|
334
|
-
}
|
435
|
+
})
|
335
436
|
end
|
336
437
|
|
337
438
|
it "respond with structs in structs in arrays" do
|
338
439
|
mock_controller do
|
339
440
|
soap_action "rumba",
|
340
441
|
:args => nil,
|
341
|
-
:return => [{:rumbas => {:zombies => :integer}}]
|
442
|
+
:return => [{:rumbas => {:@level => :integer, :zombies => :integer}}]
|
342
443
|
|
343
444
|
def rumba
|
344
|
-
render :soap => [{:rumbas => {:zombies => 100000}}, {:rumbas => {:zombies => 2}}]
|
445
|
+
render :soap => [{:rumbas => {:@level => 80, :zombies => 100000}}, {:rumbas => {:@level => 90, :zombies => 2}}]
|
345
446
|
end
|
346
447
|
end
|
347
448
|
|
348
|
-
savon(:rumba)[:rumba_response].
|
449
|
+
expect(savon(:rumba)[:rumba_response]).to eq({
|
349
450
|
:value => [
|
350
451
|
{
|
351
452
|
:rumbas => {
|
352
453
|
:zombies => "100000",
|
353
|
-
:"@xsi:type" => "tns:Rumbas"
|
454
|
+
:"@xsi:type" => "tns:Rumbas",
|
455
|
+
:"@level" => "80"
|
354
456
|
},
|
355
457
|
:"@xsi:type" => "tns:Value"
|
356
458
|
},
|
357
459
|
{
|
358
460
|
:rumbas => {
|
359
461
|
:zombies => "2",
|
360
|
-
:"@xsi:type" => "tns:Rumbas"
|
462
|
+
:"@xsi:type" => "tns:Rumbas",
|
463
|
+
:@level => "90",
|
361
464
|
},
|
362
465
|
:"@xsi:type"=>"tns:Value"
|
363
466
|
}
|
364
467
|
]
|
365
|
-
}
|
468
|
+
})
|
366
469
|
end
|
367
470
|
|
368
471
|
context "with arrays missing" do
|
@@ -375,7 +478,7 @@ describe WashOut do
|
|
375
478
|
end
|
376
479
|
end
|
377
480
|
|
378
|
-
savon(:rocknroll)[:rocknroll_response].
|
481
|
+
expect(savon(:rocknroll)[:rocknroll_response]).to be nil
|
379
482
|
end
|
380
483
|
|
381
484
|
it "respond with complext definition" do
|
@@ -387,7 +490,7 @@ describe WashOut do
|
|
387
490
|
end
|
388
491
|
end
|
389
492
|
|
390
|
-
savon(:rocknroll)[:rocknroll_response].
|
493
|
+
expect(savon(:rocknroll)[:rocknroll_response]).to be nil
|
391
494
|
end
|
392
495
|
|
393
496
|
it "respond with nested simple definition" do
|
@@ -399,8 +502,20 @@ describe WashOut do
|
|
399
502
|
end
|
400
503
|
end
|
401
504
|
|
402
|
-
savon(:rocknroll)[:rocknroll_response][:my_value].
|
403
|
-
|
505
|
+
expect(savon(:rocknroll)[:rocknroll_response][:my_value]).to be_nil
|
506
|
+
end
|
507
|
+
|
508
|
+
it "responds with missing parameters" do
|
509
|
+
mock_controller do
|
510
|
+
soap_action "rocknroll",
|
511
|
+
args: nil,
|
512
|
+
return: {my_value: :integer}
|
513
|
+
def rocknroll
|
514
|
+
render soap: {my_value: nil}
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
expect(savon(:rocknroll)[:rocknroll_response][:my_value]).to be_nil
|
404
519
|
end
|
405
520
|
|
406
521
|
it "handles incomplete array response" do
|
@@ -417,18 +532,187 @@ describe WashOut do
|
|
417
532
|
end
|
418
533
|
end
|
419
534
|
|
535
|
+
context "SOAP header" do
|
536
|
+
it "accepts requests with a simple header" do
|
537
|
+
mock_controller do
|
538
|
+
soap_action "answer", :args => nil, :return => :int, :header_args => :string
|
539
|
+
def answer
|
540
|
+
render :soap => "42"
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
request = <<-XML
|
545
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
546
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
547
|
+
<env:Header>
|
548
|
+
<tns:Auth>
|
549
|
+
<value>12345</value>
|
550
|
+
</tns:Auth>
|
551
|
+
</env:Header>
|
552
|
+
<env:Body>
|
553
|
+
<tns:answer>
|
554
|
+
<value>42</value>
|
555
|
+
</tns:answer>
|
556
|
+
</env:Body>
|
557
|
+
</env:Envelope>
|
558
|
+
XML
|
559
|
+
|
560
|
+
expect(HTTPI.post("http://app/route/api/action", request).body).to eq <<-XML
|
561
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
562
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false">
|
563
|
+
<soap:Body>
|
564
|
+
<tns:answerResponse>
|
565
|
+
<Value xsi:type="xsd:int">42</Value>
|
566
|
+
</tns:answerResponse>
|
567
|
+
</soap:Body>
|
568
|
+
</soap:Envelope>
|
569
|
+
XML
|
570
|
+
end
|
571
|
+
|
572
|
+
it "makes simple header values accessible" do
|
573
|
+
mock_controller do
|
574
|
+
soap_action "answer", :args => nil, :return => :int
|
575
|
+
def answer
|
576
|
+
expect(soap_request.headers).to eq({value: "12345"})
|
577
|
+
render :soap => "42"
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
request = <<-XML
|
582
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
583
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
584
|
+
<env:Header>
|
585
|
+
<value>12345</value>
|
586
|
+
</env:Header>
|
587
|
+
<env:Body>
|
588
|
+
<tns:answer>
|
589
|
+
<value>42</value>
|
590
|
+
</tns:answer>
|
591
|
+
</env:Body>
|
592
|
+
</env:Envelope>
|
593
|
+
XML
|
594
|
+
|
595
|
+
HTTPI.post("http://app/route/api/action", request)
|
596
|
+
|
597
|
+
end
|
598
|
+
|
599
|
+
it "makes complex header values accessible" do
|
600
|
+
mock_controller do
|
601
|
+
soap_action "answer", :args => nil, :return => :int
|
602
|
+
def answer
|
603
|
+
expect(soap_request.headers[:auth][:answer_response]).to eq "12345"
|
604
|
+
render :soap => "42"
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
request = <<-XML
|
609
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
610
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
611
|
+
<env:Header>
|
612
|
+
<Auth>
|
613
|
+
<AnswerResponse>12345</AnswerResponse>
|
614
|
+
</Auth>
|
615
|
+
</env:Header>
|
616
|
+
<env:Body>
|
617
|
+
<tns:answer>
|
618
|
+
<value>42</value>
|
619
|
+
</tns:answer>
|
620
|
+
</env:Body>
|
621
|
+
</env:Envelope>
|
622
|
+
XML
|
623
|
+
|
624
|
+
HTTPI.post("http://app/route/api/action", request)
|
625
|
+
|
626
|
+
end
|
627
|
+
|
628
|
+
it "renders a simple header if specified" do
|
629
|
+
mock_controller do
|
630
|
+
soap_action "answer", :args => nil, :return => :int, header_return: :string
|
631
|
+
def answer
|
632
|
+
render :soap => "42", :header => "12345"
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
|
637
|
+
request = <<-XML
|
638
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
639
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
640
|
+
<env:Body>
|
641
|
+
<tns:answer>
|
642
|
+
<value>42</value>
|
643
|
+
</tns:answer>
|
644
|
+
</env:Body>
|
645
|
+
</env:Envelope>
|
646
|
+
XML
|
647
|
+
|
648
|
+
expect(HTTPI.post("http://app/route/api/action", request).body).to eq <<-XML
|
649
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
650
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false">
|
651
|
+
<soap:Header>
|
652
|
+
<tns:answerResponse>
|
653
|
+
<Value xsi:type="xsd:string">12345</Value>
|
654
|
+
</tns:answerResponse>
|
655
|
+
</soap:Header>
|
656
|
+
<soap:Body>
|
657
|
+
<tns:answerResponse>
|
658
|
+
<Value xsi:type="xsd:int">42</Value>
|
659
|
+
</tns:answerResponse>
|
660
|
+
</soap:Body>
|
661
|
+
</soap:Envelope>
|
662
|
+
XML
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
it "renders a complex header if specified" do
|
667
|
+
mock_controller do
|
668
|
+
soap_action "answer", :args => nil, :return => :int, header_return: {:"Auth" => :string}
|
669
|
+
def answer
|
670
|
+
render :soap => "42", :header => {Auth: "12345"}
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
|
675
|
+
request = <<-XML
|
676
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
677
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
678
|
+
<env:Body>
|
679
|
+
<tns:answer>
|
680
|
+
<value>42</value>
|
681
|
+
</tns:answer>
|
682
|
+
</env:Body>
|
683
|
+
</env:Envelope>
|
684
|
+
XML
|
685
|
+
|
686
|
+
expect(HTTPI.post("http://app/route/api/action", request).body).to eq <<-XML
|
687
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
688
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="false">
|
689
|
+
<soap:Header>
|
690
|
+
<tns:answerResponse>
|
691
|
+
<Auth xsi:type="xsd:string">12345</Auth>
|
692
|
+
</tns:answerResponse>
|
693
|
+
</soap:Header>
|
694
|
+
<soap:Body>
|
695
|
+
<tns:answerResponse>
|
696
|
+
<Value xsi:type="xsd:int">42</Value>
|
697
|
+
</tns:answerResponse>
|
698
|
+
</soap:Body>
|
699
|
+
</soap:Envelope>
|
700
|
+
XML
|
701
|
+
end
|
702
|
+
|
703
|
+
|
420
704
|
context "types" do
|
421
705
|
it "recognize boolean" do
|
422
706
|
mock_controller do
|
423
707
|
soap_action "true", :args => :boolean, :return => :nil
|
424
708
|
def true
|
425
|
-
params[:value].
|
709
|
+
expect(params[:value]).to be true
|
426
710
|
render :soap => nil
|
427
711
|
end
|
428
712
|
|
429
713
|
soap_action "false", :args => :boolean, :return => :nil
|
430
714
|
def false
|
431
|
-
params[:value].
|
715
|
+
expect(params[:value]).to be false
|
432
716
|
render :soap => nil
|
433
717
|
end
|
434
718
|
end
|
@@ -443,26 +727,26 @@ describe WashOut do
|
|
443
727
|
mock_controller do
|
444
728
|
soap_action "date", :args => :date, :return => :nil
|
445
729
|
def date
|
446
|
-
params[:value].
|
730
|
+
expect(params[:value]).to eq Date.parse('2000-12-30') unless params[:value].blank?
|
447
731
|
render :soap => nil
|
448
732
|
end
|
449
733
|
end
|
450
734
|
|
451
735
|
savon(:date, :value => '2000-12-30')
|
452
|
-
|
736
|
+
expect { savon(:date) }.not_to raise_exception
|
453
737
|
end
|
454
738
|
|
455
739
|
it "recognize base64Binary" do
|
456
740
|
mock_controller do
|
457
741
|
soap_action "base64", :args => :base64Binary, :return => :nil
|
458
742
|
def base64
|
459
|
-
params[:value].
|
743
|
+
expect(params[:value]).to eq('test') unless params[:value].blank?
|
460
744
|
render :soap => nil
|
461
745
|
end
|
462
746
|
end
|
463
747
|
|
464
748
|
savon(:base64, :value => Base64.encode64('test'))
|
465
|
-
|
749
|
+
expect { savon(:base64) }.not_to raise_exception
|
466
750
|
end
|
467
751
|
end
|
468
752
|
|
@@ -477,9 +761,9 @@ describe WashOut do
|
|
477
761
|
end
|
478
762
|
end
|
479
763
|
|
480
|
-
|
764
|
+
expect {
|
481
765
|
savon(:duty, :bad => 42, :good => nil)
|
482
|
-
}.
|
766
|
+
}.to raise_exception(Savon::SOAPFault)
|
483
767
|
end
|
484
768
|
|
485
769
|
it "raise for date in incorrect format" do
|
@@ -489,9 +773,9 @@ describe WashOut do
|
|
489
773
|
render :soap => nil
|
490
774
|
end
|
491
775
|
end
|
492
|
-
|
776
|
+
expect {
|
493
777
|
savon(:date, :value => 'incorrect format')
|
494
|
-
}.
|
778
|
+
}.to raise_exception(Savon::SOAPFault)
|
495
779
|
end
|
496
780
|
|
497
781
|
it "raise to report SOAP errors" do
|
@@ -503,8 +787,21 @@ describe WashOut do
|
|
503
787
|
end
|
504
788
|
end
|
505
789
|
|
506
|
-
|
507
|
-
|
790
|
+
expect { savon(:error, :need_error => false) }.not_to raise_exception
|
791
|
+
expect { savon(:error, :need_error => true) }.to raise_exception(Savon::SOAPFault)
|
792
|
+
end
|
793
|
+
|
794
|
+
it "misses basic exceptions" do
|
795
|
+
mock_controller do
|
796
|
+
soap_action "error", :args => { :need_error => :boolean }, :return => nil
|
797
|
+
def error
|
798
|
+
raise self.class.const_get(:Exception), "you wanted one" if params[:need_error]
|
799
|
+
render :soap => nil
|
800
|
+
end
|
801
|
+
end
|
802
|
+
|
803
|
+
expect { savon(:error, :need_error => false) }.not_to raise_exception
|
804
|
+
expect { savon(:error, :need_error => true) }.to raise_exception(Exception)
|
508
805
|
end
|
509
806
|
|
510
807
|
it "raise for manual throws" do
|
@@ -515,7 +812,7 @@ describe WashOut do
|
|
515
812
|
end
|
516
813
|
end
|
517
814
|
|
518
|
-
|
815
|
+
expect { savon(:error) }.to raise_exception(Savon::SOAPFault)
|
519
816
|
end
|
520
817
|
|
521
818
|
it "raise when response structure mismatches" do
|
@@ -548,12 +845,12 @@ describe WashOut do
|
|
548
845
|
end
|
549
846
|
end
|
550
847
|
|
551
|
-
|
848
|
+
expect { savon(:bad) }.to raise_exception(
|
552
849
|
WashOut::Dispatcher::ProgrammerError,
|
553
850
|
/SOAP response .*wyldness.*Array.*Hash.*stallion/
|
554
851
|
)
|
555
852
|
|
556
|
-
|
853
|
+
expect { savon(:bad2) }.to raise_exception(
|
557
854
|
WashOut::Dispatcher::ProgrammerError,
|
558
855
|
/SOAP response .*oops.*String.*telephone_booths.*Array/
|
559
856
|
)
|
@@ -561,11 +858,14 @@ describe WashOut do
|
|
561
858
|
end
|
562
859
|
|
563
860
|
context "deprecates" do
|
564
|
-
|
861
|
+
# This test uses deprecated rspec expectations
|
862
|
+
# and it's not clear how to rewrite it.
|
863
|
+
xit "old syntax" do
|
565
864
|
# save rspec context check
|
566
865
|
raise_runtime_exception = raise_exception(RuntimeError)
|
567
866
|
|
568
867
|
mock_controller do
|
868
|
+
|
569
869
|
lambda {
|
570
870
|
soap_action "rumba",
|
571
871
|
:args => :integer,
|
@@ -588,8 +888,7 @@ describe WashOut do
|
|
588
888
|
end
|
589
889
|
end
|
590
890
|
|
591
|
-
savon(name.underscore.to_sym)["#{name.underscore}_response".to_sym][:value].
|
592
|
-
should == "forty two"
|
891
|
+
expect(savon(name.underscore.to_sym)["#{name.underscore}_response".to_sym][:value]).to eq "forty two"
|
593
892
|
end
|
594
893
|
|
595
894
|
it "respects :response_tag option" do
|
@@ -600,31 +899,45 @@ describe WashOut do
|
|
600
899
|
end
|
601
900
|
end
|
602
901
|
|
603
|
-
savon(:specific).
|
902
|
+
expect(savon(:specific)).to eq({:test => {:value=>"test"}})
|
604
903
|
end
|
605
904
|
|
606
905
|
it "handles snakecase option properly" do
|
607
906
|
mock_controller(snakecase_input: false, camelize_wsdl: false) do
|
608
907
|
soap_action "rocknroll", :args => {:ZOMG => :string}, :return => nil
|
609
908
|
def rocknroll
|
610
|
-
params["ZOMG"].
|
909
|
+
expect(params["ZOMG"]).to eq "yam!"
|
611
910
|
render :soap => nil
|
612
911
|
end
|
613
912
|
end
|
614
913
|
|
615
914
|
savon(:rocknroll, "ZOMG" => 'yam!')
|
616
915
|
end
|
916
|
+
end
|
917
|
+
|
918
|
+
describe "Router" do
|
919
|
+
it "raises when SOAP message without SOAP Envelope arrives" do
|
920
|
+
mock_controller do; end
|
921
|
+
invalid_request = '<a></a>'
|
922
|
+
response_hash = Nori.new.parse(HTTPI.post("http://app/route/api/action", invalid_request).body)
|
923
|
+
expect(response_hash["soap:Envelope"]["soap:Body"]["soap:Fault"]['faultstring']).to eq "Invalid SOAP request"
|
924
|
+
end
|
617
925
|
|
926
|
+
it "raises when SOAP message without SOAP Body arrives" do
|
927
|
+
mock_controller do; end
|
928
|
+
invalid_request = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"></s:Envelope>'
|
929
|
+
response_hash = Nori.new.parse(HTTPI.post("http://app/route/api/action", invalid_request).body)
|
930
|
+
expect(response_hash["soap:Envelope"]["soap:Body"]["soap:Fault"]['faultstring']).to eq "Invalid SOAP request"
|
931
|
+
end
|
618
932
|
end
|
619
933
|
|
620
934
|
describe "WS Security" do
|
621
|
-
|
622
935
|
it "appends username_token to params" do
|
623
936
|
mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
|
624
937
|
soap_action "checkToken", :args => :integer, :return => nil, :to => 'check_token'
|
625
938
|
def check_token
|
626
|
-
request.env['WSSE_TOKEN']['username'].
|
627
|
-
request.env['WSSE_TOKEN']['password'].
|
939
|
+
expect(request.env['WSSE_TOKEN']['username']).to eq "gorilla"
|
940
|
+
expect(request.env['WSSE_TOKEN']['password']).to eq "secret"
|
628
941
|
render :soap => nil
|
629
942
|
end
|
630
943
|
end
|
@@ -643,20 +956,20 @@ describe WashOut do
|
|
643
956
|
end
|
644
957
|
|
645
958
|
# correct auth
|
646
|
-
|
647
|
-
|
959
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
|
960
|
+
not_to raise_exception
|
648
961
|
|
649
962
|
# wrong user
|
650
|
-
|
651
|
-
|
963
|
+
expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret" } }.
|
964
|
+
to raise_exception(Savon::SOAPFault)
|
652
965
|
|
653
966
|
# wrong pass
|
654
|
-
|
655
|
-
|
967
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry" } }.
|
968
|
+
to raise_exception(Savon::SOAPFault)
|
656
969
|
|
657
970
|
# no auth
|
658
|
-
|
659
|
-
|
971
|
+
expect { savon(:check_auth, 42) }.
|
972
|
+
to raise_exception(Savon::SOAPFault)
|
660
973
|
end
|
661
974
|
|
662
975
|
it "handles PasswordDigest auth" do
|
@@ -668,20 +981,59 @@ describe WashOut do
|
|
668
981
|
end
|
669
982
|
|
670
983
|
# correct auth
|
671
|
-
|
672
|
-
|
984
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
|
985
|
+
not_to raise_exception
|
986
|
+
|
987
|
+
# correct digest auth
|
988
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret", :digest } }.
|
989
|
+
not_to raise_exception
|
990
|
+
|
991
|
+
# wrong user
|
992
|
+
expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret", :digest } }.
|
993
|
+
to raise_exception(Savon::SOAPFault)
|
994
|
+
|
995
|
+
# wrong pass
|
996
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry", :digest } }.
|
997
|
+
to raise_exception(Savon::SOAPFault)
|
998
|
+
|
999
|
+
# no auth
|
1000
|
+
expect { savon(:check_auth, 42) }.
|
1001
|
+
to raise_exception(Savon::SOAPFault)
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
it "handles auth callback" do
|
1005
|
+
mock_controller(
|
1006
|
+
wsse_auth_callback: lambda {|user, password, nonce, timestamp|
|
1007
|
+
authenticated = nonce ? WashOut::Wsse.matches_expected_digest?("secret", password, nonce, timestamp) : password == "secret"
|
1008
|
+
|
1009
|
+
return user == "gorilla" && authenticated
|
1010
|
+
}
|
1011
|
+
) do
|
1012
|
+
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
1013
|
+
def check_auth
|
1014
|
+
render :soap => (params[:value] == 42)
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
# correct auth
|
1019
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
|
1020
|
+
not_to raise_exception
|
1021
|
+
|
1022
|
+
# correct digest auth
|
1023
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret", :digest } }.
|
1024
|
+
not_to raise_exception
|
673
1025
|
|
674
1026
|
# wrong user
|
675
|
-
|
676
|
-
|
1027
|
+
expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret", :digest } }.
|
1028
|
+
to raise_exception(Savon::SOAPFault)
|
677
1029
|
|
678
1030
|
# wrong pass
|
679
|
-
|
680
|
-
|
1031
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry", :digest } }.
|
1032
|
+
to raise_exception(Savon::SOAPFault)
|
681
1033
|
|
682
1034
|
# no auth
|
683
|
-
|
684
|
-
|
1035
|
+
expect { savon(:check_auth, 42) }.
|
1036
|
+
to raise_exception(Savon::SOAPFault)
|
685
1037
|
end
|
686
1038
|
|
687
1039
|
end
|