soaspec 0.2.21 → 0.2.22

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
  SHA256:
3
- metadata.gz: 2b1028921ecb551ea11797baf3cc3f857a63ffe605b17e14d2fdf96789fc8b12
4
- data.tar.gz: b09a3d92546409cccfc28b2ee29b8207547fab372028605594c1751ccf175044
3
+ metadata.gz: 2f3a41968e523901e869b24522b1fe2c630518239fed2e3600f2e8f5b67a9fb5
4
+ data.tar.gz: f9af632f2e025cccf4da721120ca44e5aed446d0b5b2353e860d347fbfd28594
5
5
  SHA512:
6
- metadata.gz: 2d546e2a961ad5dd77d92587193b6b1cb7bbbcdcd355a4d33f16f84a0f62318e9b45a51607b39fdf7e1ba71e77359bc77f93e224e846ef4212320390e22c7d37
7
- data.tar.gz: aa2d86da44ddcd01187979b43f8021c21bec56627a4796d056a29104da32a4bd992ab9c342aba22471a9b2d1ad90dc843101df5779949839190f0a002185aaaa
6
+ metadata.gz: a1eb7bf52e74e6c355bf5f078707a97998c90c6084caaae85e4647ad3750e1c5daa9f593f1dbb4aa4bc688a410fa1c3c04a13e06037949a53547d1c3b04305f4
7
+ data.tar.gz: 77f6623886cb834aac76e5bdc275bee97260ddec1d0277c7f57bdb042355d45b03e94902900526520d2ffd2b0e05a23c41980d6c5eae11eee8aadf3c0f4375b2
data/ChangeLog CHANGED
@@ -1,3 +1,11 @@
1
+ Version 0.2.22
2
+ * Bug Fix
3
+ * Allow negated version of 'be_successful' to work
4
+ * Fix `Exchange.retry_count` so that it retries after first try the correct number of times
5
+ * Enhancement
6
+ * Make 'value_from_path' and 'values_from_path' methods accessible from 'response' object
7
+ * Get extracting text via RegEx actually working
8
+
1
9
  Version 0.2.21
2
10
  * Enhancement
3
11
  * Enable deprecation warnings to be removed so that they're not annoying with `Soaspec.log_warnings`
@@ -66,12 +66,12 @@ class Exchange
66
66
  def make_request
67
67
  Soaspec::SpecLogger.info 'Example ' + test_name
68
68
  request_params = @override_parameters
69
- (1..retry_count).each do |count|
69
+ (0..retry_count).each do |count|
70
70
  response = exchange_handler.make_request(request_params)
71
71
  return response unless retry_for_success?
72
72
  return response if (200..299).cover? exchange_handler.status_code_for(response)
73
73
 
74
- sleep 0.5
74
+ sleep 0.5 # Time before retrying
75
75
  break response if count == retry_count
76
76
  end
77
77
  end
@@ -90,9 +90,12 @@ class Exchange
90
90
  # response.header (head of response as Hash)
91
91
  # @example For REST it will be a RestClient::Response
92
92
  def response
93
+ require 'forwardable'
93
94
  Soaspec.last_exchange = self
94
95
  @response ||= make_request
95
96
  @response.define_singleton_method(:exchange) { Soaspec.last_exchange } unless @response.respond_to?(:exchange)
97
+ @response.extend Forwardable
98
+ @response.delegate %i[value_from_path values_from_path] => :exchange
96
99
  @response
97
100
  end
98
101
 
@@ -100,7 +103,8 @@ class Exchange
100
103
  # allow easy method chaining
101
104
  def call
102
105
  if Soaspec.log_warnings
103
- warn 'This method will be changed to return "Exchange" object in 0.3. Use "response" method if you want the response object'
106
+ warn 'This "call" method will be changed to return "Exchange" object in 0.3. ' \
107
+ 'Use "response" method if you want the "response" object'
104
108
  end
105
109
  response
106
110
  end
@@ -27,6 +27,8 @@ module Soaspec
27
27
  exchange_handler.value_from_path(response, path.to_s)
28
28
  end
29
29
 
30
+ alias_method :value_from_path, :[]
31
+
30
32
  # Using same path syntax as []. Returns true of false depending on whether an element is found
31
33
  # @return [Boolean] Whether an element exists at the path
32
34
  def element?(path)
@@ -19,12 +19,8 @@ module Soaspec
19
19
  # Set retry_for_success to true, retrying response until a successful status code is returned
20
20
  # @param [Integer] retry_count Times to retry to get a positive response
21
21
  def expect_positive_status(retry_count: 3)
22
- define_method('retry_count') do
23
- retry_count
24
- end
25
- define_method('retry_for_success?') do
26
- true
27
- end
22
+ define_method('retry_count') { retry_count }
23
+ define_method('retry_for_success?') { true }
28
24
  end
29
25
  end
30
26
  end
@@ -6,6 +6,10 @@ module Soaspec
6
6
  class ExchangeHandler
7
7
  extend Soaspec::HandlerAccessors
8
8
 
9
+ def self.use
10
+ new.use
11
+ end
12
+
9
13
  # Retrieve the name of the template file to be used in the API request
10
14
  attr_reader :template_name
11
15
 
@@ -163,6 +163,24 @@ module Soaspec
163
163
  JsonPath.on(response.body, path)
164
164
  end
165
165
 
166
+ # Calculate all JSON path values based on rules. ',', pascal_case
167
+ # @param [RestClient::Response] response Response from API
168
+ # @param [Object] path Xpath, JSONPath or other path identifying how to find element
169
+ # @param [String] attribute Generic attribute to find. Will override path
170
+ # @param [Boolean] not_empty Whether to fail if result is empty
171
+ # @return [Array] Paths to check as first and matching values (List of values matching JSON Path) as second
172
+ def calculated_json_path_matches(path, response, attribute, not_empty: false)
173
+ path = add_pascal_path(path)
174
+ paths_to_check = path.split(',')
175
+ paths_to_check = paths_to_check.map { |path_to_check| prefix_json_path(path_to_check) }
176
+ matching_values = paths_to_check.collect do |path_to_check|
177
+ json_path_values_for(response, path_to_check, attribute: attribute)
178
+ end.reject(&:empty?)
179
+ raise NoElementAtPath, "No value at JSONPath '#{paths_to_check}' in '#{response.body}'" if matching_values.empty? && not_empty
180
+
181
+ matching_values.first
182
+ end
183
+
166
184
  # Based on a exchange, return the value at the provided xpath
167
185
  # If the path does not begin with a '/', a '//' is added to it
168
186
  # @param [RestClient::Response] response Response from API
@@ -179,21 +197,12 @@ module Soaspec
179
197
 
180
198
  return result.attributes[attribute].inner_text
181
199
  when :json
182
- path = add_pascal_path(path)
183
- paths_to_check = path.split(',')
184
- paths_to_check = paths_to_check.map { |path_to_check| prefix_json_path(path_to_check) }
185
- matching_values = paths_to_check.collect do |path_to_check|
186
- json_path_values_for(response, path_to_check, attribute: attribute)
187
- end.reject(&:empty?)
188
- raise NoElementAtPath, "No value at JSONPath '#{paths_to_check}' in '#{response.body}'" if matching_values.empty?
189
-
190
- matching_values.first.first
191
- when :hash
192
- response.dig(path.split('.')) # Use path as Hash dig expression separating params via '.' TODO: Unit test
193
- else
200
+ matching_values = calculated_json_path_matches(path, response, attribute, not_empty: true)
201
+ matching_values.first
202
+ else # Assume this is a String
194
203
  raise NoElementAtPath, 'Response is empty' if response.to_s.empty?
195
204
 
196
- response.to_s[/path/] # Perform regular expression using path if not XML nor JSON TODO: Unit test
205
+ response.to_s[/#{path}/] # Perform regular expression using path if not XML nor JSON
197
206
  end
198
207
  end
199
208
 
@@ -204,7 +213,9 @@ module Soaspec
204
213
  when :xml
205
214
  xpath_elements_for(response: response, xpath: path, attribute: attribute).map(&:inner_text)
206
215
  when :json
207
- json_path_values_for(response, path, attribute: attribute)
216
+ result = calculated_json_path_matches(path, response, attribute)
217
+ result || []
218
+ # json_path_values_for(response, path, attribute: attribute)
208
219
  else
209
220
  raise "Unable to interpret type of #{response.body}"
210
221
  end
@@ -11,7 +11,7 @@ class Interpreter
11
11
  elsif json?
12
12
  :json
13
13
  else
14
- :unknown
14
+ :string
15
15
  end
16
16
  elsif response.is_a? Hash
17
17
  :hash
@@ -71,9 +71,16 @@ end
71
71
 
72
72
  # Whether response has successful status code and correct mandatory elements and values
73
73
  RSpec::Matchers.define :be_successful do
74
- match do |actual|
74
+ # @param [Exchange, RestClient::Response] actual Object that returns Exchange or is Exchange
75
+ # @return [Exchange] Exchange to use
76
+ def exchange_from(actual)
77
+ actual.respond_to?(:exchange) ? actual.exchange : actual
78
+ end
79
+
80
+ # @param [Exchange, RestClient::Response] exchange Object that returns Exchange or is Exchange
81
+ # @return [Array] List of errors when checking Exchange response is successful
82
+ def collect_errors(exchange)
75
83
  failure_list = []
76
- exchange = actual.respond_to?(:exchange) ? actual.exchange : actual
77
84
  failure_list << "#{exchange.status_code} not valid status code" unless (200..299).cover?(exchange.status_code)
78
85
  exchange.exchange_handler.expected_mandatory_elements.each do |mandatory_element_path|
79
86
  begin
@@ -88,8 +95,20 @@ RSpec::Matchers.define :be_successful do
88
95
  exchange.exchange_handler.expected_mandatory_json_values.each do |path, value|
89
96
  failure_list << "Expected value at json '#{path}' to be '#{value}' but was '#{exchange[path]}'" unless exchange[path] == value
90
97
  end
98
+ failure_list
99
+ end
100
+
101
+ match do |actual|
102
+ exchange = exchange_from actual
103
+ failure_list = collect_errors exchange
91
104
  raise failure_list.to_s unless failure_list.empty?
105
+ true
106
+ end
92
107
 
108
+ match_when_negated do |actual|
109
+ exchange = exchange_from actual
110
+ failure_list = collect_errors exchange
111
+ raise "Expected failure. Status code is #{exchange.status_code}" if failure_list.empty?
93
112
  true
94
113
  end
95
114
  end
@@ -1,3 +1,3 @@
1
1
  module Soaspec
2
- VERSION = '0.2.21'.freeze
2
+ VERSION = '0.2.22'.freeze
3
3
  end
@@ -30,7 +30,7 @@ module Soaspec
30
30
 
31
31
  documentation 'Nothing under /. Go look at /docs' do
32
32
  response 'redirects to the documentation page'
33
- status 303
33
+ status 302
34
34
  end
35
35
  get '/' do
36
36
  redirect '/docs'
@@ -38,6 +38,20 @@ module Soaspec
38
38
 
39
39
  doc_endpoint '/docs'
40
40
 
41
+ documentation 'Simulate server error' do
42
+ status 500
43
+ end
44
+ get '/server_error' do
45
+ [500, {}, 'Internal Server Error']
46
+ end
47
+
48
+ documentation 'Used to verify extract from text response' do
49
+ response 'Plain text with a pattern to match in it'
50
+ end
51
+ get '/text_response' do
52
+ 'This is some text. In here it says ID=12345 to indicate value to obtain'
53
+ end
54
+
41
55
  documentation 'Used to test attributes' do
42
56
  response 'A simple Note XML with a date attribute'
43
57
  end
@@ -63,6 +77,7 @@ module Soaspec
63
77
  JSON.generate(success: Soaspec::TestServer::IdManager.result_for(num, id), id: id)
64
78
  end
65
79
 
80
+ documentation 'Sets status as developed'
66
81
  post '/packages/developed' do
67
82
  Soaspec::TestServer::IdManager.developed = request.body.include?('true')
68
83
  Soaspec::TestServer::IdManager.developed.to_s
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.2.21
4
+ version: 0.2.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - SamuelGarrattIQA
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-20 00:00:00.000000000 Z
11
+ date: 2019-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler