Skip to content

Commit

Permalink
Merge pull request #542 from ashrocket/default_form_value
Browse files Browse the repository at this point in the history
Savon 3 sets the correct value for 'form' attribute 'qualified' 'unqualified'

This fixes a regression in Savon v3
  • Loading branch information
tjarratt committed Jan 28, 2014
2 parents 3fa5293 + 0fdaeda commit f47b5c6
Show file tree
Hide file tree
Showing 4 changed files with 306 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
@@ -1,4 +1,5 @@
## 3.0.0 (branch)
* Fix: [#539] (https://github.com/savonrb/savon/issues/539) Implement element form 'qualified' or 'unqualified' correctly

* This version requires Ruby 1.9.2 or higher. Ruby 1.8 is no longer supported!

Expand Down
9 changes: 7 additions & 2 deletions lib/savon/xs/types.rb
Expand Up @@ -66,15 +66,20 @@ def initialize(node, schemas, schema = {})
@element_form_default = schema[:element_form_default]

@name = node['name']
@form = node['form'] || 'unqualified'
# Because you've overriden the form method, you don't need to set
# unqualified as the default when no form is specified.
#@form = node['form'] || 'unqualified'
@form = node['form']

@namespaces = node.namespaces
end

attr_reader :name, :form, :namespace, :namespaces

def form
if @form == 'qualified' || @element_form_default == 'qualified'
if @form
@form
elsif @element_form_default == 'qualified'
'qualified'
else
'unqualified'
Expand Down
156 changes: 156 additions & 0 deletions spec/fixtures/wsdl/jetairways.wsdl
@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.vedaleon.com/webservices" xmlns:s1="http://www.ebxml.org/namespaces/messageHeader" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:s2="http://schemas.xmlsoap.org/ws/2002/12/secext" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.vedaleon.com/webservices" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Vedaleon Web Services</wsdl:documentation>
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://www.vedaleon.com/webservices">
<s:element name="Logon">
<s:complexType />
</s:element>
<s:element name="LogonResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="LogonResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
<s:schema elementFormDefault="qualified" targetNamespace="http://www.ebxml.org/namespaces/messageHeader">
<s:import namespace="http://www.w3.org/XML/1998/namespace" />
<s:element name="MessageHeader" type="s1:MessageHeader" />
<s:complexType name="MessageHeader">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="From" type="s1:From" />
<s:element minOccurs="0" maxOccurs="1" name="To" type="s1:To" />
<s:element minOccurs="0" maxOccurs="1" name="CPAId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="ConversationId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Service" type="s1:Service" />
<s:element minOccurs="0" maxOccurs="1" name="Action" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="MessageData" type="s1:MessageData" />
<s:element minOccurs="0" maxOccurs="1" name="DuplicateElimination" />
<s:element minOccurs="0" maxOccurs="unbounded" name="Description" type="s1:Description" />
</s:sequence>
<s:attribute form="qualified" name="id" type="s:ID" />
<s:attribute form="qualified" name="version" type="s:string" />
<s:anyAttribute />
</s:complexType>
<s:complexType name="From">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="PartyId" type="s1:PartyId" />
<s:element minOccurs="0" maxOccurs="1" name="Role" type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="PartyId">
<s:simpleContent>
<s:extension base="s:string">
<s:attribute form="qualified" name="type" type="s:string" />
</s:extension>
</s:simpleContent>
</s:complexType>
<s:complexType name="To">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="PartyId" type="s1:PartyId" />
<s:element minOccurs="0" maxOccurs="1" name="Role" type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="Service">
<s:simpleContent>
<s:extension base="s:string">
<s:attribute form="qualified" name="type" type="s:string" />
</s:extension>
</s:simpleContent>
</s:complexType>
<s:complexType name="MessageData">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="MessageId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Timestamp" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="RefToMessageId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="TimeToLive" type="s:dateTime" />
</s:sequence>
</s:complexType>
<s:complexType name="Description">
<s:simpleContent>
<s:extension base="s:string">
<s:attribute ref="xml:lang" use="optional" />
</s:extension>
</s:simpleContent>
</s:complexType>
</s:schema>
<s:schema elementFormDefault="qualified" targetNamespace="http://schemas.xmlsoap.org/ws/2002/12/secext">
<s:element name="Security" type="s2:Security" />
<s:complexType name="Security">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="UsernameToken" type="s2:SecurityUsernameToken" />
<s:element minOccurs="0" maxOccurs="1" name="BinarySecurityToken" type="s:string" />
</s:sequence>
<s:anyAttribute />
</s:complexType>
<s:complexType name="SecurityUsernameToken">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Username" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Password" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="Organization" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="Domain" type="s:string" />
</s:sequence>
</s:complexType>
</s:schema>
</wsdl:types>
<wsdl:message name="LogonSoapIn">
<wsdl:part name="parameters" element="tns:Logon" />
</wsdl:message>
<wsdl:message name="LogonSoapOut">
<wsdl:part name="parameters" element="tns:LogonResponse" />
</wsdl:message>
<wsdl:message name="LogonMessageHeader">
<wsdl:part name="MessageHeader" element="s1:MessageHeader" />
</wsdl:message>
<wsdl:message name="LogonSecurity">
<wsdl:part name="Security" element="s2:Security" />
</wsdl:message>
<wsdl:portType name="SessionCreateSoap">
<wsdl:operation name="Logon">
<wsdl:input message="tns:LogonSoapIn" />
<wsdl:output message="tns:LogonSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SessionCreateSoap" type="tns:SessionCreateSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Logon">
<soap:operation soapAction="http://www.vedaleon.com/webservices/Logon" style="document" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:LogonMessageHeader" part="MessageHeader" use="literal" />
<soap:header message="tns:LogonSecurity" part="Security" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
<soap:header message="tns:LogonMessageHeader" part="MessageHeader" use="literal" />
<soap:header message="tns:LogonSecurity" part="Security" use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="SessionCreateSoap12" type="tns:SessionCreateSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Logon">
<soap12:operation soapAction="http://www.vedaleon.com/webservices/Logon" style="document" />
<wsdl:input>
<soap12:body use="literal" />
<soap12:header message="tns:LogonMessageHeader" part="MessageHeader" use="literal" />
<soap12:header message="tns:LogonSecurity" part="Security" use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
<soap12:header message="tns:LogonMessageHeader" part="MessageHeader" use="literal" />
<soap12:header message="tns:LogonSecurity" part="Security" use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SessionCreate">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Vedaleon Web Services</wsdl:documentation>
<wsdl:port name="SessionCreateSoap" binding="tns:SessionCreateSoap">
<soap:address location="http://USE_ADDRESS_RETURNED_BY_LOCATION_SERVICE/jettaobeapi/SessionCreate.asmx" />
</wsdl:port>
<wsdl:port name="SessionCreateSoap12" binding="tns:SessionCreateSoap12">
<soap12:address location="http://USE_ADDRESS_RETURNED_BY_LOCATION_SERVICE/jettaobeapi/SessionCreate.asmx" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
142 changes: 142 additions & 0 deletions spec/integration/jetairways_spec.rb
@@ -0,0 +1,142 @@
require 'spec_helper'

describe 'Integration with Jetairways\'s SessionCreate Service' do

subject(:client) { Savon.new fixture('wsdl/jetairways') }



let(:service_name) { :SessionCreate }
let(:port_name) { :SessionCreateSoap }

it 'returns a map of services and ports' do
expect(client.services).to eq(
'SessionCreate'=> {
:ports=> {
'SessionCreateSoap'=> {
:type=>'http://schemas.xmlsoap.org/wsdl/soap/',
# symbolic endpoint
:location=>'http://USE_ADDRESS_RETURNED_BY_LOCATION_SERVICE/jettaobeapi/SessionCreate.asmx'
},
'SessionCreateSoap12'=>{
:type=>'http://schemas.xmlsoap.org/wsdl/soap12/',
# symbolic endpoint
:location=>'http://USE_ADDRESS_RETURNED_BY_LOCATION_SERVICE/jettaobeapi/SessionCreate.asmx'
}
}
}
)
end

it 'knows the operations' do
operation = client.operation(service_name, port_name, :Logon)

expect(operation.soap_action).to eq('http://www.vedaleon.com/webservices/Logon')
expect(operation.endpoint).to eq('http://USE_ADDRESS_RETURNED_BY_LOCATION_SERVICE/jettaobeapi/SessionCreate.asmx')

namespace = 'http://www.vedaleon.com/webservices'

expect(operation.body_parts).to eq([
[['Logon'], { namespace: namespace, form: 'qualified', singular: true }]
])
end

# multiple implicit headers. reference: http://www.ibm.com/developerworks/library/ws-tip-headers/index.html
it 'creates an example header' do
operation = client.operation(service_name, port_name, :Logon)

expect(operation.example_header).to eq(
MessageHeader:
{From: {PartyId: [{}], Role: 'string'},
To: {PartyId: [{}], Role: 'string'},
CPAId: 'string',
ConversationId: 'string',
Service: {},
Action: 'string',
MessageData:
{MessageId: 'string',
Timestamp: 'string',
RefToMessageId: 'string',
TimeToLive: 'dateTime'},
DuplicateElimination: {},
Description: [{}],
_id: 's:ID',
_version: 's:string'},
Security:
{UsernameToken:
{Username: 'string',
Password: 'string',
Organization: 'string',
Domain: 'string'},
BinarySecurityToken: 'string'}
)
end

it 'creates an example body' do
operation = client.operation(service_name, port_name, :Logon)

expect(operation.example_body).to eq(
Logon:{}
)
end

it 'creates a request with multiple headers' do
operation = client.operation(service_name, port_name, :Logon)

operation.header =
{
MessageHeader:
{CPAId:"9W",
ConversationId:"1",
Service:{Service:"Create"},
Action:"CreateSession",
MessageData:
{MessageId:"0",
Timestamp:"2014-02-01T12:57:12.000Z"}
},
Security:
{ UsernameToken: {
Username: 'example_user',
Password: 'my_secret',
Organization: 'example_organization'}

}
}
operation.body =
{Logon:{}}

expected = Nokogiri.XML('
<env:Envelope
xmlns:lol0="http://www.ebxml.org/namespaces/messageHeader"
xmlns:lol1="http://schemas.xmlsoap.org/ws/2002/12/secext"
xmlns:lol2="http://www.vedaleon.com/webservices"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<lol0:MessageHeader>
<lol0:CPAId>9W</lol0:CPAId>
<lol0:ConversationId>1</lol0:ConversationId>
<lol0:Service>Create</lol0:Service>
<lol0:Action>CreateSession</lol0:Action>
<lol0:MessageData>
<lol0:MessageId>0</lol0:MessageId>
<lol0:Timestamp>2014-02-01T12:57:12.000Z</lol0:Timestamp>
</lol0:MessageData>
</lol0:MessageHeader>
<lol1:Security>
<lol1:UsernameToken>
<lol1:Username>example_user</lol1:Username>
<lol1:Password>my_secret</lol1:Password>
<Organization>example_organization</Organization>
</lol1:UsernameToken>
</lol1:Security>
</env:Header>
<env:Body>
<lol2:Logon/>
</env:Body>
')

expect(Nokogiri.XML operation.build).
to be_equivalent_to(expected).respecting_element_order
end

end

0 comments on commit f47b5c6

Please sign in to comment.