soaspec 0.2.32 → 0.2.33
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +15 -15
- data/.gitlab-ci.yml +62 -62
- data/.rspec +3 -3
- data/.rubocop.yml +2 -2
- data/CODE_OF_CONDUCT.md +74 -74
- data/ChangeLog +632 -625
- data/Dockerfile +7 -7
- data/Gemfile +8 -8
- data/LICENSE.txt +21 -21
- data/README.md +231 -231
- data/Rakefile +52 -52
- data/Todo.md +16 -16
- data/exe/soaspec +138 -138
- data/exe/xml_to_yaml_file +43 -43
- data/lib/soaspec.rb +106 -105
- data/lib/soaspec/baseline.rb +23 -0
- data/lib/soaspec/core_ext/hash.rb +44 -44
- data/lib/soaspec/cucumber/generic_steps.rb +94 -94
- data/lib/soaspec/demo.rb +6 -6
- data/lib/soaspec/errors.rb +24 -22
- data/lib/soaspec/exchange/exchange.rb +129 -129
- data/lib/soaspec/exchange/exchange_extractor.rb +90 -90
- data/lib/soaspec/exchange/exchange_properties.rb +28 -28
- data/lib/soaspec/exchange/exchange_repeater.rb +21 -21
- data/lib/soaspec/exchange/request_builder.rb +70 -70
- data/lib/soaspec/exchange/variable_storer.rb +24 -24
- data/lib/soaspec/exchange_handlers/exchange_handler.rb +98 -98
- data/lib/soaspec/exchange_handlers/exchange_handler_defaults.rb +61 -61
- data/lib/soaspec/exchange_handlers/handler_accessors.rb +132 -132
- data/lib/soaspec/exchange_handlers/request/rest_request.rb +59 -51
- data/lib/soaspec/exchange_handlers/request/soap_request.rb +41 -41
- data/lib/soaspec/exchange_handlers/response_extractor.rb +84 -84
- data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +111 -111
- data/lib/soaspec/exchange_handlers/rest_handler.rb +307 -298
- data/lib/soaspec/exchange_handlers/rest_methods.rb +65 -65
- data/lib/soaspec/exchange_handlers/rest_parameters.rb +112 -112
- data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +42 -42
- data/lib/soaspec/exchange_handlers/soap_handler.rb +241 -241
- data/lib/soaspec/exe_helpers.rb +94 -94
- data/lib/soaspec/generate_server.rb +48 -48
- 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/features/support/env.rb.erb +3 -3
- data/lib/soaspec/generator/generate_exchange.html.erb +47 -47
- 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 +56 -56
- 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 +9 -9
- data/lib/soaspec/interpreter.rb +70 -70
- data/lib/soaspec/matchers.rb +140 -118
- data/lib/soaspec/o_auth2.rb +142 -142
- data/lib/soaspec/soaspec_shared_examples.rb +26 -26
- data/lib/soaspec/spec_logger.rb +143 -143
- data/lib/soaspec/template_reader.rb +30 -30
- data/lib/soaspec/test_server/bank.wsdl +90 -90
- data/lib/soaspec/test_server/get_bank.rb +166 -166
- data/lib/soaspec/test_server/id_manager.rb +41 -41
- data/lib/soaspec/test_server/invoices.rb +29 -29
- 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 +21 -21
- data/lib/soaspec/test_server/test_attribute.rb +14 -14
- data/lib/soaspec/test_server/test_namespace.rb +14 -14
- data/lib/soaspec/version.rb +6 -6
- data/lib/soaspec/virtual_server.rb +190 -176
- data/lib/soaspec/wait.rb +43 -43
- data/lib/soaspec/wsdl_generator.rb +215 -215
- data/soaspec.gemspec +58 -58
- data/test.wsdl +116 -116
- data/test.xml +10 -10
- data/test_wsdl.rb +43 -43
- metadata +4 -3
data/lib/soaspec/demo.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Load this file for demoing Soaspec (e.g in IRB). Has common settings applicable for demoing
|
4
|
-
|
5
|
-
require_relative '../soaspec'
|
6
|
-
Soaspec::SpecLogger.output_to_terminal = true
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Load this file for demoing Soaspec (e.g in IRB). Has common settings applicable for demoing
|
4
|
+
|
5
|
+
require_relative '../soaspec'
|
6
|
+
Soaspec::SpecLogger.output_to_terminal = true
|
data/lib/soaspec/errors.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Soaspec
|
4
|
-
# Standard Error related to Soaspec
|
5
|
-
class Error < StandardError; end
|
6
|
-
# Error related to a response
|
7
|
-
class ResponseError <
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Soaspec
|
4
|
+
# Standard Error related to Soaspec
|
5
|
+
class Error < StandardError; end
|
6
|
+
# Error related to a response
|
7
|
+
class ResponseError < Error; end
|
8
|
+
# Error related to not having a recorded baseline yet
|
9
|
+
class BaselineError < Error; end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Raised to represent when there's no element at an Xpath
|
13
|
+
class NoElementAtPath < Soaspec::Error
|
14
|
+
def initialize(msg = 'No element at path found')
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Did not find any element by provided key in the Hash
|
20
|
+
class NoElementInHash < Soaspec::Error
|
21
|
+
def initialize(msg = 'No element in Hash found')
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
@@ -1,129 +1,129 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../../soaspec'
|
4
|
-
require_relative 'exchange_properties'
|
5
|
-
require_relative 'exchange_extractor'
|
6
|
-
require_relative 'request_builder'
|
7
|
-
require_relative 'exchange_repeater'
|
8
|
-
require_relative 'variable_storer'
|
9
|
-
|
10
|
-
# This represents a request / response pair
|
11
|
-
# Essentially, params in the exchange that are set are related to the request
|
12
|
-
# What is returned is related to the response
|
13
|
-
#
|
14
|
-
# It is tied to an ExchangeHandler that needs to be defined either globally before it's created or in 'default_handler_used'
|
15
|
-
class Exchange
|
16
|
-
extend Soaspec::ExchangeProperties
|
17
|
-
include Soaspec::ExchangeExtractor
|
18
|
-
include Soaspec::RequestBuilder
|
19
|
-
include Soaspec::ExchangeRepeater
|
20
|
-
include Soaspec::VariableStorer
|
21
|
-
|
22
|
-
# Instance of ExchangeHandler for which this exchange is made
|
23
|
-
attr_accessor :exchange_handler
|
24
|
-
# @return [Integer] How many times to retry for a success
|
25
|
-
attr_accessor :retry_count
|
26
|
-
# @return [Integer] Times request was retried before being returned
|
27
|
-
attr_accessor :times_retried
|
28
|
-
# @@return [String] Name used for displaying class
|
29
|
-
attr_accessor :test_name
|
30
|
-
# Expect Factory to fail upon trying to create
|
31
|
-
attr_writer :fail_factory
|
32
|
-
# Parameters to override for default params
|
33
|
-
attr_accessor :override_parameters
|
34
|
-
|
35
|
-
# Set retry for success variable to true so that request will be retried
|
36
|
-
# for retry_count until it's true
|
37
|
-
def retry_for_success
|
38
|
-
@retry_for_success = true
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
# This is set on an individual Exchange marking it as one that should be retried
|
43
|
-
# @return [Bool] Whether to keep making request until success code reached
|
44
|
-
def retry_for_success?
|
45
|
-
@retry_for_success
|
46
|
-
end
|
47
|
-
|
48
|
-
# Defined as general rule from ExchangeHandler
|
49
|
-
# @return [Boolean] Whether exception is an exception that must be retried
|
50
|
-
def invalid_exception?
|
51
|
-
!exchange_handler.retry_on_exceptions.find { |e| e == exchange_handler.exception.class }.nil?
|
52
|
-
end
|
53
|
-
|
54
|
-
# Override this in subclass to tie that subclass to an ExchangeHandler
|
55
|
-
# @return [Soaspec::ExchangeHandler] Soaspec::ExchangeHandler used by this exchange
|
56
|
-
def default_handler_used; end
|
57
|
-
|
58
|
-
# Create new Exchange according to parameters set. A response will be made if called
|
59
|
-
# explicitly with 'response' method or through other methods that use it like 'status_code'
|
60
|
-
# @param [Symbol, String] name Name shown in RSpec run
|
61
|
-
# @param [Hash] override_parameters Parameters to override for default params
|
62
|
-
def initialize(name = self.class.to_s, override_parameters = {})
|
63
|
-
self.test_name ||= name.to_s
|
64
|
-
# As a last resort this uses the global parameter. The handler should be set straight before an exchange is made to use this
|
65
|
-
@exchange_handler ||= default_handler_used || Soaspec.api_handler
|
66
|
-
raise '@exchange_handler not set. Set either with `Soaspec.api_handler = Handler.new` or within the exchange' unless @exchange_handler
|
67
|
-
|
68
|
-
@fail_factory = nil
|
69
|
-
@override_parameters = override_parameters
|
70
|
-
@retry_for_success = false
|
71
|
-
self.retry_count = exchange_handler.retry_exception_limit
|
72
|
-
exchange_handler.elements.each { |element| methods_for_element(element) }
|
73
|
-
end
|
74
|
-
|
75
|
-
# @return [Hash] Hash representing what will be sent
|
76
|
-
def request_parameters
|
77
|
-
exchange_handler.request_parameters(@override_parameters)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Make request to handler with parameters defined
|
81
|
-
# Will retry until success code reached if retry_for_success? is set
|
82
|
-
# @return [Response] Response from Api handler
|
83
|
-
def make_request
|
84
|
-
Soaspec::SpecLogger.info 'Example ' + test_name
|
85
|
-
request_params = @override_parameters
|
86
|
-
(0..retry_count).each do |count|
|
87
|
-
response = exchange_handler.make_request(request_params)
|
88
|
-
return response if !retry_for_success? && !invalid_exception?
|
89
|
-
return response if (200..299).cover? exchange_handler.status_code_for(response)
|
90
|
-
|
91
|
-
sleep exchange_handler.retry_pause_time # Time before retrying
|
92
|
-
self.times_retried = count
|
93
|
-
break response if count == retry_count
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Name describing this class when used with `RSpec.describe`
|
98
|
-
# This will make the request and store the response
|
99
|
-
# @return [String] Name given when initializing
|
100
|
-
def to_s
|
101
|
-
test_name
|
102
|
-
end
|
103
|
-
|
104
|
-
# @return [RestClient::Response,Savon::Response] Returns response object from Api.
|
105
|
-
# Will make the request if not made and then cache it for later on
|
106
|
-
# @example For SOAP it will be a Savon response
|
107
|
-
# response.body (body of response as Hash)
|
108
|
-
# response.header (head of response as Hash)
|
109
|
-
# @example For REST it will be a RestClient::Response
|
110
|
-
def response
|
111
|
-
require 'forwardable'
|
112
|
-
Soaspec.last_exchange = self
|
113
|
-
@response ||= make_request
|
114
|
-
@response.define_singleton_method(:exchange) { Soaspec.last_exchange } unless @response.respond_to?(:exchange)
|
115
|
-
@response.extend Forwardable
|
116
|
-
@response.delegate %i[value_from_path values_from_path] => :exchange
|
117
|
-
@response
|
118
|
-
end
|
119
|
-
|
120
|
-
# @return [ResponseObject] Currently returning response object. This will change (in 0.3) to be itself to
|
121
|
-
# allow easy method chaining
|
122
|
-
def call
|
123
|
-
if Soaspec.log_warnings
|
124
|
-
warn 'This "call" method will be changed to return "Exchange" object in 0.3. ' \
|
125
|
-
'Use "response" method if you want the "response" object'
|
126
|
-
end
|
127
|
-
response
|
128
|
-
end
|
129
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../soaspec'
|
4
|
+
require_relative 'exchange_properties'
|
5
|
+
require_relative 'exchange_extractor'
|
6
|
+
require_relative 'request_builder'
|
7
|
+
require_relative 'exchange_repeater'
|
8
|
+
require_relative 'variable_storer'
|
9
|
+
|
10
|
+
# This represents a request / response pair
|
11
|
+
# Essentially, params in the exchange that are set are related to the request
|
12
|
+
# What is returned is related to the response
|
13
|
+
#
|
14
|
+
# It is tied to an ExchangeHandler that needs to be defined either globally before it's created or in 'default_handler_used'
|
15
|
+
class Exchange
|
16
|
+
extend Soaspec::ExchangeProperties
|
17
|
+
include Soaspec::ExchangeExtractor
|
18
|
+
include Soaspec::RequestBuilder
|
19
|
+
include Soaspec::ExchangeRepeater
|
20
|
+
include Soaspec::VariableStorer
|
21
|
+
|
22
|
+
# Instance of ExchangeHandler for which this exchange is made
|
23
|
+
attr_accessor :exchange_handler
|
24
|
+
# @return [Integer] How many times to retry for a success
|
25
|
+
attr_accessor :retry_count
|
26
|
+
# @return [Integer] Times request was retried before being returned
|
27
|
+
attr_accessor :times_retried
|
28
|
+
# @@return [String] Name used for displaying class
|
29
|
+
attr_accessor :test_name
|
30
|
+
# Expect Factory to fail upon trying to create
|
31
|
+
attr_writer :fail_factory
|
32
|
+
# Parameters to override for default params
|
33
|
+
attr_accessor :override_parameters
|
34
|
+
|
35
|
+
# Set retry for success variable to true so that request will be retried
|
36
|
+
# for retry_count until it's true
|
37
|
+
def retry_for_success
|
38
|
+
@retry_for_success = true
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# This is set on an individual Exchange marking it as one that should be retried
|
43
|
+
# @return [Bool] Whether to keep making request until success code reached
|
44
|
+
def retry_for_success?
|
45
|
+
@retry_for_success
|
46
|
+
end
|
47
|
+
|
48
|
+
# Defined as general rule from ExchangeHandler
|
49
|
+
# @return [Boolean] Whether exception is an exception that must be retried
|
50
|
+
def invalid_exception?
|
51
|
+
!exchange_handler.retry_on_exceptions.find { |e| e == exchange_handler.exception.class }.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
# Override this in subclass to tie that subclass to an ExchangeHandler
|
55
|
+
# @return [Soaspec::ExchangeHandler] Soaspec::ExchangeHandler used by this exchange
|
56
|
+
def default_handler_used; end
|
57
|
+
|
58
|
+
# Create new Exchange according to parameters set. A response will be made if called
|
59
|
+
# explicitly with 'response' method or through other methods that use it like 'status_code'
|
60
|
+
# @param [Symbol, String] name Name shown in RSpec run
|
61
|
+
# @param [Hash] override_parameters Parameters to override for default params
|
62
|
+
def initialize(name = self.class.to_s, override_parameters = {})
|
63
|
+
self.test_name ||= name.to_s
|
64
|
+
# As a last resort this uses the global parameter. The handler should be set straight before an exchange is made to use this
|
65
|
+
@exchange_handler ||= default_handler_used || Soaspec.api_handler
|
66
|
+
raise '@exchange_handler not set. Set either with `Soaspec.api_handler = Handler.new` or within the exchange' unless @exchange_handler
|
67
|
+
|
68
|
+
@fail_factory = nil
|
69
|
+
@override_parameters = override_parameters
|
70
|
+
@retry_for_success = false
|
71
|
+
self.retry_count = exchange_handler.retry_exception_limit
|
72
|
+
exchange_handler.elements.each { |element| methods_for_element(element) }
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Hash] Hash representing what will be sent
|
76
|
+
def request_parameters
|
77
|
+
exchange_handler.request_parameters(@override_parameters)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Make request to handler with parameters defined
|
81
|
+
# Will retry until success code reached if retry_for_success? is set
|
82
|
+
# @return [Response] Response from Api handler
|
83
|
+
def make_request
|
84
|
+
Soaspec::SpecLogger.info 'Example ' + test_name
|
85
|
+
request_params = @override_parameters
|
86
|
+
(0..retry_count).each do |count|
|
87
|
+
response = exchange_handler.make_request(request_params)
|
88
|
+
return response if !retry_for_success? && !invalid_exception?
|
89
|
+
return response if (200..299).cover? exchange_handler.status_code_for(response)
|
90
|
+
|
91
|
+
sleep exchange_handler.retry_pause_time # Time before retrying
|
92
|
+
self.times_retried = count
|
93
|
+
break response if count == retry_count
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Name describing this class when used with `RSpec.describe`
|
98
|
+
# This will make the request and store the response
|
99
|
+
# @return [String] Name given when initializing
|
100
|
+
def to_s
|
101
|
+
test_name
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [RestClient::Response,Savon::Response] Returns response object from Api.
|
105
|
+
# Will make the request if not made and then cache it for later on
|
106
|
+
# @example For SOAP it will be a Savon response
|
107
|
+
# response.body (body of response as Hash)
|
108
|
+
# response.header (head of response as Hash)
|
109
|
+
# @example For REST it will be a RestClient::Response
|
110
|
+
def response
|
111
|
+
require 'forwardable'
|
112
|
+
Soaspec.last_exchange = self
|
113
|
+
@response ||= make_request
|
114
|
+
@response.define_singleton_method(:exchange) { Soaspec.last_exchange } unless @response.respond_to?(:exchange)
|
115
|
+
@response.extend Forwardable
|
116
|
+
@response.delegate %i[value_from_path values_from_path] => :exchange
|
117
|
+
@response
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [ResponseObject] Currently returning response object. This will change (in 0.3) to be itself to
|
121
|
+
# allow easy method chaining
|
122
|
+
def call
|
123
|
+
if Soaspec.log_warnings
|
124
|
+
warn 'This "call" method will be changed to return "Exchange" object in 0.3. ' \
|
125
|
+
'Use "response" method if you want the "response" object'
|
126
|
+
end
|
127
|
+
response
|
128
|
+
end
|
129
|
+
end
|
@@ -1,90 +1,90 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Soaspec
|
4
|
-
# Methods for extracting aspects of the traffic for a request / response
|
5
|
-
# in an exchange from the ExchangeHandler that it's tied to
|
6
|
-
module ExchangeExtractor
|
7
|
-
# Request of API call. Either intended request or actual request
|
8
|
-
# @return [Object] Object representing request of API
|
9
|
-
def request
|
10
|
-
exchange_handler.request(@response)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Get status code from api class. This is http response code for Web Api
|
14
|
-
# @return [Integer] Status code from api class
|
15
|
-
def status_code
|
16
|
-
exchange_handler.status_code_for(response)
|
17
|
-
end
|
18
|
-
|
19
|
-
# @return [Boolean] Whether Api success code is successful
|
20
|
-
def successful_status_code?
|
21
|
-
(200..299).cover? status_code
|
22
|
-
end
|
23
|
-
|
24
|
-
# Extract value from path api class
|
25
|
-
# @example Extract unique value
|
26
|
-
# @exchange['unique_value_name']
|
27
|
-
# @example Extract value via JSON path
|
28
|
-
# @exchange['$..path.to.element']
|
29
|
-
# @example Extract value via XPath
|
30
|
-
# @exchange['//path/to/element']
|
31
|
-
# @param [Object] path Path to return element for api class E.g - for SOAP this is XPath string. For JSON, this is Hash dig Array
|
32
|
-
# @return [String] Value at path
|
33
|
-
def [](path)
|
34
|
-
exchange_handler.value_from_path(response, path.to_s)
|
35
|
-
end
|
36
|
-
|
37
|
-
alias value_from_path []
|
38
|
-
|
39
|
-
# Using same path syntax as []. Returns true of false depending on whether an element is found
|
40
|
-
# @return [Boolean] Whether an element exists at the path
|
41
|
-
def element?(path)
|
42
|
-
self[path]
|
43
|
-
true
|
44
|
-
rescue NoElementAtPath
|
45
|
-
false
|
46
|
-
end
|
47
|
-
|
48
|
-
# @example Counting items in a JSON list
|
49
|
-
# # Say there is JSON response {"notes":[{"title":"note1","note":"A note"},{"title":"note2"}]}
|
50
|
-
# titles = @exchange.values_at_path('$..title')
|
51
|
-
# expect(titles.count).to eq 2
|
52
|
-
# expect(titles.first).to eq 'note1'
|
53
|
-
# @param [String] path XPath, JSONPath to extract value
|
54
|
-
# @param [String] attribute Attribute to obtain from XML element
|
55
|
-
# @return [Array] List of values found at path
|
56
|
-
def values_from_path(path, attribute: nil)
|
57
|
-
exchange_handler.values_from_path(response, path, attribute: attribute)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Return the response equivalent of the response. XML, JSON will be converted to a Hash
|
61
|
-
# @example Counting items in a JSON list
|
62
|
-
# # Say there is JSON response {"notes":[{"title":"note1","note":"A note"},{"title":"note2"}]}
|
63
|
-
# hash = @exchange.to_hash
|
64
|
-
# expect(hash['notes'].count).to eq 2
|
65
|
-
# expect(hash['notes'].first['title']).to eq 'note1'
|
66
|
-
# @return [Hash] Hash representing the response of the API
|
67
|
-
def to_hash
|
68
|
-
exchange_handler.to_hash(response)
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
# Used to define methods on an exchange based on what's defined by the ExchangeHandler's methods
|
74
|
-
# @param [String] element Element to define methods for
|
75
|
-
def methods_for_element(element)
|
76
|
-
element_name = element.to_s.split('__custom_path_').last
|
77
|
-
define_singleton_method(element_name) do
|
78
|
-
exchange_handler.__send__(element, response) # Forward the call onto handler to retrieve the element for the response
|
79
|
-
end
|
80
|
-
define_singleton_method("#{element_name}?") do
|
81
|
-
begin
|
82
|
-
__send__ element_name
|
83
|
-
true
|
84
|
-
rescue NoElementAtPath
|
85
|
-
false
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Soaspec
|
4
|
+
# Methods for extracting aspects of the traffic for a request / response
|
5
|
+
# in an exchange from the ExchangeHandler that it's tied to
|
6
|
+
module ExchangeExtractor
|
7
|
+
# Request of API call. Either intended request or actual request
|
8
|
+
# @return [Object] Object representing request of API
|
9
|
+
def request
|
10
|
+
exchange_handler.request(@response)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get status code from api class. This is http response code for Web Api
|
14
|
+
# @return [Integer] Status code from api class
|
15
|
+
def status_code
|
16
|
+
exchange_handler.status_code_for(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Boolean] Whether Api success code is successful
|
20
|
+
def successful_status_code?
|
21
|
+
(200..299).cover? status_code
|
22
|
+
end
|
23
|
+
|
24
|
+
# Extract value from path api class
|
25
|
+
# @example Extract unique value
|
26
|
+
# @exchange['unique_value_name']
|
27
|
+
# @example Extract value via JSON path
|
28
|
+
# @exchange['$..path.to.element']
|
29
|
+
# @example Extract value via XPath
|
30
|
+
# @exchange['//path/to/element']
|
31
|
+
# @param [Object] path Path to return element for api class E.g - for SOAP this is XPath string. For JSON, this is Hash dig Array
|
32
|
+
# @return [String] Value at path
|
33
|
+
def [](path)
|
34
|
+
exchange_handler.value_from_path(response, path.to_s)
|
35
|
+
end
|
36
|
+
|
37
|
+
alias value_from_path []
|
38
|
+
|
39
|
+
# Using same path syntax as []. Returns true of false depending on whether an element is found
|
40
|
+
# @return [Boolean] Whether an element exists at the path
|
41
|
+
def element?(path)
|
42
|
+
self[path]
|
43
|
+
true
|
44
|
+
rescue NoElementAtPath
|
45
|
+
false
|
46
|
+
end
|
47
|
+
|
48
|
+
# @example Counting items in a JSON list
|
49
|
+
# # Say there is JSON response {"notes":[{"title":"note1","note":"A note"},{"title":"note2"}]}
|
50
|
+
# titles = @exchange.values_at_path('$..title')
|
51
|
+
# expect(titles.count).to eq 2
|
52
|
+
# expect(titles.first).to eq 'note1'
|
53
|
+
# @param [String] path XPath, JSONPath to extract value
|
54
|
+
# @param [String] attribute Attribute to obtain from XML element
|
55
|
+
# @return [Array] List of values found at path
|
56
|
+
def values_from_path(path, attribute: nil)
|
57
|
+
exchange_handler.values_from_path(response, path, attribute: attribute)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return the response equivalent of the response. XML, JSON will be converted to a Hash
|
61
|
+
# @example Counting items in a JSON list
|
62
|
+
# # Say there is JSON response {"notes":[{"title":"note1","note":"A note"},{"title":"note2"}]}
|
63
|
+
# hash = @exchange.to_hash
|
64
|
+
# expect(hash['notes'].count).to eq 2
|
65
|
+
# expect(hash['notes'].first['title']).to eq 'note1'
|
66
|
+
# @return [Hash] Hash representing the response of the API
|
67
|
+
def to_hash
|
68
|
+
exchange_handler.to_hash(response)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Used to define methods on an exchange based on what's defined by the ExchangeHandler's methods
|
74
|
+
# @param [String] element Element to define methods for
|
75
|
+
def methods_for_element(element)
|
76
|
+
element_name = element.to_s.split('__custom_path_').last
|
77
|
+
define_singleton_method(element_name) do
|
78
|
+
exchange_handler.__send__(element, response) # Forward the call onto handler to retrieve the element for the response
|
79
|
+
end
|
80
|
+
define_singleton_method("#{element_name}?") do
|
81
|
+
begin
|
82
|
+
__send__ element_name
|
83
|
+
true
|
84
|
+
rescue NoElementAtPath
|
85
|
+
false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|