lolsoap 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3681b9eceff632682da6150a24165ce5602e29f8
4
- data.tar.gz: 6fd0baf415e478dc90541ca8f35ccbbbcf7686ed
3
+ metadata.gz: 581a7842c694777a4af6b960f266eaebbf9e9431
4
+ data.tar.gz: 095e4cd38b1e59af2ff5514a560725f02d21b867
5
5
  SHA512:
6
- metadata.gz: 5f483f1121e5e187591ccad41044bfac1312c049d24486f781e99125c143717527571d2c1c9c8de554198c441ed1d2776f02eb2bbebdf7ef761cf12c4ff484c9
7
- data.tar.gz: aeef28d7bf905ee29f35ce754bbea3754aa0ef2946183cb3f9802d536283ed8e039446a8f84c28e114947da5350a539f18f91a594af61624ac495f6cbe146930
6
+ metadata.gz: d26800dfb89edd5bb9378a280d6be073d57ff8e273d1865b7b5cfde5ab5d83c9d3f757bb71df2213987c57c741947985d76127ea1e629b3c5e4cff963bcbd4e1
7
+ data.tar.gz: 44a08cfc2ecc91f15bcc54a442d37b912fe831d8a1bb013503efc52d392d2e04f2b0a5d4afeb684c28cbced4734048358544bef0b03195b566ee96966c95017e
data/README.md CHANGED
@@ -114,6 +114,16 @@ Development sponsored by [Loco2](http://loco2.com/).
114
114
 
115
115
  ## Changelog ##
116
116
 
117
+ ### 0.7 ###
118
+
119
+ * Added support for element references in type definitions
120
+ * Added support for operations with multipart header/body
121
+ * Added support for multipart messages in WSDL
122
+
123
+ ### 0.6 ###
124
+
125
+ * Support SOAP Header types
126
+
117
127
  ### 0.5 ###
118
128
 
119
129
  * Generate our own namespace prefixes rather than using ones from the
@@ -26,14 +26,14 @@ module LolSoap
26
26
  # b.some 'data'
27
27
  # end
28
28
  def body(klass = Builder)
29
- builder = klass.new(body_content, input_body_type)
29
+ builder = klass.new(body_content, input_body_content_type)
30
30
  yield builder if block_given?
31
31
  builder
32
32
  end
33
33
 
34
34
  # Build the header of the envelope
35
35
  def header(klass = Builder)
36
- builder = klass.new(header_content, input_header_type)
36
+ builder = klass.new(header_content, input_header_content_type)
37
37
  yield builder if block_given?
38
38
  builder
39
39
  end
@@ -54,16 +54,24 @@ module LolSoap
54
54
  input.header
55
55
  end
56
56
 
57
- def input_header_type
58
- input_header && input_header.type
57
+ def input_header_content
58
+ input_header.content
59
+ end
60
+
61
+ def input_header_content_type
62
+ input_header.content_type
59
63
  end
60
64
 
61
65
  def input_body
62
66
  input.body
63
67
  end
64
68
 
65
- def input_body_type
66
- input_body.type
69
+ def input_body_content
70
+ input_body.content
71
+ end
72
+
73
+ def input_body_content_type
74
+ input_body.content_type
67
75
  end
68
76
 
69
77
  def output
@@ -82,8 +90,12 @@ module LolSoap
82
90
  output.body
83
91
  end
84
92
 
85
- def output_body_type
86
- output_body.type
93
+ def output_body_content
94
+ output_body.content
95
+ end
96
+
97
+ def output_body_content_type
98
+ output_body.content_type
87
99
  end
88
100
 
89
101
  def to_xml(options = {})
@@ -105,7 +117,7 @@ module LolSoap
105
117
  private
106
118
 
107
119
  # @private
108
- def header_content; @header_content || @header; end
120
+ def header_content; @header_content; end
109
121
 
110
122
  # @private
111
123
  def body_content; @body_content; end
@@ -117,24 +129,29 @@ module LolSoap
117
129
  namespaces = Hash[wsdl.namespaces.map { |prefix, uri| [prefix, root.add_namespace(prefix, uri)] }]
118
130
  namespaces[soap_prefix] = root.add_namespace(soap_prefix, soap_namespace)
119
131
 
120
- @header = doc.create_element 'Header'
121
- if input_header
122
- @header_content = doc.create_element input_header.name
132
+ @header = doc.create_element input_header.name
133
+ @body = doc.create_element input_body.name
134
+
135
+ [root, @header, @body].each { |el| el.namespace = namespaces[soap_prefix] }
136
+
137
+ if input_header_content
138
+ @header_content = doc.create_element input_header_content.name
139
+ @header_content.namespace = namespaces[input_header_content.prefix]
123
140
  @header << @header_content
124
141
  else
125
- @header_content = nil
142
+ @header_content = @header
126
143
  end
127
144
 
128
- body = doc.create_element 'Body'
129
- @body_content = doc.create_element input_body.name
130
-
131
- [root, @header, body].each { |el| el.namespace = namespaces[soap_prefix] }
132
- @header_content.namespace = namespaces[input_header.prefix] if @header_content
133
- @body_content.namespace = namespaces[input_body.prefix]
145
+ if input_body_content
146
+ @body_content = doc.create_element input_body_content.name
147
+ @body_content.namespace = namespaces[input_body_content.prefix]
148
+ @body << @body_content
149
+ else
150
+ @body_content = @body
151
+ end
134
152
 
135
- body << @body_content
136
153
  root << @header
137
- root << body
154
+ root << @body
138
155
  end
139
156
  end
140
157
  end
@@ -36,12 +36,12 @@ module LolSoap
36
36
 
37
37
  # The type of the element sent in the request body
38
38
  def input_type
39
- envelope.input_body_type
39
+ envelope.input_body_content_type
40
40
  end
41
41
 
42
42
  # The type of the element that will be received in the response body
43
43
  def output_type
44
- envelope.output_body_type
44
+ envelope.output_body_content_type
45
45
  end
46
46
 
47
47
  # The MIME type of the request. This is always application/soap+xml,
@@ -1,3 +1,3 @@
1
1
  module LolSoap
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -0,0 +1,25 @@
1
+ class LolSoap::WSDL
2
+ class OperationIOPart < Element
3
+ def initialize(wsdl, name, type_reference)
4
+ super(wsdl, name, 'soap', type_reference)
5
+ end
6
+
7
+ def single_part?
8
+ type.elements.size == 1
9
+ end
10
+
11
+ def content
12
+ if single_part?
13
+ type.element(type.elements.keys.first)
14
+ end
15
+ end
16
+
17
+ def content_type
18
+ if content
19
+ content.type
20
+ else
21
+ type
22
+ end
23
+ end
24
+ end
25
+ end
data/lib/lolsoap/wsdl.rb CHANGED
@@ -10,6 +10,7 @@ module LolSoap
10
10
  require 'lolsoap/wsdl/null_type'
11
11
  require 'lolsoap/wsdl/element'
12
12
  require 'lolsoap/wsdl/null_element'
13
+ require 'lolsoap/wsdl/operation_io_part'
13
14
 
14
15
  # Create a new instance by parsing a raw string of XML
15
16
  def self.parse(raw)
@@ -114,7 +115,7 @@ module LolSoap
114
115
  def build_type(params)
115
116
  Type.new(
116
117
  params[:name],
117
- prefix(params.fetch(:namespace)),
118
+ params[:prefix] || prefix(params.fetch(:namespace)),
118
119
  build_elements(params.fetch(:elements)),
119
120
  params.fetch(:attributes)
120
121
  )
@@ -152,9 +153,35 @@ module LolSoap
152
153
  # @private
153
154
  def build_io(io, parser)
154
155
  OperationIO.new(
155
- io[:header] && build_element(parser.elements[io[:header]]),
156
- build_element(parser.elements[io[:body]])
156
+ build_io_part('Header', io[:header], parser),
157
+ build_io_part('Body', io[:body], parser)
157
158
  )
158
159
  end
160
+
161
+ # @private
162
+ def build_io_part(name, elements, parser)
163
+ OperationIOPart.new(
164
+ self,
165
+ name,
166
+ type_reference(io_part_type(name, elements, parser))
167
+ )
168
+ end
169
+
170
+ # @private
171
+ def io_part_type(name, elements, parser)
172
+ return unless elements.any?
173
+
174
+ {
175
+ :name => name,
176
+ :prefix => 'soap',
177
+ :elements => Hash[
178
+ elements.map { |el|
179
+ element = parser.elements.fetch(el)
180
+ [element[:name], element]
181
+ }
182
+ ],
183
+ :attributes => []
184
+ }
185
+ end
159
186
  end
160
187
  end
@@ -4,6 +4,8 @@ require 'cgi'
4
4
  module LolSoap
5
5
  # @private
6
6
  class WSDLParser
7
+ class ParseError < StandardError; end
8
+
7
9
  class Node
8
10
  attr_reader :parser, :node, :target_namespace, :name, :namespace
9
11
 
@@ -44,6 +46,31 @@ module LolSoap
44
46
  end
45
47
  end
46
48
 
49
+ class ReferencedElement
50
+ attr_reader :reference, :element
51
+
52
+ def initialize(reference, element)
53
+ @reference = reference
54
+ @element = element
55
+ end
56
+
57
+ def name
58
+ element.name
59
+ end
60
+
61
+ def namespace
62
+ element.namespace
63
+ end
64
+
65
+ def type
66
+ element.type
67
+ end
68
+
69
+ def singular
70
+ reference.singular
71
+ end
72
+ end
73
+
47
74
  class Type < Node
48
75
  def elements
49
76
  parent_elements.merge(own_elements)
@@ -81,7 +108,12 @@ module LolSoap
81
108
 
82
109
  def element_nodes
83
110
  node.xpath('*/xs:element | */*/xs:element | xs:complexContent/xs:extension/*/xs:element | xs:complexContent/xs:extension/*/*/xs:element', parser.ns).map { |el|
84
- Element.new(parser, el, target_namespace)
111
+ element = Element.new(parser, el, target_namespace)
112
+ if reference = el.attribute('ref')
113
+ ReferencedElement.new(element, parser.element(reference.to_s))
114
+ else
115
+ element
116
+ end
85
117
  }
86
118
  end
87
119
 
@@ -115,33 +147,61 @@ module LolSoap
115
147
  end
116
148
 
117
149
  def input
118
- @input ||= OperationIO.new(
119
- header(:input),
120
- port_type_operation[:input]
121
- )
150
+ @input ||= operation_io(:input)
122
151
  end
123
152
 
124
153
  def output
125
- @output ||= OperationIO.new(
126
- header(:output),
127
- port_type_operation[:output]
128
- )
154
+ @output ||= operation_io(:output)
129
155
  end
130
156
 
131
- private
132
-
133
157
  def port_type_operation
134
158
  parser.port_type_operations.fetch(name)
135
159
  end
136
160
 
137
- def header(direction)
138
- if msg = node.at_xpath("./d:#{direction}/s:header/@message", parser.ns)
139
- parser.messages.fetch(msg.to_s.split(':').last)
140
- end
161
+ private
162
+
163
+ def operation_io(direction)
164
+ OperationIO.new(parser, self, node.at_xpath("d:#{direction}", parser.ns))
141
165
  end
142
166
  end
143
167
 
144
- class OperationIO < Struct.new(:header, :body)
168
+ class OperationIO < Struct.new(:parser, :operation, :node)
169
+ def name
170
+ node.name
171
+ end
172
+
173
+ def header
174
+ @header ||= part_elements(:header)
175
+ end
176
+
177
+ def body
178
+ @body ||= part_elements(:body)
179
+ end
180
+
181
+ private
182
+
183
+ def operation_message
184
+ operation.port_type_operation[name.to_sym]
185
+ end
186
+
187
+ def part_elements(name)
188
+ nodes = node.xpath("s:#{name}", parser.ns)
189
+ return [] unless nodes
190
+
191
+ nodes.map { |node|
192
+ parts = parser.messages.fetch((node['message'] || operation_message).to_s.split(':').last)
193
+
194
+ parts.fetch(node['parts'] || node['part']) do |part_name|
195
+ if parts.size == 1
196
+ if name == :body
197
+ parts.values.first
198
+ end
199
+ else
200
+ raise ParseError, "Can't determine which part of #{message_name} to use as #{operation.name} #{self.name} #{name}"
201
+ end
202
+ end
203
+ }.compact
204
+ end
145
205
  end
146
206
 
147
207
  SOAP_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/'
@@ -182,11 +242,7 @@ module LolSoap
182
242
  end
183
243
 
184
244
  def type(name)
185
- name = name.split(":").last
186
- if node = doc.at_xpath("//xs:complexType[@name='#{name}']", ns)
187
- target_namespace = node.at_xpath('parent::xs:schema/@targetNamespace', ns).to_s
188
- Type.new(self, node, target_namespace)
189
- end
245
+ find_node name, Type, 'complexType'
190
246
  end
191
247
 
192
248
  def elements
@@ -204,23 +260,38 @@ module LolSoap
204
260
  end
205
261
  end
206
262
 
263
+ def element(name)
264
+ find_node name, Element, 'element'
265
+ end
266
+
207
267
  def messages
208
268
  @messages ||= Hash[
209
- doc.xpath('/d:definitions/d:message', ns).map do |msg|
210
- part = msg.at_xpath("d:part", ns)
211
- [msg.attribute('name').to_s, namespace_and_name(part, part['element'])]
212
- end
269
+ doc.xpath('/d:definitions/d:message', ns).map { |msg|
270
+ [
271
+ msg.attribute('name').to_s,
272
+ Hash[
273
+ msg.xpath('d:part', ns).map { |part|
274
+ [
275
+ part.attribute('name').to_s,
276
+ namespace_and_name(part, part['element'])
277
+ ]
278
+ }
279
+ ]
280
+ ]
281
+ }
213
282
  ]
214
283
  end
215
284
 
216
285
  def port_type_operations
217
286
  @port_type_operations ||= Hash[
218
287
  doc.xpath('/d:definitions/d:portType/d:operation', ns).map do |op|
219
- input = op.at_xpath('./d:input/@message', ns).to_s.split(':').last
220
- output = op.at_xpath('./d:output/@message', ns).to_s.split(':').last
221
- name = op.attribute('name').to_s
222
-
223
- [name, { :input => messages.fetch(input), :output => messages.fetch(output) }]
288
+ [
289
+ op.attribute('name').to_s,
290
+ {
291
+ :input => op.at_xpath('./d:input/@message', ns).to_s,
292
+ :output => op.at_xpath('./d:output/@message', ns).to_s
293
+ }
294
+ ]
224
295
  end
225
296
  ]
226
297
  end
@@ -285,6 +356,13 @@ module LolSoap
285
356
  end
286
357
  end
287
358
  end
359
+
360
+ def find_node(name, node_class, selector)
361
+ name = name.split(":").last
362
+ if node = doc.at_xpath("//xs:#{selector}[@name='#{name}']", ns)
363
+ target_namespace = node.at_xpath('parent::xs:schema/@targetNamespace', ns).to_s
364
+ node_class.new(self, node, target_namespace)
365
+ end
366
+ end
288
367
  end
289
368
  end
290
-
@@ -27,19 +27,25 @@
27
27
  </all>
28
28
  </complexType>
29
29
  </element>
30
- <element name="tradePriceRequestHeader">
30
+ <element name="specialTickerSymbol" type="xsd2:TickerSymbol"/>
31
+ <element name="authentication">
31
32
  <sequence>
32
33
  <element name="username" type="xs:string"/>
33
34
  <element name="password" type="xs:string"/>
34
35
  </sequence>
35
36
  </element>
37
+ <element name="tradePriceRequestHeader">
38
+ <sequence>
39
+ <element name="requestID" type="xs:string"/>
40
+ </sequence>
41
+ </element>
36
42
  <element name="tradePriceRequest" type="xsd1:TradePriceRequest" />
37
43
  <complexType name="xsd1:TradePriceRequest" abstract="false">
38
44
  <complexContent>
39
45
  <extension base="xsd1:BaseRequest">
40
46
  <sequence>
41
47
  <element name="tickerSymbol" type="xs:string" maxOccurs="5"/>
42
- <element name="specialTickerSymbol" type="xsd2:TickerSymbol" maxOccurs="unbounded"/>
48
+ <element ref="tns:specialTickerSymbol" maxOccurs="unbounded"/>
43
49
  </sequence>
44
50
  <attribute name="id" type="xs:string"/>
45
51
  </extension>
@@ -90,9 +96,11 @@
90
96
 
91
97
  <message name="GetLastTradePriceInputHeader">
92
98
  <part name="header" element="xsd1:tradePriceRequestHeader"/>
99
+ <part name="header2" element="xsd1:authentication"/>
93
100
  </message>
94
101
 
95
102
  <message name="GetLastTradePriceInput">
103
+ <part name="foo" xmlns:foo="http://example.com/stockquote.xsd" element="xs:string"/>
96
104
  <part name="body" xmlns:foo="http://example.com/stockquote.xsd" element="foo:tradePriceRequest"/>
97
105
  </message>
98
106
 
@@ -124,8 +132,9 @@
124
132
  <operation name="GetLastTradePrice">
125
133
  <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
126
134
  <input>
127
- <soap:header use="literal" message="GetLastTradePriceInputHeader" />
128
- <soap:body use="literal"/>
135
+ <soap:header use="literal" message="GetLastTradePriceInputHeader" part="header" />
136
+ <soap:header use="literal" message="GetLastTradePriceInputHeader" part="header2" />
137
+ <soap:body use="literal" parts="body"/>
129
138
  </input>
130
139
  <output>
131
140
  <soap:body use="literal"/>
@@ -37,11 +37,13 @@ module LolSoap
37
37
  end
38
38
 
39
39
  it 'creates some header' do
40
- subject.header do |h|
41
- h['ns0'].username 'LOCO2'
40
+ subject.header do |header|
41
+ header.authentication do |auth|
42
+ auth['ns0'].username 'LOCO2'
43
+ end
42
44
  end
43
45
 
44
- el = doc.at_xpath('/soap:Envelope/soap:Header/ns0:tradePriceRequestHeader/ns0:username', doc.namespaces)
46
+ el = doc.at_xpath('/soap:Envelope/soap:Header/ns0:authentication/ns0:username', doc.namespaces)
45
47
  el.wont_equal nil
46
48
  el.text.to_s.must_equal 'LOCO2'
47
49
  end
@@ -8,14 +8,24 @@ module LolSoap
8
8
  it 'should successfully parse a WSDL document' do
9
9
  subject.operations.length.must_equal 2
10
10
  subject.operations.fetch('GetLastTradePrice').tap do |o|
11
- o.input.header.name.must_equal 'tradePriceRequestHeader'
12
- o.input.body.name.must_equal 'tradePriceRequest'
11
+ o.input.header.tap do |header|
12
+ header.name.must_equal 'Header'
13
+ header.content.must_equal nil
14
+ header.content_type.elements.keys.size.must_equal 2
15
+ header.content_type.elements.keys.first.must_equal 'tradePriceRequestHeader'
16
+ header.content_type.elements.keys.last.must_equal 'authentication'
17
+ end
18
+ o.input.body.name.must_equal 'Body'
19
+ o.input.body.content.name.must_equal 'tradePriceRequest'
13
20
  o.action.must_equal 'http://example.com/GetLastTradePrice'
14
21
  end
15
22
 
16
23
  subject.operations.fetch('GetHistoricalPrice').tap do |o|
17
- o.input.header.must_equal nil
18
- o.input.body.name.must_equal 'historicalPriceRequest'
24
+ o.input.header.name.must_equal 'Header'
25
+ o.input.header.content.must_equal nil
26
+ o.input.header.content_type.class.must_equal WSDL::NullType
27
+ o.input.body.name.must_equal 'Body'
28
+ o.input.body.content.name.must_equal 'historicalPriceRequest'
19
29
  end
20
30
 
21
31
  subject.types.length.must_equal 4
@@ -11,7 +11,15 @@ module LolSoap
11
11
  end
12
12
 
13
13
  let(:operation) do
14
- OpenStruct.new(:input => OpenStruct.new(:body => OpenStruct.new(:prefix => 'ns0', :name => 'WashHandsRequest')))
14
+ OpenStruct.new(
15
+ :input => OpenStruct.new(
16
+ :header => OpenStruct.new(:name => 'Header'),
17
+ :body => OpenStruct.new(
18
+ :name => 'Body',
19
+ :content => OpenStruct.new(:prefix => 'ns0', :name => 'WashHandsRequest')
20
+ )
21
+ )
22
+ )
15
23
  end
16
24
 
17
25
  subject { Envelope.new(wsdl, operation) }
@@ -44,5 +44,13 @@ module LolSoap
44
44
  subject.mime.must_equal 'text/xml'
45
45
  end
46
46
  end
47
+
48
+ describe '#output_type' do
49
+ it 'returns output body content type' do
50
+ content_type = Object.new
51
+ envelope.output_body_content_type = content_type
52
+ subject.output_type.must_equal content_type
53
+ end
54
+ end
47
55
  end
48
56
  end
@@ -4,7 +4,14 @@ require 'lolsoap/response'
4
4
 
5
5
  module LolSoap
6
6
  describe Response do
7
- let(:request) { OpenStruct.new(:soap_namespace => Envelope::SOAP_1_2, :soap_version => '1.2', :output => Object.new) }
7
+ let(:request) {
8
+ OpenStruct.new(
9
+ :soap_namespace => Envelope::SOAP_1_2,
10
+ :soap_version => '1.2',
11
+ :output_type => Object.new
12
+ )
13
+ }
14
+
8
15
  let(:doc) { Nokogiri::XML(File.read(TEST_ROOT + '/fixtures/stock_quote_response.xml')) }
9
16
 
10
17
  subject { Response.new(request, doc) }
@@ -25,7 +32,7 @@ module LolSoap
25
32
  it 'builds a hash from the body node' do
26
33
  builder = OpenStruct.new(:output => Object.new)
27
34
  builder_klass = MiniTest::Mock.new
28
- builder_klass.expect(:new, builder, [subject.body, request.output])
35
+ builder_klass.expect(:new, builder, [subject.body, request.output_type])
29
36
 
30
37
  subject.body_hash(builder_klass).must_equal builder.output
31
38
  end
@@ -13,8 +13,14 @@ module LolSoap
13
13
  :operations => {
14
14
  'washHands' => {
15
15
  :action => 'urn:washHands',
16
- :input => { :body => [namespace, 'brush'] },
17
- :output => { :body => [namespace, 'Color'] }
16
+ :input => {
17
+ :header => [],
18
+ :body => [[namespace, 'brush']]
19
+ },
20
+ :output => {
21
+ :header => [],
22
+ :body => [[namespace, 'Color']]
23
+ }
18
24
  }
19
25
  },
20
26
  :types => {
@@ -94,10 +100,35 @@ module LolSoap
94
100
  subject.operations['washHands'].tap do |op|
95
101
  op.wsdl.must_equal subject
96
102
  op.action.must_equal 'urn:washHands'
97
- op.input.body.name.must_equal 'brush'
98
- op.output.tap do |output|
99
- output.body.is_a?(WSDL::Element).must_equal(true)
100
- output.body.type.elements.keys.sort.must_equal %w(hex name)
103
+
104
+ op.input.header.tap do |header|
105
+ header.is_a?(WSDL::OperationIOPart).must_equal(true)
106
+ header.name.must_equal 'Header'
107
+ header.content.must_equal nil
108
+ end
109
+
110
+ op.input.body.tap do |body|
111
+ body.is_a?(WSDL::OperationIOPart).must_equal(true)
112
+ body.name.must_equal 'Body'
113
+ body.content.is_a?(WSDL::Element).must_equal(true)
114
+ body.content.name.must_equal 'brush'
115
+ end
116
+
117
+ op.output.header.tap do |header|
118
+ header.is_a?(WSDL::OperationIOPart).must_equal(true)
119
+ header.name.must_equal 'Header'
120
+ header.content.must_equal nil
121
+ end
122
+
123
+ op.output.body.tap do |body|
124
+ body.is_a?(WSDL::OperationIOPart).must_equal(true)
125
+ body.name.must_equal 'Body'
126
+
127
+ body.content.tap do |content|
128
+ content.is_a?(WSDL::Element).must_equal(true)
129
+ content.name.must_equal 'Color'
130
+ content.type.elements.keys.sort.must_equal %w(hex name)
131
+ end
101
132
  end
102
133
  end
103
134
  end
@@ -110,6 +110,11 @@ module LolSoap
110
110
  describe '#elements' do
111
111
  it 'returns the elements with inline types' do
112
112
  subject.elements.must_equal({
113
+ [namespace, "authentication"] => {
114
+ :name => "authentication",
115
+ :namespace => namespace,
116
+ :type => nil
117
+ },
113
118
  [namespace, "tradePriceRequestHeader"] => {
114
119
  :name => "tradePriceRequestHeader",
115
120
  :namespace => namespace,
@@ -136,6 +141,11 @@ module LolSoap
136
141
  :attributes => []
137
142
  }
138
143
  },
144
+ [namespace, "specialTickerSymbol"] => {
145
+ :name => "specialTickerSymbol",
146
+ :namespace => namespace,
147
+ :type => [namespace2, 'TickerSymbol']
148
+ },
139
149
  [namespace, "historicalPriceRequest"] => {
140
150
  :name => "historicalPriceRequest",
141
151
  :namespace => namespace,
@@ -168,47 +178,71 @@ module LolSoap
168
178
  end
169
179
 
170
180
  describe '#messages' do
171
- it 'maps message names to types' do
181
+ it 'maps message names to part names and corresponding types' do
172
182
  subject.messages.must_equal({
173
- 'GetLastTradePriceInputHeader' => [namespace, 'tradePriceRequestHeader'],
174
- 'GetLastTradePriceInput' => [namespace, 'tradePriceRequest'],
175
- 'GetLastTradePriceOutput' => [namespace, 'TradePrice'],
176
- 'GetHistoricalPriceInput' => [namespace, 'historicalPriceRequest'],
177
- 'GetHistoricalPriceOutput' => [namespace, 'HistoricalPrice']
183
+ 'GetLastTradePriceInputHeader' => {
184
+ 'header' => [namespace, 'tradePriceRequestHeader'],
185
+ 'header2' => [namespace, 'authentication']
186
+ },
187
+ 'GetLastTradePriceInput' => {
188
+ 'foo' => [xs, 'string'],
189
+ 'body' => [namespace, 'tradePriceRequest']
190
+ },
191
+ 'GetLastTradePriceOutput' => {
192
+ 'body' => [namespace, 'TradePrice']
193
+ },
194
+ 'GetHistoricalPriceInput' => {
195
+ 'body' => [namespace, 'historicalPriceRequest']
196
+ },
197
+ 'GetHistoricalPriceOutput' => {
198
+ 'body' => [namespace, 'HistoricalPrice']
199
+ }
178
200
  })
179
201
  end
180
202
  end
181
203
 
182
204
  describe '#port_type_operations' do
183
- it 'is a hash containing input and output types' do
205
+ it 'maps operations to messages' do
184
206
  subject.port_type_operations.must_equal({
185
207
  'GetLastTradePrice' => {
186
- :input => [namespace, 'tradePriceRequest'],
187
- :output => [namespace, 'TradePrice']
208
+ :input => 'tns:GetLastTradePriceInput',
209
+ :output => 'tns:GetLastTradePriceOutput',
188
210
  },
189
211
  'GetHistoricalPrice' => {
190
- :input => [namespace, 'historicalPriceRequest'],
191
- :output => [namespace, 'HistoricalPrice']
212
+ :input => 'tns:GetHistoricalPriceInput',
213
+ :output => 'tns:GetHistoricalPriceOutput'
192
214
  }
193
215
  })
194
216
  end
195
217
  end
196
218
 
197
219
  describe '#operations' do
198
- it 'is a hash of operations with their action and input type' do
220
+ it 'maps operations to actions, input and output parts' do
199
221
  subject.operations.must_equal({
200
222
  'GetLastTradePrice' => {
201
223
  :action => 'http://example.com/GetLastTradePrice',
202
224
  :input => {
203
- header: [namespace, 'tradePriceRequestHeader'],
204
- body: [namespace, 'tradePriceRequest']
225
+ header: [
226
+ [namespace, 'tradePriceRequestHeader'],
227
+ [namespace, 'authentication']
228
+ ],
229
+ body: [[namespace, 'tradePriceRequest']]
205
230
  },
206
- :output => { header: nil, body: [namespace, 'TradePrice'] }
231
+ :output => {
232
+ header: [],
233
+ body: [[namespace, 'TradePrice']]
234
+ }
207
235
  },
208
236
  'GetHistoricalPrice' => {
209
237
  :action => 'http://example.com/GetHistoricalPrice',
210
- :input => { header: nil, body: [namespace, 'historicalPriceRequest'] },
211
- :output => { header: nil, body: [namespace, 'HistoricalPrice'] }
238
+ :input => {
239
+ header: [],
240
+ body: [[namespace, 'historicalPriceRequest']]
241
+ },
242
+ :output => {
243
+ header: [],
244
+ body: [[namespace, 'HistoricalPrice']]
245
+ }
212
246
  }
213
247
  })
214
248
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lolsoap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Leighton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-12 00:00:00.000000000 Z
11
+ date: 2015-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -112,6 +112,7 @@ files:
112
112
  - lib/lolsoap/wsdl/null_type.rb
113
113
  - lib/lolsoap/wsdl/operation.rb
114
114
  - lib/lolsoap/wsdl/operation_io.rb
115
+ - lib/lolsoap/wsdl/operation_io_part.rb
115
116
  - lib/lolsoap/wsdl/type.rb
116
117
  - lib/lolsoap/wsdl_parser.rb
117
118
  - lolsoap.gemspec