Class: Exchange

Inherits:
Object
  • Object
show all
Extended by:
ExchangeAccessors
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 ExchangeAccessors

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



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/soaspec/exchange.rb', line 84

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)


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/soaspec/exchange.rb', line 206

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) do
        set_value
      end
      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



36
37
38
# File 'lib/soaspec/exchange.rb', line 36

def exchange_handler
  @exchange_handler
end

#fail_factory=(value) ⇒ Object (writeonly)

Expect Factory to fail upon trying to create



42
43
44
# File 'lib/soaspec/exchange.rb', line 42

def fail_factory=(value)
  @fail_factory = value
end

#retry_countObject

How many times to retry for a success



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

def retry_count
  @retry_count
end

#test_nameObject

Name used for displaying class



40
41
42
# File 'lib/soaspec/exchange.rb', line 40

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



190
191
192
# File 'lib/soaspec/exchange.rb', line 190

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



197
198
199
200
# File 'lib/soaspec/exchange.rb', line 197

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



62
63
64
# File 'lib/soaspec/exchange.rb', line 62

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



170
171
172
173
174
175
176
177
# File 'lib/soaspec/exchange.rb', line 170

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



180
181
182
183
184
185
# File 'lib/soaspec/exchange.rb', line 180

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



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/soaspec/exchange.rb', line 111

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



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

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

#methods_for_element(element) ⇒ Object

Parameters:

  • element (String)

    Element to define methods for



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/soaspec/exchange.rb', line 67

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



158
159
160
# File 'lib/soaspec/exchange.rb', line 158

def request
  exchange_handler.request(@response)
end

#respond_to_missing?(method_name, *args) ⇒ Boolean

Used for setters that are not defined

Returns:

  • (Boolean)


224
225
226
# File 'lib/soaspec/exchange.rb', line 224

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)


150
151
152
153
# File 'lib/soaspec/exchange.rb', line 150

def response
  Soaspec.last_exchange = self
  @response ||= make_request
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



133
134
135
136
137
# File 'lib/soaspec/exchange.rb', line 133

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



51
52
53
54
# File 'lib/soaspec/exchange.rb', line 51

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



57
58
59
# File 'lib/soaspec/exchange.rb', line 57

def retry_for_success?
  @retry_for_success
end

#save!Self

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

Returns:

  • (Self)


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

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



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

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



126
127
128
# File 'lib/soaspec/exchange.rb', line 126

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



98
99
100
# File 'lib/soaspec/exchange.rb', line 98

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

#to_hashObject



237
238
239
# File 'lib/soaspec/exchange.rb', line 237

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



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

def to_s
  test_name
end

#values_from_path(path, attribute: nil) ⇒ Object



45
46
47
# File 'lib/soaspec/exchange.rb', line 45

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