savon 0.7.9 → 0.8.0.beta.1
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.
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +332 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +37 -0
- data/Rakefile +28 -39
- data/autotest/discover.rb +1 -0
- data/lib/savon.rb +10 -31
- data/lib/savon/client.rb +116 -98
- data/lib/savon/core_ext/array.rb +36 -22
- data/lib/savon/core_ext/datetime.rb +15 -6
- data/lib/savon/core_ext/hash.rb +122 -94
- data/lib/savon/core_ext/object.rb +19 -11
- data/lib/savon/core_ext/string.rb +62 -57
- data/lib/savon/core_ext/symbol.rb +13 -5
- data/lib/savon/error.rb +6 -0
- data/lib/savon/global.rb +75 -0
- data/lib/savon/http/error.rb +42 -0
- data/lib/savon/soap.rb +8 -283
- data/lib/savon/soap/fault.rb +48 -0
- data/lib/savon/soap/request.rb +61 -0
- data/lib/savon/soap/response.rb +65 -0
- data/lib/savon/soap/xml.rb +132 -0
- data/lib/savon/version.rb +2 -2
- data/lib/savon/wsdl/document.rb +107 -0
- data/lib/savon/wsdl/parser.rb +90 -0
- data/lib/savon/wsdl/request.rb +35 -0
- data/lib/savon/wsse.rb +42 -104
- data/savon.gemspec +26 -0
- data/spec/fixtures/response/response_fixture.rb +26 -26
- data/spec/fixtures/response/xml/list.xml +18 -0
- data/spec/fixtures/wsdl/wsdl_fixture.rb +6 -0
- data/spec/fixtures/wsdl/wsdl_fixture.yml +4 -4
- data/spec/savon/client_spec.rb +274 -51
- data/spec/savon/core_ext/datetime_spec.rb +1 -1
- data/spec/savon/core_ext/hash_spec.rb +40 -4
- data/spec/savon/core_ext/object_spec.rb +1 -1
- data/spec/savon/core_ext/string_spec.rb +0 -12
- data/spec/savon/http/error_spec.rb +52 -0
- data/spec/savon/savon_spec.rb +90 -0
- data/spec/savon/soap/fault_spec.rb +80 -0
- data/spec/savon/soap/request_spec.rb +45 -0
- data/spec/savon/soap/response_spec.rb +153 -0
- data/spec/savon/soap/xml_spec.rb +249 -0
- data/spec/savon/soap_spec.rb +4 -177
- data/spec/savon/{wsdl_spec.rb → wsdl/document_spec.rb} +54 -17
- data/spec/savon/wsdl/request_spec.rb +15 -0
- data/spec/savon/wsse_spec.rb +123 -92
- data/spec/spec_helper.rb +19 -4
- data/spec/support/endpoint.rb +25 -0
- metadata +97 -97
- data/.autotest +0 -5
- data/CHANGELOG +0 -176
- data/README.rdoc +0 -64
- data/lib/savon/core_ext.rb +0 -8
- data/lib/savon/core_ext/net_http.rb +0 -19
- data/lib/savon/core_ext/uri.rb +0 -10
- data/lib/savon/logger.rb +0 -56
- data/lib/savon/request.rb +0 -138
- data/lib/savon/response.rb +0 -174
- data/lib/savon/wsdl.rb +0 -137
- data/lib/savon/wsdl_stream.rb +0 -85
- data/spec/basic_spec_helper.rb +0 -11
- data/spec/endpoint_helper.rb +0 -23
- data/spec/http_stubs.rb +0 -26
- data/spec/integration/http_basic_auth_spec.rb +0 -16
- data/spec/integration/server.rb +0 -51
- data/spec/savon/core_ext/net_http_spec.rb +0 -38
- data/spec/savon/core_ext/uri_spec.rb +0 -19
- data/spec/savon/request_spec.rb +0 -117
- data/spec/savon/response_spec.rb +0 -179
- data/spec/spec.opts +0 -4
@@ -0,0 +1,35 @@
|
|
1
|
+
require "httpi"
|
2
|
+
|
3
|
+
module Savon
|
4
|
+
module WSDL
|
5
|
+
|
6
|
+
# = Savon::WSDL::Request
|
7
|
+
#
|
8
|
+
# Executes WSDL requests.
|
9
|
+
class Request
|
10
|
+
|
11
|
+
# Expects an <tt>HTTPI::Request</tt>.
|
12
|
+
def initialize(request)
|
13
|
+
self.request = request
|
14
|
+
end
|
15
|
+
|
16
|
+
# Accessor for the <tt>HTTPI::Request</tt>.
|
17
|
+
attr_accessor :request
|
18
|
+
|
19
|
+
# Executes the request and returns the response.
|
20
|
+
def response
|
21
|
+
@response ||= with_logging { HTTPI.get request }
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Logs the HTTP request and yields to a given +block+.
|
27
|
+
def with_logging
|
28
|
+
Savon.log "Retrieving WSDL from: #{request.url}"
|
29
|
+
Savon.log "Using :#{request.auth.type} authentication" if request.auth?
|
30
|
+
yield
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/savon/wsse.rb
CHANGED
@@ -1,131 +1,53 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "digest/sha1"
|
3
|
+
require "builder"
|
4
|
+
|
5
|
+
require "savon/core_ext/string"
|
6
|
+
require "savon/soap"
|
7
|
+
|
1
8
|
module Savon
|
2
9
|
|
3
10
|
# = Savon::WSSE
|
4
11
|
#
|
5
|
-
#
|
6
|
-
# is passed to it as the second argument. The object allows setting the WSSE username, password
|
7
|
-
# and whether to use digest authentication.
|
8
|
-
#
|
9
|
-
# == Credentials
|
10
|
-
#
|
11
|
-
# By default, Savon does not use WSSE authentication. Simply specify a username and password to
|
12
|
-
# change this.
|
13
|
-
#
|
14
|
-
# response = client.get_all_users do |soap, wsse|
|
15
|
-
# wsse.username = "eve"
|
16
|
-
# wsse.password = "secret"
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# == Digest
|
20
|
-
#
|
21
|
-
# To use WSSE digest authentication, just use the digest method and set it to +true+.
|
22
|
-
#
|
23
|
-
# response = client.get_all_users do |soap, wsse|
|
24
|
-
# wsse.username = "eve"
|
25
|
-
# wsse.password = "secret"
|
26
|
-
# wsse.digest = true
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# == Default to WSSE
|
30
|
-
#
|
31
|
-
# In case all you're services require WSSE authentication, you can set your credentials and whether
|
32
|
-
# to use WSSE digest for every request:
|
33
|
-
#
|
34
|
-
# Savon::WSSE.username = "eve"
|
35
|
-
# Savon::WSSE.password = "secret"
|
36
|
-
# Savon::WSSE.digest = true
|
12
|
+
# Provides WSSE authentication.
|
37
13
|
class WSSE
|
38
14
|
|
39
|
-
# Base address for WSSE docs.
|
40
|
-
BaseAddress = "http://docs.oasis-open.org/wss/2004/01"
|
41
|
-
|
42
15
|
# Namespace for WS Security Secext.
|
43
|
-
WSENamespace = "
|
16
|
+
WSENamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
|
44
17
|
|
45
18
|
# Namespace for WS Security Utility.
|
46
|
-
WSUNamespace = "
|
19
|
+
WSUNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
|
47
20
|
|
48
21
|
# URI for "wsse:Password/@Type" #PasswordText.
|
49
|
-
PasswordTextURI = "
|
22
|
+
PasswordTextURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
|
50
23
|
|
51
24
|
# URI for "wsse:Password/@Type" #PasswordDigest.
|
52
|
-
PasswordDigestURI = "
|
53
|
-
|
54
|
-
# Global WSSE username.
|
55
|
-
@@username = nil
|
56
|
-
|
57
|
-
# Returns the global WSSE username.
|
58
|
-
def self.username
|
59
|
-
@@username
|
60
|
-
end
|
61
|
-
|
62
|
-
# Sets the global WSSE username.
|
63
|
-
def self.username=(username)
|
64
|
-
@@username = username.nil? ? nil : username.to_s
|
65
|
-
end
|
66
|
-
|
67
|
-
# Global WSSE password.
|
68
|
-
@@password = nil
|
69
|
-
|
70
|
-
# Returns the global WSSE password.
|
71
|
-
def self.password
|
72
|
-
@@password
|
73
|
-
end
|
25
|
+
PasswordDigestURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"
|
74
26
|
|
75
|
-
# Sets the
|
76
|
-
def
|
77
|
-
|
27
|
+
# Sets the authentication credentials. Also accepts whether to use WSSE digest.
|
28
|
+
def credentials(username, password, digest = false)
|
29
|
+
self.username = username
|
30
|
+
self.password = password
|
31
|
+
self.digest = digest
|
78
32
|
end
|
79
33
|
|
80
|
-
|
81
|
-
@@digest = false
|
34
|
+
attr_accessor :username, :password
|
82
35
|
|
83
|
-
# Returns
|
84
|
-
def
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
# Global setting of whether to use WSSE digest.
|
89
|
-
def self.digest=(digest)
|
90
|
-
@@digest = digest
|
91
|
-
end
|
92
|
-
|
93
|
-
# Sets the WSSE username per request.
|
94
|
-
def username=(username)
|
95
|
-
@username = username.nil? ? nil : username.to_s
|
96
|
-
end
|
97
|
-
|
98
|
-
# Returns the WSSE username. Defaults to the global setting.
|
99
|
-
def username
|
100
|
-
@username || self.class.username
|
101
|
-
end
|
102
|
-
|
103
|
-
# Sets the WSSE password per request.
|
104
|
-
def password=(password)
|
105
|
-
@password = password.nil? ? nil : password.to_s
|
106
|
-
end
|
107
|
-
|
108
|
-
# Returns the WSSE password. Defaults to the global setting.
|
109
|
-
def password
|
110
|
-
@password || self.class.password
|
36
|
+
# Returns whether to use WSSE digest. Defaults to +false+.
|
37
|
+
def digest?
|
38
|
+
!!@digest
|
111
39
|
end
|
112
40
|
|
113
|
-
# Sets whether to use WSSE digest per request.
|
114
41
|
attr_writer :digest
|
115
42
|
|
116
|
-
# Returns
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
# Returns the XML for a WSSE header or an empty String unless both username and password
|
122
|
-
# were specified.
|
123
|
-
def header
|
43
|
+
# Returns the XML for a WSSE header or an empty String unless authentication
|
44
|
+
# credentials were specified.
|
45
|
+
def to_xml
|
124
46
|
return "" unless username && password
|
125
47
|
|
126
48
|
builder = Builder::XmlMarkup.new
|
127
49
|
builder.wsse :Security, "xmlns:wsse" => WSENamespace do |xml|
|
128
|
-
xml.wsse :UsernameToken, "xmlns:wsu" => WSUNamespace do
|
50
|
+
xml.wsse :UsernameToken, "wsu:Id" => wsu_id, "xmlns:wsu" => WSUNamespace do
|
129
51
|
xml.wsse :Username, username
|
130
52
|
xml.wsse :Nonce, nonce
|
131
53
|
xml.wsu :Created, timestamp
|
@@ -151,7 +73,12 @@ module Savon
|
|
151
73
|
|
152
74
|
# Returns a WSSE nonce.
|
153
75
|
def nonce
|
154
|
-
@nonce ||= Digest::SHA1.hexdigest
|
76
|
+
@nonce ||= Digest::SHA1.hexdigest random_string + timestamp
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns a random String of 100 characters.
|
80
|
+
def random_string
|
81
|
+
(0...100).map { ("a".."z").to_a[rand(26)] }.join
|
155
82
|
end
|
156
83
|
|
157
84
|
# Returns a WSSE timestamp.
|
@@ -159,5 +86,16 @@ module Savon
|
|
159
86
|
@timestamp ||= Time.now.strftime Savon::SOAP::DateTimeFormat
|
160
87
|
end
|
161
88
|
|
89
|
+
# Returns the "wsu:Id" attribute.
|
90
|
+
def wsu_id
|
91
|
+
"UsernameToken-#{count}"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Simple counter.
|
95
|
+
def count
|
96
|
+
@count ||= 0
|
97
|
+
@count += 1
|
98
|
+
end
|
99
|
+
|
162
100
|
end
|
163
101
|
end
|
data/savon.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$:.unshift lib unless $:.include? lib
|
3
|
+
|
4
|
+
require "savon/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "savon"
|
8
|
+
s.version = Savon::Version
|
9
|
+
s.authors = "Daniel Harrington"
|
10
|
+
s.email = "me@rubiii.com"
|
11
|
+
s.homepage = "http://github.com/rubiii/#{s.name}"
|
12
|
+
s.summary = "Heavy metal Ruby SOAP client"
|
13
|
+
s.description = "Savon is the heavy metal Ruby SOAP client."
|
14
|
+
|
15
|
+
s.rubyforge_project = s.name
|
16
|
+
|
17
|
+
s.add_dependency "builder", "~> 2.1.2"
|
18
|
+
s.add_dependency "crack", "~> 0.1.8"
|
19
|
+
s.add_dependency "httpi", ">= 0.6.0"
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec", "~> 2.0.0"
|
22
|
+
s.add_development_dependency "mocha", "~> 0.9.7"
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.require_path = "lib"
|
26
|
+
end
|
@@ -1,36 +1,36 @@
|
|
1
1
|
class ResponseFixture
|
2
|
+
class << self
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
:client => "radclient"
|
11
|
-
}
|
12
|
-
}
|
13
|
-
else
|
14
|
-
@@authentication ||= load_fixture :authentication
|
4
|
+
def authentication(value = nil)
|
5
|
+
@authentication ||= load_fixture :authentication
|
6
|
+
|
7
|
+
case value
|
8
|
+
when :to_hash then Savon::SOAP::XML.to_hash(@authentication)[:authenticate_response][:return]
|
9
|
+
else @authentication
|
10
|
+
end
|
15
11
|
end
|
16
|
-
end
|
17
12
|
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
def soap_fault
|
14
|
+
@soap_fault ||= load_fixture :soap_fault
|
15
|
+
end
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
def soap_fault12
|
18
|
+
@soap_fault12 ||= load_fixture :soap_fault12
|
19
|
+
end
|
25
20
|
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
def multi_ref
|
22
|
+
@multi_ref ||= load_fixture :multi_ref
|
23
|
+
end
|
29
24
|
|
30
|
-
|
25
|
+
def list
|
26
|
+
@list ||= load_fixture :list
|
27
|
+
end
|
31
28
|
|
32
|
-
|
33
|
-
File.read File.dirname(__FILE__) + "/xml/#{fixture}.xml"
|
34
|
-
end
|
29
|
+
private
|
35
30
|
|
31
|
+
def load_fixture(fixture)
|
32
|
+
File.read File.dirname(__FILE__) + "/xml/#{fixture}.xml"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
36
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
2
|
+
<soapenv:Body>
|
3
|
+
<MultiNamespacedEntryResponse xmlns="http://www.example.com/BusinessRulesEngine/xsd">
|
4
|
+
<history>
|
5
|
+
<ns10:case xmlns:ns10="http://www.example.com/Common/xsd">
|
6
|
+
<ns10:logTime>2010-09-21T18:22:01.558+10:00</ns10:logTime>
|
7
|
+
<ns10:logType>Notes Log</ns10:logType>
|
8
|
+
<ns10:logText>test</ns10:logText>
|
9
|
+
</ns10:case>
|
10
|
+
<ns11:case xmlns:ns11="http://www.example.com/Common/xsd">
|
11
|
+
<ns11:logTime>2010-09-21T18:22:07.038+10:00</ns11:logTime>
|
12
|
+
<ns11:logType>Notes Log</ns11:logType>
|
13
|
+
<ns11:logText>another test</ns11:logText>
|
14
|
+
</ns11:case>
|
15
|
+
</history>
|
16
|
+
</MultiNamespacedEntryResponse>
|
17
|
+
</soapenv:Body>
|
18
|
+
</soapenv:Envelope>
|
@@ -3,6 +3,12 @@ require "erb"
|
|
3
3
|
|
4
4
|
class WSDLFixture
|
5
5
|
|
6
|
+
# Returns a given +fixture+. Defaults to :authentication.
|
7
|
+
def self.load(fixture = nil)
|
8
|
+
fixture ||= :authentication
|
9
|
+
method_missing fixture
|
10
|
+
end
|
11
|
+
|
6
12
|
# Returns a WSDL document matching a given +method+ name when called without
|
7
13
|
# arguments. Otherwise returns the expected value for a given +method+ name
|
8
14
|
# matching a fixture.
|
@@ -1,12 +1,12 @@
|
|
1
1
|
:authentication:
|
2
|
-
:
|
2
|
+
:namespace: "http://v1_0.ws.auth.order.example.com/"
|
3
3
|
:operations:
|
4
4
|
:authenticate:
|
5
5
|
:action: "authenticate"
|
6
6
|
:input: "authenticate"
|
7
7
|
|
8
8
|
:no_namespace:
|
9
|
-
:
|
9
|
+
:namespace: "urn:ActionWebService"
|
10
10
|
:operations:
|
11
11
|
:get_all_contacts:
|
12
12
|
:action: "/api/api/GetAllContacts"
|
@@ -19,7 +19,7 @@
|
|
19
19
|
:input: "GetUserLoginById"
|
20
20
|
|
21
21
|
:namespaced_actions:
|
22
|
-
:
|
22
|
+
:namespace: "http://api.example.com/api/"
|
23
23
|
:operations:
|
24
24
|
:get_api_key:
|
25
25
|
:input: "GetApiKey"
|
@@ -32,7 +32,7 @@
|
|
32
32
|
:action: "http://api.example.com/api/User.GetClients"
|
33
33
|
|
34
34
|
:geotrust:
|
35
|
-
:
|
35
|
+
:namespace: "http://api.geotrust.com/webtrust/query"
|
36
36
|
:operations:
|
37
37
|
:get_quick_approver_list:
|
38
38
|
:action: "GetQuickApproverList"
|
data/spec/savon/client_spec.rb
CHANGED
@@ -1,86 +1,309 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Savon::Client do
|
4
|
-
|
4
|
+
let(:client) { Savon::Client.new { wsdl.document = Endpoint.wsdl } }
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
describe ".new" do
|
7
|
+
context "with a block expecting one argument" do
|
8
|
+
it "should yield the WSDL object" do
|
9
|
+
Savon::Client.new { |wsdl| wsdl.should be_a(Savon::WSDL::Document) }
|
10
|
+
end
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
context "with a block expecting two arguments" do
|
14
|
+
it "should yield the WSDL and HTTP objects" do
|
15
|
+
Savon::Client.new do |wsdl, http|
|
16
|
+
wsdl.should be_an(Savon::WSDL::Document)
|
17
|
+
http.should be_an(HTTPI::Request)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with a block expecting three arguments" do
|
23
|
+
it "should yield the WSDL, HTTP and WSSE objects" do
|
24
|
+
Savon::Client.new do |wsdl, http, wsse|
|
25
|
+
wsdl.should be_an(Savon::WSDL::Document)
|
26
|
+
http.should be_an(HTTPI::Request)
|
27
|
+
wsse.should be_an(Savon::WSSE)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with a block expecting no arguments" do
|
33
|
+
it "should let you access the WSDL object" do
|
34
|
+
Savon::Client.new { wsdl.should be_a(Savon::WSDL::Document) }
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should let you access the HTTP object" do
|
38
|
+
Savon::Client.new { http.should be_an(HTTPI::Request) }
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should let you access the WSSE object" do
|
42
|
+
Savon::Client.new { wsse.should be_a(Savon::WSSE) }
|
43
|
+
end
|
44
|
+
end
|
15
45
|
end
|
16
46
|
|
17
|
-
|
18
|
-
|
19
|
-
|
47
|
+
describe "#wsdl" do
|
48
|
+
it "should return the Savon::WSDL::Document" do
|
49
|
+
client.wsdl.should be_a(Savon::WSDL::Document)
|
50
|
+
end
|
20
51
|
end
|
21
52
|
|
22
|
-
|
23
|
-
|
53
|
+
describe "#http" do
|
54
|
+
it "should return the HTTPI::Request" do
|
55
|
+
client.http.should be_an(HTTPI::Request)
|
56
|
+
end
|
24
57
|
end
|
25
58
|
|
26
|
-
|
27
|
-
|
59
|
+
describe "#wsse" do
|
60
|
+
it "should return the Savon::WSSE object" do
|
61
|
+
client.wsse.should be_a(Savon::WSSE)
|
62
|
+
end
|
28
63
|
end
|
29
64
|
|
30
|
-
|
31
|
-
|
32
|
-
|
65
|
+
describe "#request" do
|
66
|
+
before do
|
67
|
+
HTTPI.stubs(:get).returns(new_response(:body => WSDLFixture.load))
|
68
|
+
HTTPI.stubs(:post).returns(new_response)
|
33
69
|
end
|
34
70
|
|
35
|
-
|
36
|
-
|
37
|
-
|
71
|
+
context "without any arguments" do
|
72
|
+
it "should raise an ArgumentError" do
|
73
|
+
lambda { client.request }.should raise_error(ArgumentError)
|
74
|
+
end
|
75
|
+
end
|
38
76
|
|
39
|
-
|
40
|
-
|
41
|
-
|
77
|
+
context "with a single argument (Symbol)" do
|
78
|
+
it "should set the input tag to result in <getUser>" do
|
79
|
+
client.request(:get_user) { soap.input.should == [:getUser, {}] }
|
80
|
+
end
|
42
81
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
82
|
+
it "should set the target namespace with the default identifier" do
|
83
|
+
namespace = 'xmlns:wsdl="http://v1_0.ws.auth.order.example.com/"'
|
84
|
+
HTTPI::Request.any_instance.expects(:body=).with { |value| value.include? namespace }
|
85
|
+
|
86
|
+
client.request :get_user
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should not set the target namespace if soap.namespace was set to nil" do
|
90
|
+
namespace = "http://v1_0.ws.auth.order.example.com/"
|
91
|
+
HTTPI::Request.any_instance.expects(:body=).with { |value| !value.include?(namespace) }
|
92
|
+
|
93
|
+
client.request(:get_user) { soap.namespace = nil }
|
94
|
+
end
|
47
95
|
end
|
48
96
|
|
49
|
-
|
50
|
-
|
51
|
-
|
97
|
+
context "with a single argument (String)" do
|
98
|
+
it "should set the input tag to result in <get_user>" do
|
99
|
+
client.request("get_user") { soap.input.should == [:get_user, {}] }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "with a Symbol and a Hash" do
|
104
|
+
it "should set the input tag to result in <getUser active='true'>" do
|
105
|
+
client.request(:get_user, :active => true) { soap.input.should == [:getUser, { :active => true }] }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "with two Symbols" do
|
110
|
+
it "should set the input tag to result in <wsdl:getUser>" do
|
111
|
+
client.request(:v1, :get_user) { soap.input.should == [:v1, :getUser, {}] }
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should set the target namespace with the given identifier" do
|
115
|
+
namespace = 'xmlns:v1="http://v1_0.ws.auth.order.example.com/"'
|
116
|
+
HTTPI::Request.any_instance.expects(:body=).with { |value| value.include? namespace }
|
117
|
+
|
118
|
+
client.request :v1, :get_user
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not set the target namespace if soap.namespace was set to nil" do
|
122
|
+
namespace = "http://v1_0.ws.auth.order.example.com/"
|
123
|
+
HTTPI::Request.any_instance.expects(:body=).with { |value| !value.include?(namespace) }
|
124
|
+
|
125
|
+
client.request(:v1, :get_user) { soap.namespace = nil }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "with two Symbols and a Hash" do
|
130
|
+
it "should set the input tag to result in <wsdl:getUser active='true'>" do
|
131
|
+
client.request(:wsdl, :get_user, :active => true) { soap.input.should == [:wsdl, :getUser, { :active => true }] }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "with a block expecting one argument" do
|
136
|
+
it "should yield the SOAP object" do
|
137
|
+
client.request(:authenticate) { |soap| soap.should be_a(Savon::SOAP::XML) }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "with a block expecting two arguments" do
|
142
|
+
it "should yield the SOAP and WSDL objects" do
|
143
|
+
client.request(:authenticate) do |soap, wsdl|
|
144
|
+
soap.should be_a(Savon::SOAP::XML)
|
145
|
+
wsdl.should be_an(Savon::WSDL::Document)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "with a block expecting three arguments" do
|
151
|
+
it "should yield the SOAP, WSDL and HTTP objects" do
|
152
|
+
client.request(:authenticate) do |soap, wsdl, http|
|
153
|
+
soap.should be_a(Savon::SOAP::XML)
|
154
|
+
wsdl.should be_an(Savon::WSDL::Document)
|
155
|
+
http.should be_an(HTTPI::Request)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "with a block expecting four arguments" do
|
161
|
+
it "should yield the SOAP, WSDL, HTTP and WSSE objects" do
|
162
|
+
client.request(:authenticate) do |soap, wsdl, http, wsse|
|
163
|
+
soap.should be_a(Savon::SOAP::XML)
|
164
|
+
wsdl.should be_a(Savon::WSDL::Document)
|
165
|
+
http.should be_an(HTTPI::Request)
|
166
|
+
wsse.should be_a(Savon::WSSE)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "with a block expecting no arguments" do
|
172
|
+
it "should let you access the SOAP object" do
|
173
|
+
client.request(:authenticate) { soap.should be_a(Savon::SOAP::XML) }
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should let you access the HTTP object" do
|
177
|
+
client.request(:authenticate) { http.should be_an(HTTPI::Request) }
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should let you access the WSSE object" do
|
181
|
+
client.request(:authenticate) { wsse.should be_a(Savon::WSSE) }
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should let you access the WSDL object" do
|
185
|
+
client.request(:authenticate) { wsdl.should be_a(Savon::WSDL::Document) }
|
186
|
+
end
|
52
187
|
end
|
53
|
-
response.should be_a(Savon::Response)
|
54
|
-
@client.wsdl.enabled?.should be_false
|
55
188
|
end
|
56
189
|
|
57
|
-
|
58
|
-
client
|
59
|
-
|
190
|
+
context "with a remote WSDL document" do
|
191
|
+
let(:client) { Savon::Client.new { wsdl.document = Endpoint.wsdl } }
|
192
|
+
before { HTTPI.expects(:get).returns(new_response(:body => WSDLFixture.load)) }
|
193
|
+
|
194
|
+
it "should return a list of available SOAP actions" do
|
195
|
+
client.wsdl.soap_actions.should == [:authenticate]
|
196
|
+
end
|
197
|
+
|
198
|
+
it "adds a SOAPAction header containing the SOAP action name" do
|
199
|
+
HTTPI.stubs(:post).returns(new_response)
|
200
|
+
|
201
|
+
client.request :authenticate do
|
202
|
+
http.headers["SOAPAction"].should == %{"authenticate"}
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should execute SOAP requests and return the response" do
|
207
|
+
HTTPI.expects(:post).returns(new_response)
|
208
|
+
response = client.request(:authenticate)
|
209
|
+
|
210
|
+
response.should be_a(Savon::SOAP::Response)
|
211
|
+
response.to_xml.should == ResponseFixture.authentication
|
212
|
+
end
|
60
213
|
end
|
61
214
|
|
62
|
-
|
63
|
-
client
|
64
|
-
|
215
|
+
context "with a local WSDL document" do
|
216
|
+
let(:client) { Savon::Client.new { wsdl.document = "spec/fixtures/wsdl/xml/authentication.xml" } }
|
217
|
+
|
218
|
+
before { HTTPI.expects(:get).never }
|
219
|
+
|
220
|
+
it "should return a list of available SOAP actions" do
|
221
|
+
client.wsdl.soap_actions.should == [:authenticate]
|
222
|
+
end
|
223
|
+
|
224
|
+
it "adds a SOAPAction header containing the SOAP action name" do
|
225
|
+
HTTPI.stubs(:post).returns(new_response)
|
226
|
+
|
227
|
+
client.request :authenticate do
|
228
|
+
http.headers["SOAPAction"].should == %{"authenticate"}
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should execute SOAP requests and return the response" do
|
233
|
+
HTTPI.expects(:post).returns(new_response)
|
234
|
+
response = client.request(:authenticate)
|
235
|
+
|
236
|
+
response.should be_a(Savon::SOAP::Response)
|
237
|
+
response.to_xml.should == ResponseFixture.authentication
|
238
|
+
end
|
65
239
|
end
|
66
240
|
|
67
|
-
|
68
|
-
|
241
|
+
context "without a WSDL document" do
|
242
|
+
let(:client) do
|
243
|
+
Savon::Client.new do
|
244
|
+
wsdl.endpoint = Endpoint.soap
|
245
|
+
wsdl.namespace = "http://v1_0.ws.auth.order.example.com/"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
before { HTTPI.expects(:get).never }
|
250
|
+
|
251
|
+
it "raise an ArgumentError when trying to access the WSDL" do
|
252
|
+
lambda { client.wsdl.soap_actions }.should raise_error(ArgumentError)
|
253
|
+
end
|
254
|
+
|
255
|
+
it "adds a SOAPAction header containing the SOAP action name" do
|
256
|
+
HTTPI.stubs(:post).returns(new_response)
|
257
|
+
|
258
|
+
client.request :authenticate do
|
259
|
+
http.headers["SOAPAction"].should == %{"authenticate"}
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should execute SOAP requests and return the response" do
|
264
|
+
HTTPI.expects(:post).returns(new_response)
|
265
|
+
response = client.request(:authenticate)
|
266
|
+
|
267
|
+
response.should be_a(Savon::SOAP::Response)
|
268
|
+
response.to_xml.should == ResponseFixture.authentication
|
269
|
+
end
|
69
270
|
end
|
70
271
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
272
|
+
context "when encountering a SOAP fault" do
|
273
|
+
let(:client) do
|
274
|
+
Savon::Client.new do
|
275
|
+
wsdl.endpoint = Endpoint.soap
|
276
|
+
wsdl.namespace = "http://v1_0.ws.auth.order.example.com/"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
before { HTTPI::expects(:post).returns(new_response(:code => 500, :body => ResponseFixture.soap_fault)) }
|
281
|
+
|
282
|
+
it "should raise a Savon::SOAP::Fault" do
|
283
|
+
lambda { client.request :authenticate }.should raise_error(Savon::SOAP::Fault)
|
75
284
|
end
|
76
285
|
end
|
77
286
|
|
78
|
-
|
79
|
-
|
287
|
+
context "when encountering an HTTP error" do
|
288
|
+
let(:client) do
|
289
|
+
Savon::Client.new do
|
290
|
+
wsdl.endpoint = Endpoint.soap
|
291
|
+
wsdl.namespace = "http://v1_0.ws.auth.order.example.com/"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
before { HTTPI::expects(:post).returns(new_response(:code => 500)) }
|
296
|
+
|
297
|
+
it "should raise a Savon::HTTP::Error" do
|
298
|
+
lambda { client.request :authenticate }.should raise_error(Savon::HTTP::Error)
|
299
|
+
end
|
80
300
|
end
|
81
301
|
|
82
|
-
|
83
|
-
|
302
|
+
def new_response(options = {})
|
303
|
+
defaults = { :code => 200, :headers => {}, :body => ResponseFixture.authentication }
|
304
|
+
response = defaults.merge options
|
305
|
+
|
306
|
+
HTTPI::Response.new response[:code], response[:headers], response[:body]
|
84
307
|
end
|
85
308
|
|
86
|
-
end
|
309
|
+
end
|