Skip to content

Commit

Permalink
Update rspec matcher to test nested hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
estolfo committed Nov 4, 2019
1 parent 20fa242 commit 7906e9d
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 38 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Expand Up @@ -10,7 +10,6 @@
## 7.0.0.pre

* Added `elastic_ruby_console` executable

### Client

* Fixed failing integration test
Expand Down
98 changes: 65 additions & 33 deletions api-spec-testing/rspec_matchers.rb
Expand Up @@ -157,62 +157,94 @@
end

# Match an arbitrary field of a response to a given value.
RSpec::Matchers.define :match_response do |expected_pairs, test|
RSpec::Matchers.define :match_response do |pairs, test|

match do |response|
mismatched_values(sanitize_pairs(expected_pairs), test, response).empty?
pairs = sanitize_pairs(pairs)
compare_pairs(pairs, response, test).empty?
end

failure_message do |response|
"the pair/value #{mismatched_values(sanitize_pairs(expected_pairs), test, response)}" +
" does not match the pair/value in the response #{response}"
"the actual response pair/value(s) #{@mismatched_pairs}" +
" does not match the pair/value(s) in the response #{response}"
end

def sanitize_pairs(expected_pairs)
# sql test returns results at '$body' key. See sql/translate.yml
@pairs ||= expected_pairs['$body'] ? expected_pairs['$body'] : expected_pairs
end

def mismatched_values(pairs, test, response)
@mismatched_values ||= begin
if pairs.is_a?(String)
# Must return an empty list if there are no mismatched values
compare_string_response(pairs, response) ? [] : [ pairs ]
else
compare_hash(pairs, response, test)
end
def compare_pairs(expected_pairs, response, test)
@mismatched_pairs = {}
if expected_pairs.is_a?(String)
@mismatched_pairs = expected_pairs unless compare_string_response(expected_pairs, response)
else
compare_hash(expected_pairs, response, test)
end
@mismatched_pairs
end

def compare_hash(expected_keys_values, response, test)
expected_keys_values.reject do |expected_key, expected_value|
def compare_hash(expected_pairs, actual_hash, test)
expected_pairs.each do |expected_key, expected_value|
# Select the values that don't match, used for the failure message.

if expected_value.is_a?(Hash)
compare_hash(response[expected_key], expected_value, test)
elsif expected_value.is_a?(String)
split_key = TestFile::Test.split_and_parse_key(expected_key).collect do |k|
test.get_cached_value(k)
# Find the value to compare in the response
split_key = TestFile::Test.split_and_parse_key(expected_key).collect do |k|
# Sometimes the expected *key* is a cached value from a previous request.
test.get_cached_value(k)
end
actual_value = TestFile::Test.find_value_in_document(split_key, actual_hash)
# Sometimes the key includes dots. See watcher/put_watch/60_put_watch_with_action_condition.yml
actual_value = TestFile::Test.find_value_in_document(expected_key, actual_hash) if actual_value.nil?

# Sometimes the expected *value* is a cached value from a previous request.
# See test api_key/10_basic.yml
expected_value = test.get_cached_value(expected_value)

case expected_value
when Hash
compare_hash(expected_value, actual_value, test)
when Array
unless compare_array(expected_value, actual_value, test, actual_hash)
@mismatched_pairs.merge!(expected_key => expected_value)
end
actual_value = TestFile::Test.find_value_in_document(split_key, response)

# Sometimes the expected value is a cached value from a previous request.
# See test api_key/10_basic.yml
expected_value = test.get_cached_value(expected_value)

# When you must match a regex. For example:
# match: {task: '/.+:\d+/'}
if expected_value.is_a?(String) && expected_value[0] == "/" && expected_value[-1] == "/"
/#{expected_value.tr("/", "")}/ =~ actual_value
elsif expected_key == ''
expected_value == response
else
actual_value == expected_value
when String
unless compare_string(expected_value, actual_value, test, actual_hash)
@mismatched_pairs.merge!(expected_key => expected_value)
end
else
unless expected_value == actual_value
@mismatched_pairs.merge!(expected_key => expected_value)
end
end
end
end

def compare_string(expected, actual_value, test, response)
# When you must match a regex. For example:
# match: {task: '/.+:\d+/'}
if expected[0] == "/" && expected[-1] == "/"
/#{expected.tr("/", "")}/ =~ actual_value
elsif expected == ''
actual_value == response
else
expected == actual_value
end
end

def compare_array(expected, actual, test, response)
expected.each_with_index do |value, i|
case value
when Hash
return false unless compare_hash(value, actual[i], test)
when Array
return false unless compare_array(value, actual[i], test, response)
when String
return false unless compare_string(value, actual[i], test, response)
end
end
end

def compare_string_response(expected_string, response)
regexp = Regexp.new(expected_string.strip[1..-2], Regexp::EXTENDED|Regexp::MULTILINE)
regexp =~ response
Expand Down
1 change: 1 addition & 0 deletions api-spec-testing/test_file/test.rb
Expand Up @@ -24,6 +24,7 @@ class << self
#
# @since 6.2.0
def find_value_in_document(chain, document)
return document[chain] unless chain.is_a?(Array)
return document[chain[0]] unless chain.size > 1
# a number can be a string key in a Hash or indicate an element in a list
if document.is_a?(Hash)
Expand Down
Expand Up @@ -18,7 +18,7 @@
context "#{test.description}" do

if test.skip_test?(ADMIN_CLIENT)
skip 'Test contains feature(s) not yet support or version is not satisfied'
skip 'Test contains feature(s) not yet supported or version is not satisfied'

else

Expand Down
Expand Up @@ -22,7 +22,6 @@ def put_data_frame_transform(arguments={})
raise ArgumentError, "Required argument 'body' missing" unless arguments[:body]
raise ArgumentError, "Required argument 'transform_id' missing" unless arguments[:transform_id]
arguments = arguments.clone

transform_id = URI.escape(arguments.delete(:transform_id))
body = arguments.delete(:body)

Expand All @@ -33,10 +32,12 @@ def put_data_frame_transform(arguments={})
perform_request(method, path, params, body).body
end


# Register this action with its valid params when the module is loaded.
#
# @since 8.0.0
# Register this action with its valid params when the module is loaded.
#
# @since 7.4.0
ParamsRegistry.register(:put_data_frame_transform, [ :defer_validation ].freeze)
end
end
Expand Down
2 changes: 1 addition & 1 deletion elasticsearch-xpack/spec/xpack/rest_api_yaml_spec.rb
Expand Up @@ -23,7 +23,7 @@
context "#{test.description}" do

if test.skip_test?(ADMIN_CLIENT)
skip 'Test contains feature(s) not yet support or version is not satisfied'
skip 'Test contains feature(s) not yet supported or version is not satisfied'

else

Expand Down

0 comments on commit 7906e9d

Please sign in to comment.