tictoc-savon 0.7.9
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/.autotest +5 -0
- data/CHANGELOG +176 -0
- data/LICENSE +20 -0
- data/README.rdoc +64 -0
- data/Rakefile +50 -0
- data/lib/savon.rb +35 -0
- data/lib/savon/client.rb +131 -0
- data/lib/savon/core_ext.rb +8 -0
- data/lib/savon/core_ext/array.rb +31 -0
- data/lib/savon/core_ext/datetime.rb +10 -0
- data/lib/savon/core_ext/hash.rb +107 -0
- data/lib/savon/core_ext/net_http.rb +19 -0
- data/lib/savon/core_ext/object.rb +16 -0
- data/lib/savon/core_ext/string.rb +69 -0
- data/lib/savon/core_ext/symbol.rb +8 -0
- data/lib/savon/core_ext/uri.rb +10 -0
- data/lib/savon/logger.rb +56 -0
- data/lib/savon/request.rb +138 -0
- data/lib/savon/response.rb +174 -0
- data/lib/savon/soap.rb +302 -0
- data/lib/savon/version.rb +5 -0
- data/lib/savon/wsdl.rb +137 -0
- data/lib/savon/wsdl_stream.rb +85 -0
- data/lib/savon/wsse.rb +163 -0
- data/spec/basic_spec_helper.rb +11 -0
- data/spec/endpoint_helper.rb +23 -0
- data/spec/fixtures/gzip/gzip_response_fixture.rb +7 -0
- data/spec/fixtures/gzip/message.gz +0 -0
- data/spec/fixtures/response/response_fixture.rb +36 -0
- data/spec/fixtures/response/xml/authentication.xml +14 -0
- data/spec/fixtures/response/xml/multi_ref.xml +39 -0
- data/spec/fixtures/response/xml/soap_fault.xml +8 -0
- data/spec/fixtures/response/xml/soap_fault12.xml +18 -0
- data/spec/fixtures/wsdl/wsdl_fixture.rb +37 -0
- data/spec/fixtures/wsdl/wsdl_fixture.yml +42 -0
- data/spec/fixtures/wsdl/xml/authentication.xml +63 -0
- data/spec/fixtures/wsdl/xml/geotrust.xml +156 -0
- data/spec/fixtures/wsdl/xml/namespaced_actions.xml +307 -0
- data/spec/fixtures/wsdl/xml/no_namespace.xml +115 -0
- data/spec/http_stubs.rb +26 -0
- data/spec/integration/http_basic_auth_spec.rb +16 -0
- data/spec/integration/server.rb +51 -0
- data/spec/savon/client_spec.rb +86 -0
- data/spec/savon/core_ext/array_spec.rb +49 -0
- data/spec/savon/core_ext/datetime_spec.rb +21 -0
- data/spec/savon/core_ext/hash_spec.rb +190 -0
- data/spec/savon/core_ext/net_http_spec.rb +38 -0
- data/spec/savon/core_ext/object_spec.rb +34 -0
- data/spec/savon/core_ext/string_spec.rb +99 -0
- data/spec/savon/core_ext/symbol_spec.rb +12 -0
- data/spec/savon/core_ext/uri_spec.rb +19 -0
- data/spec/savon/request_spec.rb +117 -0
- data/spec/savon/response_spec.rb +179 -0
- data/spec/savon/soap_spec.rb +202 -0
- data/spec/savon/wsdl_spec.rb +107 -0
- data/spec/savon/wsse_spec.rb +132 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +5 -0
- metadata +229 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<definitions name="Api" xmlns:typens="urn:ActionWebService" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="urn:ActionWebService" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns="http://schemas.xmlsoap.org/wsdl/">
|
3
|
+
<types>
|
4
|
+
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:ActionWebService">
|
5
|
+
<xsd:complexType name="MpUser">
|
6
|
+
<xsd:all>
|
7
|
+
<xsd:element name="avatar_thumb_url" type="xsd:string"/>
|
8
|
+
<xsd:element name="speciality" type="xsd:string"/>
|
9
|
+
<xsd:element name="avatar_icon_url" type="xsd:string"/>
|
10
|
+
<xsd:element name="firstname" type="xsd:string"/>
|
11
|
+
<xsd:element name="city" type="xsd:string"/>
|
12
|
+
<xsd:element name="mp_id" type="xsd:int"/>
|
13
|
+
<xsd:element name="lastname" type="xsd:string"/>
|
14
|
+
<xsd:element name="login" type="xsd:string"/>
|
15
|
+
</xsd:all>
|
16
|
+
</xsd:complexType>
|
17
|
+
<xsd:complexType name="MpUserArray">
|
18
|
+
<xsd:complexContent>
|
19
|
+
<xsd:restriction base="soapenc:Array">
|
20
|
+
<xsd:attribute wsdl:arrayType="typens:MpUser[]" ref="soapenc:arrayType"/>
|
21
|
+
</xsd:restriction>
|
22
|
+
</xsd:complexContent>
|
23
|
+
</xsd:complexType>
|
24
|
+
<xsd:complexType name="McContact">
|
25
|
+
<xsd:all>
|
26
|
+
<xsd:element name="last_name" type="xsd:string"/>
|
27
|
+
<xsd:element name="email" type="xsd:string"/>
|
28
|
+
<xsd:element name="mp_id" type="xsd:int"/>
|
29
|
+
<xsd:element name="role" type="xsd:int"/>
|
30
|
+
<xsd:element name="login" type="xsd:string"/>
|
31
|
+
<xsd:element name="first_name" type="xsd:string"/>
|
32
|
+
</xsd:all>
|
33
|
+
</xsd:complexType>
|
34
|
+
<xsd:complexType name="McContactArray">
|
35
|
+
<xsd:complexContent>
|
36
|
+
<xsd:restriction base="soapenc:Array">
|
37
|
+
<xsd:attribute wsdl:arrayType="typens:McContact[]" ref="soapenc:arrayType"/>
|
38
|
+
</xsd:restriction>
|
39
|
+
</xsd:complexContent>
|
40
|
+
</xsd:complexType>
|
41
|
+
</xsd:schema>
|
42
|
+
</types>
|
43
|
+
<message name="GetUserLoginById">
|
44
|
+
<part name="api_key" type="xsd:string"/>
|
45
|
+
<part name="id" type="xsd:int"/>
|
46
|
+
</message>
|
47
|
+
<message name="GetUserLoginByIdResponse">
|
48
|
+
<part name="return" type="xsd:string"/>
|
49
|
+
</message>
|
50
|
+
<message name="GetAllContacts">
|
51
|
+
<part name="api_key" type="xsd:string"/>
|
52
|
+
<part name="login" type="xsd:string"/>
|
53
|
+
</message>
|
54
|
+
<message name="GetAllContactsResponse">
|
55
|
+
<part name="return" type="typens:McContactArray"/>
|
56
|
+
</message>
|
57
|
+
<message name="SearchUser">
|
58
|
+
<part name="api_key" type="xsd:string"/>
|
59
|
+
<part name="phrase" type="xsd:string"/>
|
60
|
+
<part name="page" type="xsd:string"/>
|
61
|
+
<part name="per_page" type="xsd:string"/>
|
62
|
+
</message>
|
63
|
+
<message name="SearchUserResponse">
|
64
|
+
<part name="return" type="typens:MpUserArray"/>
|
65
|
+
</message>
|
66
|
+
<portType name="ApiApiPort">
|
67
|
+
<operation name="GetUserLoginById">
|
68
|
+
<input message="typens:GetUserLoginById"/>
|
69
|
+
<output message="typens:GetUserLoginByIdResponse"/>
|
70
|
+
</operation>
|
71
|
+
<operation name="GetAllContacts">
|
72
|
+
<input message="typens:GetAllContacts"/>
|
73
|
+
<output message="typens:GetAllContactsResponse"/>
|
74
|
+
</operation>
|
75
|
+
<operation name="SearchUser">
|
76
|
+
<input message="typens:SearchUser"/>
|
77
|
+
<output message="typens:SearchUserResponse"/>
|
78
|
+
</operation>
|
79
|
+
</portType>
|
80
|
+
<binding name="ApiApiBinding" type="typens:ApiApiPort">
|
81
|
+
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
|
82
|
+
<operation name="GetUserLoginById">
|
83
|
+
<soap:operation soapAction="/api/api/GetUserLoginById"/>
|
84
|
+
<input>
|
85
|
+
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:ActionWebService" use="encoded"/>
|
86
|
+
</input>
|
87
|
+
<output>
|
88
|
+
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:ActionWebService" use="encoded"/>
|
89
|
+
</output>
|
90
|
+
</operation>
|
91
|
+
<operation name="GetAllContacts">
|
92
|
+
<soap:operation soapAction="/api/api/GetAllContacts"/>
|
93
|
+
<input>
|
94
|
+
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:ActionWebService" use="encoded"/>
|
95
|
+
</input>
|
96
|
+
<output>
|
97
|
+
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:ActionWebService" use="encoded"/>
|
98
|
+
</output>
|
99
|
+
</operation>
|
100
|
+
<operation name="SearchUser">
|
101
|
+
<soap:operation soapAction="/api/api/SearchUser"/>
|
102
|
+
<input>
|
103
|
+
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:ActionWebService" use="encoded"/>
|
104
|
+
</input>
|
105
|
+
<output>
|
106
|
+
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:ActionWebService" use="encoded"/>
|
107
|
+
</output>
|
108
|
+
</operation>
|
109
|
+
</binding>
|
110
|
+
<service name="ApiService">
|
111
|
+
<port name="ApiApiPort" binding="typens:ApiApiBinding">
|
112
|
+
<soap:address location="http://example.com/api/api"/>
|
113
|
+
</port>
|
114
|
+
</service>
|
115
|
+
</definitions>
|
data/spec/http_stubs.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
FakeWeb.allow_net_connect = false
|
2
|
+
|
3
|
+
# Some WSDL and SOAP request.
|
4
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint, :body => WSDLFixture.authentication
|
5
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint, :body => ResponseFixture.authentication
|
6
|
+
|
7
|
+
# WSDL and SOAP request with a Savon::SOAPFault.
|
8
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:soap_fault), :body => WSDLFixture.authentication
|
9
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint(:soap_fault), :body => ResponseFixture.soap_fault
|
10
|
+
|
11
|
+
# WSDL and SOAP request with a Savon::HTTPError.
|
12
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:http_error), :body => WSDLFixture.authentication
|
13
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint(:http_error), :body => "", :status => ["404", "Not Found"]
|
14
|
+
|
15
|
+
# WSDL and SOAP request with an invalid endpoint.
|
16
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:invalid), :body => ""
|
17
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint(:invalid), :body => "", :status => ["404", "Not Found"]
|
18
|
+
|
19
|
+
# WSDL request returning a WSDL document where the main sections are not namespaced.
|
20
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:no_namespace), :body => WSDLFixture.no_namespace
|
21
|
+
|
22
|
+
# WSDL request returning a WSDL document with namespaced SOAP actions.
|
23
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:namespaced_actions), :body => WSDLFixture.namespaced_actions
|
24
|
+
|
25
|
+
# WSDL request returning a WSDL document with geotrust SOAP actions.
|
26
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:geotrust), :body => WSDLFixture.geotrust
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "basic_spec_helper"
|
2
|
+
|
3
|
+
describe Savon do
|
4
|
+
before { @client = Savon::Client.new "http://localhost:8080/http-basic-auth" }
|
5
|
+
|
6
|
+
it "should be able to handle HTTP basic authentication" do
|
7
|
+
@client.request.basic_auth "user", "password"
|
8
|
+
response = @client.do_something!
|
9
|
+
response.to_hash[:authenticate_response][:return][:success].should == true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should raise a Savon::HTTPError in case authentication failed" do
|
13
|
+
lambda { @client.do_something! }.should raise_error(Savon::HTTPError)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "webrick"
|
2
|
+
|
3
|
+
include WEBrick
|
4
|
+
|
5
|
+
# Run WEBrick. Yields the server to a given block.
|
6
|
+
def run_webrick(config = {})
|
7
|
+
config.update :Port => 8080
|
8
|
+
server = HTTPServer.new config
|
9
|
+
yield server if block_given?
|
10
|
+
["INT", "TERM"].each { |signal| trap(signal) { server.shutdown } }
|
11
|
+
server.start
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the SOAP response fixture for a given +file+.
|
15
|
+
def respond_with(file)
|
16
|
+
response_path = File.dirname(__FILE__) + "/../fixtures/response/xml"
|
17
|
+
File.read "#{response_path}/#{file}.xml"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns HTML links for a given Hash of link URI's and names.
|
21
|
+
def link_to(links)
|
22
|
+
links.map { |link| "<a href='#{link[:uri]}'>#{link[:name]}</a>" }.join("<br>")
|
23
|
+
end
|
24
|
+
|
25
|
+
run_webrick do |server|
|
26
|
+
user, password, realm = "user", "password", "realm"
|
27
|
+
|
28
|
+
htdigest = HTTPAuth::Htdigest.new "/tmp/webrick-htdigest"
|
29
|
+
htdigest.set_passwd realm, user, password
|
30
|
+
authenticator = HTTPAuth::DigestAuth.new :UserDB => htdigest, :Realm => realm
|
31
|
+
|
32
|
+
# Homepage including links to subpages.
|
33
|
+
server.mount_proc("/") do |request, response|
|
34
|
+
response.body = link_to [
|
35
|
+
{ :uri => "http-basic-auth", :name => "HTTP basic auth" },
|
36
|
+
{ :uri => "http-digest-auth", :name => "HTTP digest auth" }
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
# HTTP basic authentication.
|
41
|
+
server.mount_proc("/http-basic-auth") do |request, response|
|
42
|
+
HTTPAuth.basic_auth(request, response, realm) { |u, p| u == user && p == password }
|
43
|
+
response.body = respond_with :authentication
|
44
|
+
end
|
45
|
+
|
46
|
+
# HTTP digest authentication.
|
47
|
+
server.mount_proc("/http-digest-auth") do |request, response|
|
48
|
+
authenticator.authenticate request, response
|
49
|
+
response.body = "HTTP digest authentication successfull"
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Savon::Client do
|
4
|
+
before { @client = Savon::Client.new EndpointHelper.wsdl_endpoint }
|
5
|
+
|
6
|
+
it "should be initialized with an endpoint String" do
|
7
|
+
client = Savon::Client.new EndpointHelper.wsdl_endpoint
|
8
|
+
client.request.http.proxy?.should be_false
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should accept a proxy URI via an optional Hash of options" do
|
12
|
+
client = Savon::Client.new EndpointHelper.wsdl_endpoint, :proxy => "http://proxy"
|
13
|
+
client.request.http.proxy?.should be_true
|
14
|
+
client.request.http.proxy_address == "http://proxy"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should accept a SOAP endpoint via an optional Hash of options" do
|
18
|
+
client = Savon::Client.new EndpointHelper.wsdl_endpoint, :soap_endpoint => "http://localhost"
|
19
|
+
client.wsdl.soap_endpoint.should == "http://localhost"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have a method that returns the Savon::WSDL" do
|
23
|
+
@client.wsdl.should be_a(Savon::WSDL)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have a method that returns the Savon::Request" do
|
27
|
+
@client.request.should be_a(Savon::Request)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should respond to available SOAP actions while behaving as expected otherwise" do
|
31
|
+
WSDLFixture.authentication(:operations).keys.each do |soap_action|
|
32
|
+
@client.respond_to?(soap_action).should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
@client.respond_to?(:object_id).should be_true
|
36
|
+
@client.respond_to?(:some_undefined_method).should be_false
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should dispatch available SOAP calls via method_missing and return the Savon::Response" do
|
40
|
+
@client.authenticate.should be_a(Savon::Response)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should disable the Savon::WSDL when passed a method with an exclamation mark" do
|
44
|
+
@client.wsdl.enabled?.should be_true
|
45
|
+
[:operations, :namespace_uri, :soap_endpoint].each do |method|
|
46
|
+
Savon::WSDL.any_instance.expects(method).never
|
47
|
+
end
|
48
|
+
|
49
|
+
response = @client.authenticate! do |soap|
|
50
|
+
soap.input.should == "authenticate"
|
51
|
+
soap.input.should == "authenticate"
|
52
|
+
end
|
53
|
+
response.should be_a(Savon::Response)
|
54
|
+
@client.wsdl.enabled?.should be_false
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should raise a Savon::SOAPFault in case of a SOAP fault" do
|
58
|
+
client = Savon::Client.new EndpointHelper.wsdl_endpoint(:soap_fault)
|
59
|
+
lambda { client.authenticate! }.should raise_error(Savon::SOAPFault)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should raise a Savon::HTTPError in case of an HTTP error" do
|
63
|
+
client = Savon::Client.new EndpointHelper.wsdl_endpoint(:http_error)
|
64
|
+
lambda { client.authenticate! }.should raise_error(Savon::HTTPError)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should yield an instance of Savon::SOAP to a given block expecting one argument" do
|
68
|
+
@client.authenticate { |soap| soap.should be_a(Savon::SOAP) }
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should yield an instance of Savon::SOAP and Savon::WSSE to a gven block expecting two arguments" do
|
72
|
+
@client.authenticate do |soap, wsse|
|
73
|
+
soap.should be_a(Savon::SOAP)
|
74
|
+
wsse.should be_a(Savon::WSSE)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should have a call method that forwards to method_missing for SOAP actions named after existing methods" do
|
79
|
+
@client.call(:authenticate) { |soap| soap.should be_a(Savon::SOAP) }
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should raise a NoMethodError when the method does not match an available SOAP action or method" do
|
83
|
+
lambda { @client.some_undefined_method }.should raise_error(NoMethodError)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Array do
|
4
|
+
|
5
|
+
describe "to_soap_xml" do
|
6
|
+
it "should return the XML for an Array of Hashes" do
|
7
|
+
array = [{ :name => "adam" }, { :name => "eve" }]
|
8
|
+
result = "<user><name>adam</name></user><user><name>eve</name></user>"
|
9
|
+
|
10
|
+
array.to_soap_xml("user").should == result
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return the XML for an Array of different Objects" do
|
14
|
+
array = [:symbol, "string", 123]
|
15
|
+
result = "<value>symbol</value><value>string</value><value>123</value>"
|
16
|
+
|
17
|
+
array.to_soap_xml("value").should == result
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should default to escape special characters" do
|
21
|
+
array = ["<tag />", "adam & eve"]
|
22
|
+
result = "<value><tag /></value><value>adam & eve</value>"
|
23
|
+
|
24
|
+
array.to_soap_xml("value").should == result
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not escape special characters when told to" do
|
28
|
+
array = ["<tag />", "adam & eve"]
|
29
|
+
result = "<value><tag /></value><value>adam & eve</value>"
|
30
|
+
|
31
|
+
array.to_soap_xml("value", false).should == result
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should add attributes to a given tag" do
|
35
|
+
array = ["adam", "eve"]
|
36
|
+
result = '<value active="true">adam</value><value active="true">eve</value>'
|
37
|
+
|
38
|
+
array.to_soap_xml("value", :escape_xml, :active => true).should == result
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should add attributes to duplicate tags" do
|
42
|
+
array = ["adam", "eve"]
|
43
|
+
result = '<value id="1">adam</value><value id="2">eve</value>'
|
44
|
+
|
45
|
+
array.to_soap_xml("value", :escape_xml, :id => [1, 2]).should == result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DateTime do
|
4
|
+
before do
|
5
|
+
@datetime = DateTime.new 2012, 03, 22, 16, 22, 33
|
6
|
+
@datetime_string = "2012-03-22T16:22:33Z"
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "to_soap_value" do
|
10
|
+
it "should return an xs:dateTime compliant String" do
|
11
|
+
@datetime.to_soap_value.should == @datetime_string
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "to_soap_value!" do
|
16
|
+
it "should act like :to_soap_value" do
|
17
|
+
@datetime.to_soap_value.should == @datetime_string
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
|
5
|
+
describe "find_soap_body" do
|
6
|
+
it "should return the content from the 'soap:Body' element" do
|
7
|
+
soap_body = { "soap:Envelope" => { "soap:Body" => "content" } }
|
8
|
+
soap_body.find_soap_body.should == "content"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return an empty Hash in case the 'soap:Body' element could not be found" do
|
12
|
+
soap_body = { "some_hash" => "content" }
|
13
|
+
soap_body.find_soap_body.should == {}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "to_soap_xml" do
|
18
|
+
describe "should return SOAP request compatible XML" do
|
19
|
+
it "for a simple Hash" do
|
20
|
+
hash, result = { :some => "user" }, "<some>user</some>"
|
21
|
+
hash.to_soap_xml.should == result
|
22
|
+
end
|
23
|
+
|
24
|
+
it "for a nested Hash" do
|
25
|
+
hash, result = { :some => { :new => "user" } }, "<some><new>user</new></some>"
|
26
|
+
hash.to_soap_xml.should == result
|
27
|
+
end
|
28
|
+
|
29
|
+
it "for a Hash with multiple keys" do
|
30
|
+
hash = { :all => "users", :before => "whatever" }
|
31
|
+
hash.to_soap_xml.should include("<all>users</all>", "<before>whatever</before>")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "for a Hash containing an Array" do
|
35
|
+
hash, result = { :some => ["user", "gorilla"] }, "<some>user</some><some>gorilla</some>"
|
36
|
+
hash.to_soap_xml.should == result
|
37
|
+
end
|
38
|
+
|
39
|
+
it "for a Hash containing an Array of Hashes" do
|
40
|
+
hash = { :some => [{ :new => "user" }, { :old => "gorilla" }] }
|
41
|
+
result = "<some><new>user</new></some><some><old>gorilla</old></some>"
|
42
|
+
|
43
|
+
hash.to_soap_xml.should == result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should convert Hash key Symbols to lowerCamelCase" do
|
48
|
+
hash, result = { :find_or_create => "user" }, "<findOrCreate>user</findOrCreate>"
|
49
|
+
hash.to_soap_xml.should == result
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should not convert Hash key Strings" do
|
53
|
+
hash, result = { "find_or_create" => "user" }, "<find_or_create>user</find_or_create>"
|
54
|
+
hash.to_soap_xml.should == result
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should convert DateTime objects to xs:dateTime compliant Strings" do
|
58
|
+
hash = { :before => DateTime.new(2012, 03, 22, 16, 22, 33) }
|
59
|
+
result = "<before>2012-03-22T16:22:33Z</before>"
|
60
|
+
|
61
|
+
hash.to_soap_xml.should == result
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should convert Objects responding to to_datetime to xs:dateTime compliant Strings" do
|
65
|
+
singleton = Object.new
|
66
|
+
def singleton.to_datetime
|
67
|
+
DateTime.new(2012, 03, 22, 16, 22, 33)
|
68
|
+
end
|
69
|
+
|
70
|
+
hash, result = { :before => singleton }, "<before>2012-03-22T16:22:33Z</before>"
|
71
|
+
hash.to_soap_xml.should == result
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should call to_s on Strings even if they respond to to_datetime" do
|
75
|
+
object = "gorilla"
|
76
|
+
object.expects(:to_datetime).never
|
77
|
+
|
78
|
+
hash, result = { :name => object }, "<name>gorilla</name>"
|
79
|
+
hash.to_soap_xml.should == result
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should call to_s on any other Object" do
|
83
|
+
[666, true, false, nil].each do |object|
|
84
|
+
{ :some => object }.to_soap_xml.should == "<some>#{object}</some>"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should default to escape special characters" do
|
89
|
+
result = { :some => { :nested => "<tag />" }, :tag => "<tag />" }.to_soap_xml
|
90
|
+
result.should include("<tag><tag /></tag>")
|
91
|
+
result.should include("<some><nested><tag /></nested></some>")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not escape special characters for keys marked with an exclamation mark" do
|
95
|
+
result = { :some => { :nested! => "<tag />" }, :tag! => "<tag />" }.to_soap_xml
|
96
|
+
result.should include("<tag><tag /></tag>")
|
97
|
+
result.should include("<some><nested><tag /></nested></some>")
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should preserve the order of Hash keys and values specified through :order!" do
|
101
|
+
hash = { :find_user => { :name => "Lucy", :id => 666, :order! => [:id, :name] } }
|
102
|
+
result = "<findUser><id>666</id><name>Lucy</name></findUser>"
|
103
|
+
hash.to_soap_xml.should == result
|
104
|
+
|
105
|
+
hash = { :find_user => { :mname => "in the", :lname => "Sky", :fname => "Lucy", :order! => [:fname, :mname, :lname] } }
|
106
|
+
result = "<findUser><fname>Lucy</fname><mname>in the</mname><lname>Sky</lname></findUser>"
|
107
|
+
hash.to_soap_xml.should == result
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should raise an error if the :order! Array does not match the Hash keys" do
|
111
|
+
hash = { :name => "Lucy", :id => 666, :order! => [:name] }
|
112
|
+
lambda { hash.to_soap_xml }.should raise_error(ArgumentError)
|
113
|
+
|
114
|
+
hash = { :by_name => { :name => "Lucy", :lname => "Sky", :order! => [:mname, :name] } }
|
115
|
+
lambda { hash.to_soap_xml }.should raise_error(ArgumentError)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should add attributes to Hash keys specified through :attributes!" do
|
119
|
+
hash = { :find_user => { :person => "Lucy", :attributes! => { :person => { :id => 666 } } } }
|
120
|
+
result = '<findUser><person id="666">Lucy</person></findUser>'
|
121
|
+
hash.to_soap_xml.should == result
|
122
|
+
|
123
|
+
hash = { :find_user => { :person => "Lucy", :attributes! => { :person => { :id => 666, :city => "Hamburg" } } } }
|
124
|
+
soap_xml = hash.to_soap_xml
|
125
|
+
soap_xml.should include('id="666"', 'city="Hamburg"')
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should add attributes to duplicate Hash keys specified through :attributes!" do
|
129
|
+
hash = { :find_user => { :person => ["Lucy", "Anna"], :attributes! => { :person => { :id => [1, 3] } } } }
|
130
|
+
result = '<findUser><person id="1">Lucy</person><person id="3">Anna</person></findUser>'
|
131
|
+
hash.to_soap_xml.should == result
|
132
|
+
|
133
|
+
hash = { :find_user => { :person => ["Lucy", "Anna"], :attributes! => { :person => { :active => "true" } } } }
|
134
|
+
result = '<findUser><person active="true">Lucy</person><person active="true">Anna</person></findUser>'
|
135
|
+
hash.to_soap_xml.should == result
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "map_soap_response" do
|
140
|
+
it "should convert Hash key Strings to snake_case Symbols" do
|
141
|
+
soap_response = { "userResponse" => { "accountStatus" => "active" } }
|
142
|
+
result = { :user_response => { :account_status => "active" } }
|
143
|
+
|
144
|
+
soap_response.map_soap_response.should == result
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should strip namespaces from Hash keys" do
|
148
|
+
soap_response = { "ns:userResponse" => { "ns2:id" => "666" } }
|
149
|
+
result = { :user_response => { :id => "666" } }
|
150
|
+
|
151
|
+
soap_response.map_soap_response.should == result
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should convert Hash keys and values in Arrays" do
|
155
|
+
soap_response = { "response" => [{ "name" => "dude" }, { "name" => "gorilla" }] }
|
156
|
+
result = { :response=> [{ :name => "dude" }, { :name => "gorilla" }] }
|
157
|
+
|
158
|
+
soap_response.map_soap_response.should == result
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should convert xsi:nil values to nil Objects" do
|
162
|
+
soap_response = { "userResponse" => { "xsi:nil" => "true" } }
|
163
|
+
result = { :user_response => nil }
|
164
|
+
|
165
|
+
soap_response.map_soap_response.should == result
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should convert Hash values matching the xs:dateTime format into DateTime Objects" do
|
169
|
+
soap_response = { "response" => { "at" => "2012-03-22T16:22:33" } }
|
170
|
+
result = { :response => { :at => DateTime.new(2012, 03, 22, 16, 22, 33) } }
|
171
|
+
|
172
|
+
soap_response.map_soap_response.should == result
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should convert Hash values matching 'true' to TrueClass" do
|
176
|
+
soap_response = { "response" => { "active" => "false" } }
|
177
|
+
result = { :response => { :active => false } }
|
178
|
+
|
179
|
+
soap_response.map_soap_response.should == result
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should convert Hash values matching 'false' to FalseClass" do
|
183
|
+
soap_response = { "response" => { "active" => "true" } }
|
184
|
+
result = { :response => { :active => true } }
|
185
|
+
|
186
|
+
soap_response.map_soap_response.should == result
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|