Skip to content

Commit

Permalink
showing more respect for the target namespace and fixed objects yield…
Browse files Browse the repository at this point in the history
…ed by Savon::Client.new
  • Loading branch information
rubiii committed Oct 17, 2010
1 parent ffeaa4b commit 5e07503
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 30 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -38,6 +38,10 @@
client.request :wsdl, "GetUser" # Input tag: <wsdl:GetUser>
client.request :get_user :active => true # Input tag: <getUser active="true">

* Savon's new #request method respects the given namespace. If you don't give it a namespace,
Savon will set the target namespace to "xmlns:wsdl". But if you do specify a namespace, it will
be set to the given Symbol.

* Refactored Savon to use the new HTTPI (http://rubygems.org/gems/httpi) gem.
HTTPI::Request replaces the Savon::Request, so please make sure to have a look
at the HTTPI library and let me know about any problems. Using HTTPI actually
Expand Down
11 changes: 6 additions & 5 deletions lib/savon/client.rb
Expand Up @@ -30,7 +30,7 @@ class Client
# wsdl.namespace = "http://users.example.com"
# end
def initialize(&block)
process &block if block
process 1, &block if block
wsdl.request = http
end

Expand Down Expand Up @@ -99,6 +99,7 @@ def extract_options(args)
# Expects and Array of +options+ and preconfigures the system.
def preconfigure(options)
soap.endpoint = wsdl.endpoint
soap.namespace_identifier = options[0]
soap.namespace = wsdl.namespace
soap.body = options[2].delete :body

Expand All @@ -122,14 +123,14 @@ def set_soap_input(namespace, input, attributes)

# Processes a given +block+. Yields objects if the block expects any arguments.
# Otherwise evaluates the block in the context of this object.
def process(&block)
block.arity > 0 ? yield_objects(&block) : evaluate(&block)
def process(offset = 0, &block)
block.arity > 0 ? yield_objects(offset, &block) : evaluate(&block)
end

# Yields a number of objects to a given +block+ depending on how many arguments
# the block is expecting.
def yield_objects(&block)
yield *[soap, http, wsse, wsdl][0, block.arity]
def yield_objects(offset, &block)
yield *[soap, wsdl, http, wsse][offset, block.arity]
end

# Evaluates a given +block+ inside this object. Stores the original block binding.
Expand Down
21 changes: 17 additions & 4 deletions lib/savon/soap/xml.rb
Expand Up @@ -62,11 +62,17 @@ def namespaces
@namespaces ||= { "xmlns:env" => SOAP::Namespace[version] }
end

# Convenience method for setting the <tt>xmlns:wsdl</tt> namespace.
def namespace=(namespace)
namespaces["xmlns:wsdl"] = namespace
# Sets the default namespace identifier.
attr_writer :namespace_identifier

# Returns the default namespace identifier.
def namespace_identifier
@namespace_identifier ||= :wsdl
end

# Accessor for the default namespace URI.
attr_accessor :namespace

# Accessor for the <tt>Savon::WSSE</tt> object.
attr_accessor :wsse

Expand All @@ -84,7 +90,7 @@ def xml

# Returns the XML for a SOAP request.
def to_xml
@xml ||= builder.env :Envelope, SchemaTypes.merge(namespaces) do |xml|
@xml ||= builder.env :Envelope, complete_namespaces do |xml|
xml.env(:Header) { xml << header_for_xml } unless header_for_xml.empty?
xml.env(:Body) { xml.tag!(*input) { xml << body_to_xml } }
end
Expand All @@ -99,6 +105,13 @@ def builder
builder
end

# Returns the complete Hash of namespaces.
def complete_namespaces
defaults = SchemaTypes.dup
defaults["xmlns:#{namespace_identifier}"] = namespace if namespace
defaults.merge namespaces
end

# Returns the SOAP header as an XML String.
def header_for_xml
header.to_soap_xml + wsse_header
Expand Down
91 changes: 79 additions & 12 deletions spec/savon/client_spec.rb
Expand Up @@ -3,6 +3,47 @@
describe Savon::Client do
let(:client) { Savon::Client.new { wsdl.document = Endpoint.wsdl } }

describe ".new" do
context "with a block expecting one argument" do
it "should yield the WSDL object" do
Savon::Client.new { |wsdl| wsdl.should be_a(Savon::WSDL::Document) }
end
end

context "with a block expecting two arguments" do
it "should yield the WSDL and HTTP objects" do
Savon::Client.new do |wsdl, http|
wsdl.should be_an(Savon::WSDL::Document)
http.should be_an(HTTPI::Request)
end
end
end

context "with a block expecting three arguments" do
it "should yield the WSDL, HTTP and WSSE objects" do
Savon::Client.new do |wsdl, http, wsse|
wsdl.should be_an(Savon::WSDL::Document)
http.should be_an(HTTPI::Request)
wsse.should be_an(Savon::WSSE)
end
end
end

context "with a block expecting no arguments" do
it "should let you access the WSDL object" do
Savon::Client.new { wsdl.should be_a(Savon::WSDL::Document) }
end

it "should let you access the HTTP object" do
Savon::Client.new { http.should be_an(HTTPI::Request) }
end

it "should let you access the WSSE object" do
Savon::Client.new { wsse.should be_a(Savon::WSSE) }
end
end
end

describe "#wsdl" do
it "should return the Savon::WSDL::Document" do
client.wsdl.should be_a(Savon::WSDL::Document)
Expand All @@ -22,8 +63,6 @@
end

describe "#request" do
let(:client) { Savon::Client.new { wsdl.document = Endpoint.wsdl } }

before do
HTTPI.stubs(:get).returns(new_response(:body => WSDLFixture.load))
HTTPI.stubs(:post).returns(new_response)
Expand All @@ -39,6 +78,20 @@
it "should set the input tag to result in <getUser>" do
client.request(:get_user) { soap.input.should == [:getUser, {}] }
end

it "should set the target namespace with the default identifier" do
namespace = 'xmlns:wsdl="http://v1_0.ws.auth.order.example.com/"'
HTTPI::Request.any_instance.expects(:body=).with { |value| value.include? namespace }

client.request :get_user
end

it "should not set the target namespace if soap.namespace was set to nil" do
namespace = "http://v1_0.ws.auth.order.example.com/"
HTTPI::Request.any_instance.expects(:body=).with { |value| !value.include?(namespace) }

client.request(:get_user) { soap.namespace = nil }
end
end

context "with a single argument (String)" do
Expand All @@ -55,7 +108,21 @@

context "with two Symbols" do
it "should set the input tag to result in <wsdl:getUser>" do
client.request(:wsdl, :get_user) { soap.input.should == [:wsdl, :getUser, {}] }
client.request(:v1, :get_user) { soap.input.should == [:v1, :getUser, {}] }
end

it "should set the target namespace with the given identifier" do
namespace = 'xmlns:v1="http://v1_0.ws.auth.order.example.com/"'
HTTPI::Request.any_instance.expects(:body=).with { |value| value.include? namespace }

client.request :v1, :get_user
end

it "should not set the target namespace if soap.namespace was set to nil" do
namespace = "http://v1_0.ws.auth.order.example.com/"
HTTPI::Request.any_instance.expects(:body=).with { |value| !value.include?(namespace) }

client.request(:v1, :get_user) { soap.namespace = nil }
end
end

Expand All @@ -72,31 +139,31 @@
end

context "with a block expecting two arguments" do
it "should yield the SOAP and HTTP objects" do
client.request(:authenticate) do |soap, http|
it "should yield the SOAP and WSDL objects" do
client.request(:authenticate) do |soap, wsdl|
soap.should be_a(Savon::SOAP::XML)
http.should be_an(HTTPI::Request)
wsdl.should be_an(Savon::WSDL::Document)
end
end
end

context "with a block expecting three arguments" do
it "should yield the SOAP, HTTP and WSSE objects" do
client.request(:authenticate) do |soap, http, wsse|
it "should yield the SOAP, WSDL and HTTP objects" do
client.request(:authenticate) do |soap, wsdl, http|
soap.should be_a(Savon::SOAP::XML)
wsdl.should be_an(Savon::WSDL::Document)
http.should be_an(HTTPI::Request)
wsse.should be_a(Savon::WSSE)
end
end
end

context "with a block expecting four arguments" do
it "should yield the SOAP, HTTP, WSSE and WSDL objects" do
client.request(:authenticate) do |soap, http, wsse, wsdl|
it "should yield the SOAP, WSDL, HTTP and WSSE objects" do
client.request(:authenticate) do |soap, wsdl, http, wsse|
soap.should be_a(Savon::SOAP::XML)
wsdl.should be_a(Savon::WSDL::Document)
http.should be_an(HTTPI::Request)
wsse.should be_a(Savon::WSSE)
wsdl.should be_a(Savon::WSDL::Document)
end
end
end
Expand Down
12 changes: 3 additions & 9 deletions spec/savon/soap/xml_spec.rb
Expand Up @@ -98,13 +98,6 @@
end
end

describe "#namespace" do
it "should set the 'xmlns:wsdl' namespace" do
xml.namespace = "http://example.com"
xml.namespaces["xmlns:wsdl"].should == "http://example.com"
end
end

describe "#wsse" do
it "should set the Savon::WSSE object" do
xml.wsse = Savon::WSSE.new
Expand Down Expand Up @@ -194,8 +187,9 @@
end
end

context "using the #namespace shortcut" do
it "should contain the 'xmlns:wsdl' namespace" do
context "using the #namespace and #namespace_identifier" do
it "should contain the specified namespace" do
xml.namespace_identifier = :wsdl
xml.namespace = "http://example.com"
xml.to_xml.should include('xmlns:wsdl="http://example.com"')
end
Expand Down

0 comments on commit 5e07503

Please sign in to comment.