soaspec 0.2.33 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +15 -15
- data/.gitlab-ci.yml +62 -62
- data/.rspec +3 -3
- data/.rubocop.yml +2 -2
- data/CODE_OF_CONDUCT.md +74 -74
- data/ChangeLog +643 -632
- data/Dockerfile +7 -7
- data/Gemfile +8 -8
- data/LICENSE.txt +21 -21
- data/README.md +253 -231
- data/Rakefile +52 -52
- data/Todo.md +16 -16
- data/exe/soaspec +140 -138
- data/exe/xml_to_yaml_file +43 -43
- data/lib/soaspec.rb +118 -106
- data/lib/soaspec/baseline.rb +82 -22
- data/lib/soaspec/core_ext/hash.rb +44 -44
- data/lib/soaspec/cucumber/generic_steps.rb +94 -94
- data/lib/soaspec/demo.rb +6 -6
- data/lib/soaspec/errors.rb +24 -24
- data/lib/soaspec/exchange/exchange.rb +131 -129
- data/lib/soaspec/exchange/exchange_extractor.rb +105 -90
- data/lib/soaspec/exchange/exchange_properties.rb +28 -28
- data/lib/soaspec/exchange/exchange_repeater.rb +21 -21
- data/lib/soaspec/exchange/request_builder.rb +108 -70
- data/lib/soaspec/exchange/variable_storer.rb +24 -24
- data/lib/soaspec/exchange_handlers/exchange_handler.rb +98 -98
- data/lib/soaspec/exchange_handlers/exchange_handler_defaults.rb +61 -61
- data/lib/soaspec/exchange_handlers/handler_accessors.rb +132 -132
- data/lib/soaspec/exchange_handlers/request/rest_request.rb +77 -59
- data/lib/soaspec/exchange_handlers/request/soap_request.rb +41 -41
- data/lib/soaspec/exchange_handlers/response_extractor.rb +84 -84
- data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +111 -111
- data/lib/soaspec/exchange_handlers/rest_handler.rb +307 -307
- data/lib/soaspec/exchange_handlers/rest_methods.rb +65 -65
- data/lib/soaspec/exchange_handlers/rest_parameters.rb +112 -112
- data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +42 -42
- data/lib/soaspec/exchange_handlers/soap_handler.rb +241 -241
- data/lib/soaspec/exe_helpers.rb +94 -94
- data/lib/soaspec/generate_server.rb +48 -48
- data/lib/soaspec/generator/.rspec.erb +5 -5
- data/lib/soaspec/generator/.travis.yml.erb +5 -5
- data/lib/soaspec/generator/Gemfile.erb +8 -8
- data/lib/soaspec/generator/README.md.erb +29 -29
- data/lib/soaspec/generator/Rakefile.erb +20 -19
- data/lib/soaspec/generator/config/data/default.yml.erb +2 -2
- data/lib/soaspec/generator/css/bootstrap.css +6833 -6833
- data/lib/soaspec/generator/features/support/env.rb.erb +3 -3
- data/lib/soaspec/generator/generate_exchange.html.erb +47 -47
- data/lib/soaspec/generator/lib/blz_service.rb.erb +26 -26
- data/lib/soaspec/generator/lib/dynamic_class_content.rb.erb +12 -12
- data/lib/soaspec/generator/lib/new_rest_service.rb.erb +56 -56
- data/lib/soaspec/generator/lib/new_soap_service.rb.erb +29 -29
- data/lib/soaspec/generator/lib/package_service.rb.erb +2 -2
- data/lib/soaspec/generator/lib/shared_example.rb.erb +8 -8
- data/lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb +12 -12
- data/lib/soaspec/generator/spec/rest_spec.rb.erb +9 -9
- data/lib/soaspec/generator/spec/soap_spec.rb.erb +51 -51
- data/lib/soaspec/generator/spec/spec_helper.rb.erb +23 -23
- data/lib/soaspec/generator/template/soap_template.xml +6 -6
- data/lib/soaspec/indifferent_hash.rb +9 -9
- data/lib/soaspec/interpreter.rb +70 -70
- data/lib/soaspec/matchers.rb +136 -140
- data/lib/soaspec/o_auth2.rb +142 -142
- data/lib/soaspec/soaspec_shared_examples.rb +26 -26
- data/lib/soaspec/spec_logger.rb +143 -143
- data/lib/soaspec/template_reader.rb +30 -30
- data/lib/soaspec/test_server/bank.wsdl +90 -90
- data/lib/soaspec/test_server/get_bank.rb +166 -166
- data/lib/soaspec/test_server/id_manager.rb +41 -41
- data/lib/soaspec/test_server/invoices.rb +29 -29
- data/lib/soaspec/test_server/namespace.xml +14 -14
- data/lib/soaspec/test_server/note.xml +5 -5
- data/lib/soaspec/test_server/puppy_service.rb +21 -21
- data/lib/soaspec/test_server/test_attribute.rb +14 -14
- data/lib/soaspec/test_server/test_namespace.rb +14 -14
- data/lib/soaspec/version.rb +6 -6
- data/lib/soaspec/virtual_server.rb +193 -190
- data/lib/soaspec/wait.rb +43 -43
- data/lib/soaspec/wsdl_generator.rb +215 -215
- data/soaspec.gemspec +58 -58
- data/test.wsdl +116 -116
- data/test.xml +10 -10
- data/test_wsdl.rb +43 -43
- metadata +3 -3
data/lib/soaspec/wait.rb
CHANGED
@@ -1,43 +1,43 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Soaspec
|
4
|
-
class TimeOutError < StandardError; end
|
5
|
-
# Class to enable waiting for an expected condition to return true
|
6
|
-
class Wait
|
7
|
-
DEFAULT_TIMEOUT = 5
|
8
|
-
DEFAULT_INTERVAL = 0.2
|
9
|
-
|
10
|
-
#
|
11
|
-
# Wait until the given block returns a true value.
|
12
|
-
#
|
13
|
-
# @param [Hash] opts Options for this instance
|
14
|
-
# @option opts [Numeric] :timeout (5) Seconds to wait before timing out.
|
15
|
-
# @option opts [Numeric] :interval (0.2) Seconds to sleep between polls.
|
16
|
-
# @option opts [String] :message Exception mesage if timed out.
|
17
|
-
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Error::NoSuchElementError)
|
18
|
-
# @raise [Error::TimeOutError]
|
19
|
-
# @return [Object] the result of the block
|
20
|
-
#
|
21
|
-
def self.until(opts = {})
|
22
|
-
timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT)
|
23
|
-
ignored = Array(opts[:ignore] || NoElementAtPath)
|
24
|
-
interval = opts.fetch(:interval, DEFAULT_INTERVAL)
|
25
|
-
end_time = Time.now + timeout
|
26
|
-
last_error = nil
|
27
|
-
|
28
|
-
until Time.now > end_time
|
29
|
-
begin
|
30
|
-
result = yield
|
31
|
-
return result if result
|
32
|
-
rescue *ignored => e
|
33
|
-
# swallowed
|
34
|
-
end
|
35
|
-
sleep interval
|
36
|
-
end
|
37
|
-
|
38
|
-
msg = opts[:message] ? opts[:message].dup : "timed out after #{timeout} seconds with interval of #{interval}"
|
39
|
-
msg << " (#{last_error.message})" if last_error
|
40
|
-
raise Soaspec::TimeOutError, msg
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Soaspec
|
4
|
+
class TimeOutError < StandardError; end
|
5
|
+
# Class to enable waiting for an expected condition to return true
|
6
|
+
class Wait
|
7
|
+
DEFAULT_TIMEOUT = 5
|
8
|
+
DEFAULT_INTERVAL = 0.2
|
9
|
+
|
10
|
+
#
|
11
|
+
# Wait until the given block returns a true value.
|
12
|
+
#
|
13
|
+
# @param [Hash] opts Options for this instance
|
14
|
+
# @option opts [Numeric] :timeout (5) Seconds to wait before timing out.
|
15
|
+
# @option opts [Numeric] :interval (0.2) Seconds to sleep between polls.
|
16
|
+
# @option opts [String] :message Exception mesage if timed out.
|
17
|
+
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Error::NoSuchElementError)
|
18
|
+
# @raise [Error::TimeOutError]
|
19
|
+
# @return [Object] the result of the block
|
20
|
+
#
|
21
|
+
def self.until(opts = {})
|
22
|
+
timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT)
|
23
|
+
ignored = Array(opts[:ignore] || NoElementAtPath)
|
24
|
+
interval = opts.fetch(:interval, DEFAULT_INTERVAL)
|
25
|
+
end_time = Time.now + timeout
|
26
|
+
last_error = nil
|
27
|
+
|
28
|
+
until Time.now > end_time
|
29
|
+
begin
|
30
|
+
result = yield
|
31
|
+
return result if result
|
32
|
+
rescue *ignored => e
|
33
|
+
# swallowed
|
34
|
+
end
|
35
|
+
sleep interval
|
36
|
+
end
|
37
|
+
|
38
|
+
msg = opts[:message] ? opts[:message].dup : "timed out after #{timeout} seconds with interval of #{interval}"
|
39
|
+
msg << " (#{last_error.message})" if last_error
|
40
|
+
raise Soaspec::TimeOutError, msg
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,215 +1,215 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Soaspec
|
4
|
-
# Produce test content from a WSDL
|
5
|
-
module WsdlGenerator
|
6
|
-
include ExeHelpers
|
7
|
-
|
8
|
-
# Generate from WSDL
|
9
|
-
def generate_from_wsdl(options)
|
10
|
-
auth_name, auth_password = enter_auth_details if options[:auth] == 'basic'
|
11
|
-
@virtual = false
|
12
|
-
savon_options = { wsdl: options[:wsdl] }
|
13
|
-
savon_options[:basic_auth] = [auth_name, auth_password] if options[:auth] == 'basic'
|
14
|
-
|
15
|
-
wsdl_doc = Savon.client(**savon_options).wsdl
|
16
|
-
@wsdl_schemas = wsdl_doc.parser.schemas
|
17
|
-
# Create basic project files
|
18
|
-
create_files %w[Rakefile Gemfile README.md spec/spec_helper.rb], ignore_if_present: true
|
19
|
-
create_file(filename: '.rspec')
|
20
|
-
create_file(filename: '.travis.yml') if options[:ci] == 'travis'
|
21
|
-
create_folder 'logs'
|
22
|
-
create_file filename: "lib/#{options[:name].snakecase}.rb", content: class_content
|
23
|
-
|
24
|
-
# Files according to WSDL
|
25
|
-
wsdl_doc.operations.each do |operation, op_details|
|
26
|
-
puts "Creating files for operation: #{operation}"
|
27
|
-
@content = "default:\n"
|
28
|
-
@use_camel_case = false
|
29
|
-
puts 'Message params: ' + op_details.to_s
|
30
|
-
# From namespace identifier, find namespace, and for that find schemaLocation xsd and use that to build request
|
31
|
-
op_details[:parameters]&.each do |element, details|
|
32
|
-
@use_camel_case = true unless /[[:upper:]]/.match(element.to_s[0]).nil?
|
33
|
-
@content += " #{element.to_s.snakecase}: #{fill_in_field_from_type(details[:type])} # #{details[:type]} \n"
|
34
|
-
# TODO: If details is a Hash need to loop again
|
35
|
-
end
|
36
|
-
wsdl_to_yaml_for root_elements_for(op_details)
|
37
|
-
params = []
|
38
|
-
params << 'convert_request_keys_to: :camelcase' if @use_camel_case
|
39
|
-
params_string = params == [] ? '' : ', ' + params.join(', ')
|
40
|
-
@class_params = "'#{camel_case(operation)}'#{params_string}"
|
41
|
-
|
42
|
-
create_file(filename: "config/data/#{operation}.yml", content: @content)
|
43
|
-
create_file(filename: "spec/#{operation}_spec.rb", content: generated_soap_spec_for(operation))
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Attempt to calculate values of enumeration by looking up type in Schema
|
48
|
-
# @param [String] type Try out filling enumeration for type. Return Custom Type if can't be done
|
49
|
-
def try_enum_for(type)
|
50
|
-
raise "'@wsdl_schemas' must be defined" if @wsdl_schemas.nil?
|
51
|
-
|
52
|
-
custom_type = @wsdl_schemas.xpath("//*[@name='#{type}']")
|
53
|
-
if enumeration? custom_type
|
54
|
-
prefix = custom_type.first.namespace.prefix
|
55
|
-
enumerations = custom_type.xpath("//#{prefix}:enumeration")
|
56
|
-
return 'Custom Type' if enumerations.empty?
|
57
|
-
|
58
|
-
@enums_values = []
|
59
|
-
enumerations.each { |enum_value| @enums_values << "'#{enum_value['value']}'" }
|
60
|
-
"~randomize [#{@enums_values.join(', ')}]"
|
61
|
-
else
|
62
|
-
'Custom Type'
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# @param [Nokogiri::XML::NodeSet] type WSDL element type
|
67
|
-
# @return [Boolean] Whether WSDL type is an enumeration
|
68
|
-
def enumeration?(type)
|
69
|
-
return false unless type.first
|
70
|
-
|
71
|
-
!type.xpath("*/#{type.first.namespace.prefix}:enumeration").empty?
|
72
|
-
end
|
73
|
-
|
74
|
-
# @param [Nokogiri::XML::Element] element
|
75
|
-
# @return [String] Name of element excluding namespace
|
76
|
-
def name_after_namespace(element)
|
77
|
-
value_after_namespace(element.name)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Return value of string after a namespace
|
81
|
-
# @param [String] string String to parse for part after namespace
|
82
|
-
# @return [String] Part after the namespace, demonstrated by ':'
|
83
|
-
def value_after_namespace(string)
|
84
|
-
string.split(':').last
|
85
|
-
end
|
86
|
-
|
87
|
-
# Based on WSDL type return a valid value
|
88
|
-
# @param [String] type Type without the WSDL
|
89
|
-
# @return [Object] Value representing type to fill in
|
90
|
-
def fill_in_field_from_type(type)
|
91
|
-
case type
|
92
|
-
when 'string' then options[:string_default] # 'test string'
|
93
|
-
when 'int' then 2
|
94
|
-
when 'boolean' then true
|
95
|
-
when 'double' then '1.5'
|
96
|
-
else
|
97
|
-
try_enum_for type
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# @param [Nokogiri::XML::Element] element Element to check
|
102
|
-
# @return [Boolean] True if Nokogiri element is a complex type, that is, has a complexType element underneath itself
|
103
|
-
def complex_type?(element)
|
104
|
-
element.children.any? { |child| name_after_namespace(child) == 'complexType' }
|
105
|
-
end
|
106
|
-
|
107
|
-
# @param [String, Symbol] underscore_separated Snakecase value to be converted to camel case
|
108
|
-
# @return [String] CamelCased value
|
109
|
-
def camel_case(underscore_separated)
|
110
|
-
underscore_separated.to_s.split('_').collect(&:capitalize).join
|
111
|
-
end
|
112
|
-
|
113
|
-
# Element at the root of an operation
|
114
|
-
# @param [Hash] op_details Hash with details from WSDL for an operation
|
115
|
-
def root_element_for(op_details)
|
116
|
-
root_element = @wsdl_schemas.at_xpath("//*[@name='#{op_details[:input]}']")
|
117
|
-
raise 'Operation has no input defined' if root_element.nil?
|
118
|
-
|
119
|
-
root_element
|
120
|
-
end
|
121
|
-
|
122
|
-
# Returns list of elements present at the root of an operation
|
123
|
-
# @param [Hash] op_details Hash with details from WSDL for an operation
|
124
|
-
# @return [Nokogiri::XML::NodeSet] List of the root elements in the SOAP body
|
125
|
-
def root_elements_for(op_details)
|
126
|
-
raise "'@wsdl_schemas' must be defined" if @wsdl_schemas.nil?
|
127
|
-
|
128
|
-
root_element = root_element_for(op_details)
|
129
|
-
schema_namespace = root_element.namespace.prefix
|
130
|
-
root_type = root_element['type']
|
131
|
-
if root_type
|
132
|
-
@wsdl_schemas.xpath("//*[@name='#{value_after_namespace(root_type)}']//#{schema_namespace}:element")
|
133
|
-
else
|
134
|
-
return [] unless complex_type? root_element # Empty Array if there are no root elements
|
135
|
-
|
136
|
-
complex_type = root_element.children.find { |c| c.name == 'complexType' }
|
137
|
-
sequence = complex_type.children.find { |c| c.name == 'sequence' }
|
138
|
-
sequence.xpath("#{schema_namespace}:element")
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# Adds documentation content for all children of XML element
|
143
|
-
# This will be an example yaml for setting SOAP requests
|
144
|
-
# @param [Nokogiri::XML::Element] element Type to document for
|
145
|
-
# @param [Integer] depth How many times to iterate depth for
|
146
|
-
def document_type_for(element, depth = 1)
|
147
|
-
# raise "Too far deep for #{element}" unless depth < 6
|
148
|
-
return unless depth < 6
|
149
|
-
|
150
|
-
if complex_type? element
|
151
|
-
complex_type = element.children.find { |c| name_after_namespace(c) == 'complexType' }
|
152
|
-
sequence = complex_type.children.find { |c| name_after_namespace(c) == 'sequence' }
|
153
|
-
sequence.children.select { |node| node.class == Nokogiri::XML::Element }.each do |sub_element|
|
154
|
-
document_type_for sub_element, depth + 1
|
155
|
-
end
|
156
|
-
else
|
157
|
-
return "No type seen for #{element}, #{element.class}" unless element['type']
|
158
|
-
|
159
|
-
name = element['name']
|
160
|
-
type = value_after_namespace(element['type'])
|
161
|
-
@use_camel_case = true unless /[[:upper:]]/.match(name[0]).nil?
|
162
|
-
spaces = ' ' * depth
|
163
|
-
@content += "#{spaces}#{name.snakecase}: #{fill_in_field_from_type(type)} # #{type} \n"
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
# @todo This should return YAML rather than just set an instance variable
|
168
|
-
# Makes a yaml string in a '@content' instance variable
|
169
|
-
# @param [Nokogiri::XML::NodeSet] list List to convert to YAML
|
170
|
-
def wsdl_to_yaml_for(list)
|
171
|
-
raise "'@content' string must be set" if @content.nil?
|
172
|
-
|
173
|
-
list.each { |element| document_type_for element }
|
174
|
-
end
|
175
|
-
|
176
|
-
# Prompt user for wsdl
|
177
|
-
def ask_wsdl
|
178
|
-
prompt = <<-WSDL_LOC
|
179
|
-
Enter WSDL:
|
180
|
-
WSDL_LOC
|
181
|
-
print prompt.chop
|
182
|
-
@wsdl = $stdin.gets.strip
|
183
|
-
puts
|
184
|
-
end
|
185
|
-
|
186
|
-
# Prompt user for Service name for wsdl
|
187
|
-
def name_of_wsdl
|
188
|
-
prompt = <<-WSDL_NAME
|
189
|
-
Enter what you would like to name WSDL (CamelCase):
|
190
|
-
WSDL_NAME
|
191
|
-
print prompt.chop
|
192
|
-
@name = $stdin.gets.strip
|
193
|
-
puts
|
194
|
-
end
|
195
|
-
|
196
|
-
# Prompt user to enter basic auth details
|
197
|
-
# @return [Array] Array with Basic auth username and password entered
|
198
|
-
def enter_auth_details
|
199
|
-
prompt = <<-AUTH_PROMPT
|
200
|
-
User Name:
|
201
|
-
AUTH_PROMPT
|
202
|
-
print prompt.chop
|
203
|
-
auth_name = $stdin.gets.strip
|
204
|
-
puts
|
205
|
-
|
206
|
-
prompt = <<-PASSWORD
|
207
|
-
User Password:
|
208
|
-
PASSWORD
|
209
|
-
print prompt.chop
|
210
|
-
auth_password = $stdin.gets.strip
|
211
|
-
puts
|
212
|
-
[auth_name, auth_password]
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Soaspec
|
4
|
+
# Produce test content from a WSDL
|
5
|
+
module WsdlGenerator
|
6
|
+
include ExeHelpers
|
7
|
+
|
8
|
+
# Generate from WSDL
|
9
|
+
def generate_from_wsdl(options)
|
10
|
+
auth_name, auth_password = enter_auth_details if options[:auth] == 'basic'
|
11
|
+
@virtual = false
|
12
|
+
savon_options = { wsdl: options[:wsdl] }
|
13
|
+
savon_options[:basic_auth] = [auth_name, auth_password] if options[:auth] == 'basic'
|
14
|
+
|
15
|
+
wsdl_doc = Savon.client(**savon_options).wsdl
|
16
|
+
@wsdl_schemas = wsdl_doc.parser.schemas
|
17
|
+
# Create basic project files
|
18
|
+
create_files %w[Rakefile Gemfile README.md spec/spec_helper.rb], ignore_if_present: true
|
19
|
+
create_file(filename: '.rspec')
|
20
|
+
create_file(filename: '.travis.yml') if options[:ci] == 'travis'
|
21
|
+
create_folder 'logs'
|
22
|
+
create_file filename: "lib/#{options[:name].snakecase}.rb", content: class_content
|
23
|
+
|
24
|
+
# Files according to WSDL
|
25
|
+
wsdl_doc.operations.each do |operation, op_details|
|
26
|
+
puts "Creating files for operation: #{operation}"
|
27
|
+
@content = "default:\n"
|
28
|
+
@use_camel_case = false
|
29
|
+
puts 'Message params: ' + op_details.to_s
|
30
|
+
# From namespace identifier, find namespace, and for that find schemaLocation xsd and use that to build request
|
31
|
+
op_details[:parameters]&.each do |element, details|
|
32
|
+
@use_camel_case = true unless /[[:upper:]]/.match(element.to_s[0]).nil?
|
33
|
+
@content += " #{element.to_s.snakecase}: #{fill_in_field_from_type(details[:type])} # #{details[:type]} \n"
|
34
|
+
# TODO: If details is a Hash need to loop again
|
35
|
+
end
|
36
|
+
wsdl_to_yaml_for root_elements_for(op_details)
|
37
|
+
params = []
|
38
|
+
params << 'convert_request_keys_to: :camelcase' if @use_camel_case
|
39
|
+
params_string = params == [] ? '' : ', ' + params.join(', ')
|
40
|
+
@class_params = "'#{camel_case(operation)}'#{params_string}"
|
41
|
+
|
42
|
+
create_file(filename: "config/data/#{operation}.yml", content: @content)
|
43
|
+
create_file(filename: "spec/#{operation}_spec.rb", content: generated_soap_spec_for(operation))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Attempt to calculate values of enumeration by looking up type in Schema
|
48
|
+
# @param [String] type Try out filling enumeration for type. Return Custom Type if can't be done
|
49
|
+
def try_enum_for(type)
|
50
|
+
raise "'@wsdl_schemas' must be defined" if @wsdl_schemas.nil?
|
51
|
+
|
52
|
+
custom_type = @wsdl_schemas.xpath("//*[@name='#{type}']")
|
53
|
+
if enumeration? custom_type
|
54
|
+
prefix = custom_type.first.namespace.prefix
|
55
|
+
enumerations = custom_type.xpath("//#{prefix}:enumeration")
|
56
|
+
return 'Custom Type' if enumerations.empty?
|
57
|
+
|
58
|
+
@enums_values = []
|
59
|
+
enumerations.each { |enum_value| @enums_values << "'#{enum_value['value']}'" }
|
60
|
+
"~randomize [#{@enums_values.join(', ')}]"
|
61
|
+
else
|
62
|
+
'Custom Type'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param [Nokogiri::XML::NodeSet] type WSDL element type
|
67
|
+
# @return [Boolean] Whether WSDL type is an enumeration
|
68
|
+
def enumeration?(type)
|
69
|
+
return false unless type.first
|
70
|
+
|
71
|
+
!type.xpath("*/#{type.first.namespace.prefix}:enumeration").empty?
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param [Nokogiri::XML::Element] element
|
75
|
+
# @return [String] Name of element excluding namespace
|
76
|
+
def name_after_namespace(element)
|
77
|
+
value_after_namespace(element.name)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Return value of string after a namespace
|
81
|
+
# @param [String] string String to parse for part after namespace
|
82
|
+
# @return [String] Part after the namespace, demonstrated by ':'
|
83
|
+
def value_after_namespace(string)
|
84
|
+
string.split(':').last
|
85
|
+
end
|
86
|
+
|
87
|
+
# Based on WSDL type return a valid value
|
88
|
+
# @param [String] type Type without the WSDL
|
89
|
+
# @return [Object] Value representing type to fill in
|
90
|
+
def fill_in_field_from_type(type)
|
91
|
+
case type
|
92
|
+
when 'string' then options[:string_default] # 'test string'
|
93
|
+
when 'int' then 2
|
94
|
+
when 'boolean' then true
|
95
|
+
when 'double' then '1.5'
|
96
|
+
else
|
97
|
+
try_enum_for type
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# @param [Nokogiri::XML::Element] element Element to check
|
102
|
+
# @return [Boolean] True if Nokogiri element is a complex type, that is, has a complexType element underneath itself
|
103
|
+
def complex_type?(element)
|
104
|
+
element.children.any? { |child| name_after_namespace(child) == 'complexType' }
|
105
|
+
end
|
106
|
+
|
107
|
+
# @param [String, Symbol] underscore_separated Snakecase value to be converted to camel case
|
108
|
+
# @return [String] CamelCased value
|
109
|
+
def camel_case(underscore_separated)
|
110
|
+
underscore_separated.to_s.split('_').collect(&:capitalize).join
|
111
|
+
end
|
112
|
+
|
113
|
+
# Element at the root of an operation
|
114
|
+
# @param [Hash] op_details Hash with details from WSDL for an operation
|
115
|
+
def root_element_for(op_details)
|
116
|
+
root_element = @wsdl_schemas.at_xpath("//*[@name='#{op_details[:input]}']")
|
117
|
+
raise 'Operation has no input defined' if root_element.nil?
|
118
|
+
|
119
|
+
root_element
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns list of elements present at the root of an operation
|
123
|
+
# @param [Hash] op_details Hash with details from WSDL for an operation
|
124
|
+
# @return [Nokogiri::XML::NodeSet] List of the root elements in the SOAP body
|
125
|
+
def root_elements_for(op_details)
|
126
|
+
raise "'@wsdl_schemas' must be defined" if @wsdl_schemas.nil?
|
127
|
+
|
128
|
+
root_element = root_element_for(op_details)
|
129
|
+
schema_namespace = root_element.namespace.prefix
|
130
|
+
root_type = root_element['type']
|
131
|
+
if root_type
|
132
|
+
@wsdl_schemas.xpath("//*[@name='#{value_after_namespace(root_type)}']//#{schema_namespace}:element")
|
133
|
+
else
|
134
|
+
return [] unless complex_type? root_element # Empty Array if there are no root elements
|
135
|
+
|
136
|
+
complex_type = root_element.children.find { |c| c.name == 'complexType' }
|
137
|
+
sequence = complex_type.children.find { |c| c.name == 'sequence' }
|
138
|
+
sequence.xpath("#{schema_namespace}:element")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Adds documentation content for all children of XML element
|
143
|
+
# This will be an example yaml for setting SOAP requests
|
144
|
+
# @param [Nokogiri::XML::Element] element Type to document for
|
145
|
+
# @param [Integer] depth How many times to iterate depth for
|
146
|
+
def document_type_for(element, depth = 1)
|
147
|
+
# raise "Too far deep for #{element}" unless depth < 6
|
148
|
+
return unless depth < 6
|
149
|
+
|
150
|
+
if complex_type? element
|
151
|
+
complex_type = element.children.find { |c| name_after_namespace(c) == 'complexType' }
|
152
|
+
sequence = complex_type.children.find { |c| name_after_namespace(c) == 'sequence' }
|
153
|
+
sequence.children.select { |node| node.class == Nokogiri::XML::Element }.each do |sub_element|
|
154
|
+
document_type_for sub_element, depth + 1
|
155
|
+
end
|
156
|
+
else
|
157
|
+
return "No type seen for #{element}, #{element.class}" unless element['type']
|
158
|
+
|
159
|
+
name = element['name']
|
160
|
+
type = value_after_namespace(element['type'])
|
161
|
+
@use_camel_case = true unless /[[:upper:]]/.match(name[0]).nil?
|
162
|
+
spaces = ' ' * depth
|
163
|
+
@content += "#{spaces}#{name.snakecase}: #{fill_in_field_from_type(type)} # #{type} \n"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# @todo This should return YAML rather than just set an instance variable
|
168
|
+
# Makes a yaml string in a '@content' instance variable
|
169
|
+
# @param [Nokogiri::XML::NodeSet] list List to convert to YAML
|
170
|
+
def wsdl_to_yaml_for(list)
|
171
|
+
raise "'@content' string must be set" if @content.nil?
|
172
|
+
|
173
|
+
list.each { |element| document_type_for element }
|
174
|
+
end
|
175
|
+
|
176
|
+
# Prompt user for wsdl
|
177
|
+
def ask_wsdl
|
178
|
+
prompt = <<-WSDL_LOC
|
179
|
+
Enter WSDL:
|
180
|
+
WSDL_LOC
|
181
|
+
print prompt.chop
|
182
|
+
@wsdl = $stdin.gets.strip
|
183
|
+
puts
|
184
|
+
end
|
185
|
+
|
186
|
+
# Prompt user for Service name for wsdl
|
187
|
+
def name_of_wsdl
|
188
|
+
prompt = <<-WSDL_NAME
|
189
|
+
Enter what you would like to name WSDL (CamelCase):
|
190
|
+
WSDL_NAME
|
191
|
+
print prompt.chop
|
192
|
+
@name = $stdin.gets.strip
|
193
|
+
puts
|
194
|
+
end
|
195
|
+
|
196
|
+
# Prompt user to enter basic auth details
|
197
|
+
# @return [Array] Array with Basic auth username and password entered
|
198
|
+
def enter_auth_details
|
199
|
+
prompt = <<-AUTH_PROMPT
|
200
|
+
User Name:
|
201
|
+
AUTH_PROMPT
|
202
|
+
print prompt.chop
|
203
|
+
auth_name = $stdin.gets.strip
|
204
|
+
puts
|
205
|
+
|
206
|
+
prompt = <<-PASSWORD
|
207
|
+
User Password:
|
208
|
+
PASSWORD
|
209
|
+
print prompt.chop
|
210
|
+
auth_password = $stdin.gets.strip
|
211
|
+
puts
|
212
|
+
[auth_name, auth_password]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|