diff options
Diffstat (limited to 'spec/support/matchers')
-rw-r--r-- | spec/support/matchers/exceed_query_limit.rb | 101 | ||||
-rw-r--r-- | spec/support/matchers/graphql_matchers.rb | 22 |
2 files changed, 115 insertions, 8 deletions
diff --git a/spec/support/matchers/exceed_query_limit.rb b/spec/support/matchers/exceed_query_limit.rb index b9630b00038..cc0abfa0dd6 100644 --- a/spec/support/matchers/exceed_query_limit.rb +++ b/spec/support/matchers/exceed_query_limit.rb @@ -59,11 +59,15 @@ module ExceedQueryLimitHelpers def verify_count(&block) @subject_block = block - actual_count > expected_count + threshold + actual_count > maximum + end + + def maximum + expected_count + threshold end def failure_message - threshold_message = threshold > 0 ? " (+#{@threshold})" : '' + threshold_message = threshold > 0 ? " (+#{threshold})" : '' counts = "#{expected_count}#{threshold_message}" "Expected a maximum of #{counts} queries, got #{actual_count}:\n\n#{log_message}" end @@ -73,6 +77,55 @@ module ExceedQueryLimitHelpers end end +RSpec::Matchers.define :issue_fewer_queries_than do + supports_block_expectations + + include ExceedQueryLimitHelpers + + def control + block_arg + end + + def control_recorder + @control_recorder ||= ActiveRecord::QueryRecorder.new(&control) + end + + def expected_count + control_recorder.count + end + + def verify_count(&block) + @subject_block = block + + # These blocks need to be evaluated in an expected order, in case + # the events in expected affect the counts in actual + expected_count + actual_count + + actual_count < expected_count + end + + match do |block| + verify_count(&block) + end + + def failure_message + <<~MSG + Expected to issue fewer than #{expected_count} queries, but got #{actual_count} + + #{log_message} + MSG + end + + failure_message_when_negated do |actual| + <<~MSG + Expected query count of #{actual_count} to be less than #{expected_count} + + #{log_message} + MSG + end +end + RSpec::Matchers.define :issue_same_number_of_queries_as do supports_block_expectations @@ -82,30 +135,66 @@ RSpec::Matchers.define :issue_same_number_of_queries_as do block_arg end + chain :or_fewer do + @or_fewer = true + end + + chain :ignoring_cached_queries do + @skip_cached = true + end + def control_recorder @control_recorder ||= ActiveRecord::QueryRecorder.new(&control) end def expected_count - @expected_count ||= control_recorder.count + control_recorder.count end def verify_count(&block) @subject_block = block - (expected_count - actual_count).abs <= threshold + # These blocks need to be evaluated in an expected order, in case + # the events in expected affect the counts in actual + expected_count + actual_count + + if @or_fewer + actual_count <= expected_count + else + (expected_count - actual_count).abs <= threshold + end end match do |block| verify_count(&block) end + def failure_message + <<~MSG + Expected #{expected_count_message} queries, but got #{actual_count} + + #{log_message} + MSG + end + failure_message_when_negated do |actual| - failure_message + <<~MSG + Expected #{actual_count} not to equal #{expected_count_message} + + #{log_message} + MSG + end + + def expected_count_message + or_fewer_msg = "or fewer" if @or_fewer + threshold_msg = "(+/- #{threshold})" unless threshold.zero? + + ["#{expected_count}", or_fewer_msg, threshold_msg].compact.join(' ') end def skip_cached - false + @skip_cached || false end end diff --git a/spec/support/matchers/graphql_matchers.rb b/spec/support/matchers/graphql_matchers.rb index 3e2193a9069..7fa06e25405 100644 --- a/spec/support/matchers/graphql_matchers.rb +++ b/spec/support/matchers/graphql_matchers.rb @@ -82,12 +82,30 @@ RSpec::Matchers.define :have_graphql_mutation do |mutation_class| end end +# note: connection arguments do not have to be named, they will be inferred. RSpec::Matchers.define :have_graphql_arguments do |*expected| include GraphqlHelpers + def expected_names(field) + @names ||= Array.wrap(expected).map { |name| GraphqlHelpers.fieldnamerize(name) } + + if field.type.try(:ancestors)&.include?(GraphQL::Types::Relay::BaseConnection) + @names | %w(after before first last) + else + @names + end + end + match do |field| - argument_names = expected.map { |name| GraphqlHelpers.fieldnamerize(name) } - expect(field.arguments.keys).to contain_exactly(*argument_names) + names = expected_names(field) + + expect(field.arguments.keys).to contain_exactly(*names) + end + + failure_message do |field| + names = expected_names(field) + + "expected that #{field.name} would have the following fields: #{names.inspect}, but it has #{field.arguments.keys.inspect}." end end |