soaspec 0.3.2 → 0.3.3
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/.gitlab-ci.yml +2 -0
- data/.yardopts +1 -0
- data/ChangeLog +7 -0
- data/Dockerfile +3 -1
- data/lib/soaspec/baseline.rb +4 -2
- data/lib/soaspec/exchange_handlers/exchange_handler.rb +5 -3
- data/lib/soaspec/exchange_handlers/request/rest_request.rb +59 -9
- data/lib/soaspec/exchange_handlers/response_extractor.rb +2 -2
- data/lib/soaspec/exchange_handlers/rest_handler.rb +29 -76
- data/lib/soaspec/exchange_handlers/soap_defaults.rb +25 -0
- data/lib/soaspec/exchange_handlers/soap_globals.rb +28 -0
- data/lib/soaspec/exchange_handlers/soap_handler.rb +30 -25
- data/lib/soaspec/interpreter.rb +4 -5
- data/lib/soaspec/matchers.rb +5 -5
- data/lib/soaspec/o_auth2.rb +13 -3
- data/lib/soaspec/template_reader.rb +5 -1
- data/lib/soaspec/version.rb +1 -1
- data/lib/soaspec/virtual_server.rb +13 -8
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9f6e35bf3fb8a025d3b6b3e7331686c6b1c2c6ab332fc46edf4c63e360e4b37
|
4
|
+
data.tar.gz: a1c11edd859c3b71a5f2384cef5437c41ec609a4104df144e6491d3081f588c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74334ea904ce3ff6f131e43b1954945231bb0178aba8867564e7e9056b1f723a9506a500de582fa226d77dc872384a4944306b5dd35ae7766d1d1f0fd5c05af1
|
7
|
+
data.tar.gz: 8f9ff7688a0442663faa05a640912b8e4161317597ddd8ea6ad3e6cb7632800b50ed7441fb38caa080782e2f2b2d519d3e07ded33c552179c32514ceeeb21d35
|
data/.gitlab-ci.yml
CHANGED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--plugin yard-doctest
|
data/ChangeLog
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
Version 0.3.3
|
2
|
+
* Enhancement
|
3
|
+
* Ability to specify multipart on Soaspec::OAuth2, not always assume it's value
|
4
|
+
* Bug Fix
|
5
|
+
* SOAP error was calling undefined error
|
6
|
+
* SOAP 'format' for 'Exchange' was not being calculated as :xml
|
7
|
+
|
1
8
|
Version 0.3.2
|
2
9
|
* Enhancement
|
3
10
|
* Handle 'html' format
|
data/Dockerfile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
FROM ruby:2.6
|
2
|
-
|
2
|
+
LABEL maintainer='Samuel Garratt'
|
3
|
+
LABEL description='Dockerfile with soaspec gems preinstalled'
|
3
4
|
LABEL url="https://gitlab.com/samuel-garratt/soaspec/blob/master/Dockerfile"
|
4
5
|
# Simple Dockerfile with gems preinstalled
|
5
6
|
RUN gem install bundler rake soaspec
|
7
|
+
|
6
8
|
ENV LANG=en_US.UTF-8
|
7
9
|
ENV LANGUAGE=en_US.UTF-8
|
8
10
|
ENV LC_ALL=en_US.UTF-8
|
data/lib/soaspec/baseline.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'exe_helpers'
|
2
4
|
|
3
5
|
module Soaspec
|
@@ -8,7 +10,7 @@ module Soaspec
|
|
8
10
|
@folder = File.join('config', 'baseline')
|
9
11
|
|
10
12
|
# @return [Array] List of allowed formats
|
11
|
-
ALLOWED_FORMATS = [
|
13
|
+
ALLOWED_FORMATS = %i[raw hash].freeze
|
12
14
|
|
13
15
|
# @return [Exchange] Exchange object to save/assert baseline for
|
14
16
|
attr_accessor :exchange
|
@@ -80,4 +82,4 @@ module Soaspec
|
|
80
82
|
attr_accessor :folder
|
81
83
|
end
|
82
84
|
end
|
83
|
-
end
|
85
|
+
end
|
@@ -22,6 +22,8 @@ module Soaspec
|
|
22
22
|
|
23
23
|
# @return [String] Name of the template file to be used in the API request
|
24
24
|
attr_reader :template_name
|
25
|
+
# @return [Symbol] Option used to generate Request Body. Either :hash or :template
|
26
|
+
attr_accessor :request_option
|
25
27
|
|
26
28
|
# Explicitly defined elements for which a path has been predefined
|
27
29
|
def elements
|
@@ -33,7 +35,7 @@ module Soaspec
|
|
33
35
|
# @param [Hash] _options Parameters defining handler. Used in descendants
|
34
36
|
def initialize(name = self.class.to_s, _options = {})
|
35
37
|
use
|
36
|
-
|
38
|
+
self.request_option = :hash
|
37
39
|
raise ArgumentError, 'Cannot define both template_name and default_hash' if respond_to?(:template_name_value) && respond_to?(:default_hash_value)
|
38
40
|
|
39
41
|
@template_name = respond_to?(:template_name_value) ? template_name_value : ''
|
@@ -59,7 +61,7 @@ module Soaspec
|
|
59
61
|
# This will set the @request_option instance variable too
|
60
62
|
# @param [Hash] hash Hash to send in request body by default
|
61
63
|
def default_hash=(hash)
|
62
|
-
|
64
|
+
self.request_option = :hash
|
63
65
|
@default_hash = Soaspec.always_use_keys? ? hash.transform_keys_to_symbols : hash
|
64
66
|
end
|
65
67
|
|
@@ -67,7 +69,7 @@ module Soaspec
|
|
67
69
|
# Erb is used to parse the template file, executing Ruby code in `<%= %>` blocks to work out the final request
|
68
70
|
# @param [String] name Name of file inside 'template' folder excluding extension
|
69
71
|
def template_name=(name)
|
70
|
-
|
72
|
+
self.request_option = :template
|
71
73
|
@template_name = name
|
72
74
|
end
|
73
75
|
|
@@ -24,14 +24,40 @@ module Soaspec
|
|
24
24
|
# Headers. Keys that are `symbols` will be converted from `snake_case` to `Word-Word2`
|
25
25
|
# @return [Hash] Headers sent as part of request
|
26
26
|
attr_accessor :headers
|
27
|
+
# @return [Soaspec::RestHandler] RestHandler used for this request
|
28
|
+
attr_accessor :rest_handler
|
29
|
+
|
30
|
+
# Interpret REST parameters given provided parameters and adding defaults, making
|
31
|
+
# transformations
|
32
|
+
#
|
33
|
+
# @param [Hash] request_parameters Parameters used in making a request
|
34
|
+
# @return [Hash] Request parameters merged with default values
|
35
|
+
def interpret_parameters(request_parameters)
|
36
|
+
request_parameters = request_parameters.dup # Must duplicate hash as deletion occurring
|
37
|
+
request_parameters[:params] ||= {}
|
38
|
+
request_parameters[:method] ||= :post
|
39
|
+
suburl = request_parameters[:suburl]
|
40
|
+
if suburl
|
41
|
+
request_parameters[:suburl] = if suburl.is_a? Array
|
42
|
+
suburl.collect(&:to_s).join('/')
|
43
|
+
else
|
44
|
+
suburl.to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
# Use q for query parameters. Nested :params is ugly, long and unclear
|
48
|
+
request_parameters[:params] = request_parameters.delete(:q) if request_parameters[:q]
|
49
|
+
request_parameters
|
50
|
+
end
|
27
51
|
|
28
52
|
# @param [Hash] overall Overall parameters used in Request
|
29
53
|
# @param [Hash] options Headers and basic auth options
|
30
|
-
# @param [
|
31
|
-
def initialize(overall, options,
|
32
|
-
|
33
|
-
|
54
|
+
# @param [Soaspec::RestHandler] rest_handler RestHandler handling creation of this request
|
55
|
+
def initialize(overall, options, rest_handler)
|
56
|
+
self.rest_handler = rest_handler
|
57
|
+
overall_params = interpret_parameters(overall)
|
58
|
+
@overall_params = overall_params
|
34
59
|
self.method = overall_params.delete(:method)
|
60
|
+
self.body = payload? ? post_data : nil #body
|
35
61
|
self.suburl = overall_params.delete(:suburl)
|
36
62
|
self.test_name = overall_params.delete(:name)
|
37
63
|
self.other_params = overall_params
|
@@ -42,7 +68,7 @@ module Soaspec
|
|
42
68
|
|
43
69
|
# @return [Hash] Query parameters for a REST Request
|
44
70
|
def query
|
45
|
-
other_params[:
|
71
|
+
other_params[:params]
|
46
72
|
end
|
47
73
|
|
48
74
|
# @param [String, Symbol] value Message to send to object retrieving a value
|
@@ -65,13 +91,37 @@ module Soaspec
|
|
65
91
|
def description
|
66
92
|
suburl_desc = suburl.is_a?(Array) ? File.join(suburl) : suburl
|
67
93
|
query_desc = ''
|
68
|
-
|
69
|
-
|
70
|
-
query_desc = File.join(query_desc, "#{key}_#{value}")
|
71
|
-
end
|
94
|
+
query&.each do |key, value|
|
95
|
+
query_desc = File.join(query_desc, "#{key}_#{value}")
|
72
96
|
end
|
73
97
|
components = [method.to_s, suburl_desc, query_desc, 'response']
|
74
98
|
File.join(*components.collect!(&:to_s))
|
75
99
|
end
|
100
|
+
|
101
|
+
# @return [Boolean] Whether REST method should have a payload
|
102
|
+
def payload?
|
103
|
+
case method
|
104
|
+
when :post, :patch, :put
|
105
|
+
true
|
106
|
+
else
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# TODO: Implement this for this object
|
112
|
+
# Work out data to send based upon payload, template_name, or body
|
113
|
+
# @return [String] Payload to send in REST request
|
114
|
+
def post_data
|
115
|
+
option = rest_handler.request_option
|
116
|
+
if option == :hash && !@overall_params[:payload]
|
117
|
+
@overall_params[:payload] = JSON.generate(rest_handler.hash_used_in_request(@overall_params[:body])).to_s
|
118
|
+
elsif option == :template
|
119
|
+
test_values = nil
|
120
|
+
test_values = @overall_params[:body].dup if @overall_params[:body]
|
121
|
+
Soaspec::TemplateReader.new.render_body(rest_handler.template_name, test_values || @overall_params)
|
122
|
+
else
|
123
|
+
@overall_params[:payload]
|
124
|
+
end
|
125
|
+
end
|
76
126
|
end
|
77
127
|
end
|
@@ -16,9 +16,9 @@ module Soaspec
|
|
16
16
|
return converted.transform_keys_to_symbols if converted.is_a? Hash
|
17
17
|
return converted.map!(&:transform_keys_to_symbols) if converted.is_a? Array
|
18
18
|
|
19
|
-
raise 'Incorrect Type produced ' + converted.class
|
19
|
+
raise Soaspec::ResponseError, 'Incorrect Type produced ' + converted.class
|
20
20
|
else
|
21
|
-
raise "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}"
|
21
|
+
raise Soaspec::ResponseError, "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -38,49 +38,12 @@ module Soaspec
|
|
38
38
|
super
|
39
39
|
set_remove_keys(options, %i[api_username default_hash template_name])
|
40
40
|
@init_options = options
|
41
|
-
init_merge_options #
|
41
|
+
@merged_options ||= init_merge_options # Caches initial merge options
|
42
42
|
end
|
43
43
|
|
44
|
-
# @return [
|
45
|
-
def payload?(overall_params)
|
46
|
-
case overall_params[:method]
|
47
|
-
when :post, :patch, :put
|
48
|
-
true
|
49
|
-
else
|
50
|
-
false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# @todo Use this in actually making the request
|
55
|
-
# At the moment this is just for one to manually view the parameters
|
56
|
-
# that will be used in making a request
|
57
|
-
# @return [RestRequest] Parameters used in making a request
|
44
|
+
# @return [Soaspec::RestRequest] Parameters used in making a request
|
58
45
|
def request_parameters(override_parameters)
|
59
|
-
|
60
|
-
request = { overall: overall_params, options: init_merge_options }
|
61
|
-
request[:body] = post_data(overall_params) if payload?(overall_params)
|
62
|
-
RestRequest.new(overall_params, init_merge_options, payload?(overall_params) ? post_data(overall_params) : nil)
|
63
|
-
end
|
64
|
-
|
65
|
-
# Interpret REST parameters given provided parameters and adding defaults, making
|
66
|
-
# transformations
|
67
|
-
#
|
68
|
-
# @param [Hash] request_parameters Parameters used in making a request
|
69
|
-
# @return [Hash] Request parameters merged with default values
|
70
|
-
def interpret_parameters(request_parameters)
|
71
|
-
request_parameters[:params] ||= {}
|
72
|
-
request_parameters[:method] ||= :post
|
73
|
-
suburl = request_parameters[:suburl]
|
74
|
-
if suburl
|
75
|
-
if suburl.is_a? Array
|
76
|
-
request_parameters[:suburl] = suburl.collect(&:to_s).join('/')
|
77
|
-
else
|
78
|
-
request_parameters[:suburl] = suburl.to_s
|
79
|
-
end
|
80
|
-
end
|
81
|
-
# Use q for query parameters. Nested :params is ugly, long and unclear
|
82
|
-
request_parameters[:params][:params] = request_parameters[:q] if request_parameters[:q]
|
83
|
-
request_parameters
|
46
|
+
RestRequest.new(override_parameters, @merged_options, self)
|
84
47
|
end
|
85
48
|
|
86
49
|
# Override this with 'after_response' within class definition to perform an action
|
@@ -100,20 +63,19 @@ module Soaspec
|
|
100
63
|
# @option override_parameters [String] :template_name Path to file to be read via ERB and passed in request body
|
101
64
|
# @return [RestClient::Response] Response from making request
|
102
65
|
def make_request(override_parameters)
|
103
|
-
|
104
|
-
test_values = interpret_parameters override_parameters
|
66
|
+
req_params = request_parameters override_parameters
|
105
67
|
# In order for ERB to be calculated at correct time, the first time request is made, the resource should be created
|
106
68
|
@resource ||= RestClient::Resource.new(ERB.new(base_url_value).result(binding), @merged_options)
|
107
|
-
@resource_used =
|
69
|
+
@resource_used = req_params.suburl ? @resource[req_params.suburl] : @resource
|
108
70
|
|
109
71
|
self.exception = nil # Remove any previously stored exception
|
110
72
|
begin
|
111
|
-
response = case
|
73
|
+
response = case req_params.method
|
112
74
|
when :post, :patch, :put
|
113
|
-
Soaspec::SpecLogger.info("request body: #{post_data
|
114
|
-
@resource_used.send(
|
75
|
+
Soaspec::SpecLogger.info("request body: #{req_params.post_data}")
|
76
|
+
@resource_used.send(req_params.method, req_params.post_data, req_params.other_params)
|
115
77
|
else # :get, :delete
|
116
|
-
@resource_used.send(
|
78
|
+
@resource_used.send(req_params.method, req_params.other_params )
|
117
79
|
end
|
118
80
|
rescue RestClient::Exception => e
|
119
81
|
self.exception = e
|
@@ -126,6 +88,17 @@ module Soaspec
|
|
126
88
|
response
|
127
89
|
end
|
128
90
|
|
91
|
+
# @param [Hash] override_hash Values to override default hash with
|
92
|
+
# @return [Hash] Hash used in REST request based on data conversion
|
93
|
+
def hash_used_in_request(override_hash)
|
94
|
+
request = override_hash ? @default_hash.merge(override_hash) : @default_hash
|
95
|
+
if pascal_keys?
|
96
|
+
request.map { |k, v| [convert_to_pascal_case(k.to_s), v] }.to_h
|
97
|
+
else
|
98
|
+
request
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
129
102
|
# Add values to here when extending this class to have default REST options.
|
130
103
|
# See rest client resource at https://github.com/rest-client/rest-client for details
|
131
104
|
# It's easier to set headers via 'headers' accessor rather than here
|
@@ -145,6 +118,7 @@ module Soaspec
|
|
145
118
|
end
|
146
119
|
|
147
120
|
# Initialize value of merged options
|
121
|
+
# Also called to verify any issues with options on creating object
|
148
122
|
# @return [Hash] Hash of merged options
|
149
123
|
def init_merge_options
|
150
124
|
options = rest_resource_options
|
@@ -179,6 +153,9 @@ module Soaspec
|
|
179
153
|
# @return [Boolean] Whether response body contains expected key
|
180
154
|
def include_key?(response, expected)
|
181
155
|
value_from_path(response, expected)
|
156
|
+
true
|
157
|
+
rescue NoElementAtPath
|
158
|
+
false
|
182
159
|
end
|
183
160
|
|
184
161
|
# @return [Integer] HTTP Status code for response
|
@@ -270,38 +247,14 @@ module Soaspec
|
|
270
247
|
end
|
271
248
|
end
|
272
249
|
|
273
|
-
# @return [RestClient::Request] Request of API call. Either intended request or actual request
|
250
|
+
# @return [RestClient::Request, String] Request of API call. Either intended request or actual request
|
274
251
|
def request(response)
|
275
|
-
|
252
|
+
if response.nil?
|
253
|
+
return 'Request not yet sent. Call :request_parameters' \
|
254
|
+
'for what will be sent'
|
255
|
+
end
|
276
256
|
|
277
257
|
response.request
|
278
258
|
end
|
279
|
-
|
280
|
-
# Work out data to send based upon payload, template_name, or body
|
281
|
-
# @return [String] Payload to send in REST request
|
282
|
-
def post_data(test_values)
|
283
|
-
data = if @request_option == :hash && !test_values[:payload]
|
284
|
-
test_values[:payload] = JSON.generate(hash_used_in_request(test_values[:body])).to_s
|
285
|
-
elsif @request_option == :template
|
286
|
-
test_values = test_values[:body].dup if test_values[:body]
|
287
|
-
test_values = IndifferentHash.new(test_values) # Allow test_values to be either Symbol or String
|
288
|
-
Soaspec::TemplateReader.new.render_body(template_name, binding)
|
289
|
-
else
|
290
|
-
test_values[:payload]
|
291
|
-
end
|
292
|
-
# Soaspec::SpecLogger.info "Request Empty for '#{@request_option}'" if data.strip.empty?
|
293
|
-
data
|
294
|
-
end
|
295
|
-
|
296
|
-
# @param [Hash] override_hash Values to override default hash with
|
297
|
-
# @return [Hash] Hash used in REST request based on data conversion
|
298
|
-
def hash_used_in_request(override_hash)
|
299
|
-
request = override_hash ? @default_hash.merge(override_hash) : @default_hash
|
300
|
-
if pascal_keys?
|
301
|
-
request.map { |k, v| [convert_to_pascal_case(k.to_s), v] }.to_h
|
302
|
-
else
|
303
|
-
request
|
304
|
-
end
|
305
|
-
end
|
306
259
|
end
|
307
260
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Soaspec
|
3
|
+
# Default values set in order to make testing easier. Override to fit what you
|
4
|
+
# need in testing
|
5
|
+
module SoapDefaults
|
6
|
+
class << self
|
7
|
+
# Default Savon options. See http://savonrb.com/version2/globals.html for details
|
8
|
+
# @example Things could go wrong if not set properly
|
9
|
+
# env_namespace: :soap, # Change environment namespace
|
10
|
+
# namespace_identifier: :tst, # Change namespace element
|
11
|
+
# element_form_default: :qualified # Populate each element with namespace
|
12
|
+
# namespace: 'http://Extended_namespace.xsd' change root namespace
|
13
|
+
# basic_auth: 'user', 'password'
|
14
|
+
# @return [Hash] Default Savon options for all BasicSoapHandler
|
15
|
+
def options
|
16
|
+
{
|
17
|
+
ssl_verify_mode: :none, # Easier for testing. Not so secure
|
18
|
+
follow_redirects: true, # Necessary for many API calls
|
19
|
+
soap_version: 2, # use SOAP 1.2. You will get 415 error if this is incorrect
|
20
|
+
raise_errors: false # HTTP errors not cause failure as often negative test scenarios expect not 200 response
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Soaspec
|
2
|
+
# Singleton methods for assigning Savon globals (http://savonrb.com/version2/globals.html)
|
3
|
+
module SoapGlobals
|
4
|
+
# Set SOAP WSDL. Use namespace and endpoint if no WSDL defined
|
5
|
+
# @param [String] path Path to wsdl, either on network or locally
|
6
|
+
def wsdl(path)
|
7
|
+
define_method('wsdl') { path }
|
8
|
+
end
|
9
|
+
|
10
|
+
# Set Basic auth
|
11
|
+
def basic_auth(user, password)
|
12
|
+
define_method('basic_auth') { [user, password] }
|
13
|
+
end
|
14
|
+
|
15
|
+
# SOAP version number. Default is version 1.2
|
16
|
+
# @example SOAP Version 1.1
|
17
|
+
# soap_version 1
|
18
|
+
def soap_version(number)
|
19
|
+
define_method('soap_version') { number }
|
20
|
+
end
|
21
|
+
|
22
|
+
%w[raise_errors namespace namespaces endpoint ssl_verify_mode].each do |method|
|
23
|
+
define_method(method) do |param|
|
24
|
+
define_method(method) { param }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -6,6 +6,8 @@ require_relative '../errors'
|
|
6
6
|
require_relative 'handler_accessors'
|
7
7
|
require_relative '../interpreter'
|
8
8
|
require_relative 'request/soap_request'
|
9
|
+
require_relative 'soap_globals'
|
10
|
+
require_relative 'soap_defaults'
|
9
11
|
require 'forwardable'
|
10
12
|
|
11
13
|
module Soaspec
|
@@ -22,6 +24,7 @@ module Soaspec
|
|
22
24
|
class SoapHandler < ExchangeHandler
|
23
25
|
extend Soaspec::SoapAccessors
|
24
26
|
extend Forwardable
|
27
|
+
extend Soaspec::SoapGlobals
|
25
28
|
|
26
29
|
delegate [:operations] => :client
|
27
30
|
|
@@ -29,6 +32,17 @@ module Soaspec
|
|
29
32
|
attr_accessor :client
|
30
33
|
# SOAP Operation to use by default
|
31
34
|
attr_accessor :operation
|
35
|
+
# @return [Hash] List of Savon globals
|
36
|
+
attr_writer :savon_globals
|
37
|
+
|
38
|
+
def savon_globals
|
39
|
+
@savon_globals = {}
|
40
|
+
%i[wsdl basic_auth soap_version raise_errors namespace namespaces endpoint
|
41
|
+
ssl_verify_mode].each do |global|
|
42
|
+
@savon_globals.merge!(global => send(global)) if respond_to? global
|
43
|
+
end
|
44
|
+
@savon_globals
|
45
|
+
end
|
32
46
|
|
33
47
|
# Attributes set at the root XML element of SOAP request
|
34
48
|
def request_root_attributes; end
|
@@ -43,23 +57,6 @@ module Soaspec
|
|
43
57
|
}
|
44
58
|
end
|
45
59
|
|
46
|
-
# Default Savon options. See http://savonrb.com/version2/globals.html for details
|
47
|
-
# @example Things could go wrong if not set properly
|
48
|
-
# env_namespace: :soap, # Change environment namespace
|
49
|
-
# namespace_identifier: :tst, # Change namespace element
|
50
|
-
# element_form_default: :qualified # Populate each element with namespace
|
51
|
-
# namespace: 'http://Extended_namespace.xsd' change root namespace
|
52
|
-
# basic_auth: 'user', 'password'
|
53
|
-
# @return [Hash] Default Savon options for all BasicSoapHandler
|
54
|
-
def default_options
|
55
|
-
{
|
56
|
-
ssl_verify_mode: :none, # Easier for testing. Not so secure
|
57
|
-
follow_redirects: true, # Necessary for many API calls
|
58
|
-
soap_version: 2, # use SOAP 1.2. You will get 415 error if this is incorrect
|
59
|
-
raise_errors: false # HTTP errors not cause failure as often negative test scenarios expect not 200 response
|
60
|
-
}
|
61
|
-
end
|
62
|
-
|
63
60
|
# Add values to here when extending this class to have default Savon options.
|
64
61
|
# See http://savonrb.com/version2/globals.html for details
|
65
62
|
# @return [Hash] Savon options adding to & overriding defaults
|
@@ -77,14 +74,17 @@ module Soaspec
|
|
77
74
|
end
|
78
75
|
super
|
79
76
|
set_remove_keys(options, %i[operation default_hash template_name])
|
80
|
-
merged_options =
|
77
|
+
merged_options = SoapDefaults.options
|
78
|
+
merged_options.merge!(logging_options) if Soaspec::SpecLogger.log_api_traffic?
|
81
79
|
merged_options.merge! savon_options
|
80
|
+
puts 'globals' + savon_globals.to_s
|
81
|
+
merged_options.merge! savon_globals
|
82
82
|
merged_options.merge!(options)
|
83
83
|
self.client = Savon.client(merged_options)
|
84
84
|
end
|
85
85
|
|
86
86
|
# @param [Hash] override_parameters Parameters for building the request
|
87
|
-
# @return [
|
87
|
+
# @return [SoapRequest] Parameters used in making a request
|
88
88
|
def request_parameters(override_parameters)
|
89
89
|
SoapRequest.new(operation, request_body_params(override_parameters), @request_option)
|
90
90
|
end
|
@@ -97,7 +97,7 @@ module Soaspec
|
|
97
97
|
test_values.transform_keys_to_symbols if Soaspec.always_use_keys?
|
98
98
|
if @request_option == :template
|
99
99
|
test_values = IndifferentHash.new(test_values) # Allow test_values to be either Symbol or String
|
100
|
-
{ xml: Soaspec::TemplateReader.new.render_body(template_name,
|
100
|
+
{ xml: Soaspec::TemplateReader.new.render_body(template_name, test_values) }
|
101
101
|
elsif @request_option == :hash
|
102
102
|
{ message: @default_hash.merge(test_values), attributes: request_root_attributes }
|
103
103
|
end
|
@@ -111,7 +111,7 @@ module Soaspec
|
|
111
111
|
begin
|
112
112
|
client.call request.operation, request.body # request_body_params(request_parameters)
|
113
113
|
rescue Savon::HTTPError => e
|
114
|
-
|
114
|
+
e
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
@@ -213,14 +213,19 @@ module Soaspec
|
|
213
213
|
|
214
214
|
# Convenience methods for once off usage of a SOAP request
|
215
215
|
class << self
|
216
|
+
# @return [Array] List of operations WSDL can perform
|
217
|
+
def operations
|
218
|
+
operation_class = new('Get operations')
|
219
|
+
operation_class.operations
|
220
|
+
end
|
221
|
+
|
216
222
|
# Implement undefined setter with []= for FactoryBot to use without needing to define params to set
|
217
223
|
# @param [Object] method_name Name of method not defined
|
218
224
|
# @param [Object] args Arguments passed to method
|
219
225
|
# @param [Object] block
|
220
226
|
def method_missing(method_name, *args, &block)
|
221
|
-
tmp_class = new(method_name)
|
222
|
-
operations = tmp_class.operations
|
223
227
|
if operations.include? method_name
|
228
|
+
tmp_class = new(method_name)
|
224
229
|
tmp_class.operation = method_name
|
225
230
|
exchange = Exchange.new(method_name, *args)
|
226
231
|
exchange.exchange_handler = tmp_class
|
@@ -231,9 +236,9 @@ module Soaspec
|
|
231
236
|
end
|
232
237
|
end
|
233
238
|
|
239
|
+
# Override respond_to_missing so that any method name that is an operation
|
240
|
+
# can be used
|
234
241
|
def respond_to_missing?(method_name, *args)
|
235
|
-
tmp_class = new(args)
|
236
|
-
operations = tmp_class.operations
|
237
242
|
operations.include?(method_name) || super
|
238
243
|
end
|
239
244
|
end
|
data/lib/soaspec/interpreter.rb
CHANGED
@@ -15,7 +15,8 @@ class Interpreter
|
|
15
15
|
@xml_errors = nil
|
16
16
|
@json_errors = nil
|
17
17
|
@response = response
|
18
|
-
|
18
|
+
case @response
|
19
|
+
when String
|
19
20
|
if xml?
|
20
21
|
:xml
|
21
22
|
elsif json?
|
@@ -25,10 +26,8 @@ class Interpreter
|
|
25
26
|
else
|
26
27
|
:string
|
27
28
|
end
|
28
|
-
|
29
|
-
|
30
|
-
elsif response.is_a?(Nokogiri::XML::NodeSet) || response.is_a?(Nokogiri::XML::Document)
|
31
|
-
:xml
|
29
|
+
when Hash then :hash
|
30
|
+
when Nokogiri::XML::NodeSet, Nokogiri::XML::Document, Savon::Response then :xml
|
32
31
|
else
|
33
32
|
:unknown
|
34
33
|
end
|
data/lib/soaspec/matchers.rb
CHANGED
@@ -25,19 +25,20 @@ RSpec::Matchers.define :include_in_body do |expected|
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
# Whether an element exists at expected
|
29
|
-
RSpec::Matchers.define :have_element_at_path do |
|
28
|
+
# Whether an element exists at expected path
|
29
|
+
RSpec::Matchers.define :have_element_at_path do |path|
|
30
30
|
match do |object|
|
31
31
|
# Object like `response` returns the Exchange object from which a path can be obtained
|
32
32
|
exchange = object.respond_to?(:exchange) ? object.exchange : object
|
33
|
-
|
33
|
+
exchange.element? path # [xpath]
|
34
|
+
# expect { exchange[xpath] }.to_not raise_error # Error will be raised if Path returns no value
|
34
35
|
end
|
35
36
|
|
36
37
|
# TODO: Would be better to print failure message
|
37
38
|
failure_message do |object|
|
38
39
|
# Object like `response` returns the Exchange object from which a path can be obtained
|
39
40
|
exchange = object.respond_to?(:exchange) ? object.exchange : object
|
40
|
-
"expected that #{exchange.exchange_handler.response_body(exchange.response, format: :raw)} would have element at path '#{
|
41
|
+
"expected that #{exchange.exchange_handler.response_body(exchange.response, format: :raw)} would have element at path '#{path}'"
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
@@ -76,7 +77,6 @@ end
|
|
76
77
|
# @param [Symbol] format Format to save the baseline as. Default is :raw. Use :hash
|
77
78
|
# to store as hash which will ignore order in comparison
|
78
79
|
RSpec::Matchers.define :match_baseline do |format = :raw|
|
79
|
-
|
80
80
|
match do |exchange|
|
81
81
|
Soaspec::Baseline.new(exchange, format).matches?
|
82
82
|
end
|
data/lib/soaspec/o_auth2.rb
CHANGED
@@ -132,11 +132,21 @@ module Soaspec
|
|
132
132
|
payload.merge(if params[:password] && params[:username]
|
133
133
|
{
|
134
134
|
grant_type: 'password', username: params[:username],
|
135
|
-
password: password
|
136
|
-
}
|
135
|
+
password: password
|
136
|
+
}.merge multipart true
|
137
137
|
else
|
138
|
-
{ grant_type: 'client_credentials' }
|
138
|
+
{ grant_type: 'client_credentials' }.merge multipart false
|
139
139
|
end)
|
140
140
|
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# @param [Boolean] default Default value for multipart
|
145
|
+
# @return [Hash] Multipart set to true if not set and is grant_type password
|
146
|
+
def multipart(default)
|
147
|
+
return { multipart: true } if (params[:multipart].nil? && default) || params[:multipart]
|
148
|
+
|
149
|
+
{}
|
150
|
+
end
|
141
151
|
end
|
142
152
|
end
|
@@ -15,7 +15,11 @@ module Soaspec
|
|
15
15
|
|
16
16
|
# @param [String] template_name File where template is stored
|
17
17
|
# @return [String] Body of template after determining test_values
|
18
|
-
def render_body(template_name,
|
18
|
+
def render_body(template_name, test_values)
|
19
|
+
test_values = IndifferentHash.new(test_values) # Allow test_values to be either Symbol or String
|
20
|
+
test_values&.each do |key, value|
|
21
|
+
instance_variable_set("@#{key}", value)
|
22
|
+
end
|
19
23
|
self.template_name = template_name
|
20
24
|
unless File.exist? file_location
|
21
25
|
raise "Cannot see file at #{file_location}. "\
|
data/lib/soaspec/version.rb
CHANGED
@@ -102,6 +102,11 @@ module Soaspec
|
|
102
102
|
Soaspec::TestServer::IdManager.developed.to_s
|
103
103
|
end
|
104
104
|
|
105
|
+
documentation 'Sends back params received'
|
106
|
+
get '/echoer' do
|
107
|
+
params.to_s
|
108
|
+
end
|
109
|
+
|
105
110
|
# Used for simple testing of posing
|
106
111
|
documentation 'Simply sends the response body back'
|
107
112
|
post '/echoer' do
|
@@ -192,14 +197,14 @@ module Soaspec
|
|
192
197
|
|
193
198
|
documentation 'HTML doc that is not valid HTML'
|
194
199
|
get '/html_doc' do
|
195
|
-
|
196
|
-
<!doctype html>
|
197
|
-
<html lang="en">
|
198
|
-
<head></head>
|
199
|
-
<body>
|
200
|
-
<h1>Heading</h1>
|
201
|
-
</body>
|
202
|
-
</html>
|
200
|
+
<<~HTML
|
201
|
+
<!doctype html>
|
202
|
+
<html lang="en">
|
203
|
+
<head></head>
|
204
|
+
<body>
|
205
|
+
<h1>Heading</h1>
|
206
|
+
</body>
|
207
|
+
</html>
|
203
208
|
HTML
|
204
209
|
end
|
205
210
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soaspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SamuelGarrattIQA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -459,6 +459,7 @@ files:
|
|
459
459
|
- ".gitlab-ci.yml"
|
460
460
|
- ".rspec"
|
461
461
|
- ".rubocop.yml"
|
462
|
+
- ".yardopts"
|
462
463
|
- CODE_OF_CONDUCT.md
|
463
464
|
- ChangeLog
|
464
465
|
- Dockerfile
|
@@ -492,6 +493,8 @@ files:
|
|
492
493
|
- lib/soaspec/exchange_handlers/rest_methods.rb
|
493
494
|
- lib/soaspec/exchange_handlers/rest_parameters.rb
|
494
495
|
- lib/soaspec/exchange_handlers/rest_parameters_defaults.rb
|
496
|
+
- lib/soaspec/exchange_handlers/soap_defaults.rb
|
497
|
+
- lib/soaspec/exchange_handlers/soap_globals.rb
|
495
498
|
- lib/soaspec/exchange_handlers/soap_handler.rb
|
496
499
|
- lib/soaspec/exe_helpers.rb
|
497
500
|
- lib/soaspec/generate_server.rb
|
@@ -558,7 +561,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
558
561
|
- !ruby/object:Gem::Version
|
559
562
|
version: '0'
|
560
563
|
requirements: []
|
561
|
-
rubygems_version: 3.0.
|
564
|
+
rubygems_version: 3.0.6
|
562
565
|
signing_key:
|
563
566
|
specification_version: 4
|
564
567
|
summary: Helps to create tests for 'SOAP' or 'REST' apis
|