lolsoap 0.2.0 → 0.3.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.
- data/VERSION +1 -1
- data/lib/lolsoap/builder.rb +5 -1
- data/lib/lolsoap/envelope.rb +16 -8
- data/lib/lolsoap/wsdl.rb +69 -32
- data/lib/lolsoap/wsdl/element.rb +15 -10
- data/lib/lolsoap/wsdl/immediate_type_reference.rb +9 -0
- data/lib/lolsoap/wsdl/named_type_reference.rb +14 -0
- data/lib/lolsoap/wsdl/type.rb +9 -1
- data/lib/lolsoap/wsdl_parser.rb +107 -24
- data/lolsoap.gemspec +4 -2
- data/test/fixtures/stock_quote.wsdl +62 -5
- data/test/integration/test_envelope.rb +4 -4
- data/test/integration/test_wsdl.rb +3 -3
- data/test/unit/test_builder.rb +11 -3
- data/test/unit/test_envelope.rb +3 -3
- data/test/unit/test_wsdl.rb +61 -26
- data/test/unit/test_wsdl_parser.rb +110 -10
- data/test/unit/wsdl/test_element.rb +10 -7
- metadata +5 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/lolsoap/builder.rb
CHANGED
@@ -52,13 +52,17 @@ module LolSoap
|
|
52
52
|
# Add a tag manually, rather than through method_missing. This is so you can still
|
53
53
|
# add tags for the very small number of tags that are also existing methods.
|
54
54
|
def __tag__(name, *args, &block)
|
55
|
-
__prefixed_tag__(@type.
|
55
|
+
__prefixed_tag__(@type.element_prefix(name.to_s), @type.sub_type(name.to_s), name, *args, &block)
|
56
56
|
end
|
57
57
|
|
58
58
|
def __attribute__(name, value)
|
59
59
|
@node[name.to_s] = value.to_s
|
60
60
|
end
|
61
61
|
|
62
|
+
def __content__(value)
|
63
|
+
@node.content = value
|
64
|
+
end
|
65
|
+
|
62
66
|
# @private
|
63
67
|
def __prefixed_tag__(prefix, sub_type, name, *args)
|
64
68
|
sub_node = @node.document.create_element(name.to_s, *args)
|
data/lib/lolsoap/envelope.rb
CHANGED
@@ -26,7 +26,7 @@ module LolSoap
|
|
26
26
|
# b.some 'data'
|
27
27
|
# end
|
28
28
|
def body(klass = Builder)
|
29
|
-
builder = klass.new(
|
29
|
+
builder = klass.new(content, input_type)
|
30
30
|
yield builder if block_given?
|
31
31
|
builder
|
32
32
|
end
|
@@ -46,14 +46,22 @@ module LolSoap
|
|
46
46
|
operation.action
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
49
|
+
def input
|
50
50
|
operation.input
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
53
|
+
def input_type
|
54
|
+
input.type
|
55
|
+
end
|
56
|
+
|
57
|
+
def output
|
54
58
|
operation.output
|
55
59
|
end
|
56
60
|
|
61
|
+
def output_type
|
62
|
+
output.type
|
63
|
+
end
|
64
|
+
|
57
65
|
def to_xml(options = {})
|
58
66
|
doc.to_xml(options)
|
59
67
|
end
|
@@ -73,7 +81,7 @@ module LolSoap
|
|
73
81
|
private
|
74
82
|
|
75
83
|
# @private
|
76
|
-
def
|
84
|
+
def content; @content; end
|
77
85
|
|
78
86
|
# @private
|
79
87
|
def initialize_doc
|
@@ -84,13 +92,13 @@ module LolSoap
|
|
84
92
|
|
85
93
|
@header = doc.create_element 'Header'
|
86
94
|
|
87
|
-
@body
|
88
|
-
@
|
95
|
+
@body = doc.create_element 'Body'
|
96
|
+
@content = doc.create_element input.name
|
89
97
|
|
90
98
|
[root, @header, @body].each { |el| el.namespace = namespaces[soap_prefix] }
|
91
|
-
@
|
99
|
+
@content.namespace = namespaces[input.prefix]
|
92
100
|
|
93
|
-
@body << @
|
101
|
+
@body << @content
|
94
102
|
root << @header
|
95
103
|
root << @body
|
96
104
|
end
|
data/lib/lolsoap/wsdl.rb
CHANGED
@@ -4,6 +4,8 @@ module LolSoap
|
|
4
4
|
class WSDL
|
5
5
|
require 'lolsoap/wsdl/operation'
|
6
6
|
require 'lolsoap/wsdl/type'
|
7
|
+
require 'lolsoap/wsdl/named_type_reference'
|
8
|
+
require 'lolsoap/wsdl/immediate_type_reference'
|
7
9
|
require 'lolsoap/wsdl/null_type'
|
8
10
|
require 'lolsoap/wsdl/element'
|
9
11
|
require 'lolsoap/wsdl/null_element'
|
@@ -19,6 +21,9 @@ module LolSoap
|
|
19
21
|
# Hash of namespaces used in the WSDL document (keys are prefixes)
|
20
22
|
attr_reader :namespaces
|
21
23
|
|
24
|
+
# Namespaces used by the types (a subset of #namespaces)
|
25
|
+
attr_reader :type_namespaces
|
26
|
+
|
22
27
|
# Hash of namespace prefixes used in the WSDL document (keys are namespace URIs)
|
23
28
|
attr_reader :prefixes
|
24
29
|
|
@@ -26,22 +31,13 @@ module LolSoap
|
|
26
31
|
attr_reader :soap_version
|
27
32
|
|
28
33
|
def initialize(parser)
|
29
|
-
@types
|
30
|
-
@operations
|
31
|
-
@endpoint
|
32
|
-
@namespaces
|
33
|
-
@
|
34
|
-
@
|
35
|
-
|
36
|
-
|
37
|
-
# Hash of operations that are supports by the SOAP service
|
38
|
-
def operations
|
39
|
-
@operations.dup
|
40
|
-
end
|
41
|
-
|
42
|
-
# Get a single operation
|
43
|
-
def operation(name)
|
44
|
-
@operations.fetch(name)
|
34
|
+
@types = load_types(parser)
|
35
|
+
@operations = load_operations(parser)
|
36
|
+
@endpoint = parser.endpoint
|
37
|
+
@namespaces = parser.namespaces
|
38
|
+
@type_namespaces = load_type_namespaces(parser)
|
39
|
+
@prefixes = parser.prefixes
|
40
|
+
@soap_version = parser.soap_version
|
45
41
|
end
|
46
42
|
|
47
43
|
# Hash of types declared by the service
|
@@ -54,9 +50,14 @@ module LolSoap
|
|
54
50
|
@types.fetch(name) { NullType.new }
|
55
51
|
end
|
56
52
|
|
57
|
-
#
|
58
|
-
def
|
59
|
-
|
53
|
+
# Hash of operations that are supports by the SOAP service
|
54
|
+
def operations
|
55
|
+
@operations.dup
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get a single operation
|
59
|
+
def operation(name)
|
60
|
+
@operations.fetch(name)
|
60
61
|
end
|
61
62
|
|
62
63
|
def inspect
|
@@ -68,39 +69,75 @@ module LolSoap
|
|
68
69
|
|
69
70
|
private
|
70
71
|
|
72
|
+
# @private
|
73
|
+
def load_types(parser)
|
74
|
+
Hash[
|
75
|
+
parser.types.map do |prefixed_name, type|
|
76
|
+
[prefixed_name, build_type(type)]
|
77
|
+
end
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
71
81
|
# @private
|
72
82
|
def load_operations(parser)
|
73
83
|
Hash[
|
74
84
|
parser.operations.map do |k, op|
|
75
|
-
[k, Operation.new(self, op[:action],
|
85
|
+
[k, Operation.new(self, op[:action], message_format(op[:input], parser), message_format(op[:output], parser))]
|
76
86
|
end
|
77
87
|
]
|
78
88
|
end
|
79
89
|
|
80
90
|
# @private
|
81
|
-
def
|
91
|
+
def load_type_namespaces(parser)
|
82
92
|
Hash[
|
83
|
-
parser.types.map do |
|
84
|
-
[
|
85
|
-
prefixed_name,
|
86
|
-
Type.new(
|
87
|
-
type[:name],
|
88
|
-
type[:prefix],
|
89
|
-
build_elements(type[:elements]),
|
90
|
-
type[:attributes]
|
91
|
-
)
|
92
|
-
]
|
93
|
+
parser.types.merge(parser.elements).values.map do |el|
|
94
|
+
[el[:prefix], namespaces[el[:prefix]]]
|
93
95
|
end
|
94
96
|
]
|
95
97
|
end
|
96
98
|
|
99
|
+
# @private
|
100
|
+
def build_type(params)
|
101
|
+
Type.new(
|
102
|
+
params[:name],
|
103
|
+
params[:prefix],
|
104
|
+
build_elements(params[:elements]),
|
105
|
+
params[:attributes]
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
97
109
|
# @private
|
98
110
|
def build_elements(elements)
|
99
111
|
Hash[
|
100
112
|
elements.map do |name, el|
|
101
|
-
[name,
|
113
|
+
[name, build_element(el)]
|
102
114
|
end
|
103
115
|
]
|
104
116
|
end
|
117
|
+
|
118
|
+
# @private
|
119
|
+
def build_element(params)
|
120
|
+
Element.new(
|
121
|
+
self,
|
122
|
+
params[:name],
|
123
|
+
params[:prefix],
|
124
|
+
type_reference(params[:type]),
|
125
|
+
params[:singular]
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
# @private
|
130
|
+
def type_reference(type)
|
131
|
+
if type.respond_to?(:to_str)
|
132
|
+
NamedTypeReference.new(type, self)
|
133
|
+
else
|
134
|
+
ImmediateTypeReference.new(build_type(type))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# @private
|
139
|
+
def message_format(element, parser)
|
140
|
+
build_element(parser.elements[element])
|
141
|
+
end
|
105
142
|
end
|
106
143
|
end
|
data/lib/lolsoap/wsdl/element.rb
CHANGED
@@ -1,24 +1,29 @@
|
|
1
1
|
class LolSoap::WSDL
|
2
2
|
class Element
|
3
|
-
attr_reader :name
|
3
|
+
attr_reader :name, :prefix, :type_reference
|
4
4
|
|
5
|
-
def initialize(wsdl, name,
|
6
|
-
@wsdl
|
7
|
-
@name
|
8
|
-
@
|
9
|
-
@
|
5
|
+
def initialize(wsdl, name, prefix, type_reference, singular = true)
|
6
|
+
@wsdl = wsdl
|
7
|
+
@name = name
|
8
|
+
@prefix = prefix
|
9
|
+
@type_reference = type_reference
|
10
|
+
@singular = singular
|
11
|
+
end
|
12
|
+
|
13
|
+
def type
|
14
|
+
type_reference.type
|
10
15
|
end
|
11
16
|
|
12
17
|
def singular?
|
13
18
|
@singular == true
|
14
19
|
end
|
15
20
|
|
16
|
-
def
|
17
|
-
|
21
|
+
def inspect
|
22
|
+
"<#{self.class} name=#{prefix_and_name.inspect} type=#{type.to_s.inspect}>"
|
18
23
|
end
|
19
24
|
|
20
|
-
def
|
21
|
-
"
|
25
|
+
def prefix_and_name
|
26
|
+
"#{prefix}:#{name}"
|
22
27
|
end
|
23
28
|
|
24
29
|
private
|
data/lib/lolsoap/wsdl/type.rb
CHANGED
@@ -19,6 +19,10 @@ class LolSoap::WSDL
|
|
19
19
|
@elements.fetch(name) { NullElement.new }
|
20
20
|
end
|
21
21
|
|
22
|
+
def element_prefix(name)
|
23
|
+
@elements.fetch(name, self).prefix
|
24
|
+
end
|
25
|
+
|
22
26
|
def sub_type(name)
|
23
27
|
element(name).type
|
24
28
|
end
|
@@ -32,9 +36,13 @@ class LolSoap::WSDL
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def inspect
|
35
|
-
"<#{self.class} name=\"#{
|
39
|
+
"<#{self.class} name=\"#{prefix_and_name.inspect}\" " \
|
36
40
|
"elements=#{elements.inspect} " \
|
37
41
|
"attributes=#{attributes.inspect}>"
|
38
42
|
end
|
43
|
+
|
44
|
+
def prefix_and_name
|
45
|
+
"#{prefix}:#{name}"
|
46
|
+
end
|
39
47
|
end
|
40
48
|
end
|
data/lib/lolsoap/wsdl_parser.rb
CHANGED
@@ -3,7 +3,7 @@ require 'nokogiri'
|
|
3
3
|
module LolSoap
|
4
4
|
# @private
|
5
5
|
class WSDLParser
|
6
|
-
class
|
6
|
+
class Node
|
7
7
|
attr_reader :parser, :node, :target_namespace, :name, :prefix
|
8
8
|
|
9
9
|
def initialize(parser, node, target_namespace)
|
@@ -17,28 +17,84 @@ module LolSoap
|
|
17
17
|
"#{prefix}:#{name}"
|
18
18
|
end
|
19
19
|
|
20
|
+
def prefix_and_name(string)
|
21
|
+
parser.prefix_and_name(string, target_namespace)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Element < Node
|
26
|
+
def type
|
27
|
+
if complex_type = node.at_xpath('xs:complexType', parser.ns)
|
28
|
+
type = Type.new(parser, complex_type, target_namespace)
|
29
|
+
{
|
30
|
+
:elements => type.elements,
|
31
|
+
:attributes => type.attributes
|
32
|
+
}
|
33
|
+
else
|
34
|
+
prefix_and_name(node.attr('type').to_s).join(':')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def singular
|
39
|
+
max_occurs.empty? || max_occurs == '1'
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def max_occurs
|
45
|
+
@max_occurs ||= node.attribute('maxOccurs').to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Type < Node
|
20
50
|
def elements
|
21
|
-
|
22
|
-
|
23
|
-
|
51
|
+
parent_elements.merge(own_elements)
|
52
|
+
end
|
53
|
+
|
54
|
+
def attributes
|
55
|
+
parent_attributes + own_attributes
|
56
|
+
end
|
57
|
+
|
58
|
+
def base_type
|
59
|
+
@base_type ||= begin
|
60
|
+
if extension = node.at_xpath('xs:complexContent/xs:extension/@base', parser.ns)
|
61
|
+
parser.type(extension.to_s)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
24
67
|
|
68
|
+
def own_elements
|
69
|
+
Hash[
|
70
|
+
element_nodes.map do |element|
|
25
71
|
[
|
26
|
-
|
72
|
+
element.name,
|
27
73
|
{
|
28
|
-
:
|
29
|
-
:
|
74
|
+
:name => element.name,
|
75
|
+
:prefix => element.prefix,
|
76
|
+
:type => element.type,
|
77
|
+
:singular => element.singular
|
30
78
|
}
|
31
79
|
]
|
32
80
|
end
|
33
81
|
]
|
34
82
|
end
|
35
83
|
|
36
|
-
def
|
37
|
-
node.xpath('
|
84
|
+
def element_nodes
|
85
|
+
node.xpath('*/xs:element | */*/xs:element | xs:complexContent/xs:extension/*/xs:element | xs:complexContent/xs:extension/*/*/xs:element', parser.ns).map { |el| Element.new(parser, el, target_namespace) }
|
38
86
|
end
|
39
87
|
|
40
|
-
def
|
41
|
-
|
88
|
+
def parent_elements
|
89
|
+
base_type ? base_type.elements : {}
|
90
|
+
end
|
91
|
+
|
92
|
+
def own_attributes
|
93
|
+
node.xpath('xs:attribute/@name | */xs:extension/xs:attribute/@name', parser.ns).map(&:text)
|
94
|
+
end
|
95
|
+
|
96
|
+
def parent_attributes
|
97
|
+
base_type ? base_type.attributes : []
|
42
98
|
end
|
43
99
|
end
|
44
100
|
|
@@ -79,24 +135,41 @@ module LolSoap
|
|
79
135
|
def types
|
80
136
|
@types ||= begin
|
81
137
|
types = {}
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
type
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
:prefix => type.prefix,
|
91
|
-
:elements => type.elements,
|
92
|
-
:attributes => type.attributes
|
93
|
-
}
|
94
|
-
end
|
138
|
+
each_node('xs:complexType[not(@abstract)]') do |node, target_ns|
|
139
|
+
type = Type.new(self, node, target_ns)
|
140
|
+
types[type.name_with_prefix] = {
|
141
|
+
:name => type.name,
|
142
|
+
:prefix => type.prefix,
|
143
|
+
:elements => type.elements,
|
144
|
+
:attributes => type.attributes
|
145
|
+
}
|
95
146
|
end
|
96
147
|
types
|
97
148
|
end
|
98
149
|
end
|
99
150
|
|
151
|
+
def type(name)
|
152
|
+
name = prefix_and_name(name).last
|
153
|
+
node = doc.at_xpath("//xs:complexType[@name='#{name}']", ns)
|
154
|
+
target_namespace = node.at_xpath('parent::xs:schema/@targetNamespace', ns).to_s
|
155
|
+
Type.new(self, node, target_namespace)
|
156
|
+
end
|
157
|
+
|
158
|
+
def elements
|
159
|
+
@elements ||= begin
|
160
|
+
elements = {}
|
161
|
+
each_node('xs:element') do |node, target_ns|
|
162
|
+
element = Element.new(self, node, target_ns)
|
163
|
+
elements[element.name_with_prefix] = {
|
164
|
+
:name => element.name,
|
165
|
+
:prefix => element.prefix,
|
166
|
+
:type => element.type
|
167
|
+
}
|
168
|
+
end
|
169
|
+
elements
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
100
173
|
def messages
|
101
174
|
@messages ||= Hash[
|
102
175
|
doc.xpath('/d:definitions/d:message', ns).map do |msg|
|
@@ -165,5 +238,15 @@ module LolSoap
|
|
165
238
|
|
166
239
|
[prefix, name]
|
167
240
|
end
|
241
|
+
|
242
|
+
def each_node(xpath)
|
243
|
+
schemas.each do |schema|
|
244
|
+
target_namespace = schema.attr('targetNamespace').to_s
|
245
|
+
|
246
|
+
schema.xpath(xpath, ns).each do |node|
|
247
|
+
yield node, target_namespace
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
168
251
|
end
|
169
252
|
end
|
data/lolsoap.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "lolsoap"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jon Leighton"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-06-24"
|
13
13
|
s.description = "A library for dealing with SOAP requests and responses. We tear our hair out so you don't have to."
|
14
14
|
s.email = "j@jonathanleighton.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -37,6 +37,8 @@ Gem::Specification.new do |s|
|
|
37
37
|
"lib/lolsoap/response.rb",
|
38
38
|
"lib/lolsoap/wsdl.rb",
|
39
39
|
"lib/lolsoap/wsdl/element.rb",
|
40
|
+
"lib/lolsoap/wsdl/immediate_type_reference.rb",
|
41
|
+
"lib/lolsoap/wsdl/named_type_reference.rb",
|
40
42
|
"lib/lolsoap/wsdl/null_element.rb",
|
41
43
|
"lib/lolsoap/wsdl/null_type.rb",
|
42
44
|
"lib/lolsoap/wsdl/operation.rb",
|
@@ -20,12 +20,48 @@
|
|
20
20
|
</all>
|
21
21
|
</complexType>
|
22
22
|
</element>
|
23
|
-
<
|
23
|
+
<element name="tradePriceRequest" type="TradePriceRequest" />
|
24
|
+
<complexType name="xsd1:TradePriceRequest">
|
25
|
+
<complexContent>
|
26
|
+
<extension base="xsd1:BaseRequest">
|
27
|
+
<sequence>
|
28
|
+
<element name="tickerSymbol" type="xs:string" maxOccurs="5"/>
|
29
|
+
<element name="specialTickerSymbol" type="xsd2:TickerSymbol" maxOccurs="unbounded"/>
|
30
|
+
</sequence>
|
31
|
+
<attribute name="id" type="xs:string"/>
|
32
|
+
</extension>
|
33
|
+
</complexContent>
|
34
|
+
</complexType>
|
35
|
+
<element name="xsd1:HistoricalPrice">
|
36
|
+
<complexType>
|
37
|
+
<sequence>
|
38
|
+
<element name="date" type="xs:date"/>
|
39
|
+
<element name="price" type="xs:float"/>
|
40
|
+
</sequence>
|
41
|
+
</complexType>
|
42
|
+
</element>
|
43
|
+
<element name="historicalPriceRequest" type="HistoricalPriceRequest" />
|
44
|
+
<complexType name="xsd1:HistoricalPriceRequest">
|
45
|
+
<complexContent>
|
46
|
+
<extension base="xsd1:BaseRequest">
|
47
|
+
<sequence>
|
48
|
+
<element name="dateRange">
|
49
|
+
<complexType>
|
50
|
+
<sequence>
|
51
|
+
<element name="startDate" maxOccurs="1" type="xs:string" />
|
52
|
+
<element name="endDate" maxOccurs="1" type="xs:string" />
|
53
|
+
</sequence>
|
54
|
+
</complexType>
|
55
|
+
</element>
|
56
|
+
</sequence>
|
57
|
+
</extension>
|
58
|
+
</complexContent>
|
59
|
+
</complexType>
|
60
|
+
<complexType abstract="true" name="BaseRequest">
|
24
61
|
<sequence>
|
25
|
-
<element name="
|
26
|
-
<element name="specialTickerSymbol" type="xsd2:TickerSymbol" maxOccurs="unbounded"/>
|
27
|
-
<attribute name="id" type="xs:string"/>
|
62
|
+
<element name="accountId" type="xs:string" maxOccurs="1"/>
|
28
63
|
</sequence>
|
64
|
+
<attribute name="signature" type="xs:string"/>
|
29
65
|
</complexType>
|
30
66
|
</schema>
|
31
67
|
|
@@ -40,18 +76,30 @@
|
|
40
76
|
</types>
|
41
77
|
|
42
78
|
<message name="GetLastTradePriceInput">
|
43
|
-
<part name="body" element="xsd1:
|
79
|
+
<part name="body" element="xsd1:tradePriceRequest"/>
|
44
80
|
</message>
|
45
81
|
|
46
82
|
<message name="GetLastTradePriceOutput">
|
47
83
|
<part name="body" element="xsd3:TradePrice"/>
|
48
84
|
</message>
|
49
85
|
|
86
|
+
<message name="GetHistoricalPriceInput">
|
87
|
+
<part name="body" element="xsd1:historicalPriceRequest"/>
|
88
|
+
</message>
|
89
|
+
|
90
|
+
<message name="GetHistoricalPriceOutput">
|
91
|
+
<part name="body" element="xsd1:HistoricalPrice"/>
|
92
|
+
</message>
|
93
|
+
|
50
94
|
<portType name="StockQuotePortType">
|
51
95
|
<operation name="GetLastTradePrice">
|
52
96
|
<input message="tns:GetLastTradePriceInput"/>
|
53
97
|
<output message="tns:GetLastTradePriceOutput"/>
|
54
98
|
</operation>
|
99
|
+
<operation name="GetHistoricalPrice">
|
100
|
+
<input message="tns:GetHistoricalPriceInput"/>
|
101
|
+
<output message="tns:GetHistoricalPriceOutput"/>
|
102
|
+
</operation>
|
55
103
|
</portType>
|
56
104
|
|
57
105
|
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
|
@@ -65,6 +113,15 @@
|
|
65
113
|
<soap:body use="literal"/>
|
66
114
|
</output>
|
67
115
|
</operation>
|
116
|
+
<operation name="GetHistoricalPrice">
|
117
|
+
<soap:operation soapAction="http://example.com/GetHistoricalPrice"/>
|
118
|
+
<input>
|
119
|
+
<soap:body use="literal"/>
|
120
|
+
</input>
|
121
|
+
<output>
|
122
|
+
<soap:body use="literal"/>
|
123
|
+
</output>
|
124
|
+
</operation>
|
68
125
|
</binding>
|
69
126
|
|
70
127
|
<service name="StockQuoteService">
|
@@ -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/xsd1:
|
13
|
+
body = doc.at_xpath('/soap:Envelope/soap:Body/xsd1:tradePriceRequest', doc.namespaces)
|
14
14
|
body.wont_equal nil
|
15
15
|
end
|
16
16
|
|
@@ -24,15 +24,15 @@ module LolSoap
|
|
24
24
|
b.id 42
|
25
25
|
end
|
26
26
|
|
27
|
-
el = doc.at_xpath('//xsd1:
|
27
|
+
el = doc.at_xpath('//xsd1:tradePriceRequest/xsd1: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('//xsd1:
|
31
|
+
el = doc.at_xpath('//xsd1:tradePriceRequest/xsd1:specialTickerSymbol/xsd2: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('//xsd1:
|
35
|
+
attr = doc.at_xpath('//xsd1:tradePriceRequest/@id', doc.namespaces)
|
36
36
|
attr.to_s.must_equal "42"
|
37
37
|
end
|
38
38
|
|
@@ -6,10 +6,10 @@ module LolSoap
|
|
6
6
|
subject { WSDL.parse(File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')) }
|
7
7
|
|
8
8
|
it 'should successfully parse a WSDL document' do
|
9
|
-
subject.operations.length.must_equal
|
9
|
+
subject.operations.length.must_equal 2
|
10
10
|
subject.operations['GetLastTradePrice'].tap do |o|
|
11
|
-
o.input.must_equal
|
12
|
-
o.action.must_equal
|
11
|
+
o.input.name.must_equal 'tradePriceRequest'
|
12
|
+
o.action.must_equal 'http://example.com/GetLastTradePrice'
|
13
13
|
end
|
14
14
|
|
15
15
|
subject.types.length.must_equal 3
|
data/test/unit/test_builder.rb
CHANGED
@@ -15,6 +15,10 @@ module LolSoap
|
|
15
15
|
end
|
16
16
|
let(:type) do
|
17
17
|
type = OpenStruct.new(:prefix => 'a')
|
18
|
+
def type.element_prefix(name)
|
19
|
+
@element_prefixes = { 'bar' => 'b' }
|
20
|
+
@element_prefixes.fetch(name) { 'a' }
|
21
|
+
end
|
18
22
|
def type.has_attribute?(*); false; end
|
19
23
|
def type.sub_type(name)
|
20
24
|
@sub_types ||= { 'foo' => Object.new, 'bar' => Object.new, 'clone' => Object.new }
|
@@ -47,7 +51,7 @@ module LolSoap
|
|
47
51
|
end
|
48
52
|
|
49
53
|
it 'yields to a block, if given' do
|
50
|
-
expect_node_added node.namespace_scopes[
|
54
|
+
expect_node_added node.namespace_scopes[0], 'bar' do
|
51
55
|
block = nil
|
52
56
|
ret = subject.__tag__(:bar) { |b| block = b }
|
53
57
|
block.object_id.must_equal ret.object_id
|
@@ -57,7 +61,7 @@ module LolSoap
|
|
57
61
|
|
58
62
|
describe 'method missing' do
|
59
63
|
it 'delegates to __tag__' do
|
60
|
-
expect_node_added node.namespace_scopes[
|
64
|
+
expect_node_added node.namespace_scopes[0], 'bar', 'baz' do
|
61
65
|
subject.bar 'baz'
|
62
66
|
end
|
63
67
|
end
|
@@ -67,6 +71,11 @@ module LolSoap
|
|
67
71
|
subject.clone
|
68
72
|
end
|
69
73
|
end
|
74
|
+
|
75
|
+
it 'sets content' do
|
76
|
+
subject.__content__ 'zomg'
|
77
|
+
node.content.must_equal 'zomg'
|
78
|
+
end
|
70
79
|
end
|
71
80
|
|
72
81
|
it 'responds to anything' do
|
@@ -91,6 +100,5 @@ module LolSoap
|
|
91
100
|
subject.__type__.must_equal type
|
92
101
|
end
|
93
102
|
end
|
94
|
-
|
95
103
|
end
|
96
104
|
end
|
data/test/unit/test_envelope.rb
CHANGED
@@ -106,16 +106,16 @@ module LolSoap
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
describe '#
|
109
|
+
describe '#input' do
|
110
110
|
it "returns the operation's input" do
|
111
|
-
subject.
|
111
|
+
subject.input.must_equal operation.input
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
115
|
describe '#output' do
|
116
116
|
it "returns the operation's output" do
|
117
117
|
operation.output = 'lol'
|
118
|
-
subject.
|
118
|
+
subject.output.must_equal 'lol'
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
data/test/unit/test_wsdl.rb
CHANGED
@@ -12,7 +12,7 @@ module LolSoap
|
|
12
12
|
:operations => {
|
13
13
|
'washHands' => {
|
14
14
|
:action => 'urn:washHands',
|
15
|
-
:input => 'bla:
|
15
|
+
:input => 'bla:brush',
|
16
16
|
:output => 'bla:Color'
|
17
17
|
}
|
18
18
|
},
|
@@ -20,30 +20,64 @@ module LolSoap
|
|
20
20
|
'bla:Brush' => {
|
21
21
|
:elements => {
|
22
22
|
'handleColor' => {
|
23
|
-
:
|
23
|
+
:name => 'handleColor',
|
24
|
+
:prefix => 'bla',
|
25
|
+
:type => {
|
26
|
+
:elements => {
|
27
|
+
'name' => {
|
28
|
+
:name => 'name',
|
29
|
+
:prefix => 'bla',
|
30
|
+
:type => 'xs:string',
|
31
|
+
:singular => true
|
32
|
+
},
|
33
|
+
'hex' => {
|
34
|
+
:name => 'hex',
|
35
|
+
:prefix => 'bla',
|
36
|
+
:type => 'xs:string',
|
37
|
+
:singular => true
|
38
|
+
}
|
39
|
+
},
|
40
|
+
:attributes => []
|
41
|
+
},
|
24
42
|
:singular => true
|
25
43
|
},
|
26
44
|
'age' => {
|
45
|
+
:name => 'age',
|
46
|
+
:prefix => 'bla',
|
27
47
|
:type => 'xs:int',
|
28
48
|
:singular => false
|
29
49
|
}
|
30
50
|
},
|
31
51
|
:attributes => ['id'],
|
32
52
|
:prefix => 'bla'
|
53
|
+
}
|
54
|
+
},
|
55
|
+
:elements => {
|
56
|
+
'bla:brush' => {
|
57
|
+
:name => 'brush',
|
58
|
+
:prefix => 'bla',
|
59
|
+
:type => 'bla:Brush'
|
33
60
|
},
|
34
61
|
'bla:Color' => {
|
35
|
-
:
|
36
|
-
|
37
|
-
|
38
|
-
|
62
|
+
:name => 'Color',
|
63
|
+
:prefix => 'bla',
|
64
|
+
:type => {
|
65
|
+
:elements => {
|
66
|
+
'name' => {
|
67
|
+
:name => 'name',
|
68
|
+
:prefix => 'bla',
|
69
|
+
:type => 'xs:string',
|
70
|
+
:singular => true
|
71
|
+
},
|
72
|
+
'hex' => {
|
73
|
+
:name => 'hex',
|
74
|
+
:prefix => 'bla',
|
75
|
+
:type => 'xs:string',
|
76
|
+
:singular => true
|
77
|
+
}
|
39
78
|
},
|
40
|
-
|
41
|
-
|
42
|
-
:singular => true
|
43
|
-
}
|
44
|
-
},
|
45
|
-
:attributes => [],
|
46
|
-
:prefix => 'bla'
|
79
|
+
:attributes => []
|
80
|
+
}
|
47
81
|
}
|
48
82
|
}
|
49
83
|
)
|
@@ -55,10 +89,13 @@ module LolSoap
|
|
55
89
|
it 'returns a hash of operations' do
|
56
90
|
subject.operations.length.must_equal 1
|
57
91
|
subject.operations['washHands'].tap do |op|
|
58
|
-
op.wsdl.must_equal
|
59
|
-
op.action.must_equal
|
60
|
-
op.input.must_equal
|
61
|
-
op.output.
|
92
|
+
op.wsdl.must_equal subject
|
93
|
+
op.action.must_equal 'urn:washHands'
|
94
|
+
op.input.name.must_equal 'brush'
|
95
|
+
op.output.tap do |output|
|
96
|
+
output.is_a?(WSDL::Element).must_equal(true)
|
97
|
+
output.type.elements.keys.sort.must_equal %w(hex name)
|
98
|
+
end
|
62
99
|
end
|
63
100
|
end
|
64
101
|
end
|
@@ -84,28 +121,26 @@ module LolSoap
|
|
84
121
|
|
85
122
|
describe '#types' do
|
86
123
|
it 'returns a hash of types' do
|
87
|
-
subject.types.length.must_equal
|
124
|
+
subject.types.length.must_equal 1
|
88
125
|
|
89
126
|
subject.types['bla:Brush'].tap do |t|
|
90
127
|
t.elements.length.must_equal 2
|
91
|
-
t.element('handleColor').type.
|
128
|
+
t.element('handleColor').type.tap do |type|
|
129
|
+
type.is_a?(WSDL::Type).must_equal true
|
130
|
+
type.elements.keys.sort.must_equal %w(hex name)
|
131
|
+
end
|
132
|
+
t.element('handleColor').prefix.must_equal 'bla'
|
92
133
|
t.element('handleColor').singular?.must_equal true
|
93
134
|
t.element('age').type.must_equal WSDL::NullType.new
|
94
135
|
t.element('age').singular?.must_equal false
|
95
136
|
t.attributes.must_equal ['id']
|
96
137
|
end
|
97
|
-
|
98
|
-
subject.types['bla:Color'].tap do |t|
|
99
|
-
t.elements.length.must_equal 2
|
100
|
-
t.element('name').type.must_equal WSDL::NullType.new
|
101
|
-
t.element('hex').type.must_equal WSDL::NullType.new
|
102
|
-
end
|
103
138
|
end
|
104
139
|
end
|
105
140
|
|
106
141
|
describe '#type' do
|
107
142
|
it 'returns a single type' do
|
108
|
-
subject.type('bla:
|
143
|
+
subject.type('bla:Brush').must_equal subject.types['bla:Brush']
|
109
144
|
end
|
110
145
|
|
111
146
|
it 'returns a null object if a type is missing' do
|
@@ -37,33 +37,69 @@ module LolSoap
|
|
37
37
|
:prefix => 'xsd1',
|
38
38
|
:name => 'TradePriceRequest',
|
39
39
|
:elements => {
|
40
|
+
'accountId' => {
|
41
|
+
:name => 'accountId',
|
42
|
+
:prefix => 'xsd1',
|
43
|
+
:type => 'xs:string',
|
44
|
+
:singular => true
|
45
|
+
},
|
40
46
|
'tickerSymbol' => {
|
47
|
+
:name => 'tickerSymbol',
|
48
|
+
:prefix => 'xsd1',
|
41
49
|
:type => 'xs:string',
|
42
50
|
:singular => false
|
43
51
|
},
|
44
52
|
'specialTickerSymbol' => {
|
53
|
+
:name => 'specialTickerSymbol',
|
54
|
+
:prefix => 'xsd1',
|
45
55
|
:type => 'xsd2:TickerSymbol',
|
46
56
|
:singular => false
|
47
57
|
}
|
48
58
|
},
|
49
|
-
:attributes => ['id']
|
59
|
+
:attributes => ['signature', 'id']
|
50
60
|
},
|
51
|
-
'xsd1:
|
61
|
+
'xsd1:HistoricalPriceRequest' => {
|
52
62
|
:prefix => 'xsd1',
|
53
|
-
:name => '
|
63
|
+
:name => 'HistoricalPriceRequest',
|
54
64
|
:elements => {
|
55
|
-
'
|
56
|
-
:
|
65
|
+
'accountId' => {
|
66
|
+
:name => 'accountId',
|
67
|
+
:prefix => 'xsd1',
|
68
|
+
:type => 'xs:string',
|
69
|
+
:singular => true
|
70
|
+
},
|
71
|
+
'dateRange' => {
|
72
|
+
:name => 'dateRange',
|
73
|
+
:prefix => 'xsd1',
|
74
|
+
:type => {
|
75
|
+
:elements => {
|
76
|
+
'startDate' => {
|
77
|
+
:name => 'startDate',
|
78
|
+
:prefix => 'xsd1',
|
79
|
+
:type => 'xs:string',
|
80
|
+
:singular => true
|
81
|
+
},
|
82
|
+
'endDate' => {
|
83
|
+
:name => 'endDate',
|
84
|
+
:prefix => 'xsd1',
|
85
|
+
:type => 'xs:string',
|
86
|
+
:singular => true
|
87
|
+
}
|
88
|
+
},
|
89
|
+
:attributes => []
|
90
|
+
},
|
57
91
|
:singular => true
|
58
92
|
}
|
59
93
|
},
|
60
|
-
:attributes => []
|
94
|
+
:attributes => ['signature']
|
61
95
|
},
|
62
96
|
'xsd2:TickerSymbol' => {
|
63
97
|
:prefix => 'xsd2',
|
64
98
|
:name => 'TickerSymbol',
|
65
99
|
:elements => {
|
66
100
|
'name' => {
|
101
|
+
:name => 'name',
|
102
|
+
:prefix => 'xsd2',
|
67
103
|
:type => 'xs:string',
|
68
104
|
:singular => true
|
69
105
|
}
|
@@ -74,11 +110,66 @@ module LolSoap
|
|
74
110
|
end
|
75
111
|
end
|
76
112
|
|
113
|
+
describe '#elements' do
|
114
|
+
it 'returns the elements with inline types' do
|
115
|
+
subject.elements.must_equal({
|
116
|
+
"xsd1:tradePriceRequest" => {
|
117
|
+
:name => "tradePriceRequest",
|
118
|
+
:prefix => "xsd1",
|
119
|
+
:type => "xsd1:TradePriceRequest"
|
120
|
+
},
|
121
|
+
"xsd1:TradePrice" => {
|
122
|
+
:name => "TradePrice",
|
123
|
+
:prefix => "xsd1",
|
124
|
+
:type => {
|
125
|
+
:elements => {
|
126
|
+
'price' => {
|
127
|
+
:name => 'price',
|
128
|
+
:prefix => 'xsd1',
|
129
|
+
:type => 'xs:float',
|
130
|
+
:singular => true
|
131
|
+
}
|
132
|
+
},
|
133
|
+
:attributes => []
|
134
|
+
}
|
135
|
+
},
|
136
|
+
"xsd1:historicalPriceRequest" => {
|
137
|
+
:name => "historicalPriceRequest",
|
138
|
+
:prefix => "xsd1",
|
139
|
+
:type => "xsd1:HistoricalPriceRequest"
|
140
|
+
},
|
141
|
+
"xsd1:HistoricalPrice" => {
|
142
|
+
:name => "HistoricalPrice",
|
143
|
+
:prefix => "xsd1",
|
144
|
+
:type => {
|
145
|
+
:elements => {
|
146
|
+
'date' => {
|
147
|
+
:name => 'date',
|
148
|
+
:prefix => 'xsd1',
|
149
|
+
:type => 'xs:date',
|
150
|
+
:singular => true
|
151
|
+
},
|
152
|
+
'price' => {
|
153
|
+
:name => 'price',
|
154
|
+
:prefix => 'xsd1',
|
155
|
+
:type => 'xs:float',
|
156
|
+
:singular => true
|
157
|
+
}
|
158
|
+
},
|
159
|
+
:attributes => []
|
160
|
+
}
|
161
|
+
}
|
162
|
+
})
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
77
166
|
describe '#messages' do
|
78
167
|
it 'maps message names to types' do
|
79
168
|
subject.messages.must_equal({
|
80
|
-
'GetLastTradePriceInput'
|
81
|
-
'GetLastTradePriceOutput'
|
169
|
+
'GetLastTradePriceInput' => 'xsd1:tradePriceRequest',
|
170
|
+
'GetLastTradePriceOutput' => 'xsd1:TradePrice',
|
171
|
+
'GetHistoricalPriceInput' => 'xsd1:historicalPriceRequest',
|
172
|
+
'GetHistoricalPriceOutput' => 'xsd1:HistoricalPrice'
|
82
173
|
})
|
83
174
|
end
|
84
175
|
end
|
@@ -87,8 +178,12 @@ module LolSoap
|
|
87
178
|
it 'is a hash containing input and output types' do
|
88
179
|
subject.port_type_operations.must_equal({
|
89
180
|
'GetLastTradePrice' => {
|
90
|
-
:input => 'xsd1:
|
181
|
+
:input => 'xsd1:tradePriceRequest',
|
91
182
|
:output => 'xsd1:TradePrice'
|
183
|
+
},
|
184
|
+
'GetHistoricalPrice' => {
|
185
|
+
:input => 'xsd1:historicalPriceRequest',
|
186
|
+
:output => 'xsd1:HistoricalPrice'
|
92
187
|
}
|
93
188
|
})
|
94
189
|
end
|
@@ -99,8 +194,13 @@ module LolSoap
|
|
99
194
|
subject.operations.must_equal({
|
100
195
|
'GetLastTradePrice' => {
|
101
196
|
:action => 'http://example.com/GetLastTradePrice',
|
102
|
-
:input => 'xsd1:
|
197
|
+
:input => 'xsd1:tradePriceRequest',
|
103
198
|
:output => 'xsd1:TradePrice'
|
199
|
+
},
|
200
|
+
'GetHistoricalPrice' => {
|
201
|
+
:action => 'http://example.com/GetHistoricalPrice',
|
202
|
+
:input => 'xsd1:historicalPriceRequest',
|
203
|
+
:output => 'xsd1:HistoricalPrice'
|
104
204
|
}
|
105
205
|
})
|
106
206
|
end
|
@@ -3,15 +3,18 @@ require 'lolsoap/wsdl'
|
|
3
3
|
|
4
4
|
class LolSoap::WSDL
|
5
5
|
describe Element do
|
6
|
-
let(:wsdl)
|
7
|
-
|
6
|
+
let(:wsdl) { MiniTest::Mock.new }
|
7
|
+
let(:type_reference) { MiniTest::Mock.new }
|
8
|
+
let(:type) { Object.new }
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
subject { Element.new(wsdl, 'bar', 'foo', type_reference, true) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
type_reference.expect(:type, type)
|
14
|
+
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
wsdl.expect(:type, type, ['WashHandsRequest'])
|
16
|
+
describe '#type' do
|
17
|
+
it 'returns the type via the reference' do
|
15
18
|
subject.type.must_equal type
|
16
19
|
end
|
17
20
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lolsoap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -120,6 +120,8 @@ files:
|
|
120
120
|
- lib/lolsoap/response.rb
|
121
121
|
- lib/lolsoap/wsdl.rb
|
122
122
|
- lib/lolsoap/wsdl/element.rb
|
123
|
+
- lib/lolsoap/wsdl/immediate_type_reference.rb
|
124
|
+
- lib/lolsoap/wsdl/named_type_reference.rb
|
123
125
|
- lib/lolsoap/wsdl/null_element.rb
|
124
126
|
- lib/lolsoap/wsdl/null_type.rb
|
125
127
|
- lib/lolsoap/wsdl/operation.rb
|
@@ -162,7 +164,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
164
|
version: '0'
|
163
165
|
segments:
|
164
166
|
- 0
|
165
|
-
hash:
|
167
|
+
hash: 413746061
|
166
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
169
|
none: false
|
168
170
|
requirements:
|