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
71
# 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)


188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/soaspec/exchange.rb', line 188

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



172
173
174
# File 'lib/soaspec/exchange.rb', line 172

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



179
180
181
182
# File 'lib/soaspec/exchange.rb', line 179

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



152
153
154
155
156
157
158
159
# File 'lib/soaspec/exchange.rb', line 152

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



162
163
164
165
166
167
# File 'lib/soaspec/exchange.rb', line 162

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



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

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



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

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



140
141
142
# File 'lib/soaspec/exchange.rb', line 140

def request
  exchange_handler.request(@response)
end

#respond_to_missing?(method_name, *args) ⇒ Boolean

Used for setters that are not defined

Returns:

  • (Boolean)


204
205
206
# File 'lib/soaspec/exchange.rb', line 204

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



130
131
132
133
134
135
# File 'lib/soaspec/exchange.rb', line 130

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



111
112
113
114
115
116
# File 'lib/soaspec/exchange.rb', line 111

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)


211
212
213
214
215
# File 'lib/soaspec/exchange.rb', line 211

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



146
147
148
# File 'lib/soaspec/exchange.rb', line 146

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



104
105
106
# File 'lib/soaspec/exchange.rb', line 104

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



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

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



218
219
220
# File 'lib/soaspec/exchange.rb', line 218

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



121
122
123
# File 'lib/soaspec/exchange.rb', line 121

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



229
230
231
232
233
234
235
# File 'lib/soaspec/exchange.rb', line 229

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