savon 0.3.2 → 0.5.0

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 (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