they-savon 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +13 -0
  4. data/CHANGELOG.md +631 -0
  5. data/Gemfile +9 -0
  6. data/LICENSE +20 -0
  7. data/README.md +42 -0
  8. data/Rakefile +7 -0
  9. data/lib/savon/client.rb +168 -0
  10. data/lib/savon/core_ext/object.rb +14 -0
  11. data/lib/savon/core_ext/string.rb +23 -0
  12. data/lib/savon/error.rb +6 -0
  13. data/lib/savon/global.rb +129 -0
  14. data/lib/savon/http/error.rb +42 -0
  15. data/lib/savon/soap/fault.rb +59 -0
  16. data/lib/savon/soap/request.rb +71 -0
  17. data/lib/savon/soap/response.rb +109 -0
  18. data/lib/savon/soap/xml.rb +227 -0
  19. data/lib/savon/soap.rb +21 -0
  20. data/lib/savon/version.rb +5 -0
  21. data/lib/savon/wasabi/document.rb +41 -0
  22. data/lib/savon.rb +14 -0
  23. data/savon.gemspec +32 -0
  24. data/spec/fixtures/gzip/message.gz +0 -0
  25. data/spec/fixtures/response/another_soap_fault.xml +14 -0
  26. data/spec/fixtures/response/authentication.xml +14 -0
  27. data/spec/fixtures/response/header.xml +13 -0
  28. data/spec/fixtures/response/list.xml +18 -0
  29. data/spec/fixtures/response/multi_ref.xml +39 -0
  30. data/spec/fixtures/response/soap_fault.xml +8 -0
  31. data/spec/fixtures/response/soap_fault12.xml +18 -0
  32. data/spec/fixtures/response/taxcloud.xml +1 -0
  33. data/spec/fixtures/wsdl/authentication.xml +63 -0
  34. data/spec/fixtures/wsdl/lower_camel.xml +52 -0
  35. data/spec/fixtures/wsdl/multiple_namespaces.xml +61 -0
  36. data/spec/fixtures/wsdl/multiple_types.xml +60 -0
  37. data/spec/fixtures/wsdl/taxcloud.xml +934 -0
  38. data/spec/savon/client_spec.rb +461 -0
  39. data/spec/savon/core_ext/object_spec.rb +19 -0
  40. data/spec/savon/core_ext/string_spec.rb +37 -0
  41. data/spec/savon/http/error_spec.rb +52 -0
  42. data/spec/savon/savon_spec.rb +146 -0
  43. data/spec/savon/soap/fault_spec.rb +89 -0
  44. data/spec/savon/soap/request_spec.rb +57 -0
  45. data/spec/savon/soap/response_spec.rb +224 -0
  46. data/spec/savon/soap/xml_spec.rb +309 -0
  47. data/spec/savon/soap_spec.rb +16 -0
  48. data/spec/savon/wasabi/document_spec.rb +45 -0
  49. data/spec/spec_helper.rb +15 -0
  50. data/spec/support/endpoint.rb +25 -0
  51. data/spec/support/fixture.rb +35 -0
  52. metadata +216 -0
@@ -0,0 +1,146 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon do
4
+
5
+ describe ".configure" do
6
+ around do |example|
7
+ Savon.reset_config!
8
+ example.run
9
+ Savon.reset_config!
10
+ Savon.log = false # disable logging
11
+ end
12
+
13
+ describe "log" do
14
+ it "should default to true" do
15
+ Savon.log?.should be_true
16
+ end
17
+
18
+ it "should set whether to log HTTP requests" do
19
+ Savon.configure { |config| config.log = false }
20
+ Savon.log?.should be_false
21
+ end
22
+ end
23
+
24
+ describe "logger" do
25
+ it "should set the logger to use" do
26
+ MyLogger = Class.new
27
+ Savon.configure { |config| config.logger = MyLogger }
28
+ Savon.logger.should == MyLogger
29
+ end
30
+
31
+ it "should default to Logger writing to STDOUT" do
32
+ Savon.logger.should be_a(Logger)
33
+ end
34
+ end
35
+
36
+ describe "log filter" do
37
+
38
+ context "without a log filter set" do
39
+ it "should not filter XML messages" do
40
+ filtered_message = Savon.filtered(Fixture.response(:authentication))
41
+ filtered_message.should == Fixture.response(:authentication)
42
+ end
43
+
44
+ it "should not filter non-XML messages" do
45
+ filtered_message = Savon.filtered('This is an information message.')
46
+ filtered_message.should == 'This is an information message.'
47
+ end
48
+ end
49
+
50
+ context "with a log filter set" do
51
+ before(:each) do
52
+ Savon.configure { |config| config.log_filter = ['tokenHash'] }
53
+ end
54
+
55
+ it "should set log filter" do
56
+ Savon.log_filter.should == ['tokenHash']
57
+ end
58
+
59
+ it "should filter element values" do
60
+ filtered_value = "AAAJxA;cIedoT;mY10ExZwG6JuKgp2OYKxow=="
61
+ filtered_message = Savon.filtered(Fixture.response(:authentication))
62
+ filtered_message.should_not include(filtered_value)
63
+ filtered_message.should include('***FILTERED***')
64
+ end
65
+
66
+ it "should not filter non-XML messages" do
67
+ filtered_message = Savon.filtered('This is an information message.')
68
+ filtered_message.should == 'This is an information message.'
69
+ end
70
+ end
71
+
72
+ context "with multiple log filters set" do
73
+ before(:each) do
74
+ Savon.configure { |config| config.log_filter = ['logType','logTime'] }
75
+ end
76
+
77
+ it "should filter element values" do
78
+ filtered_values = /Notes Log|2010-09-21T18:22:01|2010-09-21T18:22:07/
79
+ filtered_message = Savon.filtered(Fixture.response(:list))
80
+
81
+ filtered_message.should_not =~ filtered_values
82
+ filtered_message.should include('<ns10:logTime>***FILTERED***</ns10:logTime>')
83
+ filtered_message.should include('<ns10:logType>***FILTERED***</ns10:logType>')
84
+ filtered_message.should include('<ns11:logTime>***FILTERED***</ns11:logTime>')
85
+ filtered_message.should include('<ns11:logType>***FILTERED***</ns11:logType>')
86
+ end
87
+
88
+ it "should not filter non-XML messages" do
89
+ filtered_message = Savon.filtered('This is an information message.')
90
+
91
+ filtered_message.should == 'This is an information message.'
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ describe "log_level" do
98
+ it "should default to :debug" do
99
+ Savon.log_level.should == :debug
100
+ end
101
+
102
+ it "should set the log level to use" do
103
+ Savon.configure { |config| config.log_level = :info }
104
+ Savon.log_level.should == :info
105
+ end
106
+ end
107
+
108
+ describe "raise_errors" do
109
+ it "should default to true" do
110
+ Savon.raise_errors?.should be_true
111
+ end
112
+
113
+ it "should not raise errors when disabled" do
114
+ Savon.raise_errors = false
115
+ Savon.raise_errors?.should be_false
116
+ end
117
+ end
118
+
119
+ describe "soap_version" do
120
+ it "should default to SOAP 1.1" do
121
+ Savon.soap_version.should == 1
122
+ end
123
+
124
+ it "should return 2 if set to SOAP 1.2" do
125
+ Savon.soap_version = 2
126
+ Savon.soap_version.should == 2
127
+ end
128
+
129
+ it "should raise an ArgumentError in case of an invalid version" do
130
+ lambda { Savon.soap_version = 3 }.should raise_error(ArgumentError)
131
+ end
132
+ end
133
+
134
+ describe "strip_namespaces" do
135
+ it "should default to true" do
136
+ Savon.strip_namespaces?.should == true
137
+ end
138
+
139
+ it "should not strip namespaces when set to false" do
140
+ Savon.strip_namespaces = false
141
+ Savon.strip_namespaces?.should == false
142
+ end
143
+ end
144
+ end
145
+
146
+ end
@@ -0,0 +1,89 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::SOAP::Fault do
4
+ let(:soap_fault) { Savon::SOAP::Fault.new new_response(:body => Fixture.response(:soap_fault)) }
5
+ let(:soap_fault2) { Savon::SOAP::Fault.new new_response(:body => Fixture.response(:soap_fault12)) }
6
+ let(:another_soap_fault) { Savon::SOAP::Fault.new new_response(:body => Fixture.response(:another_soap_fault)) }
7
+ let(:no_fault) { Savon::SOAP::Fault.new new_response }
8
+
9
+ it "should be a Savon::Error" do
10
+ Savon::SOAP::Fault.should < Savon::Error
11
+ end
12
+
13
+ describe "#http" do
14
+ it "should return the HTTPI::Response" do
15
+ soap_fault.http.should be_an(HTTPI::Response)
16
+ end
17
+ end
18
+
19
+ describe "#present?" do
20
+ it "should return true if the HTTP response contains a SOAP 1.1 fault" do
21
+ soap_fault.should be_present
22
+ end
23
+
24
+ it "should return true if the HTTP response contains a SOAP 1.2 fault" do
25
+ soap_fault2.should be_present
26
+ end
27
+
28
+ it "should return true if the HTTP response contains a SOAP fault with different namespaces" do
29
+ another_soap_fault.should be_present
30
+ end
31
+
32
+ it "should return false unless the HTTP response contains a SOAP fault" do
33
+ no_fault.should_not be_present
34
+ end
35
+ end
36
+
37
+ [:message, :to_s].each do |method|
38
+ describe "##{method}" do
39
+ it "should return an empty String unless a SOAP fault is present" do
40
+ no_fault.send(method).should == ""
41
+ end
42
+
43
+ it "should return a SOAP 1.1 fault message" do
44
+ soap_fault.send(method).should == "(soap:Server) Fault occurred while processing."
45
+ end
46
+
47
+ it "should return a SOAP 1.2 fault message" do
48
+ soap_fault2.send(method).should == "(soap:Sender) Sender Timeout"
49
+ end
50
+
51
+ it "should return a SOAP fault message (with different namespaces)" do
52
+ another_soap_fault.send(method).should == "(ERR_NO_SESSION) Wrong session message"
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#to_hash" do
58
+ it "should return the SOAP response as a Hash unless a SOAP fault is present" do
59
+ no_fault.to_hash[:authenticate_response][:return][:success].should be_true
60
+ end
61
+
62
+ it "should return a SOAP 1.1 fault as a Hash" do
63
+ soap_fault.to_hash.should == {
64
+ :fault => {
65
+ :faultstring => "Fault occurred while processing.",
66
+ :faultcode => "soap:Server"
67
+ }
68
+ }
69
+ end
70
+
71
+ it "should return a SOAP 1.2 fault as a Hash" do
72
+ soap_fault2.to_hash.should == {
73
+ :fault => {
74
+ :detail => { :max_time => "P5M" },
75
+ :reason => { :text => "Sender Timeout" },
76
+ :code => { :value => "soap:Sender", :subcode => { :value => "m:MessageTimeout" } }
77
+ }
78
+ }
79
+ end
80
+ end
81
+
82
+ def new_response(options = {})
83
+ defaults = { :code => 500, :headers => {}, :body => Fixture.response(:authentication) }
84
+ response = defaults.merge options
85
+
86
+ HTTPI::Response.new response[:code], response[:headers], response[:body]
87
+ end
88
+
89
+ end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::SOAP::Request do
4
+ let(:soap_request) { Savon::SOAP::Request.new HTTPI::Request.new, soap }
5
+ let(:soap) { Savon::SOAP::XML.new Endpoint.soap, [nil, :get_user, {}], :id => 1 }
6
+
7
+ it "contains the content type for each supported SOAP version" do
8
+ content_type = Savon::SOAP::Request::ContentType
9
+ content_type[1].should == "text/xml;charset=UTF-8"
10
+ content_type[2].should == "application/soap+xml;charset=UTF-8"
11
+ end
12
+
13
+ describe ".execute" do
14
+ it "executes a SOAP request and returns the response" do
15
+ HTTPI.expects(:post).returns(HTTPI::Response.new 200, {}, Fixture.response(:authentication))
16
+ response = Savon::SOAP::Request.execute HTTPI::Request.new, soap
17
+ response.should be_a(Savon::SOAP::Response)
18
+ end
19
+ end
20
+
21
+ describe ".new" do
22
+ it "uses the SOAP endpoint for the request" do
23
+ soap_request.request.url.should == URI(soap.endpoint)
24
+ end
25
+
26
+ it "sets the SOAP body for the request" do
27
+ soap_request.request.body.should == soap.to_xml
28
+ end
29
+
30
+ it "sets the Content-Type header for SOAP 1.1" do
31
+ soap_request.request.headers["Content-Type"].should == Savon::SOAP::Request::ContentType[1]
32
+ end
33
+
34
+ it "sets the Content-Type header for SOAP 1.2" do
35
+ soap.version = 2
36
+ soap_request.request.headers["Content-Type"].should == Savon::SOAP::Request::ContentType[2]
37
+ end
38
+
39
+ it "does not set the Content-Type header if it's already specified" do
40
+ headers = { "Content-Type" => "text/plain" }
41
+ soap_request = Savon::SOAP::Request.new HTTPI::Request.new(:headers => headers), soap
42
+ soap_request.request.headers["Content-Type"].should == headers["Content-Type"]
43
+ end
44
+
45
+ it "sets the Content-Length header" do
46
+ soap_request.request.headers["Content-Length"].should == soap.to_xml.length.to_s
47
+ end
48
+ end
49
+
50
+ describe "#response" do
51
+ it "executes an HTTP POST request and returns a Savon::SOAP::Response" do
52
+ HTTPI.expects(:post).returns(HTTPI::Response.new 200, {}, Fixture.response(:authentication))
53
+ soap_request.response.should be_a(Savon::SOAP::Response)
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,224 @@
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 "#[]" do
120
+ it "should return the SOAP response body as a Hash" do
121
+ soap_response[:authenticate_response][:return].should ==
122
+ Fixture.response_hash(:authentication)[:authenticate_response][:return]
123
+ end
124
+ end
125
+
126
+ describe "#header" do
127
+ it "should return the SOAP response header as a Hash" do
128
+ response = soap_response :body => Fixture.response(:header)
129
+ response.header.should include(:session_number => "ABCD1234")
130
+ end
131
+ end
132
+
133
+ %w(body to_hash).each do |method|
134
+ describe "##{method}" do
135
+ it "should return the SOAP response body as a Hash" do
136
+ soap_response.send(method)[:authenticate_response][:return].should ==
137
+ Fixture.response_hash(:authentication)[:authenticate_response][:return]
138
+ end
139
+
140
+ it "should return a Hash for a SOAP multiRef response" do
141
+ hash = soap_response(:body => Fixture.response(:multi_ref)).send(method)
142
+
143
+ hash[:list_response].should be_a(Hash)
144
+ hash[:multi_ref].should be_an(Array)
145
+ end
146
+
147
+ it "should add existing namespaced elements as an array" do
148
+ hash = soap_response(:body => Fixture.response(:list)).send(method)
149
+
150
+ hash[:multi_namespaced_entry_response][:history].should be_a(Hash)
151
+ hash[:multi_namespaced_entry_response][:history][:case].should be_an(Array)
152
+ end
153
+ end
154
+ end
155
+
156
+ describe "#to_array" do
157
+ context "when the given path exists" do
158
+ it "should return an Array containing the path value" do
159
+ soap_response.to_array(:authenticate_response, :return).should ==
160
+ [Fixture.response_hash(:authentication)[:authenticate_response][:return]]
161
+ end
162
+ end
163
+
164
+ context "when the given path returns nil" do
165
+ it "should return an empty Array" do
166
+ soap_response.to_array(:authenticate_response, :undefined).should == []
167
+ end
168
+ end
169
+
170
+ context "when the given path does not exist at all" do
171
+ it "should return an empty Array" do
172
+ soap_response.to_array(:authenticate_response, :some, :undefined, :path).should == []
173
+ end
174
+ end
175
+ end
176
+
177
+ describe "#hash" do
178
+ it "should return the complete SOAP response XML as a Hash" do
179
+ response = soap_response :body => Fixture.response(:header)
180
+ response.hash[:envelope][:header][:session_number].should == "ABCD1234"
181
+ end
182
+ end
183
+
184
+ describe "#to_xml" do
185
+ it "should return the raw SOAP response body" do
186
+ soap_response.to_xml.should == Fixture.response(:authentication)
187
+ end
188
+ end
189
+
190
+ describe "#doc" do
191
+ it "returns a Nokogiri::XML::Document for the SOAP response XML" do
192
+ soap_response.doc.should be_a(Nokogiri::XML::Document)
193
+ end
194
+ end
195
+
196
+ describe "#xpath" do
197
+ it "permits XPath access to elements in the request" do
198
+ soap_response.xpath("//client").first.inner_text.should == "radclient"
199
+ soap_response.xpath("//ns2:authenticateResponse/return/success").first.inner_text.should == "true"
200
+ end
201
+ end
202
+
203
+ describe "#http" do
204
+ it "should return the HTTPI::Response" do
205
+ soap_response.http.should be_an(HTTPI::Response)
206
+ end
207
+ end
208
+
209
+ def soap_response(options = {})
210
+ defaults = { :code => 200, :headers => {}, :body => Fixture.response(:authentication) }
211
+ response = defaults.merge options
212
+
213
+ Savon::SOAP::Response.new HTTPI::Response.new(response[:code], response[:headers], response[:body])
214
+ end
215
+
216
+ def soap_fault_response
217
+ soap_response :code => 500, :body => Fixture.response(:soap_fault)
218
+ end
219
+
220
+ def http_error_response
221
+ soap_response :code => 404, :body => "Not found"
222
+ end
223
+
224
+ end