rubocop-rspec 2.20.0 → 2.22.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 +12 -0
- data/config/obsoletion.yml +6 -0
- data/lib/rubocop/cop/rspec/change_by_zero.rb +31 -21
- 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/file_path.rb +1 -1
- data/lib/rubocop/cop/rspec/indexed_let.rb +8 -3
- data/lib/rubocop/cop/rspec/match_array.rb +1 -1
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +4 -2
- 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 -6
- data/lib/rubocop/rspec/factory_bot/language.rb +0 -37
- data/lib/rubocop/rspec/factory_bot.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e786386e218833ac7f78af9ffcadadb6bf6c822a31b455cac1567152fd3bc9c0
|
4
|
+
data.tar.gz: 384170b4ae3a06c05b30855ae9361057c53226b40b924d4ec1d49c0d15195658
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 554345811f404b27a39fd522e0085022c39147e0487f04ea77ed7887002451af112e2ddc45ad94841c0a4201a76f37fbfb7a2e64aed3c7efa91cddf1a30843bc
|
7
|
+
data.tar.gz: 22882a56ddf03c55d6eaf299fb05197c835049054231e6d7798e2ca3eac5cbd9840eeada823a12431b00efd37289a8353792dfe3c8f653b2606f9ccda480615a
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.22.0 (2023-05-06)
|
6
|
+
|
7
|
+
- Extract factory_bot cops to a separate repository, [`rubocop-factory_bot`](https://github.com/rubocop/rubocop-factory_bot). The `rubocop-factory_bot` repository is a dependency of `rubocop-rspec` and the factory_bot cops are aliased (`RSpec/FactoryBot/Foo` == `FactoryBot/Foo`) until v3.0 is released, so the change will be invisible to users until then. ([@ydah])
|
8
|
+
|
9
|
+
## 2.21.0 (2023-05-05)
|
10
|
+
|
11
|
+
- Fix a false positive in `RSpec/IndexedLet` with suffixes after index-like numbers. ([@pirj])
|
12
|
+
- Fix an error for `RSpec/Rails/HaveHttpStatus` with comparison with strings containing non-numeric characters. ([@ydah])
|
13
|
+
- Fix an error for `RSpec/MatchArray` when `match_array` with no argument. ([@ydah])
|
14
|
+
- Add support `a_block_changing` and `changing` for `RSpec/ChangeByZero`. ([@ydah])
|
15
|
+
- Drop Ruby 2.6 support. ([@ydah])
|
16
|
+
|
5
17
|
## 2.20.0 (2023-04-18)
|
6
18
|
|
7
19
|
- Add new `RSpec/IndexedLet` cop. ([@dmitrytsepelev])
|
data/config/obsoletion.yml
CHANGED
@@ -21,3 +21,9 @@ renamed:
|
|
21
21
|
RSpec/Capybara/SpecificFinders: Capybara/SpecificFinders
|
22
22
|
RSpec/Capybara/SpecificMatcher: Capybara/SpecificMatcher
|
23
23
|
RSpec/Capybara/VisibilityMatcher: Capybara/VisibilityMatcher
|
24
|
+
RSpec/FactoryBot/AttributeDefinedStatically: FactoryBot/AttributeDefinedStatically
|
25
|
+
RSpec/FactoryBot/ConsistentParenthesesStyle: FactoryBot/ConsistentParenthesesStyle
|
26
|
+
RSpec/FactoryBot/CreateList: FactoryBot/CreateList
|
27
|
+
RSpec/FactoryBot/FactoryClassName: FactoryBot/FactoryClassName
|
28
|
+
RSpec/FactoryBot/FactoryNameStyle: FactoryBot/FactoryNameStyle
|
29
|
+
RSpec/FactoryBot/SyntaxMethods: FactoryBot/SyntaxMethods
|
@@ -59,15 +59,16 @@ module RuboCop
|
|
59
59
|
#
|
60
60
|
class ChangeByZero < Base
|
61
61
|
extend AutoCorrector
|
62
|
-
MSG = 'Prefer `not_to change` over `to
|
62
|
+
MSG = 'Prefer `not_to change` over `to %<method>s.by(0)`.'
|
63
63
|
MSG_COMPOUND = 'Prefer %<preferred>s with compound expectations ' \
|
64
|
-
'over
|
65
|
-
|
64
|
+
'over `%<method>s.by(0)`.'
|
65
|
+
CHANGE_METHODS = Set[:change, :a_block_changing, :changing].freeze
|
66
|
+
RESTRICT_ON_SEND = CHANGE_METHODS.freeze
|
66
67
|
|
67
68
|
# @!method expect_change_with_arguments(node)
|
68
69
|
def_node_matcher :expect_change_with_arguments, <<-PATTERN
|
69
70
|
(send
|
70
|
-
(send nil?
|
71
|
+
$(send nil? CHANGE_METHODS ...) :by
|
71
72
|
(int 0))
|
72
73
|
PATTERN
|
73
74
|
|
@@ -75,48 +76,61 @@ module RuboCop
|
|
75
76
|
def_node_matcher :expect_change_with_block, <<-PATTERN
|
76
77
|
(send
|
77
78
|
(block
|
78
|
-
(send nil?
|
79
|
+
$(send nil? CHANGE_METHODS)
|
79
80
|
(args)
|
80
|
-
(send (...)
|
81
|
+
(send (...) _)) :by
|
81
82
|
(int 0))
|
82
83
|
PATTERN
|
83
84
|
|
84
85
|
# @!method change_nodes(node)
|
85
86
|
def_node_search :change_nodes, <<-PATTERN
|
86
|
-
$(send nil?
|
87
|
+
$(send nil? CHANGE_METHODS ...)
|
87
88
|
PATTERN
|
88
89
|
|
89
90
|
def on_send(node)
|
90
|
-
expect_change_with_arguments(node.parent) do
|
91
|
-
|
91
|
+
expect_change_with_arguments(node.parent) do |change|
|
92
|
+
register_offense(node.parent, change)
|
92
93
|
end
|
93
94
|
|
94
|
-
expect_change_with_block(node.parent.parent) do
|
95
|
-
|
95
|
+
expect_change_with_block(node.parent.parent) do |change|
|
96
|
+
register_offense(node.parent.parent, change)
|
96
97
|
end
|
97
98
|
end
|
98
99
|
|
99
100
|
private
|
100
101
|
|
101
|
-
|
102
|
-
|
102
|
+
# rubocop:disable Metrics/MethodLength
|
103
|
+
def register_offense(node, change_node)
|
103
104
|
if compound_expectations?(node)
|
104
|
-
add_offense(
|
105
|
+
add_offense(node.source_range,
|
106
|
+
message: message_compound(change_node)) do |corrector|
|
105
107
|
autocorrect_compound(corrector, node)
|
106
108
|
end
|
107
109
|
else
|
108
|
-
add_offense(
|
109
|
-
|
110
|
+
add_offense(node.source_range,
|
111
|
+
message: message(change_node)) do |corrector|
|
112
|
+
autocorrect(corrector, node, change_node)
|
110
113
|
end
|
111
114
|
end
|
112
115
|
end
|
116
|
+
# rubocop:enable Metrics/MethodLength
|
113
117
|
|
114
118
|
def compound_expectations?(node)
|
115
119
|
%i[and or & |].include?(node.parent.method_name)
|
116
120
|
end
|
117
121
|
|
118
|
-
def
|
122
|
+
def message(change_node)
|
123
|
+
format(MSG, method: change_node.method_name)
|
124
|
+
end
|
125
|
+
|
126
|
+
def message_compound(change_node)
|
127
|
+
format(MSG_COMPOUND, preferred: preferred_method,
|
128
|
+
method: change_node.method_name)
|
129
|
+
end
|
130
|
+
|
131
|
+
def autocorrect(corrector, node, change_node)
|
119
132
|
corrector.replace(node.parent.loc.selector, 'not_to')
|
133
|
+
corrector.replace(change_node.loc.selector, 'change')
|
120
134
|
range = node.loc.dot.with(end_pos: node.source_range.end_pos)
|
121
135
|
corrector.remove(range)
|
122
136
|
end
|
@@ -135,10 +149,6 @@ module RuboCop
|
|
135
149
|
cop_config['NegatedMatcher']
|
136
150
|
end
|
137
151
|
|
138
|
-
def message_compound
|
139
|
-
format(MSG_COMPOUND, preferred: preferred_method)
|
140
|
-
end
|
141
|
-
|
142
152
|
def preferred_method
|
143
153
|
negated_matcher ? "`#{negated_matcher}`" : 'negated matchers'
|
144
154
|
end
|
@@ -4,124 +4,31 @@ 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
|
-
# @!method value_matcher(node)
|
34
|
-
def_node_matcher :value_matcher, <<-PATTERN
|
35
|
-
(send _ !#reserved_method? $...)
|
36
|
-
PATTERN
|
37
|
-
|
38
|
-
# @!method factory_attributes(node)
|
39
|
-
def_node_matcher :factory_attributes, <<-PATTERN
|
40
|
-
(block (send _ #attribute_defining_method? ...) _ { (begin $...) $(send ...) } )
|
41
|
-
PATTERN
|
42
|
-
|
43
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
44
|
-
attributes = factory_attributes(node) || []
|
45
|
-
attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective
|
46
|
-
|
47
|
-
attributes.each do |attribute|
|
48
|
-
next unless offensive_receiver?(attribute.receiver, node)
|
49
|
-
next if proc?(attribute) || association?(attribute.first_argument)
|
50
|
-
|
51
|
-
add_offense(attribute) do |corrector|
|
52
|
-
autocorrect(corrector, attribute)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def autocorrect(corrector, node)
|
60
|
-
if node.parenthesized?
|
61
|
-
autocorrect_replacing_parens(corrector, node)
|
62
|
-
else
|
63
|
-
autocorrect_without_parens(corrector, node)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def offensive_receiver?(receiver, node)
|
68
|
-
receiver.nil? ||
|
69
|
-
receiver.self_type? ||
|
70
|
-
receiver_matches_first_block_argument?(receiver, node)
|
71
|
-
end
|
72
|
-
|
73
|
-
def receiver_matches_first_block_argument?(receiver, node)
|
74
|
-
first_block_argument = node.arguments.first
|
75
|
-
|
76
|
-
!first_block_argument.nil? &&
|
77
|
-
receiver.lvar_type? &&
|
78
|
-
receiver.node_parts == first_block_argument.node_parts
|
79
|
-
end
|
80
|
-
|
81
|
-
def proc?(attribute)
|
82
|
-
value_matcher(attribute).to_a.all?(&:block_pass_type?)
|
83
|
-
end
|
84
|
-
|
85
|
-
# @!method association?(node)
|
86
|
-
def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
|
87
|
-
|
88
|
-
def autocorrect_replacing_parens(corrector, node)
|
89
|
-
left_braces, right_braces = braces(node)
|
90
|
-
|
91
|
-
corrector.replace(node.location.begin, " #{left_braces}")
|
92
|
-
corrector.replace(node.location.end, right_braces)
|
93
|
-
end
|
94
|
-
|
95
|
-
def autocorrect_without_parens(corrector, node)
|
96
|
-
left_braces, right_braces = braces(node)
|
97
|
-
|
98
|
-
argument = node.first_argument
|
99
|
-
expression = argument.source_range
|
100
|
-
corrector.insert_before(expression, left_braces)
|
101
|
-
corrector.insert_after(expression, right_braces)
|
102
|
-
end
|
103
|
-
|
104
|
-
def braces(node)
|
105
|
-
if value_hash_without_braces?(node.first_argument)
|
106
|
-
['{ { ', ' } }']
|
107
|
-
else
|
108
|
-
['{ ', ' }']
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def value_hash_without_braces?(node)
|
113
|
-
node.hash_type? && !node.braces?
|
114
|
-
end
|
115
|
-
|
116
|
-
def reserved_method?(method_name)
|
117
|
-
RuboCop::RSpec::FactoryBot.reserved_methods.include?(method_name)
|
118
|
-
end
|
119
|
-
|
120
|
-
def attribute_defining_method?(method_name)
|
121
|
-
RuboCop::RSpec::FactoryBot.attribute_defining_methods
|
122
|
-
.include?(method_name)
|
123
|
-
end
|
124
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Always declare attribute values as blocks.
|
9
|
+
# #
|
10
|
+
# # @example
|
11
|
+
# # # bad
|
12
|
+
# # kind [:active, :rejected].sample
|
13
|
+
# #
|
14
|
+
# # # good
|
15
|
+
# # kind { [:active, :rejected].sample }
|
16
|
+
# #
|
17
|
+
# # # bad
|
18
|
+
# # closed_at 1.day.from_now
|
19
|
+
# #
|
20
|
+
# # # good
|
21
|
+
# # closed_at { 1.day.from_now }
|
22
|
+
# #
|
23
|
+
# # # bad
|
24
|
+
# # count 1
|
25
|
+
# #
|
26
|
+
# # # good
|
27
|
+
# # count { 1 }
|
28
|
+
# #
|
29
|
+
# class AttributeDefinedStatically < ::RuboCop::Cop::Base; end
|
30
|
+
AttributeDefinedStatically =
|
31
|
+
::RuboCop::Cop::FactoryBot::AttributeDefinedStatically
|
125
32
|
end
|
126
33
|
end
|
127
34
|
end
|
@@ -4,113 +4,46 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module FactoryBot
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# #
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# create
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# #
|
20
|
-
#
|
21
|
-
# create(:user)
|
22
|
-
# create(:
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# #
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# create :login
|
32
|
-
#
|
33
|
-
# #
|
34
|
-
# #
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
include RuboCop::Cop::Util
|
48
|
-
|
49
|
-
def self.autocorrect_incompatible_with
|
50
|
-
[Style::MethodCallWithArgsParentheses]
|
51
|
-
end
|
52
|
-
|
53
|
-
MSG_REQUIRE_PARENS = 'Prefer method call with parentheses'
|
54
|
-
MSG_OMIT_PARENS = 'Prefer method call without parentheses'
|
55
|
-
|
56
|
-
FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
|
57
|
-
|
58
|
-
RESTRICT_ON_SEND = FACTORY_CALLS
|
59
|
-
|
60
|
-
# @!method factory_call(node)
|
61
|
-
def_node_matcher :factory_call, <<-PATTERN
|
62
|
-
(send
|
63
|
-
{#factory_bot? nil?} %FACTORY_CALLS
|
64
|
-
{sym str send lvar} _*
|
65
|
-
)
|
66
|
-
PATTERN
|
67
|
-
|
68
|
-
def on_send(node)
|
69
|
-
return if ambiguous_without_parentheses?(node)
|
70
|
-
|
71
|
-
factory_call(node) do
|
72
|
-
return if node.method?(:generate) && node.arguments.count > 1
|
73
|
-
|
74
|
-
if node.parenthesized?
|
75
|
-
process_with_parentheses(node)
|
76
|
-
else
|
77
|
-
process_without_parentheses(node)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
def process_with_parentheses(node)
|
85
|
-
return unless style == :omit_parentheses
|
86
|
-
return unless same_line?(node, node.first_argument)
|
87
|
-
|
88
|
-
add_offense(node.loc.selector,
|
89
|
-
message: MSG_OMIT_PARENS) do |corrector|
|
90
|
-
remove_parentheses(corrector, node)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def process_without_parentheses(node)
|
95
|
-
return unless style == :require_parentheses
|
96
|
-
|
97
|
-
add_offense(node.loc.selector,
|
98
|
-
message: MSG_REQUIRE_PARENS) do |corrector|
|
99
|
-
add_parentheses(node, corrector)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
AMBIGUOUS_TYPES = %i[send pair array and or if].freeze
|
104
|
-
|
105
|
-
def ambiguous_without_parentheses?(node)
|
106
|
-
node.parent && AMBIGUOUS_TYPES.include?(node.parent.type)
|
107
|
-
end
|
108
|
-
|
109
|
-
def remove_parentheses(corrector, node)
|
110
|
-
corrector.replace(node.location.begin, ' ')
|
111
|
-
corrector.remove(node.location.end)
|
112
|
-
end
|
113
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Use a consistent style for parentheses in factory bot calls.
|
9
|
+
# #
|
10
|
+
# # @example
|
11
|
+
# #
|
12
|
+
# # # bad
|
13
|
+
# # create :user
|
14
|
+
# # build(:user)
|
15
|
+
# # create(:login)
|
16
|
+
# # create :login
|
17
|
+
# #
|
18
|
+
# # @example `EnforcedStyle: require_parentheses` (default)
|
19
|
+
# #
|
20
|
+
# # # good
|
21
|
+
# # create(:user)
|
22
|
+
# # create(:user)
|
23
|
+
# # create(:login)
|
24
|
+
# # build(:login)
|
25
|
+
# #
|
26
|
+
# # @example `EnforcedStyle: omit_parentheses`
|
27
|
+
# #
|
28
|
+
# # # good
|
29
|
+
# # create :user
|
30
|
+
# # build :user
|
31
|
+
# # create :login
|
32
|
+
# # create :login
|
33
|
+
# #
|
34
|
+
# # # also good
|
35
|
+
# # # when method name and first argument are not on same line
|
36
|
+
# # create(
|
37
|
+
# # :user
|
38
|
+
# # )
|
39
|
+
# # build(
|
40
|
+
# # :user,
|
41
|
+
# # name: 'foo'
|
42
|
+
# # )
|
43
|
+
# #
|
44
|
+
# class ConsistentParenthesesStyle < ::RuboCop::Cop::Base; end
|
45
|
+
ConsistentParenthesesStyle =
|
46
|
+
::RuboCop::Cop::FactoryBot::ConsistentParenthesesStyle
|
114
47
|
end
|
115
48
|
end
|
116
49
|
end
|
@@ -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
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
# Checks that spec file paths are consistent and well-formed.
|
7
7
|
#
|
8
8
|
# By default, this checks that spec file paths are consistent with the
|
9
|
-
# test subject and
|
9
|
+
# test subject and enforces that it reflects the described
|
10
10
|
# class/module and its optionally called out method.
|
11
11
|
#
|
12
12
|
# With the configuration option `IgnoreMethods` the called out method will
|
@@ -56,19 +56,24 @@ module RuboCop
|
|
56
56
|
|
57
57
|
private
|
58
58
|
|
59
|
-
|
59
|
+
SUFFIX_INDEX_REGEX = /_?\d+$/.freeze
|
60
|
+
INDEX_REGEX = /\d+/.freeze
|
60
61
|
|
61
62
|
def filter_indexed_lets(candidates)
|
62
63
|
candidates
|
63
64
|
.filter { |node| indexed_let?(node) }
|
64
|
-
.group_by { |node|
|
65
|
+
.group_by { |node| let_name_stripped_index(node) }
|
65
66
|
.values
|
66
67
|
.filter { |lets| lets.length > cop_config['Max'] }
|
67
68
|
.flatten
|
68
69
|
end
|
69
70
|
|
70
71
|
def indexed_let?(node)
|
71
|
-
let?(node) &&
|
72
|
+
let?(node) && SUFFIX_INDEX_REGEX.match?(let_name(node))
|
73
|
+
end
|
74
|
+
|
75
|
+
def let_name_stripped_index(node)
|
76
|
+
let_name(node).to_s.gsub(INDEX_REGEX, '')
|
72
77
|
end
|
73
78
|
end
|
74
79
|
end
|
@@ -18,7 +18,7 @@ module RuboCop
|
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
20
|
MSG =
|
21
|
-
'Prefer `expect(response).%<to>s have_http_status(%<status>
|
21
|
+
'Prefer `expect(response).%<to>s have_http_status(%<status>s)` ' \
|
22
22
|
'over `%<bad_code>s`.'
|
23
23
|
|
24
24
|
RUNNERS = %i[to to_not not_to].to_set
|
@@ -37,12 +37,14 @@ module RuboCop
|
|
37
37
|
|
38
38
|
def on_send(node)
|
39
39
|
match_status(node) do |response_status, to, match, status|
|
40
|
+
return unless status.to_s.match?(/\A\d+\z/)
|
41
|
+
|
40
42
|
message = format(MSG, to: to, status: status,
|
41
43
|
bad_code: node.source)
|
42
44
|
add_offense(node, message: message) do |corrector|
|
43
45
|
corrector.replace(response_status, 'response')
|
44
46
|
corrector.replace(match.loc.selector, 'have_http_status')
|
45
|
-
corrector.replace(match.first_argument, status.
|
47
|
+
corrector.replace(match.first_argument, status.to_s)
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
@@ -16,6 +16,12 @@ module RuboCop
|
|
16
16
|
RSpec/Capybara/SpecificFinders
|
17
17
|
RSpec/Capybara/SpecificMatcher
|
18
18
|
RSpec/Capybara/VisibilityMatcher
|
19
|
+
RSpec/FactoryBot/AttributeDefinedStatically
|
20
|
+
RSpec/FactoryBot/ConsistentParenthesesStyle
|
21
|
+
RSpec/FactoryBot/CreateList
|
22
|
+
RSpec/FactoryBot/FactoryClassName
|
23
|
+
RSpec/FactoryBot/FactoryNameStyle
|
24
|
+
RSpec/FactoryBot/SyntaxMethods
|
19
25
|
)
|
20
26
|
AMENDMENTS = %(Metrics/BlockLength)
|
21
27
|
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -5,6 +5,7 @@ require 'yaml'
|
|
5
5
|
|
6
6
|
require 'rubocop'
|
7
7
|
require 'rubocop-capybara'
|
8
|
+
require 'rubocop-factory_bot'
|
8
9
|
|
9
10
|
require_relative 'rubocop/rspec'
|
10
11
|
require_relative 'rubocop/rspec/inject'
|
@@ -16,8 +17,6 @@ require_relative 'rubocop/rspec/wording'
|
|
16
17
|
# Dependent on `RuboCop::RSpec::Language::NodePattern`.
|
17
18
|
require_relative 'rubocop/rspec/language'
|
18
19
|
|
19
|
-
require_relative 'rubocop/rspec/factory_bot/language'
|
20
|
-
|
21
20
|
require_relative 'rubocop/cop/rspec/mixin/final_end_location'
|
22
21
|
require_relative 'rubocop/cop/rspec/mixin/inside_example_group'
|
23
22
|
require_relative 'rubocop/cop/rspec/mixin/location_help'
|
@@ -37,7 +36,6 @@ require_relative 'rubocop/rspec/concept'
|
|
37
36
|
require_relative 'rubocop/rspec/corrector/move_node'
|
38
37
|
require_relative 'rubocop/rspec/example'
|
39
38
|
require_relative 'rubocop/rspec/example_group'
|
40
|
-
require_relative 'rubocop/rspec/factory_bot'
|
41
39
|
require_relative 'rubocop/rspec/hook'
|
42
40
|
|
43
41
|
RuboCop::RSpec::Inject.defaults!
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Backus
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-05-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -40,6 +40,20 @@ dependencies:
|
|
40
40
|
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '2.17'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: rubocop-factory_bot
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '2.22'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '2.22'
|
43
57
|
description: |2
|
44
58
|
Code style checking for RSpec files.
|
45
59
|
A plugin for the RuboCop code style enforcing & linting tool.
|
@@ -197,8 +211,6 @@ files:
|
|
197
211
|
- lib/rubocop/rspec/description_extractor.rb
|
198
212
|
- lib/rubocop/rspec/example.rb
|
199
213
|
- lib/rubocop/rspec/example_group.rb
|
200
|
-
- lib/rubocop/rspec/factory_bot.rb
|
201
|
-
- lib/rubocop/rspec/factory_bot/language.rb
|
202
214
|
- lib/rubocop/rspec/hook.rb
|
203
215
|
- lib/rubocop/rspec/inject.rb
|
204
216
|
- lib/rubocop/rspec/language.rb
|
@@ -222,14 +234,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
222
234
|
requirements:
|
223
235
|
- - ">="
|
224
236
|
- !ruby/object:Gem::Version
|
225
|
-
version: 2.
|
237
|
+
version: 2.7.0
|
226
238
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
227
239
|
requirements:
|
228
240
|
- - ">="
|
229
241
|
- !ruby/object:Gem::Version
|
230
242
|
version: '0'
|
231
243
|
requirements: []
|
232
|
-
rubygems_version: 3.4.
|
244
|
+
rubygems_version: 3.4.12
|
233
245
|
signing_key:
|
234
246
|
specification_version: 4
|
235
247
|
summary: Code style checking for RSpec files
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module RSpec
|
5
|
-
module FactoryBot
|
6
|
-
# Contains node matchers for common FactoryBot DSL.
|
7
|
-
module Language
|
8
|
-
extend RuboCop::NodePattern::Macros
|
9
|
-
|
10
|
-
METHODS = %i[
|
11
|
-
attributes_for
|
12
|
-
attributes_for_list
|
13
|
-
attributes_for_pair
|
14
|
-
build
|
15
|
-
build_list
|
16
|
-
build_pair
|
17
|
-
build_stubbed
|
18
|
-
build_stubbed_list
|
19
|
-
build_stubbed_pair
|
20
|
-
create
|
21
|
-
create_list
|
22
|
-
create_pair
|
23
|
-
generate
|
24
|
-
generate_list
|
25
|
-
null
|
26
|
-
null_list
|
27
|
-
null_pair
|
28
|
-
].to_set.freeze
|
29
|
-
|
30
|
-
# @!method factory_bot?(node)
|
31
|
-
def_node_matcher :factory_bot?, <<~PATTERN
|
32
|
-
(const {nil? cbase} {:FactoryGirl :FactoryBot})
|
33
|
-
PATTERN
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module RSpec
|
5
|
-
# RuboCop FactoryBot project namespace
|
6
|
-
module FactoryBot
|
7
|
-
ATTRIBUTE_DEFINING_METHODS = %i[
|
8
|
-
factory
|
9
|
-
ignore
|
10
|
-
trait
|
11
|
-
traits_for_enum
|
12
|
-
transient
|
13
|
-
].freeze
|
14
|
-
|
15
|
-
UNPROXIED_METHODS = %i[
|
16
|
-
__send__
|
17
|
-
__id__
|
18
|
-
nil?
|
19
|
-
send
|
20
|
-
object_id
|
21
|
-
extend
|
22
|
-
instance_eval
|
23
|
-
initialize
|
24
|
-
block_given?
|
25
|
-
raise
|
26
|
-
caller
|
27
|
-
method
|
28
|
-
].freeze
|
29
|
-
|
30
|
-
DEFINITION_PROXY_METHODS = %i[
|
31
|
-
add_attribute
|
32
|
-
after
|
33
|
-
association
|
34
|
-
before
|
35
|
-
callback
|
36
|
-
ignore
|
37
|
-
initialize_with
|
38
|
-
sequence
|
39
|
-
skip_create
|
40
|
-
to_create
|
41
|
-
].freeze
|
42
|
-
|
43
|
-
RESERVED_METHODS =
|
44
|
-
DEFINITION_PROXY_METHODS +
|
45
|
-
UNPROXIED_METHODS +
|
46
|
-
ATTRIBUTE_DEFINING_METHODS
|
47
|
-
|
48
|
-
private_constant(
|
49
|
-
:ATTRIBUTE_DEFINING_METHODS,
|
50
|
-
:UNPROXIED_METHODS,
|
51
|
-
:DEFINITION_PROXY_METHODS,
|
52
|
-
:RESERVED_METHODS
|
53
|
-
)
|
54
|
-
|
55
|
-
def self.attribute_defining_methods
|
56
|
-
ATTRIBUTE_DEFINING_METHODS
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.reserved_methods
|
60
|
-
RESERVED_METHODS
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|