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



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

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)


210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/soaspec/exchange.rb', line 210

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

#override_parametersObject

Parameters to override for default params



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

def override_parameters
  @override_parameters
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



194
195
196
# File 'lib/soaspec/exchange.rb', line 194

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



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

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



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

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



174
175
176
177
178
179
180
181
# File 'lib/soaspec/exchange.rb', line 174

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



184
185
186
187
188
189
# File 'lib/soaspec/exchange.rb', line 184

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



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

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



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

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

#methods_for_element(element) ⇒ Object

Parameters:

  • element (String)

    Element to define methods for



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

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



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

def request
  exchange_handler.request(@response)
end

#respond_to_missing?(method_name, *args) ⇒ Boolean

Used for setters that are not defined

Returns:

  • (Boolean)


228
229
230
# File 'lib/soaspec/exchange.rb', line 228

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



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

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



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

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



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

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



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

def retry_for_success?
  @retry_for_success
end

#save!Self

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

Returns:

  • (Self)


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

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



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

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



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

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



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

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



242
243
244
# File 'lib/soaspec/exchange.rb', line 242

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



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

def to_s
  test_name
end

#until(&script) ⇒ Object

Wait until the passed block returns true



247
248
249
250
251
252
# File 'lib/soaspec/exchange.rb', line 247

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

#values_from_path(path, attribute: nil) ⇒ Object



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

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