Module: FactorySloth::ExecutionCheck

Defined in:
lib/factory_sloth/execution_check.rb

Overview

This adds code that makes a spec run fail and thus prevents changes if: a) the patched factory in the given line is never called b) the built record was persisted later anyway The rationale behind a) is that things like skipped examples should not be broken. The rationale behind b) is that not much DB work would be saved, but diff noise would be increased and ease of editing the example reduced.

Note: the caller column is only available in a roundabout way in Ruby >= 3.1, bugs.ruby-lang.org/issues/17930, 19452, so multiple replacements in one line would not be validated correctly iff they had mixed validity.

Constant Summary collapse

FACTORY_UNUSED_CODE =
77
FACTORY_PERSISTED_LATER_CODE =
78

Class Method Summary collapse

Class Method Details

.for(line, variant) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/factory_sloth/execution_check.rb', line 16

def self.for(line, variant)
  "    ; defined?(FactoryBot) && defined?(RSpec) && RSpec.configure do |config|\n      records_by_line = {} # track records initialized through factories per line\n\n      FactoryBot::Syntax::Methods.class_eval do\n        original_variant = instance_method(\"\#{variant}\") # e.g. build\n\n        define_method(\"\#{variant}\") do |*args, **kwargs, &blk|\n          result = original_variant.bind_call(self, *args, **kwargs, &blk)\n          list = records_by_line[caller_locations(1, 1)&.first&.lineno] ||= []\n          list.concat([result].flatten) # to work with single, list, and pair\n          result\n        end\n      end\n\n      config.after(:suite) do\n        records = records_by_line[\#{line}]\n        records&.any? || exit!(\#{FACTORY_UNUSED_CODE})\n        unless \"\#{variant}\".include?('stub') # factory_bot stub stubs persisted? as true\n          records.any? { |r| r.respond_to?(:persisted?) && r.persisted? } &&\n            exit!(\#{FACTORY_PERSISTED_LATER_CODE})\n        end\n      end\n    end\n  RUBY\nend\n"