tictoc-savon 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.autotest +5 -0
  2. data/CHANGELOG +176 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +64 -0
  5. data/Rakefile +50 -0
  6. data/lib/savon.rb +35 -0
  7. data/lib/savon/client.rb +131 -0
  8. data/lib/savon/core_ext.rb +8 -0
  9. data/lib/savon/core_ext/array.rb +31 -0
  10. data/lib/savon/core_ext/datetime.rb +10 -0
  11. data/lib/savon/core_ext/hash.rb +107 -0
  12. data/lib/savon/core_ext/net_http.rb +19 -0
  13. data/lib/savon/core_ext/object.rb +16 -0
  14. data/lib/savon/core_ext/string.rb +69 -0
  15. data/lib/savon/core_ext/symbol.rb +8 -0
  16. data/lib/savon/core_ext/uri.rb +10 -0
  17. data/lib/savon/logger.rb +56 -0
  18. data/lib/savon/request.rb +138 -0
  19. data/lib/savon/response.rb +174 -0
  20. data/lib/savon/soap.rb +302 -0
  21. data/lib/savon/version.rb +5 -0
  22. data/lib/savon/wsdl.rb +137 -0
  23. data/lib/savon/wsdl_stream.rb +85 -0
  24. data/lib/savon/wsse.rb +163 -0
  25. data/spec/basic_spec_helper.rb +11 -0
  26. data/spec/endpoint_helper.rb +23 -0
  27. data/spec/fixtures/gzip/gzip_response_fixture.rb +7 -0
  28. data/spec/fixtures/gzip/message.gz +0 -0
  29. data/spec/fixtures/response/response_fixture.rb +36 -0
  30. data/spec/fixtures/response/xml/authentication.xml +14 -0
  31. data/spec/fixtures/response/xml/multi_ref.xml +39 -0
  32. data/spec/fixtures/response/xml/soap_fault.xml +8 -0
  33. data/spec/fixtures/response/xml/soap_fault12.xml +18 -0
  34. data/spec/fixtures/wsdl/wsdl_fixture.rb +37 -0
  35. data/spec/fixtures/wsdl/wsdl_fixture.yml +42 -0
  36. data/spec/fixtures/wsdl/xml/authentication.xml +63 -0
  37. data/spec/fixtures/wsdl/xml/geotrust.xml +156 -0
  38. data/spec/fixtures/wsdl/xml/namespaced_actions.xml +307 -0
  39. data/spec/fixtures/wsdl/xml/no_namespace.xml +115 -0
  40. data/spec/http_stubs.rb +26 -0
  41. data/spec/integration/http_basic_auth_spec.rb +16 -0
  42. data/spec/integration/server.rb +51 -0
  43. data/spec/savon/client_spec.rb +86 -0
  44. data/spec/savon/core_ext/array_spec.rb +49 -0
  45. data/spec/savon/core_ext/datetime_spec.rb +21 -0
  46. data/spec/savon/core_ext/hash_spec.rb +190 -0
  47. data/spec/savon/core_ext/net_http_spec.rb +38 -0
  48. data/spec/savon/core_ext/object_spec.rb +34 -0
  49. data/spec/savon/core_ext/string_spec.rb +99 -0
  50. data/spec/savon/core_ext/symbol_spec.rb +12 -0
  51. data/spec/savon/core_ext/uri_spec.rb +19 -0
  52. data/spec/savon/request_spec.rb +117 -0
  53. data/spec/savon/response_spec.rb +179 -0
  54. data/spec/savon/soap_spec.rb +202 -0
  55. data/spec/savon/wsdl_spec.rb +107 -0
  56. data/spec/savon/wsse_spec.rb +132 -0
  57. data/spec/spec.opts +4 -0
  58. data/spec/spec_helper.rb +5 -0
  59. metadata +229 -0
@@ -0,0 +1,38 @@
1
+ require "spec_helper"
2
+
3
+ describe Net::HTTP do
4
+ before do
5
+ @some_uri = URI "http://example.com"
6
+ @another_uri = URI "http://example.org"
7
+ @http = Net::HTTP.new @some_uri.host, @some_uri.port
8
+ end
9
+
10
+ describe "endpoint" do
11
+ it "changes the address and port of a Net::HTTP object" do
12
+ @http.address.should == @some_uri.host
13
+ @http.port.should == @some_uri.port
14
+
15
+ @http.endpoint @another_uri.host, @another_uri.port
16
+ @http.address.should == @another_uri.host
17
+ @http.port.should == @another_uri.port
18
+ end
19
+ end
20
+
21
+ describe "ssl_client_auth" do
22
+ it "accepts a Hash of options for SSL client authentication" do
23
+ @http.cert.should be_nil
24
+ @http.key.should be_nil
25
+ @http.ca_file.should be_nil
26
+ @http.verify_mode.should be_nil
27
+
28
+ @http.ssl_client_auth :cert => "cert", :key => "key",
29
+ :ca_file => "ca_file", :verify_mode => OpenSSL::SSL::VERIFY_PEER
30
+
31
+ @http.cert.should == "cert"
32
+ @http.key.should == "key"
33
+ @http.ca_file.should == "ca_file"
34
+ @http.verify_mode.should == OpenSSL::SSL::VERIFY_PEER
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ describe Object do
4
+
5
+ describe "blank?" do
6
+ it "returns true for Objects perceived to be blank" do
7
+ ["", false, nil, [], {}].each do |object|
8
+ object.should be_blank
9
+ end
10
+ end
11
+
12
+ it "returns false for every other Object" do
13
+ ["!blank", true, [:a], {:a => "b"}].each do |object|
14
+ object.should_not be_blank
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "to_soap_value" do
20
+ it "returns an xs:dateTime compliant String for Objects responding to to_datetime" do
21
+ singleton = Object.new
22
+ def singleton.to_datetime
23
+ DateTime.new(2012, 03, 22, 16, 22, 33)
24
+ end
25
+
26
+ singleton.to_soap_value.should == "2012-03-22T16:22:33Z"
27
+ end
28
+
29
+ it "calls to_s unless the Object responds to to_datetime" do
30
+ "value".to_soap_value.should == "value".to_s
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,99 @@
1
+ require "spec_helper"
2
+
3
+ describe String do
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
+ describe "snakecase" do
18
+ it "converts a lowerCamelCase String to snakecase" do
19
+ "lowerCamelCase".snakecase.should == "lower_camel_case"
20
+ end
21
+
22
+ it "converts period characters to underscores" do
23
+ "User.GetEmail".snakecase.should == "user_get_email"
24
+ end
25
+ end
26
+
27
+ describe "lower_camelcase" do
28
+ it "converts a snakecase String to lowerCamelCase" do
29
+ "lower_camel_case".lower_camelcase.should == "lowerCamelCase"
30
+ end
31
+ end
32
+
33
+ describe "starts_with?" do
34
+ it "should return whether it starts with a given suffix" do
35
+ "authenticate".starts_with?("auth").should be_true
36
+ "authenticate".starts_with?("cate").should be_false
37
+ end
38
+ end
39
+
40
+ describe "ends_with?" do
41
+ it "should return whether it ends with a given suffix" do
42
+ "authenticate!".ends_with?("!").should be_true
43
+ "authenticate".ends_with?("cate").should be_true
44
+ "authenticate".ends_with?("?").should be_false
45
+ end
46
+ end
47
+
48
+ describe "strip_namespace" do
49
+ it "strips the namespace from a namespaced String" do
50
+ "ns:customer".strip_namespace.should == "customer"
51
+ end
52
+
53
+ it "returns the original String for a String without namespace" do
54
+ "customer".strip_namespace.should == "customer"
55
+ end
56
+ end
57
+
58
+ describe "map_soap_response" do
59
+ it "returns a DateTime Object for Strings matching the xs:dateTime format" do
60
+ "2012-03-22T16:22:33".map_soap_response.should ==
61
+ DateTime.new(2012, 03, 22, 16, 22, 33)
62
+ end
63
+
64
+ it "returns true for Strings matching 'true'" do
65
+ "true".map_soap_response.should be_true
66
+ end
67
+
68
+ it "returns false for Strings matching 'false'" do
69
+ "false".map_soap_response.should be_false
70
+ end
71
+
72
+ it "defaults to return the original value" do
73
+ "whatever".map_soap_response.should == "whatever"
74
+ end
75
+ end
76
+
77
+ describe "to_soap_key" do
78
+ it "removes exclamation marks from the end of the String" do
79
+ "value".to_soap_key.should == "value"
80
+ "value!".to_soap_key.should == "value"
81
+ end
82
+ end
83
+
84
+ describe "to_soap_value" do
85
+ it "should return the String value and escape special characters" do
86
+ "string".to_soap_value.should == "string"
87
+ "<tag>".to_soap_value.should == "&lt;tag&gt;"
88
+ "at&t".to_soap_value.should == "at&amp;t"
89
+ '"quotes"'.to_soap_value.should == "&quot;quotes&quot;"
90
+ end
91
+ end
92
+
93
+ describe "to_soap_value!" do
94
+ it "should just return the String value without escaping special characters" do
95
+ "<tag>".to_soap_value!.should == "<tag>"
96
+ end
97
+ end
98
+
99
+ end
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe Symbol do
4
+
5
+ describe "to_soap_key" do
6
+ it "converts the Symbol from snake_case to a lowerCamelCase String" do
7
+ :lower_camel_case.to_soap_key.should == "lowerCamelCase"
8
+ :lower_camel_case!.to_soap_key.should == "lowerCamelCase"
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe URI::HTTP do
4
+
5
+ describe "ssl?" do
6
+ it "returns true for https URI's" do
7
+ URI("https://example.com").ssl?.should be_true
8
+ end
9
+
10
+ it "returns false for non-https URI's" do
11
+ URI("http://example.com").ssl?.should be_false
12
+ end
13
+
14
+ it "returns nil for invalid URI's without a scheme" do
15
+ URI("example").ssl?.should be_nil
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,117 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::Request do
4
+ before { @request = Savon::Request.new EndpointHelper.wsdl_endpoint }
5
+
6
+ it "contains the ContentType for each supported SOAP version" do
7
+ content_type = { 1 => "text/xml;charset=UTF-8", 2 => "application/soap+xml;charset=UTF-8" }
8
+ content_type.each { |version, type| Savon::Request::ContentType[version].should == type }
9
+ end
10
+
11
+ # defaults to log request and response. disabled for spec execution
12
+
13
+ it "has both getter and setter for whether to log (global setting)" do
14
+ Savon::Request.log = true
15
+ Savon::Request.log?.should be_true
16
+ Savon::Request.log = false
17
+ Savon::Request.log?.should be_false
18
+ end
19
+
20
+ it "defaults to use a Logger instance for logging" do
21
+ Savon::Request.logger.should be_a(Logger)
22
+ end
23
+
24
+ it "has both getter and setter for the logger to use (global setting)" do
25
+ Savon::Request.logger = {}
26
+ Savon::Request.logger.should be_a(Hash)
27
+ Savon::Request.logger = Logger.new STDOUT
28
+ end
29
+
30
+ it "defaults to :debug for logging" do
31
+ Savon::Request.log_level.should == :debug
32
+ end
33
+
34
+ it "has both getter and setter for the log level to use (global setting)" do
35
+ Savon::Request.log_level = :info
36
+ Savon::Request.log_level.should == :info
37
+ Savon::Request.log_level = :debug
38
+ end
39
+
40
+ it "is initialized with a SOAP endpoint String" do
41
+ Savon::Request.new EndpointHelper.wsdl_endpoint
42
+ end
43
+
44
+ it "has a getter for the SOAP endpoint URI" do
45
+ @request.endpoint.should == URI(EndpointHelper.wsdl_endpoint)
46
+ end
47
+
48
+ it "should have a getter for the proxy URI" do
49
+ @request.proxy.should == URI("")
50
+ end
51
+
52
+ it "should have a getter for the HTTP headers which defaults to an empty Hash" do
53
+ @request.headers.should == {}
54
+ end
55
+
56
+ it "should have a setter for the HTTP headers" do
57
+ headers = { "some" => "thing" }
58
+
59
+ @request.headers = headers
60
+ @request.headers.should == headers
61
+ end
62
+
63
+ it "should return the Net::HTTP object" do
64
+ @request.http.should be_kind_of(Net::HTTP)
65
+ end
66
+
67
+ it "should have a method for setting HTTP basic auth credentials" do
68
+ @request.basic_auth "user", "password"
69
+ end
70
+
71
+ it "retrieves the WSDL document and returns the Net::HTTP response" do
72
+ wsdl_response = @request.wsdl
73
+
74
+ wsdl_response.should be_a(Net::HTTPResponse)
75
+ wsdl_response.body.should == WSDLFixture.authentication
76
+ end
77
+
78
+
79
+ describe "when executing a SOAP request" do
80
+ before :each do
81
+ operation = WSDLFixture.authentication(:operations)[:authenticate]
82
+ action, input = operation[:action], operation[:input]
83
+ @soap = Savon::SOAP.new action, input, EndpointHelper.soap_endpoint
84
+ end
85
+
86
+ it "should return the Net::HTTP response" do
87
+ soap_response = @request.soap @soap
88
+
89
+ soap_response.should be_a(Net::HTTPResponse)
90
+ soap_response.body.should == ResponseFixture.authentication
91
+ end
92
+
93
+ it "should include Accept-Encoding gzip if it is enabled" do
94
+ @request = Savon::Request.new EndpointHelper.wsdl_endpoint, :gzip => true
95
+ a_post = Net::HTTP::Post.new(@soap.endpoint.request_uri, {})
96
+
97
+ Net::HTTP::Post.expects(:new).with(anything, has_entry("Accept-encoding" => "gzip,deflate")).returns(a_post)
98
+
99
+ @request.soap @soap
100
+ end
101
+
102
+ it "should not include Accept-Encoding gzip if it is not enabled" do
103
+ @request = Savon::Request.new EndpointHelper.wsdl_endpoint, :gzip => false
104
+ a_post = Net::HTTP::Post.new(@soap.endpoint.request_uri, {})
105
+
106
+ Net::HTTP::Post.expects(:new).with(anything, Not(has_entry("Accept-encoding" => "gzip,deflate"))).returns(a_post)
107
+
108
+ @request.soap @soap
109
+ end
110
+ end
111
+
112
+ it "should not include host when creating HTTP requests" do
113
+ request = @request.send(:request, :wsdl)
114
+ request.path.should_not include("example.com")
115
+ end
116
+
117
+ end
@@ -0,0 +1,179 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::Response do
4
+ before { @response = Savon::Response.new http_response_mock }
5
+
6
+ it "defaults to raises both Savon::SOAPFault and Savon::HTTPError" do
7
+ Savon::Response.raise_errors?.should be_true
8
+ end
9
+
10
+ it "has both getter and setter for whether to raise errors (global setting)" do
11
+ Savon::Response.raise_errors = false
12
+ Savon::Response.raise_errors?.should == false
13
+ Savon::Response.raise_errors = true
14
+ end
15
+
16
+ describe "initialize" do
17
+ it "expects a Net::HTTPResponse" do
18
+ Savon::Response.new http_response_mock
19
+ end
20
+
21
+ it "raises a Savon::SOAPFault in case of a SOAP fault" do
22
+ lambda { savon_response_with :soap_fault }.should raise_error(Savon::SOAPFault)
23
+ end
24
+
25
+ it "does not raise a Savon::SOAPFault in case the default is turned off" do
26
+ Savon::Response.raise_errors = false
27
+ savon_response_with :soap_fault
28
+ Savon::Response.raise_errors = true
29
+ end
30
+
31
+ it "raises a Savon::HTTPError in case of an HTTP error" do
32
+ lambda { savon_response_with :http_error }.should raise_error(Savon::HTTPError)
33
+ end
34
+
35
+ it "does not raise a Savon::HTTPError in case the default is turned off" do
36
+ Savon::Response.raise_errors = false
37
+ savon_response_with :http_error
38
+ Savon::Response.raise_errors = true
39
+ end
40
+ end
41
+
42
+ describe "soap_fault?" do
43
+ before { Savon::Response.raise_errors = false }
44
+
45
+ it "does not return true in case the response seems to be ok" do
46
+ @response.soap_fault?.should_not be_true
47
+ end
48
+
49
+ it "returns true in case of a SOAP fault" do
50
+ savon_response_with(:soap_fault).soap_fault?.should be_true
51
+ end
52
+
53
+ after { Savon::Response.raise_errors = true }
54
+ end
55
+
56
+ describe "soap_fault" do
57
+ before { Savon::Response.raise_errors = false }
58
+
59
+ it "returns the SOAP fault message in case of a SOAP fault" do
60
+ savon_response_with(:soap_fault).soap_fault.
61
+ should == "(soap:Server) Fault occurred while processing."
62
+ end
63
+
64
+ it "returns the SOAP fault message in case of a SOAP 1.2 fault" do
65
+ savon_response_with(:soap_fault12).soap_fault.
66
+ should == "(soap:Sender) Sender Timeout"
67
+ end
68
+
69
+ after { Savon::Response.raise_errors = true }
70
+ end
71
+
72
+ describe "http_error?" do
73
+ before { Savon::Response.raise_errors = false }
74
+
75
+ it "does not return true in case the response seems to be ok" do
76
+ @response.http_error?.should_not be_true
77
+ end
78
+
79
+ it "returns true in case of an HTTP error" do
80
+ savon_response_with(:http_error).http_error?.should be_true
81
+ end
82
+
83
+ after { Savon::Response.raise_errors = true }
84
+ end
85
+
86
+ describe "http_error" do
87
+ before { Savon::Response.raise_errors = false }
88
+
89
+ it "returns the HTTP error message in case of an HTTP error" do
90
+ savon_response_with(:http_error).http_error.should == "Not found (404)"
91
+ end
92
+
93
+ after { Savon::Response.raise_errors = true }
94
+ end
95
+
96
+ it "should return the SOAP response body as a Hash" do
97
+ @response.to_hash[:authenticate_response][:return].should ==
98
+ ResponseFixture.authentication(:to_hash)
99
+ end
100
+
101
+ it "should return a Hash for a SOAP multiRef response" do
102
+ @response = Savon::Response.new http_response_mock(200, ResponseFixture.multi_ref, "OK")
103
+
104
+ @response.to_hash[:list_response].should be_a(Hash)
105
+ @response.to_hash[:multi_ref].should be_an(Array)
106
+ end
107
+
108
+ it "should return the raw SOAP response body" do
109
+ @response.to_xml.should == ResponseFixture.authentication
110
+ @response.to_s.should == ResponseFixture.authentication
111
+ end
112
+
113
+ it "should return the Net::HTTP response object" do
114
+ @response.http.should be_a(Mocha::Mock)
115
+ @response.http.should respond_to(:code)
116
+ @response.http.should respond_to(:message)
117
+ @response.http.should respond_to(:body)
118
+ end
119
+
120
+ describe "GZipped responses" do
121
+ it "should be decoded if Content-encoding header is gzip" do
122
+ @response = Savon::Response.new http_response_mock(200, body = "Encoded", "OK", 'content-encoding' => 'gzip')
123
+
124
+ should_decode_body body
125
+
126
+ @response.to_xml
127
+ end
128
+
129
+ # header logic extracted from http://dev.ctor.org/svn/soap4r/trunk/lib/soap/streamHandler.rb
130
+ it "should be decoded if body starts with gzip header" do
131
+ @response = Savon::Response.new http_response_mock(200, body = "\x1f\x8bEncoded", "OK")
132
+
133
+ should_decode_body body
134
+
135
+ @response.to_xml
136
+ end
137
+
138
+ it "should be decoded when header is set" do
139
+ @response = Savon::Response.new http_response_mock(200, GzipResponseFixture.message, "OK", 'content-encoding' => 'gzip')
140
+ @response.to_xml.should == "A short gzip encoded message\n"
141
+ end
142
+
143
+ it "should be decoded when header is not set" do
144
+ @response = Savon::Response.new http_response_mock(200, GzipResponseFixture.message, "OK")
145
+ @response.to_xml.should == "A short gzip encoded message\n"
146
+ end
147
+ end
148
+
149
+ def should_decode_body(body)
150
+ StringIO.expects(:new).with(body).returns(stream = mock("StringIO"))
151
+
152
+ Zlib::GzipReader.expects(:new).with(stream).returns(mock("Zlib::GzipReader") do
153
+ expects(:read)
154
+ expects(:close)
155
+ end)
156
+ end
157
+
158
+ def savon_response_with(error_type)
159
+ mock = case error_type
160
+ when :soap_fault then http_response_mock 200, ResponseFixture.soap_fault
161
+ when :soap_fault12 then http_response_mock 200, ResponseFixture.soap_fault12
162
+ when :http_error then http_response_mock 404, "", "Not found"
163
+ end
164
+ Savon::Response.new mock
165
+ end
166
+
167
+ def http_response_mock(code = 200, body = nil, message = "OK", headers = {})
168
+ body ||= ResponseFixture.authentication
169
+ mock = mock "Net::HTTPResponse"
170
+ mock.stubs :code => code.to_s, :message => message, :content_type => "text/html", :body => body
171
+
172
+ mock.stubs("[]").with(anything).returns(nil)
173
+ headers.each { |key, value| mock.stubs("[]").with(key).returns(value) }
174
+
175
+ mock
176
+ end
177
+
178
+ end
179
+