savon 0.7.9 → 0.8.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.gitignore +9 -0
  2. data/.rspec +1 -0
  3. data/.yardopts +2 -0
  4. data/CHANGELOG.md +332 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +37 -0
  8. data/Rakefile +28 -39
  9. data/autotest/discover.rb +1 -0
  10. data/lib/savon.rb +10 -31
  11. data/lib/savon/client.rb +116 -98
  12. data/lib/savon/core_ext/array.rb +36 -22
  13. data/lib/savon/core_ext/datetime.rb +15 -6
  14. data/lib/savon/core_ext/hash.rb +122 -94
  15. data/lib/savon/core_ext/object.rb +19 -11
  16. data/lib/savon/core_ext/string.rb +62 -57
  17. data/lib/savon/core_ext/symbol.rb +13 -5
  18. data/lib/savon/error.rb +6 -0
  19. data/lib/savon/global.rb +75 -0
  20. data/lib/savon/http/error.rb +42 -0
  21. data/lib/savon/soap.rb +8 -283
  22. data/lib/savon/soap/fault.rb +48 -0
  23. data/lib/savon/soap/request.rb +61 -0
  24. data/lib/savon/soap/response.rb +65 -0
  25. data/lib/savon/soap/xml.rb +132 -0
  26. data/lib/savon/version.rb +2 -2
  27. data/lib/savon/wsdl/document.rb +107 -0
  28. data/lib/savon/wsdl/parser.rb +90 -0
  29. data/lib/savon/wsdl/request.rb +35 -0
  30. data/lib/savon/wsse.rb +42 -104
  31. data/savon.gemspec +26 -0
  32. data/spec/fixtures/response/response_fixture.rb +26 -26
  33. data/spec/fixtures/response/xml/list.xml +18 -0
  34. data/spec/fixtures/wsdl/wsdl_fixture.rb +6 -0
  35. data/spec/fixtures/wsdl/wsdl_fixture.yml +4 -4
  36. data/spec/savon/client_spec.rb +274 -51
  37. data/spec/savon/core_ext/datetime_spec.rb +1 -1
  38. data/spec/savon/core_ext/hash_spec.rb +40 -4
  39. data/spec/savon/core_ext/object_spec.rb +1 -1
  40. data/spec/savon/core_ext/string_spec.rb +0 -12
  41. data/spec/savon/http/error_spec.rb +52 -0
  42. data/spec/savon/savon_spec.rb +90 -0
  43. data/spec/savon/soap/fault_spec.rb +80 -0
  44. data/spec/savon/soap/request_spec.rb +45 -0
  45. data/spec/savon/soap/response_spec.rb +153 -0
  46. data/spec/savon/soap/xml_spec.rb +249 -0
  47. data/spec/savon/soap_spec.rb +4 -177
  48. data/spec/savon/{wsdl_spec.rb → wsdl/document_spec.rb} +54 -17
  49. data/spec/savon/wsdl/request_spec.rb +15 -0
  50. data/spec/savon/wsse_spec.rb +123 -92
  51. data/spec/spec_helper.rb +19 -4
  52. data/spec/support/endpoint.rb +25 -0
  53. metadata +97 -97
  54. data/.autotest +0 -5
  55. data/CHANGELOG +0 -176
  56. data/README.rdoc +0 -64
  57. data/lib/savon/core_ext.rb +0 -8
  58. data/lib/savon/core_ext/net_http.rb +0 -19
  59. data/lib/savon/core_ext/uri.rb +0 -10
  60. data/lib/savon/logger.rb +0 -56
  61. data/lib/savon/request.rb +0 -138
  62. data/lib/savon/response.rb +0 -174
  63. data/lib/savon/wsdl.rb +0 -137
  64. data/lib/savon/wsdl_stream.rb +0 -85
  65. data/spec/basic_spec_helper.rb +0 -11
  66. data/spec/endpoint_helper.rb +0 -23
  67. data/spec/http_stubs.rb +0 -26
  68. data/spec/integration/http_basic_auth_spec.rb +0 -16
  69. data/spec/integration/server.rb +0 -51
  70. data/spec/savon/core_ext/net_http_spec.rb +0 -38
  71. data/spec/savon/core_ext/uri_spec.rb +0 -19
  72. data/spec/savon/request_spec.rb +0 -117
  73. data/spec/savon/response_spec.rb +0 -179
  74. data/spec/spec.opts +0 -4
@@ -3,7 +3,7 @@ require "spec_helper"
3
3
  describe DateTime do
4
4
  before do
5
5
  @datetime = DateTime.new 2012, 03, 22, 16, 22, 33
6
- @datetime_string = "2012-03-22T16:22:33Z"
6
+ @datetime_string = "2012-03-22T16:22:33+00:00"
7
7
  end
8
8
 
9
9
  describe "to_soap_value" do
@@ -56,7 +56,7 @@ describe Hash do
56
56
 
57
57
  it "should convert DateTime objects to xs:dateTime compliant Strings" do
58
58
  hash = { :before => DateTime.new(2012, 03, 22, 16, 22, 33) }
59
- result = "<before>2012-03-22T16:22:33Z</before>"
59
+ result = "<before>2012-03-22T16:22:33+00:00</before>"
60
60
 
61
61
  hash.to_soap_xml.should == result
62
62
  end
@@ -67,7 +67,7 @@ describe Hash do
67
67
  DateTime.new(2012, 03, 22, 16, 22, 33)
68
68
  end
69
69
 
70
- hash, result = { :before => singleton }, "<before>2012-03-22T16:22:33Z</before>"
70
+ hash, result = { :before => singleton }, "<before>2012-03-22T16:22:33+00:00</before>"
71
71
  hash.to_soap_xml.should == result
72
72
  end
73
73
 
@@ -79,8 +79,12 @@ describe Hash do
79
79
  hash.to_soap_xml.should == result
80
80
  end
81
81
 
82
+ it "should properly serialize nil values" do
83
+ { :some => nil }.to_soap_xml.should == '<some xsi:nil="true"/>'
84
+ end
85
+
82
86
  it "should call to_s on any other Object" do
83
- [666, true, false, nil].each do |object|
87
+ [666, true, false].each do |object|
84
88
  { :some => object }.to_soap_xml.should == "<some>#{object}</some>"
85
89
  end
86
90
  end
@@ -151,6 +155,21 @@ describe Hash do
151
155
  soap_response.map_soap_response.should == result
152
156
  end
153
157
 
158
+ context "with Savon.strip_namespaces set to false" do
159
+ around do |example|
160
+ Savon.strip_namespaces = false
161
+ example.run
162
+ Savon.strip_namespaces = true
163
+ end
164
+
165
+ it "should not strip namespaces from Hash keys" do
166
+ soap_response = { "ns:userResponse" => { "ns2:id" => "666" } }
167
+ result = { "ns:user_response" => { "ns2:id" => "666" } }
168
+
169
+ soap_response.map_soap_response.should == result
170
+ end
171
+ end
172
+
154
173
  it "should convert Hash keys and values in Arrays" do
155
174
  soap_response = { "response" => [{ "name" => "dude" }, { "name" => "gorilla" }] }
156
175
  result = { :response=> [{ :name => "dude" }, { :name => "gorilla" }] }
@@ -166,7 +185,7 @@ describe Hash do
166
185
  end
167
186
 
168
187
  it "should convert Hash values matching the xs:dateTime format into DateTime Objects" do
169
- soap_response = { "response" => { "at" => "2012-03-22T16:22:33" } }
188
+ soap_response = { "response" => { "at" => "2012-03-22T16:22:33+00:00" } }
170
189
  result = { :response => { :at => DateTime.new(2012, 03, 22, 16, 22, 33) } }
171
190
 
172
191
  soap_response.map_soap_response.should == result
@@ -185,6 +204,23 @@ describe Hash do
185
204
 
186
205
  soap_response.map_soap_response.should == result
187
206
  end
207
+
208
+ it "should convert namespaced entries to array elements" do
209
+ soap_response = {
210
+ "history" => {
211
+ "ns10:case" => { "ns10:name" => "a_name" },
212
+ "ns11:case" => { "ns11:name" => "another_name" }
213
+ }
214
+ }
215
+
216
+ result = {
217
+ :history => {
218
+ :case => [{ :name => "a_name" }, { :name => "another_name" }]
219
+ }
220
+ }
221
+
222
+ soap_response.map_soap_response.should == result
223
+ end
188
224
  end
189
225
 
190
226
  end
@@ -23,7 +23,7 @@ describe Object do
23
23
  DateTime.new(2012, 03, 22, 16, 22, 33)
24
24
  end
25
25
 
26
- singleton.to_soap_value.should == "2012-03-22T16:22:33Z"
26
+ singleton.to_soap_value.should == "2012-03-22T16:22:33+00:00"
27
27
  end
28
28
 
29
29
  it "calls to_s unless the Object responds to to_datetime" do
@@ -2,18 +2,6 @@ require "spec_helper"
2
2
 
3
3
  describe String do
4
4
 
5
- describe "self.random" do
6
- it "returns a random 100-character String" do
7
- String.random.should be_a(String)
8
- String.random.length.should == 100
9
- end
10
-
11
- it "returns a random String of a given length" do
12
- String.random(50).should be_a(String)
13
- String.random(50).length.should == 50
14
- end
15
- end
16
-
17
5
  describe "snakecase" do
18
6
  it "converts a lowerCamelCase String to snakecase" do
19
7
  "lowerCamelCase".snakecase.should == "lower_camel_case"
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::HTTP::Error do
4
+ let(:http_error) { Savon::HTTP::Error.new new_response(:code => 404, :body => "Not Found") }
5
+ let(:no_error) { Savon::HTTP::Error.new new_response }
6
+
7
+ it "should be a Savon::Error" do
8
+ Savon::HTTP::Error.should < Savon::Error
9
+ end
10
+
11
+ describe "#http" do
12
+ it "should return the HTTPI::Response" do
13
+ http_error.http.should be_an(HTTPI::Response)
14
+ end
15
+ end
16
+
17
+ describe "#present?" do
18
+ it "should return true if there was an HTTP error" do
19
+ http_error.should be_present
20
+ end
21
+
22
+ it "should return false unless there was an HTTP error" do
23
+ no_error.should_not be_present
24
+ end
25
+ end
26
+
27
+ [:message, :to_s].each do |method|
28
+ describe "##{method}" do
29
+ it "should return an empty String unless an HTTP error is present" do
30
+ no_error.send(method).should == ""
31
+ end
32
+
33
+ it "should return the HTTP error message" do
34
+ http_error.send(method).should == "HTTP error (404): Not Found"
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "#to_hash" do
40
+ it "should return the HTTP response details as a Hash" do
41
+ http_error.to_hash.should == { :code => 404, :headers => {}, :body => "Not Found" }
42
+ end
43
+ end
44
+
45
+ def new_response(options = {})
46
+ defaults = { :code => 200, :headers => {}, :body => ResponseFixture.authentication }
47
+ response = defaults.merge options
48
+
49
+ HTTPI::Response.new response[:code], response[:headers], response[:body]
50
+ end
51
+
52
+ end
@@ -0,0 +1,90 @@
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
+ end
11
+
12
+ describe "log" do
13
+ it "should default to true" do
14
+ Savon.log?.should be_true
15
+ end
16
+
17
+ it "should set whether to log HTTP requests" do
18
+ Savon.configure { |config| config.log = false }
19
+ Savon.log?.should be_false
20
+ end
21
+ end
22
+
23
+ describe "logger" do
24
+ it "should set the logger to use" do
25
+ MyLogger = Class.new
26
+ Savon.configure { |config| config.logger = MyLogger }
27
+ Savon.logger.should == MyLogger
28
+ end
29
+
30
+ it "should default to Logger writing to STDOUT" do
31
+ Savon.logger.should be_a(Logger)
32
+ end
33
+ end
34
+
35
+ describe "log_level" do
36
+ it "should default to :debug" do
37
+ Savon.log_level.should == :debug
38
+ end
39
+
40
+ it "should set the log level to use" do
41
+ Savon.configure { |config| config.log_level = :info }
42
+ Savon.log_level.should == :info
43
+ end
44
+ end
45
+
46
+ describe "raise_errors" do
47
+ it "should default to true" do
48
+ Savon.raise_errors?.should be_true
49
+ end
50
+
51
+ it "should not raise errors when disabled" do
52
+ Savon.raise_errors = false
53
+ Savon.raise_errors?.should be_false
54
+
55
+ Savon.raise_errors = true # reset to default
56
+ end
57
+ end
58
+
59
+ describe "soap_version" do
60
+ it "should default to SOAP 1.1" do
61
+ Savon.soap_version.should == 1
62
+ end
63
+
64
+ it "should return 2 if set to SOAP 1.2" do
65
+ Savon.soap_version = 2
66
+ Savon.soap_version.should == 2
67
+
68
+ Savon.soap_version = 1 # reset to default
69
+ end
70
+
71
+ it "should raise an ArgumentError in case of an invalid version" do
72
+ lambda { Savon.soap_version = 3 }.should raise_error(ArgumentError)
73
+ end
74
+ end
75
+
76
+ describe "strip_namespaces" do
77
+ it "should default to true" do
78
+ Savon.strip_namespaces?.should == true
79
+ end
80
+
81
+ it "should not strip namespaces when set to false" do
82
+ Savon.strip_namespaces = false
83
+ Savon.strip_namespaces?.should == false
84
+
85
+ Savon.strip_namespaces = true # reset to default
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,80 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::SOAP::Fault do
4
+ let(:soap_fault) { Savon::SOAP::Fault.new new_response(:body => ResponseFixture.soap_fault) }
5
+ let(:soap_fault2) { Savon::SOAP::Fault.new new_response(:body => ResponseFixture.soap_fault12) }
6
+ let(:no_fault) { Savon::SOAP::Fault.new new_response }
7
+
8
+ it "should be a Savon::Error" do
9
+ Savon::SOAP::Fault.should < Savon::Error
10
+ end
11
+
12
+ describe "#http" do
13
+ it "should return the HTTPI::Response" do
14
+ soap_fault.http.should be_an(HTTPI::Response)
15
+ end
16
+ end
17
+
18
+ describe "#present?" do
19
+ it "should return true if the HTTP response contains a SOAP 1.1 fault" do
20
+ soap_fault.should be_present
21
+ end
22
+
23
+ it "should return true if the HTTP response contains a SOAP 1.2 fault" do
24
+ soap_fault2.should be_present
25
+ end
26
+
27
+ it "should return false unless the HTTP response contains a SOAP fault" do
28
+ no_fault.should_not be_present
29
+ end
30
+ end
31
+
32
+ [:message, :to_s].each do |method|
33
+ describe "##{method}" do
34
+ it "should return an empty String unless a SOAP fault is present" do
35
+ no_fault.send(method).should == ""
36
+ end
37
+
38
+ it "should return a SOAP 1.1 fault message" do
39
+ soap_fault.send(method).should == "(soap:Server) Fault occurred while processing."
40
+ end
41
+
42
+ it "should return a SOAP 1.2 fault message" do
43
+ soap_fault2.send(method).should == "(soap:Sender) Sender Timeout"
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#to_hash" do
49
+ it "should return the SOAP response as a Hash unless a SOAP fault is present" do
50
+ no_fault.to_hash[:authenticate_response][:return][:success].should be_true
51
+ end
52
+
53
+ it "should return a SOAP 1.1 fault as a Hash" do
54
+ soap_fault.to_hash.should == {
55
+ :fault => {
56
+ :faultstring => "Fault occurred while processing.",
57
+ :faultcode => "soap:Server"
58
+ }
59
+ }
60
+ end
61
+
62
+ it "should return a SOAP 1.2 fault as a Hash" do
63
+ soap_fault2.to_hash.should == {
64
+ :fault => {
65
+ :detail => { :max_time => "P5M" },
66
+ :reason => { :text => "Sender Timeout" },
67
+ :code => { :value => "soap:Sender", :subcode => { :value => "m:MessageTimeout" } }
68
+ }
69
+ }
70
+ end
71
+ end
72
+
73
+ def new_response(options = {})
74
+ defaults = { :code => 200, :headers => {}, :body => ResponseFixture.authentication }
75
+ response = defaults.merge options
76
+
77
+ HTTPI::Response.new response[:code], response[:headers], response[:body]
78
+ end
79
+
80
+ end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::SOAP::Request do
4
+ let(:request) { Savon::SOAP::Request.new HTTPI::Request.new, soap }
5
+ let(:soap) { Savon::SOAP::XML.new Endpoint.soap, :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 ".new" do
14
+ it "should use the SOAP endpoint for the request" do
15
+ request.request.url.should == URI(soap.endpoint)
16
+ end
17
+
18
+ it "should set the SOAP body for the request" do
19
+ request.request.body.should == soap.to_xml
20
+ end
21
+
22
+ it "should set the 'Content-Type' header for SOAP 1.1" do
23
+ request.request.headers["Content-Type"].should == Savon::SOAP::Request::ContentType[1]
24
+ end
25
+
26
+ it "should set the 'Content-Type' header for SOAP 1.2" do
27
+ soap.version = 2
28
+ request.request.headers["Content-Type"].should == Savon::SOAP::Request::ContentType[2]
29
+ end
30
+
31
+ it "should not set the 'Content-Type' header if it's already specified" do
32
+ headers = { "Content-Type" => "text/plain" }
33
+ request = Savon::SOAP::Request.new HTTPI::Request.new(:headers => headers), soap
34
+ request.request.headers["Content-Type"].should == headers["Content-Type"]
35
+ end
36
+ end
37
+
38
+ describe "#response" do
39
+ it "should execute an HTTP POST request and return a Savon::SOAP::Response" do
40
+ HTTPI.expects(:post).returns(HTTPI::Response.new 200, {}, ResponseFixture.authentication)
41
+ request.response.should be_a(Savon::SOAP::Response)
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,153 @@
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 "#to_hash" do
120
+ it "should return the SOAP response body as a Hash" do
121
+ soap_response.to_hash[:authenticate_response][:return].should ==
122
+ ResponseFixture.authentication(:to_hash)
123
+ end
124
+ end
125
+
126
+ describe "#to_xml" do
127
+ it "should return the raw SOAP response body" do
128
+ soap_response.to_xml.should == ResponseFixture.authentication
129
+ end
130
+ end
131
+
132
+ describe "#http" do
133
+ it "should return the HTTPI::Response" do
134
+ soap_response.http.should be_an(HTTPI::Response)
135
+ end
136
+ end
137
+
138
+ def soap_response(options = {})
139
+ defaults = { :code => 200, :headers => {}, :body => ResponseFixture.authentication }
140
+ response = defaults.merge options
141
+
142
+ Savon::SOAP::Response.new HTTPI::Response.new(response[:code], response[:headers], response[:body])
143
+ end
144
+
145
+ def soap_fault_response
146
+ soap_response :body => ResponseFixture.soap_fault
147
+ end
148
+
149
+ def http_error_response
150
+ soap_response :code => 404, :body => "Not found"
151
+ end
152
+
153
+ end