@@ -249,7 +249,7 @@ class FieldModels
249249 end
250250
251251 def failure_text
252- expectation_failed_message ( 'query_by' , true )
252+ expectation_failed_message ( 'query_by' , show_values : true )
253253 end
254254 end
255255
@@ -267,15 +267,41 @@ def failure_text
267267 include MatcherErrors
268268
269269 # Convert the map of expected values to a Hash of all arrays
270- temp_expected = expected . transform_values { |v | v . is_a? ( Array ) ? v : [ v ] }
270+ expected = expected . transform_values { |v | v . is_a? ( Array ) ? v : [ v ] }
271271
272272 match do |block |
273273 @query_stats = Queries ::FieldCounter . instrument ( &block )
274- temp_expected == @query_stats . query_values . select { |k , _ | temp_expected . keys . include? ( k ) }
274+ expected == @query_stats . query_values . select { |k , _ | expected . keys . include? ( k ) }
275275 end
276276
277277 def failure_text
278- expectation_failed_message ( 'query_by' , true , true )
278+ expectation_failed_message ( 'query_by' , show_values : true , subset : true )
279+ end
280+ end
281+
282+ # The following will succeed:
283+ #
284+ # expect {
285+ # WcRiskClass.last.update_attributes(id: 9999)
286+ # WcRiskClass.last.update_attributes(id: 1234)
287+ # }.to query_by_field_at_least_ignore_notfound(
288+ # 'id' => 6666,
289+ # )
290+ #
291+ RSpec ::Matchers . define ( :query_by_field_at_least_ignore_notfound ) do |expected = { } |
292+ include MatcherConfiguration
293+ include MatcherErrors
294+
295+ # Convert the map of expected values to a Hash of all arrays
296+ expected = expected . transform_values { |v | v . is_a? ( Array ) ? v : [ v ] }
297+
298+ match do |block |
299+ @query_stats = Queries ::FieldCounter . instrument ( &block )
300+ expected . select { |k , _ | @query_stats . query_values . keys . include? ( k ) } == @query_stats . query_values . select { |k , _ | expected . keys . include? ( k ) }
301+ end
302+
303+ def failure_text
304+ expectation_failed_message ( 'query_by' , show_values : true , subset : true , ignore_missing : true )
279305 end
280306 end
281307 end
@@ -301,24 +327,33 @@ def supports_block_expectations?
301327 end
302328
303329 module MatcherErrors
304- def create_display_string ( max_key_length , key , left , right , values_only )
305- "#{ key . rjust ( max_key_length , ' ' ) } – expected: #{ left } , got: #{ right } #{ "(#{ '+' if right > left } #{ right - left } )" if values_only } "
330+ def create_display_string ( max_key_length , key , left , right , show_values )
331+ diff_array = right - left
332+ if diff_array . empty?
333+ diff_array = left - right
334+ end
335+ "#{ key . rjust ( max_key_length , ' ' ) } – expected: #{ left } , got: #{ right } #{ "(difference: #{ diff_array } )" if show_values } "
306336 end
307337
308338 # Show the difference between expected and actual values with one value
309339 # per line. This is done by hand because as of this writing the author
310340 # doesn't understand how RSpec does its nice hash diff printing.
311- def difference ( keys , values_only : false )
341+ def difference ( keys , show_values : false )
312342 max_key_length = keys . reduce ( 0 ) { |max , key | [ max , key . size ] . max }
313343
344+ _expected = expected
345+ if show_values
346+ _expected = expected . transform_values { |v | v . is_a? ( Array ) ? v : [ v ] }
347+ end
348+
314349 keys . map do |key |
315- left = expected . fetch ( key , values_only ? [ ] : 0 )
316- left = [ left ] unless left . is_a? ( Array ) || ! values_only
350+ left = _expected . fetch ( key , show_values ? [ ] : 0 )
351+ left = [ left ] unless left . is_a? ( Array ) || show_values
317352
318353 right = @query_stats . queries . fetch ( key , { } )
319- right = values_only ? right . fetch ( :values , [ ] ) : right . fetch ( :count , 0 )
354+ right = show_values ? right . fetch ( :values , [ ] ) : right . fetch ( :count , 0 )
320355
321- create_display_string ( max_key_length , key , left , right , values_only )
356+ create_display_string ( max_key_length , key , left , right , show_values )
322357 end . compact
323358 end
324359
@@ -341,29 +376,32 @@ def no_queries_fail_message(crud_operation)
341376 "Expected ActiveRecord to not #{ crud_operation } any records, got #{ @query_stats . query_counts } \n \n Where unexpected queries came from:\n \n #{ source_lines ( @query_stats . query_counts . keys ) . join ( "\n " ) } "
342377 end
343378
344- def reject_record ( subset , expected , key )
345- if subset && !expected [ key ] . nil?
346- ( expected [ key ] - @query_stats . queries [ key ] [ :values ] ) . empty?
379+ def reject_record ( subset , current_expected , key , ignore_missing )
380+ if subset && !current_expected [ key ] . nil?
381+ if ignore_missing
382+ @query_stats . queries [ key ] [ :values ] . empty? || ( current_expected [ key ] - @query_stats . queries [ key ] [ :values ] ) . empty?
383+ else
384+ ( current_expected [ key ] - @query_stats . queries [ key ] [ :values ] ) . empty?
385+ end
347386 else
348- @query_stats . queries [ key ] [ :values ] == expected [ key ]
387+ ignore_missing || @query_stats . queries [ key ] [ :values ] == current_expected [ key ]
349388 end
350389 end
351390
352- def filter_model_names ( subset , values_only )
391+ def filter_model_names ( subset , show_values , ignore_missing )
353392 all_model_names = expected . keys + @query_stats . queries . keys
354- if values_only
355- all_model_names . reject { |key | reject_record ( subset , expected , key ) } . uniq
393+ if show_values
394+ _expected = expected . transform_values { |v | v . is_a? ( Array ) ? v : [ v ] }
395+ all_model_names . reject { |key | reject_record ( subset , _expected , key , ignore_missing ) } . uniq
356396 else
357397 all_model_names . reject { |key | expected [ key ] == @query_stats . queries [ key ] [ :count ] } . uniq
358398 end
359399 end
360400
361- def expectation_failed_message ( crud_operation , values_only : false , subset : false )
362- expected . transform_values { |v | v . is_a ( Array ) ? v : [ v ] } if values_only
363-
364- model_names_with_wrong_count = filter_model_names ( subset , values_only )
365- "Expected ActiveRecord to #{ crud_operation } #{ expected } , got #{ values_only ? @query_stats . query_values : @query_stats . query_counts } \n " \
366- "Expectations that differed:\n #{ difference ( model_names_with_wrong_count , values_only : values_only ) . join ( "\n " ) } \n \n Where unexpected queries came from:\n \n #{ source_lines ( model_names_with_wrong_count ) . join ( "\n " ) } "
401+ def expectation_failed_message ( crud_operation , show_values : false , subset : false , ignore_missing : false )
402+ model_names_with_wrong_count = filter_model_names ( subset , show_values , ignore_missing )
403+ "Expected ActiveRecord to #{ crud_operation } #{ expected } , got #{ show_values ? @query_stats . query_values : @query_stats . query_counts } \n " \
404+ "Expectations that differed:\n #{ difference ( model_names_with_wrong_count , show_values : show_values ) . join ( "\n " ) } \n \n Where unexpected queries came from:\n \n #{ source_lines ( model_names_with_wrong_count ) . join ( "\n " ) } "
367405 end
368406 end
369407 end
0 commit comments