soaspec 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +13 -13
- data/.rspec +3 -3
- data/.travis.yml +5 -5
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +13 -13
- data/Gemfile.lock +97 -87
- data/LICENSE.txt +21 -21
- data/README.md +51 -42
- data/Rakefile +20 -17
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/exe/soaspec-init +142 -142
- data/lib/soaspec.rb +36 -35
- data/lib/soaspec/basic_soap_handler.rb +104 -84
- data/lib/soaspec/common.rb +24 -24
- data/lib/soaspec/exchange.rb +46 -39
- data/lib/soaspec/hash_methods.rb +29 -0
- data/lib/soaspec/matchers.rb +23 -16
- data/lib/soaspec/shared_examples.rb +6 -6
- data/lib/soaspec/tester.rb +31 -31
- data/lib/soaspec/version.rb +3 -3
- data/soaspec.gemspec +32 -32
- data/template/soap_template.xml +9 -9
- metadata +3 -2
data/lib/soaspec.rb
CHANGED
@@ -1,35 +1,36 @@
|
|
1
|
-
require 'rest-client' # REST
|
2
|
-
require 'erb' # Embedded ruby
|
3
|
-
require 'yaml' # Reading yaml
|
4
|
-
require 'rspec' # Testing framework
|
5
|
-
require 'savon' # SOAP
|
6
|
-
require 'nokogiri' # XPath
|
7
|
-
require 'date'
|
8
|
-
|
9
|
-
require 'soaspec/version'
|
10
|
-
require 'soaspec/common'
|
11
|
-
require 'soaspec/basic_soap_handler'
|
12
|
-
require 'soaspec/tester'
|
13
|
-
require 'soaspec/exchange'
|
14
|
-
require 'soaspec/matchers'
|
15
|
-
require 'soaspec/shared_examples'
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
1
|
+
require 'rest-client' # REST
|
2
|
+
require 'erb' # Embedded ruby
|
3
|
+
require 'yaml' # Reading yaml
|
4
|
+
require 'rspec' # Testing framework
|
5
|
+
require 'savon' # SOAP
|
6
|
+
require 'nokogiri' # XPath
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
require 'soaspec/version'
|
10
|
+
require 'soaspec/common'
|
11
|
+
require 'soaspec/basic_soap_handler'
|
12
|
+
require 'soaspec/tester'
|
13
|
+
require 'soaspec/exchange'
|
14
|
+
require 'soaspec/matchers'
|
15
|
+
require 'soaspec/shared_examples'
|
16
|
+
require 'soaspec/hash_methods'
|
17
|
+
|
18
|
+
# Gem for handling SOAP and REST api tests
|
19
|
+
module Soaspec
|
20
|
+
|
21
|
+
def self.hi
|
22
|
+
puts 'Hello world!'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Represents Environment parameters used in Soaspec tests
|
26
|
+
module Environment
|
27
|
+
|
28
|
+
def self.api_handler=(handler)
|
29
|
+
@api_handler = handler
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.api_handler
|
33
|
+
@api_handler
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,85 +1,105 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require_relative 'common'
|
3
|
-
require_relative 'tester'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@request_option
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
1
|
+
require 'yaml'
|
2
|
+
require_relative 'common'
|
3
|
+
require_relative 'tester'
|
4
|
+
require_relative 'hash_methods'
|
5
|
+
|
6
|
+
module Soaspec
|
7
|
+
# Wraps around Savon client defining default values dependent on the soap request
|
8
|
+
class BasicSoapHandler < Tester
|
9
|
+
# Savon client used to make SOAP calls
|
10
|
+
attr_accessor :client
|
11
|
+
# Namespaces used in XML body
|
12
|
+
attr_accessor :namespaces
|
13
|
+
# SOAP Operation to use by default
|
14
|
+
attr_accessor :default_operation
|
15
|
+
|
16
|
+
# Options to log xml request and response
|
17
|
+
def logging_options
|
18
|
+
{
|
19
|
+
log: true, # See request and response. (Put this in traffic file)
|
20
|
+
log_level: :debug,
|
21
|
+
logger: file_logger,
|
22
|
+
pretty_print_xml: true # Prints XML pretty
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
# Default Savon options
|
27
|
+
def default_options
|
28
|
+
{
|
29
|
+
ssl_verify_mode: :none,
|
30
|
+
follow_redirects: true, # Necessary for many API calls
|
31
|
+
soap_version: 2, # use SOAP 1.2. You will get 415 error if this set to default
|
32
|
+
raise_errors: false
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add values to here when extending this class
|
37
|
+
def class_options
|
38
|
+
{
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
# Setup object to handle communicating with a particular SOAP WSDL
|
43
|
+
# @param [Hash] specific_options Options defining SOAP request. WSDL, authentication, see http://savonrb.com/version2/globals.html for list of options
|
44
|
+
def initialize(name, specific_options = {})
|
45
|
+
super
|
46
|
+
options = default_options.merge logging_options
|
47
|
+
options.merge! class_options
|
48
|
+
options.merge!(specific_options)
|
49
|
+
@client = Savon.client(options)
|
50
|
+
self.namespaces = {}
|
51
|
+
@name = name
|
52
|
+
end
|
53
|
+
|
54
|
+
# Sends a call to the API (is being made obsolete)
|
55
|
+
# @param [Hash] options Dictionary of key value pairs specifying what API call to make
|
56
|
+
# @return [SavonResponse] Savon response from which areas (header, body, etc) of the SOAP response can be accessed
|
57
|
+
# def call(options)
|
58
|
+
# test_values = options[:overide_values]['request'] || {} # Empty hash if no specific request values are set
|
59
|
+
# options[:operation] ||= self.default_operation
|
60
|
+
# # Erb parses template file, executing Ruby code in `<% %>` blocks to work out final request
|
61
|
+
# render_body = ERB.new(options[:template]).result(binding)
|
62
|
+
# @client.call(options[:operation], xml: render_body ) # Call the SOAP operation with the request XML provided
|
63
|
+
# end
|
64
|
+
|
65
|
+
def name(name)
|
66
|
+
@test_values = {}
|
67
|
+
@test_name = name
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def override(request_parameters)
|
72
|
+
@test_values = request_parameters
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
# Used in together with Exchange request that passes such override parameters
|
77
|
+
def make_request(override_parameters)
|
78
|
+
test_values = override_parameters # Used in Erb
|
79
|
+
# Erb parses template file, executing Ruby code in `<% %>` blocks to work out final request
|
80
|
+
if @request_option == :template
|
81
|
+
test_values = test_values.transform_keys_to_symbols # Either string or symbol
|
82
|
+
request_body = File.read('template/' + template_name + '.xml')
|
83
|
+
render_body = ERB.new(request_body).result(binding)
|
84
|
+
@client.call(default_operation, xml: render_body ) # Call the SOAP operation with the request XML provided
|
85
|
+
elsif @request_option == :hash
|
86
|
+
@client.call(default_operation, message: @default_hash.merge(test_values))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
Soaspec::Environment.api_handler = self
|
92
|
+
@name
|
93
|
+
end
|
94
|
+
|
95
|
+
def include?(value)
|
96
|
+
@xml_response.include? value
|
97
|
+
end
|
98
|
+
|
99
|
+
def default_hash=(hash)
|
100
|
+
@request_option = :hash
|
101
|
+
@default_hash = hash
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
85
105
|
end
|
data/lib/soaspec/common.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
class Hash
|
2
|
-
|
3
|
-
# Loop through each item within a key within a Hash if the key exists
|
4
|
-
# @param [Key] Key within hash to iterate through
|
5
|
-
def each_if_not_null(key)
|
6
|
-
case key.class.to_s
|
7
|
-
when 'String'
|
8
|
-
if self[key]
|
9
|
-
self[key].each do |list_item|
|
10
|
-
yield(list_item)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
when 'Array'
|
14
|
-
if self[key[0]]
|
15
|
-
if self[key[0]][key[1]]
|
16
|
-
self[key[0]][key[1]].each do |list_item|
|
17
|
-
yield(list_item)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Loop through each item within a key within a Hash if the key exists
|
4
|
+
# @param [Key] Key within hash to iterate through
|
5
|
+
def each_if_not_null(key)
|
6
|
+
case key.class.to_s
|
7
|
+
when 'String'
|
8
|
+
if self[key]
|
9
|
+
self[key].each do |list_item|
|
10
|
+
yield(list_item)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
when 'Array'
|
14
|
+
if self[key[0]]
|
15
|
+
if self[key[0]][key[1]]
|
16
|
+
self[key[0]][key[1]].each do |list_item|
|
17
|
+
yield(list_item)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/soaspec/exchange.rb
CHANGED
@@ -1,40 +1,47 @@
|
|
1
|
-
require_relative '../soaspec'
|
2
|
-
|
3
|
-
# This represents a request / response pair
|
4
|
-
class Exchange
|
5
|
-
|
6
|
-
attr_reader :xml_response
|
7
|
-
|
8
|
-
attr_reader :xml_doc
|
9
|
-
|
10
|
-
def initialize(name, override_parameters = {})
|
11
|
-
@test_name = name.to_s
|
12
|
-
@api_class = Soaspec::Environment.api_handler
|
13
|
-
@override_parameters = override_parameters
|
14
|
-
end
|
15
|
-
|
16
|
-
# Make request to handler with parameters defined
|
17
|
-
def make_request
|
18
|
-
@api_class.make_request(@override_parameters)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Name describing this class when used with `RSpec.describe`
|
22
|
-
# @return [String] Name given when initializing
|
23
|
-
def to_s
|
24
|
-
@response = self.make_request
|
25
|
-
if Soaspec::Environment.api_handler.class
|
26
|
-
@xml_response = @response.to_xml
|
27
|
-
@xml_doc =
|
28
|
-
end
|
29
|
-
@test_name
|
30
|
-
end
|
31
|
-
|
32
|
-
def contain(value)
|
33
|
-
@xml_response.include? value
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
1
|
+
require_relative '../soaspec'
|
2
|
+
|
3
|
+
# This represents a request / response pair
|
4
|
+
class Exchange
|
5
|
+
|
6
|
+
attr_reader :xml_response
|
7
|
+
|
8
|
+
attr_reader :xml_doc
|
9
|
+
|
10
|
+
def initialize(name, override_parameters = {})
|
11
|
+
@test_name = name.to_s
|
12
|
+
@api_class = Soaspec::Environment.api_handler
|
13
|
+
@override_parameters = override_parameters
|
14
|
+
end
|
15
|
+
|
16
|
+
# Make request to handler with parameters defined
|
17
|
+
def make_request
|
18
|
+
@api_class.make_request(@override_parameters)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Name describing this class when used with `RSpec.describe`
|
22
|
+
# @return [String] Name given when initializing
|
23
|
+
def to_s
|
24
|
+
@response = self.make_request
|
25
|
+
if Soaspec::Environment.api_handler.class < Soaspec::BasicSoapHandler
|
26
|
+
@xml_response = @response.to_xml
|
27
|
+
@xml_doc = @response.doc
|
28
|
+
end
|
29
|
+
@test_name
|
30
|
+
end
|
31
|
+
|
32
|
+
def contain(value)
|
33
|
+
@xml_response.include? value
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns Savon response
|
37
|
+
# response.body (body of response as Hash)
|
38
|
+
# response.header (head of response as Hash)
|
39
|
+
def response
|
40
|
+
@response
|
41
|
+
end
|
42
|
+
|
43
|
+
def status_code
|
44
|
+
@response.http.code
|
45
|
+
end
|
46
|
+
|
40
47
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
# Override Hash class with convience methods
|
3
|
+
class Hash
|
4
|
+
|
5
|
+
def self.transform_keys_to_symbols(value)
|
6
|
+
return value if not value.is_a?(Hash)
|
7
|
+
hash = value.inject({}){|memo,(k,v)| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); memo}
|
8
|
+
return hash
|
9
|
+
end
|
10
|
+
|
11
|
+
# Take keys of hash and transform those to a symbols
|
12
|
+
def transform_keys_to_symbols
|
13
|
+
inject({}){|memo, (k, v)| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); memo}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Value present in nested Hash
|
17
|
+
def include_value?(value)
|
18
|
+
self.each_value do |v|
|
19
|
+
return true if v == value
|
20
|
+
if v.is_a? Hash
|
21
|
+
v.each_value do |v|
|
22
|
+
return true if v == value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/soaspec/matchers.rb
CHANGED
@@ -1,17 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
|
2
|
+
require_relative 'hash_methods'
|
3
|
+
|
4
|
+
RSpec::Matchers.define :contain_value do |expected|
|
5
|
+
match do |actual|
|
6
|
+
expect(actual.response.body.include_value?(expected)).to be true
|
7
|
+
end
|
8
|
+
|
9
|
+
failure_message do |actual|
|
10
|
+
"expected that #{actual.response.body} would contain value #{expected}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec::Matchers.define :have_element_at_xpath do |expected|
|
15
|
+
match do |exchange|
|
16
|
+
expect(exchange.xml_doc.at_xpath(expected, Soaspec::Environment.api_handler.namespaces).content).not_to be_empty
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec::Matchers.define :have_xpath_value do |expected_hash|
|
21
|
+
match do |exchange|
|
22
|
+
expect(exchange.xml_doc.at_xpath(expected_hash.keys.first, Soaspec::Environment.api_handler.namespaces).content).to eq expected_hash.values.first
|
23
|
+
end
|
17
24
|
end
|