rubocop-factory_bot 2.23.1 → 2.24.0

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: 5d8a45a48d47318e9e16e7b3bbde99ae9dcf94f6e90c068f0916ff2945511e85
4
- data.tar.gz: 52ff0ffe8fb20bc0ed3ec4dca29aa13a29b106e39f7bacac370388f0c789bf1c
3
+ metadata.gz: f2bb256bf3c94a3ff0eca302abed9006719524c843b826f194fbb68c29fea483
4
+ data.tar.gz: 7b619d4d6732c155369caf1edef5f8c6b1af302ba4114c4ace18eb462e2d14af
5
5
  SHA512:
6
- metadata.gz: 53082b6baa7e6ebe69f3ebcc1404f2c8421bfcd3ee6905eba12789faca59c1c090b84abc4696a0773598ab06eb97e8aa2b70384864376b58e568d9eef5ce2549
7
- data.tar.gz: 26f1817b168218b61f7657400f777ec5eb972cedab14501b2f6a5b1bd8691af9b4c3b04607969923eb58ffca49e4070622040950a7d00742624d4d5b03cf9ee1
6
+ metadata.gz: 79e7569730a8530231ac5b5f584f35a7e0c2d2d23174966cee57ce5b4ea45d32617bff8adf5ba0d2ad8a4fe59a32c9bd6a6bf67d90f587cfec0a9b4a558e1bc7
7
+ data.tar.gz: '02965c01b59d3583720b8ca926f0cd2db764557ec41ac4992c582e0622d6d5b364a167ed3933485bd8df7e2d882febdd353878e88e1b175145ea350ffcc1da6b'
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 2.24.0 (2023-09-18)
6
+
7
+ - Fix `FactoryBot/AssociationStyle` cop to ignore explicit associations with `strategy: :build`. ([@pirj])
8
+ - Change `FactoryBot/CreateList` so that it is not an offense if not repeated multiple times. ([@ydah])
9
+ - Fix a false positive for `FactoryBot/AssociationStyle` when `association` is called in trait block and column name is keyword. ([@ydah])
10
+ - Fix a false positive for `FactoryBot/AssociationStyle` when `EnforcedStyle: Explicit` and using trait within trait. ([@ydah])
11
+ - Change `FactoryBot/AssociationStyle`, `FactoryBot/AttributeDefinedStatically`, `FactoryBot/CreateList` and `FactoryBot/FactoryClassName` to work with minitest style directory. ([@ydah])
12
+ - Add `FactoryBot/IdSequence` cop. ([@owst])
13
+
5
14
  ## 2.23.1 (2023-05-15)
6
15
 
7
16
  - Fix `FactoryBot/AssociationStyle` cop for a blockless `factory`. ([@pirj])
@@ -73,6 +82,7 @@
73
82
  [@liberatys]: https://github.com/Liberatys
74
83
  [@morissetcl]: https://github.com/morissetcl
75
84
  [@ngouy]: https://github.com/ngouy
85
+ [@owst]: https://github.com/owst
76
86
  [@pirj]: https://github.com/pirj
77
87
  [@r7kamura]: https://github.com/r7kamura
78
88
  [@seanpdoyle]: https://github.com/seanpdoyle
data/config/default.yml CHANGED
@@ -2,9 +2,10 @@
2
2
  FactoryBot:
3
3
  Enabled: true
4
4
  Include:
5
- - "**/*_spec.rb"
6
- - "**/spec/**/*"
7
- - "**/test/**/*"
5
+ - "**/spec/factories.rb"
6
+ - "**/spec/factories/**/*.rb"
7
+ - "**/test/factories.rb"
8
+ - "**/test/factories/**/*.rb"
8
9
  - "**/features/support/factories/**/*.rb"
9
10
  DocumentationBaseURL: https://docs.rubocop.org/rubocop-factory_bot
10
11
 
@@ -12,11 +13,8 @@ FactoryBot/AssociationStyle:
12
13
  Description: Use a consistent style to define associations.
13
14
  Enabled: pending
14
15
  Safe: false
15
- Include:
16
- - spec/factories.rb
17
- - spec/factories/**/*.rb
18
- - features/support/factories/**/*.rb
19
16
  VersionAdded: '2.23'
17
+ VersionChanged: "<<next>>"
20
18
  EnforcedStyle: implicit
21
19
  SupportedStyles:
22
20
  - explicit
@@ -27,17 +25,18 @@ FactoryBot/AssociationStyle:
27
25
  FactoryBot/AttributeDefinedStatically:
28
26
  Description: Always declare attribute values as blocks.
29
27
  Enabled: true
30
- Include:
31
- - spec/factories.rb
32
- - spec/factories/**/*.rb
33
- - features/support/factories/**/*.rb
34
28
  VersionAdded: '1.28'
35
- VersionChanged: '2.0'
29
+ VersionChanged: "<<next>>"
36
30
  Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/AttributeDefinedStatically
37
31
 
38
32
  FactoryBot/ConsistentParenthesesStyle:
39
33
  Description: Use a consistent style for parentheses in factory_bot calls.
40
34
  Enabled: pending
35
+ Include:
36
+ - "**/*_spec.rb"
37
+ - "**/spec/**/*"
38
+ - "**/test/**/*"
39
+ - "**/features/support/factories/**/*.rb"
41
40
  EnforcedStyle: require_parentheses
42
41
  SupportedStyles:
43
42
  - require_parentheses
@@ -53,9 +52,8 @@ FactoryBot/CreateList:
53
52
  Include:
54
53
  - "**/*_spec.rb"
55
54
  - "**/spec/**/*"
56
- - spec/factories.rb
57
- - spec/factories/**/*.rb
58
- - features/support/factories/**/*.rb
55
+ - "**/test/**/*"
56
+ - "**/features/support/factories/**/*.rb"
59
57
  EnforcedStyle: create_list
60
58
  SupportedStyles:
61
59
  - create_list
@@ -63,12 +61,17 @@ FactoryBot/CreateList:
63
61
  ExplicitOnly: false
64
62
  SafeAutoCorrect: false
65
63
  VersionAdded: '1.25'
66
- VersionChanged: '2.23'
64
+ VersionChanged: "<<next>>"
67
65
  Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/CreateList
68
66
 
69
67
  FactoryBot/FactoryAssociationWithStrategy:
70
68
  Description: Use definition in factory association instead of hard coding a strategy.
71
69
  Enabled: pending
70
+ Include:
71
+ - "**/*_spec.rb"
72
+ - "**/spec/**/*"
73
+ - "**/test/**/*"
74
+ - "**/features/support/factories/**/*.rb"
72
75
  VersionAdded: '2.23'
73
76
  VersionChanged: '2.23'
74
77
  Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryAssociationWithStrategy
@@ -76,17 +79,18 @@ FactoryBot/FactoryAssociationWithStrategy:
76
79
  FactoryBot/FactoryClassName:
77
80
  Description: Use string value when setting the class attribute explicitly.
78
81
  Enabled: true
79
- Include:
80
- - spec/factories.rb
81
- - spec/factories/**/*.rb
82
- - features/support/factories/**/*.rb
83
82
  VersionAdded: '1.37'
84
- VersionChanged: '2.0'
83
+ VersionChanged: "<<next>>"
85
84
  Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryClassName
86
85
 
87
86
  FactoryBot/FactoryNameStyle:
88
87
  Description: Checks for name style for argument of FactoryBot::Syntax::Methods.
89
88
  Enabled: pending
89
+ Include:
90
+ - "**/*_spec.rb"
91
+ - "**/spec/**/*"
92
+ - "**/test/**/*"
93
+ - "**/features/support/factories/**/*.rb"
90
94
  EnforcedStyle: symbol
91
95
  SupportedStyles:
92
96
  - symbol
@@ -96,15 +100,31 @@ FactoryBot/FactoryNameStyle:
96
100
  VersionChanged: '2.23'
97
101
  Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryNameStyle
98
102
 
103
+ FactoryBot/IdSequence:
104
+ Description: Do not create a FactoryBot sequence for an id column.
105
+ Enabled: pending
106
+ VersionAdded: "<<next>>"
107
+ Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/IdSequence
108
+
99
109
  FactoryBot/RedundantFactoryOption:
100
110
  Description: Checks for redundant `factory` option.
101
111
  Enabled: pending
112
+ Include:
113
+ - "**/*_spec.rb"
114
+ - "**/spec/**/*"
115
+ - "**/test/**/*"
116
+ - "**/features/support/factories/**/*.rb"
102
117
  VersionAdded: '2.23'
103
118
  Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/RedundantFactoryOption
104
119
 
105
120
  FactoryBot/SyntaxMethods:
106
121
  Description: Use shorthands from `FactoryBot::Syntax::Methods` in your specs.
107
122
  Enabled: pending
123
+ Include:
124
+ - "**/*_spec.rb"
125
+ - "**/spec/**/*"
126
+ - "**/test/**/*"
127
+ - "**/features/support/factories/**/*.rb"
108
128
  SafeAutoCorrect: false
109
129
  VersionAdded: '2.7'
110
130
  Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/SyntaxMethods
@@ -21,6 +21,16 @@ module RuboCop
21
21
  # user
22
22
  # end
23
23
  #
24
+ # # bad
25
+ # factory :post do
26
+ # association :user, :author
27
+ # end
28
+ #
29
+ # # good
30
+ # factory :post do
31
+ # user factory: %i[user author]
32
+ # end
33
+ #
24
34
  # @example EnforcedStyle: explicit
25
35
  # # bad
26
36
  # factory :post do
@@ -32,6 +42,16 @@ module RuboCop
32
42
  # association :user
33
43
  # end
34
44
  #
45
+ # # bad
46
+ # factory :post do
47
+ # user factory: %i[user author]
48
+ # end
49
+ #
50
+ # # good
51
+ # factory :post do
52
+ # association :user, :author
53
+ # end
54
+ #
35
55
  # # good (NonImplicitAssociationMethodNames: ['email'])
36
56
  # sequence :email do |n|
37
57
  # "person#{n}@example.com"
@@ -53,6 +73,11 @@ module RuboCop
53
73
  ].freeze
54
74
 
55
75
  RESTRICT_ON_SEND = %i[factory trait].freeze
76
+ KEYWORDS = %i[alias and begin break case class def defined? do
77
+ else elsif end ensure false for if in module
78
+ next nil not or redo rescue retry return self
79
+ super then true undef unless until when while
80
+ yield __FILE__ __LINE__ __ENCODING__].freeze
56
81
 
57
82
  def on_send(node)
58
83
  bad_associations_in(node).each do |association|
@@ -72,6 +97,13 @@ module RuboCop
72
97
  (send nil? :association sym ...)
73
98
  PATTERN
74
99
 
100
+ # @!method with_strategy_build_option?(node)
101
+ def_node_matcher :with_strategy_build_option?, <<~PATTERN
102
+ (send nil? :association sym ...
103
+ (hash <(pair (sym :strategy) (sym :build)) ...>)
104
+ )
105
+ PATTERN
106
+
75
107
  # @!method implicit_association?(node)
76
108
  def_node_matcher :implicit_association?, <<~PATTERN
77
109
  (send nil? !#non_implicit_association_method_name? ...)
@@ -103,6 +135,16 @@ module RuboCop
103
135
  (send nil? :association _ (sym $_)* ...)
104
136
  PATTERN
105
137
 
138
+ # @!method association_names(node)
139
+ def_node_search :association_names, <<~PATTERN
140
+ (send nil? :association $...)
141
+ PATTERN
142
+
143
+ # @!method trait_name(node)
144
+ def_node_search :trait_name, <<~PATTERN
145
+ (send nil? :trait (sym $_) )
146
+ PATTERN
147
+
106
148
  def autocorrect(corrector, node)
107
149
  if style == :explicit
108
150
  autocorrect_to_explicit_style(corrector, node)
@@ -131,9 +173,22 @@ module RuboCop
131
173
 
132
174
  def bad?(node)
133
175
  if style == :explicit
134
- implicit_association?(node)
176
+ implicit_association?(node) &&
177
+ !trait_within_trait?(node)
135
178
  else
136
- explicit_association?(node)
179
+ explicit_association?(node) &&
180
+ !with_strategy_build_option?(node) &&
181
+ !keyword?(node)
182
+ end
183
+ end
184
+
185
+ def keyword?(node)
186
+ association_names(node).any? do |associations|
187
+ associations.any? do |association|
188
+ next unless association.sym_type?
189
+
190
+ KEYWORDS.include?(association.value)
191
+ end
137
192
  end
138
193
  end
139
194
 
@@ -190,6 +245,14 @@ module RuboCop
190
245
  end
191
246
  options
192
247
  end
248
+
249
+ def trait_within_trait?(node)
250
+ factory_node = node.ancestors.reverse.find do |ancestor|
251
+ ancestor.method?(:factory) if ancestor.block_type?
252
+ end
253
+
254
+ trait_name(factory_node).include?(node.method_name)
255
+ end
193
256
  end
194
257
  end
195
258
  end
@@ -58,7 +58,7 @@ module RuboCop
58
58
  # create_list :user, 3
59
59
  # 3.times { create :user }
60
60
  #
61
- class CreateList < ::RuboCop::Cop::Base
61
+ class CreateList < ::RuboCop::Cop::Base # rubocop:disable Metrics/ClassLength
62
62
  extend AutoCorrector
63
63
  include ConfigurableEnforcedStyle
64
64
  include RuboCop::FactoryBot::Language
@@ -68,24 +68,15 @@ module RuboCop
68
68
  MSG_N_TIMES = 'Prefer %<number>s.times.map.'
69
69
  RESTRICT_ON_SEND = %i[create_list].freeze
70
70
 
71
- # @!method repetition_block?(node)
72
- def_node_matcher :repetition_block?, <<-PATTERN
73
- (block {#array_new? #n_times? #n_times_map?} ...)
74
- PATTERN
75
-
76
- # @!method array_new?(node)
77
- def_node_matcher :array_new?, <<-PATTERN
78
- (send (const {nil? cbase} :Array) :new (int _))
79
- PATTERN
80
-
81
- # @!method n_times?(node)
82
- def_node_matcher :n_times?, <<-PATTERN
83
- (send (int _) :times)
84
- PATTERN
85
-
86
- # @!method n_times_map?(node)
87
- def_node_matcher :n_times_map?, <<-PATTERN
88
- (send #n_times? :map)
71
+ # @!method repeat_count(node)
72
+ def_node_matcher :repeat_count, <<-PATTERN
73
+ (block
74
+ {
75
+ (send (const {nil? cbase} :Array) :new (int $_)) # Array.new(3) { create(:user) }
76
+ (send (int $_) :times) # 3.times { create(:user) }
77
+ (send (send (int $_) :times) :map) # 3.times.map { create(:user) }
78
+ }
79
+ ...)
89
80
  PATTERN
90
81
 
91
82
  # @!method block_with_arg_and_used?(node)
@@ -99,7 +90,7 @@ module RuboCop
99
90
 
100
91
  # @!method arguments_include_method_call?(node)
101
92
  def_node_matcher :arguments_include_method_call?, <<~PATTERN
102
- (send #factory_call? :create sym `$(send ...))
93
+ (send #factory_call? :create sym `(send ...))
103
94
  PATTERN
104
95
 
105
96
  # @!method factory_call(node)
@@ -119,6 +110,7 @@ module RuboCop
119
110
 
120
111
  def on_array(node)
121
112
  return unless same_factory_calls_in_array?(node)
113
+ return if node.values.size < 2
122
114
 
123
115
  add_offense(
124
116
  node,
@@ -128,10 +120,9 @@ module RuboCop
128
120
  end
129
121
  end
130
122
 
131
- def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler
123
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, Metrics/CyclomaticComplexity
132
124
  return unless style == :create_list
133
-
134
- return unless repetition_block?(node)
125
+ return unless repeat_multiple_time?(node)
135
126
  return if block_with_arg_and_used?(node)
136
127
  return unless node.body
137
128
  return if arguments_include_method_call?(node.body)
@@ -146,6 +137,8 @@ module RuboCop
146
137
  return unless style == :n_times
147
138
 
148
139
  factory_list_call(node) do |count|
140
+ next if count < 2
141
+
149
142
  message = format(MSG_N_TIMES, number: count)
150
143
  add_offense(node.loc.selector, message: message) do |corrector|
151
144
  TimesCorrector.new(node).call(corrector)
@@ -155,6 +148,12 @@ module RuboCop
155
148
 
156
149
  private
157
150
 
151
+ def repeat_multiple_time?(node)
152
+ return false unless (count = repeat_count(node))
153
+
154
+ count > 1
155
+ end
156
+
158
157
  # For ease of modification, it is replaced with the `n_times` style,
159
158
  # but if it is not appropriate for the configured style,
160
159
  # it will be replaced in the subsequent autocorrection.
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module FactoryBot
6
+ # Do not create a FactoryBot sequence for an id column.
7
+ #
8
+ # @example
9
+ # # bad - can lead to conflicts between FactoryBot and DB sequences
10
+ # factory :foo do
11
+ # sequence :id
12
+ # end
13
+ #
14
+ # # good - a non-id column
15
+ # factory :foo do
16
+ # sequence :some_non_id_column
17
+ # end
18
+ #
19
+ class IdSequence < ::RuboCop::Cop::Base
20
+ extend AutoCorrector
21
+ include RangeHelp
22
+
23
+ MSG = 'Do not create a sequence for an id attribute'
24
+ RESTRICT_ON_SEND = %i[sequence].freeze
25
+
26
+ def on_send(node)
27
+ return unless node.first_argument.value == :id
28
+
29
+ add_offense(node) do |corrector|
30
+ range_to_remove = range_by_whole_lines(
31
+ node.source_range,
32
+ include_final_newline: true
33
+ )
34
+
35
+ corrector.remove(range_to_remove)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -7,5 +7,6 @@ require_relative 'factory_bot/create_list'
7
7
  require_relative 'factory_bot/factory_association_with_strategy'
8
8
  require_relative 'factory_bot/factory_class_name'
9
9
  require_relative 'factory_bot/factory_name_style'
10
+ require_relative 'factory_bot/id_sequence'
10
11
  require_relative 'factory_bot/redundant_factory_option'
11
12
  require_relative 'factory_bot/syntax_methods'
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module FactoryBot
5
5
  # Version information for the factory_bot RuboCop plugin.
6
6
  module Version
7
- STRING = '2.23.1'
7
+ STRING = '2.24.0'
8
8
  end
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-factory_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.23.1
4
+ version: 2.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Backus
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2023-05-16 00:00:00.000000000 Z
15
+ date: 2023-09-18 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rubocop
@@ -51,6 +51,7 @@ files:
51
51
  - lib/rubocop/cop/factory_bot/factory_association_with_strategy.rb
52
52
  - lib/rubocop/cop/factory_bot/factory_class_name.rb
53
53
  - lib/rubocop/cop/factory_bot/factory_name_style.rb
54
+ - lib/rubocop/cop/factory_bot/id_sequence.rb
54
55
  - lib/rubocop/cop/factory_bot/mixin/configurable_explicit_only.rb
55
56
  - lib/rubocop/cop/factory_bot/redundant_factory_option.rb
56
57
  - lib/rubocop/cop/factory_bot/syntax_methods.rb
@@ -82,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
83
  - !ruby/object:Gem::Version
83
84
  version: '0'
84
85
  requirements: []
85
- rubygems_version: 3.4.13
86
+ rubygems_version: 3.3.7
86
87
  signing_key:
87
88
  specification_version: 4
88
89
  summary: Code style checking for factory_bot files