soaspec 0.2.23 → 0.2.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +15 -15
- data/.gitlab-ci.yml +33 -33
- data/.rspec +3 -3
- data/.rubocop.yml +2 -2
- data/CODE_OF_CONDUCT.md +74 -74
- data/ChangeLog +577 -573
- data/Gemfile +6 -6
- data/LICENSE.txt +21 -21
- data/README.md +230 -230
- data/Rakefile +42 -42
- data/Todo.md +15 -15
- data/exe/soaspec +123 -123
- data/exe/xml_to_yaml_file +42 -42
- data/lib/soaspec.rb +101 -101
- data/lib/soaspec/core_ext/hash.rb +35 -35
- data/lib/soaspec/cucumber/generic_steps.rb +85 -85
- data/lib/soaspec/demo.rb +4 -4
- data/lib/soaspec/exchange/exchange.rb +111 -111
- data/lib/soaspec/exchange/exchange_extractor.rb +83 -83
- data/lib/soaspec/exchange/exchange_properties.rb +26 -26
- data/lib/soaspec/exchange/exchange_repeater.rb +19 -19
- data/lib/soaspec/exchange/request_builder.rb +68 -68
- data/lib/soaspec/exchange/variable_storer.rb +22 -22
- data/lib/soaspec/exchange_handlers/exchange_handler.rb +126 -126
- data/lib/soaspec/exchange_handlers/handler_accessors.rb +130 -130
- data/lib/soaspec/exchange_handlers/response_extractor.rb +82 -82
- data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +109 -109
- data/lib/soaspec/exchange_handlers/rest_handler.rb +259 -259
- data/lib/soaspec/exchange_handlers/rest_methods.rb +44 -44
- data/lib/soaspec/exchange_handlers/rest_parameters.rb +86 -86
- data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +21 -21
- data/lib/soaspec/exchange_handlers/soap_handler.rb +235 -235
- data/lib/soaspec/exe_helpers.rb +92 -92
- data/lib/soaspec/generate_server.rb +37 -37
- data/lib/soaspec/generator/.rspec.erb +5 -5
- data/lib/soaspec/generator/.travis.yml.erb +5 -5
- data/lib/soaspec/generator/Gemfile.erb +8 -8
- data/lib/soaspec/generator/README.md.erb +29 -29
- data/lib/soaspec/generator/Rakefile.erb +19 -19
- data/lib/soaspec/generator/config/data/default.yml.erb +2 -2
- data/lib/soaspec/generator/css/bootstrap.css +6833 -6833
- data/lib/soaspec/generator/generate_exchange.html.erb +35 -35
- data/lib/soaspec/generator/lib/blz_service.rb.erb +26 -26
- data/lib/soaspec/generator/lib/dynamic_class_content.rb.erb +12 -12
- data/lib/soaspec/generator/lib/new_rest_service.rb.erb +51 -51
- data/lib/soaspec/generator/lib/new_soap_service.rb.erb +29 -29
- data/lib/soaspec/generator/lib/package_service.rb.erb +2 -2
- data/lib/soaspec/generator/lib/shared_example.rb.erb +8 -8
- data/lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb +12 -12
- data/lib/soaspec/generator/spec/rest_spec.rb.erb +9 -9
- data/lib/soaspec/generator/spec/soap_spec.rb.erb +51 -51
- data/lib/soaspec/generator/spec/spec_helper.rb.erb +23 -23
- data/lib/soaspec/generator/template/soap_template.xml +6 -6
- data/lib/soaspec/indifferent_hash.rb +7 -7
- data/lib/soaspec/interpreter.rb +39 -39
- data/lib/soaspec/matchers.rb +114 -114
- data/lib/soaspec/not_found_errors.rb +13 -13
- data/lib/soaspec/o_auth2.rb +128 -128
- data/lib/soaspec/soaspec_shared_examples.rb +24 -24
- data/lib/soaspec/spec_logger.rb +121 -121
- data/lib/soaspec/template_reader.rb +28 -28
- data/lib/soaspec/test_server/bank.wsdl +90 -90
- data/lib/soaspec/test_server/get_bank.rb +164 -164
- data/lib/soaspec/test_server/id_manager.rb +39 -39
- data/lib/soaspec/test_server/invoices.rb +27 -27
- data/lib/soaspec/test_server/namespace.xml +14 -14
- data/lib/soaspec/test_server/note.xml +5 -5
- data/lib/soaspec/test_server/puppy_service.rb +19 -19
- data/lib/soaspec/test_server/test_attribute.rb +12 -12
- data/lib/soaspec/test_server/test_namespace.rb +12 -12
- data/lib/soaspec/version.rb +4 -3
- data/lib/soaspec/virtual_server.rb +174 -174
- data/lib/soaspec/wait.rb +41 -41
- data/lib/soaspec/wsdl_generator.rb +215 -215
- data/soaspec.gemspec +53 -53
- data/test.wsdl +116 -116
- data/test.xml +10 -10
- data/test_wsdl.rb +41 -41
- metadata +3 -4
@@ -1,35 +1,35 @@
|
|
1
|
-
# Override Hash class with convenience methods
|
2
|
-
class Hash
|
3
|
-
# Transform each key in Hash to a symbol. Privately used by non-self method
|
4
|
-
# @param [Object] value Value inside hash to transform keys under
|
5
|
-
def self.transform_keys_to_symbols(value)
|
6
|
-
return value unless value.is_a?(Hash)
|
7
|
-
|
8
|
-
hash = value.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); }
|
9
|
-
hash
|
10
|
-
end
|
11
|
-
|
12
|
-
# Take keys of hash and transform those to a symbols
|
13
|
-
def transform_keys_to_symbols
|
14
|
-
each_with_object({}) { |(k, v), memo| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); }
|
15
|
-
end
|
16
|
-
|
17
|
-
# Value present in nested Hash.
|
18
|
-
# @return [Boolean] Whether value is included in nested Hash
|
19
|
-
def include_value?(value)
|
20
|
-
each_value do |v|
|
21
|
-
return true if v == value
|
22
|
-
next unless v.is_a? Hash
|
23
|
-
|
24
|
-
v.each_value do |v|
|
25
|
-
return true if v == value
|
26
|
-
next unless v.is_a? Hash
|
27
|
-
|
28
|
-
v.each_value do |v|
|
29
|
-
return true if v == value
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
false
|
34
|
-
end
|
35
|
-
end
|
1
|
+
# Override Hash class with convenience methods
|
2
|
+
class Hash
|
3
|
+
# Transform each key in Hash to a symbol. Privately used by non-self method
|
4
|
+
# @param [Object] value Value inside hash to transform keys under
|
5
|
+
def self.transform_keys_to_symbols(value)
|
6
|
+
return value unless value.is_a?(Hash)
|
7
|
+
|
8
|
+
hash = value.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); }
|
9
|
+
hash
|
10
|
+
end
|
11
|
+
|
12
|
+
# Take keys of hash and transform those to a symbols
|
13
|
+
def transform_keys_to_symbols
|
14
|
+
each_with_object({}) { |(k, v), memo| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Value present in nested Hash.
|
18
|
+
# @return [Boolean] Whether value is included in nested Hash
|
19
|
+
def include_value?(value)
|
20
|
+
each_value do |v|
|
21
|
+
return true if v == value
|
22
|
+
next unless v.is_a? Hash
|
23
|
+
|
24
|
+
v.each_value do |v|
|
25
|
+
return true if v == value
|
26
|
+
next unless v.is_a? Hash
|
27
|
+
|
28
|
+
v.each_value do |v|
|
29
|
+
return true if v == value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
@@ -1,85 +1,85 @@
|
|
1
|
-
require 'active_support/core_ext/string/inflections'
|
2
|
-
|
3
|
-
# @return [Exchange] Return current or last exchange used in Cucumber
|
4
|
-
def current_exchange
|
5
|
-
@current_exchange ||= Soaspec.last_exchange
|
6
|
-
end
|
7
|
-
|
8
|
-
# Pass in the operation (HTTP method or SOAP operation) in first parameter and api name as second.
|
9
|
-
# API name can be mulitple words and it will be converted to camel case to find the ExchangeHandler class
|
10
|
-
# @example Create an Exchange representing an HTTP 'post' based on the 'Puppy' RestHandler class
|
11
|
-
# I am performing a post on the Puppy API
|
12
|
-
# @example Create an Exchange for a 'get_bank' operation on for a 'Banking' SoapHandler class
|
13
|
-
# I am performing a get_bank on the Banking API
|
14
|
-
Given 'I am performing a {word} on the {string} API' do |operation, api_name|
|
15
|
-
@current_exchange = api_name.tr(' ', '_').camelize.constantize.send operation
|
16
|
-
end
|
17
|
-
|
18
|
-
# Set a parameter in the request body
|
19
|
-
# @example Set the name element in the request body to Charlie
|
20
|
-
# And I set the name to 'Charlie'
|
21
|
-
# @param [String] Element in request body to set
|
22
|
-
# @param [String] Value to set it to
|
23
|
-
Given 'I set the {word} to {string}' do |key, value|
|
24
|
-
current_exchange[key] = value
|
25
|
-
end
|
26
|
-
|
27
|
-
# Add onto the base_url to make a complete url for the test
|
28
|
-
# @example base_url is 'http://petstore.swagger.io/v2' and I want a post to 'http://petstore.swagger.io/v2/pet'
|
29
|
-
# I use the path pet
|
30
|
-
Given 'I use the path {word}' do |suburl|
|
31
|
-
current_exchange.suburl = suburl
|
32
|
-
end
|
33
|
-
|
34
|
-
# Add a query parameter for http 'get' requests. e.g. will add '?filter_key=filter_value' onto URL
|
35
|
-
# @example To create a query for '?status=sold'
|
36
|
-
# And I filter 'status' by 'sold'
|
37
|
-
# @example To add a query for 'area' being 'australia' to make a total of '?status=sold&area=austrialia'
|
38
|
-
# And I filter 'area' by 'australia'
|
39
|
-
Given 'I filter {string} by {string}' do |filter_key, filter_value|
|
40
|
-
transformed_key = filter_key.to_sym
|
41
|
-
if current_exchange.override_parameters[:q]
|
42
|
-
current_exchange.override_parameters[:q][transformed_key] = filter_value
|
43
|
-
else
|
44
|
-
current_exchange.override_parameters[:q] = { transformed_key => filter_value }
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Add HTTP header 'header_name' as 'header_value'
|
49
|
-
# @example
|
50
|
-
# And I set header 'accept' to 'application/xml'
|
51
|
-
Given 'I set header {string} to {string}' do |header_name, header_value|
|
52
|
-
if current_exchange.override_parameters[:params]
|
53
|
-
current_exchange.override_parameters[:params][header_name] = header_value
|
54
|
-
else
|
55
|
-
current_exchange.override_parameters[:params] = { header_name => header_value }
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Make the API call. This is automatically done when any method extracting a response is made. It can be done
|
60
|
-
# explicitly here as it is a meaningful step
|
61
|
-
When 'I make the request' do
|
62
|
-
current_exchange.call
|
63
|
-
end
|
64
|
-
|
65
|
-
# Extract the value from the response that is at the path 'key' and verify it is eq to expected_value
|
66
|
-
# @example Assert response body has at the path 'name', the value 'Charlie'
|
67
|
-
# Then it should have the name 'Charlie'
|
68
|
-
Then 'it should have the {word} {string}' do |key, expected_value|
|
69
|
-
expect(current_exchange[key]).to eq expected_value
|
70
|
-
end
|
71
|
-
|
72
|
-
# Extract the value from the response that is at the path 'key_string' and verify it is eq to expected_value
|
73
|
-
# Conversion is made on key_string to make it one snake case word
|
74
|
-
# @example Assert response body has at the path 'customer_name', the value 'Charlie'
|
75
|
-
# Then it should have the 'customer name' 'Charlie'
|
76
|
-
Then 'it should have the {string} {string}' do |key_string, expected_value|
|
77
|
-
key = key_string.tr(' ', '_')
|
78
|
-
actual_value = current_exchange.respond_to?(key) ? current_exchange.send(key) : current_exchange[key]
|
79
|
-
expect(actual_value.to_s).to eq expected_value
|
80
|
-
end
|
81
|
-
|
82
|
-
# Verify that the HTTP status code is 200..299 and that any defined mandatory elements / mandatory values are as expected
|
83
|
-
Then 'it should be successful' do
|
84
|
-
expect(current_exchange).to be_successful
|
85
|
-
end
|
1
|
+
require 'active_support/core_ext/string/inflections'
|
2
|
+
|
3
|
+
# @return [Exchange] Return current or last exchange used in Cucumber
|
4
|
+
def current_exchange
|
5
|
+
@current_exchange ||= Soaspec.last_exchange
|
6
|
+
end
|
7
|
+
|
8
|
+
# Pass in the operation (HTTP method or SOAP operation) in first parameter and api name as second.
|
9
|
+
# API name can be mulitple words and it will be converted to camel case to find the ExchangeHandler class
|
10
|
+
# @example Create an Exchange representing an HTTP 'post' based on the 'Puppy' RestHandler class
|
11
|
+
# I am performing a post on the Puppy API
|
12
|
+
# @example Create an Exchange for a 'get_bank' operation on for a 'Banking' SoapHandler class
|
13
|
+
# I am performing a get_bank on the Banking API
|
14
|
+
Given 'I am performing a {word} on the {string} API' do |operation, api_name|
|
15
|
+
@current_exchange = api_name.tr(' ', '_').camelize.constantize.send operation
|
16
|
+
end
|
17
|
+
|
18
|
+
# Set a parameter in the request body
|
19
|
+
# @example Set the name element in the request body to Charlie
|
20
|
+
# And I set the name to 'Charlie'
|
21
|
+
# @param [String] Element in request body to set
|
22
|
+
# @param [String] Value to set it to
|
23
|
+
Given 'I set the {word} to {string}' do |key, value|
|
24
|
+
current_exchange[key] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
# Add onto the base_url to make a complete url for the test
|
28
|
+
# @example base_url is 'http://petstore.swagger.io/v2' and I want a post to 'http://petstore.swagger.io/v2/pet'
|
29
|
+
# I use the path pet
|
30
|
+
Given 'I use the path {word}' do |suburl|
|
31
|
+
current_exchange.suburl = suburl
|
32
|
+
end
|
33
|
+
|
34
|
+
# Add a query parameter for http 'get' requests. e.g. will add '?filter_key=filter_value' onto URL
|
35
|
+
# @example To create a query for '?status=sold'
|
36
|
+
# And I filter 'status' by 'sold'
|
37
|
+
# @example To add a query for 'area' being 'australia' to make a total of '?status=sold&area=austrialia'
|
38
|
+
# And I filter 'area' by 'australia'
|
39
|
+
Given 'I filter {string} by {string}' do |filter_key, filter_value|
|
40
|
+
transformed_key = filter_key.to_sym
|
41
|
+
if current_exchange.override_parameters[:q]
|
42
|
+
current_exchange.override_parameters[:q][transformed_key] = filter_value
|
43
|
+
else
|
44
|
+
current_exchange.override_parameters[:q] = { transformed_key => filter_value }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Add HTTP header 'header_name' as 'header_value'
|
49
|
+
# @example
|
50
|
+
# And I set header 'accept' to 'application/xml'
|
51
|
+
Given 'I set header {string} to {string}' do |header_name, header_value|
|
52
|
+
if current_exchange.override_parameters[:params]
|
53
|
+
current_exchange.override_parameters[:params][header_name] = header_value
|
54
|
+
else
|
55
|
+
current_exchange.override_parameters[:params] = { header_name => header_value }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Make the API call. This is automatically done when any method extracting a response is made. It can be done
|
60
|
+
# explicitly here as it is a meaningful step
|
61
|
+
When 'I make the request' do
|
62
|
+
current_exchange.call
|
63
|
+
end
|
64
|
+
|
65
|
+
# Extract the value from the response that is at the path 'key' and verify it is eq to expected_value
|
66
|
+
# @example Assert response body has at the path 'name', the value 'Charlie'
|
67
|
+
# Then it should have the name 'Charlie'
|
68
|
+
Then 'it should have the {word} {string}' do |key, expected_value|
|
69
|
+
expect(current_exchange[key]).to eq expected_value
|
70
|
+
end
|
71
|
+
|
72
|
+
# Extract the value from the response that is at the path 'key_string' and verify it is eq to expected_value
|
73
|
+
# Conversion is made on key_string to make it one snake case word
|
74
|
+
# @example Assert response body has at the path 'customer_name', the value 'Charlie'
|
75
|
+
# Then it should have the 'customer name' 'Charlie'
|
76
|
+
Then 'it should have the {string} {string}' do |key_string, expected_value|
|
77
|
+
key = key_string.tr(' ', '_')
|
78
|
+
actual_value = current_exchange.respond_to?(key) ? current_exchange.send(key) : current_exchange[key]
|
79
|
+
expect(actual_value.to_s).to eq expected_value
|
80
|
+
end
|
81
|
+
|
82
|
+
# Verify that the HTTP status code is 200..299 and that any defined mandatory elements / mandatory values are as expected
|
83
|
+
Then 'it should be successful' do
|
84
|
+
expect(current_exchange).to be_successful
|
85
|
+
end
|
data/lib/soaspec/demo.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Load this file for demoing Soaspec (e.g in IRB). Has common settings applicable for demoing
|
2
|
-
|
3
|
-
require_relative '../soaspec'
|
4
|
-
Soaspec::SpecLogger.output_to_terminal = true
|
1
|
+
# Load this file for demoing Soaspec (e.g in IRB). Has common settings applicable for demoing
|
2
|
+
|
3
|
+
require_relative '../soaspec'
|
4
|
+
Soaspec::SpecLogger.output_to_terminal = true
|
@@ -1,111 +1,111 @@
|
|
1
|
-
require_relative '../../soaspec'
|
2
|
-
require_relative 'exchange_properties'
|
3
|
-
require_relative 'exchange_extractor'
|
4
|
-
require_relative 'request_builder'
|
5
|
-
require_relative 'exchange_repeater'
|
6
|
-
require_relative 'variable_storer'
|
7
|
-
|
8
|
-
# This represents a request / response pair
|
9
|
-
# Essentially, params in the exchange that are set are related to the request
|
10
|
-
# What is returned is related to the response
|
11
|
-
class Exchange
|
12
|
-
extend Soaspec::ExchangeProperties
|
13
|
-
include Soaspec::ExchangeExtractor
|
14
|
-
include Soaspec::RequestBuilder
|
15
|
-
include Soaspec::ExchangeRepeater
|
16
|
-
include Soaspec::VariableStorer
|
17
|
-
|
18
|
-
# Instance of ExchangeHandler for which this exchange is made
|
19
|
-
attr_accessor :exchange_handler
|
20
|
-
# How many times to retry for a success
|
21
|
-
attr_accessor :retry_count
|
22
|
-
# Name used for displaying class
|
23
|
-
attr_accessor :test_name
|
24
|
-
# Expect Factory to fail upon trying to create
|
25
|
-
attr_writer :fail_factory
|
26
|
-
# Parameters to override for default params
|
27
|
-
attr_accessor :override_parameters
|
28
|
-
|
29
|
-
# Set retry for success variable to true so that request will be retried
|
30
|
-
# for retry_count until it's true
|
31
|
-
def retry_for_success
|
32
|
-
@retry_for_success = true
|
33
|
-
self
|
34
|
-
end
|
35
|
-
|
36
|
-
# @return [Bool] Whether to keep making request until success code reached
|
37
|
-
def retry_for_success?
|
38
|
-
@retry_for_success
|
39
|
-
end
|
40
|
-
|
41
|
-
# @return [Boolean] Soaspec::ExchangeHandler used by this exchange
|
42
|
-
def default_handler_used
|
43
|
-
nil
|
44
|
-
end
|
45
|
-
|
46
|
-
# Create new Exchange according to parameters set. A response will be made if called
|
47
|
-
# explicitly with 'response' method or through other methods that use it like 'status_code'
|
48
|
-
# @param [Symbol, String] name Name shown in RSpec run
|
49
|
-
# @param [Hash] override_parameters Parameters to override for default params
|
50
|
-
def initialize(name = self.class.to_s, override_parameters = {})
|
51
|
-
self.test_name ||= name.to_s
|
52
|
-
# As a last resort this uses the global parameter. The handler should be set straight before an exchange is made to use this
|
53
|
-
@exchange_handler ||= default_handler_used || Soaspec.api_handler
|
54
|
-
raise '@exchange_handler not set. Set either with `Soaspec.api_handler = Handler.new` or within the exchange' unless @exchange_handler
|
55
|
-
|
56
|
-
@fail_factory = nil
|
57
|
-
@override_parameters = override_parameters
|
58
|
-
@retry_for_success = false
|
59
|
-
self.retry_count = 3
|
60
|
-
@exchange_handler.elements.each { |element| methods_for_element(element) }
|
61
|
-
end
|
62
|
-
|
63
|
-
# Make request to handler with parameters defined
|
64
|
-
# Will retry until success code reached if retry_for_success? is set
|
65
|
-
# @return [Response] Response from Api handler
|
66
|
-
def make_request
|
67
|
-
Soaspec::SpecLogger.info 'Example ' + test_name
|
68
|
-
request_params = @override_parameters
|
69
|
-
(0..retry_count).each do |count|
|
70
|
-
response = exchange_handler.make_request(request_params)
|
71
|
-
return response unless retry_for_success?
|
72
|
-
return response if (200..299).cover? exchange_handler.status_code_for(response)
|
73
|
-
|
74
|
-
sleep 0.5 # Time before retrying
|
75
|
-
break response if count == retry_count
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# Name describing this class when used with `RSpec.describe`
|
80
|
-
# This will make the request and store the response
|
81
|
-
# @return [String] Name given when initializing
|
82
|
-
def to_s
|
83
|
-
test_name
|
84
|
-
end
|
85
|
-
|
86
|
-
# @return [RestClient::Response,Savon::Response] Returns response object from Api.
|
87
|
-
# Will make the request if not made and then cache it for later on
|
88
|
-
# @example For SOAP it will be a Savon response
|
89
|
-
# response.body (body of response as Hash)
|
90
|
-
# response.header (head of response as Hash)
|
91
|
-
# @example For REST it will be a RestClient::Response
|
92
|
-
def response
|
93
|
-
require 'forwardable'
|
94
|
-
Soaspec.last_exchange = self
|
95
|
-
@response ||= make_request
|
96
|
-
@response.define_singleton_method(:exchange) { Soaspec.last_exchange } unless @response.respond_to?(:exchange)
|
97
|
-
@response.extend Forwardable
|
98
|
-
@response.delegate %i[value_from_path values_from_path] => :exchange
|
99
|
-
@response
|
100
|
-
end
|
101
|
-
|
102
|
-
# @return [ResponseObject] Currently returning response object. This will change (in 0.3) to be itself to
|
103
|
-
# allow easy method chaining
|
104
|
-
def call
|
105
|
-
if Soaspec.log_warnings
|
106
|
-
warn 'This "call" method will be changed to return "Exchange" object in 0.3. ' \
|
107
|
-
'Use "response" method if you want the "response" object'
|
108
|
-
end
|
109
|
-
response
|
110
|
-
end
|
111
|
-
end
|
1
|
+
require_relative '../../soaspec'
|
2
|
+
require_relative 'exchange_properties'
|
3
|
+
require_relative 'exchange_extractor'
|
4
|
+
require_relative 'request_builder'
|
5
|
+
require_relative 'exchange_repeater'
|
6
|
+
require_relative 'variable_storer'
|
7
|
+
|
8
|
+
# This represents a request / response pair
|
9
|
+
# Essentially, params in the exchange that are set are related to the request
|
10
|
+
# What is returned is related to the response
|
11
|
+
class Exchange
|
12
|
+
extend Soaspec::ExchangeProperties
|
13
|
+
include Soaspec::ExchangeExtractor
|
14
|
+
include Soaspec::RequestBuilder
|
15
|
+
include Soaspec::ExchangeRepeater
|
16
|
+
include Soaspec::VariableStorer
|
17
|
+
|
18
|
+
# Instance of ExchangeHandler for which this exchange is made
|
19
|
+
attr_accessor :exchange_handler
|
20
|
+
# How many times to retry for a success
|
21
|
+
attr_accessor :retry_count
|
22
|
+
# Name used for displaying class
|
23
|
+
attr_accessor :test_name
|
24
|
+
# Expect Factory to fail upon trying to create
|
25
|
+
attr_writer :fail_factory
|
26
|
+
# Parameters to override for default params
|
27
|
+
attr_accessor :override_parameters
|
28
|
+
|
29
|
+
# Set retry for success variable to true so that request will be retried
|
30
|
+
# for retry_count until it's true
|
31
|
+
def retry_for_success
|
32
|
+
@retry_for_success = true
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Bool] Whether to keep making request until success code reached
|
37
|
+
def retry_for_success?
|
38
|
+
@retry_for_success
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Boolean] Soaspec::ExchangeHandler used by this exchange
|
42
|
+
def default_handler_used
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# Create new Exchange according to parameters set. A response will be made if called
|
47
|
+
# explicitly with 'response' method or through other methods that use it like 'status_code'
|
48
|
+
# @param [Symbol, String] name Name shown in RSpec run
|
49
|
+
# @param [Hash] override_parameters Parameters to override for default params
|
50
|
+
def initialize(name = self.class.to_s, override_parameters = {})
|
51
|
+
self.test_name ||= name.to_s
|
52
|
+
# As a last resort this uses the global parameter. The handler should be set straight before an exchange is made to use this
|
53
|
+
@exchange_handler ||= default_handler_used || Soaspec.api_handler
|
54
|
+
raise '@exchange_handler not set. Set either with `Soaspec.api_handler = Handler.new` or within the exchange' unless @exchange_handler
|
55
|
+
|
56
|
+
@fail_factory = nil
|
57
|
+
@override_parameters = override_parameters
|
58
|
+
@retry_for_success = false
|
59
|
+
self.retry_count = 3
|
60
|
+
@exchange_handler.elements.each { |element| methods_for_element(element) }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Make request to handler with parameters defined
|
64
|
+
# Will retry until success code reached if retry_for_success? is set
|
65
|
+
# @return [Response] Response from Api handler
|
66
|
+
def make_request
|
67
|
+
Soaspec::SpecLogger.info 'Example ' + test_name
|
68
|
+
request_params = @override_parameters
|
69
|
+
(0..retry_count).each do |count|
|
70
|
+
response = exchange_handler.make_request(request_params)
|
71
|
+
return response unless retry_for_success?
|
72
|
+
return response if (200..299).cover? exchange_handler.status_code_for(response)
|
73
|
+
|
74
|
+
sleep 0.5 # Time before retrying
|
75
|
+
break response if count == retry_count
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Name describing this class when used with `RSpec.describe`
|
80
|
+
# This will make the request and store the response
|
81
|
+
# @return [String] Name given when initializing
|
82
|
+
def to_s
|
83
|
+
test_name
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [RestClient::Response,Savon::Response] Returns response object from Api.
|
87
|
+
# Will make the request if not made and then cache it for later on
|
88
|
+
# @example For SOAP it will be a Savon response
|
89
|
+
# response.body (body of response as Hash)
|
90
|
+
# response.header (head of response as Hash)
|
91
|
+
# @example For REST it will be a RestClient::Response
|
92
|
+
def response
|
93
|
+
require 'forwardable'
|
94
|
+
Soaspec.last_exchange = self
|
95
|
+
@response ||= make_request
|
96
|
+
@response.define_singleton_method(:exchange) { Soaspec.last_exchange } unless @response.respond_to?(:exchange)
|
97
|
+
@response.extend Forwardable
|
98
|
+
@response.delegate %i[value_from_path values_from_path] => :exchange
|
99
|
+
@response
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [ResponseObject] Currently returning response object. This will change (in 0.3) to be itself to
|
103
|
+
# allow easy method chaining
|
104
|
+
def call
|
105
|
+
if Soaspec.log_warnings
|
106
|
+
warn 'This "call" method will be changed to return "Exchange" object in 0.3. ' \
|
107
|
+
'Use "response" method if you want the "response" object'
|
108
|
+
end
|
109
|
+
response
|
110
|
+
end
|
111
|
+
end
|