soaspec 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|