rubocop-rspec 2.21.0 → 2.23.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 +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +1 -1
- data/config/default.yml +37 -16
- data/config/obsoletion.yml +6 -0
- data/lib/rubocop/cop/rspec/empty_example_group.rb +3 -0
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +11 -4
- data/lib/rubocop/cop/rspec/expect_actual.rb +2 -2
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +25 -118
- data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +40 -107
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +30 -250
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +19 -46
- data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +23 -64
- data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +45 -79
- data/lib/rubocop/cop/rspec/focus.rb +13 -0
- data/lib/rubocop/cop/rspec/indexed_let.rb +32 -1
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +4 -0
- data/lib/rubocop/cop/rspec/named_subject.rb +1 -1
- data/lib/rubocop/cop/rspec/pending.rb +12 -2
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +3 -3
- data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +92 -0
- data/lib/rubocop/cop/rspec/receive_messages.rb +155 -0
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +1 -1
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +2 -0
- data/lib/rubocop/rspec/config_formatter.rb +6 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +1 -3
- metadata +18 -4
- data/lib/rubocop/rspec/factory_bot/language.rb +0 -37
- data/lib/rubocop/rspec/factory_bot.rb +0 -64
@@ -4,256 +4,36 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module FactoryBot
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# #
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# #
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# #
|
19
|
-
#
|
20
|
-
#
|
21
|
-
# #
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# #
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# #
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# #
|
32
|
-
#
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
include RuboCop::RSpec::FactoryBot::Language
|
38
|
-
|
39
|
-
MSG_CREATE_LIST = 'Prefer create_list.'
|
40
|
-
MSG_N_TIMES = 'Prefer %<number>s.times.'
|
41
|
-
RESTRICT_ON_SEND = %i[create_list].freeze
|
42
|
-
|
43
|
-
# @!method array_new_or_n_times_block?(node)
|
44
|
-
def_node_matcher :array_new_or_n_times_block?, <<-PATTERN
|
45
|
-
(block
|
46
|
-
{
|
47
|
-
(send (const {nil? | cbase} :Array) :new (int _)) |
|
48
|
-
(send (int _) :times)
|
49
|
-
}
|
50
|
-
...
|
51
|
-
)
|
52
|
-
PATTERN
|
53
|
-
|
54
|
-
# @!method block_with_arg_and_used?(node)
|
55
|
-
def_node_matcher :block_with_arg_and_used?, <<-PATTERN
|
56
|
-
(block
|
57
|
-
_
|
58
|
-
(args (arg _value))
|
59
|
-
`_value
|
60
|
-
)
|
61
|
-
PATTERN
|
62
|
-
|
63
|
-
# @!method arguments_include_method_call?(node)
|
64
|
-
def_node_matcher :arguments_include_method_call?, <<-PATTERN
|
65
|
-
(send ${nil? #factory_bot?} :create (sym $_) `$(send ...))
|
66
|
-
PATTERN
|
67
|
-
|
68
|
-
# @!method factory_call(node)
|
69
|
-
def_node_matcher :factory_call, <<-PATTERN
|
70
|
-
(send ${nil? #factory_bot?} :create (sym $_) $...)
|
71
|
-
PATTERN
|
72
|
-
|
73
|
-
# @!method factory_list_call(node)
|
74
|
-
def_node_matcher :factory_list_call, <<-PATTERN
|
75
|
-
(send {nil? #factory_bot?} :create_list (sym _) (int $_) ...)
|
76
|
-
PATTERN
|
77
|
-
|
78
|
-
def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler
|
79
|
-
return unless style == :create_list
|
80
|
-
|
81
|
-
return unless array_new_or_n_times_block?(node)
|
82
|
-
return if block_with_arg_and_used?(node)
|
83
|
-
return unless node.body
|
84
|
-
return if arguments_include_method_call?(node.body)
|
85
|
-
return unless contains_only_factory?(node.body)
|
86
|
-
|
87
|
-
add_offense(node.send_node, message: MSG_CREATE_LIST) do |corrector|
|
88
|
-
CreateListCorrector.new(node.send_node).call(corrector)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def on_send(node)
|
93
|
-
return unless style == :n_times
|
94
|
-
|
95
|
-
factory_list_call(node) do |count|
|
96
|
-
message = format(MSG_N_TIMES, number: count)
|
97
|
-
add_offense(node.loc.selector, message: message) do |corrector|
|
98
|
-
TimesCorrector.new(node).call(corrector)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
private
|
104
|
-
|
105
|
-
def contains_only_factory?(node)
|
106
|
-
if node.block_type?
|
107
|
-
factory_call(node.send_node)
|
108
|
-
else
|
109
|
-
factory_call(node)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# :nodoc
|
114
|
-
module Corrector
|
115
|
-
private
|
116
|
-
|
117
|
-
def build_options_string(options)
|
118
|
-
options.map(&:source).join(', ')
|
119
|
-
end
|
120
|
-
|
121
|
-
def format_method_call(node, method, arguments)
|
122
|
-
if node.block_type? || node.parenthesized?
|
123
|
-
"#{method}(#{arguments})"
|
124
|
-
else
|
125
|
-
"#{method} #{arguments}"
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def format_receiver(receiver)
|
130
|
-
return '' unless receiver
|
131
|
-
|
132
|
-
"#{receiver.source}."
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# :nodoc
|
137
|
-
class TimesCorrector
|
138
|
-
include Corrector
|
139
|
-
|
140
|
-
def initialize(node)
|
141
|
-
@node = node
|
142
|
-
end
|
143
|
-
|
144
|
-
def call(corrector)
|
145
|
-
replacement = generate_n_times_block(node)
|
146
|
-
corrector.replace(node.block_node || node, replacement)
|
147
|
-
end
|
148
|
-
|
149
|
-
private
|
150
|
-
|
151
|
-
attr_reader :node
|
152
|
-
|
153
|
-
def generate_n_times_block(node)
|
154
|
-
factory, count, *options = node.arguments
|
155
|
-
|
156
|
-
arguments = factory.source
|
157
|
-
options = build_options_string(options)
|
158
|
-
arguments += ", #{options}" unless options.empty?
|
159
|
-
|
160
|
-
replacement = format_receiver(node.receiver)
|
161
|
-
replacement += format_method_call(node, 'create', arguments)
|
162
|
-
replacement += " #{factory_call_block_source}" if node.block_node
|
163
|
-
"#{count.source}.times { #{replacement} }"
|
164
|
-
end
|
165
|
-
|
166
|
-
def factory_call_block_source
|
167
|
-
node.block_node.location.begin.with(
|
168
|
-
end_pos: node.block_node.location.end.end_pos
|
169
|
-
).source
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# :nodoc:
|
174
|
-
class CreateListCorrector
|
175
|
-
include Corrector
|
176
|
-
|
177
|
-
def initialize(node)
|
178
|
-
@node = node.parent
|
179
|
-
end
|
180
|
-
|
181
|
-
def call(corrector)
|
182
|
-
replacement = if node.body.block_type?
|
183
|
-
call_with_block_replacement(node)
|
184
|
-
else
|
185
|
-
call_replacement(node)
|
186
|
-
end
|
187
|
-
|
188
|
-
corrector.replace(node, replacement)
|
189
|
-
end
|
190
|
-
|
191
|
-
private
|
192
|
-
|
193
|
-
attr_reader :node
|
194
|
-
|
195
|
-
def call_with_block_replacement(node)
|
196
|
-
block = node.body
|
197
|
-
arguments = build_arguments(block, count_from(node))
|
198
|
-
replacement = format_receiver(block.receiver)
|
199
|
-
replacement += format_method_call(block, 'create_list', arguments)
|
200
|
-
replacement += format_block(block)
|
201
|
-
replacement
|
202
|
-
end
|
203
|
-
|
204
|
-
def build_arguments(node, count)
|
205
|
-
factory, *options = *node.send_node.arguments
|
206
|
-
|
207
|
-
arguments = ":#{factory.value}, #{count}"
|
208
|
-
options = build_options_string(options)
|
209
|
-
arguments += ", #{options}" unless options.empty?
|
210
|
-
arguments
|
211
|
-
end
|
212
|
-
|
213
|
-
def call_replacement(node)
|
214
|
-
block = node.body
|
215
|
-
factory, *options = *block.arguments
|
216
|
-
|
217
|
-
arguments = "#{factory.source}, #{count_from(node)}"
|
218
|
-
options = build_options_string(options)
|
219
|
-
arguments += ", #{options}" unless options.empty?
|
220
|
-
|
221
|
-
replacement = format_receiver(block.receiver)
|
222
|
-
replacement += format_method_call(block, 'create_list', arguments)
|
223
|
-
replacement
|
224
|
-
end
|
225
|
-
|
226
|
-
def count_from(node)
|
227
|
-
count_node =
|
228
|
-
if node.receiver.int_type?
|
229
|
-
node.receiver
|
230
|
-
else
|
231
|
-
node.send_node.first_argument
|
232
|
-
end
|
233
|
-
count_node.source
|
234
|
-
end
|
235
|
-
|
236
|
-
def format_block(node)
|
237
|
-
if node.body.begin_type?
|
238
|
-
format_multiline_block(node)
|
239
|
-
else
|
240
|
-
format_singleline_block(node)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
def format_multiline_block(node)
|
245
|
-
indent = ' ' * node.body.loc.column
|
246
|
-
indent_end = ' ' * node.parent.loc.column
|
247
|
-
" do #{node.arguments.source}\n" \
|
248
|
-
"#{indent}#{node.body.source}\n" \
|
249
|
-
"#{indent_end}end"
|
250
|
-
end
|
251
|
-
|
252
|
-
def format_singleline_block(node)
|
253
|
-
" { #{node.arguments.source} #{node.body.source} }"
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Checks for create_list usage.
|
9
|
+
# #
|
10
|
+
# # This cop can be configured using the `EnforcedStyle` option
|
11
|
+
# #
|
12
|
+
# # @example `EnforcedStyle: create_list` (default)
|
13
|
+
# # # bad
|
14
|
+
# # 3.times { create :user }
|
15
|
+
# #
|
16
|
+
# # # good
|
17
|
+
# # create_list :user, 3
|
18
|
+
# #
|
19
|
+
# # # bad
|
20
|
+
# # 3.times { create :user, age: 18 }
|
21
|
+
# #
|
22
|
+
# # # good - index is used to alter the created models attributes
|
23
|
+
# # 3.times { |n| create :user, age: n }
|
24
|
+
# #
|
25
|
+
# # # good - contains a method call, may return different values
|
26
|
+
# # 3.times { create :user, age: rand }
|
27
|
+
# #
|
28
|
+
# # @example `EnforcedStyle: n_times`
|
29
|
+
# # # bad
|
30
|
+
# # create_list :user, 3
|
31
|
+
# #
|
32
|
+
# # # good
|
33
|
+
# # 3.times { create :user }
|
34
|
+
# #
|
35
|
+
# class CreateList < ::RuboCop::Cop::Base; end
|
36
|
+
CreateList = ::RuboCop::Cop::FactoryBot::CreateList
|
257
37
|
end
|
258
38
|
end
|
259
39
|
end
|
@@ -4,52 +4,25 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module FactoryBot
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# #
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# #
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
|
27
|
-
'constant.'
|
28
|
-
ALLOWED_CONSTANTS = %w[Hash OpenStruct].freeze
|
29
|
-
RESTRICT_ON_SEND = %i[factory].freeze
|
30
|
-
|
31
|
-
# @!method class_name(node)
|
32
|
-
def_node_matcher :class_name, <<~PATTERN
|
33
|
-
(send _ :factory _ (hash <(pair (sym :class) $(const ...)) ...>))
|
34
|
-
PATTERN
|
35
|
-
|
36
|
-
def on_send(node)
|
37
|
-
class_name(node) do |cn|
|
38
|
-
next if allowed?(cn.const_name)
|
39
|
-
|
40
|
-
msg = format(MSG, class_name: cn.const_name)
|
41
|
-
add_offense(cn, message: msg) do |corrector|
|
42
|
-
corrector.replace(cn, "'#{cn.source}'")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def allowed?(const_name)
|
50
|
-
ALLOWED_CONSTANTS.include?(const_name)
|
51
|
-
end
|
52
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Use string value when setting the class attribute explicitly.
|
9
|
+
# #
|
10
|
+
# # This cop would promote faster tests by lazy-loading of
|
11
|
+
# # application files. Also, this could help you suppress potential
|
12
|
+
# # bugs in combination with external libraries by avoiding a preload
|
13
|
+
# # of application files from the factory files.
|
14
|
+
# #
|
15
|
+
# # @example
|
16
|
+
# # # bad
|
17
|
+
# # factory :foo, class: Foo do
|
18
|
+
# # end
|
19
|
+
# #
|
20
|
+
# # # good
|
21
|
+
# # factory :foo, class: 'Foo' do
|
22
|
+
# # end
|
23
|
+
# #
|
24
|
+
# class FactoryClassName < ::RuboCop::Cop::Base; end
|
25
|
+
FactoryClassName = ::RuboCop::Cop::FactoryBot::FactoryClassName
|
53
26
|
end
|
54
27
|
end
|
55
28
|
end
|
@@ -4,70 +4,29 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module FactoryBot
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# #
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# #
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# #
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# #
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
include RuboCop::RSpec::FactoryBot::Language
|
31
|
-
|
32
|
-
MSG = 'Use %<prefer>s to refer to a factory.'
|
33
|
-
FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
|
34
|
-
RESTRICT_ON_SEND = FACTORY_CALLS
|
35
|
-
|
36
|
-
# @!method factory_call(node)
|
37
|
-
def_node_matcher :factory_call, <<-PATTERN
|
38
|
-
(send
|
39
|
-
{#factory_bot? nil?} %FACTORY_CALLS
|
40
|
-
${str sym} ...
|
41
|
-
)
|
42
|
-
PATTERN
|
43
|
-
|
44
|
-
def on_send(node)
|
45
|
-
factory_call(node) do |name|
|
46
|
-
if offense_for_symbol_style?(name)
|
47
|
-
register_offense(name, name.value.to_sym.inspect)
|
48
|
-
elsif offense_for_string_style?(name)
|
49
|
-
register_offense(name, name.value.to_s.inspect)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def offense_for_symbol_style?(name)
|
57
|
-
name.str_type? && style == :symbol
|
58
|
-
end
|
59
|
-
|
60
|
-
def offense_for_string_style?(name)
|
61
|
-
name.sym_type? && style == :string
|
62
|
-
end
|
63
|
-
|
64
|
-
def register_offense(name, prefer)
|
65
|
-
add_offense(name,
|
66
|
-
message: format(MSG, prefer: style.to_s)) do |corrector|
|
67
|
-
corrector.replace(name, prefer)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Checks for name style for argument of FactoryBot::Syntax::Methods.
|
9
|
+
# #
|
10
|
+
# # @example EnforcedStyle: symbol (default)
|
11
|
+
# # # bad
|
12
|
+
# # create('user')
|
13
|
+
# # build "user", username: "NAME"
|
14
|
+
# #
|
15
|
+
# # # good
|
16
|
+
# # create(:user)
|
17
|
+
# # build :user, username: "NAME"
|
18
|
+
# #
|
19
|
+
# # @example EnforcedStyle: string
|
20
|
+
# # # bad
|
21
|
+
# # create(:user)
|
22
|
+
# # build :user, username: "NAME"
|
23
|
+
# #
|
24
|
+
# # # good
|
25
|
+
# # create('user')
|
26
|
+
# # build "user", username: "NAME"
|
27
|
+
# #
|
28
|
+
# class FactoryNameStyle < ::RuboCop::Cop::Base; end
|
29
|
+
FactoryNameStyle = ::RuboCop::Cop::FactoryBot::FactoryNameStyle
|
71
30
|
end
|
72
31
|
end
|
73
32
|
end
|
@@ -4,85 +4,51 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module FactoryBot
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# `
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# #
|
40
|
-
#
|
41
|
-
# FactoryBot.
|
42
|
-
# FactoryBot.
|
43
|
-
#
|
44
|
-
# #
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
include RangeHelp
|
53
|
-
include RuboCop::RSpec::FactoryBot::Language
|
54
|
-
|
55
|
-
MSG = 'Use `%<method>s` from `FactoryBot::Syntax::Methods`.'
|
56
|
-
|
57
|
-
RESTRICT_ON_SEND = RuboCop::RSpec::FactoryBot::Language::METHODS
|
58
|
-
|
59
|
-
def on_send(node)
|
60
|
-
return unless factory_bot?(node.receiver)
|
61
|
-
return unless inside_example_group?(node)
|
62
|
-
|
63
|
-
message = format(MSG, method: node.method_name)
|
64
|
-
|
65
|
-
add_offense(crime_scene(node), message: message) do |corrector|
|
66
|
-
corrector.remove(offense(node))
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def crime_scene(node)
|
73
|
-
range_between(
|
74
|
-
node.source_range.begin_pos,
|
75
|
-
node.loc.selector.end_pos
|
76
|
-
)
|
77
|
-
end
|
78
|
-
|
79
|
-
def offense(node)
|
80
|
-
range_between(
|
81
|
-
node.source_range.begin_pos,
|
82
|
-
node.loc.selector.begin_pos
|
83
|
-
)
|
84
|
-
end
|
85
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Use shorthands from `FactoryBot::Syntax::Methods` in your specs.
|
9
|
+
# #
|
10
|
+
# # @safety
|
11
|
+
# # The autocorrection is marked as unsafe because the cop
|
12
|
+
# # cannot verify whether you already include
|
13
|
+
# # `FactoryBot::Syntax::Methods` in your test suite.
|
14
|
+
# #
|
15
|
+
# # If you're using Rails, add the following configuration to
|
16
|
+
# # `spec/support/factory_bot.rb` and be sure to require that file
|
17
|
+
# # in `rails_helper.rb`:
|
18
|
+
# #
|
19
|
+
# # [source,ruby]
|
20
|
+
# # ----
|
21
|
+
# # RSpec.configure do |config|
|
22
|
+
# # config.include FactoryBot::Syntax::Methods
|
23
|
+
# # end
|
24
|
+
# # ----
|
25
|
+
# #
|
26
|
+
# # If you're not using Rails:
|
27
|
+
# #
|
28
|
+
# # [source,ruby]
|
29
|
+
# # ----
|
30
|
+
# # RSpec.configure do |config|
|
31
|
+
# # config.include FactoryBot::Syntax::Methods
|
32
|
+
# #
|
33
|
+
# # config.before(:suite) do
|
34
|
+
# # FactoryBot.find_definitions
|
35
|
+
# # end
|
36
|
+
# # end
|
37
|
+
# # ----
|
38
|
+
# #
|
39
|
+
# # @example
|
40
|
+
# # # bad
|
41
|
+
# # FactoryBot.create(:bar)
|
42
|
+
# # FactoryBot.build(:bar)
|
43
|
+
# # FactoryBot.attributes_for(:bar)
|
44
|
+
# #
|
45
|
+
# # # good
|
46
|
+
# # create(:bar)
|
47
|
+
# # build(:bar)
|
48
|
+
# # attributes_for(:bar)
|
49
|
+
# #
|
50
|
+
# class SyntaxMethods < ::RuboCop::Cop::Base; end
|
51
|
+
SyntaxMethods = ::RuboCop::Cop::FactoryBot::SyntaxMethods
|
86
52
|
end
|
87
53
|
end
|
88
54
|
end
|
@@ -34,6 +34,18 @@ module RuboCop
|
|
34
34
|
# # good
|
35
35
|
# describe 'test' do; end
|
36
36
|
#
|
37
|
+
# # bad
|
38
|
+
# shared_examples 'test', focus: true do; end
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# shared_examples 'test' do; end
|
42
|
+
#
|
43
|
+
# # bad
|
44
|
+
# shared_context 'test', focus: true do; end
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# shared_context 'test' do; end
|
48
|
+
#
|
37
49
|
# # bad (does not support autocorrection)
|
38
50
|
# focus 'test' do; end
|
39
51
|
#
|
@@ -51,6 +63,7 @@ module RuboCop
|
|
51
63
|
#Examples.regular
|
52
64
|
#Examples.skipped
|
53
65
|
#Examples.pending
|
66
|
+
#SharedGroups.all
|
54
67
|
}
|
55
68
|
PATTERN
|
56
69
|
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
8
8
|
# It makes reading the test harder because it's not clear what exactly
|
9
9
|
# is tested by this particular example.
|
10
10
|
#
|
11
|
+
# The configurable options `AllowedIdentifiers` and `AllowedPatterns`
|
12
|
+
# will also read those set in `Naming/VariableNumber`.
|
13
|
+
#
|
11
14
|
# @example `Max: 1 (default)`
|
12
15
|
# # bad
|
13
16
|
# let(:item_1) { create(:item) }
|
@@ -31,7 +34,20 @@ module RuboCop
|
|
31
34
|
# let(:item_1) { create(:item) }
|
32
35
|
# let(:item_2) { create(:item) }
|
33
36
|
#
|
37
|
+
# @example `AllowedIdentifiers: ['item_1', 'item_2']`
|
38
|
+
# # good
|
39
|
+
# let(:item_1) { create(:item) }
|
40
|
+
# let(:item_2) { create(:item) }
|
41
|
+
#
|
42
|
+
# @example `AllowedPatterns: ['item']`
|
43
|
+
# # good
|
44
|
+
# let(:item_1) { create(:item) }
|
45
|
+
# let(:item_2) { create(:item) }
|
46
|
+
#
|
34
47
|
class IndexedLet < Base
|
48
|
+
include AllowedIdentifiers
|
49
|
+
include AllowedPattern
|
50
|
+
|
35
51
|
MSG = 'This `let` statement uses index in its name. Please give it ' \
|
36
52
|
'a meaningful name.'
|
37
53
|
|
@@ -69,12 +85,27 @@ module RuboCop
|
|
69
85
|
end
|
70
86
|
|
71
87
|
def indexed_let?(node)
|
72
|
-
let?(node) &&
|
88
|
+
let?(node) &&
|
89
|
+
SUFFIX_INDEX_REGEX.match?(let_name(node)) &&
|
90
|
+
!allowed_identifier?(let_name(node).to_s) &&
|
91
|
+
!matches_allowed_pattern?(let_name(node).to_s)
|
73
92
|
end
|
74
93
|
|
75
94
|
def let_name_stripped_index(node)
|
76
95
|
let_name(node).to_s.gsub(INDEX_REGEX, '')
|
77
96
|
end
|
97
|
+
|
98
|
+
def cop_config_patterns_values
|
99
|
+
Array(config.for_cop('Naming/VariableNumber')
|
100
|
+
.fetch('AllowedPatterns', [])) +
|
101
|
+
Array(cop_config.fetch('AllowedPatterns', []))
|
102
|
+
end
|
103
|
+
|
104
|
+
def allowed_identifiers
|
105
|
+
Array(config.for_cop('Naming/VariableNumber')
|
106
|
+
.fetch('AllowedIdentifiers', [])) +
|
107
|
+
Array(cop_config.fetch('AllowedIdentifiers', []))
|
108
|
+
end
|
78
109
|
end
|
79
110
|
end
|
80
111
|
end
|
@@ -48,7 +48,7 @@ module RuboCop
|
|
48
48
|
class InstanceVariable < Base
|
49
49
|
include TopLevelGroup
|
50
50
|
|
51
|
-
MSG = 'Avoid instance variables
|
51
|
+
MSG = 'Avoid instance variables - use let, ' \
|
52
52
|
'a method call, or a local variable (if possible).'
|
53
53
|
|
54
54
|
# @!method dynamic_class?(node)
|