rubocop-factory_bot 2.23.1 → 2.26.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 +4 -4
- data/CHANGELOG.md +33 -1
- data/config/default.yml +54 -21
- data/lib/rubocop/cop/factory_bot/association_style.rb +66 -2
- data/lib/rubocop/cop/factory_bot/attribute_defined_statically.rb +1 -1
- data/lib/rubocop/cop/factory_bot/consistent_parentheses_style.rb +12 -0
- data/lib/rubocop/cop/factory_bot/create_list.rb +23 -24
- data/lib/rubocop/cop/factory_bot/excessive_create_list.rb +52 -0
- data/lib/rubocop/cop/factory_bot/factory_name_style.rb +8 -1
- data/lib/rubocop/cop/factory_bot/id_sequence.rb +44 -0
- data/lib/rubocop/cop/factory_bot_cops.rb +2 -0
- data/lib/rubocop/factory_bot/cop/generator.rb +25 -0
- data/lib/rubocop/factory_bot/version.rb +1 -1
- metadata +12 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60519b0d051edd3ba23a10f3dfb346dc5aaed4964c489bcfabdb7d16c084cb63
|
|
4
|
+
data.tar.gz: effac41ed4215d5cb27295cdb0a37d8c7021c309e97a8f8e6f8fdf6e385e8226
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee33ad705e93ffa3a68240adabd9de50735819d4d82bbf66868f2efa80d489a0032fd045878bf8fd539dc7677fed9bbf9ef0e3755340b81b4fc1881220e0b24c
|
|
7
|
+
data.tar.gz: 89936fe77a9c8f3ff5dad656b9e30455ec2f6467ac7cba1c678e63fca22396825c3859bc1830f6e766a90109cbae3eca68f64d5a110e3bbd8cebd229cf3218e9
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
## Master (Unreleased)
|
|
4
4
|
|
|
5
|
+
## 2.26.1 (2024-06-12)
|
|
6
|
+
|
|
7
|
+
- Bump RuboCop requirement to +1.61. ([@ydah])
|
|
8
|
+
|
|
9
|
+
## 2.26.0 (2024-06-08)
|
|
10
|
+
|
|
11
|
+
- Fix a false positive for `FactoryBot/AssociationStyle` when using nested factories with traits. ([@jaydorsey])
|
|
12
|
+
- Support `AutoCorrect: contextual` option for LSP. ([@ydah])
|
|
13
|
+
|
|
14
|
+
## 2.25.1 (2024-01-08)
|
|
15
|
+
|
|
16
|
+
- Fix a false positive for `FactoryBot/CreateList` when create call does have method calls and repeat multiple times with other argument. ([@ydah])
|
|
17
|
+
- Fix an error occurred for `FactoryBot/IdSequence` when `sequence` with non-symbol argument or without argument. ([@ydah])
|
|
18
|
+
|
|
19
|
+
## 2.25.0 (2024-01-04)
|
|
20
|
+
|
|
21
|
+
- Fix a false positive for `FactoryBot/FactoryNameStyle` when namespaced models. ([@ydah])
|
|
22
|
+
- Add new `FactoryBot/ExcessiveCreateList` cop. ([@ddieulivol])
|
|
23
|
+
- Fix a false positive for `FactoryBot/ConsistentParenthesesStyle` when hash pinning. ([@ydah])
|
|
24
|
+
|
|
25
|
+
## 2.24.0 (2023-09-18)
|
|
26
|
+
|
|
27
|
+
- Fix `FactoryBot/AssociationStyle` cop to ignore explicit associations with `strategy: :build`. ([@pirj])
|
|
28
|
+
- Change `FactoryBot/CreateList` so that it is not an offense if not repeated multiple times. ([@ydah])
|
|
29
|
+
- Fix a false positive for `FactoryBot/AssociationStyle` when `association` is called in trait block and column name is keyword. ([@ydah])
|
|
30
|
+
- Fix a false positive for `FactoryBot/AssociationStyle` when `EnforcedStyle: Explicit` and using trait within trait. ([@ydah])
|
|
31
|
+
- Change `FactoryBot/AssociationStyle`, `FactoryBot/AttributeDefinedStatically`, `FactoryBot/CreateList` and `FactoryBot/FactoryClassName` to work with minitest style directory. ([@ydah])
|
|
32
|
+
- Add `FactoryBot/IdSequence` cop. ([@owst])
|
|
33
|
+
|
|
5
34
|
## 2.23.1 (2023-05-15)
|
|
6
35
|
|
|
7
36
|
- Fix `FactoryBot/AssociationStyle` cop for a blockless `factory`. ([@pirj])
|
|
@@ -22,7 +51,7 @@
|
|
|
22
51
|
|
|
23
52
|
## Previously (see [rubocop-rspec's changelist](https://github.com/rubocop/rubocop-rspec/blob/70a97b1895ce4b9bcd6ff336d5d343ddc6175fe6/CHANGELOG.md) for details)
|
|
24
53
|
|
|
25
|
-
- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` inside `&&`, `||` and `:?` when `omit_parentheses` is on ([@dmitrytsepelev])
|
|
54
|
+
- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` inside `&&`, `||` and `:?` when `omit_parentheses` is on. ([@dmitrytsepelev])
|
|
26
55
|
- Add new `RSpec/FactoryBot/FactoryNameStyle` cop. ([@ydah])
|
|
27
56
|
- Fix wrong autocorrection in `n_times` style on `RSpec/FactoryBot/CreateList`. ([@r7kamura])
|
|
28
57
|
- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` when using `generate` with multiple arguments. ([@ydah])
|
|
@@ -65,14 +94,17 @@
|
|
|
65
94
|
[@bquorning]: https://github.com/bquorning
|
|
66
95
|
[@composerinteralia]: https://github.com/composerinteralia
|
|
67
96
|
[@darhazer]: https://github.com/Darhazer
|
|
97
|
+
[@ddieulivol]: https://github.com/ddieulivol
|
|
68
98
|
[@dmitrytsepelev]: https://github.com/dmitrytsepelev
|
|
69
99
|
[@harrylewis]: https://github.com/harrylewis
|
|
100
|
+
[@jaydorsey]: https://github.com/jaydorsey
|
|
70
101
|
[@jfragoulis]: https://github.com/jfragoulis
|
|
71
102
|
[@jonatas]: https://github.com/jonatas
|
|
72
103
|
[@leoarnold]: https://github.com/leoarnold
|
|
73
104
|
[@liberatys]: https://github.com/Liberatys
|
|
74
105
|
[@morissetcl]: https://github.com/morissetcl
|
|
75
106
|
[@ngouy]: https://github.com/ngouy
|
|
107
|
+
[@owst]: https://github.com/owst
|
|
76
108
|
[@pirj]: https://github.com/pirj
|
|
77
109
|
[@r7kamura]: https://github.com/r7kamura
|
|
78
110
|
[@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
|
-
- "
|
|
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: '2.24'
|
|
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.
|
|
29
|
+
VersionChanged: '2.24'
|
|
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
|
|
@@ -50,12 +49,12 @@ FactoryBot/ConsistentParenthesesStyle:
|
|
|
50
49
|
FactoryBot/CreateList:
|
|
51
50
|
Description: Checks for create_list usage.
|
|
52
51
|
Enabled: true
|
|
52
|
+
AutoCorrect: contextual
|
|
53
53
|
Include:
|
|
54
54
|
- "**/*_spec.rb"
|
|
55
55
|
- "**/spec/**/*"
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
- features/support/factories/**/*.rb
|
|
56
|
+
- "**/test/**/*"
|
|
57
|
+
- "**/features/support/factories/**/*.rb"
|
|
59
58
|
EnforcedStyle: create_list
|
|
60
59
|
SupportedStyles:
|
|
61
60
|
- create_list
|
|
@@ -63,12 +62,29 @@ FactoryBot/CreateList:
|
|
|
63
62
|
ExplicitOnly: false
|
|
64
63
|
SafeAutoCorrect: false
|
|
65
64
|
VersionAdded: '1.25'
|
|
66
|
-
VersionChanged: '2.
|
|
65
|
+
VersionChanged: '2.26'
|
|
67
66
|
Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/CreateList
|
|
68
67
|
|
|
68
|
+
FactoryBot/ExcessiveCreateList:
|
|
69
|
+
Description: Check for excessive model creation in a list.
|
|
70
|
+
Enabled: pending
|
|
71
|
+
Include:
|
|
72
|
+
- "**/*_spec.rb"
|
|
73
|
+
- "**/spec/**/*"
|
|
74
|
+
- "**/test/**/*"
|
|
75
|
+
- "**/features/support/factories/**/*.rb"
|
|
76
|
+
MaxAmount: 10
|
|
77
|
+
VersionAdded: '2.25'
|
|
78
|
+
Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/ExcessiveCreateList
|
|
79
|
+
|
|
69
80
|
FactoryBot/FactoryAssociationWithStrategy:
|
|
70
81
|
Description: Use definition in factory association instead of hard coding a strategy.
|
|
71
82
|
Enabled: pending
|
|
83
|
+
Include:
|
|
84
|
+
- "**/*_spec.rb"
|
|
85
|
+
- "**/spec/**/*"
|
|
86
|
+
- "**/test/**/*"
|
|
87
|
+
- "**/features/support/factories/**/*.rb"
|
|
72
88
|
VersionAdded: '2.23'
|
|
73
89
|
VersionChanged: '2.23'
|
|
74
90
|
Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryAssociationWithStrategy
|
|
@@ -76,17 +92,18 @@ FactoryBot/FactoryAssociationWithStrategy:
|
|
|
76
92
|
FactoryBot/FactoryClassName:
|
|
77
93
|
Description: Use string value when setting the class attribute explicitly.
|
|
78
94
|
Enabled: true
|
|
79
|
-
Include:
|
|
80
|
-
- spec/factories.rb
|
|
81
|
-
- spec/factories/**/*.rb
|
|
82
|
-
- features/support/factories/**/*.rb
|
|
83
95
|
VersionAdded: '1.37'
|
|
84
|
-
VersionChanged: '2.
|
|
96
|
+
VersionChanged: '2.24'
|
|
85
97
|
Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryClassName
|
|
86
98
|
|
|
87
99
|
FactoryBot/FactoryNameStyle:
|
|
88
100
|
Description: Checks for name style for argument of FactoryBot::Syntax::Methods.
|
|
89
101
|
Enabled: pending
|
|
102
|
+
Include:
|
|
103
|
+
- "**/*_spec.rb"
|
|
104
|
+
- "**/spec/**/*"
|
|
105
|
+
- "**/test/**/*"
|
|
106
|
+
- "**/features/support/factories/**/*.rb"
|
|
90
107
|
EnforcedStyle: symbol
|
|
91
108
|
SupportedStyles:
|
|
92
109
|
- symbol
|
|
@@ -96,15 +113,31 @@ FactoryBot/FactoryNameStyle:
|
|
|
96
113
|
VersionChanged: '2.23'
|
|
97
114
|
Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryNameStyle
|
|
98
115
|
|
|
116
|
+
FactoryBot/IdSequence:
|
|
117
|
+
Description: Do not create a FactoryBot sequence for an id column.
|
|
118
|
+
Enabled: pending
|
|
119
|
+
VersionAdded: '2.24'
|
|
120
|
+
Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/IdSequence
|
|
121
|
+
|
|
99
122
|
FactoryBot/RedundantFactoryOption:
|
|
100
123
|
Description: Checks for redundant `factory` option.
|
|
101
124
|
Enabled: pending
|
|
125
|
+
Include:
|
|
126
|
+
- "**/*_spec.rb"
|
|
127
|
+
- "**/spec/**/*"
|
|
128
|
+
- "**/test/**/*"
|
|
129
|
+
- "**/features/support/factories/**/*.rb"
|
|
102
130
|
VersionAdded: '2.23'
|
|
103
131
|
Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/RedundantFactoryOption
|
|
104
132
|
|
|
105
133
|
FactoryBot/SyntaxMethods:
|
|
106
134
|
Description: Use shorthands from `FactoryBot::Syntax::Methods` in your specs.
|
|
107
135
|
Enabled: pending
|
|
136
|
+
Include:
|
|
137
|
+
- "**/*_spec.rb"
|
|
138
|
+
- "**/spec/**/*"
|
|
139
|
+
- "**/test/**/*"
|
|
140
|
+
- "**/features/support/factories/**/*.rb"
|
|
108
141
|
SafeAutoCorrect: false
|
|
109
142
|
VersionAdded: '2.7'
|
|
110
143
|
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"
|
|
@@ -47,12 +67,18 @@ module RuboCop
|
|
|
47
67
|
|
|
48
68
|
DEFAULT_NON_IMPLICIT_ASSOCIATION_METHOD_NAMES = %w[
|
|
49
69
|
association
|
|
70
|
+
factory
|
|
50
71
|
sequence
|
|
51
72
|
skip_create
|
|
52
73
|
traits_for_enum
|
|
53
74
|
].freeze
|
|
54
75
|
|
|
55
76
|
RESTRICT_ON_SEND = %i[factory trait].freeze
|
|
77
|
+
KEYWORDS = %i[alias and begin break case class def defined? do
|
|
78
|
+
else elsif end ensure false for if in module
|
|
79
|
+
next nil not or redo rescue retry return self
|
|
80
|
+
super then true undef unless until when while
|
|
81
|
+
yield __FILE__ __LINE__ __ENCODING__].freeze
|
|
56
82
|
|
|
57
83
|
def on_send(node)
|
|
58
84
|
bad_associations_in(node).each do |association|
|
|
@@ -72,6 +98,13 @@ module RuboCop
|
|
|
72
98
|
(send nil? :association sym ...)
|
|
73
99
|
PATTERN
|
|
74
100
|
|
|
101
|
+
# @!method with_strategy_build_option?(node)
|
|
102
|
+
def_node_matcher :with_strategy_build_option?, <<~PATTERN
|
|
103
|
+
(send nil? :association sym ...
|
|
104
|
+
(hash <(pair (sym :strategy) (sym :build)) ...>)
|
|
105
|
+
)
|
|
106
|
+
PATTERN
|
|
107
|
+
|
|
75
108
|
# @!method implicit_association?(node)
|
|
76
109
|
def_node_matcher :implicit_association?, <<~PATTERN
|
|
77
110
|
(send nil? !#non_implicit_association_method_name? ...)
|
|
@@ -103,6 +136,16 @@ module RuboCop
|
|
|
103
136
|
(send nil? :association _ (sym $_)* ...)
|
|
104
137
|
PATTERN
|
|
105
138
|
|
|
139
|
+
# @!method association_names(node)
|
|
140
|
+
def_node_search :association_names, <<~PATTERN
|
|
141
|
+
(send nil? :association $...)
|
|
142
|
+
PATTERN
|
|
143
|
+
|
|
144
|
+
# @!method trait_name(node)
|
|
145
|
+
def_node_search :trait_name, <<~PATTERN
|
|
146
|
+
(send nil? :trait (sym $_) )
|
|
147
|
+
PATTERN
|
|
148
|
+
|
|
106
149
|
def autocorrect(corrector, node)
|
|
107
150
|
if style == :explicit
|
|
108
151
|
autocorrect_to_explicit_style(corrector, node)
|
|
@@ -131,9 +174,22 @@ module RuboCop
|
|
|
131
174
|
|
|
132
175
|
def bad?(node)
|
|
133
176
|
if style == :explicit
|
|
134
|
-
implicit_association?(node)
|
|
177
|
+
implicit_association?(node) &&
|
|
178
|
+
!trait_within_trait?(node)
|
|
135
179
|
else
|
|
136
|
-
explicit_association?(node)
|
|
180
|
+
explicit_association?(node) &&
|
|
181
|
+
!with_strategy_build_option?(node) &&
|
|
182
|
+
!keyword?(node)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def keyword?(node)
|
|
187
|
+
association_names(node).any? do |associations|
|
|
188
|
+
associations.any? do |association|
|
|
189
|
+
next unless association.sym_type?
|
|
190
|
+
|
|
191
|
+
KEYWORDS.include?(association.value)
|
|
192
|
+
end
|
|
137
193
|
end
|
|
138
194
|
end
|
|
139
195
|
|
|
@@ -190,6 +246,14 @@ module RuboCop
|
|
|
190
246
|
end
|
|
191
247
|
options
|
|
192
248
|
end
|
|
249
|
+
|
|
250
|
+
def trait_within_trait?(node)
|
|
251
|
+
factory_node = node.ancestors.reverse.find do |ancestor|
|
|
252
|
+
ancestor.method?(:factory) if ancestor.block_type?
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
trait_name(factory_node).include?(node.method_name)
|
|
256
|
+
end
|
|
193
257
|
end
|
|
194
258
|
end
|
|
195
259
|
end
|
|
@@ -75,6 +75,17 @@ module RuboCop
|
|
|
75
75
|
)
|
|
76
76
|
PATTERN
|
|
77
77
|
|
|
78
|
+
# @!method omit_hash_value?(node)
|
|
79
|
+
def_node_matcher :omit_hash_value?, <<~PATTERN
|
|
80
|
+
(send
|
|
81
|
+
#factory_call? %FACTORY_CALLS
|
|
82
|
+
{sym str send lvar}
|
|
83
|
+
(hash
|
|
84
|
+
<value_omission? ...>
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
PATTERN
|
|
88
|
+
|
|
78
89
|
def self.autocorrect_incompatible_with
|
|
79
90
|
[Style::MethodCallWithArgsParentheses]
|
|
80
91
|
end
|
|
@@ -97,6 +108,7 @@ module RuboCop
|
|
|
97
108
|
def register_offense_with_parentheses(node)
|
|
98
109
|
return if style == :require_parentheses || !node.parenthesized?
|
|
99
110
|
return unless same_line?(node, node.first_argument)
|
|
111
|
+
return if omit_hash_value?(node)
|
|
100
112
|
|
|
101
113
|
add_offense(node.loc.selector,
|
|
102
114
|
message: MSG_OMIT_PARENS) do |corrector|
|
|
@@ -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
|
|
72
|
-
def_node_matcher :
|
|
73
|
-
(block
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
93
|
+
(send #factory_call? :create sym ... `(send ...))
|
|
103
94
|
PATTERN
|
|
104
95
|
|
|
105
96
|
# @!method factory_call(node)
|
|
@@ -113,12 +104,13 @@ module RuboCop
|
|
|
113
104
|
PATTERN
|
|
114
105
|
|
|
115
106
|
# @!method factory_calls_in_array?(node)
|
|
116
|
-
def_node_search :factory_calls_in_array?,
|
|
107
|
+
def_node_search :factory_calls_in_array?, <<~PATTERN
|
|
117
108
|
(array #factory_call+)
|
|
118
109
|
PATTERN
|
|
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:
|
|
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,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module FactoryBot
|
|
6
|
+
# Check for excessive model creation in a list.
|
|
7
|
+
#
|
|
8
|
+
# @example MaxAmount: 10 (default)
|
|
9
|
+
# # We do not allow more than 10 items to be created
|
|
10
|
+
#
|
|
11
|
+
# # bad
|
|
12
|
+
# create_list(:merge_request, 1000, state: :opened)
|
|
13
|
+
#
|
|
14
|
+
# # good
|
|
15
|
+
# create_list(:merge_request, 10, state: :opened)
|
|
16
|
+
#
|
|
17
|
+
# @example MaxAmount: 20
|
|
18
|
+
# # We do not allow more than 20 items to be created
|
|
19
|
+
#
|
|
20
|
+
# # bad
|
|
21
|
+
# create_list(:merge_request, 1000, state: :opened)
|
|
22
|
+
#
|
|
23
|
+
# # good
|
|
24
|
+
# create_list(:merge_request, 15, state: :opened)
|
|
25
|
+
#
|
|
26
|
+
class ExcessiveCreateList < ::RuboCop::Cop::Base
|
|
27
|
+
include ConfigurableExplicitOnly
|
|
28
|
+
|
|
29
|
+
MESSAGE =
|
|
30
|
+
'Avoid using `create_list` with more than %<max_amount>s items.'
|
|
31
|
+
|
|
32
|
+
# @!method create_list?(node)
|
|
33
|
+
def_node_matcher :create_list?, <<~PATTERN
|
|
34
|
+
(send #factory_call? :create_list {sym str} $(int _) ...)
|
|
35
|
+
PATTERN
|
|
36
|
+
|
|
37
|
+
RESTRICT_ON_SEND = %i[create_list].freeze
|
|
38
|
+
|
|
39
|
+
def on_send(node)
|
|
40
|
+
number_node = create_list?(node)
|
|
41
|
+
return unless number_node
|
|
42
|
+
|
|
43
|
+
max_amount = cop_config['MaxAmount']
|
|
44
|
+
return if number_node.value <= max_amount
|
|
45
|
+
|
|
46
|
+
add_offense(number_node, message:
|
|
47
|
+
format(MESSAGE, max_amount: max_amount))
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -14,6 +14,9 @@ module RuboCop
|
|
|
14
14
|
# create(:user)
|
|
15
15
|
# build :user, username: "NAME"
|
|
16
16
|
#
|
|
17
|
+
# # good - namespaced models
|
|
18
|
+
# create('users/internal')
|
|
19
|
+
#
|
|
17
20
|
# @example EnforcedStyle: string
|
|
18
21
|
# # bad
|
|
19
22
|
# create(:user)
|
|
@@ -76,13 +79,17 @@ module RuboCop
|
|
|
76
79
|
private
|
|
77
80
|
|
|
78
81
|
def offense_for_symbol_style?(name)
|
|
79
|
-
name.str_type? && style == :symbol
|
|
82
|
+
name.str_type? && style == :symbol && !namespaced?(name)
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
def offense_for_string_style?(name)
|
|
83
86
|
name.sym_type? && style == :string
|
|
84
87
|
end
|
|
85
88
|
|
|
89
|
+
def namespaced?(name)
|
|
90
|
+
name.value.include?('/')
|
|
91
|
+
end
|
|
92
|
+
|
|
86
93
|
def register_offense(name, prefer)
|
|
87
94
|
add_offense(name,
|
|
88
95
|
message: format(MSG, prefer: style.to_s)) do |corrector|
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
include RuboCop::FactoryBot::Language
|
|
23
|
+
|
|
24
|
+
MSG = 'Do not create a sequence for an id attribute'
|
|
25
|
+
RESTRICT_ON_SEND = %i[sequence].freeze
|
|
26
|
+
|
|
27
|
+
def on_send(node)
|
|
28
|
+
return unless node.receiver.nil? || factory_bot?(node.receiver)
|
|
29
|
+
return unless node.first_argument&.sym_type? &&
|
|
30
|
+
node.first_argument.value == :id
|
|
31
|
+
|
|
32
|
+
add_offense(node) do |corrector|
|
|
33
|
+
range_to_remove = range_by_whole_lines(
|
|
34
|
+
node.source_range,
|
|
35
|
+
include_final_newline: true
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
corrector.remove(range_to_remove)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -4,8 +4,10 @@ require_relative 'factory_bot/association_style'
|
|
|
4
4
|
require_relative 'factory_bot/attribute_defined_statically'
|
|
5
5
|
require_relative 'factory_bot/consistent_parentheses_style'
|
|
6
6
|
require_relative 'factory_bot/create_list'
|
|
7
|
+
require_relative 'factory_bot/excessive_create_list'
|
|
7
8
|
require_relative 'factory_bot/factory_association_with_strategy'
|
|
8
9
|
require_relative 'factory_bot/factory_class_name'
|
|
9
10
|
require_relative 'factory_bot/factory_name_style'
|
|
11
|
+
require_relative 'factory_bot/id_sequence'
|
|
10
12
|
require_relative 'factory_bot/redundant_factory_option'
|
|
11
13
|
require_relative 'factory_bot/syntax_methods'
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module FactoryBot
|
|
5
|
+
module Cop
|
|
6
|
+
# Source and spec generator for new cops
|
|
7
|
+
#
|
|
8
|
+
# This generator will take a cop name and generate a source file
|
|
9
|
+
# and spec file when given a valid qualified cop name.
|
|
10
|
+
# @api private
|
|
11
|
+
class Generator < RuboCop::Cop::Generator
|
|
12
|
+
def todo
|
|
13
|
+
<<~TODO
|
|
14
|
+
Do 4 steps:
|
|
15
|
+
1. Modify the description of #{badge} in config/default.yml
|
|
16
|
+
2. Implement your new cop in the generated file!
|
|
17
|
+
3. Add an entry about new cop to CHANGELOG.md
|
|
18
|
+
4. Commit your new cop with a message such as
|
|
19
|
+
e.g. "Add new `#{badge}` cop"
|
|
20
|
+
TODO
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
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.
|
|
4
|
+
version: 2.26.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Backus
|
|
@@ -9,10 +9,10 @@ authors:
|
|
|
9
9
|
- Phil Pirozhkov
|
|
10
10
|
- Maxim Krizhanovsky
|
|
11
11
|
- Andrew Bromwich
|
|
12
|
-
autorequire:
|
|
12
|
+
autorequire:
|
|
13
13
|
bindir: bin
|
|
14
14
|
cert_chain: []
|
|
15
|
-
date:
|
|
15
|
+
date: 2024-06-11 00:00:00.000000000 Z
|
|
16
16
|
dependencies:
|
|
17
17
|
- !ruby/object:Gem::Dependency
|
|
18
18
|
name: rubocop
|
|
@@ -20,18 +20,18 @@ dependencies:
|
|
|
20
20
|
requirements:
|
|
21
21
|
- - "~>"
|
|
22
22
|
- !ruby/object:Gem::Version
|
|
23
|
-
version: '1.
|
|
23
|
+
version: '1.61'
|
|
24
24
|
type: :runtime
|
|
25
25
|
prerelease: false
|
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
|
27
27
|
requirements:
|
|
28
28
|
- - "~>"
|
|
29
29
|
- !ruby/object:Gem::Version
|
|
30
|
-
version: '1.
|
|
30
|
+
version: '1.61'
|
|
31
31
|
description: |
|
|
32
32
|
Code style checking for factory_bot files.
|
|
33
33
|
A plugin for the RuboCop code style enforcing & linting tool.
|
|
34
|
-
email:
|
|
34
|
+
email:
|
|
35
35
|
executables: []
|
|
36
36
|
extensions: []
|
|
37
37
|
extra_rdoc_files:
|
|
@@ -48,14 +48,17 @@ files:
|
|
|
48
48
|
- lib/rubocop/cop/factory_bot/attribute_defined_statically.rb
|
|
49
49
|
- lib/rubocop/cop/factory_bot/consistent_parentheses_style.rb
|
|
50
50
|
- lib/rubocop/cop/factory_bot/create_list.rb
|
|
51
|
+
- lib/rubocop/cop/factory_bot/excessive_create_list.rb
|
|
51
52
|
- lib/rubocop/cop/factory_bot/factory_association_with_strategy.rb
|
|
52
53
|
- lib/rubocop/cop/factory_bot/factory_class_name.rb
|
|
53
54
|
- lib/rubocop/cop/factory_bot/factory_name_style.rb
|
|
55
|
+
- lib/rubocop/cop/factory_bot/id_sequence.rb
|
|
54
56
|
- lib/rubocop/cop/factory_bot/mixin/configurable_explicit_only.rb
|
|
55
57
|
- lib/rubocop/cop/factory_bot/redundant_factory_option.rb
|
|
56
58
|
- lib/rubocop/cop/factory_bot/syntax_methods.rb
|
|
57
59
|
- lib/rubocop/cop/factory_bot_cops.rb
|
|
58
60
|
- lib/rubocop/factory_bot/config_formatter.rb
|
|
61
|
+
- lib/rubocop/factory_bot/cop/generator.rb
|
|
59
62
|
- lib/rubocop/factory_bot/description_extractor.rb
|
|
60
63
|
- lib/rubocop/factory_bot/factory_bot.rb
|
|
61
64
|
- lib/rubocop/factory_bot/language.rb
|
|
@@ -67,7 +70,7 @@ metadata:
|
|
|
67
70
|
changelog_uri: https://github.com/rubocop/rubocop-factory_bot/blob/master/CHANGELOG.md
|
|
68
71
|
documentation_uri: https://docs.rubocop.org/rubocop-factory_bot/
|
|
69
72
|
rubygems_mfa_required: 'true'
|
|
70
|
-
post_install_message:
|
|
73
|
+
post_install_message:
|
|
71
74
|
rdoc_options: []
|
|
72
75
|
require_paths:
|
|
73
76
|
- lib
|
|
@@ -82,8 +85,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
82
85
|
- !ruby/object:Gem::Version
|
|
83
86
|
version: '0'
|
|
84
87
|
requirements: []
|
|
85
|
-
rubygems_version: 3.
|
|
86
|
-
signing_key:
|
|
88
|
+
rubygems_version: 3.5.9
|
|
89
|
+
signing_key:
|
|
87
90
|
specification_version: 4
|
|
88
91
|
summary: Code style checking for factory_bot files
|
|
89
92
|
test_files: []
|