factory_sloth 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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: