soaspec 0.0.30 → 0.0.31
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +5 -0
- data/Gemfile.lock +1 -1
- data/lib/soaspec.rb +5 -3
- data/lib/soaspec/exchange.rb +1 -1
- data/lib/soaspec/{exchange_handler.rb → exchange_handlers/exchange_handler.rb} +2 -2
- data/lib/soaspec/{rest_handler.rb → exchange_handlers/rest_handler.rb} +48 -33
- data/lib/soaspec/{basic_soap_handler.rb → exchange_handlers/soap_handler.rb} +38 -15
- data/lib/soaspec/interpreter.rb +26 -0
- data/lib/soaspec/matchers.rb +7 -9
- data/lib/soaspec/not_found_errors.rb +14 -0
- data/lib/soaspec/soaspec_shared_examples.rb +1 -1
- data/lib/soaspec/version.rb +1 -1
- metadata +7 -6
- data/lib/soaspec/xpath_not_found.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e08d39845eefbfb87ab3a5b7b8e6ae80fa321d54
|
4
|
+
data.tar.gz: 7903a5ab815ef9d56c9b6223b1d945181c57317e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccf078e392801d2ff1686836701c4ded6afbb2166591ad543c6ba6fa7b54fa0946f637e5bfdb3401b0e90deb105751e01edc2040379295dc280bf64acded3528
|
7
|
+
data.tar.gz: 2d8c97db2287c39369b0e6258202a3b446aa4c4e4375fd35af46402daf2bab6d5f260d93934d31852d089073549f5b94b7168ae6b85b99477387055388352b12
|
data/ChangeLog
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
Version 0.0.31 / 2018-3-8
|
2
|
+
* Enhancements
|
3
|
+
* Compacted unit tests for exchange handler
|
4
|
+
* Implemented include_key? and find via xpath for REST handler. See specs
|
5
|
+
|
1
6
|
Version 0.0.30 / 2018-3-6
|
2
7
|
* Bug fix
|
3
8
|
* Made generated class file name in soaspec-generate snakecase (was CamelCase)
|
data/Gemfile.lock
CHANGED
data/lib/soaspec.rb
CHANGED
@@ -8,16 +8,18 @@ require 'nokogiri' # XPath
|
|
8
8
|
require 'date'
|
9
9
|
|
10
10
|
require 'soaspec/version'
|
11
|
-
require 'soaspec/
|
12
|
-
require 'soaspec/exchange_handler'
|
11
|
+
require 'soaspec/exchange_handlers/soap_handler'
|
12
|
+
require 'soaspec/exchange_handlers/exchange_handler'
|
13
13
|
require 'soaspec/exchange'
|
14
14
|
require 'soaspec/matchers'
|
15
15
|
require 'soaspec/soaspec_shared_examples'
|
16
16
|
require 'soaspec/hash_methods'
|
17
17
|
require 'soaspec/spec_logger'
|
18
18
|
require 'soaspec/exe_helpers'
|
19
|
-
require 'soaspec/rest_handler'
|
19
|
+
require 'soaspec/exchange_handlers/rest_handler'
|
20
20
|
require 'soaspec/accessors'
|
21
|
+
require 'soaspec/interpreter'
|
22
|
+
require 'soaspec/not_found_errors'
|
21
23
|
|
22
24
|
# Gem for handling SOAP and REST api tests
|
23
25
|
module Soaspec
|
data/lib/soaspec/exchange.rb
CHANGED
@@ -39,7 +39,7 @@ class Exchange
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# Extract value from path api class
|
42
|
-
# @param [
|
42
|
+
# @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
|
43
43
|
# @return [String] Value at path
|
44
44
|
def [](path)
|
45
45
|
@api_class.value_from_path(self, path)
|
@@ -9,7 +9,7 @@ module Soaspec
|
|
9
9
|
|
10
10
|
# Set instance variable name
|
11
11
|
# @param [String, Symbol] name Name used when describing API test
|
12
|
-
# @param [Hash] options Parameters defining
|
12
|
+
# @param [Hash] options Parameters defining handler. Used in descendants
|
13
13
|
def initialize(name, options)
|
14
14
|
@name = name
|
15
15
|
end
|
@@ -18,7 +18,7 @@ module Soaspec
|
|
18
18
|
# @return [String] Name set upon initialisation
|
19
19
|
def to_s
|
20
20
|
Soaspec::Environment.api_handler = self
|
21
|
-
@name
|
21
|
+
@name.to_s
|
22
22
|
end
|
23
23
|
|
24
24
|
# Set the request option type and the template name
|
@@ -1,8 +1,9 @@
|
|
1
1
|
|
2
2
|
require_relative 'exchange_handler'
|
3
|
-
require_relative 'hash_methods'
|
4
|
-
require_relative '
|
5
|
-
require_relative 'accessors'
|
3
|
+
require_relative '../hash_methods'
|
4
|
+
require_relative '../not_found_errors'
|
5
|
+
require_relative '../accessors'
|
6
|
+
require_relative '../interpreter'
|
6
7
|
require 'json'
|
7
8
|
require 'nori'
|
8
9
|
|
@@ -54,16 +55,10 @@ module Soaspec
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def name(name)
|
57
|
-
@test_values = {}
|
58
58
|
@test_name = name
|
59
59
|
self
|
60
60
|
end
|
61
61
|
|
62
|
-
def override(request_parameters)
|
63
|
-
@test_values = request_parameters
|
64
|
-
self
|
65
|
-
end
|
66
|
-
|
67
62
|
# Used in together with Exchange request that passes such override parameters
|
68
63
|
# @param [Hash] override_parameters Params to characterize REST request
|
69
64
|
def make_request(override_parameters)
|
@@ -103,25 +98,17 @@ module Soaspec
|
|
103
98
|
response.body.include? expected
|
104
99
|
end
|
105
100
|
|
101
|
+
# Whether the request found the desired value or not
|
106
102
|
def found?(response)
|
107
|
-
response
|
103
|
+
status_code_for(response) != 404
|
108
104
|
end
|
109
105
|
|
110
106
|
# Convert XML or JSON response into a Hash
|
111
107
|
# @param [String] response Response as a String (either in XML or JSON)
|
112
108
|
# @return [Hash]
|
113
109
|
def extract_hash(response)
|
114
|
-
raise "Empty Body. Can't assert on it" if response.body.empty?
|
115
|
-
|
116
|
-
when '<'
|
117
|
-
:xml
|
118
|
-
when '{'
|
119
|
-
:json
|
120
|
-
else
|
121
|
-
:unknown
|
122
|
-
end
|
123
|
-
|
124
|
-
case type
|
110
|
+
raise ArgumentError("Empty Body. Can't assert on it") if response.body.empty?
|
111
|
+
case Interpreter.response_type_for response
|
125
112
|
when :json
|
126
113
|
JSON.parse(response.body).transform_keys_to_symbols
|
127
114
|
when :xml
|
@@ -132,10 +119,17 @@ module Soaspec
|
|
132
119
|
end
|
133
120
|
end
|
134
121
|
|
122
|
+
# @return [Boolean] Whether response contains expected value
|
135
123
|
def include_value?(response, expected)
|
136
124
|
extract_hash(response).include_value? expected
|
137
125
|
end
|
138
126
|
|
127
|
+
# @return [Boolean] Whether response body contains expected key
|
128
|
+
def include_key?(response, expected)
|
129
|
+
extract_hash(response).include_key? expected
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [Integer] HTTP Status code for response
|
139
133
|
def status_code_for(response)
|
140
134
|
response.code
|
141
135
|
end
|
@@ -160,23 +154,44 @@ module Soaspec
|
|
160
154
|
end
|
161
155
|
|
162
156
|
# Returns the value at the provided xpath
|
163
|
-
|
157
|
+
# @param [Exchange] exchange
|
158
|
+
# @param [String] xpath
|
159
|
+
# @return [String] Value inside element found through Xpath
|
160
|
+
def xpath_value_for(exchange: nil, xpath: nil)
|
161
|
+
raise ArgumentError unless exchange && xpath
|
162
|
+
response = exchange.response
|
163
|
+
raise "Can't perform XPATH if response is not XML" unless Interpreter.response_type_for(response) == :xml
|
164
164
|
result =
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
raise NoElementAtXpath, "No value at Xpath '#{param[:xpath]}'" unless result
|
165
|
+
if Soaspec::Environment.strip_namespaces? && !xpath.include?(':')
|
166
|
+
temp_doc = Nokogiri.parse response.body
|
167
|
+
temp_doc.remove_namespaces!
|
168
|
+
temp_doc.xpath(xpath).first
|
169
|
+
else
|
170
|
+
Nokogiri.parse(response.body).xpath(xpath).first
|
171
|
+
end
|
172
|
+
raise NoElementAtXpath, "No value at Xpath '#{xpath}'" unless result
|
174
173
|
result.inner_text
|
175
174
|
end
|
176
175
|
|
176
|
+
# Based on a exchange, return the value at the provided xpath
|
177
|
+
# If the path does not begin with a '/', a '//' is added to it
|
178
|
+
# @param [Exchange] exchange
|
179
|
+
# @param [Object] path Xpath or other path identifying how to find element
|
180
|
+
# @return [String] Value at Xpath
|
177
181
|
def value_from_path(exchange, path)
|
178
|
-
|
179
|
-
|
182
|
+
case Interpreter.response_type_for(exchange.response)
|
183
|
+
when :xml
|
184
|
+
path = '//' + path if path[0] != '/'
|
185
|
+
xpath_value_for(exchange: exchange, xpath: path)
|
186
|
+
when :json
|
187
|
+
hash = extract_hash exchange.response
|
188
|
+
value = hash.dig(*path)
|
189
|
+
raise NoElementInHash, "Element in #{hash} not found with path '#{path}'" unless value
|
190
|
+
value
|
191
|
+
else
|
192
|
+
raise 'Unrecognised response message. Neither xml nor json detected'
|
193
|
+
end
|
194
|
+
|
180
195
|
end
|
181
196
|
|
182
197
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
|
2
2
|
require_relative 'exchange_handler'
|
3
|
-
require_relative 'hash_methods'
|
4
|
-
require_relative '
|
5
|
-
require_relative 'accessors'
|
3
|
+
require_relative '../hash_methods'
|
4
|
+
require_relative '../not_found_errors'
|
5
|
+
require_relative '../accessors'
|
6
|
+
require_relative '../interpreter'
|
6
7
|
|
7
8
|
module Soaspec
|
8
9
|
|
@@ -73,20 +74,16 @@ module Soaspec
|
|
73
74
|
options.merge! savon_options
|
74
75
|
options.merge!(specific_options)
|
75
76
|
@client = Savon.client(options)
|
77
|
+
@default_hash = {}
|
78
|
+
@request_option = :hash
|
76
79
|
super
|
77
80
|
end
|
78
81
|
|
79
82
|
def name(name)
|
80
|
-
@test_values = {}
|
81
83
|
@test_name = name
|
82
84
|
self
|
83
85
|
end
|
84
86
|
|
85
|
-
def override(request_parameters)
|
86
|
-
@test_values = request_parameters
|
87
|
-
self
|
88
|
-
end
|
89
|
-
|
90
87
|
# Used in together with Exchange request that passes such override parameters
|
91
88
|
def make_request(override_parameters)
|
92
89
|
test_values = override_parameters # Used in Erb
|
@@ -101,6 +98,8 @@ module Soaspec
|
|
101
98
|
end
|
102
99
|
end
|
103
100
|
|
101
|
+
# Set the default hash representing data to be used in making a request
|
102
|
+
# This will set the @request_option instance variable too
|
104
103
|
def default_hash=(hash)
|
105
104
|
@request_option = :hash
|
106
105
|
@default_hash = Soaspec::Environment.always_use_keys? ? hash.transform_keys_to_symbols : hash
|
@@ -119,28 +118,51 @@ module Soaspec
|
|
119
118
|
end
|
120
119
|
end
|
121
120
|
|
121
|
+
# @return [Boolean] Whether the request found the desired value or not
|
122
|
+
def found?(response)
|
123
|
+
status_code_for(response) != 404
|
124
|
+
end
|
125
|
+
|
126
|
+
# Response status code for response. '200' indicates a success
|
127
|
+
# @param [Savon::Response] response
|
128
|
+
# @return [Integer] Status code
|
122
129
|
def status_code_for(response)
|
123
130
|
response.http.code
|
124
131
|
end
|
125
132
|
|
133
|
+
# @return [Boolean] Whether response includes provided string within it
|
126
134
|
def include_in_body?(response, expected)
|
127
135
|
response.to_xml.to_s.include? expected
|
128
136
|
end
|
129
137
|
|
138
|
+
# @return [Boolean] Whether response body contains expected key
|
139
|
+
def include_key?(response, expected)
|
140
|
+
response.body.include_key? expected
|
141
|
+
end
|
142
|
+
|
130
143
|
# Returns the value at the provided xpath
|
131
|
-
|
144
|
+
# @param [Exchange] exchange
|
145
|
+
# @param [String] xpath
|
146
|
+
# @return [String] Value inside element found through Xpath
|
147
|
+
def xpath_value_for(exchange: nil, xpath: nil)
|
148
|
+
raise ArgumentError unless exchange && xpath
|
132
149
|
result =
|
133
|
-
if Soaspec::Environment.strip_namespaces? && !
|
134
|
-
temp_doc =
|
150
|
+
if Soaspec::Environment.strip_namespaces? && !xpath.include?(':')
|
151
|
+
temp_doc = exchange.response.doc
|
135
152
|
temp_doc.remove_namespaces!
|
136
|
-
temp_doc.xpath(
|
153
|
+
temp_doc.xpath(xpath).first
|
137
154
|
else
|
138
|
-
|
155
|
+
exchange.response.xpath(xpath).first
|
139
156
|
end
|
140
|
-
raise NoElementAtXpath, "No value at Xpath '#{
|
157
|
+
raise NoElementAtXpath, "No value at Xpath '#{xpath}'" unless result
|
141
158
|
result.inner_text
|
142
159
|
end
|
143
160
|
|
161
|
+
# Based on a exchange, return the value at the provided xpath
|
162
|
+
# If the path does not begin with a '/', a '//' is added to it
|
163
|
+
# @param [Exchange] exchange
|
164
|
+
# @param [String] path Xpath
|
165
|
+
# @return [String] Value at Xpath
|
144
166
|
def value_from_path(exchange, path)
|
145
167
|
path = '//' + path if path[0] != '/'
|
146
168
|
xpath_value_for(exchange: exchange, xpath: path)
|
@@ -153,6 +175,7 @@ module Soaspec
|
|
153
175
|
|
154
176
|
end
|
155
177
|
|
178
|
+
# Deprecated class name. Will be removed in the future
|
156
179
|
class BasicSoapHandler < SoapHandler
|
157
180
|
|
158
181
|
def initialize(name, specific_options = {})
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
# Help interpret the general type of a particular object
|
3
|
+
class Interpreter
|
4
|
+
|
5
|
+
# @param [Object] response API response
|
6
|
+
# @return [Symbol] Type of provided response
|
7
|
+
def self.response_type_for(response)
|
8
|
+
if response.is_a? String
|
9
|
+
case response.body[0]
|
10
|
+
when '<'
|
11
|
+
:xml
|
12
|
+
when '{'
|
13
|
+
:json
|
14
|
+
else
|
15
|
+
:unknown
|
16
|
+
end
|
17
|
+
elsif response.is_a? Hash
|
18
|
+
:hash
|
19
|
+
elsif response.is_a? Nokogiri::XML::NodeSet
|
20
|
+
:xml
|
21
|
+
else
|
22
|
+
:unknown
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/lib/soaspec/matchers.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
require_relative 'hash_methods'
|
3
|
-
require_relative '
|
3
|
+
require_relative 'not_found_errors'
|
4
4
|
|
5
5
|
# TODO: Mathcers are specific to SOAP. Make generic for REST and others by using actual.api_class
|
6
6
|
|
@@ -10,9 +10,8 @@ RSpec::Matchers.define :contain_value do |expected|
|
|
10
10
|
expect(actual.api_class.include_value?(actual.response, expected)).to be true
|
11
11
|
end
|
12
12
|
|
13
|
-
# TODO: Fix this for REST
|
14
13
|
failure_message do |actual|
|
15
|
-
"expected that #{actual.response
|
14
|
+
"expected that #{actual.api_class.response_body(actual.response, format: :hash)} would contain value #{expected}"
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
@@ -22,31 +21,30 @@ RSpec::Matchers.define :include_in_body do |expected|
|
|
22
21
|
expect(actual.api_class.include_in_body?(actual.response, expected)).to be true
|
23
22
|
end
|
24
23
|
|
25
|
-
# TODO: Fix this for REST
|
26
24
|
failure_message do |actual|
|
27
|
-
"expected that #{actual.
|
25
|
+
"expected that #{actual.api_class.response_body(actual.response, format: :xml)} would contain value #{expected}"
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
31
29
|
# Whether expected element exists in body
|
32
30
|
RSpec::Matchers.define :contain_key do |expected|
|
33
31
|
match do |actual|
|
34
|
-
expect(actual.
|
32
|
+
expect(actual.api_class.include_key?(actual.response, expected)).to be true
|
35
33
|
end
|
36
34
|
|
37
35
|
failure_message do |actual|
|
38
|
-
"expected that #{actual.response
|
36
|
+
"expected that #{actual.api_class.response_body(actual.response, format: :hash)} would contain key #{expected}"
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
42
40
|
# Whether an element exists at expected xpath
|
43
41
|
RSpec::Matchers.define :have_element_at_xpath do |xpath|
|
44
42
|
match do |exchange|
|
45
|
-
expect { exchange[xpath] }.to_not raise_error
|
43
|
+
expect { exchange[xpath] }.to_not raise_error # Error will be raised if XPath returns no value
|
46
44
|
end
|
47
45
|
|
48
46
|
failure_message do |actual|
|
49
|
-
"expected that #{actual.response
|
47
|
+
"expected that #{actual.api_class.response_body(actual.response, format: :xml)} would have element at xpath '#{xpath}'"
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
# Raised to represent when there's no element at an Xpath
|
3
|
+
class NoElementAtXpath < StandardError
|
4
|
+
def initialize(msg="No element at Xpath found")
|
5
|
+
super
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Did not find any element by provided key in the Hash
|
10
|
+
class NoElementInHash < StandardError
|
11
|
+
def initialize(msg='No element in Hash found')
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
@@ -10,7 +10,7 @@ shared_examples_for 'success scenario' do
|
|
10
10
|
expect(described_class).to contain_key mandatory_element
|
11
11
|
end
|
12
12
|
end
|
13
|
-
# TODO: Remove this. Handle
|
13
|
+
# TODO: Remove this. Handle deprecated method temporarily
|
14
14
|
described_class.api_class.mandatory_elements.each do |mandatory_element|
|
15
15
|
puts "Overriding 'mandatory_elements' deprecated. Use new 'expected_mandatory_elements' instead of overriding this method"
|
16
16
|
it mandatory_element do
|
data/lib/soaspec/version.rb
CHANGED
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.0.
|
4
|
+
version: 0.0.31
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SamuelGarrattIQA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -152,17 +152,18 @@ files:
|
|
152
152
|
- exe/xml_to_yaml_file
|
153
153
|
- lib/soaspec.rb
|
154
154
|
- lib/soaspec/accessors.rb
|
155
|
-
- lib/soaspec/basic_soap_handler.rb
|
156
155
|
- lib/soaspec/exchange.rb
|
157
|
-
- lib/soaspec/exchange_handler.rb
|
156
|
+
- lib/soaspec/exchange_handlers/exchange_handler.rb
|
157
|
+
- lib/soaspec/exchange_handlers/rest_handler.rb
|
158
|
+
- lib/soaspec/exchange_handlers/soap_handler.rb
|
158
159
|
- lib/soaspec/exe_helpers.rb
|
159
160
|
- lib/soaspec/hash_methods.rb
|
161
|
+
- lib/soaspec/interpreter.rb
|
160
162
|
- lib/soaspec/matchers.rb
|
161
|
-
- lib/soaspec/
|
163
|
+
- lib/soaspec/not_found_errors.rb
|
162
164
|
- lib/soaspec/soaspec_shared_examples.rb
|
163
165
|
- lib/soaspec/spec_logger.rb
|
164
166
|
- lib/soaspec/version.rb
|
165
|
-
- lib/soaspec/xpath_not_found.rb
|
166
167
|
- soaspec.gemspec
|
167
168
|
- template/soap_template.xml
|
168
169
|
- test.wsdl
|