require_relative '../soaspec' # This represents a request / response pair class Exchange # Class of Api Handler for which this exchange is made attr_reader :api_class # How many times to retry for a success attr_accessor :retry_count # Params used when making a request attr_accessor :default_params # Set retry for success variable to true so that request will be retried # for retry_count until it's true def retry_for_success @retry_for_success = true self end # @return [Bool] Whether to keep making request until success code reached def retry_for_success? @retry_for_success end # @param [Symbol, String] name Name shown in RSpec run # @param [Hash] override_parameters Parameters to override for default params def initialize(name, override_parameters = {}) @test_name = name.to_s @api_class = Soaspec.api_handler # This uses the global parameter. The handler should be set straight before an exchange is made @override_parameters = override_parameters @retry_for_success = false self.retry_count = 3 @api_class.elements.each do |element| define_singleton_method(element.to_s.split('__custom_path_').last) do @api_class.__send__(element, response) # Forward the call onto handler to retrieve the element for the response end end end # Merge exchange initialized request params with ones set later on def merge_request_body if @override_parameters[:body] @override_parameters[:body].merge!(default_params[:body]) @override_parameters else @override_parameters.merge(default_params[:body]) end end # Make request to handler with parameters defined # Will retry until success code reached if retry_for_success? is set # @return [Response] Response from Api handler def make_request Soaspec::SpecLogger.add_to 'Example ' + @test_name request_params = default_params ? merge_request_body : @override_parameters retry_count.times do response = @api_class.make_request(request_params) return response unless retry_for_success? return response if (200..299).cover? @api_class.status_code_for(response) response end end # Stores a value in the api handler that can be accessed by the provided name # @param [Symbol] name Name of method to use to access this value within handler # @param [String] value Path to value to store def store(name, value) @api_class.store(name, self[value]) end # Retrieve the stored value from the Api Handler # @param [String, Symbol] name Name of value to retrieve # @return [Object] value from the Api Handler stored previously def retrieve(name) method = '__stored_val__' + name.to_s raise ArgumentError('Value not stored at ') unless api_class.respond_to? method @api_class.send(method) end # Name describing this class when used with `RSpec.describe` # This will make the request and store the response # @return [String] Name given when initializing def to_s @test_name end # Returns response object from Api. Will make the request if not made and then cache it for later on # For example for SOAP it will be a Savon response # response.body (body of response as Hash) # response.header (head of response as Hash) def response @response ||= make_request end alias call response # Get status code from api class. This is http response for Web Api # @return [Integer] Status code from api class def status_code @api_class.status_code_for(response) end # Dummy request used to make a request without verifying it and ignoring WSDL errors # @return [Boolean] Always returns true. Unless of course an unexpected exception occurs def dummy_request make_request true rescue Savon::HTTPError puts 'Resolver error' # This seems to occur first time IP address asks for WSDL true end # Extract value from path api class # @param [Object] path Path to return element for api class E.g - for SOAP this is XPath string. For JSON, this is Hash dig Array # @return [String] Value at path def [](path) @api_class.value_from_path(response, path.to_s) end # Set a parameter request in the request body. # Can be used to build a request over several steps (e.g Cucumber) # Will be used with FactoryBot def []=(key, value) self.default_params = { body: {} } unless default_params # Initialize as Hash if not set default_params[:body][key] = value end end