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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +10 -5
  4. data/Appraisals +16 -9
  5. data/Gemfile +3 -1
  6. data/README.md +112 -8
  7. data/Rakefile +15 -5
  8. data/app/helpers/wash_out_helper.rb +62 -25
  9. data/app/views/{wash_with_soap → wash_out}/document/error.builder +1 -1
  10. data/app/views/{wash_with_soap → wash_out}/document/response.builder +8 -3
  11. data/app/views/{wash_with_soap → wash_out}/document/wsdl.builder +16 -16
  12. data/app/views/{wash_with_soap → wash_out}/rpc/error.builder +1 -1
  13. data/app/views/{wash_with_soap → wash_out}/rpc/response.builder +9 -4
  14. data/app/views/{wash_with_soap → wash_out}/rpc/wsdl.builder +17 -17
  15. data/gemfiles/rails_3.2.13.gemfile +21 -0
  16. data/gemfiles/rails_4.0.0.gemfile +21 -0
  17. data/gemfiles/rails_4.1.0.gemfile +21 -0
  18. data/gemfiles/rails_4.2.0.gemfile +21 -0
  19. data/gemfiles/rails_5.0.0.beta2.gemfile +19 -0
  20. data/gemfiles/rails_5.0.0.gemfile +20 -0
  21. data/gemfiles/rails_5.1.1.gemfile +20 -0
  22. data/lib/wash_out/dispatcher.rb +126 -48
  23. data/lib/wash_out/engine.rb +1 -2
  24. data/lib/wash_out/model.rb +1 -1
  25. data/lib/wash_out/param.rb +14 -1
  26. data/lib/wash_out/router.rb +61 -19
  27. data/lib/wash_out/soap.rb +15 -3
  28. data/lib/wash_out/soap_config.rb +2 -0
  29. data/lib/wash_out/version.rb +1 -1
  30. data/lib/wash_out/wsse.rb +49 -23
  31. data/lib/wash_out.rb +35 -6
  32. data/spec/dummy/app/controllers/application_controller.rb +1 -1
  33. data/spec/dummy/config/environments/test.rb +1 -0
  34. data/spec/fixtures/nested_refs_to_arrays.xml +19 -0
  35. data/spec/fixtures/ref_to_one_array.xml +11 -0
  36. data/spec/fixtures/refs_to_arrays.xml +16 -0
  37. data/spec/lib/wash_out/dispatcher_spec.rb +135 -13
  38. data/spec/lib/wash_out/middleware_spec.rb +8 -8
  39. data/spec/lib/wash_out/param_spec.rb +43 -11
  40. data/spec/lib/wash_out/router_spec.rb +50 -0
  41. data/spec/lib/wash_out/type_spec.rb +9 -9
  42. data/spec/lib/wash_out_spec.rb +440 -88
  43. data/spec/spec_helper.rb +26 -4
  44. metadata +27 -16
@@ -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 = Savon::Client.new(:log => false, :wsdl => 'http://app/api/wsdl', &block)
19
- savon.call(method, :message => message).to_hash
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
- lambda {
56
+ expect {
32
57
  mock_controller do
33
58
  # nothing
34
59
  end
35
- }.should_not raise_exception
60
+ }.not_to raise_exception
36
61
  end
37
62
 
38
63
  it "allows definition of a simple action" do
39
- lambda {
64
+ expect {
40
65
  mock_controller do
41
66
  soap_action "answer", :args => nil, :return => :integer
42
67
  end
43
- }.should_not raise_exception
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.should be_a_kind_of(Array)
96
+ expect(operations).to be_a_kind_of(Array)
72
97
 
73
- operations.map{|e| e[:'@name']}.sort.should == ['Result', 'getArea', 'rocky'].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">').should == true
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'].should == "0"
86
- x[:'@max_occurs'].should == "unbounded"
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.should == <<-XML
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
- should == "42"
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
- should == "42"
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].should == true
168
- savon(:check_answer, 13)[:check_answer_response][:value].should == false
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].should == '420k'
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
- should == ({ :area => (Math::PI * 25).to_s, :distance_from_o => (5.0).to_s })
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.should == {"rumbas" => [1, 2, 3]}
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.should == {}
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.should == {"nested" => {}}
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.should == {
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
- should == {:zoo=>"zoo", :boo=>{:moo=>"moo", :doo=>"doo", :"@xsi:type"=>"tns:Boo"}}
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].should == {:value => ["1", "2", "3"]}
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].should == {
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].should == {
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].should be_nil
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].should be_nil
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
- should == { :"@xsi:type" => "tns:MyValue" }
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].should == true
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].should == false
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].should == Date.parse('2000-12-30') unless params[:value].blank?
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
- lambda { savon(:date) }.should_not raise_exception
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].should == 'test' unless params[:value].blank?
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
- lambda { savon(:base64) }.should_not raise_exception
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
- lambda {
764
+ expect {
481
765
  savon(:duty, :bad => 42, :good => nil)
482
- }.should raise_exception(Savon::SOAPFault)
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
- lambda {
776
+ expect {
493
777
  savon(:date, :value => 'incorrect format')
494
- }.should raise_exception(Savon::SOAPFault)
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
- lambda { savon(:error, :need_error => false) }.should_not raise_exception
507
- lambda { savon(:error, :need_error => true) }.should raise_exception(Savon::SOAPFault)
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
- lambda { savon(:error) }.should raise_exception(Savon::SOAPFault)
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
- lambda { savon(:bad) }.should raise_exception(
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
- lambda { savon(:bad2) }.should raise_exception(
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
- it "old syntax" do
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).should == {:test => {:value=>"test"}}
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"].should == "yam!"
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'].should == "gorilla"
627
- request.env['WSSE_TOKEN']['password'].should == "secret"
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
- lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
647
- should_not raise_exception
959
+ expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
960
+ not_to raise_exception
648
961
 
649
962
  # wrong user
650
- lambda { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret" } }.
651
- should raise_exception(Savon::SOAPFault)
963
+ expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret" } }.
964
+ to raise_exception(Savon::SOAPFault)
652
965
 
653
966
  # wrong pass
654
- lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry" } }.
655
- should raise_exception(Savon::SOAPFault)
967
+ expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry" } }.
968
+ to raise_exception(Savon::SOAPFault)
656
969
 
657
970
  # no auth
658
- lambda { savon(:check_auth, 42) }.
659
- should raise_exception(Savon::SOAPFault)
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
- lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "secret", :digest } }.
672
- should_not raise_exception
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
- lambda { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret", :digest } }.
676
- should raise_exception(Savon::SOAPFault)
1027
+ expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret", :digest } }.
1028
+ to raise_exception(Savon::SOAPFault)
677
1029
 
678
1030
  # wrong pass
679
- lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry", :digest } }.
680
- should raise_exception(Savon::SOAPFault)
1031
+ expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry", :digest } }.
1032
+ to raise_exception(Savon::SOAPFault)
681
1033
 
682
1034
  # no auth
683
- lambda { savon(:check_auth, 42) }.
684
- should raise_exception(Savon::SOAPFault)
1035
+ expect { savon(:check_auth, 42) }.
1036
+ to raise_exception(Savon::SOAPFault)
685
1037
  end
686
1038
 
687
1039
  end