savon 0.6.8 → 0.7.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.
@@ -76,6 +76,11 @@ module Savon
76
76
  @namespaces ||= { "xmlns:env" => SOAPNamespace[version] }
77
77
  end
78
78
 
79
+ # Convenience method for setting the "xmlns:wsdl" namespace.
80
+ def namespace=(namespace)
81
+ namespaces["xmlns:wsdl"] = namespace
82
+ end
83
+
79
84
  # Sets the SOAP version.
80
85
  def version=(version)
81
86
  @version = version if Savon::SOAPVersions.include? version
@@ -10,6 +10,14 @@ module Savon
10
10
  @request = request
11
11
  end
12
12
 
13
+ # Sets whether to use the WSDL.
14
+ attr_writer :enabled
15
+
16
+ # Returns whether to use the WSDL. Defaults to +true+.
17
+ def enabled?
18
+ @enabled.nil? ? true : @enabled
19
+ end
20
+
13
21
  # Returns the namespace URI of the WSDL.
14
22
  def namespace_uri
15
23
  @namespace_uri ||= stream.namespace_uri
@@ -0,0 +1,12 @@
1
+ require "rubygems"
2
+ require "rake"
3
+ require "spec"
4
+ require "mocha"
5
+ require "fakeweb"
6
+
7
+ Spec::Runner.configure do |config|
8
+ config.mock_with :mocha
9
+ end
10
+
11
+ require "savon"
12
+ Savon::Request.log = false
@@ -23,10 +23,14 @@ class ResponseFixture
23
23
  @@soap_fault12 ||= load_fixture :soap_fault12
24
24
  end
25
25
 
26
+ def self.multi_ref
27
+ @@multi_ref ||= load_fixture :multi_ref
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def self.load_fixture(fixture)
29
- File.read(File.dirname(__FILE__) + "/xml/#{fixture}.xml")
33
+ File.read File.dirname(__FILE__) + "/xml/#{fixture}.xml"
30
34
  end
31
35
 
32
36
  end
@@ -0,0 +1,39 @@
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
+ <ns1:listResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://ws.example.com">
4
+ <listReturn soapenc:arrayType="ns2:HistoryEntry[3]" xsi:type="soapenc:Array" xmlns:ns2="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
5
+ <listReturn href="#id0"/>
6
+ <listReturn href="#id1"/>
7
+ <listReturn href="#id2"/>
8
+ </listReturn>
9
+ </ns1:listResponse>
10
+ <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns5:HistoryEntry" xmlns:ns5="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
11
+ <date xsi:type="xsd:dateTime">2009-09-22T13:47:23.000Z</date>
12
+ <location xsi:type="soapenc:string">Archive</location>
13
+ <mailId href="#id9"/>
14
+ <referenceId href="#id8"/>
15
+ <state xsi:type="soapenc:string">Original</state>
16
+ <subject xsi:type="soapenc:string">Mail from 09-22-2009: Misc</subject>
17
+ </multiRef>
18
+ <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns6:HistoryEntry" xmlns:ns6="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
19
+ <date xsi:type="xsd:dateTime">2009-04-30T06:38:34.000Z</date>
20
+ <location xsi:type="soapenc:string">Archive</location>
21
+ <mailId href="#id10"/>
22
+ <referenceId href="#id8"/>
23
+ <state xsi:type="soapenc:string">Original</state>
24
+ <subject xsi:type="soapenc:string">Mail from 04-29-2009: Technical support</subject>
25
+ </multiRef>
26
+ <multiRef id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns7:HistoryEntry" xmlns:ns7="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
27
+ <date xsi:type="xsd:dateTime">2009-12-18T15:43:21.000Z</date>
28
+ <location xsi:type="soapenc:string">Archive</location>
29
+ <mailId href="#id11"/>
30
+ <referenceId href="#id8"/>
31
+ <state xsi:type="soapenc:string">Original</state>
32
+ <subject xsi:type="soapenc:string">Mail from 12-17-2009: Misc</subject>
33
+ </multiRef>
34
+ <multiRef id="id11" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">972219</multiRef>
35
+ <multiRef id="id10" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">708021</multiRef>
36
+ <multiRef id="id8" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">0</multiRef>
37
+ <multiRef id="id9" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">855763</multiRef>
38
+ </soapenv:Body>
39
+ </soapenv:Envelope>
@@ -1,18 +1,18 @@
1
1
  <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://www.example.org/timeouts">
2
- <soap:Body>
3
- <soap:Fault>
4
- <Code>
5
- <Value>soap:Sender</Value>
6
- <Subcode>
7
- <Value>m:MessageTimeout</Value>
8
- </Subcode>
9
- </Code>
10
- <Reason>
11
- <Text xml:lang="en">Sender Timeout</Text>
12
- </Reason>
13
- <Detail>
14
- <m:MaxTime>P5M</m:MaxTime>
15
- </Detail>
16
- </soap:Fault>
17
- </soap:Body>
18
- </soap:Envelope>
2
+ <soap:Body>
3
+ <soap:Fault>
4
+ <Code>
5
+ <Value>soap:Sender</Value>
6
+ <Subcode>
7
+ <Value>m:MessageTimeout</Value>
8
+ </Subcode>
9
+ </Code>
10
+ <Reason>
11
+ <Text xml:lang="en">Sender Timeout</Text>
12
+ </Reason>
13
+ <Detail>
14
+ <m:MaxTime>P5M</m:MaxTime>
15
+ </Detail>
16
+ </soap:Fault>
17
+ </soap:Body>
18
+ </soap:Envelope>
@@ -20,7 +20,7 @@ private
20
20
  def self.expectations
21
21
  return @@expectations if @@expectations
22
22
 
23
- file = File.read(File.dirname(__FILE__) + "/wsdl_fixture.yml")
23
+ file = File.read File.dirname(__FILE__) + "/wsdl_fixture.yml"
24
24
  @@expectations = YAML.load ERB.new(file).result
25
25
  end
26
26
 
@@ -30,7 +30,7 @@ private
30
30
  def self.wsdl(wsdl)
31
31
  return @@wsdl[wsdl] if @@wsdl[wsdl]
32
32
 
33
- file = File.read(File.dirname(__FILE__) + "/xml/#{wsdl}.xml")
33
+ file = File.read File.dirname(__FILE__) + "/xml/#{wsdl}.xml"
34
34
  @@wsdl[wsdl] = file
35
35
  end
36
36
 
@@ -0,0 +1,12 @@
1
+ require "basic_spec_helper"
2
+
3
+ describe Savon do
4
+ before { @endpoint = "http://localhost:8080/http-basic-auth" }
5
+
6
+ it "should be able to handle HTTP basic authentication" do
7
+ client = Savon::Client.new @endpoint
8
+ client.request.basic_auth "user", "password"
9
+ response = client.do_something!
10
+ response.to_hash[:authenticate_response][:return][:success].should == true
11
+ end
12
+ 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
@@ -3,32 +3,26 @@ require "spec_helper"
3
3
  describe Savon::Client do
4
4
  before { @client = Savon::Client.new EndpointHelper.wsdl_endpoint }
5
5
 
6
- it "is initialized with a SOAP endpoint String" do
7
- Savon::Client.new EndpointHelper.wsdl_endpoint
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
8
9
  end
9
10
 
10
- it "accepts a proxy URI passed in via options" do
11
- Savon::Client.new EndpointHelper.wsdl_endpoint, :proxy => 'http://proxy'
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"
12
15
  end
13
16
 
14
- it "accepts settings for SSL client authentication via options" do
15
- Savon::Client.new EndpointHelper.wsdl_endpoint, :ssl => {
16
- :client_cert => "client cert",
17
- :client_key => "client key",
18
- :ca_file => "ca file",
19
- :verify => OpenSSL::SSL::VERIFY_PEER
20
- }
17
+ it "should have a method that returns the Savon::WSDL" do
18
+ @client.wsdl.should be_a(Savon::WSDL)
21
19
  end
22
20
 
23
- it "has a getter for accessing the Savon::WSDL" do
24
- @client.wsdl.should be_a Savon::WSDL
21
+ it "should have a method that returns the Savon::Request" do
22
+ @client.request.should be_a(Savon::Request)
25
23
  end
26
24
 
27
- it "has a getter for accessing the Savon::Request" do
28
- @client.request.should be_a Savon::Request
29
- end
30
-
31
- it "responds to SOAP actions while still behaving as usual otherwise" do
25
+ it "should respond to available SOAP actions while behaving as expected otherwise" do
32
26
  WSDLFixture.authentication(:operations).keys.each do |soap_action|
33
27
  @client.respond_to?(soap_action).should be_true
34
28
  end
@@ -37,61 +31,47 @@ describe Savon::Client do
37
31
  @client.respond_to?(:some_undefined_method).should be_false
38
32
  end
39
33
 
40
- it "dispatches SOAP calls via method_missing and returns the Savon::Response" do
41
- @client.authenticate.should be_a Savon::Response
34
+ it "should dispatch available SOAP calls via method_missing and return the Savon::Response" do
35
+ @client.authenticate.should be_a(Savon::Response)
42
36
  end
43
37
 
44
- describe "disabling retrieving and parsing the WSDL document" do
45
- it "can be done globally for every instance of Savon::Client" do
46
- @client.wsdl?.should be_true
47
- Savon::Client.wsdl = false
48
-
49
- expect_the_wsdl_to_be_disabled
50
- @client.authenticate.should be_a Savon::Response
51
-
52
- Savon::Client.wsdl = true
53
- end
54
-
55
- it "can be done per request" do
56
- @client.wsdl = false
57
-
58
- expect_the_wsdl_to_be_disabled
59
- @client.authenticate.should be_a Savon::Response
38
+ it "should disable the Savon::WSDL when passed a method with an exclamation mark" do
39
+ @client.wsdl.enabled?.should be_true
40
+ [:respond_to?, :operations, :namespace_uri, :soap_endpoint].each do |method|
41
+ Savon::WSDL.any_instance.expects(method).never
60
42
  end
61
43
 
62
- def expect_the_wsdl_to_be_disabled
63
- @client.wsdl?.should be_false
64
- [:respond_to?, :operations, :namespace_uri, :soap_endpoint].each do |method|
65
- Savon::WSDL.any_instance.expects(method).never
66
- end
44
+ response = @client.authenticate! do |soap|
45
+ soap.input.should == "authenticate"
46
+ soap.input.should == "authenticate"
67
47
  end
48
+ response.should be_a(Savon::Response)
49
+ @client.wsdl.enabled?.should be_false
68
50
  end
69
51
 
70
- it "raises a Savon::SOAPFault in case of a SOAP fault" do
52
+ it "should raise a Savon::SOAPFault in case of a SOAP fault" do
71
53
  client = Savon::Client.new EndpointHelper.wsdl_endpoint(:soap_fault)
72
- client.wsdl = false
73
- lambda { client.authenticate }.should raise_error Savon::SOAPFault
54
+ lambda { client.authenticate! }.should raise_error(Savon::SOAPFault)
74
55
  end
75
56
 
76
- it "raises a Savon::HTTPError in case of an HTTP error" do
57
+ it "should raise a Savon::HTTPError in case of an HTTP error" do
77
58
  client = Savon::Client.new EndpointHelper.wsdl_endpoint(:http_error)
78
- client.wsdl = false
79
- lambda { client.authenticate }.should raise_error Savon::HTTPError
59
+ lambda { client.authenticate! }.should raise_error(Savon::HTTPError)
80
60
  end
81
61
 
82
- it "yields the SOAP object to a block when it expects one argument" do
83
- @client.authenticate { |soap| soap.should be_a Savon::SOAP }
62
+ it "should yield an instance of Savon::SOAP to a given block expecting one argument" do
63
+ @client.authenticate { |soap| soap.should be_a(Savon::SOAP) }
84
64
  end
85
65
 
86
- it "yields the SOAP and WSSE object to a block when it expects two argument" do
66
+ it "should yield an instance of Savon::SOAP and Savon::WSSE to a gven block expecting two arguments" do
87
67
  @client.authenticate do |soap, wsse|
88
- soap.should be_a Savon::SOAP
89
- wsse.should be_a Savon::WSSE
68
+ soap.should be_a(Savon::SOAP)
69
+ wsse.should be_a(Savon::WSSE)
90
70
  end
91
71
  end
92
72
 
93
- it "still raises a NoMethodError for undefined methods" do
94
- lambda { @client.some_undefined_method }.should raise_error NoMethodError
73
+ it "should raise a NoMethodError when the method does not match an available SOAP action or method" do
74
+ lambda { @client.some_undefined_method }.should raise_error(NoMethodError)
95
75
  end
96
76
 
97
77
  end
@@ -2,26 +2,13 @@ require "spec_helper"
2
2
 
3
3
  describe Hash do
4
4
 
5
- describe "find_regexp" do
6
- before do
7
- @soap_fault_hash = { "soap:Envelope" => { "soap:Body" => { "soap:Fault" => {
8
- "faultcode" => "soap:Server", "faultstring" => "Fault occurred while processing."
9
- } } } }
5
+ describe "find_soap_body" do
6
+ it "returns the content from the 'soap:Body' element" do
7
+ { "soap:Envelope" => { "soap:Body" => "content" } }.find_soap_body.should == "content"
10
8
  end
11
9
 
12
- it "returns an empty Hash in case it did not find the specified value" do
13
- result = @soap_fault_hash.find_regexp "soap:Fault"
14
-
15
- result.should be_a Hash
16
- result.should be_empty
17
- end
18
-
19
- it "returns the value of the last Regexp filter found in the Hash" do
20
- @soap_fault_hash.find_regexp([".+:Envelope", ".+:Body"]).
21
- should == @soap_fault_hash["soap:Envelope"]["soap:Body"]
22
-
23
- @soap_fault_hash.find_regexp([/.+:Envelope/, /.+:Body/, /.+Fault/]).
24
- should == @soap_fault_hash["soap:Envelope"]["soap:Body"]["soap:Fault"]
10
+ it "returns an empty Hash in case the 'soap:Body' element could not be found" do
11
+ { "some_hash" => "content" }.find_soap_body.should == {}
25
12
  end
26
13
  end
27
14
 
@@ -39,8 +26,8 @@ describe Hash do
39
26
  it "for a Hash with multiple keys" do
40
27
  soap_xml = { :all => "users", :before => "whatever" }.to_soap_xml
41
28
 
42
- soap_xml.should include "<all>users</all>"
43
- soap_xml.should include "<before>whatever</before>"
29
+ soap_xml.should include("<all>users</all>")
30
+ soap_xml.should include("<before>whatever</before>")
44
31
  end
45
32
 
46
33
  it "for a Hash containing an Array" do
@@ -92,6 +79,23 @@ describe Hash do
92
79
  { :some => object }.to_soap_xml.should == "<some>#{object}</some>"
93
80
  end
94
81
  end
82
+
83
+ it "preserves the order of Hash keys and values specified through :@inorder" do
84
+ { :find_user => { :name => "Lucy", :id => 666, :@inorder => [:id, :name] } }.to_soap_xml.
85
+ should == "<findUser><id>666</id><name>Lucy</name></findUser>"
86
+
87
+ { :find_user => { :by_name => { :mname => "in the", :lname => "Sky", :fname => "Lucy",
88
+ :@inorder => [:fname, :mname, :lname] } } }.to_soap_xml. should ==
89
+ "<findUser><byName><fname>Lucy</fname><mname>in the</mname><lname>Sky</lname></byName></findUser>"
90
+ end
91
+
92
+ it "raises an error if the :@inorder Array does not match the Hash keys" do
93
+ lambda { { :name => "Lucy", :id => 666, :@inorder => [:name] }.to_soap_xml }.
94
+ should raise_error(RuntimeError)
95
+
96
+ lambda { { :by_name => { :name => "Lucy", :lname => "Sky", :@inorder => [:mname, :name] } }.to_soap_xml }.
97
+ should raise_error(RuntimeError)
98
+ end
95
99
  end
96
100
 
97
101
  describe "map_soap_response" do
@@ -0,0 +1,38 @@
1
+ require "spec_helper"
2
+
3
+ describe Net::HTTP do
4
+ before do
5
+ @some_uri = URI "http://example.com"
6
+ @another_uri = URI "http://example.org"
7
+ @http = Net::HTTP.new @some_uri.host, @some_uri.port
8
+ end
9
+
10
+ describe "endpoint" do
11
+ it "changes the address and port of a Net::HTTP object" do
12
+ @http.address.should == @some_uri.host
13
+ @http.port.should == @some_uri.port
14
+
15
+ @http.endpoint @another_uri.host, @another_uri.port
16
+ @http.address.should == @another_uri.host
17
+ @http.port.should == @another_uri.port
18
+ end
19
+ end
20
+
21
+ describe "ssl_client_auth" do
22
+ it "accepts a Hash of options for SSL client authentication" do
23
+ @http.cert.should be_nil
24
+ @http.key.should be_nil
25
+ @http.ca_file.should be_nil
26
+ @http.verify_mode.should be_nil
27
+
28
+ @http.ssl_client_auth :cert => "cert", :key => "key",
29
+ :ca_file => "ca_file", :verify_mode => OpenSSL::SSL::VERIFY_PEER
30
+
31
+ @http.cert.should == "cert"
32
+ @http.key.should == "key"
33
+ @http.ca_file.should == "ca_file"
34
+ @http.verify_mode.should == OpenSSL::SSL::VERIFY_PEER
35
+ end
36
+ end
37
+
38
+ end