soaspec 0.0.30 → 0.0.31

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb181def6480766a52b057843a32f43f12aa1156
4
- data.tar.gz: '0187e411bdbfb2d722063222d2c5e32001979cb6'
3
+ metadata.gz: e08d39845eefbfb87ab3a5b7b8e6ae80fa321d54
4
+ data.tar.gz: 7903a5ab815ef9d56c9b6223b1d945181c57317e
5
5
  SHA512:
6
- metadata.gz: 8760fa3a0f1f639fa86c1c328b7d8afcb1acdd62a28ac87d8c1c4aab98018fdff1a5153ecbb63397339ca163a86275e6f2c8fecf519449aa3e08e0a5fd08f666
7
- data.tar.gz: 63d3ce6daf896b56b3b2585430fba47879c529fb5fde312d44e3fdb948307f2a7d657c29995dfd07c02c9b04cbc945b24d380c7289bdcb15a3f2a7c9fb6a9e20
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- soaspec (0.0.30)
4
+ soaspec (0.0.31)
5
5
  rest-client (>= 2.0)
6
6
  rspec (~> 3.0)
7
7
  rspec-its (>= 1.2.0)
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/basic_soap_handler'
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
@@ -39,7 +39,7 @@ class Exchange
39
39
  end
40
40
 
41
41
  # Extract value from path api class
42
- # @param [String] path Path to return element for api class E.g - for SOAP this is XPath
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 'xpath_not_found'
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.code != 404
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
- type = case response.body[0]
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
- def xpath_value_for(param)
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
- if Soaspec::Environment.strip_namespaces? && !param[:xpath].include?(':')
166
- temp_doc = param[:exchange].response.doc
167
- temp_doc.remove_namespaces!
168
- temp_doc.xpath(param[:xpath]).first
169
- else
170
- puts 'no strip' + param[:xpath]
171
- param[:exchange].response.xpath(param[:xpath]).first
172
- end
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
- path = '//' + path if path[0] != '/'
179
- xpath_value_for(exchange: exchange, xpath: path)
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 'xpath_not_found'
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
- def xpath_value_for(param)
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? && !param[:xpath].include?(':')
134
- temp_doc = param[:exchange].response.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(param[:xpath]).first
153
+ temp_doc.xpath(xpath).first
137
154
  else
138
- param[:exchange].response.xpath(param[:xpath]).first
155
+ exchange.response.xpath(xpath).first
139
156
  end
140
- raise NoElementAtXpath, "No value at Xpath '#{param[:xpath]}'" unless result
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
@@ -1,6 +1,6 @@
1
1
 
2
2
  require_relative 'hash_methods'
3
- require_relative 'xpath_not_found'
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.body} would contain value #{expected}"
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.response.body.to_xml} would contain value #{expected}"
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.response.body.include_key?(expected)).to be true
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.body} would contain key #{expected}"
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.to_xml} would have element at xpath '#{xpath}'"
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 depracated method temporariliy
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
@@ -1,3 +1,3 @@
1
1
  module Soaspec
2
- VERSION = '0.0.30'
2
+ VERSION = '0.0.31'
3
3
  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.0.30
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-06 00:00:00.000000000 Z
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/rest_handler.rb
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
@@ -1,7 +0,0 @@
1
-
2
- # Raised to represent when there's no element at an Xpath
3
- class NoElementAtXpath < StandardError
4
- def initialize(msg="No element Xpath not found")
5
- super
6
- end
7
- end