factory_sloth 1.3.0 → 1.3.1

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: 9032b54abec61f25adcfd938a503f312017667f64b4aa1f303ede50a346a62be
4
- data.tar.gz: 901d358d3572a708ec8190c2d2e59dbdab3bce42f894301284dc285895d48f19
3
+ metadata.gz: 1ca25fc42535f24034b3a52ddb2b88d9e64dbd68b83e2febb7ddb31679daa118
4
+ data.tar.gz: 92814709e951c1dc15040496ec1c5dea101f2bdcb8d58eb1298182a91a2df2f1
5
5
  SHA512:
6
- metadata.gz: b1aa29c8c7dd007c5e82ee4cfbc164df1550ace4c2d7880e0471b4a892a2dad33a8e03469c56ec5620f99e7c2dc8c6c47f0d7256102910385acea9a3f97f4b74
7
- data.tar.gz: bace623884d7e447200af29fb216f8814f86a7bae4deda093105bb9df716c8151332136a473c31cd6c9e51bc07ded9f2306e9eda29b536b7b4aa130384f0059a
6
+ metadata.gz: 188f7f29920ba9f868171c65c21e7e4611e8c8c9cf41eb229e3f1a17fb98c6c970a491051fac6b501b5544b4298cef22f42335e8306e93370225c9acedfe8182
7
+ data.tar.gz: dbc6452a523efb648d0f2d71594d883c469194164b86a8f2f16ece21a171e8d82bd2a8260072e777b731b1001ad9f0eb0c5f51ce1610ebf3f8cc67b7d19e4471
data/CHANGELOG.md CHANGED
@@ -1,11 +1,17 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.3.1] - 2023-05-24
4
+
5
+ ### Fixed
6
+
7
+ - Stop trying to patch lines with multiple create calls, which was unreliable
8
+
3
9
  ## [1.3.0] - 2023-05-22
4
10
 
5
11
  ### Added
6
12
 
7
- - nicer output
8
- - verbose mode
13
+ - Nicer output
14
+ - Verbose mode
9
15
 
10
16
  ## [1.2.2] - 2023-05-18
11
17
 
@@ -22,17 +22,7 @@ module FactorySloth
22
22
  def call
23
23
  self.create_calls = CreateCallFinder.call(code: original_code)
24
24
 
25
- # Performance note: it might be faster to write ALL possible patches for a
26
- # given spec file to tempfiles first, and then run them all in a single
27
- # rspec call. However, this would make it impossible to use `--fail-fast`,
28
- # and might make examples fail that are not as idempotent as they should be.
29
- self.changed_create_calls =
30
- create_calls.sort_by { |call| [-call.line, -call.column] }.select do |call|
31
- build_result = try_patch(call, 'build')
32
- next if build_result == ABORT
33
-
34
- build_result == SUCCESS || try_patch(call, 'build_stubbed') == SUCCESS
35
- end
25
+ self.changed_create_calls = find_changeable_create_calls
36
26
 
37
27
  # validate whole spec after changes, e.g. to detect side-effects
38
28
  self.ok = changed_create_calls.none? || begin
@@ -65,6 +55,27 @@ module FactorySloth
65
55
 
66
56
  attr_writer :create_calls, :changed_create_calls, :ok, :path, :original_code, :patched_code
67
57
 
58
+ # Performance note: it might be faster to write ALL possible patches for a
59
+ # given spec file to tempfiles first, and then run them all in a single
60
+ # rspec call. However, this would make it impossible to use `--fail-fast`,
61
+ # and might make examples fail that are not as idempotent as they should be.
62
+ def find_changeable_create_calls
63
+ lines = create_calls.map(&:line)
64
+
65
+ self.changed_create_calls =
66
+ create_calls.sort_by { |call| [-call.line, -call.column] }.select do |call|
67
+ if lines.count(call.line) > 1
68
+ print_call_info(call, 'multiple create calls per line are unsupported, skipping')
69
+ next
70
+ end
71
+
72
+ build_result = try_patch(call, 'build')
73
+ next if build_result == ABORT
74
+
75
+ build_result == SUCCESS || try_patch(call, 'build_stubbed') == SUCCESS
76
+ end
77
+ end
78
+
68
79
  def try_patch(call, base_variant)
69
80
  variant = call.name.sub('create', base_variant)
70
81
  FactorySloth.verbose && puts("#{link_to_call(call)}: trying #{variant} ...")
@@ -79,14 +90,14 @@ module FactorySloth
79
90
 
80
91
  if result.success?
81
92
  info = FactorySloth.dry_run ? 'can be replaced' : 'replaced'
82
- puts call_message(call, "#{info} with #{variant}"), ''
93
+ print_call_info(call, "#{info} with #{variant}")
83
94
  self.patched_code = new_patched_code
84
95
  SUCCESS
85
96
  elsif result.exitstatus == ExecutionCheck::FACTORY_UNUSED_CODE
86
- puts call_message(call, "is never executed, skipping"), ''
97
+ print_call_info(call, "is never executed, skipping")
87
98
  ABORT
88
99
  elsif result.exitstatus == ExecutionCheck::FACTORY_PERSISTED_LATER_CODE
89
- FactorySloth.verbose && puts("Record is persisted later, skipping")
100
+ FactorySloth.verbose && print_call_info("record is persisted later, skipping")
90
101
  ABORT
91
102
  end
92
103
  end
@@ -100,13 +111,17 @@ module FactorySloth
100
111
  ABORT = :ABORT # returned if there is no need to try other variants
101
112
  SUCCESS = :SUCCESS
102
113
 
103
- def call_message(call, message)
114
+ def print_call_info(call, message)
104
115
  line_content = original_code[/\A(?:.*\R){#{call.line - 1}}\K.*/]
105
- indent = line_content[/^\s*/]
106
-
107
- "#{link_to_call(call)}: #{call.name} #{message}\n"\
108
- " #{line_content.delete_prefix(indent)}\n"\
109
- " #{' ' * (call.column - indent.size)}#{Color.yellow('^' * call.name.size)}"
116
+ indentation = line_content[/^\s*/]
117
+ underline = Color.yellow('^' * call.name.size)
118
+
119
+ puts(
120
+ "#{link_to_call(call)}: #{call.name} #{message}",
121
+ " #{line_content.delete_prefix(indentation)}",
122
+ " #{' ' * (call.column - indentation.size)}#{underline}",
123
+ "",
124
+ )
110
125
  end
111
126
 
112
127
  def link_to_call(call)
@@ -14,8 +14,12 @@ module FactorySloth::Color
14
14
  private
15
15
 
16
16
  def colorize(str, color_code)
17
- return str unless $stdout.is_a?(IO) && $stdout.tty?
17
+ return str unless tty?
18
18
 
19
19
  "\e[#{color_code}m#{str}\e[0m"
20
20
  end
21
+
22
+ def tty?
23
+ $stdout.is_a?(IO) && $stdout.tty?
24
+ end
21
25
  end
@@ -4,6 +4,10 @@
4
4
  # The rationale behind a) is that things like skipped examples should not
5
5
  # be broken. The rationale behind b) is that not much DB work would be saved,
6
6
  # but diff noise would be increased and ease of editing the example reduced.
7
+ #
8
+ # Note: the caller column is only available in a roundabout way in Ruby >= 3.1,
9
+ # https://bugs.ruby-lang.org/issues/17930, 19452, so multiple replacements
10
+ # in one line would not be validated correctly iff they had mixed validity.
7
11
 
8
12
  module FactorySloth::ExecutionCheck
9
13
  FACTORY_UNUSED_CODE = 77
@@ -15,10 +19,10 @@ module FactorySloth::ExecutionCheck
15
19
  records_by_line = {} # track records initialized through factories per line
16
20
 
17
21
  FactoryBot::Syntax::Methods.class_eval do
18
- alias ___original_#{variant} #{variant} # e.g. ___original_build build
22
+ original_variant = instance_method("#{variant}") # e.g. build
19
23
 
20
- define_method("#{variant}") do |*args, **kwargs, &blk| # e.g. build
21
- result = ___original_#{variant}(*args, **kwargs, &blk)
24
+ define_method("#{variant}") do |*args, **kwargs, &blk|
25
+ result = original_variant.bind_call(self, *args, **kwargs, &blk)
22
26
  list = records_by_line[caller_locations(1, 1)&.first&.lineno] ||= []
23
27
  list.concat([result].flatten) # to work with single, list, and pair
24
28
  result
@@ -1,3 +1,3 @@
1
1
  module FactorySloth
2
- VERSION = '1.3.0'
2
+ VERSION = '1.3.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_sloth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janosch Müller
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-22 00:00:00.000000000 Z
11
+ date: 2023-05-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: