lolsoap 0.6.1 → 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.
- checksums.yaml +4 -4
- data/README.md +10 -0
- data/lib/lolsoap/envelope.rb +38 -21
- data/lib/lolsoap/request.rb +2 -2
- data/lib/lolsoap/version.rb +1 -1
- data/lib/lolsoap/wsdl/operation_io_part.rb +25 -0
- data/lib/lolsoap/wsdl.rb +30 -3
- data/lib/lolsoap/wsdl_parser.rb +109 -31
- data/test/fixtures/stock_quote.wsdl +13 -4
- data/test/integration/test_envelope.rb +5 -3
- data/test/integration/test_wsdl.rb +14 -4
- data/test/unit/test_envelope.rb +9 -1
- data/test/unit/test_request.rb +8 -0
- data/test/unit/test_response.rb +9 -2
- data/test/unit/test_wsdl.rb +37 -6
- data/test/unit/test_wsdl_parser.rb +51 -17
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 581a7842c694777a4af6b960f266eaebbf9e9431
|
4
|
+
data.tar.gz: 095e4cd38b1e59af2ff5514a560725f02d21b867
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/lolsoap/envelope.rb
CHANGED
@@ -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,
|
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,
|
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
|
58
|
-
input_header
|
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
|
66
|
-
input_body.
|
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
|
86
|
-
output_body.
|
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
|
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
|
121
|
-
|
122
|
-
|
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 =
|
142
|
+
@header_content = @header
|
126
143
|
end
|
127
144
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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
|
data/lib/lolsoap/request.rb
CHANGED
@@ -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.
|
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.
|
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,
|
data/lib/lolsoap/version.rb
CHANGED
@@ -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]
|
156
|
-
|
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
|
data/lib/lolsoap/wsdl_parser.rb
CHANGED
@@ -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 ||=
|
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 ||=
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
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(:
|
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
|
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
|
210
|
-
|
211
|
-
|
212
|
-
|
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
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
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="
|
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
|
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:
|
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 |
|
41
|
-
|
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:
|
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.
|
12
|
-
|
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
|
18
|
-
o.input.
|
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
|
data/test/unit/test_envelope.rb
CHANGED
@@ -11,7 +11,15 @@ module LolSoap
|
|
11
11
|
end
|
12
12
|
|
13
13
|
let(:operation) do
|
14
|
-
OpenStruct.new(
|
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) }
|
data/test/unit/test_request.rb
CHANGED
@@ -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
|
data/test/unit/test_response.rb
CHANGED
@@ -4,7 +4,14 @@ require 'lolsoap/response'
|
|
4
4
|
|
5
5
|
module LolSoap
|
6
6
|
describe Response do
|
7
|
-
let(:request) {
|
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.
|
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
|
data/test/unit/test_wsdl.rb
CHANGED
@@ -13,8 +13,14 @@ module LolSoap
|
|
13
13
|
:operations => {
|
14
14
|
'washHands' => {
|
15
15
|
:action => 'urn:washHands',
|
16
|
-
:input => {
|
17
|
-
|
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
|
-
|
98
|
-
op.
|
99
|
-
|
100
|
-
|
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' =>
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
'
|
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 '
|
205
|
+
it 'maps operations to messages' do
|
184
206
|
subject.port_type_operations.must_equal({
|
185
207
|
'GetLastTradePrice' => {
|
186
|
-
:input =>
|
187
|
-
:output =>
|
208
|
+
:input => 'tns:GetLastTradePriceInput',
|
209
|
+
:output => 'tns:GetLastTradePriceOutput',
|
188
210
|
},
|
189
211
|
'GetHistoricalPrice' => {
|
190
|
-
:input =>
|
191
|
-
:output =>
|
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 '
|
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: [
|
204
|
-
|
225
|
+
header: [
|
226
|
+
[namespace, 'tradePriceRequestHeader'],
|
227
|
+
[namespace, 'authentication']
|
228
|
+
],
|
229
|
+
body: [[namespace, 'tradePriceRequest']]
|
205
230
|
},
|
206
|
-
:output => {
|
231
|
+
:output => {
|
232
|
+
header: [],
|
233
|
+
body: [[namespace, 'TradePrice']]
|
234
|
+
}
|
207
235
|
},
|
208
236
|
'GetHistoricalPrice' => {
|
209
237
|
:action => 'http://example.com/GetHistoricalPrice',
|
210
|
-
:input => {
|
211
|
-
|
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.
|
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-
|
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
|