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