soaspec 0.0.77 → 0.0.78
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +5 -0
- data/ChangeLog +4 -0
- data/Rakefile +5 -0
- data/exe/soaspec +95 -17
- data/lib/soaspec/exe_helpers.rb +24 -447
- data/lib/soaspec/generator/.rspec.erb +5 -0
- data/lib/soaspec/generator/.travis.yml.erb +5 -0
- data/lib/soaspec/generator/Gemfile.erb +8 -0
- data/lib/soaspec/generator/README.md.erb +29 -0
- data/lib/soaspec/generator/Rakefile.erb +20 -0
- data/lib/soaspec/generator/config/data/default.yml.erb +2 -0
- data/lib/soaspec/generator/lib/blz_service.rb.erb +24 -0
- data/lib/soaspec/generator/lib/dynamic_class_content.rb.erb +12 -0
- data/lib/soaspec/generator/lib/shared_example.rb.erb +8 -0
- data/lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb +14 -0
- data/lib/soaspec/generator/spec/soap_spec.rb.erb +53 -0
- data/lib/soaspec/generator/spec/spec_helper.rb.erb +20 -0
- data/lib/soaspec/generator/template/soap_template.xml +7 -0
- data/lib/soaspec/version.rb +1 -1
- data/lib/soaspec/wsdl_generator.rb +94 -0
- data/lib/soaspec.rb +1 -0
- metadata +16 -4
- data/exe/soaspec-generate +0 -200
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81af3fccf7fe08aef640bb651f3db64a35becdee
|
4
|
+
data.tar.gz: 4f3147e1f49580a340a698adf1531da764f21d58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '049af0af886c7087970fc9825afbbe1590a5088ce0cdcc60db865d1d8271578dba801c5603c50bdc1d44e38d920513612f0ccb724e30eca5551f4d19062dfb32'
|
7
|
+
data.tar.gz: a03feb257476d536b6cc03a4ce7c05939b90660d847dbae522f4d667be991596434c21f988361a28d94fee7f5f26afcda70b8759ab84c28cc48a44a703d1bfb2
|
data/.gitlab-ci.yml
CHANGED
data/ChangeLog
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
Version 0.0.78
|
2
|
+
* Enhancements
|
3
|
+
* Use 'thor' for `soaspec generate`, allowing less prompt and more options through command line. Added tests for it
|
4
|
+
|
1
5
|
Version 0.0.77
|
2
6
|
* Enhancements
|
3
7
|
* Use 'thor' for soaspec-init binary changing it to be `soaspec init`. Will update `soaspec-generate` in next version
|
data/Rakefile
CHANGED
@@ -7,6 +7,11 @@ ENV['test'] ||= ''
|
|
7
7
|
|
8
8
|
RSpec::Core::RakeTask.new(:run_spec) do |t|
|
9
9
|
t.pattern = "spec/**/#{ENV['folder']}*/#{ENV['test']}*_spec.rb"
|
10
|
+
t.exclude_pattern = 'spec/exe/*_spec.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new(exe_spec: %i[start_test_server]) do |t|
|
14
|
+
t.pattern = 'spec/exe/*_spec.rb'
|
10
15
|
end
|
11
16
|
|
12
17
|
desc 'Run tests'
|
data/exe/soaspec
CHANGED
@@ -7,39 +7,117 @@ require 'savon'
|
|
7
7
|
require 'soaspec'
|
8
8
|
|
9
9
|
module Soaspec
|
10
|
+
|
10
11
|
# Common executable for Soaspec
|
11
12
|
class Exe < Thor
|
12
13
|
|
13
14
|
include Soaspec::ExeHelpers
|
15
|
+
include Soaspec::WsdlGenerator
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
long_desc <<-LONGDESC
|
18
|
+
`soaspec new` will generate the initial files and folders for starting a testing project using soaspec
|
19
|
+
\x5
|
20
|
+
|
21
|
+
`soaspec new soap` will create example files testing against a virtual SOAP service
|
22
|
+
\x5
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
`soaspec new rest` will create example files testing against a virtual REST service
|
25
|
+
LONGDESC
|
26
|
+
desc 'new [type]', 'Initialize soaspec repository'
|
27
|
+
option :ci, default: 'jenkins', banner: 'What Continuous Integration is used'
|
28
|
+
option :virtual, type: :boolean, default: true, banner: 'Whether to set things up for a virtual server'
|
29
|
+
def new(type = 'initial')
|
30
|
+
puts 'Creating files for soaspec'
|
31
|
+
@virtual = options[:virtual]
|
32
|
+
create_file(filename: 'Gemfile')
|
33
|
+
create_file(filename: 'Rakefile')
|
34
|
+
create_file(filename: '.rspec')
|
35
|
+
create_file(filename: '.travis.yml') if options[:ci] == 'travis'
|
36
|
+
create_file(filename: 'README.md')
|
22
37
|
create_folder 'lib'
|
23
|
-
|
24
|
-
|
38
|
+
if type == 'soap'
|
39
|
+
create_file filename: 'lib/blz_service.rb'
|
40
|
+
create_file filename: 'lib/shared_example.rb'
|
41
|
+
end
|
25
42
|
create_folder 'config'
|
26
43
|
create_folder 'config/data'
|
27
|
-
create_file(filename: 'config/data/default.yml'
|
44
|
+
create_file(filename: 'config/data/default.yml')
|
28
45
|
create_folder 'spec'
|
29
|
-
|
30
|
-
|
31
|
-
create_file(filename: 'spec/spec_helper.rb', content: spec_helper_content)
|
32
|
-
create_file(filename: 'spec/soap_spec.rb', content: soap_spec_content)
|
33
|
-
create_file(filename: 'spec/test_server.rb', content: test_server_content)
|
34
|
-
create_file(filename: 'spec/test_data/wsdl/get_bank.wsdl', content: test_wsdl_content)
|
46
|
+
create_file(filename: 'spec/spec_helper.rb')
|
47
|
+
create_file(filename: 'spec/soap_spec.rb') if type == 'soap'
|
35
48
|
create_folder 'template'
|
36
|
-
create_file(filename: 'template/soap_template.xml',
|
49
|
+
create_file(filename: 'template/soap_template.xml', erb: false) if type == 'soap'
|
37
50
|
create_folder 'logs'
|
38
51
|
|
39
52
|
puts "Run 'bundle install' to install necessary gems"
|
40
53
|
puts "Run 'rake spec' to run the tests"
|
41
|
-
puts "Note: Setup runs Sinatra for Test Service on port 4567 by default. Change Rakefile 'start_test_server' task to update this"
|
42
54
|
end
|
55
|
+
|
56
|
+
desc 'generate', 'Generate initial test code from wsdl'
|
57
|
+
long_desc <<-LONGDESC
|
58
|
+
`soaspec generate wsdl=wsdl name=ServiceName ` will generate the initial files and folders to test each operation in a wsdl
|
59
|
+
\x5
|
60
|
+
Additionally the auth parameter can be used to use basic authentication to retrieve the WSDL.
|
61
|
+
To do use the following `soaspec generate --auth=basic`
|
62
|
+
|
63
|
+
LONGDESC
|
64
|
+
option :wsdl, required: true, aliases: :w
|
65
|
+
option :name, default: 'Service', aliases: :n
|
66
|
+
option :ci, default: 'jenkins', banner: 'What Continuous Integration is used'
|
67
|
+
option :auth
|
68
|
+
option :string_default, default: 'test string'
|
69
|
+
def generate
|
70
|
+
enter_auth_details if options[:auth] == 'basic'
|
71
|
+
@virtual = false
|
72
|
+
savon_options = { wsdl: options[:wsdl] }
|
73
|
+
savon_options[:basic_auth] = [@auth_name, @auth_password] if options[:auth] == 'basic'
|
74
|
+
|
75
|
+
@wsdl_doc = Savon.client(**savon_options).wsdl
|
76
|
+
@wsdl_schemas = @wsdl_doc.parser.schemas
|
77
|
+
|
78
|
+
create_file filename: 'Rakefile', ignore_if_present: true
|
79
|
+
create_file filename: 'Gemfile', ignore_if_present: true
|
80
|
+
create_file(filename: '.rspec')
|
81
|
+
create_file(filename: '.travis.yml') if options[:ci] == 'travis'
|
82
|
+
create_file filename: 'README.md', ignore_if_present: true
|
83
|
+
create_folder 'spec'
|
84
|
+
create_file filename: 'spec/spec_helper.rb', ignore_if_present: true
|
85
|
+
|
86
|
+
create_folder 'logs'
|
87
|
+
create_folder 'config'
|
88
|
+
create_folder 'config/data'
|
89
|
+
create_folder 'lib'
|
90
|
+
create_file filename: "lib/#{options[:name].snakecase}.rb", content: class_content
|
91
|
+
|
92
|
+
# Files according to WSDL
|
93
|
+
@wsdl_doc.operations.each do |operation, details|
|
94
|
+
puts "Creating files for operation: #{operation}"
|
95
|
+
@content = "default:\n"
|
96
|
+
@use_camel_case = false
|
97
|
+
puts 'Message params: ' + details.to_s
|
98
|
+
# From namespace identifier, find namespace, and for that find schemaLocation xsd and use that to build request
|
99
|
+
if details[:parameters]
|
100
|
+
details[:parameters].each do |element, details|
|
101
|
+
@use_camel_case = true if /[[:upper:]]/.match(element.to_s[0]) != nil
|
102
|
+
@content += " #{element.to_s.snakecase}: #{fill_in_field_from_type(details[:type])} # #{details[:type]} \n"
|
103
|
+
# TODO: If details is a Hash need to loop again
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
root_type = @wsdl_schemas.at_xpath("//*[@name='#{details[:input]}']")['type'].split(':').last
|
108
|
+
root_elements = @wsdl_schemas.xpath("//*[@name='#{root_type}']//xsd:element")
|
109
|
+
wsdl_to_yaml_for root_elements
|
110
|
+
|
111
|
+
params = []
|
112
|
+
params << 'convert_request_keys_to: :camelcase' if @use_camel_case
|
113
|
+
params_string = params == [] ? '' : ', ' + params.join(', ')
|
114
|
+
@class_params = "'#{camel_case(operation)}'#{params_string}"
|
115
|
+
|
116
|
+
create_file(filename: "config/data/#{operation}.yml", content: @content)
|
117
|
+
create_file(filename: "spec/#{operation}_spec.rb", content: generated_soap_spec_for(operation))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
43
121
|
end
|
44
122
|
end
|
45
123
|
|
data/lib/soaspec/exe_helpers.rb
CHANGED
@@ -1,16 +1,27 @@
|
|
1
1
|
|
2
|
+
require 'fileutils'
|
2
3
|
module Soaspec
|
3
4
|
# Help with tasks common to soaspec executables
|
4
5
|
module ExeHelpers
|
5
|
-
|
6
|
+
|
7
|
+
# Spec task string depending upon whether virtual is used
|
8
|
+
def spec_task
|
9
|
+
task_name = options[:virtual] ? 'spec: :start_test_server' : ':spec'
|
10
|
+
"RSpec::Core::RakeTask.new(#{task_name}) do |t|"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Retrieve default file contents based on filename
|
14
|
+
def retrieve_contents(filename, erb)
|
15
|
+
default_file = File.join(File.dirname(__FILE__), 'generator', filename + (erb ? '.erb' : ''))
|
16
|
+
contents = File.read(default_file)
|
17
|
+
erb ? ERB.new(contents).result(binding) : contents
|
18
|
+
end
|
6
19
|
|
7
20
|
# @param [String] filename Name of the file to create
|
8
21
|
# @param [String] content Content to place inside file
|
9
|
-
def create_file(filename: nil, content: nil, ignore_if_present: false)
|
10
|
-
#filename = options[:filename]
|
22
|
+
def create_file(filename: nil, content: nil, ignore_if_present: false, erb: true)
|
11
23
|
raise 'Need to pass filename' unless filename
|
12
|
-
|
13
|
-
raise 'Need to pass contents to insert into file' unless content
|
24
|
+
content ||= retrieve_contents(filename, erb)
|
14
25
|
if File.exist? filename
|
15
26
|
old_content = File.read(filename)
|
16
27
|
if old_content != content && !ignore_if_present
|
@@ -24,456 +35,22 @@ module Soaspec
|
|
24
35
|
|
25
36
|
def create_folder(folder)
|
26
37
|
if File.exist? folder
|
27
|
-
unless File.directory? folder
|
28
|
-
warn "!! #{folder} already exists and is not a directory"
|
29
|
-
end
|
38
|
+
warn "!! #{folder} already exists and is not a directory" unless File.directory? folder
|
30
39
|
else
|
31
40
|
FileUtils.mkdir folder
|
32
41
|
puts "Created folder: #{folder}/"
|
33
42
|
end
|
34
43
|
end
|
35
44
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
require 'rspec/core/rake_task' # See See https://relishapp.com/rspec/rspec-core/docs/command-line/rake-task for details
|
40
|
-
|
41
|
-
# This runs `rspec` command with the following options. Type `rake spec` to run this task
|
42
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
43
|
-
t.pattern = "spec/*_spec.rb" # Run all specs in 'spec' folder ending in '_spec'
|
44
|
-
# Next line shows output on the screen, Junit xml report and an HTML report
|
45
|
-
t.rspec_opts = "--format documentation --format RspecJunitFormatter --out logs/spec.xml --format html --out logs/spec.html"
|
46
|
-
t.fail_on_error = false
|
47
|
-
end
|
48
|
-
|
49
|
-
task :default => :spec # This runs the 'spec' task by default when no task is mentioned. E.g., if only `rake` is typed
|
50
|
-
|
51
|
-
RAKE
|
52
|
-
end
|
53
|
-
|
54
|
-
def rake_virtual_content
|
55
|
-
<<-EOF
|
56
|
-
# The list of task for a Rake file can be seen with `rake -T`
|
57
|
-
require 'rspec/core/rake_task' # See See https://relishapp.com/rspec/rspec-core/docs/command-line/rake-task for details
|
58
|
-
|
59
|
-
# This runs `rspec` command with the following options. Type `rake spec` to run this task
|
60
|
-
RSpec::Core::RakeTask.new(:run_spec) do |t|
|
61
|
-
t.pattern = "spec/*_spec.rb" # Run all specs in 'spec' folder ending in '_spec'
|
62
|
-
# Next line shows output on the screen, Junit xml report and an HTML report
|
63
|
-
t.rspec_opts = "--format documentation --format RspecJunitFormatter --out logs/spec.xml --format html --out logs/spec.html"
|
64
|
-
t.fail_on_error = false
|
65
|
-
end
|
66
|
-
|
67
|
-
task :spec => %w[start_test_server run_spec]
|
68
|
-
|
69
|
-
task :default => :spec # This runs the 'spec' task by default when no task is mentioned. E.g., if only `rake` is typed
|
70
|
-
|
71
|
-
desc 'Start virtual web service'
|
72
|
-
task :start_test_server do
|
73
|
-
ENV['test_server_pid'] = Process.spawn('ruby', 'spec/test_server.rb', err: %w[logs/test_server.log w]).to_s
|
74
|
-
puts 'Running test server at pid ' + ENV['test_server_pid']
|
75
|
-
end
|
76
|
-
|
77
|
-
EOF
|
78
|
-
end
|
79
|
-
|
80
|
-
def gem_content
|
81
|
-
<<-EOF
|
82
|
-
source 'https://rubygems.org'
|
83
|
-
|
84
|
-
gem 'data_magic'
|
85
|
-
gem 'require_all'
|
86
|
-
gem 'rspec_junit_formatter'
|
87
|
-
gem 'rake'
|
88
|
-
gem 'soaspec'
|
89
|
-
gem 'sinatra'
|
90
|
-
|
91
|
-
EOF
|
92
|
-
end
|
93
|
-
|
94
|
-
def spec_helper_content
|
95
|
-
<<-EOF
|
96
|
-
|
97
|
-
require 'soaspec'
|
98
|
-
require 'require_all'
|
99
|
-
require_all 'lib'
|
100
|
-
require 'data_magic'
|
101
|
-
|
102
|
-
include DataMagic # Used as example of loading data smartly. Use 'data_for' method to load yml data
|
103
|
-
|
104
|
-
RSpec.configure do |config|
|
105
|
-
# This will make backtrace much shorter by removing many lines from rspec failure message
|
106
|
-
config.backtrace_exclusion_patterns = [
|
107
|
-
/rspec/
|
108
|
-
]
|
109
|
-
|
110
|
-
# Close test server after all RSpec tests have run
|
111
|
-
config.after(:suite) do
|
112
|
-
Process.kill(:QUIT, ENV['test_server_pid'].to_i) if ENV['test_server_pid'] # && Process.wait - causes failure
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
EOF
|
118
|
-
end
|
119
|
-
|
120
|
-
# @return [String] Content of README.md to aid someone getting started with this using this gem
|
121
|
-
def readme_content
|
122
|
-
<<-EOF
|
123
|
-
|
124
|
-
# Installation
|
125
|
-
|
126
|
-
Run `bundle install` to install the gems mentioned in the Gemfile.
|
127
|
-
|
128
|
-
To avoid conflict with gems on the machine globally it may be better to specify gem location with:
|
129
|
-
|
130
|
-
`bundle install --path ~/.gem`
|
131
|
-
|
132
|
-
# Running tests
|
133
|
-
On the command line type:
|
134
|
-
`bundle exec rake spec` or simply `bundle exec rake`
|
135
|
-
|
136
|
-
# Structure
|
137
|
-
|
138
|
-
## Tests
|
139
|
-
Tests are within the 'spec' folder and end in '_spec'. Setup and teardown for tests is in 'spec/spec_helper'
|
140
|
-
|
141
|
-
## Templates
|
142
|
-
These are the base requests with ERB inside them to create smartly changing requests accoring to the test.yml
|
143
|
-
|
144
|
-
## Data
|
145
|
-
Data used in the test is stored in `config/data` folder. The `data_magic` gem is used by default to read files here.
|
146
|
-
|
147
|
-
## Libaries
|
148
|
-
Libaries to be installed are in 'Gemfile'. Specific gem versions can be specified here and enforeced with `bundle exec rake`
|
149
|
-
|
150
|
-
## Reports
|
151
|
-
Reports are shown in the 'logs' folder. By default Rake produces a junit, an html report, and a `traffic.log` file with the API request and responses in it
|
152
|
-
|
153
|
-
EOF
|
154
|
-
end
|
155
|
-
|
156
|
-
def test_server_content
|
157
|
-
<<-FILEEOF
|
158
|
-
# Used to run virtual web service on localhost. This makes tests more reliable and faster
|
159
|
-
|
160
|
-
require 'sinatra'
|
161
|
-
require 'nokogiri'
|
162
|
-
require 'erb'
|
163
|
-
|
164
|
-
# Representing a GetBank SOAP service
|
165
|
-
class GetBank
|
166
|
-
|
167
|
-
def self.success_response_template
|
168
|
-
<<-EOF
|
169
|
-
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
|
170
|
-
<soapenv:Body>
|
171
|
-
<ns1:getBankResponse xmlns:ns1="http://thomas-bayer.com/blz/">
|
172
|
-
<ns1:details>
|
173
|
-
<ns1:bezeichnung>Deutsche Bank</ns1:bezeichnung>
|
174
|
-
<ns1:bic>DEUTDEMMXXX <%= soap_action %></ns1:bic>
|
175
|
-
<ns1:ort>München</ns1:ort>
|
176
|
-
<ns1:plz><%= @test_id %></ns1:plz>
|
177
|
-
</ns1:details>
|
178
|
-
</ns1:getBankResponse>
|
179
|
-
</soapenv:Body>
|
180
|
-
</soapenv:Envelope>
|
181
|
-
EOF
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.error_response_template
|
185
|
-
<<-EOF
|
186
|
-
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
|
187
|
-
<soapenv:Body>
|
188
|
-
<soapenv:Fault>
|
189
|
-
<soapenv:Code>
|
190
|
-
<soapenv:Value>soapenv:Receiver</soapenv:Value>
|
191
|
-
</soapenv:Code>
|
192
|
-
<soapenv:Reason>
|
193
|
-
<soapenv:Text xml:lang="en-US">org.apache.axis2.databinding.ADBException: Unexpected subelement getBank</soapenv:Text>
|
194
|
-
</soapenv:Reason>
|
195
|
-
<soapenv:Detail>
|
196
|
-
<Exception>org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank
|
197
|
-
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:417)
|
198
|
-
at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.fromOM(BLZServiceMessageReceiverInOut.java:124)
|
199
|
-
at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.invokeBusinessLogic(BLZServiceMessageReceiverInOut.java:43)
|
200
|
-
at org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver.invokeBusinessLogic(AbstractInOutSyncMessageReceiver.java:42)
|
201
|
-
at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:96)
|
202
|
-
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:145)
|
203
|
-
at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
|
204
|
-
at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:120)
|
205
|
-
at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
|
206
|
-
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
|
207
|
-
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
|
208
|
-
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
|
209
|
-
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
|
210
|
-
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
|
211
|
-
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
|
212
|
-
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
|
213
|
-
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
|
214
|
-
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
|
215
|
-
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
|
216
|
-
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683)
|
217
|
-
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
|
218
|
-
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
|
219
|
-
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
|
220
|
-
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
|
221
|
-
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
|
222
|
-
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
|
223
|
-
at java.lang.Thread.run(Thread.java:745)
|
224
|
-
Caused by: java.lang.Exception: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank
|
225
|
-
at com.thomas_bayer.adb.GetBankType$Factory.parse(GetBankType.java:423)
|
226
|
-
at com.thomas_bayer.adb.GetBank$Factory.parse(GetBank.java:304)
|
227
|
-
at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.fromOM(BLZServiceMessageReceiverInOut.java:117)
|
228
|
-
... 25 more
|
229
|
-
Caused by: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank
|
230
|
-
at com.thomas_bayer.adb.GetBankType$Factory.parse(GetBankType.java:410)
|
231
|
-
... 27 more
|
232
|
-
</Exception>
|
233
|
-
</soapenv:Detail>
|
234
|
-
</soapenv:Fault>
|
235
|
-
</soapenv:Body>
|
236
|
-
</soapenv:Envelope>
|
237
|
-
EOF
|
238
|
-
end
|
239
|
-
|
240
|
-
def self.response_for(request)
|
241
|
-
request_body = request.body
|
242
|
-
soap_action = request.env['HTTP_SOAPACTION'].strip
|
243
|
-
doc = Nokogiri::XML(request_body)
|
244
|
-
blz_element = doc.xpath('//tns:blz').first
|
245
|
-
return 500, error_response_template unless blz_element
|
246
|
-
@test_id = blz_element.inner_text
|
247
|
-
ERB.new(success_response_template).result(binding)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
# This is the one being hit
|
252
|
-
post '/BLZService' do
|
253
|
-
GetBank.response_for request
|
254
|
-
end
|
255
|
-
FILEEOF
|
256
|
-
end
|
257
|
-
|
258
|
-
def weather_web_service
|
259
|
-
<<-WEATH_WEB
|
260
|
-
require 'soaspec'
|
261
|
-
|
262
|
-
# This class is not part of the gem. It's an example of a class you can make
|
263
|
-
# to describe your APIs. Usually this would exist in the 'lib' directory
|
264
|
-
# Common configuration for the Savon client should go here
|
265
|
-
class BLZService < Soaspec::SoapHandler
|
266
|
-
# Add to or override default Savon client options
|
267
|
-
def savon_options
|
268
|
-
{
|
269
|
-
# wsdl: 'http://www.thomas-bayer.com/axis2/services/BLZService?wsdl' # External
|
270
|
-
wsdl: File.join('spec', 'test_data', 'wsdl', 'get_bank.wsdl')
|
271
|
-
}
|
272
|
-
end
|
273
|
-
|
274
|
-
# # Specifying that get_weather_result must be present in the SOAP response
|
275
|
-
mandatory_elements [:plz]
|
276
|
-
|
277
|
-
# Example of xpath value that must be true for all success scenarios
|
278
|
-
mandatory_xpath_values 'ns1:bezeichnung' => 'Deutsche Bank'
|
279
|
-
|
280
|
-
# Example of setting an attribute on the root XML element
|
281
|
-
root_attributes 'Version' => '1' # TODO: Create test on request for this
|
282
|
-
|
283
|
-
end
|
284
|
-
|
285
|
-
WEATH_WEB
|
286
|
-
end
|
287
|
-
|
288
|
-
def soap_spec_content
|
289
|
-
<<-SOAP_SPEC
|
290
|
-
|
291
|
-
require 'spec_helper'
|
292
|
-
|
293
|
-
Soaspec.strip_namespaces = true # This allows namespace not to be used. Be careful with this
|
294
|
-
|
295
|
-
id = '70070010'
|
296
|
-
# BLZService.new(template_name: 'soap_template') Use this instead of default_hash to use template approach
|
297
|
-
|
298
|
-
context 'Test Examples' do
|
299
|
-
context BLZService.new('Get Bank', operation: :get_bank, default_hash: { blz: id }) do
|
300
|
-
|
301
|
-
describe Exchange.new(:default) do
|
302
|
-
it { is_expected.to contain_value id }
|
303
|
-
it { is_expected.to include_in_body id }
|
304
|
-
it_behaves_like 'success scenario'
|
305
|
-
after(:all) { described_class.store(:title, 'bezeichnung') }
|
306
|
-
end
|
307
|
-
|
308
|
-
describe Exchange.new(:xpath_eg, blz: 100000) do
|
309
|
-
its(['plz']) { is_expected.to eq '100000' }
|
310
|
-
it { is_expected.to have_xpath_value '//ns1:bezeichnung' => 'Deutsche Bank' }
|
311
|
-
context 'Handle retrieving stored value' do
|
312
|
-
it { is_expected.to have_xpath_value 'bezeichnung' => described_class.retrieve(:title) }
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
describe Exchange.new(:yaml_eg, data_for(:small_id)) do
|
317
|
-
it_behaves_like 'success scenario'
|
318
|
-
end
|
319
|
-
|
320
|
-
# Retry for success more for web services that intermittently fail
|
321
|
-
describe Exchange.new(:short_hand_xpath).retry_for_success do
|
322
|
-
# Be careful. If you call a method that does not use namespaces, calling one that does may not find the element
|
323
|
-
its(['ns1:bezeichnung']) { is_expected.to eq 'Deutsche Bank' } # '//' is not required at the beginning
|
324
|
-
end
|
325
|
-
describe Exchange.new('Check existence of elements') do
|
326
|
-
it { is_expected.to have_element_at_xpath '//ns1:bezeichnung' }
|
327
|
-
it { is_expected.not_to have_element_at_xpath '//ns1:bezeichnung_pretend' }
|
328
|
-
end
|
329
|
-
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
error_example = BLZService.new('Error example')
|
334
|
-
error_example.operation = :get_bank
|
335
|
-
error_example.default_hash = {}
|
336
|
-
|
337
|
-
context 'Error Examples' do
|
338
|
-
context error_example do
|
339
|
-
describe Exchange.new(:no_blz_error) do
|
340
|
-
it_behaves_like 'error scenario'
|
341
|
-
end
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
|
346
|
-
SOAP_SPEC
|
45
|
+
# Create class representing wsdl in general
|
46
|
+
def class_content
|
47
|
+
ERB.new(File.read(File.join(File.dirname(__FILE__), 'generator', 'lib/dynamic_class_content.rb.erb'))).result(binding)
|
347
48
|
end
|
348
49
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
shared_examples_for 'error scenario' do
|
355
|
-
it 'does not have status code of 200' do
|
356
|
-
expect(described_class.status_code).not_to eq 200
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
SHARE_EG
|
361
|
-
end
|
362
|
-
|
363
|
-
def soap_template_content
|
364
|
-
<<-SOAP_TEMP
|
365
|
-
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://thomas-bayer.com/blz/" xmlns:env="http://www.w3.org/2003/05/soap-envelope">
|
366
|
-
<env:Body>
|
367
|
-
<tns:getBank>
|
368
|
-
<tns:blz><%= test_values[:blz] || '70070010' %></tns:blz>
|
369
|
-
</tns:getBank>
|
370
|
-
</env:Body>
|
371
|
-
</env:Envelope>
|
372
|
-
SOAP_TEMP
|
373
|
-
end
|
374
|
-
|
375
|
-
def default_yaml_content
|
376
|
-
<<-DEF_YAML
|
377
|
-
small_id:
|
378
|
-
blz: 100
|
379
|
-
|
380
|
-
DEF_YAML
|
381
|
-
end
|
382
|
-
|
383
|
-
def test_wsdl_content
|
384
|
-
<<TEST_WSDL
|
385
|
-
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:tns="http://thomas-bayer.com/blz/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://thomas-bayer.com/blz/">
|
386
|
-
<wsdl:documentation>BLZService</wsdl:documentation>
|
387
|
-
<wsdl:types>
|
388
|
-
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://thomas-bayer.com/blz/">
|
389
|
-
<xsd:element name="getBank" type="tns:getBankType"/>
|
390
|
-
<xsd:element name="getBankResponse" type="tns:getBankResponseType"/>
|
391
|
-
<xsd:complexType name="getBankType">
|
392
|
-
<xsd:sequence>
|
393
|
-
<xsd:element name="blz" type="xsd:string"/>
|
394
|
-
</xsd:sequence>
|
395
|
-
</xsd:complexType>
|
396
|
-
<xsd:complexType name="getBankResponseType">
|
397
|
-
<xsd:sequence>
|
398
|
-
<xsd:element name="details" type="tns:detailsType"/>
|
399
|
-
</xsd:sequence>
|
400
|
-
</xsd:complexType>
|
401
|
-
<xsd:complexType name="detailsType">
|
402
|
-
<xsd:sequence>
|
403
|
-
<xsd:element minOccurs="0" name="bezeichnung" type="xsd:string"/>
|
404
|
-
<xsd:element minOccurs="0" name="bic" type="xsd:string"/>
|
405
|
-
<xsd:element minOccurs="0" name="ort" type="xsd:string"/>
|
406
|
-
<xsd:element minOccurs="0" name="plz" type="xsd:string"/>
|
407
|
-
</xsd:sequence>
|
408
|
-
</xsd:complexType>
|
409
|
-
</xsd:schema>
|
410
|
-
</wsdl:types>
|
411
|
-
<wsdl:message name="getBank">
|
412
|
-
<wsdl:part name="parameters" element="tns:getBank"/>
|
413
|
-
</wsdl:message>
|
414
|
-
<wsdl:message name="getBankResponse">
|
415
|
-
<wsdl:part name="parameters" element="tns:getBankResponse"/>
|
416
|
-
</wsdl:message>
|
417
|
-
<wsdl:portType name="BLZServicePortType">
|
418
|
-
<wsdl:operation name="getBank">
|
419
|
-
<wsdl:input message="tns:getBank"/>
|
420
|
-
<!--<wsdl:output message="tns:getBankResponse" wsaw:Action="http://thomas-bayer.com/blz/BLZService/getBankResponse"/>-->
|
421
|
-
<wsdl:output message="tns:getBankResponse" wsaw:Action="http://localhost:4567/BLZService/getBankResponse"/>
|
422
|
-
</wsdl:operation>
|
423
|
-
</wsdl:portType>
|
424
|
-
<wsdl:binding name="BLZServiceSOAP11Binding" type="tns:BLZServicePortType">
|
425
|
-
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
426
|
-
<wsdl:operation name="getBank">
|
427
|
-
<soap:operation style="document" soapAction=""/>
|
428
|
-
<wsdl:input>
|
429
|
-
<soap:body use="literal"/>
|
430
|
-
</wsdl:input>
|
431
|
-
<wsdl:output>
|
432
|
-
<soap:body use="literal"/>
|
433
|
-
</wsdl:output>
|
434
|
-
</wsdl:operation>
|
435
|
-
</wsdl:binding>
|
436
|
-
<wsdl:binding name="BLZServiceSOAP12Binding" type="tns:BLZServicePortType">
|
437
|
-
<soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
438
|
-
<wsdl:operation name="getBank">
|
439
|
-
<soap12:operation style="document" soapAction=""/>
|
440
|
-
<wsdl:input>
|
441
|
-
<soap12:body use="literal"/>
|
442
|
-
</wsdl:input>
|
443
|
-
<wsdl:output>
|
444
|
-
<soap12:body use="literal"/>
|
445
|
-
</wsdl:output>
|
446
|
-
</wsdl:operation>
|
447
|
-
</wsdl:binding>
|
448
|
-
<wsdl:binding name="BLZServiceHttpBinding" type="tns:BLZServicePortType">
|
449
|
-
<http:binding verb="POST"/>
|
450
|
-
<wsdl:operation name="getBank">
|
451
|
-
<http:operation location="BLZService/getBank"/>
|
452
|
-
<wsdl:input>
|
453
|
-
<mime:content part="getBank" type="text/xml"/>
|
454
|
-
</wsdl:input>
|
455
|
-
<wsdl:output>
|
456
|
-
<mime:content part="getBank" type="text/xml"/>
|
457
|
-
</wsdl:output>
|
458
|
-
</wsdl:operation>
|
459
|
-
</wsdl:binding>
|
460
|
-
<wsdl:service name="BLZService">
|
461
|
-
<wsdl:port name="BLZServiceSOAP11port_http" binding="tns:BLZServiceSOAP11Binding">
|
462
|
-
<!-- <soap:address location="http://www.thomas-bayer.com/axis2/services/BLZService"/> -->
|
463
|
-
<soap:address location="http://localhost:4567/BLZService"/>
|
464
|
-
</wsdl:port>
|
465
|
-
<wsdl:port name="BLZServiceSOAP12port_http" binding="tns:BLZServiceSOAP12Binding">
|
466
|
-
<!--<soap12:address location="http://www.thomas-bayer.com/axis2/services/BLZService"/>-->
|
467
|
-
<soap12:address location="http://localhost:4567/BLZService"/>
|
468
|
-
</wsdl:port>
|
469
|
-
<wsdl:port name="BLZServiceHttpport" binding="tns:BLZServiceHttpBinding">
|
470
|
-
<!--<http:address location="http://www.thomas-bayer.com/axis2/services/BLZService"/>-->
|
471
|
-
<soap:address location="http://localhost:4567/BLZService"/>
|
472
|
-
</wsdl:port>
|
473
|
-
</wsdl:service>
|
474
|
-
</wsdl:definitions>
|
475
|
-
|
476
|
-
TEST_WSDL
|
50
|
+
# Create a spec for an WSDL operation
|
51
|
+
# @param [String] operation Used in ERB to create a test for a WSDL operation
|
52
|
+
def generated_soap_spec_for(operation)
|
53
|
+
ERB.new(File.read(File.join(File.dirname(__FILE__), 'generator', 'spec/dynamic_soap_spec.rb.erb'))).result(binding)
|
477
54
|
end
|
478
55
|
|
479
56
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
# Installation
|
3
|
+
|
4
|
+
Run `bundle install` to install the gems mentioned in the Gemfile.
|
5
|
+
|
6
|
+
To avoid conflict with gems on the machine globally it may be better to specify gem location with:
|
7
|
+
|
8
|
+
`bundle install --path ~/.gem`
|
9
|
+
|
10
|
+
# Running tests
|
11
|
+
On the command line type:
|
12
|
+
`bundle exec rake spec` or simply `bundle exec rake`
|
13
|
+
|
14
|
+
# Structure
|
15
|
+
|
16
|
+
## Tests
|
17
|
+
RSpec tests are within the `spec` folder and end in `_spec`. Setup and teardown for tests is in `spec/spec_helper`
|
18
|
+
|
19
|
+
## Templates
|
20
|
+
These are the base requests with ERB inside them to create smartly changing requests accoring to the test.yml
|
21
|
+
|
22
|
+
## Data
|
23
|
+
Data used in the test is stored in `config/data` folder. The `data_magic` gem is used by default to read files here.
|
24
|
+
|
25
|
+
## Libraries
|
26
|
+
Libaries to be installed are in 'Gemfile'. Specific gem versions can be specified here and enforeced with `bundle exec rake`
|
27
|
+
|
28
|
+
## Reports
|
29
|
+
Reports are shown in the 'logs' folder. By default Rake produces a junit, an html report, and a `traffic.log` file with the API request and responses in it
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
# The list of task for a Rake file can be seen with `rake -T`
|
3
|
+
require 'rspec/core/rake_task' # See https://relishapp.com/rspec/rspec-core/docs/command-line/rake-task for details
|
4
|
+
|
5
|
+
# This runs `rspec` command with the following options. Type `rake spec` to run this task
|
6
|
+
<%= spec_task %>
|
7
|
+
t.pattern = "spec/*_spec.rb" # Run all specs in 'spec' folder ending in '_spec'
|
8
|
+
<%= 't.fail_on_error = false' if options[:ci] == 'jenkins' %>
|
9
|
+
end
|
10
|
+
|
11
|
+
task default: :spec # This runs the 'spec' task by default when no task is mentioned. E.g., if only `rake` is typed
|
12
|
+
|
13
|
+
<% if @virtual %>
|
14
|
+
desc 'Start virtual web service'
|
15
|
+
task :start_test_server do
|
16
|
+
ENV['test_server_pid'] = Process.spawn('soaspec-virtual-server', err: %w[logs/test_server.log w]).to_s
|
17
|
+
puts 'Running test server at pid ' + ENV['test_server_pid']
|
18
|
+
sleep 0.5 # Wait a little for virtual server to start up
|
19
|
+
end
|
20
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
require 'soaspec'
|
3
|
+
|
4
|
+
# This class is not part of the gem. It's an example of a class you can make
|
5
|
+
# to describe your APIs. Usually this would exist in the 'lib' directory
|
6
|
+
# Common configuration for the Savon client should go here
|
7
|
+
class BLZService < Soaspec::SoapHandler
|
8
|
+
# Add to or override default Savon client options
|
9
|
+
def savon_options
|
10
|
+
{
|
11
|
+
wsdl: 'http://localhost:4999/BLZService?wsdl'
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
# # Specifying that get_weather_result must be present in the SOAP response
|
16
|
+
mandatory_elements [:plz]
|
17
|
+
|
18
|
+
# Example of xpath value that must be true for all success scenarios
|
19
|
+
mandatory_xpath_values 'ns1:bezeichnung' => 'Deutsche Bank'
|
20
|
+
|
21
|
+
# Example of setting an attribute on the root XML element
|
22
|
+
root_attributes 'Version' => '1'
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
Soaspec.strip_namespaces = true # This allows namespace not to be used. Be careful with this
|
5
|
+
|
6
|
+
<%= operation %> = <%= options[:name] %>.new(<%= @class_params %>)
|
7
|
+
<%= operation %>.operation = :<%= operation %>
|
8
|
+
<%= operation %>.default_hash = data_for '<%= operation %>/default'
|
9
|
+
|
10
|
+
context <%= operation %> do
|
11
|
+
describe Exchange.new(:default) do
|
12
|
+
it_behaves_like 'success scenario'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
Soaspec.strip_namespaces = true # This allows namespace not to be used. Be careful with this
|
5
|
+
|
6
|
+
id = '70070010'
|
7
|
+
# BLZService.new(template_name: 'soap_template') Use this instead of default_hash to use template approach
|
8
|
+
|
9
|
+
context 'Test Examples' do
|
10
|
+
context BLZService.new('Get Bank', operation: :get_bank, default_hash: { blz: id }) do
|
11
|
+
|
12
|
+
describe Exchange.new(:default) do
|
13
|
+
it { is_expected.to contain_value id }
|
14
|
+
it { is_expected.to include_in_body id }
|
15
|
+
it_behaves_like 'success scenario'
|
16
|
+
after(:all) { described_class.store(:title, 'bezeichnung') }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Exchange.new(:xpath_eg, blz: 100000) do
|
20
|
+
its(['plz']) { is_expected.to eq '100000' }
|
21
|
+
it { is_expected.to have_xpath_value '//ns1:bezeichnung' => 'Deutsche Bank' }
|
22
|
+
context 'Handle retrieving stored value' do
|
23
|
+
it { is_expected.to have_xpath_value 'bezeichnung' => described_class.retrieve(:title) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Exchange.new(:yaml_eg, data_for(:small_id)) do
|
28
|
+
it_behaves_like 'success scenario'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Retry for success more for web services that intermittently fail
|
32
|
+
describe Exchange.new(:short_hand_xpath).retry_for_success do
|
33
|
+
# Be careful. If you call a method that does not use namespaces, calling one that does may not find the element
|
34
|
+
its(['ns1:bezeichnung']) { is_expected.to eq 'Deutsche Bank' } # '//' is not required at the beginning
|
35
|
+
end
|
36
|
+
describe Exchange.new('Check existence of elements') do
|
37
|
+
it { is_expected.to have_element_at_xpath '//ns1:bezeichnung' }
|
38
|
+
it { is_expected.not_to have_element_at_xpath '//ns1:bezeichnung_pretend' }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
error_example = BLZService.new('Error example')
|
44
|
+
error_example.operation = :get_bank
|
45
|
+
error_example.default_hash = {}
|
46
|
+
|
47
|
+
context 'Error Examples' do
|
48
|
+
context error_example do
|
49
|
+
describe Exchange.new(:no_blz_error) do
|
50
|
+
it_behaves_like 'error scenario'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
require 'soaspec'
|
3
|
+
require 'require_all'
|
4
|
+
require_all 'lib'
|
5
|
+
require 'data_magic'
|
6
|
+
|
7
|
+
include DataMagic # Used as example of loading data smartly. Use 'data_for' method to load yml data
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
# This will make backtrace much shorter by removing many lines from rspec failure message
|
11
|
+
config.backtrace_exclusion_patterns = [
|
12
|
+
/rspec/
|
13
|
+
]
|
14
|
+
<% if @virtual %>
|
15
|
+
# Close test server after all RSpec tests have run
|
16
|
+
config.after(:suite) do
|
17
|
+
Process.kill(:QUIT, ENV['test_server_pid'].to_i) if ENV['test_server_pid']
|
18
|
+
end
|
19
|
+
<% end %>
|
20
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://thomas-bayer.com/blz/" xmlns:env="http://www.w3.org/2003/05/soap-envelope">
|
2
|
+
<env:Body>
|
3
|
+
<tns:getBank>
|
4
|
+
<tns:blz><%= test_values[:blz] || '70070010' %></tns:blz>
|
5
|
+
</tns:getBank>
|
6
|
+
</env:Body>
|
7
|
+
</env:Envelope>
|
data/lib/soaspec/version.rb
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
|
2
|
+
module Soaspec
|
3
|
+
module WsdlGenerator
|
4
|
+
def try_enum_for(type)
|
5
|
+
custom_type = @wsdl_schemas.xpath("//*[@name='#{type}']")
|
6
|
+
if custom_type.first
|
7
|
+
prefix = custom_type.first.namespace.prefix
|
8
|
+
enumerations = custom_type.xpath("//#{prefix}:enumeration")
|
9
|
+
return 'Custom Type' if enumerations.empty?
|
10
|
+
@enums_values = Array.new
|
11
|
+
enumerations.each do |enum_value|
|
12
|
+
@enums_values << "'#{enum_value['value']}'"
|
13
|
+
end
|
14
|
+
"~randomize [#{@enums_values.join(', ')}]"
|
15
|
+
else
|
16
|
+
'Custom Type'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def value_after_namespace(string)
|
21
|
+
string.split(':').last
|
22
|
+
end
|
23
|
+
|
24
|
+
# Based on WSDL type return a valid value
|
25
|
+
# @param [String] type Type without the WSDL
|
26
|
+
def fill_in_field_from_type(type)
|
27
|
+
case type
|
28
|
+
when 'string'
|
29
|
+
options[:string_default] # 'test string'
|
30
|
+
when 'int'
|
31
|
+
2
|
32
|
+
when 'boolean'
|
33
|
+
true
|
34
|
+
when 'double'
|
35
|
+
'1.5'
|
36
|
+
else
|
37
|
+
try_enum_for type
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [String, Symbol] underscore_separated Snakecase value to be converted to camel case
|
42
|
+
def camel_case(underscore_separated)
|
43
|
+
underscore_separated.to_s.split('_').collect(&:capitalize).join
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [Nokogiri::NodeSet] list List
|
47
|
+
def wsdl_to_yaml_for(list)
|
48
|
+
puts list
|
49
|
+
list.each do |element|
|
50
|
+
name = element['name']
|
51
|
+
type = value_after_namespace(element['type'])
|
52
|
+
puts 'Name ' + name + ' type ' + type
|
53
|
+
@use_camel_case = true if (/[[:upper:]]/.match(name[0]) != nil)
|
54
|
+
@content += " #{name.snakecase}: #{fill_in_field_from_type(type)} # #{type} \n"
|
55
|
+
# TODO: If details is a Hash need to loop again
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def ask_wsdl
|
60
|
+
prompt = <<-EOF
|
61
|
+
Enter WSDL:
|
62
|
+
EOF
|
63
|
+
print prompt.chop
|
64
|
+
@wsdl = $stdin.gets.strip
|
65
|
+
puts
|
66
|
+
end
|
67
|
+
|
68
|
+
def name_of_wsdl
|
69
|
+
prompt = <<-EOF
|
70
|
+
Enter what you would like to name WSDL (CamelCase):
|
71
|
+
EOF
|
72
|
+
print prompt.chop
|
73
|
+
@name = $stdin.gets.strip
|
74
|
+
puts
|
75
|
+
end
|
76
|
+
|
77
|
+
# Prompt user to enter basic auth details
|
78
|
+
def enter_auth_details
|
79
|
+
prompt = <<-EOF
|
80
|
+
User Name:
|
81
|
+
EOF
|
82
|
+
print prompt.chop
|
83
|
+
@auth_name = $stdin.gets.strip
|
84
|
+
puts
|
85
|
+
|
86
|
+
prompt = <<-EOF
|
87
|
+
User Password:
|
88
|
+
EOF
|
89
|
+
print prompt.chop
|
90
|
+
@auth_password = $stdin.gets.strip
|
91
|
+
puts
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/soaspec.rb
CHANGED
@@ -26,6 +26,7 @@ require 'soaspec/test_server/get_bank'
|
|
26
26
|
require 'soaspec/test_server/test_attribute'
|
27
27
|
require 'soaspec/test_server/puppy_service'
|
28
28
|
require 'soaspec/test_server/invoices'
|
29
|
+
require 'soaspec/wsdl_generator'
|
29
30
|
|
30
31
|
# Gem for handling SOAP and REST api tests
|
31
32
|
module Soaspec
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soaspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.78
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SamuelGarrattIQA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -282,7 +282,6 @@ email:
|
|
282
282
|
- samuel.garratt@integrationqa.com
|
283
283
|
executables:
|
284
284
|
- soaspec
|
285
|
-
- soaspec-generate
|
286
285
|
- soaspec-virtual-server
|
287
286
|
- xml_to_yaml_file
|
288
287
|
extensions: []
|
@@ -301,7 +300,6 @@ files:
|
|
301
300
|
- Rakefile
|
302
301
|
- Todo.md
|
303
302
|
- exe/soaspec
|
304
|
-
- exe/soaspec-generate
|
305
303
|
- exe/soaspec-virtual-server
|
306
304
|
- exe/xml_to_yaml_file
|
307
305
|
- lib/soaspec.rb
|
@@ -313,6 +311,19 @@ files:
|
|
313
311
|
- lib/soaspec/exchange_handlers/rest_methods.rb
|
314
312
|
- lib/soaspec/exchange_handlers/soap_handler.rb
|
315
313
|
- lib/soaspec/exe_helpers.rb
|
314
|
+
- lib/soaspec/generator/.rspec.erb
|
315
|
+
- lib/soaspec/generator/.travis.yml.erb
|
316
|
+
- lib/soaspec/generator/Gemfile.erb
|
317
|
+
- lib/soaspec/generator/README.md.erb
|
318
|
+
- lib/soaspec/generator/Rakefile.erb
|
319
|
+
- lib/soaspec/generator/config/data/default.yml.erb
|
320
|
+
- lib/soaspec/generator/lib/blz_service.rb.erb
|
321
|
+
- lib/soaspec/generator/lib/dynamic_class_content.rb.erb
|
322
|
+
- lib/soaspec/generator/lib/shared_example.rb.erb
|
323
|
+
- lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb
|
324
|
+
- lib/soaspec/generator/spec/soap_spec.rb.erb
|
325
|
+
- lib/soaspec/generator/spec/spec_helper.rb.erb
|
326
|
+
- lib/soaspec/generator/template/soap_template.xml
|
316
327
|
- lib/soaspec/interpreter.rb
|
317
328
|
- lib/soaspec/matchers.rb
|
318
329
|
- lib/soaspec/not_found_errors.rb
|
@@ -325,6 +336,7 @@ files:
|
|
325
336
|
- lib/soaspec/test_server/puppy_service.rb
|
326
337
|
- lib/soaspec/test_server/test_attribute.rb
|
327
338
|
- lib/soaspec/version.rb
|
339
|
+
- lib/soaspec/wsdl_generator.rb
|
328
340
|
- soaspec.gemspec
|
329
341
|
- test.wsdl
|
330
342
|
- test.xml
|
data/exe/soaspec-generate
DELETED
@@ -1,200 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# Generate Soaspec tests from a WSDL. Later Swagger, other definitions will be added
|
4
|
-
#
|
5
|
-
#http://www.webservicex.com/globalweather.asmx?wsdl
|
6
|
-
|
7
|
-
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
8
|
-
|
9
|
-
require 'savon'
|
10
|
-
require 'soaspec'
|
11
|
-
|
12
|
-
include Soaspec::ExeHelpers
|
13
|
-
|
14
|
-
def try_enum_for(type)
|
15
|
-
custom_type = @wsdl_schemas.xpath("//*[@name='#{type}']")
|
16
|
-
if custom_type.first
|
17
|
-
prefix = custom_type.first.namespace.prefix
|
18
|
-
enumerations = custom_type.xpath("//#{prefix}:enumeration")
|
19
|
-
return 'Custom Type' if enumerations.empty?
|
20
|
-
@enums_values = Array.new
|
21
|
-
enumerations.each do |enum_value|
|
22
|
-
@enums_values << "'#{enum_value['value']}'"
|
23
|
-
end
|
24
|
-
"~randomize [#{@enums_values.join(', ')}]"
|
25
|
-
else
|
26
|
-
'Custom Type'
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def value_after_namespace(string)
|
31
|
-
string.split(':').last
|
32
|
-
end
|
33
|
-
|
34
|
-
# Based on WSDL type return a valid value
|
35
|
-
# @param [String] type Type without the WSDL
|
36
|
-
def fill_in_field_from_type(type)
|
37
|
-
case type
|
38
|
-
when 'string'
|
39
|
-
'test string'
|
40
|
-
when 'int'
|
41
|
-
2
|
42
|
-
when 'boolean'
|
43
|
-
true
|
44
|
-
when 'double'
|
45
|
-
'1.5'
|
46
|
-
else
|
47
|
-
try_enum_for type
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def ask_wsdl
|
52
|
-
prompt = <<-EOF
|
53
|
-
Enter WSDL:
|
54
|
-
EOF
|
55
|
-
print prompt.chop
|
56
|
-
@wsdl = $stdin.gets.strip
|
57
|
-
puts
|
58
|
-
end
|
59
|
-
|
60
|
-
def name_of_wsdl
|
61
|
-
prompt = <<-EOF
|
62
|
-
Enter what you would like to name WSDL (CamelCase):
|
63
|
-
EOF
|
64
|
-
print prompt.chop
|
65
|
-
@name = $stdin.gets.strip
|
66
|
-
puts
|
67
|
-
end
|
68
|
-
|
69
|
-
def authentication_type
|
70
|
-
prompt = <<-EOF
|
71
|
-
Authentication
|
72
|
-
(1) Basic
|
73
|
-
(2) None
|
74
|
-
|
75
|
-
Type:
|
76
|
-
EOF
|
77
|
-
print prompt.chop
|
78
|
-
num = $stdin.gets.to_i - 1
|
79
|
-
puts
|
80
|
-
|
81
|
-
@auth = [:basic, :none][num] || :none
|
82
|
-
|
83
|
-
if @auth == :basic
|
84
|
-
prompt = <<-EOF
|
85
|
-
User Name:
|
86
|
-
EOF
|
87
|
-
print prompt.chop
|
88
|
-
@auth_name = $stdin.gets.strip
|
89
|
-
puts
|
90
|
-
|
91
|
-
prompt = <<-EOF
|
92
|
-
User Password:
|
93
|
-
EOF
|
94
|
-
print prompt.chop
|
95
|
-
@auth_password = $stdin.gets.strip
|
96
|
-
puts
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
def camel_case(underscore_seperated)
|
102
|
-
underscore_seperated.to_s.split('_').collect(&:capitalize).join
|
103
|
-
end
|
104
|
-
|
105
|
-
@class_content = <<-EOF
|
106
|
-
|
107
|
-
require 'soaspec'
|
108
|
-
|
109
|
-
class <%= @name %> < Soaspec::SoapHandler
|
110
|
-
# Add to or override default Savon client options
|
111
|
-
def savon_options
|
112
|
-
{
|
113
|
-
wsdl: '<%= @wsdl %>'
|
114
|
-
}
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
EOF
|
119
|
-
|
120
|
-
@soap_spec_content = <<-EOF
|
121
|
-
|
122
|
-
require 'spec_helper'
|
123
|
-
|
124
|
-
Soaspec.strip_namespaces = true # This allows namespace not to be used. Be careful with this
|
125
|
-
|
126
|
-
<%= operation %> = <%= @name %>.new(<%= @class_params %>)
|
127
|
-
<%= operation %>.operation = :<%= operation %>
|
128
|
-
<%= operation %>.default_hash = data_for '<%= operation %>/default'
|
129
|
-
|
130
|
-
context <%= operation %> do
|
131
|
-
describe Exchange.new(:default) do
|
132
|
-
it_behaves_like 'success scenario'
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
EOF
|
137
|
-
|
138
|
-
# @param [Nokogiri::NodeSet] list List
|
139
|
-
def wsdl_to_yaml_for(list)
|
140
|
-
puts list
|
141
|
-
list.each do |element|
|
142
|
-
name = element['name']
|
143
|
-
type = value_after_namespace(element['type'])
|
144
|
-
puts 'Name ' + name + ' type ' + type
|
145
|
-
@use_camel_case = true if (/[[:upper:]]/.match(name[0]) != nil)
|
146
|
-
@content += " #{name.snakecase}: #{fill_in_field_from_type(type)} # #{type} \n"
|
147
|
-
# TODO: If details is a Hash need to loop again
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
name_of_wsdl
|
152
|
-
ask_wsdl
|
153
|
-
|
154
|
-
authentication_type
|
155
|
-
|
156
|
-
savon_options = { wsdl: @wsdl }
|
157
|
-
savon_options[:basic_auth] = [@auth_name, @auth_password] if @auth == :basic
|
158
|
-
|
159
|
-
@wsdl_doc = Savon.client(**savon_options).wsdl
|
160
|
-
@wsdl_schemas = @wsdl_doc.parser.schemas
|
161
|
-
|
162
|
-
# Basic files. May already be there
|
163
|
-
create_file filename: 'Rakefile', content: rake_content, ignore_if_present: true
|
164
|
-
create_file filename: 'Gemfile', content: gem_content, ignore_if_present: true
|
165
|
-
create_folder 'spec'
|
166
|
-
create_file filename: 'spec/spec_helper.rb', content: spec_helper_content
|
167
|
-
create_file filename: 'README.md', content: readme_content, ignore_if_present: true
|
168
|
-
|
169
|
-
create_folder 'logs'
|
170
|
-
create_folder 'config'
|
171
|
-
create_folder 'config/data'
|
172
|
-
create_folder 'lib'
|
173
|
-
create_file filename: "lib/#{@name.to_s.snakecase}.rb", content: ERB.new(@class_content).result(binding)
|
174
|
-
# Files according to WSDL
|
175
|
-
@wsdl_doc.operations.each do |operation, details|
|
176
|
-
puts "Creating files for operation: #{operation}"
|
177
|
-
@content = "default:\n"
|
178
|
-
@use_camel_case = false
|
179
|
-
puts 'Message params: ' + details.to_s
|
180
|
-
# From namespace identifier, find namespace, and for that find schemaLocation xsd and use that to build request
|
181
|
-
if details[:parameters]
|
182
|
-
details[:parameters].each do |element, details|
|
183
|
-
@use_camel_case = true if (/[[:upper:]]/.match(element.to_s[0]) != nil)
|
184
|
-
@content += " #{element.to_s.snakecase}: #{fill_in_field_from_type(details[:type])} # #{details[:type]} \n"
|
185
|
-
# TODO: If details is a Hash need to loop again
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
root_type = @wsdl_schemas.at_xpath("//*[@name='#{details[:input]}']")['type'].split(':').last
|
190
|
-
root_elements = @wsdl_schemas.xpath("//*[@name='#{root_type}']//xsd:element")
|
191
|
-
wsdl_to_yaml_for root_elements
|
192
|
-
|
193
|
-
params = []
|
194
|
-
params << 'convert_request_keys_to: :camelcase' if @use_camel_case
|
195
|
-
params_string = params == [] ? '' : ', ' + params.join(', ')
|
196
|
-
@class_params = "'#{camel_case(operation)}'#{params_string}"
|
197
|
-
|
198
|
-
create_file(filename: "config/data/#{operation}.yml", content: @content)
|
199
|
-
create_file(filename: "spec/#{operation}_spec.rb", content: ERB.new(@soap_spec_content).result(binding))
|
200
|
-
end
|