s-savon 0.8.6

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 (61) hide show
  1. data/.gitignore +9 -0
  2. data/.rspec +1 -0
  3. data/.yardopts +2 -0
  4. data/CHANGELOG.md +461 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +37 -0
  8. data/Rakefile +40 -0
  9. data/lib/savon.rb +14 -0
  10. data/lib/savon/client.rb +157 -0
  11. data/lib/savon/core_ext/hash.rb +70 -0
  12. data/lib/savon/core_ext/object.rb +14 -0
  13. data/lib/savon/core_ext/string.rb +51 -0
  14. data/lib/savon/core_ext/time.rb +14 -0
  15. data/lib/savon/error.rb +6 -0
  16. data/lib/savon/global.rb +75 -0
  17. data/lib/savon/http/error.rb +42 -0
  18. data/lib/savon/soap.rb +24 -0
  19. data/lib/savon/soap/fault.rb +59 -0
  20. data/lib/savon/soap/request.rb +61 -0
  21. data/lib/savon/soap/response.rb +80 -0
  22. data/lib/savon/soap/xml.rb +187 -0
  23. data/lib/savon/version.rb +5 -0
  24. data/lib/savon/wsdl/document.rb +112 -0
  25. data/lib/savon/wsdl/parser.rb +102 -0
  26. data/lib/savon/wsdl/request.rb +35 -0
  27. data/lib/savon/wsse.rb +150 -0
  28. data/savon.gemspec +29 -0
  29. data/spec/fixtures/gzip/message.gz +0 -0
  30. data/spec/fixtures/response/another_soap_fault.xml +14 -0
  31. data/spec/fixtures/response/authentication.xml +14 -0
  32. data/spec/fixtures/response/header.xml +13 -0
  33. data/spec/fixtures/response/list.xml +18 -0
  34. data/spec/fixtures/response/multi_ref.xml +39 -0
  35. data/spec/fixtures/response/soap_fault.xml +8 -0
  36. data/spec/fixtures/response/soap_fault12.xml +18 -0
  37. data/spec/fixtures/wsdl/authentication.xml +63 -0
  38. data/spec/fixtures/wsdl/geotrust.xml +156 -0
  39. data/spec/fixtures/wsdl/namespaced_actions.xml +307 -0
  40. data/spec/fixtures/wsdl/no_namespace.xml +115 -0
  41. data/spec/fixtures/wsdl/two_bindings.xml +25 -0
  42. data/spec/savon/client_spec.rb +346 -0
  43. data/spec/savon/core_ext/hash_spec.rb +121 -0
  44. data/spec/savon/core_ext/object_spec.rb +19 -0
  45. data/spec/savon/core_ext/string_spec.rb +57 -0
  46. data/spec/savon/core_ext/time_spec.rb +13 -0
  47. data/spec/savon/http/error_spec.rb +52 -0
  48. data/spec/savon/savon_spec.rb +85 -0
  49. data/spec/savon/soap/fault_spec.rb +89 -0
  50. data/spec/savon/soap/request_spec.rb +45 -0
  51. data/spec/savon/soap/response_spec.rb +174 -0
  52. data/spec/savon/soap/xml_spec.rb +335 -0
  53. data/spec/savon/soap_spec.rb +21 -0
  54. data/spec/savon/wsdl/document_spec.rb +132 -0
  55. data/spec/savon/wsdl/parser_spec.rb +99 -0
  56. data/spec/savon/wsdl/request_spec.rb +15 -0
  57. data/spec/savon/wsse_spec.rb +213 -0
  58. data/spec/spec_helper.rb +14 -0
  59. data/spec/support/endpoint.rb +25 -0
  60. data/spec/support/fixture.rb +37 -0
  61. metadata +251 -0
@@ -0,0 +1,174 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::SOAP::Response do
4
+
5
+ describe ".new" do
6
+ it "should raise a Savon::SOAP::Fault in case of a SOAP fault" do
7
+ lambda { soap_fault_response }.should raise_error(Savon::SOAP::Fault)
8
+ end
9
+
10
+ it "should not raise a Savon::SOAP::Fault in case the default is turned off" do
11
+ Savon.raise_errors = false
12
+ lambda { soap_fault_response }.should_not raise_error(Savon::SOAP::Fault)
13
+ Savon.raise_errors = true
14
+ end
15
+
16
+ it "should raise a Savon::HTTP::Error in case of an HTTP error" do
17
+ lambda { soap_response :code => 500 }.should raise_error(Savon::HTTP::Error)
18
+ end
19
+
20
+ it "should not raise a Savon::HTTP::Error in case the default is turned off" do
21
+ Savon.raise_errors = false
22
+ soap_response :code => 500
23
+ Savon.raise_errors = true
24
+ end
25
+ end
26
+
27
+ describe "#success?" do
28
+ around do |example|
29
+ Savon.raise_errors = false
30
+ example.run
31
+ Savon.raise_errors = true
32
+ end
33
+
34
+ it "should return true if the request was successful" do
35
+ soap_response.should be_a_success
36
+ end
37
+
38
+ it "should return false if there was a SOAP fault" do
39
+ soap_fault_response.should_not be_a_success
40
+ end
41
+
42
+ it "should return false if there was an HTTP error" do
43
+ http_error_response.should_not be_a_success
44
+ end
45
+ end
46
+
47
+ describe "#soap_fault?" do
48
+ around do |example|
49
+ Savon.raise_errors = false
50
+ example.run
51
+ Savon.raise_errors = true
52
+ end
53
+
54
+ it "should not return true in case the response seems to be ok" do
55
+ soap_response.soap_fault?.should be_false
56
+ end
57
+
58
+ it "should return true in case of a SOAP fault" do
59
+ soap_fault_response.soap_fault?.should be_true
60
+ end
61
+ end
62
+
63
+ describe "#soap_fault" do
64
+ around do |example|
65
+ Savon.raise_errors = false
66
+ example.run
67
+ Savon.raise_errors = true
68
+ end
69
+
70
+ it "should return a Savon::SOAP::Fault" do
71
+ soap_fault_response.soap_fault.should be_a(Savon::SOAP::Fault)
72
+ end
73
+
74
+ it "should return a Savon::SOAP::Fault containing the HTTPI::Response" do
75
+ soap_fault_response.soap_fault.http.should be_an(HTTPI::Response)
76
+ end
77
+
78
+ it "should return a Savon::SOAP::Fault even if the SOAP response seems to be ok" do
79
+ soap_response.soap_fault.should be_a(Savon::SOAP::Fault)
80
+ end
81
+ end
82
+
83
+ describe "#http_error?" do
84
+ around do |example|
85
+ Savon.raise_errors = false
86
+ example.run
87
+ Savon.raise_errors = true
88
+ end
89
+
90
+ it "should not return true in case the response seems to be ok" do
91
+ soap_response.http_error?.should_not be_true
92
+ end
93
+
94
+ it "should return true in case of an HTTP error" do
95
+ soap_response(:code => 500).http_error?.should be_true
96
+ end
97
+ end
98
+
99
+ describe "#http_error" do
100
+ around do |example|
101
+ Savon.raise_errors = false
102
+ example.run
103
+ Savon.raise_errors = true
104
+ end
105
+
106
+ it "should return a Savon::HTTP::Error" do
107
+ http_error_response.http_error.should be_a(Savon::HTTP::Error)
108
+ end
109
+
110
+ it "should return a Savon::HTTP::Error containing the HTTPI::Response" do
111
+ http_error_response.http_error.http.should be_an(HTTPI::Response)
112
+ end
113
+
114
+ it "should return a Savon::HTTP::Error even if the HTTP response seems to be ok" do
115
+ soap_response.http_error.should be_a(Savon::HTTP::Error)
116
+ end
117
+ end
118
+
119
+ describe "#header" do
120
+ it "should return the SOAP response header as a Hash" do
121
+ response = soap_response :body => Fixture.response(:header)
122
+ response.header.should include(:session_number => "ABCD1234")
123
+ end
124
+ end
125
+
126
+ describe "#to_hash" do
127
+ it "should return the SOAP response body as a Hash" do
128
+ soap_response.to_hash[:authenticate_response][:return].should ==
129
+ Fixture.response_hash(:authentication)[:authenticate_response][:return]
130
+ end
131
+ end
132
+
133
+ describe "#to_array" do
134
+ it "should delegate to Savon::SOAP::XML.to_array" do
135
+ Savon::SOAP::XML.expects(:to_array).with(soap_response.to_hash, :authenticate_response, :return)
136
+ soap_response.to_array :authenticate_response, :return
137
+ end
138
+ end
139
+
140
+ describe "#basic_hash" do
141
+ it "should return the complete SOAP response XML as a Hash" do
142
+ response = soap_response :body => Fixture.response(:header)
143
+ response.basic_hash["soap:Envelope"]["soap:Header"]["SessionNumber"].should == "ABCD1234"
144
+ end
145
+ end
146
+
147
+ describe "#to_xml" do
148
+ it "should return the raw SOAP response body" do
149
+ soap_response.to_xml.should == Fixture.response(:authentication)
150
+ end
151
+ end
152
+
153
+ describe "#http" do
154
+ it "should return the HTTPI::Response" do
155
+ soap_response.http.should be_an(HTTPI::Response)
156
+ end
157
+ end
158
+
159
+ def soap_response(options = {})
160
+ defaults = { :code => 200, :headers => {}, :body => Fixture.response(:authentication) }
161
+ response = defaults.merge options
162
+
163
+ Savon::SOAP::Response.new HTTPI::Response.new(response[:code], response[:headers], response[:body])
164
+ end
165
+
166
+ def soap_fault_response
167
+ soap_response :code => 500, :body => Fixture.response(:soap_fault)
168
+ end
169
+
170
+ def http_error_response
171
+ soap_response :code => 404, :body => "Not found"
172
+ end
173
+
174
+ end
@@ -0,0 +1,335 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::SOAP::XML do
4
+ let(:xml) { Savon::SOAP::XML.new Endpoint.soap, :authenticate, :id => 1 }
5
+
6
+ describe ".to_hash" do
7
+ it "should return a given SOAP response body as a Hash" do
8
+ hash = Savon::SOAP::XML.to_hash Fixture.response(:authentication)
9
+ hash[:authenticate_response][:return].should == {
10
+ :success => true,
11
+ :authentication_value => {
12
+ :token_hash => "AAAJxA;cIedoT;mY10ExZwG6JuKgp2OYKxow==",
13
+ :token => "a68d1d6379b62ff339a0e0c69ed4d9cf",
14
+ :client => "radclient"
15
+ }
16
+ }
17
+ end
18
+
19
+ it "should return a Hash for a SOAP multiRef response" do
20
+ hash = Savon::SOAP::XML.to_hash Fixture.response(:multi_ref)
21
+
22
+ hash[:list_response].should be_a(Hash)
23
+ hash[:multi_ref].should be_an(Array)
24
+ end
25
+
26
+ it "should add existing namespaced elements as an array" do
27
+ hash = Savon::SOAP::XML.to_hash Fixture.response(:list)
28
+
29
+ hash[:multi_namespaced_entry_response][:history].should be_a(Hash)
30
+ hash[:multi_namespaced_entry_response][:history][:case].should be_an(Array)
31
+ end
32
+ end
33
+
34
+ describe ".parse" do
35
+ it "should convert the given XML into a Hash" do
36
+ hash = Savon::SOAP::XML.parse Fixture.response(:list)
37
+ hash["soapenv:Envelope"]["soapenv:Body"].should be_a(Hash)
38
+ end
39
+ end
40
+
41
+ describe ".to_array" do
42
+ let(:response_hash) { Fixture.response_hash :authentication }
43
+
44
+ context "when the given path exists" do
45
+ it "should return an Array containing the path value" do
46
+ Savon::SOAP::XML.to_array(response_hash, :authenticate_response, :return).should ==
47
+ [response_hash[:authenticate_response][:return]]
48
+ end
49
+ end
50
+
51
+ context "when the given path returns nil" do
52
+ it "should return an empty Array" do
53
+ Savon::SOAP::XML.to_array(response_hash, :authenticate_response, :undefined).should == []
54
+ end
55
+ end
56
+
57
+ context "when the given path does not exist at all" do
58
+ it "should return an empty Array" do
59
+ Savon::SOAP::XML.to_array(response_hash, :authenticate_response, :some, :wrong, :path).should == []
60
+ end
61
+ end
62
+ end
63
+
64
+ describe ".new" do
65
+ it "should accept an endpoint, an input tag and a SOAP body" do
66
+ xml = Savon::SOAP::XML.new Endpoint.soap, :authentication, :id => 1
67
+
68
+ xml.endpoint.should == Endpoint.soap
69
+ xml.input.should == :authentication
70
+ xml.body.should == { :id => 1 }
71
+ end
72
+ end
73
+
74
+ describe "#input" do
75
+ it "should set the input tag" do
76
+ xml.input = :test
77
+ xml.input.should == :test
78
+ end
79
+ end
80
+
81
+ describe "#endpoint" do
82
+ it "should set the endpoint to use" do
83
+ xml.endpoint = "http://test.com"
84
+ xml.endpoint.should == "http://test.com"
85
+ end
86
+ end
87
+
88
+ describe "#version" do
89
+ it "should default to SOAP 1.1" do
90
+ xml.version.should == 1
91
+ end
92
+
93
+ it "should default to the global default" do
94
+ Savon.soap_version = 2
95
+ xml.version.should == 2
96
+
97
+ reset_soap_version
98
+ end
99
+
100
+ it "should set the SOAP version to use" do
101
+ xml.version = 2
102
+ xml.version.should == 2
103
+ end
104
+
105
+ it "should raise an ArgumentError in case of an invalid version" do
106
+ lambda { xml.version = 3 }.should raise_error(ArgumentError)
107
+ end
108
+ end
109
+
110
+ describe "#header" do
111
+ it "should default to an empty Hash" do
112
+ xml.header.should == {}
113
+ end
114
+
115
+ it "should set the SOAP header" do
116
+ xml.header = { "MySecret" => "abc" }
117
+ xml.header.should == { "MySecret" => "abc" }
118
+ end
119
+ end
120
+
121
+ describe "#env_namespace" do
122
+ it "should default to :env" do
123
+ xml.env_namespace.should == :env
124
+ end
125
+
126
+ it "should set the SOAP envelope namespace" do
127
+ xml.env_namespace = :soapenv
128
+ xml.env_namespace.should == :soapenv
129
+ end
130
+ end
131
+
132
+ describe "#namespaces" do
133
+ it "should default to a Hash containing the namespace for SOAP 1.1" do
134
+ xml.namespaces.should == { "xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/" }
135
+ end
136
+
137
+ it "should default to a Hash containing the namespace for SOAP 1.2 if that's the current version" do
138
+ xml.version = 2
139
+ xml.namespaces.should == { "xmlns:env" => "http://www.w3.org/2003/05/soap-envelope" }
140
+ end
141
+
142
+ it "should set the SOAP header" do
143
+ xml.namespaces = { "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema" }
144
+ xml.namespaces.should == { "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema" }
145
+ end
146
+ end
147
+
148
+ describe "#wsse" do
149
+ it "should set the Savon::WSSE object" do
150
+ xml.wsse = Savon::WSSE.new
151
+ xml.wsse.should be_a(Savon::WSSE)
152
+ end
153
+ end
154
+
155
+ describe "#body" do
156
+ it "should set the SOAP body Hash" do
157
+ xml.body = { :id => 1 }
158
+ xml.to_xml.should include("<id>1</id>")
159
+ end
160
+
161
+ it "should also accepts an XML String" do
162
+ xml.body = "<id>1</id>"
163
+ xml.to_xml.should include("<id>1</id>")
164
+ end
165
+ end
166
+
167
+ describe "#xml" do
168
+ it "lets you specify a completely custom XML String" do
169
+ xml.xml = "<custom>xml</custom>"
170
+ xml.to_xml.should == "<custom>xml</custom>"
171
+ end
172
+
173
+ it "yields a Builder::XmlMarkup object to a given block" do
174
+ xml.xml { |xml| xml.using("Builder") }
175
+ xml.to_xml.should == '<?xml version="1.0" encoding="UTF-8"?><using>Builder</using>'
176
+ end
177
+ end
178
+
179
+ describe "#to_xml" do
180
+ after { reset_soap_version }
181
+
182
+ context "by default" do
183
+ it "should start with an XML declaration" do
184
+ xml.to_xml.should match(/^<\?xml version="1.0" encoding="UTF-8"\?>/)
185
+ end
186
+
187
+ it "should use default SOAP envelope namespace" do
188
+ xml.to_xml.should include("<env:Envelope", "<env:Body")
189
+ end
190
+
191
+ it "should add the xsd namespace" do
192
+ uri = "http://www.w3.org/2001/XMLSchema"
193
+ xml.to_xml.should match(/<env:Envelope (.*)xmlns:xsd="#{uri}"(.*)>/)
194
+ end
195
+
196
+ it "should add the xsi namespace" do
197
+ uri = "http://www.w3.org/2001/XMLSchema-instance"
198
+ xml.to_xml.should match(/<env:Envelope (.*)xmlns:xsi="#{uri}"(.*)>/)
199
+ end
200
+
201
+ it "should have a SOAP envelope tag with a SOAP 1.1 namespace" do
202
+ uri = "http://schemas.xmlsoap.org/soap/envelope/"
203
+ xml.to_xml.should match(/<env:Envelope (.*)xmlns:env="#{uri}"(.*)>/)
204
+ end
205
+
206
+ it "should have a SOAP body containing the SOAP input tag and body Hash" do
207
+ xml.to_xml.should include('<env:Body><authenticate><id>1</id></authenticate></env:Body>')
208
+ end
209
+
210
+ it "should accept a SOAP body as an XML String" do
211
+ xml.body = "<someId>1</someId>"
212
+ xml.to_xml.should include('<env:Body><authenticate><someId>1</someId></authenticate></env:Body>')
213
+ end
214
+
215
+ it "should not contain a SOAP header" do
216
+ xml.to_xml.should_not include('<env:Header')
217
+ end
218
+ end
219
+
220
+ context "with a SOAP header" do
221
+ it "should contain the given header" do
222
+ xml.header = {
223
+ :token => "secret",
224
+ :attributes! => { :token => { :xmlns => "http://example.com" } }
225
+ }
226
+
227
+ xml.to_xml.should include('<env:Header><token xmlns="http://example.com">secret</token></env:Header>')
228
+ end
229
+ end
230
+
231
+ context "with the global SOAP version set to 1.2" do
232
+ it "should contain the namespace for SOAP 1.2" do
233
+ Savon.soap_version = 2
234
+
235
+ uri = "http://www.w3.org/2003/05/soap-envelope"
236
+ xml.to_xml.should match(/<env:Envelope (.*)xmlns:env="#{uri}"(.*)>/)
237
+ reset_soap_version
238
+ end
239
+ end
240
+
241
+ context "with a global and request SOAP version" do
242
+ it "should contain the namespace for the request SOAP version" do
243
+ Savon.soap_version = 2
244
+ xml.version = 1
245
+
246
+ uri = "http://schemas.xmlsoap.org/soap/envelope/"
247
+ xml.to_xml.should match(/<env:Envelope (.*)xmlns:env="#{uri}"(.*)>/)
248
+ reset_soap_version
249
+ end
250
+ end
251
+
252
+ context "with the SOAP envelope namespace set to an empty String" do
253
+ it "should not add a namespace to SOAP envelope tags" do
254
+ xml.env_namespace = ""
255
+ xml.to_xml.should include("<Envelope", "<Body")
256
+ end
257
+ end
258
+
259
+ context "using the #namespace and #namespace_identifier" do
260
+ it "should contain the specified namespace" do
261
+ xml.namespace_identifier = :wsdl
262
+ xml.namespace = "http://example.com"
263
+ xml.to_xml.should include('xmlns:wsdl="http://example.com"')
264
+ end
265
+ end
266
+
267
+ context "with :element_form_default set to :qualified and a :namespace" do
268
+ let :xml do
269
+ Savon::SOAP::XML.new Endpoint.soap, :authenticate, :user => { :id => 1, ":noNamespace" => true }
270
+ end
271
+
272
+ it "should namespace the default elements" do
273
+ xml.element_form_default = :qualified
274
+ xml.namespace_identifier = :wsdl
275
+
276
+ xml.to_xml.should include(
277
+ "<wsdl:user>",
278
+ "<wsdl:id>1</wsdl:id>",
279
+ "<noNamespace>true</noNamespace>"
280
+ )
281
+ end
282
+ end
283
+
284
+ context "with WSSE authentication" do
285
+ it "should containg a SOAP header with WSSE authentication details" do
286
+ xml.wsse = Savon::WSSE.new
287
+ xml.wsse.credentials "username", "password"
288
+
289
+ xml.to_xml.should include("<env:Header><wsse:Security")
290
+ xml.to_xml.should include("<wsse:Username>username</wsse:Username>")
291
+ xml.to_xml.should include("password</wsse:Password>")
292
+ end
293
+ end
294
+
295
+ context "with a simple input tag (Symbol)" do
296
+ it "should just add the input tag" do
297
+ xml.input = :simple
298
+ xml.to_xml.should include('<simple><id>1</id></simple>')
299
+ end
300
+ end
301
+
302
+ context "with a simple input tag (Array)" do
303
+ it "should just add the input tag" do
304
+ xml.input = :simple
305
+ xml.to_xml.should include('<simple><id>1</id></simple>')
306
+ end
307
+ end
308
+
309
+ context "with an input tag and a namespace Hash (Array)" do
310
+ it "should contain the input tag with namespaces" do
311
+ xml.input = [:getUser, { "active" => true }]
312
+ xml.to_xml.should include('<getUser active="true"><id>1</id></getUser>')
313
+ end
314
+ end
315
+
316
+ context "with a prefixed input tag (Array)" do
317
+ it "should contain a prefixed input tag" do
318
+ xml.input = [:wsdl, :getUser]
319
+ xml.to_xml.should include('<wsdl:getUser><id>1</id></wsdl:getUser>')
320
+ end
321
+ end
322
+
323
+ context "with a prefixed input tag and a namespace Hash (Array)" do
324
+ it "should contain a prefixed input tag with namespaces" do
325
+ xml.input = [:wsdl, :getUser, { :only_active => false }]
326
+ xml.to_xml.should include('<wsdl:getUser only_active="false"><id>1</id></wsdl:getUser>')
327
+ end
328
+ end
329
+ end
330
+
331
+ def reset_soap_version
332
+ Savon.soap_version = Savon::SOAP::DefaultVersion
333
+ end
334
+
335
+ end