wash-out 0.10.1
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/.travis.yml +35 -0
- data/Appraisals +25 -0
- data/CHANGELOG.md +102 -0
- data/Gemfile +16 -0
- data/Guardfile +12 -0
- data/LICENSE +22 -0
- data/README.md +246 -0
- data/Rakefile +13 -0
- data/app/helpers/wash_out_helper.rb +106 -0
- data/app/views/wash_out/document/error.builder +9 -0
- data/app/views/wash_out/document/response.builder +10 -0
- data/app/views/wash_out/document/wsdl.builder +68 -0
- data/app/views/wash_out/rpc/error.builder +10 -0
- data/app/views/wash_out/rpc/response.builder +11 -0
- data/app/views/wash_out/rpc/wsdl.builder +68 -0
- data/gemfiles/rails_3.1.3.gemfile +20 -0
- data/gemfiles/rails_3.2.12.gemfile +20 -0
- data/gemfiles/rails_4.0.0.gemfile +19 -0
- data/gemfiles/rails_4.1.0.gemfile +19 -0
- data/gemfiles/rails_4.2.0.gemfile +19 -0
- data/gemfiles/rails_5.0.0.beta2.gemfile +19 -0
- data/init.rb +1 -0
- data/lib/wash_out.rb +53 -0
- data/lib/wash_out/configurable.rb +41 -0
- data/lib/wash_out/dispatcher.rb +218 -0
- data/lib/wash_out/engine.rb +12 -0
- data/lib/wash_out/middleware.rb +41 -0
- data/lib/wash_out/model.rb +29 -0
- data/lib/wash_out/param.rb +200 -0
- data/lib/wash_out/router.rb +95 -0
- data/lib/wash_out/soap.rb +48 -0
- data/lib/wash_out/soap_config.rb +93 -0
- data/lib/wash_out/type.rb +29 -0
- data/lib/wash_out/version.rb +3 -0
- data/lib/wash_out/wsse.rb +101 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +51 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +23 -0
- data/spec/dummy/config/environments/test.rb +30 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +8 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/lib/wash_out/dispatcher_spec.rb +99 -0
- data/spec/lib/wash_out/middleware_spec.rb +33 -0
- data/spec/lib/wash_out/param_spec.rb +94 -0
- data/spec/lib/wash_out/router_spec.rb +22 -0
- data/spec/lib/wash_out/type_spec.rb +41 -0
- data/spec/lib/wash_out_spec.rb +754 -0
- data/spec/spec_helper.rb +82 -0
- data/wash_out.gemspec +21 -0
- metadata +128 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'wash_out/router'
|
3
|
+
|
4
|
+
describe WashOut::Router do
|
5
|
+
it 'returns a 200 with empty soap action' do
|
6
|
+
|
7
|
+
mock_controller do
|
8
|
+
# nothing
|
9
|
+
end
|
10
|
+
|
11
|
+
env = {}
|
12
|
+
env['REQUEST_METHOD'] = 'GET'
|
13
|
+
env['rack.input'] = double 'basic-rack-input', {:string => ''}
|
14
|
+
result = WashOut::Router.new('Api').call env
|
15
|
+
|
16
|
+
expect(result[0]).to eq(200)
|
17
|
+
#expect(result[1]['Content-Type']).to eq('text/xml')
|
18
|
+
|
19
|
+
msg = result[2][0]
|
20
|
+
expect(msg).to eq('OK')
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#encoding:utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe WashOut::Type do
|
6
|
+
|
7
|
+
it "defines custom type" do
|
8
|
+
|
9
|
+
class Abraka1 < WashOut::Type
|
10
|
+
map :test => :string
|
11
|
+
end
|
12
|
+
|
13
|
+
class Abraka2 < WashOut::Type
|
14
|
+
type_name 'test'
|
15
|
+
map :foo => Abraka1
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(Abraka1.wash_out_param_name).to eq 'abraka1'
|
19
|
+
expect(Abraka1.wash_out_param_map).to eq({:test => :string})
|
20
|
+
|
21
|
+
expect(Abraka2.wash_out_param_name).to eq 'test'
|
22
|
+
expect(Abraka2.wash_out_param_map).to eq({:foo => Abraka1})
|
23
|
+
end
|
24
|
+
|
25
|
+
it "allows arrays inside custom types" do
|
26
|
+
class Abraka1 < WashOut::Type
|
27
|
+
map :test => :string
|
28
|
+
end
|
29
|
+
class Abraka2 < WashOut::Type
|
30
|
+
type_name 'test'
|
31
|
+
map :foo => [:bar => Abraka1]
|
32
|
+
end
|
33
|
+
|
34
|
+
expect(Abraka1.wash_out_param_name).to eq 'abraka1'
|
35
|
+
expect(Abraka1.wash_out_param_map).to eq({:test => :string})
|
36
|
+
|
37
|
+
expect(Abraka2.wash_out_param_name).to eq 'test'
|
38
|
+
expect(Abraka2.wash_out_param_map).to eq({:foo => [:bar => Abraka1]})
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,754 @@
|
|
1
|
+
#encoding:utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe WashOut do
|
6
|
+
|
7
|
+
let :nori do
|
8
|
+
Nori.new(
|
9
|
+
:strip_namespaces => true,
|
10
|
+
:advanced_typecasting => true,
|
11
|
+
:convert_tags_to => lambda {|x| x.snakecase.to_sym}
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def savon(method, message={}, &block)
|
16
|
+
message = {:value => message} unless message.is_a?(Hash)
|
17
|
+
|
18
|
+
savon = Savon::Client.new(:log => false, :wsdl => 'http://app/api/wsdl', &block)
|
19
|
+
savon.call(method, :message => message).to_hash
|
20
|
+
end
|
21
|
+
|
22
|
+
def savon!(method, message={}, &block)
|
23
|
+
message = {:value => message} unless message.is_a?(Hash)
|
24
|
+
|
25
|
+
savon = Savon::Client.new(:log => true, :wsdl => 'http://app/api/wsdl', &block)
|
26
|
+
savon.call(method, :message => message).to_hash
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "Module" do
|
30
|
+
it "includes" do
|
31
|
+
expect {
|
32
|
+
mock_controller do
|
33
|
+
# nothing
|
34
|
+
end
|
35
|
+
}.not_to raise_exception
|
36
|
+
end
|
37
|
+
|
38
|
+
it "allows definition of a simple action" do
|
39
|
+
expect {
|
40
|
+
mock_controller do
|
41
|
+
soap_action "answer", :args => nil, :return => :integer
|
42
|
+
end
|
43
|
+
}.not_to raise_exception
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "WSDL" do
|
48
|
+
let :wsdl do
|
49
|
+
mock_controller do
|
50
|
+
soap_action :result, :args => nil, :return => :int
|
51
|
+
|
52
|
+
soap_action "getArea", :args => {
|
53
|
+
:circle => [{
|
54
|
+
:center => { :x => [:integer], :y => :integer },
|
55
|
+
:radius => :double
|
56
|
+
}]},
|
57
|
+
:return => { :area => :double }
|
58
|
+
soap_action "rocky", :args => { :circle1 => { :x => :integer } },
|
59
|
+
:return => { :circle2 => { :y => :integer } }
|
60
|
+
end
|
61
|
+
|
62
|
+
HTTPI.get("http://app/api/wsdl").body
|
63
|
+
end
|
64
|
+
|
65
|
+
let :xml do
|
66
|
+
nori.parse wsdl
|
67
|
+
end
|
68
|
+
|
69
|
+
it "lists operations" do
|
70
|
+
operations = xml[:definitions][:binding][:operation]
|
71
|
+
expect(operations).to be_a_kind_of(Array)
|
72
|
+
|
73
|
+
expect(operations.map{|e| e[:'@name']}.sort).to eq ['Result', 'getArea', 'rocky'].sort
|
74
|
+
end
|
75
|
+
|
76
|
+
it "defines complex types" do
|
77
|
+
expect(wsdl.include?('<xsd:complexType name="Circle1">')).to be true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "defines arrays" do
|
81
|
+
x = xml[:definitions][:types][:schema][:complex_type].
|
82
|
+
find{|x| x[:'@name'] == 'Center'}[:sequence][:element].
|
83
|
+
find{|x| x[:'@name'] == 'X'}
|
84
|
+
|
85
|
+
expect(x[:'@min_occurs']).to eq "0"
|
86
|
+
expect(x[:'@max_occurs']).to eq "unbounded"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "Dispatcher" do
|
91
|
+
|
92
|
+
context "simple actions" do
|
93
|
+
it "accepts requests with no HTTP header" do
|
94
|
+
mock_controller do
|
95
|
+
soap_action "answer", :args => nil, :return => :int
|
96
|
+
def answer
|
97
|
+
render :soap => "42"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
request = <<-XML
|
102
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
103
|
+
<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/">
|
104
|
+
<env:Body>
|
105
|
+
<tns:answer>
|
106
|
+
<value>42</value>
|
107
|
+
</tns:answer>
|
108
|
+
</env:Body>
|
109
|
+
</env:Envelope>
|
110
|
+
XML
|
111
|
+
|
112
|
+
expect(HTTPI.post("http://app/api/action", request).body).to eq <<-XML
|
113
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
114
|
+
<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
|
+
<soap:Body>
|
116
|
+
<tns:answerResponse>
|
117
|
+
<Value xsi:type="xsd:int">42</Value>
|
118
|
+
</tns:answerResponse>
|
119
|
+
</soap:Body>
|
120
|
+
</soap:Envelope>
|
121
|
+
XML
|
122
|
+
end
|
123
|
+
|
124
|
+
it "accept no parameters" do
|
125
|
+
mock_controller do
|
126
|
+
soap_action "answer", :args => nil, :return => :int
|
127
|
+
def answer
|
128
|
+
render :soap => "42"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
expect(savon(:answer)[:answer_response][:value]).
|
133
|
+
to eq "42"
|
134
|
+
end
|
135
|
+
|
136
|
+
it "accept insufficient parameters" do
|
137
|
+
mock_controller do
|
138
|
+
soap_action "answer", :args => {:a => :integer}, :return => :integer
|
139
|
+
def answer
|
140
|
+
render :soap => "42"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
expect(savon(:answer)[:answer_response][:value]).
|
145
|
+
to eq "42"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "accept empty parameter" do
|
149
|
+
mock_controller do
|
150
|
+
soap_action "answer", :args => {:a => :string}, :return => {:a => :string}
|
151
|
+
def answer
|
152
|
+
render :soap => {:a => params[:a]}
|
153
|
+
end
|
154
|
+
end
|
155
|
+
expect(savon(:answer, :a => '')[:answer_response][:a]).
|
156
|
+
to eq({:"@xsi:type"=>"xsd:string"})
|
157
|
+
end
|
158
|
+
|
159
|
+
it "accept one parameter" do
|
160
|
+
mock_controller do
|
161
|
+
soap_action "checkAnswer", :args => :integer, :return => :boolean, :to => 'check_answer'
|
162
|
+
def check_answer
|
163
|
+
render :soap => (params[:value] == 42)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
expect(savon(:check_answer, 42)[:check_answer_response][:value]).to be true
|
168
|
+
expect(savon(:check_answer, 13)[:check_answer_response][:value]).to be false
|
169
|
+
end
|
170
|
+
|
171
|
+
it "accept two parameters" do
|
172
|
+
mock_controller do
|
173
|
+
soap_action "funky", :args => { :a => :integer, :b => :string }, :return => :string
|
174
|
+
def funky
|
175
|
+
render :soap => ((params[:a] * 10).to_s + params[:b])
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
expect(savon(:funky, :a => 42, :b => 'k')[:funky_response][:value]).to eq '420k'
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context "complex actions" do
|
184
|
+
it "accept nested structures" do
|
185
|
+
mock_controller do
|
186
|
+
soap_action "getArea", :args => { :circle => { :center => { :x => :integer,
|
187
|
+
:y => :integer },
|
188
|
+
:radius => :double } },
|
189
|
+
:return => { :area => :double,
|
190
|
+
:distance_from_o => :double },
|
191
|
+
:to => :get_area
|
192
|
+
def get_area
|
193
|
+
circle = params[:circle]
|
194
|
+
render :soap => { :area => Math::PI * circle[:radius] ** 2,
|
195
|
+
:distance_from_o => Math.sqrt(circle[:center][:x] ** 2 + circle[:center][:y] ** 2) }
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
message = { :circle => { :center => { :x => 3, :y => 4 },
|
200
|
+
:radius => 5 } }
|
201
|
+
|
202
|
+
expect(savon(:get_area, message)[:get_area_response]).
|
203
|
+
to eq ({ :area => (Math::PI * 25).to_s, :distance_from_o => (5.0).to_s })
|
204
|
+
end
|
205
|
+
|
206
|
+
it "accept arrays" do
|
207
|
+
mock_controller do
|
208
|
+
soap_action "rumba",
|
209
|
+
:args => {
|
210
|
+
:rumbas => [:integer]
|
211
|
+
},
|
212
|
+
:return => nil
|
213
|
+
def rumba
|
214
|
+
expect(params).to eq({"rumbas" => [1, 2, 3]})
|
215
|
+
render :soap => nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
savon(:rumba, :rumbas => [1, 2, 3])
|
220
|
+
end
|
221
|
+
|
222
|
+
it "accept empty arrays" do
|
223
|
+
mock_controller do
|
224
|
+
soap_action "rumba",
|
225
|
+
:args => {
|
226
|
+
:my_array => [:integer]
|
227
|
+
},
|
228
|
+
:return => nil
|
229
|
+
def rumba
|
230
|
+
expect(params).to eq({})
|
231
|
+
render :soap => nil
|
232
|
+
end
|
233
|
+
end
|
234
|
+
savon(:rumba, :empty => [])
|
235
|
+
end
|
236
|
+
|
237
|
+
it "accept nested empty arrays" do
|
238
|
+
mock_controller do
|
239
|
+
soap_action "rumba",
|
240
|
+
:args => {
|
241
|
+
:nested => {:my_array => [:integer] }
|
242
|
+
},
|
243
|
+
:return => nil
|
244
|
+
def rumba
|
245
|
+
expect(params).to eq({"nested" => {}})
|
246
|
+
render :soap => nil
|
247
|
+
end
|
248
|
+
end
|
249
|
+
savon(:rumba, :nested => {:my_array => []})
|
250
|
+
end
|
251
|
+
|
252
|
+
it "accept nested structures inside arrays" do
|
253
|
+
mock_controller do
|
254
|
+
soap_action "rumba",
|
255
|
+
:args => {
|
256
|
+
:rumbas => [ {
|
257
|
+
:zombies => :string,
|
258
|
+
:puppies => :string
|
259
|
+
} ]
|
260
|
+
},
|
261
|
+
:return => nil
|
262
|
+
def rumba
|
263
|
+
expect(params).to eq({
|
264
|
+
"rumbas" => [
|
265
|
+
{"zombies" => 'suck', "puppies" => 'rock'},
|
266
|
+
{"zombies" => 'slow', "puppies" => 'fast'}
|
267
|
+
]
|
268
|
+
})
|
269
|
+
render :soap => nil
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
savon :rumba, :rumbas => [
|
274
|
+
{:zombies => 'suck', :puppies => 'rock'},
|
275
|
+
{:zombies => 'slow', :puppies => 'fast'}
|
276
|
+
]
|
277
|
+
end
|
278
|
+
|
279
|
+
it "respond with nested structures" do
|
280
|
+
mock_controller do
|
281
|
+
soap_action "gogogo",
|
282
|
+
:args => nil,
|
283
|
+
:return => {
|
284
|
+
:zoo => :string,
|
285
|
+
:boo => { :moo => :string, :doo => :string }
|
286
|
+
}
|
287
|
+
def gogogo
|
288
|
+
render :soap => {
|
289
|
+
:zoo => 'zoo',
|
290
|
+
:boo => { :moo => 'moo', :doo => 'doo' }
|
291
|
+
}
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
expect(savon(:gogogo)[:gogogo_response]).
|
296
|
+
to eq({
|
297
|
+
:zoo=>"zoo",
|
298
|
+
:boo=>{
|
299
|
+
:moo=>"moo",
|
300
|
+
:doo=>"doo",
|
301
|
+
:"@xsi:type"=>"tns:Boo"
|
302
|
+
}
|
303
|
+
})
|
304
|
+
end
|
305
|
+
|
306
|
+
it "respond with arrays" do
|
307
|
+
mock_controller do
|
308
|
+
soap_action "rumba",
|
309
|
+
:args => nil,
|
310
|
+
:return => [:integer]
|
311
|
+
def rumba
|
312
|
+
render :soap => [1, 2, 3]
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
expect(savon(:rumba)[:rumba_response]).to eq({
|
317
|
+
:value => ["1", "2", "3"]
|
318
|
+
})
|
319
|
+
end
|
320
|
+
|
321
|
+
it "respond with complex structures inside arrays" do
|
322
|
+
mock_controller do
|
323
|
+
soap_action "rumba",
|
324
|
+
:args => nil,
|
325
|
+
:return => {
|
326
|
+
:rumbas => [{:@level => :integer, :zombies => :string, :puppies => :string}]
|
327
|
+
}
|
328
|
+
def rumba
|
329
|
+
render :soap =>
|
330
|
+
{:rumbas => [
|
331
|
+
{:@level => 80, :zombies => "suck1", :puppies => "rock1" },
|
332
|
+
{:zombies => "suck2", :puppies => "rock2" }
|
333
|
+
]
|
334
|
+
}
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
expect(savon(:rumba)[:rumba_response]).to eq({
|
339
|
+
:rumbas => [
|
340
|
+
{:zombies => "suck1",:puppies => "rock1", :"@xsi:type"=>"tns:Rumbas", :@level => "80"},
|
341
|
+
{:zombies => "suck2", :puppies => "rock2", :"@xsi:type"=>"tns:Rumbas" }
|
342
|
+
]
|
343
|
+
})
|
344
|
+
end
|
345
|
+
|
346
|
+
it "respond with structs in structs in arrays" do
|
347
|
+
mock_controller do
|
348
|
+
soap_action "rumba",
|
349
|
+
:args => nil,
|
350
|
+
:return => [{:rumbas => {:@level => :integer, :zombies => :integer}}]
|
351
|
+
|
352
|
+
def rumba
|
353
|
+
render :soap => [{:rumbas => {:@level => 80, :zombies => 100000}}, {:rumbas => {:@level => 90, :zombies => 2}}]
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
expect(savon(:rumba)[:rumba_response]).to eq({
|
358
|
+
:value => [
|
359
|
+
{
|
360
|
+
:rumbas => {
|
361
|
+
:zombies => "100000",
|
362
|
+
:"@xsi:type" => "tns:Rumbas",
|
363
|
+
:"@level" => "80"
|
364
|
+
},
|
365
|
+
:"@xsi:type" => "tns:Value"
|
366
|
+
},
|
367
|
+
{
|
368
|
+
:rumbas => {
|
369
|
+
:zombies => "2",
|
370
|
+
:"@xsi:type" => "tns:Rumbas",
|
371
|
+
:@level => "90",
|
372
|
+
},
|
373
|
+
:"@xsi:type"=>"tns:Value"
|
374
|
+
}
|
375
|
+
]
|
376
|
+
})
|
377
|
+
end
|
378
|
+
|
379
|
+
context "with arrays missing" do
|
380
|
+
it "respond with simple definition" do
|
381
|
+
mock_controller do
|
382
|
+
soap_action "rocknroll",
|
383
|
+
:args => nil, :return => { :my_value => [:integer] }
|
384
|
+
def rocknroll
|
385
|
+
render :soap => {}
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
expect(savon(:rocknroll)[:rocknroll_response]).to be nil
|
390
|
+
end
|
391
|
+
|
392
|
+
it "respond with complext definition" do
|
393
|
+
mock_controller do
|
394
|
+
soap_action "rocknroll",
|
395
|
+
:args => nil, :return => { :my_value => [{ :value => :integer }] }
|
396
|
+
def rocknroll
|
397
|
+
render :soap => {}
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
expect(savon(:rocknroll)[:rocknroll_response]).to be nil
|
402
|
+
end
|
403
|
+
|
404
|
+
it "respond with nested simple definition" do
|
405
|
+
mock_controller do
|
406
|
+
soap_action "rocknroll",
|
407
|
+
:args => nil, :return => { :my_value => { :my_array => [{ :value => :integer }] } }
|
408
|
+
def rocknroll
|
409
|
+
render :soap => {}
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
expect(savon(:rocknroll)[:rocknroll_response][:my_value]).
|
414
|
+
to eq({
|
415
|
+
:"@xsi:type" => "tns:MyValue"
|
416
|
+
})
|
417
|
+
end
|
418
|
+
|
419
|
+
it "handles incomplete array response" do
|
420
|
+
mock_controller do
|
421
|
+
soap_action "rocknroll",
|
422
|
+
:args => nil, :return => { :my_value => [{ :value => :string }] }
|
423
|
+
def rocknroll
|
424
|
+
render :soap => { :my_value => [nil] }
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
expect{savon(:rocknroll)}.not_to raise_error
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
context "types" do
|
434
|
+
it "recognize boolean" do
|
435
|
+
mock_controller do
|
436
|
+
soap_action "true", :args => :boolean, :return => :nil
|
437
|
+
def true
|
438
|
+
expect(params[:value]).to be true
|
439
|
+
render :soap => nil
|
440
|
+
end
|
441
|
+
|
442
|
+
soap_action "false", :args => :boolean, :return => :nil
|
443
|
+
def false
|
444
|
+
expect(params[:value]).to be false
|
445
|
+
render :soap => nil
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
savon(:true, :value => "true")
|
450
|
+
savon(:true, :value => "1")
|
451
|
+
savon(:false, :value => "false")
|
452
|
+
savon(:false, :value => "0")
|
453
|
+
end
|
454
|
+
|
455
|
+
it "recognize dates" do
|
456
|
+
mock_controller do
|
457
|
+
soap_action "date", :args => :date, :return => :nil
|
458
|
+
def date
|
459
|
+
expect(params[:value]).to eq Date.parse('2000-12-30') unless params[:value].blank?
|
460
|
+
render :soap => nil
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
savon(:date, :value => '2000-12-30')
|
465
|
+
expect { savon(:date) }.not_to raise_exception
|
466
|
+
end
|
467
|
+
|
468
|
+
it "recognize base64Binary" do
|
469
|
+
mock_controller do
|
470
|
+
soap_action "base64", :args => :base64Binary, :return => :nil
|
471
|
+
def base64
|
472
|
+
expect(params[:value]).to eq('test') unless params[:value].blank?
|
473
|
+
render :soap => nil
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
savon(:base64, :value => Base64.encode64('test'))
|
478
|
+
expect { savon(:base64) }.not_to raise_exception
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
context "errors" do
|
483
|
+
it "raise for incorrect requests" do
|
484
|
+
mock_controller do
|
485
|
+
soap_action "duty",
|
486
|
+
:args => {:bad => {:a => :string, :b => :string}, :good => {:a => :string, :b => :string}},
|
487
|
+
:return => nil
|
488
|
+
def duty
|
489
|
+
render :soap => nil
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
expect {
|
494
|
+
savon(:duty, :bad => 42, :good => nil)
|
495
|
+
}.to raise_exception(Savon::SOAPFault)
|
496
|
+
end
|
497
|
+
|
498
|
+
it "raise for date in incorrect format" do
|
499
|
+
mock_controller do
|
500
|
+
soap_action "date", :args => :date, :return => :nil
|
501
|
+
def date
|
502
|
+
render :soap => nil
|
503
|
+
end
|
504
|
+
end
|
505
|
+
expect {
|
506
|
+
savon(:date, :value => 'incorrect format')
|
507
|
+
}.to raise_exception(Savon::SOAPFault)
|
508
|
+
end
|
509
|
+
|
510
|
+
it "raise to report SOAP errors" do
|
511
|
+
mock_controller do
|
512
|
+
soap_action "error", :args => { :need_error => :boolean }, :return => nil
|
513
|
+
def error
|
514
|
+
raise self.class.const_get(:SOAPError), "you wanted one" if params[:need_error]
|
515
|
+
render :soap => nil
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
expect { savon(:error, :need_error => false) }.not_to raise_exception
|
520
|
+
expect { savon(:error, :need_error => true) }.to raise_exception(Savon::SOAPFault)
|
521
|
+
end
|
522
|
+
|
523
|
+
it "misses basic exceptions" do
|
524
|
+
mock_controller do
|
525
|
+
soap_action "error", :args => { :need_error => :boolean }, :return => nil
|
526
|
+
def error
|
527
|
+
raise self.class.const_get(:Exception), "you wanted one" if params[:need_error]
|
528
|
+
render :soap => nil
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
expect { savon(:error, :need_error => false) }.not_to raise_exception
|
533
|
+
expect { savon(:error, :need_error => true) }.to raise_exception(Exception)
|
534
|
+
end
|
535
|
+
|
536
|
+
it "raise for manual throws" do
|
537
|
+
mock_controller do
|
538
|
+
soap_action "error", :args => nil, :return => nil
|
539
|
+
def error
|
540
|
+
render_soap_error "a message"
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
expect { savon(:error) }.to raise_exception(Savon::SOAPFault)
|
545
|
+
end
|
546
|
+
|
547
|
+
it "raise when response structure mismatches" do
|
548
|
+
mock_controller do
|
549
|
+
soap_action 'bad', :args => :integer, :return => {
|
550
|
+
:basic => :string,
|
551
|
+
:stallions => {
|
552
|
+
:stallion => [
|
553
|
+
:name => :string,
|
554
|
+
:wyldness => :integer,
|
555
|
+
]
|
556
|
+
},
|
557
|
+
}
|
558
|
+
def bad
|
559
|
+
render :soap => {
|
560
|
+
:basic => 'hi',
|
561
|
+
:stallions => [{:name => 'ted', :wyldness => 11}]
|
562
|
+
}
|
563
|
+
end
|
564
|
+
|
565
|
+
soap_action 'bad2', :args => :integer, :return => {
|
566
|
+
:basic => :string,
|
567
|
+
:telephone_booths => [:string]
|
568
|
+
}
|
569
|
+
def bad2
|
570
|
+
render :soap => {
|
571
|
+
:basic => 'hihi',
|
572
|
+
:telephone_booths => 'oops'
|
573
|
+
}
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
expect { savon(:bad) }.to raise_exception(
|
578
|
+
WashOut::Dispatcher::ProgrammerError,
|
579
|
+
/SOAP response .*wyldness.*Array.*Hash.*stallion/
|
580
|
+
)
|
581
|
+
|
582
|
+
expect { savon(:bad2) }.to raise_exception(
|
583
|
+
WashOut::Dispatcher::ProgrammerError,
|
584
|
+
/SOAP response .*oops.*String.*telephone_booths.*Array/
|
585
|
+
)
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
context "deprecates" do
|
590
|
+
# This test uses deprecated rspec expectations
|
591
|
+
# and it's not clear how to rewrite it.
|
592
|
+
xit "old syntax" do
|
593
|
+
# save rspec context check
|
594
|
+
raise_runtime_exception = raise_exception(RuntimeError)
|
595
|
+
|
596
|
+
mock_controller do
|
597
|
+
|
598
|
+
lambda {
|
599
|
+
soap_action "rumba",
|
600
|
+
:args => :integer,
|
601
|
+
:return => []
|
602
|
+
}.should raise_runtime_exception
|
603
|
+
def rumba
|
604
|
+
render :soap => nil
|
605
|
+
end
|
606
|
+
end
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
it "allows arbitrary action names" do
|
611
|
+
name = 'AnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything'
|
612
|
+
|
613
|
+
mock_controller do
|
614
|
+
soap_action name, :args => nil, :return => :integer, :to => :answer
|
615
|
+
def answer
|
616
|
+
render :soap => "forty two"
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
expect(savon(name.underscore.to_sym)["#{name.underscore}_response".to_sym][:value]).to eq "forty two"
|
621
|
+
end
|
622
|
+
|
623
|
+
it "respects :response_tag option" do
|
624
|
+
mock_controller do
|
625
|
+
soap_action "specific", :response_tag => "test", :return => :string
|
626
|
+
def specific
|
627
|
+
render :soap => "test"
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
expect(savon(:specific)).to eq({:test => {:value=>"test"}})
|
632
|
+
end
|
633
|
+
|
634
|
+
it "handles snakecase option properly" do
|
635
|
+
mock_controller(snakecase_input: false, camelize_wsdl: false) do
|
636
|
+
soap_action "rocknroll", :args => {:ZOMG => :string}, :return => nil
|
637
|
+
def rocknroll
|
638
|
+
expect(params["ZOMG"]).to eq "yam!"
|
639
|
+
render :soap => nil
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
savon(:rocknroll, "ZOMG" => 'yam!')
|
644
|
+
end
|
645
|
+
|
646
|
+
end
|
647
|
+
|
648
|
+
describe "WS Security" do
|
649
|
+
|
650
|
+
it "appends username_token to params" do
|
651
|
+
mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
|
652
|
+
soap_action "checkToken", :args => :integer, :return => nil, :to => 'check_token'
|
653
|
+
def check_token
|
654
|
+
expect(request.env['WSSE_TOKEN']['username']).to eq "gorilla"
|
655
|
+
expect(request.env['WSSE_TOKEN']['password']).to eq "secret"
|
656
|
+
render :soap => nil
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
savon(:check_token, 42) do
|
661
|
+
wsse_auth "gorilla", "secret"
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
it "handles PasswordText auth" do
|
666
|
+
mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
|
667
|
+
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
668
|
+
def check_auth
|
669
|
+
render :soap => (params[:value] == 42)
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
# correct auth
|
674
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
|
675
|
+
not_to raise_exception
|
676
|
+
|
677
|
+
# wrong user
|
678
|
+
expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret" } }.
|
679
|
+
to raise_exception(Savon::SOAPFault)
|
680
|
+
|
681
|
+
# wrong pass
|
682
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry" } }.
|
683
|
+
to raise_exception(Savon::SOAPFault)
|
684
|
+
|
685
|
+
# no auth
|
686
|
+
expect { savon(:check_auth, 42) }.
|
687
|
+
to raise_exception(Savon::SOAPFault)
|
688
|
+
end
|
689
|
+
|
690
|
+
it "handles PasswordDigest auth" do
|
691
|
+
mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
|
692
|
+
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
693
|
+
def check_auth
|
694
|
+
render :soap => (params[:value] == 42)
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
# correct auth
|
699
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
|
700
|
+
not_to raise_exception
|
701
|
+
|
702
|
+
# correct digest auth
|
703
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret", :digest } }.
|
704
|
+
not_to raise_exception
|
705
|
+
|
706
|
+
# wrong user
|
707
|
+
expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret", :digest } }.
|
708
|
+
to raise_exception(Savon::SOAPFault)
|
709
|
+
|
710
|
+
# wrong pass
|
711
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry", :digest } }.
|
712
|
+
to raise_exception(Savon::SOAPFault)
|
713
|
+
|
714
|
+
# no auth
|
715
|
+
expect { savon(:check_auth, 42) }.
|
716
|
+
to raise_exception(Savon::SOAPFault)
|
717
|
+
end
|
718
|
+
|
719
|
+
it "handles auth callback" do
|
720
|
+
mock_controller(
|
721
|
+
wsse_auth_callback: lambda {|user, password|
|
722
|
+
return user == "gorilla" && password == "secret"
|
723
|
+
}
|
724
|
+
) do
|
725
|
+
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
726
|
+
def check_auth
|
727
|
+
render :soap => (params[:value] == 42)
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
# correct auth
|
732
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret" } }.
|
733
|
+
not_to raise_exception
|
734
|
+
|
735
|
+
# correct digest auth
|
736
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "secret", :digest } }.
|
737
|
+
to raise_exception(Savon::SOAPFault)
|
738
|
+
|
739
|
+
# wrong user
|
740
|
+
expect { savon(:check_auth, 42){ wsse_auth "chimpanzee", "secret", :digest } }.
|
741
|
+
to raise_exception(Savon::SOAPFault)
|
742
|
+
|
743
|
+
# wrong pass
|
744
|
+
expect { savon(:check_auth, 42){ wsse_auth "gorilla", "nicetry", :digest } }.
|
745
|
+
to raise_exception(Savon::SOAPFault)
|
746
|
+
|
747
|
+
# no auth
|
748
|
+
expect { savon(:check_auth, 42) }.
|
749
|
+
to raise_exception(Savon::SOAPFault)
|
750
|
+
end
|
751
|
+
|
752
|
+
end
|
753
|
+
|
754
|
+
end
|