savon 0.3.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/README.textile +68 -0
  2. data/Rakefile +9 -7
  3. data/VERSION +1 -1
  4. data/lib/savon.rb +33 -34
  5. data/lib/savon/client.rb +96 -0
  6. data/lib/savon/core_ext.rb +6 -0
  7. data/lib/savon/core_ext/datetime.rb +8 -0
  8. data/lib/savon/core_ext/hash.rb +65 -0
  9. data/lib/savon/core_ext/object.rb +14 -0
  10. data/lib/savon/core_ext/string.rb +41 -0
  11. data/lib/savon/core_ext/symbol.rb +8 -0
  12. data/lib/savon/core_ext/uri.rb +10 -0
  13. data/lib/savon/request.rb +103 -0
  14. data/lib/savon/soap.rb +71 -0
  15. data/lib/savon/validation.rb +57 -0
  16. data/lib/savon/wsdl.rb +39 -41
  17. data/lib/savon/wsse.rb +111 -0
  18. data/spec/fixtures/multiple_user_response.xml +22 -0
  19. data/spec/fixtures/soap_fault.xml +0 -0
  20. data/spec/fixtures/user_fixture.rb +42 -0
  21. data/spec/fixtures/user_response.xml +4 -2
  22. data/spec/fixtures/user_wsdl.xml +0 -0
  23. data/spec/http_stubs.rb +20 -0
  24. data/spec/savon/client_spec.rb +144 -0
  25. data/spec/savon/core_ext/datetime_spec.rb +12 -0
  26. data/spec/savon/core_ext/hash_spec.rb +146 -0
  27. data/spec/savon/core_ext/object_spec.rb +26 -0
  28. data/spec/savon/core_ext/string_spec.rb +52 -0
  29. data/spec/savon/core_ext/symbol_spec.rb +11 -0
  30. data/spec/savon/core_ext/uri_spec.rb +15 -0
  31. data/spec/savon/request_spec.rb +93 -0
  32. data/spec/savon/savon_spec.rb +37 -0
  33. data/spec/savon/soap_spec.rb +101 -0
  34. data/spec/savon/validation_spec.rb +88 -0
  35. data/spec/savon/wsdl_spec.rb +17 -46
  36. data/spec/savon/wsse_spec.rb +169 -0
  37. data/spec/spec_helper.rb +7 -92
  38. data/spec/spec_helper_methods.rb +29 -0
  39. metadata +68 -20
  40. data/README.rdoc +0 -62
  41. data/lib/savon/service.rb +0 -151
  42. data/spec/savon/service_spec.rb +0 -76
@@ -0,0 +1,11 @@
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
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,15 @@
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
+ end
14
+
15
+ end
@@ -0,0 +1,93 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::Request do
4
+ before { @request = new_request_instance }
5
+
6
+ def new_request_instance
7
+ Savon::Request.new SpecHelper.some_endpoint
8
+ end
9
+
10
+ describe "ContentType" do
11
+ it "contains the ContentType for each supported SOAP version" do
12
+ Savon::SOAPVersions.each do |soap_version|
13
+ Savon::Request::ContentType[soap_version].should be_a String
14
+ Savon::Request::ContentType[soap_version].should_not be_empty
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "@log" do
20
+ # It defaults to true, but it's turned off for spec execution.
21
+
22
+ it "has accessor methods" do
23
+ Savon::Request.log = true
24
+ Savon::Request.log?.should be_true
25
+ Savon::Request.log = false
26
+ Savon::Request.log?.should be_false
27
+ end
28
+ end
29
+
30
+ describe "@logger" do
31
+ it "defaults to Logger" do
32
+ Savon::Request.logger.should be_a Logger
33
+ end
34
+
35
+ it "has accessor methods" do
36
+ Savon::Request.logger = nil
37
+ Savon::Request.logger.should be_nil
38
+ Savon::Request.logger = Logger.new STDOUT
39
+ end
40
+ end
41
+
42
+ describe "@log_level" do
43
+ it "defaults to :debug" do
44
+ Savon::Request.log_level.should == :debug
45
+ end
46
+
47
+ it "has accessor methods" do
48
+ Savon::Request.log_level = :info
49
+ Savon::Request.log_level.should == :info
50
+ Savon::Request.log_level = :debug
51
+ end
52
+ end
53
+
54
+ describe "initialize" do
55
+ it "expects a SOAP endpoint String" do
56
+ new_request_instance
57
+ end
58
+
59
+ it "raises an ArgumentError in case of an invaluid endpoint" do
60
+ lambda { Savon::Request.new "invalid" }.should raise_error ArgumentError
61
+ end
62
+ end
63
+
64
+ describe "endpoint" do
65
+ it "returns the SOAP endpoint URI" do
66
+ @request.endpoint.should == SpecHelper.some_endpoint_uri
67
+ end
68
+ end
69
+
70
+ describe "wsdl" do
71
+ it "retrieves the WSDL document and returns the Net::HTTPResponse" do
72
+ wsdl_response = @request.wsdl
73
+
74
+ wsdl_response.should be_a Net::HTTPResponse
75
+ wsdl_response.body.should == UserFixture.user_wsdl
76
+ end
77
+ end
78
+
79
+ describe "soap" do
80
+ it "executes a SOAP request and returns the Net::HTTPResponse" do
81
+ soap_response = @request.soap new_soap_instance
82
+
83
+ soap_response.should be_a Net::HTTPResponse
84
+ soap_response.body.should == UserFixture.user_response
85
+ end
86
+ end
87
+
88
+ def new_soap_instance(options = {})
89
+ Savon::SOAP.new UserFixture.soap_actions[:find_user], { :id => 666 },
90
+ options, UserFixture.namespace_uri
91
+ end
92
+
93
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon do
4
+
5
+ describe "VERSION" do
6
+ it "contains the current version of the library" do
7
+ Savon::VERSION.should be_a String
8
+ Savon::VERSION.should_not be_empty
9
+ end
10
+ end
11
+
12
+ describe "SOAPVersions" do
13
+ it "contains an Array of supported SOAP versions" do
14
+ Savon::SOAPVersions.should be_an Array
15
+ Savon::SOAPVersions.should_not be_empty
16
+ end
17
+ end
18
+
19
+ describe "SOAPDateTimeFormat" do
20
+ it "contains the xs:dateTime format" do
21
+ Savon::SOAPDateTimeFormat.should be_a String
22
+ Savon::SOAPDateTimeFormat.should_not be_empty
23
+
24
+ UserFixture.datetime_object.strftime(Savon::SOAPDateTimeFormat).
25
+ should == UserFixture.datetime_string
26
+ end
27
+ end
28
+
29
+ describe "SOAPDateTimeRegexp" do
30
+ it "contains a Regexp matching the xs:dateTime format" do
31
+ Savon::SOAPDateTimeRegexp.should be_a Regexp
32
+ (Savon::SOAPDateTimeRegexp === UserFixture.datetime_string).
33
+ should be_true
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,101 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::SOAP do
4
+ before { @soap = new_soap_instance }
5
+
6
+ def new_soap_instance(options = {})
7
+ Savon::SOAP.new UserFixture.soap_actions[:find_user], { :id => 666 },
8
+ options, UserFixture.namespace_uri
9
+ end
10
+
11
+ describe "@version" do
12
+ it "defaults to 1" do
13
+ Savon::SOAP.version.should == 1
14
+ end
15
+
16
+ it "has accessor methods" do
17
+ [1, 2].each do |soap_version|
18
+ Savon::SOAP.version = soap_version
19
+ Savon::SOAP.version.should == soap_version
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "initialize" do
25
+ it "expects the SOAP action, body, options and the namespace URI" do
26
+ new_soap_instance
27
+ end
28
+ end
29
+
30
+ describe "action" do
31
+ it "returns the SOAP action" do
32
+ @soap.action.should == UserFixture.soap_actions[:find_user]
33
+ end
34
+ end
35
+
36
+ describe "options" do
37
+ it "returns the SOAP options" do
38
+ @soap.options.should == {}
39
+ end
40
+ end
41
+
42
+ describe "body" do
43
+ before { Savon::SOAP.version = 1 }
44
+
45
+ it "returns the XML for a SOAP request" do
46
+ @soap.body.should == soap_body
47
+ end
48
+
49
+ it "caches the XML, returning the same Object every time" do
50
+ @soap.body.object_id.should == @soap.body.object_id
51
+ end
52
+
53
+ it "uses the SOAP namespace for the SOAP version passed in via options" do
54
+ soap = new_soap_instance :soap_version => 2
55
+ soap.body.should include Savon::SOAP::SOAPNamespace[2]
56
+ end
57
+
58
+ it "uses the SOAP namespace for the default SOAP version otherwise" do
59
+ Savon::SOAP.version = 2
60
+ @soap.body.should include Savon::SOAP::SOAPNamespace[2]
61
+ end
62
+
63
+ def soap_body
64
+ "<env:Envelope xmlns:wsdl=\"http://v1_0.ws.user.example.com\" " <<
65
+ "xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">" <<
66
+ "<env:Header></env:Header>" <<
67
+ "<env:Body><wsdl:findUser><id>666</id></wsdl:findUser></env:Body>" <<
68
+ "</env:Envelope>"
69
+ end
70
+ end
71
+
72
+ describe "version" do
73
+ it "returns the SOAP version from options" do
74
+ soap = new_soap_instance :soap_version => 2
75
+ soap.version.should == 2
76
+ end
77
+
78
+ it "returns the default SOAP version otherwise" do
79
+ @soap.version.should == Savon::SOAP.version
80
+ end
81
+ end
82
+
83
+ describe "SOAPNamespace" do
84
+ it "contains the SOAP namespace for each supported SOAP version" do
85
+ Savon::SOAPVersions.each do |soap_version|
86
+ Savon::SOAP::SOAPNamespace[soap_version].should be_a String
87
+ Savon::SOAP::SOAPNamespace[soap_version].should_not be_empty
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "ContentType" do
93
+ it "contains the Content-Types for each supported SOAP version" do
94
+ Savon::SOAPVersions.each do |soap_version|
95
+ Savon::SOAP::ContentType[soap_version].should be_a String
96
+ Savon::SOAP::ContentType[soap_version].should_not be_empty
97
+ end
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,88 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::Validation do
4
+ before do
5
+ @validation = Class.new
6
+ class << @validation
7
+ include Savon::Validation
8
+ end
9
+ end
10
+
11
+ describe "validate!" do
12
+ describe ":endpoint" do
13
+ it "returns true for valid endpoints" do
14
+ @validation.validate!(:endpoint, "http://example.com").should be_true
15
+ end
16
+
17
+ it "raises an ArgumentError in case of invalid endpoints" do
18
+ lambda { @validation.validate! :endpoint, "invalid" }.
19
+ should raise_error ArgumentError
20
+ end
21
+ end
22
+
23
+ describe ":soap_version" do
24
+ it "returns true for valid SOAP versions" do
25
+ Savon::SOAPVersions.each do |soap_version|
26
+ @validation.validate!(:soap_version, soap_version).should be_true
27
+ end
28
+ end
29
+
30
+ it "raises an ArgumentError in case of invalid SOAP versions" do
31
+ [5, 9, nil, false, "upcoming"].each do |soap_version|
32
+ lambda { @validation.validate! :soap_version, soap_version }.
33
+ should raise_error ArgumentError
34
+ end
35
+ end
36
+ end
37
+
38
+ describe ":soap_body" do
39
+ it "returns true for Hashes" do
40
+ @validation.validate!(:soap_body, {}).should be_true
41
+ end
42
+
43
+ it "returns true for Objects responding to to_s" do
44
+ [123, "body", Time.now].each do |soap_body|
45
+ lambda { @validation.validate!(:soap_body, soap_body) }.should be_true
46
+ end
47
+ end
48
+
49
+ it "raises an ArgumentError in case of an invalid SOAP body" do
50
+ singleton = "pretending like there is no such thing as to_s"
51
+ def singleton.respond_to?(method)
52
+ false
53
+ end
54
+
55
+ lambda { @validation.validate! :endpoint, singleton }.
56
+ should raise_error ArgumentError
57
+ end
58
+ end
59
+
60
+ describe ":response_process" do
61
+ it "returns true for Objects responding to call" do
62
+ @validation.validate!(:response_process, Proc.new {}).should be_true
63
+ end
64
+
65
+ it "raises an ArgumentError for an invalid response process" do
66
+ [123, "block", [], {}].each do |response_process|
67
+ lambda { @validation.validate! :response_process, response_process }.
68
+ should raise_error ArgumentError
69
+ end
70
+ end
71
+ end
72
+
73
+ describe ":wsse_credentials" do
74
+ it "returns true for valid WSSE credentials" do
75
+ wsse_credentials = { :username => "user", :password => "secret" }
76
+ @validation.validate!(:wsse_credentials, wsse_credentials).should be_true
77
+ end
78
+
79
+ it "returns false for invalid WSSE credentials" do
80
+ [{ :username => "user" }, { :password => "secret" }].each do |wsse_credentials|
81
+ lambda { @validation.validate! :wsse_credentials, wsse_credentials }.
82
+ should raise_error ArgumentError
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+ end
@@ -1,65 +1,36 @@
1
- require File.join(File.dirname(__FILE__), "..", "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  describe Savon::WSDL do
4
- include SpecHelper
4
+ before { @wsdl = Savon::WSDL.new Savon::Request.new SpecHelper.some_endpoint }
5
5
 
6
- #namespace_uri
7
- describe "namespace_uri" do
8
- before { @wsdl = new_wsdl }
9
-
10
- it "returns the namespace URI from the WSDL" do
11
- @wsdl.namespace_uri == UserFixture.namespace_uri
12
- end
13
-
14
- it "returns the same object every time" do
15
- @wsdl.namespace_uri.should equal(@wsdl.namespace_uri)
6
+ describe "initialize" do
7
+ it "expects a Savon::Request object" do
8
+ Savon::WSDL.new Savon::Request.new SpecHelper.some_endpoint
16
9
  end
17
10
  end
18
11
 
19
- # soap_actions
20
- describe "soap_actions" do
21
- before { @wsdl = new_wsdl }
22
-
23
- it "returns the SOAP actions from the WSDL" do
24
- @wsdl.soap_actions == UserFixture.soap_actions
25
- end
26
-
27
- it "returns the same object every time" do
28
- @wsdl.soap_actions.should equal(@wsdl.soap_actions)
12
+ describe "namespace_uri" do
13
+ it "returns the namespace URI from the WSDL" do
14
+ @wsdl.namespace_uri.should == UserFixture.namespace_uri
29
15
  end
30
16
  end
31
17
 
32
- # choice_elements
33
- describe "choice_elements" do
34
- before { @wsdl = new_wsdl }
35
-
36
- it "returns the choice elements from the WSDL" do
37
- @wsdl.choice_elements == UserFixture.choice_elements
38
- end
39
-
40
- it "returns the same object every time" do
41
- @wsdl.choice_elements.should equal(@wsdl.choice_elements)
18
+ describe "soap_actions" do
19
+ it "returns an Array containing all available SOAP actions" do
20
+ @wsdl.soap_actions.should == UserFixture.soap_actions.keys
42
21
  end
43
22
  end
44
23
 
45
- # initialize
46
- describe "initialize" do
47
- it "expects an endpoint URI and a Net::HTTP instance" do
48
- @wsdl = Savon::WSDL.new(some_uri, some_http)
24
+ describe "mapped_soap_actions" do
25
+ it "returns a Hash containing all available SOAP actions and their original names" do
26
+ @wsdl.mapped_soap_actions.should == UserFixture.soap_actions
49
27
  end
50
28
  end
51
29
 
52
- # to_s
53
30
  describe "to_s" do
54
- before { @wsdl = new_wsdl }
55
-
56
- it "returns nil before the WSDL document was retrieved" do
57
- @wsdl.to_s.should be_nil
58
- end
59
-
60
- it "returns the response body when available" do
61
- @wsdl.soap_actions # trigger http request
31
+ it "returns the WSDL document" do
62
32
  @wsdl.to_s.should == UserFixture.user_wsdl
63
33
  end
64
34
  end
65
- end
35
+
36
+ end
@@ -0,0 +1,169 @@
1
+ require "spec_helper"
2
+
3
+ describe Savon::WSSE do
4
+ before do
5
+ @wsse = new_wsse_instance
6
+ @wsse_username = "gorilla"
7
+ @wsse_password = "secret"
8
+ end
9
+
10
+ def new_wsse_instance(credentials = {})
11
+ wsse = Class.new
12
+ class << wsse
13
+ include Savon::WSSE
14
+ attr_accessor :options
15
+ end
16
+ wsse.options = { :wsse => {} }
17
+ wsse
18
+ end
19
+
20
+ def wsse_options(digest = false)
21
+ { :wsse => { :username => @wsse_username,
22
+ :password => @wsse_password, :digest => digest } }
23
+ end
24
+
25
+ describe "WSENamespace" do
26
+ it "contains namespace for WS Security Secext" do
27
+ Savon::WSSE::WSENamespace.should be_a String
28
+ Savon::WSSE::WSENamespace.should_not be_empty
29
+ end
30
+ end
31
+
32
+ describe "WSUNamespace" do
33
+ it "contains namespace for WS Security Utility" do
34
+ Savon::WSSE::WSUNamespace.should be_a String
35
+ Savon::WSSE::WSUNamespace.should_not be_empty
36
+ end
37
+ end
38
+
39
+ describe "@username" do
40
+ it "defaults to nil" do
41
+ Savon::WSSE.username.should be_nil
42
+ end
43
+
44
+ it "has accessor methods" do
45
+ Savon::WSSE.username = "gorilla"
46
+ Savon::WSSE.username.should == "gorilla"
47
+ Savon::WSSE.username = nil
48
+ end
49
+ end
50
+
51
+ describe "@password" do
52
+ it "defaults to nil" do
53
+ Savon::WSSE.password.should be_nil
54
+ end
55
+
56
+ it "has accessor methods" do
57
+ Savon::WSSE.password = "secret"
58
+ Savon::WSSE.password.should == "secret"
59
+ Savon::WSSE.password = nil
60
+ end
61
+ end
62
+
63
+ describe "@digest" do
64
+ it "defaults to false" do
65
+ Savon::WSSE.digest?.should be_false
66
+ end
67
+
68
+ it "has accessor methods" do
69
+ Savon::WSSE.digest = true
70
+ Savon::WSSE.digest?.should == true
71
+ Savon::WSSE.digest = false
72
+ end
73
+ end
74
+
75
+ describe "wsse?" do
76
+ describe "returns true in case WSSE credentials are available" do
77
+ it "via options" do
78
+ @wsse.options = wsse_options
79
+ @wsse.wsse?.should be_true
80
+ end
81
+
82
+ it "via defaults" do
83
+ Savon::WSSE.username = "gorilla"
84
+ Savon::WSSE.password = "secret"
85
+
86
+ @wsse.wsse?.should be_true
87
+ end
88
+ end
89
+
90
+ describe "returns false in case WSSE credentials are missing or incomplete" do
91
+ it "via options" do
92
+ @wsse.wsse?.should be_false
93
+
94
+ new_wsse_instance(:wsse => { :username => @wsse_username }).wsse?.
95
+ should be_false
96
+
97
+ new_wsse_instance(:wsse => { :password => @wsse_password }).wsse?.
98
+ should be_false
99
+ end
100
+
101
+ it "via defaults" do
102
+ Savon::WSSE.username = @wsse_username
103
+ @wsse.wsse?.should be_false
104
+
105
+ Savon::WSSE.username = nil
106
+ Savon::WSSE.password = @wsse_password
107
+ @wsse.wsse?.should be_false
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "wsse_header" do
113
+ describe "returns the XML for a WSSE authentication header" do
114
+ it "with WSSE credentials specified via options" do
115
+ @wsse.options = wsse_options
116
+ wsse_header = @wsse.wsse_header Builder::XmlMarkup.new
117
+
118
+ wsse_header.should include_security_namespaces
119
+ wsse_header.should include @wsse_username
120
+ wsse_header.should include @wsse_password
121
+ end
122
+
123
+ it "with WSSE credentials specified via defaults" do
124
+ Savon::WSSE.username = @wsse_username
125
+ Savon::WSSE.password = @wsse_password
126
+ wsse_header = @wsse.wsse_header Builder::XmlMarkup.new
127
+
128
+ wsse_header.should include_security_namespaces
129
+ wsse_header.should include @wsse_username
130
+ wsse_header.should include @wsse_password
131
+ end
132
+ end
133
+
134
+ describe "returns the XML for a WSSE digest header if specified" do
135
+ before {}
136
+ it "via options" do
137
+ @wsse.options = wsse_options :for_digest
138
+ wsse_header = @wsse.wsse_header Builder::XmlMarkup.new
139
+
140
+ wsse_header.should include_security_namespaces
141
+ wsse_header.should include @wsse_username
142
+ wsse_header.should_not include @wsse_password
143
+ end
144
+
145
+ it "via defaults" do
146
+ Savon::WSSE.digest = true
147
+ @wsse.options = wsse_options
148
+ wsse_header = @wsse.wsse_header Builder::XmlMarkup.new
149
+
150
+ wsse_header.should include_security_namespaces
151
+ wsse_header.should include @wsse_username
152
+ wsse_header.should_not include @wsse_password
153
+ end
154
+ end
155
+
156
+ def include_security_namespaces
157
+ simple_matcher("include security namespaces") do |given|
158
+ given.should include Savon::WSSE::WSENamespace
159
+ given.should include Savon::WSSE::WSUNamespace
160
+ end
161
+ end
162
+ end
163
+
164
+ after do
165
+ Savon::WSSE.username = nil
166
+ Savon::WSSE.password = nil
167
+ Savon::WSSE.digest = false
168
+ end
169
+ end