Class: Exchange

Inherits:
Object
  • Object
show all
Extended by:
ExchangeProperties
Defined in:
lib/soaspec/exchange.rb

Overview

This represents a request / response pair Essentially, params in the exchange that are set are related to the request What is returned is related to the response

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ExchangeProperties

default_handler, expect_positive_status

Constructor Details

#initialize(name = self.class.to_s, override_parameters = {}) ⇒ Exchange

Returns a new instance of Exchange.

Parameters:

  • name (Symbol, String) (defaults to: self.class.to_s)

    Name shown in RSpec run

  • override_parameters (Hash) (defaults to: {})

    Parameters to override for default params



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/soaspec/exchange.rb', line 60

def initialize(name = self.class.to_s, override_parameters = {})
  self.test_name ||= name.to_s
  # As a last resort this uses the global parameter. The handler should be set straight before an exchange is made to use this
  @exchange_handler ||= default_handler_used || Soaspec.api_handler
  raise '@exchange_handler not set. Set either with `Soaspec.api_handler = Handler.new` or within the exchange' unless @exchange_handler
  @fail_factory = nil
  @override_parameters = override_parameters
  @retry_for_success = false
  self.retry_count = 3
  @exchange_handler.elements.each { |element| methods_for_element(element) }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object

Implement undefined setter with []= for FactoryBot to use without needing to define params to set

Parameters:

  • method_name (Object)

    Name of method not defined

  • args (Object)

    Arguments passed to method

  • block (Object)


185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/soaspec/exchange.rb', line 185

def method_missing(method_name, *args, &block)
  set_value = args.first
  if method_name[-1] == '=' # A setter method
    getter_name = method_name[0..-2]
    if set_value.class < Exchange # This would be prerequisite exchange
      define_singleton_method(getter_name) { set_value }
      self[getter_name] = set_value.id if set_value.respond_to?(:id)
    else
      self[getter_name] = set_value
    end
  else
    super
  end
end

Instance Attribute Details

#exchange_handlerObject

Instance of ExchangeHandler for which this exchange is made



11
12
13
# File 'lib/soaspec/exchange.rb', line 11

def exchange_handler
  @exchange_handler
end

#fail_factory=(value) ⇒ Object (writeonly)

Expect Factory to fail upon trying to create



17
18
19
# File 'lib/soaspec/exchange.rb', line 17

def fail_factory=(value)
  @fail_factory = value
end

#override_parametersObject

Parameters to override for default params



19
20
21
# File 'lib/soaspec/exchange.rb', line 19

def override_parameters
  @override_parameters
end

#retry_countObject

How many times to retry for a success



13
14
15
# File 'lib/soaspec/exchange.rb', line 13

def retry_count
  @retry_count
end

#test_nameObject

Name used for displaying class



15
16
17
# File 'lib/soaspec/exchange.rb', line 15

def test_name
  @test_name
end

Instance Method Details

#[](path) ⇒ String

Extract value from path api class

Parameters:

  • path (Object)

    Path to return element for api class E.g - for SOAP this is XPath string. For JSON, this is Hash dig Array

Returns:

  • (String)

    Value at path



169
170
171
# File 'lib/soaspec/exchange.rb', line 169

def [](path)
  exchange_handler.value_from_path(response, path.to_s)
end

#[]=(key, value) ⇒ Object

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



176
177
178
179
# File 'lib/soaspec/exchange.rb', line 176

def []=(key, value)
  @override_parameters[:body] ||= {}
  @override_parameters[:body][key] = value
end

#default_handler_usedBoolean

Returns Soaspec::ExchangeHandler used by this exchange.

Returns:

  • (Boolean)

    Soaspec::ExchangeHandler used by this exchange



38
39
40
# File 'lib/soaspec/exchange.rb', line 38

def default_handler_used
  nil
end

#dummy_requestBoolean

Dummy request used to make a request without verifying it and ignoring WSDL errors

Returns:

  • (Boolean)

    Always returns true. Unless of course an unexpected exception occurs



149
150
151
152
153
154
155
156
# File 'lib/soaspec/exchange.rb', line 149

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

#element?(path) ⇒ Boolean

Returns Whether an element exists at the path.

Returns:

  • (Boolean)

    Whether an element exists at the path



159
160
161
162
163
164
# File 'lib/soaspec/exchange.rb', line 159

def element?(path)
  [path]
  true
rescue NoElementAtPath
  false
end

#make_requestResponse

Make request to handler with parameters defined Will retry until success code reached if retry_for_success? is set

Returns:

  • (Response)

    Response from Api handler



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/soaspec/exchange.rb', line 87

def make_request
  Soaspec::SpecLogger.info 'Example ' + test_name
  request_params = @override_parameters
  (1..retry_count).each do |count|
    response = exchange_handler.make_request(request_params)
    return response unless retry_for_success?
    return response if (200..299).cover? @exchange_handler.status_code_for(response)
    sleep 0.5
    break response if count == retry_count
  end
end

#method=(method) ⇒ Object

Specify HTTP method to use. Default is :post

Parameters:

  • method (Symbol)

    HTTP method. E.g, :get, :patch



80
81
82
# File 'lib/soaspec/exchange.rb', line 80

def method=(method)
  @override_parameters[:method] = method
end

#methods_for_element(element) ⇒ Object

Parameters:

  • element (String)

    Element to define methods for



43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/soaspec/exchange.rb', line 43

def methods_for_element(element)
  element_name = element.to_s.split('__custom_path_').last
  define_singleton_method(element_name) do
    exchange_handler.__send__(element, response) # Forward the call onto handler to retrieve the element for the response
  end
  define_singleton_method("#{element_name}?") do
    begin
      __send__ element_name
      true
    rescue NoElementAtPath
      false
    end
  end
end

#requestObject

Request of API call. Either intended request or actual request



137
138
139
# File 'lib/soaspec/exchange.rb', line 137

def request
  exchange_handler.request(@response)
end

#respond_to_missing?(method_name, *args) ⇒ Boolean

Used for setters that are not defined

Returns:

  • (Boolean)


201
202
203
# File 'lib/soaspec/exchange.rb', line 201

def respond_to_missing?(method_name, *args)
  method_name[-1] == '=' || super
end

#responseObject Also known as: call

Returns response object from Api. Will make the request if not made and then cache it for later on

Examples:

For SOAP it will be a Savon response

response.body (body of response as Hash)
response.header (head of response as Hash)

For REST it will be a RestClient::Response



127
128
129
130
131
132
# File 'lib/soaspec/exchange.rb', line 127

def response
  Soaspec.last_exchange = self
  @response ||= make_request
  @response.define_singleton_method(:exchange) { Soaspec.last_exchange } unless @response.respond_to?(:exchange)
  @response
end

#retrieve(name) ⇒ Object

Retrieve the stored value from the Api Handler

Parameters:

  • name (String, Symbol)

    Name of value to retrieve

Returns:

  • (Object)

    value from the Api Handler stored previously



109
110
111
112
113
# File 'lib/soaspec/exchange.rb', line 109

def retrieve(name)
  method = '__stored_val__' + name.to_s
  raise ArgumentError('Value not stored at ') unless exchange_handler.respond_to? method
  exchange_handler.send(method)
end

#retry_for_successObject

Set retry for success variable to true so that request will be retried for retry_count until it’s true



27
28
29
30
# File 'lib/soaspec/exchange.rb', line 27

def retry_for_success
  @retry_for_success = true
  self
end

#retry_for_success?Bool

Returns Whether to keep making request until success code reached.

Returns:

  • (Bool)

    Whether to keep making request until success code reached



33
34
35
# File 'lib/soaspec/exchange.rb', line 33

def retry_for_success?
  @retry_for_success
end

#save!Self

Makes request, caching the response and returning self Used by FactoryBot

Returns:

  • (Self)


208
209
210
211
212
# File 'lib/soaspec/exchange.rb', line 208

def save!
  @retry_for_success = @fail_factory ? false : true
  call
  self
end

#status_codeInteger

Get status code from api class. This is http response for Web Api

Returns:

  • (Integer)

    Status code from api class



143
144
145
# File 'lib/soaspec/exchange.rb', line 143

def status_code
  exchange_handler.status_code_for(response)
end

#store(name, value) ⇒ Object

Stores a value in the api handler that can be accessed by the provided name

Parameters:

  • name (Symbol)

    Name of method to use to access this value within handler

  • value (String)

    Path to value to store



102
103
104
# File 'lib/soaspec/exchange.rb', line 102

def store(name, value)
  exchange_handler.store(name, self[value])
end

#suburl=(url) ⇒ Object

Specify a url to add onto the base_url of the ExchangeHandler used

Parameters:

  • url (String)

    Url to add onto the base_url of the ExchangeHandler used



74
75
76
# File 'lib/soaspec/exchange.rb', line 74

def suburl=(url)
  @override_parameters[:suburl] = url
end

#to_hashHash

Returns Hash representing the response of the API.

Returns:

  • (Hash)

    Hash representing the response of the API



215
216
217
# File 'lib/soaspec/exchange.rb', line 215

def to_hash
  exchange_handler.to_hash(response)
end

#to_sString

Name describing this class when used with ‘RSpec.describe` This will make the request and store the response

Returns:

  • (String)

    Name given when initializing



118
119
120
# File 'lib/soaspec/exchange.rb', line 118

def to_s
  test_name
end

#until(opts = {}, &script) ⇒ Self

Wait until the passed block returns true

Parameters:

  • opts (Hash) (defaults to: {})

    Options for this instance

Options Hash (opts):

  • :timeout (Numeric) — default: 5

    Seconds to wait before timing out.

  • :interval (Numeric) — default: 0.2

    Seconds to sleep between polls.

  • :message (String)

    Exception mesage if timed out.

  • :ignore (Array, Exception)

    Exceptions to ignore while polling (default: Error::NoSuchElementError)

Returns:

  • (Self)

    Returns itself so operations can be done on the exchange after it’s done waiting



226
227
228
229
230
231
232
# File 'lib/soaspec/exchange.rb', line 226

def until(opts = {}, &script)
  Soaspec::Wait.until(opts) do
    @response = nil # Reset response so it can be made repeatedly
    instance_eval(&script)
  end
  self
end

#values_from_path(path, attribute: nil) ⇒ Object



21
22
23
# File 'lib/soaspec/exchange.rb', line 21

def values_from_path(path, attribute: nil)
  exchange_handler.values_from_path(response, path, attribute: attribute)
end