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 +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
|