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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67969ede0a36306652d44ece28fb979980e81e72
4
- data.tar.gz: 6ca6c9d0887c36bcbb1683299308f349c2a70180
3
+ metadata.gz: 81af3fccf7fe08aef640bb651f3db64a35becdee
4
+ data.tar.gz: 4f3147e1f49580a340a698adf1531da764f21d58
5
5
  SHA512:
6
- metadata.gz: d31d9064daa746a272fb2cac0da67f5b797f86c3258b973136f7f55f2f91678fa3f23b3fbb038a6c57ab9d431c8a21643c02d6b0d12b53189b8735dcbb09b928
7
- data.tar.gz: 54a3005df87d30182c036ca6177818dac46b0eda51856b100aa611c5c4dde276beba4f8e010545c6d74757c316990d3f7f0ae1c31c51d6cf20e591a1779d2ad3
6
+ metadata.gz: '049af0af886c7087970fc9825afbbe1590a5088ce0cdcc60db865d1d8271578dba801c5603c50bdc1d44e38d920513612f0ccb724e30eca5551f4d19062dfb32'
7
+ data.tar.gz: a03feb257476d536b6cc03a4ce7c05939b90660d847dbae522f4d667be991596434c21f988361a28d94fee7f5f26afcda70b8759ab84c28cc48a44a703d1bfb2
data/.gitlab-ci.yml CHANGED
@@ -13,6 +13,11 @@ rspec:
13
13
  paths:
14
14
  - coverage/
15
15
 
16
+ exe_spec:
17
+ stage: test
18
+ script:
19
+ - bundle exec rake exe_spec
20
+
16
21
  cucumber:
17
22
  stage: test
18
23
  script:
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
- desc 'soaspec [type]', 'Initialize soaspec repository'
16
- def init
17
- puts 'Creating files for soaspec'
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
- create_file(filename: 'Gemfile', content: gem_content)
20
- create_file(filename: 'Rakefile', content: rake_virtual_content)
21
- create_file(filename: 'README.md', content: readme_content)
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
- create_file(filename: 'lib/blz_service.rb', content: weather_web_service)
24
- create_file filename: 'lib/shared_example.rb', content: shared_examples_content
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', content: default_yaml_content)
44
+ create_file(filename: 'config/data/default.yml')
28
45
  create_folder 'spec'
29
- create_folder 'spec/test_data'
30
- create_folder 'spec/test_data/wsdl'
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', content: soap_template_content)
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
 
@@ -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
- require 'fileutils'
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
- #content = options[:content]
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
- def rake_content
37
- <<-RAKE
38
- # The list of task for a Rake file can be seen with `rake -T`
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
- def shared_examples_content
350
- <<-SHARE_EG
351
-
352
- require 'rspec'
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,5 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ <%= '--format RspecJunitFormatter --out logs/spec.xml' if options[:ci] == 'jenkins' %>
4
+ --format html --out logs/spec.html
5
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.4
5
+ before_install: gem install bundler -v 1.16.0
@@ -0,0 +1,8 @@
1
+
2
+ source 'https://rubygems.org'
3
+
4
+ gem 'data_magic'
5
+ gem 'require_all'
6
+ gem 'rake'
7
+ <%= "gem 'rspec_junit_formatter'" if options[:ci] == 'jenkins' %>
8
+ gem 'soaspec'
@@ -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,2 @@
1
+ small_id:
2
+ blz: 100
@@ -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,12 @@
1
+
2
+ require 'soaspec'
3
+
4
+ class <%= options[:name] %> < Soaspec::SoapHandler
5
+ # Add to or override default Savon client options
6
+ def savon_options
7
+ {
8
+ wsdl: '<%= options[:wsdl] %>'
9
+ }
10
+ end
11
+
12
+ end
@@ -0,0 +1,8 @@
1
+
2
+ require 'rspec'
3
+
4
+ shared_examples_for 'error scenario' do
5
+ it 'does not have status code of 200' do
6
+ expect(described_class.status_code).not_to eq 200
7
+ end
8
+ 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>
@@ -1,3 +1,3 @@
1
1
  module Soaspec
2
- VERSION = '0.0.77'.freeze
2
+ VERSION = '0.0.78'.freeze
3
3
  end
@@ -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.77
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-18 00:00:00.000000000 Z
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