lolsoap 0.4.2 → 0.5.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 +6 -0
- data/VERSION +1 -1
- data/lib/lolsoap/envelope.rb +1 -1
- data/lib/lolsoap/wsdl/named_type_reference.rb +6 -5
- data/lib/lolsoap/wsdl/operation.rb +4 -2
- data/lib/lolsoap/wsdl/type.rb +1 -1
- data/lib/lolsoap/wsdl.rb +45 -38
- data/lib/lolsoap/wsdl_parser.rb +29 -45
- data/lolsoap.gemspec +3 -3
- data/test/fixtures/stock_quote.wsdl +4 -4
- data/test/integration/test_envelope.rb +6 -6
- data/test/integration/test_wsdl.rb +3 -3
- data/test/unit/test_envelope.rb +5 -5
- data/test/unit/test_wsdl.rb +43 -47
- data/test/unit/test_wsdl_parser.rb +92 -99
- 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: d15ac33320b9b7a7f32e1fd15e111ba323683c75
|
4
|
+
data.tar.gz: d9fdcb8040c0e9e714b0512f73c69c15ca70d686
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4b2624bb3b81de8109863c618d1c9a11146f2394b908da4ffa1a3737ad9cd624e5a206f14262d23b454f9a1d9576ef1d1bfc3713101f49b020ee76f19f00428
|
7
|
+
data.tar.gz: 62efc9d01ee3e439b115aa9c7eb10c293036d353aa849a999fd9ecfd676c88ae0a483c976b320f1d974dea42923092655716212b4c6d185c24892a96d2019710
|
data/README.md
CHANGED
@@ -114,6 +114,12 @@ Development sponsored by [Loco2](http://loco2.com/).
|
|
114
114
|
|
115
115
|
## Changelog ##
|
116
116
|
|
117
|
+
### 0.5 ###
|
118
|
+
|
119
|
+
* Generate our own namespace prefixes rather than using ones from the
|
120
|
+
WSDL document. This fixes issues with WSDLs that use the same prefix
|
121
|
+
to denote different namespaces in different places.
|
122
|
+
|
117
123
|
### 0.4 ###
|
118
124
|
|
119
125
|
* Don't raise an exception on when a SOAP fault is detected. Whether or
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/lib/lolsoap/envelope.rb
CHANGED
@@ -87,7 +87,7 @@ module LolSoap
|
|
87
87
|
def initialize_doc
|
88
88
|
doc.root = root = doc.create_element('Envelope')
|
89
89
|
|
90
|
-
namespaces = Hash[wsdl.
|
90
|
+
namespaces = Hash[wsdl.namespaces.map { |prefix, uri| [prefix, root.add_namespace(prefix, uri)] }]
|
91
91
|
namespaces[soap_prefix] = root.add_namespace(soap_prefix, soap_namespace)
|
92
92
|
|
93
93
|
@header = doc.create_element 'Header'
|
@@ -1,14 +1,15 @@
|
|
1
1
|
class LolSoap::WSDL
|
2
2
|
class NamedTypeReference
|
3
|
-
attr_reader :name, :wsdl
|
3
|
+
attr_reader :namespace, :name, :wsdl
|
4
4
|
|
5
|
-
def initialize(name, wsdl)
|
6
|
-
@
|
7
|
-
@
|
5
|
+
def initialize(namespace, name, wsdl)
|
6
|
+
@namespace = namespace
|
7
|
+
@name = name
|
8
|
+
@wsdl = wsdl
|
8
9
|
end
|
9
10
|
|
10
11
|
def type
|
11
|
-
wsdl.type(name)
|
12
|
+
wsdl.type(namespace, name)
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
class LolSoap::WSDL
|
2
2
|
class Operation
|
3
|
-
attr_reader :wsdl, :action, :input, :output
|
3
|
+
attr_reader :wsdl, :name, :action, :input, :output
|
4
4
|
|
5
|
-
def initialize(wsdl, action, input, output)
|
5
|
+
def initialize(wsdl, name, action, input, output)
|
6
6
|
@wsdl = wsdl
|
7
|
+
@name = name
|
7
8
|
@action = action
|
8
9
|
@input = input
|
9
10
|
@output = output
|
@@ -11,6 +12,7 @@ class LolSoap::WSDL
|
|
11
12
|
|
12
13
|
def inspect
|
13
14
|
"<#{self.class} " \
|
15
|
+
"name=#{name.inspect} " \
|
14
16
|
"action=#{action.inspect} " \
|
15
17
|
"input=#{input.inspect}>"
|
16
18
|
end
|
data/lib/lolsoap/wsdl/type.rb
CHANGED
data/lib/lolsoap/wsdl.rb
CHANGED
@@ -18,41 +18,37 @@ module LolSoap
|
|
18
18
|
# The SOAP endpoint URL
|
19
19
|
attr_reader :endpoint
|
20
20
|
|
21
|
-
# Hash of
|
22
|
-
attr_reader :namespaces
|
23
|
-
|
24
|
-
# Namespaces used by the types (a subset of #namespaces)
|
25
|
-
attr_reader :type_namespaces
|
26
|
-
|
27
|
-
# Hash of namespace prefixes used in the WSDL document (keys are namespace URIs)
|
21
|
+
# Hash of generated prefixes to namespaces
|
28
22
|
attr_reader :prefixes
|
29
23
|
|
24
|
+
# Hash of namespaces to generated prefixes
|
25
|
+
attr_reader :namespaces
|
26
|
+
|
30
27
|
# The version of SOAP detected.
|
31
28
|
attr_reader :soap_version
|
32
29
|
|
33
30
|
def initialize(parser)
|
34
|
-
@
|
35
|
-
@
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@
|
40
|
-
@soap_version = parser.soap_version
|
31
|
+
@prefixes = generate_prefixes(parser)
|
32
|
+
@namespaces = prefixes.invert
|
33
|
+
@types = load_types(parser)
|
34
|
+
@operations = load_operations(parser)
|
35
|
+
@endpoint = parser.endpoint
|
36
|
+
@soap_version = parser.soap_version
|
41
37
|
end
|
42
38
|
|
43
39
|
# Hash of types declared by the service
|
44
40
|
def types
|
45
|
-
@types.
|
41
|
+
Hash[@types.values.map { |t| [t.name, t] }]
|
46
42
|
end
|
47
43
|
|
48
44
|
# Get a single type, or a NullType if the type doesn't exist
|
49
|
-
def type(name)
|
50
|
-
@types.fetch(name) { NullType.new }
|
45
|
+
def type(namespace, name)
|
46
|
+
@types.fetch([namespace, name]) { NullType.new }
|
51
47
|
end
|
52
48
|
|
53
|
-
# Hash of operations that are
|
49
|
+
# Hash of operations that are supported by the SOAP service
|
54
50
|
def operations
|
55
|
-
@operations.
|
51
|
+
Hash[@operations.values.map { |o| [o.name, o] }]
|
56
52
|
end
|
57
53
|
|
58
54
|
# Get a single operation
|
@@ -60,11 +56,16 @@ module LolSoap
|
|
60
56
|
@operations.fetch(name)
|
61
57
|
end
|
62
58
|
|
59
|
+
# Get the prefix for a namespace
|
60
|
+
def prefix(namespace)
|
61
|
+
prefixes.fetch namespace
|
62
|
+
end
|
63
|
+
|
63
64
|
def inspect
|
64
65
|
"<#{self.class} " \
|
65
|
-
"namespaces=#{
|
66
|
-
"operations=#{
|
67
|
-
"types=#{
|
66
|
+
"namespaces=#{namespaces.inspect} " \
|
67
|
+
"operations=#{operations.inspect} " \
|
68
|
+
"types=#{types.inspect}>"
|
68
69
|
end
|
69
70
|
|
70
71
|
private
|
@@ -72,8 +73,8 @@ module LolSoap
|
|
72
73
|
# @private
|
73
74
|
def load_types(parser)
|
74
75
|
Hash[
|
75
|
-
parser.types.map do |
|
76
|
-
[
|
76
|
+
parser.types.map do |id, type|
|
77
|
+
[id, build_type(type)]
|
77
78
|
end
|
78
79
|
]
|
79
80
|
end
|
@@ -82,27 +83,33 @@ module LolSoap
|
|
82
83
|
def load_operations(parser)
|
83
84
|
Hash[
|
84
85
|
parser.operations.map do |k, op|
|
85
|
-
[k, Operation.new(self, op[:action], message_format(op[:input], parser), message_format(op[:output], parser))]
|
86
|
+
[k, Operation.new(self, k, op[:action], message_format(op[:input], parser), message_format(op[:output], parser))]
|
86
87
|
end
|
87
88
|
]
|
88
89
|
end
|
89
90
|
|
90
91
|
# @private
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
def generate_prefixes(parser)
|
93
|
+
prefixes = {}
|
94
|
+
index = 0
|
95
|
+
|
96
|
+
parser.types.merge(parser.elements).values.each do |el|
|
97
|
+
unless prefixes[el[:namespace]]
|
98
|
+
prefixes[el[:namespace]] = "ns#{index}"
|
99
|
+
index += 1
|
95
100
|
end
|
96
|
-
|
101
|
+
end
|
102
|
+
|
103
|
+
prefixes
|
97
104
|
end
|
98
105
|
|
99
106
|
# @private
|
100
107
|
def build_type(params)
|
101
108
|
Type.new(
|
102
109
|
params[:name],
|
103
|
-
params
|
104
|
-
build_elements(params
|
105
|
-
params
|
110
|
+
prefix(params.fetch(:namespace)),
|
111
|
+
build_elements(params.fetch(:elements)),
|
112
|
+
params.fetch(:attributes)
|
106
113
|
)
|
107
114
|
end
|
108
115
|
|
@@ -120,7 +127,7 @@ module LolSoap
|
|
120
127
|
Element.new(
|
121
128
|
self,
|
122
129
|
params[:name],
|
123
|
-
params[:
|
130
|
+
prefix(params[:namespace]),
|
124
131
|
type_reference(params[:type]),
|
125
132
|
params[:singular]
|
126
133
|
)
|
@@ -128,16 +135,16 @@ module LolSoap
|
|
128
135
|
|
129
136
|
# @private
|
130
137
|
def type_reference(type)
|
131
|
-
if type.
|
132
|
-
NamedTypeReference.new(type, self)
|
138
|
+
if type.is_a?(Array)
|
139
|
+
NamedTypeReference.new(*type, self)
|
133
140
|
else
|
134
|
-
ImmediateTypeReference.new(build_type(type))
|
141
|
+
ImmediateTypeReference.new(type ? build_type(type) : NullType.new)
|
135
142
|
end
|
136
143
|
end
|
137
144
|
|
138
145
|
# @private
|
139
146
|
def message_format(element, parser)
|
140
|
-
build_element(parser.elements
|
147
|
+
build_element(parser.elements.fetch(element))
|
141
148
|
end
|
142
149
|
end
|
143
150
|
end
|
data/lib/lolsoap/wsdl_parser.rb
CHANGED
@@ -5,21 +5,17 @@ module LolSoap
|
|
5
5
|
# @private
|
6
6
|
class WSDLParser
|
7
7
|
class Node
|
8
|
-
attr_reader :parser, :node, :target_namespace, :name, :
|
8
|
+
attr_reader :parser, :node, :target_namespace, :name, :namespace
|
9
9
|
|
10
10
|
def initialize(parser, node, target_namespace)
|
11
11
|
@parser = parser
|
12
12
|
@node = node
|
13
13
|
@target_namespace = target_namespace
|
14
|
-
@
|
14
|
+
@namespace, @name = parser.namespace_and_name(node, node.attr('name').to_s, target_namespace)
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def prefix_and_name(string)
|
22
|
-
parser.prefix_and_name(string, target_namespace)
|
17
|
+
def id
|
18
|
+
[namespace, name]
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
@@ -29,10 +25,11 @@ module LolSoap
|
|
29
25
|
type = Type.new(parser, complex_type, target_namespace)
|
30
26
|
{
|
31
27
|
:elements => type.elements,
|
28
|
+
:namespace => type.namespace,
|
32
29
|
:attributes => type.attributes
|
33
30
|
}
|
34
|
-
|
35
|
-
|
31
|
+
elsif type = node.attr('type')
|
32
|
+
parser.namespace_and_name(node, type, target_namespace)
|
36
33
|
end
|
37
34
|
end
|
38
35
|
|
@@ -72,10 +69,10 @@ module LolSoap
|
|
72
69
|
[
|
73
70
|
element.name,
|
74
71
|
{
|
75
|
-
:name
|
76
|
-
:
|
77
|
-
:type
|
78
|
-
:singular
|
72
|
+
:name => element.name,
|
73
|
+
:namespace => element.namespace,
|
74
|
+
:type => element.type,
|
75
|
+
:singular => element.singular
|
79
76
|
}
|
80
77
|
]
|
81
78
|
end
|
@@ -83,7 +80,9 @@ module LolSoap
|
|
83
80
|
end
|
84
81
|
|
85
82
|
def element_nodes
|
86
|
-
node.xpath('*/xs:element | */*/xs:element | xs:complexContent/xs:extension/*/xs:element | xs:complexContent/xs:extension/*/*/xs:element', parser.ns).map { |el|
|
83
|
+
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)
|
85
|
+
}
|
87
86
|
end
|
88
87
|
|
89
88
|
def parent_elements
|
@@ -112,19 +111,6 @@ module LolSoap
|
|
112
111
|
@doc = doc
|
113
112
|
end
|
114
113
|
|
115
|
-
def namespaces
|
116
|
-
@namespaces ||= begin
|
117
|
-
namespaces = Hash[doc.collect_namespaces.map { |k, v| [k.sub(/^xmlns:/, ''), v] }]
|
118
|
-
namespaces.delete('xmlns')
|
119
|
-
namespaces
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# We invert the hash in a deterministic way so that the results are repeatable.
|
124
|
-
def prefixes
|
125
|
-
@prefixes ||= Hash[namespaces.sort_by { |k, v| k }.uniq { |k, v| v }].invert
|
126
|
-
end
|
127
|
-
|
128
114
|
def endpoint
|
129
115
|
@endpoint ||= CGI.unescape(doc.at_xpath('/d:definitions/d:service/d:port/s:address/@location', ns).to_s)
|
130
116
|
end
|
@@ -138,9 +124,9 @@ module LolSoap
|
|
138
124
|
types = {}
|
139
125
|
each_node('xs:complexType[not(@abstract="true")]') do |node, target_ns|
|
140
126
|
type = Type.new(self, node, target_ns)
|
141
|
-
types[type.
|
127
|
+
types[type.id] = {
|
142
128
|
:name => type.name,
|
143
|
-
:
|
129
|
+
:namespace => type.namespace,
|
144
130
|
:elements => type.elements,
|
145
131
|
:attributes => type.attributes
|
146
132
|
}
|
@@ -150,7 +136,7 @@ module LolSoap
|
|
150
136
|
end
|
151
137
|
|
152
138
|
def type(name)
|
153
|
-
name =
|
139
|
+
name = name.split(":").last
|
154
140
|
if node = doc.at_xpath("//xs:complexType[@name='#{name}']", ns)
|
155
141
|
target_namespace = node.at_xpath('parent::xs:schema/@targetNamespace', ns).to_s
|
156
142
|
Type.new(self, node, target_namespace)
|
@@ -162,10 +148,10 @@ module LolSoap
|
|
162
148
|
elements = {}
|
163
149
|
each_node('xs:element') do |node, target_ns|
|
164
150
|
element = Element.new(self, node, target_ns)
|
165
|
-
elements[element.
|
166
|
-
:name
|
167
|
-
:
|
168
|
-
:type
|
151
|
+
elements[element.id] = {
|
152
|
+
:name => element.name,
|
153
|
+
:namespace => element.namespace,
|
154
|
+
:type => element.type
|
169
155
|
}
|
170
156
|
end
|
171
157
|
elements
|
@@ -176,7 +162,7 @@ module LolSoap
|
|
176
162
|
@messages ||= Hash[
|
177
163
|
doc.xpath('/d:definitions/d:message', ns).map do |msg|
|
178
164
|
element = msg.at_xpath('./d:part/@element', ns).to_s
|
179
|
-
[msg.attribute('name').to_s,
|
165
|
+
[msg.attribute('name').to_s, namespace_and_name(msg, element)]
|
180
166
|
end
|
181
167
|
]
|
182
168
|
end
|
@@ -227,18 +213,16 @@ module LolSoap
|
|
227
213
|
}
|
228
214
|
end
|
229
215
|
|
230
|
-
def
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
# Ensure we always use the same prefix for a given namespace
|
235
|
-
prefix = prefixes.fetch(namespaces.fetch(prefix))
|
216
|
+
def namespace_and_name(node, prefixed_name, default_namespace = nil)
|
217
|
+
if prefixed_name.include? ':'
|
218
|
+
prefix, name = prefixed_name.split(':')
|
219
|
+
namespace = node.namespaces.fetch("xmlns:#{prefix}")
|
236
220
|
else
|
237
|
-
name
|
238
|
-
|
221
|
+
name = prefixed_name
|
222
|
+
namespace = default_namespace
|
239
223
|
end
|
240
224
|
|
241
|
-
[
|
225
|
+
[namespace, name]
|
242
226
|
end
|
243
227
|
|
244
228
|
def each_node(xpath)
|
data/lolsoap.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: lolsoap 0.
|
5
|
+
# stub: lolsoap 0.5.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "lolsoap"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.5.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = ["Jon Leighton"]
|
13
|
-
s.date = "2013-12-
|
13
|
+
s.date = "2013-12-10"
|
14
14
|
s.description = "A library for dealing with SOAP requests and responses. We tear our hair out so you don't have to."
|
15
15
|
s.email = "j@jonathanleighton.com"
|
16
16
|
s.extra_rdoc_files = [
|
@@ -23,11 +23,11 @@
|
|
23
23
|
<element name="TradePrice">
|
24
24
|
<complexType>
|
25
25
|
<all>
|
26
|
-
<element name="
|
26
|
+
<element name="Price" type="xsd3:price"/>
|
27
27
|
</all>
|
28
28
|
</complexType>
|
29
29
|
</element>
|
30
|
-
<element name="tradePriceRequest" type="TradePriceRequest" />
|
30
|
+
<element name="tradePriceRequest" type="xsd1:TradePriceRequest" />
|
31
31
|
<complexType name="xsd1:TradePriceRequest" abstract="false">
|
32
32
|
<complexContent>
|
33
33
|
<extension base="xsd1:BaseRequest">
|
@@ -47,7 +47,7 @@
|
|
47
47
|
</sequence>
|
48
48
|
</complexType>
|
49
49
|
</element>
|
50
|
-
<element name="historicalPriceRequest" type="HistoricalPriceRequest" />
|
50
|
+
<element name="historicalPriceRequest" type="xsd1:HistoricalPriceRequest" />
|
51
51
|
<complexType name="xsd1:HistoricalPriceRequest">
|
52
52
|
<complexContent>
|
53
53
|
<extension base="xsd1:BaseRequest">
|
@@ -87,7 +87,7 @@
|
|
87
87
|
</message>
|
88
88
|
|
89
89
|
<message name="GetLastTradePriceOutput">
|
90
|
-
<part name="body" element="
|
90
|
+
<part name="body" element="xsd1:TradePrice"/>
|
91
91
|
</message>
|
92
92
|
|
93
93
|
<message name="GetHistoricalPriceInput">
|
@@ -10,7 +10,7 @@ module LolSoap
|
|
10
10
|
let(:doc) { subject.doc }
|
11
11
|
|
12
12
|
it 'creates an empty envelope' do
|
13
|
-
body = doc.at_xpath('/soap:Envelope/soap:Body/
|
13
|
+
body = doc.at_xpath('/soap:Envelope/soap:Body/ns0:tradePriceRequest', doc.namespaces)
|
14
14
|
body.wont_equal nil
|
15
15
|
end
|
16
16
|
|
@@ -24,24 +24,24 @@ module LolSoap
|
|
24
24
|
b.id 42
|
25
25
|
end
|
26
26
|
|
27
|
-
el = doc.at_xpath('//
|
27
|
+
el = doc.at_xpath('//ns0:tradePriceRequest/ns0:tickerSymbol', doc.namespaces)
|
28
28
|
el.wont_equal nil
|
29
29
|
el.text.to_s.must_equal 'LOCO2'
|
30
30
|
|
31
|
-
el = doc.at_xpath('//
|
31
|
+
el = doc.at_xpath('//ns0:tradePriceRequest/ns0:specialTickerSymbol/ns1:name', doc.namespaces)
|
32
32
|
el.wont_equal nil
|
33
33
|
el.text.to_s.must_equal 'LOCOLOCOLOCO'
|
34
34
|
|
35
|
-
attr = doc.at_xpath('//
|
35
|
+
attr = doc.at_xpath('//ns0:tradePriceRequest/@id', doc.namespaces)
|
36
36
|
attr.to_s.must_equal "42"
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'creates some header' do
|
40
40
|
subject.header do |h|
|
41
|
-
h['
|
41
|
+
h['ns0'].verySpecialBoolean true
|
42
42
|
end
|
43
43
|
|
44
|
-
el = doc.at_xpath('/soap:Envelope/soap:Header/
|
44
|
+
el = doc.at_xpath('/soap:Envelope/soap:Header/ns0:verySpecialBoolean', doc.namespaces)
|
45
45
|
el.wont_equal nil
|
46
46
|
el.text.to_s.must_equal 'true'
|
47
47
|
end
|
@@ -7,14 +7,14 @@ module LolSoap
|
|
7
7
|
|
8
8
|
it 'should successfully parse a WSDL document' do
|
9
9
|
subject.operations.length.must_equal 2
|
10
|
-
subject.operations
|
10
|
+
subject.operations.fetch('GetLastTradePrice').tap do |o|
|
11
11
|
o.input.name.must_equal 'tradePriceRequest'
|
12
12
|
o.action.must_equal 'http://example.com/GetLastTradePrice'
|
13
13
|
end
|
14
14
|
|
15
15
|
subject.types.length.must_equal 4
|
16
|
-
subject.types
|
17
|
-
t.prefix.must_equal '
|
16
|
+
subject.types.fetch('TradePriceRequest').tap do |t|
|
17
|
+
t.prefix.must_equal 'ns0'
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/test/unit/test_envelope.rb
CHANGED
@@ -5,25 +5,25 @@ module LolSoap
|
|
5
5
|
describe Envelope do
|
6
6
|
let(:wsdl) do
|
7
7
|
OpenStruct.new(
|
8
|
-
:
|
9
|
-
:soap_version
|
8
|
+
:namespaces => { 'ns0' => 'http://example.com/foo' },
|
9
|
+
:soap_version => '1.2'
|
10
10
|
)
|
11
11
|
end
|
12
12
|
|
13
13
|
let(:operation) do
|
14
|
-
OpenStruct.new(:input => OpenStruct.new(:prefix => '
|
14
|
+
OpenStruct.new(:input => OpenStruct.new(:prefix => 'ns0', :name => 'WashHandsRequest'))
|
15
15
|
end
|
16
16
|
|
17
17
|
subject { Envelope.new(wsdl, operation) }
|
18
18
|
|
19
19
|
let(:doc) { subject.doc }
|
20
20
|
let(:header) { doc.at_xpath('/soap:Envelope/soap:Header', doc.namespaces) }
|
21
|
-
let(:input) { doc.at_xpath('/soap:Envelope/soap:Body/
|
21
|
+
let(:input) { doc.at_xpath('/soap:Envelope/soap:Body/ns0:WashHandsRequest', doc.namespaces) }
|
22
22
|
|
23
23
|
it 'has a skeleton SOAP envelope structure when first created' do
|
24
24
|
doc.namespaces.must_equal(
|
25
25
|
'xmlns:soap' => Envelope::SOAP_1_2,
|
26
|
-
'xmlns:
|
26
|
+
'xmlns:ns0' => 'http://example.com/foo'
|
27
27
|
)
|
28
28
|
|
29
29
|
header.wont_equal nil
|
data/test/unit/test_wsdl.rb
CHANGED
@@ -5,6 +5,7 @@ module LolSoap
|
|
5
5
|
describe WSDL do
|
6
6
|
describe 'with a doc that can be parsed' do
|
7
7
|
let(:namespace) { 'http://lolsoap.api/bla' }
|
8
|
+
let(:xs) { "http://www.w3.org/2001/XMLSchema" }
|
8
9
|
|
9
10
|
let(:parser) do
|
10
11
|
OpenStruct.new(
|
@@ -12,70 +13,72 @@ module LolSoap
|
|
12
13
|
:operations => {
|
13
14
|
'washHands' => {
|
14
15
|
:action => 'urn:washHands',
|
15
|
-
:input => '
|
16
|
-
:output => '
|
16
|
+
:input => [namespace, 'brush'],
|
17
|
+
:output => [namespace, 'Color']
|
17
18
|
}
|
18
19
|
},
|
19
20
|
:types => {
|
20
|
-
'
|
21
|
+
[namespace, 'Brush'] => {
|
22
|
+
:name => 'Brush',
|
21
23
|
:elements => {
|
22
24
|
'handleColor' => {
|
23
|
-
:name
|
24
|
-
:
|
25
|
-
:type
|
25
|
+
:name => 'handleColor',
|
26
|
+
:namespace => namespace,
|
27
|
+
:type => {
|
26
28
|
:elements => {
|
27
29
|
'name' => {
|
28
|
-
:name
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:singular => true
|
30
|
+
:name => 'name',
|
31
|
+
:namespace => namespace,
|
32
|
+
:singular => true
|
32
33
|
},
|
33
34
|
'hex' => {
|
34
|
-
:name
|
35
|
-
:
|
36
|
-
:type
|
37
|
-
:singular
|
35
|
+
:name => 'hex',
|
36
|
+
:namespace => namespace,
|
37
|
+
:type => [xs, "string"],
|
38
|
+
:singular => true
|
38
39
|
}
|
39
40
|
},
|
41
|
+
:namespace => namespace,
|
40
42
|
:attributes => []
|
41
43
|
},
|
42
44
|
:singular => true
|
43
45
|
},
|
44
46
|
'age' => {
|
45
|
-
:name
|
46
|
-
:
|
47
|
-
:type
|
48
|
-
:singular
|
47
|
+
:name => 'age',
|
48
|
+
:namespace => namespace,
|
49
|
+
:type => [xs, "int"],
|
50
|
+
:singular => false
|
49
51
|
}
|
50
52
|
},
|
51
53
|
:attributes => ['id'],
|
52
|
-
:
|
54
|
+
:namespace => namespace
|
53
55
|
}
|
54
56
|
},
|
55
57
|
:elements => {
|
56
|
-
'
|
57
|
-
:name
|
58
|
-
:
|
59
|
-
:type
|
58
|
+
[namespace, 'brush'] => {
|
59
|
+
:name => 'brush',
|
60
|
+
:namespace => namespace,
|
61
|
+
:type => [namespace, 'Brush']
|
60
62
|
},
|
61
|
-
'
|
62
|
-
:name
|
63
|
-
:
|
64
|
-
:type
|
63
|
+
[namespace, 'Color'] => {
|
64
|
+
:name => 'Color',
|
65
|
+
:namespace => namespace,
|
66
|
+
:type => {
|
65
67
|
:elements => {
|
66
68
|
'name' => {
|
67
|
-
:name
|
68
|
-
:
|
69
|
-
:type
|
70
|
-
:singular
|
69
|
+
:name => 'name',
|
70
|
+
:namespace => namespace,
|
71
|
+
:type => [xs, "string"],
|
72
|
+
:singular => true
|
71
73
|
},
|
72
74
|
'hex' => {
|
73
|
-
:name
|
74
|
-
:
|
75
|
-
:type
|
76
|
-
:singular
|
75
|
+
:name => 'hex',
|
76
|
+
:namespace => namespace,
|
77
|
+
:type => [xs, "string"],
|
78
|
+
:singular => true
|
77
79
|
}
|
78
80
|
},
|
81
|
+
:namespace => namespace,
|
79
82
|
:attributes => []
|
80
83
|
}
|
81
84
|
}
|
@@ -115,7 +118,7 @@ module LolSoap
|
|
115
118
|
|
116
119
|
describe '#namespaces' do
|
117
120
|
it 'returns a namespaces hash' do
|
118
|
-
subject.namespaces.must_equal({ '
|
121
|
+
subject.namespaces.must_equal({ 'ns0' => namespace })
|
119
122
|
end
|
120
123
|
end
|
121
124
|
|
@@ -123,13 +126,13 @@ module LolSoap
|
|
123
126
|
it 'returns a hash of types' do
|
124
127
|
subject.types.length.must_equal 1
|
125
128
|
|
126
|
-
subject.types['
|
129
|
+
subject.types['Brush'].tap do |t|
|
127
130
|
t.elements.length.must_equal 2
|
128
131
|
t.element('handleColor').type.tap do |type|
|
129
132
|
type.is_a?(WSDL::Type).must_equal true
|
130
133
|
type.elements.keys.sort.must_equal %w(hex name)
|
131
134
|
end
|
132
|
-
t.element('handleColor').prefix.must_equal '
|
135
|
+
t.element('handleColor').prefix.must_equal 'ns0'
|
133
136
|
t.element('handleColor').singular?.must_equal true
|
134
137
|
t.element('age').type.must_equal WSDL::NullType.new
|
135
138
|
t.element('age').singular?.must_equal false
|
@@ -140,18 +143,11 @@ module LolSoap
|
|
140
143
|
|
141
144
|
describe '#type' do
|
142
145
|
it 'returns a single type' do
|
143
|
-
subject.type('
|
146
|
+
subject.type(namespace, 'Brush').must_equal subject.types.fetch('Brush')
|
144
147
|
end
|
145
148
|
|
146
149
|
it 'returns a null object if a type is missing' do
|
147
|
-
subject.type('FooBar').must_equal WSDL::NullType.new
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
describe '#type_namespaces' do
|
152
|
-
it 'returns only the namespaces that are used by types' do
|
153
|
-
parser.namespaces['foo'] = 'bar'
|
154
|
-
subject.type_namespaces.must_equal 'bla' => namespace
|
150
|
+
subject.type(namespace, 'FooBar').must_equal WSDL::NullType.new
|
155
151
|
end
|
156
152
|
end
|
157
153
|
end
|
@@ -7,23 +7,13 @@ module LolSoap
|
|
7
7
|
File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:doc)
|
10
|
+
let(:doc) { Nokogiri::XML(raw_doc) }
|
11
|
+
let(:namespace) { "http://example.com/stockquote.xsd" }
|
12
|
+
let(:namespace2) { "http://example.com/stockquote2.xsd" }
|
13
|
+
let(:xs) { "http://www.w3.org/2001/XMLSchema" }
|
11
14
|
|
12
15
|
subject { WSDLParser.new(doc) }
|
13
16
|
|
14
|
-
describe '#namespaces' do
|
15
|
-
it 'returns the namespaces used' do
|
16
|
-
subject.namespaces.must_equal({
|
17
|
-
'tns' => 'http://example.com/stockquote.wsdl',
|
18
|
-
'xsd1' => 'http://example.com/stockquote.xsd',
|
19
|
-
'xsd2' => 'http://example.com/stockquote2.xsd',
|
20
|
-
'xsd3' => 'http://example.com/stockquote.xsd',
|
21
|
-
'soap' => 'http://schemas.xmlsoap.org/wsdl/soap12/',
|
22
|
-
'xs' => 'http://www.w3.org/2001/XMLSchema'
|
23
|
-
})
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
17
|
describe '#endpoint' do
|
28
18
|
it 'returns the SOAP 1.2 service endpoint' do
|
29
19
|
subject.endpoint.must_equal 'http://example.com/stockquote'
|
@@ -33,63 +23,64 @@ module LolSoap
|
|
33
23
|
describe '#types' do
|
34
24
|
it 'returns the types, with attributes and namespace' do
|
35
25
|
subject.types.must_equal({
|
36
|
-
'
|
37
|
-
:prefix => 'xsd1',
|
26
|
+
[namespace, 'Price'] => {
|
38
27
|
:name => 'Price',
|
28
|
+
:namespace => namespace,
|
39
29
|
:elements => {},
|
40
30
|
:attributes => ['currency']
|
41
31
|
},
|
42
|
-
'
|
43
|
-
:
|
44
|
-
:
|
32
|
+
[namespace, 'TradePriceRequest'] => {
|
33
|
+
:name => 'TradePriceRequest',
|
34
|
+
:namespace => namespace,
|
45
35
|
:elements => {
|
46
36
|
'accountId' => {
|
47
|
-
:name
|
48
|
-
:
|
49
|
-
:type
|
50
|
-
:singular
|
37
|
+
:name => 'accountId',
|
38
|
+
:namespace => namespace,
|
39
|
+
:type => [xs, "string"],
|
40
|
+
:singular => true
|
51
41
|
},
|
52
42
|
'tickerSymbol' => {
|
53
|
-
:name
|
54
|
-
:
|
55
|
-
:type
|
56
|
-
:singular
|
43
|
+
:name => 'tickerSymbol',
|
44
|
+
:namespace => namespace,
|
45
|
+
:type => [xs, "string"],
|
46
|
+
:singular => false
|
57
47
|
},
|
58
48
|
'specialTickerSymbol' => {
|
59
|
-
:name
|
60
|
-
:
|
61
|
-
:type
|
62
|
-
:singular
|
49
|
+
:name => 'specialTickerSymbol',
|
50
|
+
:namespace => namespace,
|
51
|
+
:type => [namespace2, 'TickerSymbol'],
|
52
|
+
:singular => false
|
63
53
|
}
|
64
54
|
},
|
65
55
|
:attributes => ['signature', 'id']
|
66
56
|
},
|
67
|
-
'
|
68
|
-
:
|
69
|
-
:
|
57
|
+
[namespace, 'HistoricalPriceRequest'] => {
|
58
|
+
:name => 'HistoricalPriceRequest',
|
59
|
+
:namespace => namespace,
|
70
60
|
:elements => {
|
71
61
|
'accountId' => {
|
72
|
-
:name
|
73
|
-
:
|
74
|
-
:type
|
75
|
-
:singular
|
62
|
+
:name => 'accountId',
|
63
|
+
:namespace => namespace,
|
64
|
+
:type => [xs, "string"],
|
65
|
+
:singular => true
|
76
66
|
},
|
77
67
|
'dateRange' => {
|
78
|
-
:name
|
79
|
-
:
|
80
|
-
:type
|
81
|
-
:
|
68
|
+
:name => 'dateRange',
|
69
|
+
:namespace => namespace,
|
70
|
+
:type => {
|
71
|
+
:namespace => namespace,
|
72
|
+
:elements => {
|
82
73
|
'startDate' => {
|
83
|
-
:name
|
84
|
-
:
|
85
|
-
:type
|
86
|
-
:singular
|
74
|
+
:name => 'startDate',
|
75
|
+
:namespace => namespace,
|
76
|
+
:type => [xs, "string"],
|
77
|
+
:singular => true
|
87
78
|
},
|
88
79
|
'endDate' => {
|
89
|
-
:name
|
90
|
-
:
|
91
|
-
:type
|
92
|
-
:singular
|
80
|
+
:name => 'endDate',
|
81
|
+
:namespace => namespace,
|
82
|
+
:type => [xs, "string"],
|
83
|
+
:singular => true
|
93
84
|
}
|
94
85
|
},
|
95
86
|
:attributes => []
|
@@ -99,15 +90,15 @@ module LolSoap
|
|
99
90
|
},
|
100
91
|
:attributes => ['signature']
|
101
92
|
},
|
102
|
-
'
|
103
|
-
:
|
104
|
-
:
|
105
|
-
:elements
|
93
|
+
[namespace2, 'TickerSymbol'] => {
|
94
|
+
:name => 'TickerSymbol',
|
95
|
+
:namespace => namespace2,
|
96
|
+
:elements => {
|
106
97
|
'name' => {
|
107
|
-
:name
|
108
|
-
:
|
109
|
-
:type
|
110
|
-
:singular
|
98
|
+
:name => 'name',
|
99
|
+
:namespace => namespace2,
|
100
|
+
:type => [xs, "string"],
|
101
|
+
:singular => true
|
111
102
|
}
|
112
103
|
},
|
113
104
|
:attributes => []
|
@@ -119,47 +110,49 @@ module LolSoap
|
|
119
110
|
describe '#elements' do
|
120
111
|
it 'returns the elements with inline types' do
|
121
112
|
subject.elements.must_equal({
|
122
|
-
"
|
123
|
-
:name
|
124
|
-
:
|
125
|
-
:type
|
113
|
+
[namespace, "tradePriceRequest"] => {
|
114
|
+
:name => "tradePriceRequest",
|
115
|
+
:namespace => namespace,
|
116
|
+
:type => [namespace, "TradePriceRequest"]
|
126
117
|
},
|
127
|
-
"
|
128
|
-
:name
|
129
|
-
:
|
130
|
-
:type
|
118
|
+
[namespace, "TradePrice"] => {
|
119
|
+
:name => "TradePrice",
|
120
|
+
:namespace => namespace,
|
121
|
+
:type => {
|
122
|
+
:namespace => namespace,
|
131
123
|
:elements => {
|
132
|
-
'
|
133
|
-
:name
|
134
|
-
:
|
135
|
-
:type
|
136
|
-
:singular
|
124
|
+
'Price' => {
|
125
|
+
:name => 'Price',
|
126
|
+
:namespace => namespace,
|
127
|
+
:type => [namespace, 'price'],
|
128
|
+
:singular => true
|
137
129
|
}
|
138
130
|
},
|
139
131
|
:attributes => []
|
140
132
|
}
|
141
133
|
},
|
142
|
-
"
|
143
|
-
:name
|
144
|
-
:
|
145
|
-
:type
|
134
|
+
[namespace, "historicalPriceRequest"] => {
|
135
|
+
:name => "historicalPriceRequest",
|
136
|
+
:namespace => namespace,
|
137
|
+
:type => [namespace, "HistoricalPriceRequest"]
|
146
138
|
},
|
147
|
-
"
|
148
|
-
:name
|
149
|
-
:
|
150
|
-
:type
|
139
|
+
[namespace, "HistoricalPrice"] => {
|
140
|
+
:name => "HistoricalPrice",
|
141
|
+
:namespace => namespace,
|
142
|
+
:type => {
|
143
|
+
:namespace => namespace,
|
151
144
|
:elements => {
|
152
145
|
'date' => {
|
153
|
-
:name
|
154
|
-
:
|
155
|
-
:type
|
156
|
-
:singular
|
146
|
+
:name => 'date',
|
147
|
+
:namespace => namespace,
|
148
|
+
:type => [xs, 'date'],
|
149
|
+
:singular => true
|
157
150
|
},
|
158
151
|
'price' => {
|
159
|
-
:name
|
160
|
-
:
|
161
|
-
:type
|
162
|
-
:singular
|
152
|
+
:name => 'price',
|
153
|
+
:namespace => namespace,
|
154
|
+
:type => [xs, 'float'],
|
155
|
+
:singular => true
|
163
156
|
}
|
164
157
|
},
|
165
158
|
:attributes => []
|
@@ -172,10 +165,10 @@ module LolSoap
|
|
172
165
|
describe '#messages' do
|
173
166
|
it 'maps message names to types' do
|
174
167
|
subject.messages.must_equal({
|
175
|
-
'GetLastTradePriceInput' => '
|
176
|
-
'GetLastTradePriceOutput' => '
|
177
|
-
'GetHistoricalPriceInput' => '
|
178
|
-
'GetHistoricalPriceOutput' => '
|
168
|
+
'GetLastTradePriceInput' => [namespace, 'tradePriceRequest'],
|
169
|
+
'GetLastTradePriceOutput' => [namespace, 'TradePrice'],
|
170
|
+
'GetHistoricalPriceInput' => [namespace, 'historicalPriceRequest'],
|
171
|
+
'GetHistoricalPriceOutput' => [namespace, 'HistoricalPrice']
|
179
172
|
})
|
180
173
|
end
|
181
174
|
end
|
@@ -184,12 +177,12 @@ module LolSoap
|
|
184
177
|
it 'is a hash containing input and output types' do
|
185
178
|
subject.port_type_operations.must_equal({
|
186
179
|
'GetLastTradePrice' => {
|
187
|
-
:input => '
|
188
|
-
:output => '
|
180
|
+
:input => [namespace, 'tradePriceRequest'],
|
181
|
+
:output => [namespace, 'TradePrice']
|
189
182
|
},
|
190
183
|
'GetHistoricalPrice' => {
|
191
|
-
:input => '
|
192
|
-
:output => '
|
184
|
+
:input => [namespace, 'historicalPriceRequest'],
|
185
|
+
:output => [namespace, 'HistoricalPrice']
|
193
186
|
}
|
194
187
|
})
|
195
188
|
end
|
@@ -200,13 +193,13 @@ module LolSoap
|
|
200
193
|
subject.operations.must_equal({
|
201
194
|
'GetLastTradePrice' => {
|
202
195
|
:action => 'http://example.com/GetLastTradePrice',
|
203
|
-
:input => '
|
204
|
-
:output => '
|
196
|
+
:input => [namespace, 'tradePriceRequest'],
|
197
|
+
:output => [namespace, 'TradePrice']
|
205
198
|
},
|
206
199
|
'GetHistoricalPrice' => {
|
207
200
|
:action => 'http://example.com/GetHistoricalPrice',
|
208
|
-
:input => '
|
209
|
-
:output => '
|
201
|
+
:input => [namespace, 'historicalPriceRequest'],
|
202
|
+
:output => [namespace, 'HistoricalPrice']
|
210
203
|
}
|
211
204
|
})
|
212
205
|
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.5.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: 2013-12-
|
11
|
+
date: 2013-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -162,3 +162,4 @@ signing_key:
|
|
162
162
|
specification_version: 4
|
163
163
|
summary: A library for dealing with SOAP requests and responses.
|
164
164
|
test_files: []
|
165
|
+
has_rdoc:
|