lib/soaspec/exe_helpers.rb in soaspec-0.0.77 vs lib/soaspec/exe_helpers.rb in soaspec-0.0.78

- old
+ new

@@ -1,18 +1,29 @@ +require 'fileutils' module Soaspec # Help with tasks common to soaspec executables module ExeHelpers - require 'fileutils' + # Spec task string depending upon whether virtual is used + def spec_task + task_name = options[:virtual] ? 'spec: :start_test_server' : ':spec' + "RSpec::Core::RakeTask.new(#{task_name}) do |t|" + end + + # Retrieve default file contents based on filename + def retrieve_contents(filename, erb) + default_file = File.join(File.dirname(__FILE__), 'generator', filename + (erb ? '.erb' : '')) + contents = File.read(default_file) + erb ? ERB.new(contents).result(binding) : contents + end + # @param [String] filename Name of the file to create # @param [String] content Content to place inside file - def create_file(filename: nil, content: nil, ignore_if_present: false) - #filename = options[:filename] + def create_file(filename: nil, content: nil, ignore_if_present: false, erb: true) raise 'Need to pass filename' unless filename - #content = options[:content] - raise 'Need to pass contents to insert into file' unless content + content ||= retrieve_contents(filename, erb) if File.exist? filename old_content = File.read(filename) if old_content != content && !ignore_if_present warn "!! #{filename} already exists and differs from template" end @@ -22,459 +33,25 @@ end end def create_folder(folder) if File.exist? folder - unless File.directory? folder - warn "!! #{folder} already exists and is not a directory" - end + warn "!! #{folder} already exists and is not a directory" unless File.directory? folder else FileUtils.mkdir folder puts "Created folder: #{folder}/" end end - def rake_content - <<-RAKE -# The list of task for a Rake file can be seen with `rake -T` -require 'rspec/core/rake_task' # See See https://relishapp.com/rspec/rspec-core/docs/command-line/rake-task for details - -# This runs `rspec` command with the following options. Type `rake spec` to run this task -RSpec::Core::RakeTask.new(:spec) do |t| - t.pattern = "spec/*_spec.rb" # Run all specs in 'spec' folder ending in '_spec' - # Next line shows output on the screen, Junit xml report and an HTML report - t.rspec_opts = "--format documentation --format RspecJunitFormatter --out logs/spec.xml --format html --out logs/spec.html" - t.fail_on_error = false -end - -task :default => :spec # This runs the 'spec' task by default when no task is mentioned. E.g., if only `rake` is typed - - RAKE + # Create class representing wsdl in general + def class_content + ERB.new(File.read(File.join(File.dirname(__FILE__), 'generator', 'lib/dynamic_class_content.rb.erb'))).result(binding) end - def rake_virtual_content - <<-EOF -# The list of task for a Rake file can be seen with `rake -T` -require 'rspec/core/rake_task' # See See https://relishapp.com/rspec/rspec-core/docs/command-line/rake-task for details - -# This runs `rspec` command with the following options. Type `rake spec` to run this task -RSpec::Core::RakeTask.new(:run_spec) do |t| - t.pattern = "spec/*_spec.rb" # Run all specs in 'spec' folder ending in '_spec' - # Next line shows output on the screen, Junit xml report and an HTML report - t.rspec_opts = "--format documentation --format RspecJunitFormatter --out logs/spec.xml --format html --out logs/spec.html" - t.fail_on_error = false -end - -task :spec => %w[start_test_server run_spec] - -task :default => :spec # This runs the 'spec' task by default when no task is mentioned. E.g., if only `rake` is typed - -desc 'Start virtual web service' -task :start_test_server do - ENV['test_server_pid'] = Process.spawn('ruby', 'spec/test_server.rb', err: %w[logs/test_server.log w]).to_s - puts 'Running test server at pid ' + ENV['test_server_pid'] -end - - EOF - end - - def gem_content - <<-EOF -source 'https://rubygems.org' - -gem 'data_magic' -gem 'require_all' -gem 'rspec_junit_formatter' -gem 'rake' -gem 'soaspec' -gem 'sinatra' - - EOF - end - - def spec_helper_content - <<-EOF - -require 'soaspec' -require 'require_all' -require_all 'lib' -require 'data_magic' - -include DataMagic # Used as example of loading data smartly. Use 'data_for' method to load yml data - -RSpec.configure do |config| - # This will make backtrace much shorter by removing many lines from rspec failure message - config.backtrace_exclusion_patterns = [ - /rspec/ - ] - - # Close test server after all RSpec tests have run - config.after(:suite) do - Process.kill(:QUIT, ENV['test_server_pid'].to_i) if ENV['test_server_pid'] # && Process.wait - causes failure - end - -end - - EOF - end - - # @return [String] Content of README.md to aid someone getting started with this using this gem - def readme_content - <<-EOF - -# Installation - -Run `bundle install` to install the gems mentioned in the Gemfile. - -To avoid conflict with gems on the machine globally it may be better to specify gem location with: - -`bundle install --path ~/.gem` - -# Running tests -On the command line type: -`bundle exec rake spec` or simply `bundle exec rake` - -# Structure - -## Tests -Tests are within the 'spec' folder and end in '_spec'. Setup and teardown for tests is in 'spec/spec_helper' - -## Templates -These are the base requests with ERB inside them to create smartly changing requests accoring to the test.yml - -## Data -Data used in the test is stored in `config/data` folder. The `data_magic` gem is used by default to read files here. - -## Libaries -Libaries to be installed are in 'Gemfile'. Specific gem versions can be specified here and enforeced with `bundle exec rake` - -## Reports -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 - - EOF - end - - def test_server_content - <<-FILEEOF -# Used to run virtual web service on localhost. This makes tests more reliable and faster - - require 'sinatra' - require 'nokogiri' - require 'erb' - -# Representing a GetBank SOAP service - class GetBank - - def self.success_response_template - <<-EOF -<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"> - <soapenv:Body> - <ns1:getBankResponse xmlns:ns1="http://thomas-bayer.com/blz/"> - <ns1:details> - <ns1:bezeichnung>Deutsche Bank</ns1:bezeichnung> - <ns1:bic>DEUTDEMMXXX <%= soap_action %></ns1:bic> - <ns1:ort>München</ns1:ort> - <ns1:plz><%= @test_id %></ns1:plz> - </ns1:details> - </ns1:getBankResponse> - </soapenv:Body> -</soapenv:Envelope> - EOF - end - - def self.error_response_template - <<-EOF -<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"> - <soapenv:Body> - <soapenv:Fault> - <soapenv:Code> - <soapenv:Value>soapenv:Receiver</soapenv:Value> - </soapenv:Code> - <soapenv:Reason> - <soapenv:Text xml:lang="en-US">org.apache.axis2.databinding.ADBException: Unexpected subelement getBank</soapenv:Text> - </soapenv:Reason> - <soapenv:Detail> - <Exception>org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank - at org.apache.axis2.AxisFault.makeFault(AxisFault.java:417) - at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.fromOM(BLZServiceMessageReceiverInOut.java:124) - at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.invokeBusinessLogic(BLZServiceMessageReceiverInOut.java:43) - at org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver.invokeBusinessLogic(AbstractInOutSyncMessageReceiver.java:42) - at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:96) - at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:145) - at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275) - at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:120) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:646) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) - at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) - at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) - at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) - at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) - at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) - at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) - at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) - at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) - at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) - at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683) - at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) - at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) - at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) - at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315) - at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) - at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) - at java.lang.Thread.run(Thread.java:745) -Caused by: java.lang.Exception: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank - at com.thomas_bayer.adb.GetBankType$Factory.parse(GetBankType.java:423) - at com.thomas_bayer.adb.GetBank$Factory.parse(GetBank.java:304) - at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.fromOM(BLZServiceMessageReceiverInOut.java:117) - ... 25 more -Caused by: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank - at com.thomas_bayer.adb.GetBankType$Factory.parse(GetBankType.java:410) - ... 27 more -</Exception> - </soapenv:Detail> - </soapenv:Fault> - </soapenv:Body> -</soapenv:Envelope> - EOF - end - - def self.response_for(request) - request_body = request.body - soap_action = request.env['HTTP_SOAPACTION'].strip - doc = Nokogiri::XML(request_body) - blz_element = doc.xpath('//tns:blz').first - return 500, error_response_template unless blz_element - @test_id = blz_element.inner_text - ERB.new(success_response_template).result(binding) - end - end - -# This is the one being hit - post '/BLZService' do - GetBank.response_for request - end - FILEEOF - end - - def weather_web_service - <<-WEATH_WEB - require 'soaspec' - - # This class is not part of the gem. It's an example of a class you can make - # to describe your APIs. Usually this would exist in the 'lib' directory - # Common configuration for the Savon client should go here - class BLZService < Soaspec::SoapHandler - # Add to or override default Savon client options - def savon_options - { - # wsdl: 'http://www.thomas-bayer.com/axis2/services/BLZService?wsdl' # External - wsdl: File.join('spec', 'test_data', 'wsdl', 'get_bank.wsdl') - } - end - - # # Specifying that get_weather_result must be present in the SOAP response - mandatory_elements [:plz] - - # Example of xpath value that must be true for all success scenarios - mandatory_xpath_values 'ns1:bezeichnung' => 'Deutsche Bank' - - # Example of setting an attribute on the root XML element - root_attributes 'Version' => '1' # TODO: Create test on request for this - - end - - WEATH_WEB - end - - def soap_spec_content - <<-SOAP_SPEC - - require 'spec_helper' - - Soaspec.strip_namespaces = true # This allows namespace not to be used. Be careful with this - - id = '70070010' - # BLZService.new(template_name: 'soap_template') Use this instead of default_hash to use template approach - - context 'Test Examples' do - context BLZService.new('Get Bank', operation: :get_bank, default_hash: { blz: id }) do - - describe Exchange.new(:default) do - it { is_expected.to contain_value id } - it { is_expected.to include_in_body id } - it_behaves_like 'success scenario' - after(:all) { described_class.store(:title, 'bezeichnung') } - end - - describe Exchange.new(:xpath_eg, blz: 100000) do - its(['plz']) { is_expected.to eq '100000' } - it { is_expected.to have_xpath_value '//ns1:bezeichnung' => 'Deutsche Bank' } - context 'Handle retrieving stored value' do - it { is_expected.to have_xpath_value 'bezeichnung' => described_class.retrieve(:title) } - end - end - - describe Exchange.new(:yaml_eg, data_for(:small_id)) do - it_behaves_like 'success scenario' - end - - # Retry for success more for web services that intermittently fail - describe Exchange.new(:short_hand_xpath).retry_for_success do - # Be careful. If you call a method that does not use namespaces, calling one that does may not find the element - its(['ns1:bezeichnung']) { is_expected.to eq 'Deutsche Bank' } # '//' is not required at the beginning - end - describe Exchange.new('Check existence of elements') do - it { is_expected.to have_element_at_xpath '//ns1:bezeichnung' } - it { is_expected.not_to have_element_at_xpath '//ns1:bezeichnung_pretend' } - end - - end - end - - error_example = BLZService.new('Error example') - error_example.operation = :get_bank - error_example.default_hash = {} - - context 'Error Examples' do - context error_example do - describe Exchange.new(:no_blz_error) do - it_behaves_like 'error scenario' - end - end - end - - - SOAP_SPEC - end - - def shared_examples_content - <<-SHARE_EG - - require 'rspec' - - shared_examples_for 'error scenario' do - it 'does not have status code of 200' do - expect(described_class.status_code).not_to eq 200 - end - end - - SHARE_EG - end - - def soap_template_content - <<-SOAP_TEMP - <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"> - <env:Body> - <tns:getBank> - <tns:blz><%= test_values[:blz] || '70070010' %></tns:blz> - </tns:getBank> - </env:Body> - </env:Envelope> - SOAP_TEMP - end - - def default_yaml_content - <<-DEF_YAML - small_id: - blz: 100 - - DEF_YAML - end - - def test_wsdl_content - <<TEST_WSDL - <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/"> - <wsdl:documentation>BLZService</wsdl:documentation> - <wsdl:types> - <xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://thomas-bayer.com/blz/"> - <xsd:element name="getBank" type="tns:getBankType"/> - <xsd:element name="getBankResponse" type="tns:getBankResponseType"/> - <xsd:complexType name="getBankType"> - <xsd:sequence> - <xsd:element name="blz" type="xsd:string"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="getBankResponseType"> - <xsd:sequence> - <xsd:element name="details" type="tns:detailsType"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="detailsType"> - <xsd:sequence> - <xsd:element minOccurs="0" name="bezeichnung" type="xsd:string"/> - <xsd:element minOccurs="0" name="bic" type="xsd:string"/> - <xsd:element minOccurs="0" name="ort" type="xsd:string"/> - <xsd:element minOccurs="0" name="plz" type="xsd:string"/> - </xsd:sequence> - </xsd:complexType> - </xsd:schema> - </wsdl:types> - <wsdl:message name="getBank"> - <wsdl:part name="parameters" element="tns:getBank"/> - </wsdl:message> - <wsdl:message name="getBankResponse"> - <wsdl:part name="parameters" element="tns:getBankResponse"/> - </wsdl:message> - <wsdl:portType name="BLZServicePortType"> - <wsdl:operation name="getBank"> - <wsdl:input message="tns:getBank"/> - <!--<wsdl:output message="tns:getBankResponse" wsaw:Action="http://thomas-bayer.com/blz/BLZService/getBankResponse"/>--> - <wsdl:output message="tns:getBankResponse" wsaw:Action="http://localhost:4567/BLZService/getBankResponse"/> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="BLZServiceSOAP11Binding" type="tns:BLZServicePortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> - <wsdl:operation name="getBank"> - <soap:operation style="document" soapAction=""/> - <wsdl:input> - <soap:body use="literal"/> - </wsdl:input> - <wsdl:output> - <soap:body use="literal"/> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:binding name="BLZServiceSOAP12Binding" type="tns:BLZServicePortType"> - <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> - <wsdl:operation name="getBank"> - <soap12:operation style="document" soapAction=""/> - <wsdl:input> - <soap12:body use="literal"/> - </wsdl:input> - <wsdl:output> - <soap12:body use="literal"/> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:binding name="BLZServiceHttpBinding" type="tns:BLZServicePortType"> - <http:binding verb="POST"/> - <wsdl:operation name="getBank"> - <http:operation location="BLZService/getBank"/> - <wsdl:input> - <mime:content part="getBank" type="text/xml"/> - </wsdl:input> - <wsdl:output> - <mime:content part="getBank" type="text/xml"/> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:service name="BLZService"> - <wsdl:port name="BLZServiceSOAP11port_http" binding="tns:BLZServiceSOAP11Binding"> - <!-- <soap:address location="http://www.thomas-bayer.com/axis2/services/BLZService"/> --> - <soap:address location="http://localhost:4567/BLZService"/> - </wsdl:port> - <wsdl:port name="BLZServiceSOAP12port_http" binding="tns:BLZServiceSOAP12Binding"> - <!--<soap12:address location="http://www.thomas-bayer.com/axis2/services/BLZService"/>--> - <soap12:address location="http://localhost:4567/BLZService"/> - </wsdl:port> - <wsdl:port name="BLZServiceHttpport" binding="tns:BLZServiceHttpBinding"> - <!--<http:address location="http://www.thomas-bayer.com/axis2/services/BLZService"/>--> - <soap:address location="http://localhost:4567/BLZService"/> - </wsdl:port> - </wsdl:service> - </wsdl:definitions> - -TEST_WSDL + # Create a spec for an WSDL operation + # @param [String] operation Used in ERB to create a test for a WSDL operation + def generated_soap_spec_for(operation) + ERB.new(File.read(File.join(File.dirname(__FILE__), 'generator', 'spec/dynamic_soap_spec.rb.erb'))).result(binding) end end end \ No newline at end of file