washout_builder 0.9.12 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +6 -0
  3. data/Gemfile +11 -0
  4. data/README.rdoc +2 -1
  5. data/Rakefile +3 -1
  6. data/app/helpers/washout_builder_helper.rb +7 -169
  7. data/app/views/wash_with_html/doc.builder +11 -11
  8. data/lib/washout_builder.rb +24 -5
  9. data/lib/washout_builder/dispatcher.rb +6 -7
  10. data/lib/washout_builder/document/complex_type.rb +102 -0
  11. data/lib/washout_builder/document/generator.rb +114 -0
  12. data/lib/washout_builder/document/virtus_model.rb +45 -0
  13. data/lib/washout_builder/type.rb +2 -1
  14. data/lib/washout_builder/version.rb +1 -1
  15. data/spec/app/controllers/washout_builder_controller_spec.rb +8 -0
  16. data/spec/app/helpers/washout_builder_helper_spec.rb +8 -0
  17. data/spec/app/integration/washout_builder_all_services_spec.rb +7 -0
  18. data/spec/app/integration/washout_builder_service_spec.rb +7 -0
  19. data/spec/dummy/Rakefile +7 -0
  20. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  21. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  22. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  23. data/spec/dummy/config.ru +4 -0
  24. data/spec/dummy/config/application.rb +51 -0
  25. data/spec/dummy/config/boot.rb +10 -0
  26. data/spec/dummy/config/environment.rb +5 -0
  27. data/spec/dummy/config/environments/development.rb +23 -0
  28. data/spec/dummy/config/environments/test.rb +29 -0
  29. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  30. data/spec/dummy/config/initializers/inflections.rb +10 -0
  31. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  32. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  33. data/spec/dummy/config/initializers/session_store.rb +8 -0
  34. data/spec/dummy/config/locales/en.yml +5 -0
  35. data/spec/dummy/config/routes.rb +58 -0
  36. data/spec/dummy/public/404.html +26 -0
  37. data/spec/dummy/public/422.html +26 -0
  38. data/spec/dummy/public/500.html +26 -0
  39. data/spec/dummy/public/favicon.ico +0 -0
  40. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  41. data/spec/dummy/script/rails +6 -0
  42. data/spec/lib/washout_builder/dispatcher_spec.rb +51 -0
  43. data/spec/lib/washout_builder/document/complex_type_spec.rb +0 -0
  44. data/spec/lib/washout_builder/document/generator_spec.rb +0 -0
  45. data/spec/lib/washout_builder/document/virtus_model_spec.rb +0 -0
  46. data/spec/lib/washout_builder/engine_spec.rb +6 -0
  47. data/spec/lib/washout_builder/soap_spec.rb +15 -0
  48. data/spec/lib/washout_builder/type_spec.rb +21 -0
  49. data/spec/lib/washout_builder_spec.rb +697 -0
  50. data/spec/spec_helper.rb +2 -0
  51. metadata +74 -1
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ <p>We've been notified about this issue and we'll take a look at it shortly.</p>
24
+ </div>
25
+ </body>
26
+ </html>
File without changes
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,51 @@
1
+ #encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe WashoutBuilder::Dispatcher do
6
+
7
+ class Dispatcher < ApplicationController
8
+ soap_service
9
+
10
+ def params
11
+ @_params
12
+ end
13
+ end
14
+
15
+
16
+
17
+
18
+ describe "#_load_params" do
19
+ let(:dispatcher) { Dispatcher.new }
20
+ let(:soap_config) {
21
+ OpenStruct.new(
22
+ WashOut::Rails::Engine.config.wash_out.merge( { camelize_wsdl: false })
23
+ )
24
+ }
25
+ it "should load params for an array" do
26
+ spec = WashOut::Param.parse_def(soap_config, {:my_array => [:integer] } )
27
+ xml_data = {:my_array => [1, 2, 3]}
28
+ dispatcher._load_params(spec, xml_data).should == {"my_array" => [1, 2, 3]}
29
+ end
30
+
31
+ it "should load params for an empty array" do
32
+ spec = WashOut::Param.parse_def(soap_config, {:my_array => [:integer] } )
33
+ xml_data = {}
34
+ dispatcher._load_params(spec, xml_data).should == {}
35
+ end
36
+
37
+ it "should load params for a nested array" do
38
+ spec = WashOut::Param.parse_def(soap_config, {:nested => {:my_array => [:integer]}} )
39
+ xml_data = {:nested => {:my_array => [1, 2, 3]}}
40
+ dispatcher._load_params(spec, xml_data).should == {"nested" => {"my_array" => [1, 2, 3]}}
41
+ end
42
+
43
+ it "should load params for an empty nested array" do
44
+ spec = WashOut::Param.parse_def(soap_config, {:nested => {:empty => [:integer] }} )
45
+ xml_data = {:nested => nil}
46
+ dispatcher._load_params(spec, xml_data).should == {"nested" => {}}
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe WashoutBuilder::Engine do
5
+
6
+ end
@@ -0,0 +1,15 @@
1
+ #encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe WashoutBuilder::SOAP do
6
+
7
+ # [
8
+ # WashoutBuilder::Dispatcher,
9
+ # WashOut::Rails::Controller
10
+ # ].each do |extension|
11
+ # specify { WashoutBuilder::SOAP.included_modules.should include(extension) }
12
+ # end
13
+ #
14
+
15
+ end
@@ -0,0 +1,21 @@
1
+ #encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe WashoutBuilder::Type do
6
+
7
+ [ "string",
8
+ "integer",
9
+ "double",
10
+ "boolean",
11
+ "date",
12
+ "datetime",
13
+ "float",
14
+ "time",
15
+ "int"].each do |type|
16
+ it "defines a list of types" do
17
+ WashoutBuilder::Type::BASIC_TYPES.should include(type)
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,697 @@
1
+ #encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe WashoutBuilder do
6
+
7
+ before(:each) do
8
+ WashOut::Rails::Engine.config.wash_out[:wsdl_style] = 'rpc'
9
+ WashOut::Rails::Engine.config.wash_out[:parser] = :nokogiri
10
+ WashOut::Rails::Engine.config.wash_out[:catch_xml_errors] = true
11
+ end
12
+
13
+ let :nori do
14
+ Nori.new(
15
+ :strip_namespaces => true,
16
+ :advanced_typecasting => true,
17
+ :convert_tags_to => lambda {|x| x.snakecase.to_sym}
18
+ )
19
+ end
20
+
21
+ def savon(method, message={}, &block)
22
+ message = {:value => message} unless message.is_a?(Hash)
23
+
24
+ savon_client = Savon::Client.new(:log => false, :wsdl => 'http://app/api/wsdl', &block)
25
+ result = savon_client.call(method, :message => message)
26
+ result.respond_to?(:to_hash) ? result.to_hash : result
27
+ end
28
+
29
+ def savon!(method, message={}, &block)
30
+ message = {:value => message} unless message.is_a?(Hash)
31
+
32
+ savon_client = Savon::Client.new(:log => true, :wsdl => 'http://app/api/wsdl', &block)
33
+ result = savon_client.call(method, :message => message)
34
+ result.respond_to?(:to_hash) ? result.to_hash : result
35
+ end
36
+
37
+ describe "Module" do
38
+ it "includes" do
39
+ lambda {
40
+ mock_controller do
41
+ # nothing
42
+ end
43
+ }.should_not raise_exception
44
+ end
45
+
46
+ it "allows definition of a simple action" do
47
+ lambda {
48
+ mock_controller do
49
+ soap_action "answer", :args => nil, :return => :integer
50
+ end
51
+ }.should_not raise_exception
52
+ end
53
+ end
54
+
55
+ describe "WSDL" do
56
+ let :wsdl do
57
+ mock_controller do
58
+ soap_action :result, :args => nil, :return => :int
59
+
60
+ soap_action "getArea", :args => {
61
+ :circle => [{
62
+ :center => { :x => [:integer], :y => :integer },
63
+ :radius => :double
64
+ }]},
65
+ :return => { :area => :double }
66
+ soap_action "rocky", :args => { :circle1 => { :x => :integer } },
67
+ :return => { :circle2 => { :y => :integer } }
68
+ end
69
+
70
+ HTTPI.get("http://app/api/wsdl").body
71
+ end
72
+
73
+ let :xml do
74
+ nori.parse wsdl
75
+ end
76
+
77
+ it "lists operations" do
78
+ operations = xml[:definitions][:binding][:operation]
79
+ operations.should be_a_kind_of(Array)
80
+
81
+ operations.map{|e| e[:'@name']}.sort.should == ['Result', 'getArea', 'rocky'].sort
82
+ end
83
+
84
+ it "defines complex types" do
85
+ wsdl.include?('<xsd:complexType name="Circle1">').should == true
86
+ end
87
+
88
+ it "defines arrays" do
89
+ x = xml[:definitions][:types][:schema][:complex_type].
90
+ find{|x| x[:'@name'] == 'Center'}[:sequence][:element].
91
+ find{|x| x[:'@name'] == 'X'}
92
+
93
+ x[:'@min_occurs'].should == "0"
94
+ x[:'@max_occurs'].should == "unbounded"
95
+ end
96
+ end
97
+
98
+ describe "Dispatcher" do
99
+
100
+ context "simple actions" do
101
+ it "accepts requests with no HTTP header" do
102
+ mock_controller do
103
+ soap_action "answer", :args => nil, :return => :int
104
+ def answer
105
+ render :soap => "42"
106
+ end
107
+ end
108
+
109
+ request = <<-XML
110
+ <?xml version="1.0" encoding="UTF-8"?>
111
+ <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/">
112
+ <env:Body>
113
+ <tns:answer>
114
+ <value>42</value>
115
+ </tns:answer>
116
+ </env:Body>
117
+ </env:Envelope>
118
+ XML
119
+
120
+ HTTPI.post("http://app/api/action", request).body.should == <<-XML
121
+ <?xml version="1.0" encoding="UTF-8"?>
122
+ <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">
123
+ <soap:Body>
124
+ <tns:answerResponse>
125
+ <Value xsi:type="xsd:int">42</Value>
126
+ </tns:answerResponse>
127
+ </soap:Body>
128
+ </soap:Envelope>
129
+ XML
130
+ end
131
+
132
+ it "accept no parameters" do
133
+ mock_controller do
134
+ soap_action "answer", :args => nil, :return => :int
135
+ def answer
136
+ render :soap => "42"
137
+ end
138
+ end
139
+
140
+ savon(:answer)[:answer_response][:value].
141
+ should == "42"
142
+ end
143
+
144
+ it "accept insufficient parameters" do
145
+ mock_controller do
146
+ soap_action "answer", :args => {:a => :integer}, :return => :integer
147
+ def answer
148
+ render :soap => "42"
149
+ end
150
+ end
151
+
152
+ savon(:answer)[:answer_response][:value].
153
+ should == "42"
154
+ end
155
+
156
+ it "accept empty parameter" do
157
+ mock_controller do
158
+ soap_action "answer", :args => {:a => :string}, :return => {:a => :string}
159
+ def answer
160
+ render :soap => {:a => params[:a]}
161
+ end
162
+ end
163
+ savon(:answer, :a => '')[:answer_response][:a].
164
+ should == {:"@xsi:type"=>"xsd:string"}
165
+ end
166
+
167
+ it "accept one parameter" do
168
+ mock_controller do
169
+ soap_action "checkAnswer", :args => :integer, :return => :boolean, :to => 'check_answer'
170
+ def check_answer
171
+ render :soap => (params[:value] == 42)
172
+ end
173
+ end
174
+
175
+ savon(:check_answer, 42)[:check_answer_response][:value].should == true
176
+ savon(:check_answer, 13)[:check_answer_response][:value].should == false
177
+ end
178
+
179
+ it "accept two parameters" do
180
+ mock_controller do
181
+ soap_action "funky", :args => { :a => :integer, :b => :string }, :return => :string
182
+ def funky
183
+ render :soap => ((params[:a] * 10).to_s + params[:b])
184
+ end
185
+ end
186
+
187
+ savon(:funky, :a => 42, :b => 'k')[:funky_response][:value].should == '420k'
188
+ end
189
+ end
190
+
191
+ context "complex actions" do
192
+ it "accept nested structures" do
193
+ mock_controller do
194
+ soap_action "getArea", :args => { :circle => { :center => { :x => :integer,
195
+ :y => :integer },
196
+ :radius => :double } },
197
+ :return => { :area => :double,
198
+ :distance_from_o => :double },
199
+ :to => :get_area
200
+ def get_area
201
+ circle = params[:circle]
202
+ render :soap => { :area => Math::PI * circle[:radius] ** 2,
203
+ :distance_from_o => Math.sqrt(circle[:center][:x] ** 2 + circle[:center][:y] ** 2) }
204
+ end
205
+ end
206
+
207
+ message = { :circle => { :center => { :x => 3, :y => 4 },
208
+ :radius => 5 } }
209
+
210
+ savon(:get_area, message)[:get_area_response].
211
+ should == ({ :area => (Math::PI * 25).to_s, :distance_from_o => (5.0).to_s })
212
+ end
213
+
214
+ it "accept arrays" do
215
+ mock_controller do
216
+ soap_action "rumba",
217
+ :args => {
218
+ :rumbas => [:integer]
219
+ },
220
+ :return => nil
221
+ def rumba
222
+ params.should == {"rumbas" => [1, 2, 3]}
223
+ render :soap => nil
224
+ end
225
+ end
226
+
227
+ savon(:rumba, :rumbas => [1, 2, 3])
228
+ end
229
+
230
+ it "accept empty arrays" do
231
+ mock_controller do
232
+ soap_action "rumba",
233
+ :args => {
234
+ :my_array => [:integer]
235
+ },
236
+ :return => nil
237
+ def rumba
238
+ params.should == {}
239
+ render :soap => nil
240
+ end
241
+ end
242
+ savon(:rumba, :empty => [])
243
+ end
244
+
245
+ it "accept nested empty arrays" do
246
+ mock_controller do
247
+ soap_action "rumba",
248
+ :args => {
249
+ :nested => {:my_array => [:integer] }
250
+ },
251
+ :return => nil
252
+ def rumba
253
+ params.should == {"nested" => {}}
254
+ render :soap => nil
255
+ end
256
+ end
257
+ savon(:rumba, :nested => {:my_array => []})
258
+ end
259
+
260
+ it "accept nested structures inside arrays" do
261
+ mock_controller do
262
+ soap_action "rumba",
263
+ :args => {
264
+ :rumbas => [ {
265
+ :zombies => :string,
266
+ :puppies => :string
267
+ } ]
268
+ },
269
+ :return => nil
270
+ def rumba
271
+ params.should == {
272
+ "rumbas" => [
273
+ {"zombies" => 'suck', "puppies" => 'rock'},
274
+ {"zombies" => 'slow', "puppies" => 'fast'}
275
+ ]
276
+ }
277
+ render :soap => nil
278
+ end
279
+ end
280
+
281
+ savon :rumba, :rumbas => [
282
+ {:zombies => 'suck', :puppies => 'rock'},
283
+ {:zombies => 'slow', :puppies => 'fast'}
284
+ ]
285
+ end
286
+
287
+ it "respond with nested structures" do
288
+ mock_controller do
289
+ soap_action "gogogo",
290
+ :args => nil,
291
+ :return => {
292
+ :zoo => :string,
293
+ :boo => { :moo => :string, :doo => :string }
294
+ }
295
+ def gogogo
296
+ render :soap => {
297
+ :zoo => 'zoo',
298
+ :boo => { :moo => 'moo', :doo => 'doo' }
299
+ }
300
+ end
301
+ end
302
+
303
+ savon(:gogogo)[:gogogo_response].
304
+ should == {:zoo=>"zoo", :boo=>{:moo=>"moo", :doo=>"doo", :"@xsi:type"=>"tns:Boo"}}
305
+ end
306
+
307
+ it "respond with arrays" do
308
+ mock_controller do
309
+ soap_action "rumba",
310
+ :args => nil,
311
+ :return => [:integer]
312
+ def rumba
313
+ render :soap => [1, 2, 3]
314
+ end
315
+ end
316
+
317
+ savon(:rumba)[:rumba_response].should == {:value => ["1", "2", "3"]}
318
+ end
319
+
320
+ it "respond with complex structures inside arrays" do
321
+ mock_controller do
322
+ soap_action "rumba",
323
+ :args => nil,
324
+ :return => {
325
+ :rumbas => [{:zombies => :string, :puppies => :string}]
326
+ }
327
+ def rumba
328
+ render :soap =>
329
+ {:rumbas => [
330
+ {:zombies => "suck1", :puppies => "rock1" },
331
+ {:zombies => "suck2", :puppies => "rock2" }
332
+ ]
333
+ }
334
+ end
335
+ end
336
+
337
+ savon(:rumba)[:rumba_response].should == {
338
+ :rumbas => [
339
+ {:zombies => "suck1",:puppies => "rock1", :"@xsi:type"=>"tns:Rumbas"},
340
+ {:zombies => "suck2", :puppies => "rock2", :"@xsi:type"=>"tns:Rumbas" }
341
+ ]
342
+ }
343
+ end
344
+
345
+ it "respond with structs in structs in arrays" do
346
+ mock_controller do
347
+ soap_action "rumba",
348
+ :args => nil,
349
+ :return => [{:rumbas => {:zombies => :integer}}]
350
+
351
+ def rumba
352
+ render :soap => [{:rumbas => {:zombies => 100000}}, {:rumbas => {:zombies => 2}}]
353
+ end
354
+ end
355
+
356
+ savon(:rumba)[:rumba_response].should == {
357
+ :value => [
358
+ {
359
+ :rumbas => {
360
+ :zombies => "100000",
361
+ :"@xsi:type" => "tns:Rumbas"
362
+ },
363
+ :"@xsi:type" => "tns:Value"
364
+ },
365
+ {
366
+ :rumbas => {
367
+ :zombies => "2",
368
+ :"@xsi:type" => "tns:Rumbas"
369
+ },
370
+ :"@xsi:type"=>"tns:Value"
371
+ }
372
+ ]
373
+ }
374
+ end
375
+
376
+ context "with arrays missing" do
377
+ it "respond with simple definition" do
378
+ mock_controller do
379
+ soap_action "rocknroll",
380
+ :args => nil, :return => { :my_value => [:integer] }
381
+ def rocknroll
382
+ render :soap => {}
383
+ end
384
+ end
385
+
386
+ savon(:rocknroll)[:rocknroll_response].should be_nil
387
+ end
388
+
389
+ it "respond with complext definition" do
390
+ mock_controller do
391
+ soap_action "rocknroll",
392
+ :args => nil, :return => { :my_value => [{ :value => :integer }] }
393
+ def rocknroll
394
+ render :soap => {}
395
+ end
396
+ end
397
+
398
+ savon(:rocknroll)[:rocknroll_response].should be_nil
399
+ end
400
+
401
+ it "respond with nested simple definition" do
402
+ mock_controller do
403
+ soap_action "rocknroll",
404
+ :args => nil, :return => { :my_value => { :my_array => [{ :value => :integer }] } }
405
+ def rocknroll
406
+ render :soap => {}
407
+ end
408
+ end
409
+
410
+ savon(:rocknroll)[:rocknroll_response][:my_value].
411
+ should == { :"@xsi:type" => "tns:MyValue" }
412
+ end
413
+
414
+ it "handles incomplete array response" do
415
+ mock_controller do
416
+ soap_action "rocknroll",
417
+ :args => nil, :return => { :my_value => [{ :value => :string }] }
418
+ def rocknroll
419
+ render :soap => { :my_value => [nil] }
420
+ end
421
+ end
422
+
423
+ expect{savon(:rocknroll)}.not_to raise_error
424
+ end
425
+ end
426
+ end
427
+
428
+ context "types" do
429
+ it "recognize boolean" do
430
+ mock_controller do
431
+ soap_action "true", :args => :boolean, :return => :nil
432
+ def true
433
+ params[:value].should == true
434
+ render :soap => nil
435
+ end
436
+
437
+ soap_action "false", :args => :boolean, :return => :nil
438
+ def false
439
+ params[:value].should == false
440
+ render :soap => nil
441
+ end
442
+ end
443
+
444
+ savon(:true, :value => "true")
445
+ savon(:true, :value => "1")
446
+ savon(:false, :value => "false")
447
+ savon(:false, :value => "0")
448
+ end
449
+
450
+ it "recognize dates" do
451
+ mock_controller do
452
+ soap_action "date", :args => :date, :return => :nil
453
+ def date
454
+ params[:value].should == Date.parse('2000-12-30') unless params[:value].blank?
455
+ render :soap => nil
456
+ end
457
+ end
458
+
459
+ savon(:date, :value => '2000-12-30')
460
+ lambda { savon(:date) }.should_not raise_exception
461
+ end
462
+
463
+ it "recognize base64Binary" do
464
+ mock_controller do
465
+ soap_action "base64", :args => :base64Binary, :return => :nil
466
+ def base64
467
+ params[:value].should == 'test' unless params[:value].blank?
468
+ render :soap => nil
469
+ end
470
+ end
471
+
472
+ savon(:base64, :value => Base64.encode64('test'))
473
+ lambda { savon(:base64) }.should_not raise_exception
474
+ end
475
+ end
476
+
477
+ context "errors" do
478
+ it "raise for incorrect requests" do
479
+ mock_controller do
480
+ soap_action "duty",
481
+ :args => {:bad => {:a => :string, :b => :string}, :good => {:a => :string, :b => :string}},
482
+ :return => nil
483
+ def duty
484
+ render :soap => nil
485
+ end
486
+ end
487
+
488
+ lambda {
489
+ savon(:duty, :bad => 42, :good => nil)
490
+ }.should raise_exception(Savon::SOAPFault)
491
+ end
492
+
493
+ it "raise for date in incorrect format" do
494
+ mock_controller do
495
+ soap_action "date", :args => :date, :return => :nil
496
+ def date
497
+ render :soap => nil
498
+ end
499
+ end
500
+ lambda {
501
+ savon(:date, :value => 'incorrect format')
502
+ }.should raise_exception(Savon::SOAPFault)
503
+ end
504
+
505
+ it "raise to report SOAP errors", :fails =>true do
506
+ mock_controller do
507
+ soap_action "error", :args => { :need_error => :boolean }, :return => nil
508
+ def error
509
+ raise self.class.const_get(:SOAPError), "you wanted one" if params[:need_error]
510
+ render :soap => nil
511
+ end
512
+ end
513
+
514
+ lambda { savon(:error, :need_error => false) }.should_not raise_exception
515
+ lambda { savon(:error, :need_error => true) }.should raise_exception(Savon::SOAPFault)
516
+ end
517
+
518
+ it "raise for manual throws" do
519
+ mock_controller do
520
+ soap_action "error", :args => nil, :return => nil
521
+ def error
522
+ render_soap_error "a message"
523
+ end
524
+ end
525
+
526
+ lambda { savon(:error) }.should raise_exception(Savon::SOAPFault)
527
+ end
528
+
529
+ it "raise when response structure mismatches" do
530
+ mock_controller do
531
+ soap_action 'bad', :args => :integer, :return => {
532
+ :basic => :string,
533
+ :stallions => {
534
+ :stallion => [
535
+ :name => :string,
536
+ :wyldness => :integer,
537
+ ]
538
+ },
539
+ }
540
+ def bad
541
+ render :soap => {
542
+ :basic => 'hi',
543
+ :stallions => [{:name => 'ted', :wyldness => 11}]
544
+ }
545
+ end
546
+
547
+ soap_action 'bad2', :args => :integer, :return => {
548
+ :basic => :string,
549
+ :telephone_booths => [:string]
550
+ }
551
+ def bad2
552
+ render :soap => {
553
+ :basic => 'hihi',
554
+ :telephone_booths => 'oops'
555
+ }
556
+ end
557
+ end
558
+
559
+ lambda { savon(:bad) }.should raise_exception(
560
+ WashOut::ProgrammerError,
561
+ /SOAP response .*wyldness.*Array.*Hash.*stallion/
562
+ )
563
+
564
+ lambda { savon(:bad2) }.should raise_exception(
565
+ WashOut::ProgrammerError,
566
+ /SOAP response .*oops.*String.*telephone_booths.*Array/
567
+ )
568
+ end
569
+ end
570
+
571
+ context "deprecates" do
572
+ it "old syntax" do
573
+ # save rspec context check
574
+ raise_runtime_exception = raise_exception(RuntimeError)
575
+
576
+ mock_controller do
577
+ lambda {
578
+ soap_action "rumba",
579
+ :args => :integer,
580
+ :return => []
581
+ }.should raise_runtime_exception
582
+ def rumba
583
+ render :soap => nil
584
+ end
585
+ end
586
+ end
587
+ end
588
+
589
+ it "allows arbitrary action names" do
590
+ name = 'AnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything'
591
+
592
+ mock_controller do
593
+ soap_action name, :args => nil, :return => :integer, :to => :answer
594
+ def answer
595
+ render :soap => "forty two"
596
+ end
597
+ end
598
+
599
+ savon(name.underscore.to_sym)["#{name.underscore}_response".to_sym][:value].
600
+ should == "forty two"
601
+ end
602
+
603
+ it "respects :response_tag option" do
604
+ mock_controller do
605
+ soap_action "specific", :response_tag => "test", :return => :string
606
+ def specific
607
+ render :soap => "test"
608
+ end
609
+ end
610
+
611
+ savon(:specific).should == {:test => {:value=>"test"}}
612
+ end
613
+
614
+ it "handles snakecase option properly" do
615
+ mock_controller(snakecase_input: false, camelize_wsdl: false) do
616
+ soap_action "rocknroll", :args => {:ZOMG => :string}, :return => nil
617
+ def rocknroll
618
+ params["ZOMG"].should == "yam!"
619
+ render :soap => nil
620
+ end
621
+ end
622
+
623
+ savon(:rocknroll, "ZOMG" => 'yam!')
624
+ end
625
+
626
+ end
627
+
628
+ describe "WS Security" do
629
+
630
+ it "appends username_token to params" do
631
+ mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
632
+ soap_action "checkToken", :args => :integer, :return => nil, :to => 'check_token'
633
+ def check_token
634
+ request.env['WSSE_TOKEN']['username'].should == "gorilla"
635
+ request.env['WSSE_TOKEN']['password'].should == "secret"
636
+ render :soap => nil
637
+ end
638
+ end
639
+
640
+ savon(:check_token, 42) do
641
+ wsse_auth "gorilla", "secret"
642
+ end
643
+ end
644
+
645
+ it "handles PasswordText auth" do
646
+ mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
647
+ soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
648
+ def check_auth
649
+ render :soap => (params[:value] == 42)
650
+ end
651
+ end
652
+
653
+ # correct auth
654
+ lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
655
+ should_not raise_exception
656
+
657
+ # wrong user
658
+ lambda { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret" } }.
659
+ should raise_exception(Savon::SOAPFault)
660
+
661
+ # wrong pass
662
+ lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry" } }.
663
+ should raise_exception(Savon::SOAPFault)
664
+
665
+ # no auth
666
+ lambda { savon(:check_auth, 42) }.
667
+ should raise_exception(Savon::SOAPFault)
668
+ end
669
+
670
+ it "handles PasswordDigest auth" do
671
+ mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
672
+ soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
673
+ def check_auth
674
+ render :soap => (params[:value] == 42)
675
+ end
676
+ end
677
+
678
+ # correct auth
679
+ lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "secret", :digest } }.
680
+ should_not raise_exception
681
+
682
+ # wrong user
683
+ lambda { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret", :digest } }.
684
+ should raise_exception(Savon::SOAPFault)
685
+
686
+ # wrong pass
687
+ lambda { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry", :digest } }.
688
+ should raise_exception(Savon::SOAPFault)
689
+
690
+ # no auth
691
+ lambda { savon(:check_auth, 42) }.
692
+ should raise_exception(Savon::SOAPFault)
693
+ end
694
+
695
+ end
696
+
697
+ end