rubocop-rspec 2.13.1 → 2.14.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 +405 -379
- data/CODE_OF_CONDUCT.md +4 -4
- data/MIT-LICENSE.md +1 -2
- data/config/default.yml +65 -4
- data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +106 -0
- data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +85 -0
- data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +9 -2
- data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +5 -82
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +14 -14
- data/lib/rubocop/cop/rspec/change_by_zero.rb +1 -1
- data/lib/rubocop/cop/rspec/context_wording.rb +4 -2
- data/lib/rubocop/cop/rspec/example_wording.rb +32 -0
- data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +99 -0
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +2 -2
- data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +1 -19
- data/lib/rubocop/cop/rspec/implicit_subject.rb +86 -19
- data/lib/rubocop/cop/rspec/let_before_examples.rb +15 -1
- data/lib/rubocop/cop/rspec/mixin/capybara_help.rb +80 -0
- data/lib/rubocop/cop/rspec/mixin/css_selector.rb +48 -1
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +23 -0
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +47 -6
- data/lib/rubocop/cop/rspec/pending.rb +2 -11
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +135 -0
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +1 -1
- data/lib/rubocop/cop/rspec/sort_metadata.rb +102 -0
- data/lib/rubocop/cop/rspec/subject_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +5 -0
- data/lib/rubocop/rspec/factory_bot/language.rb +20 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +2 -0
- metadata +9 -2
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
module Rails
|
7
|
+
# Identifies redundant spec type.
|
8
|
+
#
|
9
|
+
# After setting up rspec-rails, you will have enabled
|
10
|
+
# `config.infer_spec_type_from_file_location!` by default in
|
11
|
+
# spec/rails_helper.rb. This cop works in conjunction with this config.
|
12
|
+
# If you disable this config, disable this cop as well.
|
13
|
+
#
|
14
|
+
# @safety
|
15
|
+
# This cop is marked as unsafe because
|
16
|
+
# `config.infer_spec_type_from_file_location!` may not be enabled.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# # bad
|
20
|
+
# # spec/models/user_spec.rb
|
21
|
+
# RSpec.describe User, type: :model do
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# # spec/models/user_spec.rb
|
26
|
+
# RSpec.describe User do
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# # spec/models/user_spec.rb
|
31
|
+
# RSpec.describe User, type: :common do
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# @example `Inferences` configuration
|
35
|
+
# # .rubocop.yml
|
36
|
+
# # RSpec/InferredSpecType:
|
37
|
+
# # Inferences:
|
38
|
+
# # services: service
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# # spec/services/user_spec.rb
|
42
|
+
# RSpec.describe User, type: :service do
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# # good
|
46
|
+
# # spec/services/user_spec.rb
|
47
|
+
# RSpec.describe User do
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# # good
|
51
|
+
# # spec/services/user_spec.rb
|
52
|
+
# RSpec.describe User, type: :common do
|
53
|
+
# end
|
54
|
+
class InferredSpecType < Base
|
55
|
+
extend AutoCorrector
|
56
|
+
|
57
|
+
MSG = 'Remove redundant spec type.'
|
58
|
+
|
59
|
+
# @param [RuboCop::AST::BlockNode] node
|
60
|
+
def on_block(node)
|
61
|
+
return unless example_group?(node)
|
62
|
+
|
63
|
+
pair_node = describe_with_type(node)
|
64
|
+
return unless pair_node
|
65
|
+
return unless inferred_type?(pair_node)
|
66
|
+
|
67
|
+
removable_node = detect_removable_node(pair_node)
|
68
|
+
add_offense(removable_node) do |corrector|
|
69
|
+
autocorrect(corrector, removable_node)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
alias on_numblock on_block
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# @!method describe_with_type(node)
|
77
|
+
# @param [RuboCop::AST::BlockNode] node
|
78
|
+
# @return [RuboCop::AST::PairNode, nil]
|
79
|
+
def_node_matcher :describe_with_type, <<~PATTERN
|
80
|
+
(block
|
81
|
+
(send #rspec? #ExampleGroups.all
|
82
|
+
...
|
83
|
+
(hash <$(pair (sym :type) sym) ...>)
|
84
|
+
)
|
85
|
+
...
|
86
|
+
)
|
87
|
+
PATTERN
|
88
|
+
|
89
|
+
# @param [RuboCop::AST::Corrector] corrector
|
90
|
+
# @param [RuboCop::AST::Node] node
|
91
|
+
def autocorrect(corrector, node)
|
92
|
+
corrector.remove(
|
93
|
+
node.location.expression.with(
|
94
|
+
begin_pos: node.left_sibling.location.expression.end_pos
|
95
|
+
)
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param [RuboCop::AST::PairNode] node
|
100
|
+
# @return [RuboCop::AST::Node]
|
101
|
+
def detect_removable_node(node)
|
102
|
+
if node.parent.pairs.size == 1
|
103
|
+
node.parent
|
104
|
+
else
|
105
|
+
node
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# @return [String]
|
110
|
+
def file_path
|
111
|
+
processed_source.file_path
|
112
|
+
end
|
113
|
+
|
114
|
+
# @param [RuboCop::AST::PairNode] node
|
115
|
+
# @return [Boolean]
|
116
|
+
def inferred_type?(node)
|
117
|
+
inferred_type_from_file_path.inspect == node.value.source
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [Symbol, nil]
|
121
|
+
def inferred_type_from_file_path
|
122
|
+
inferences.find do |prefix, type|
|
123
|
+
break type.to_sym if file_path.include?("spec/#{prefix}/")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# @return [Hash]
|
128
|
+
def inferences
|
129
|
+
cop_config['Inferences'] || {}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
#
|
48
48
|
class RepeatedIncludeExample < Base
|
49
49
|
MSG = 'Repeated include of shared_examples %<name>s ' \
|
50
|
-
|
50
|
+
'on line(s) %<repeat>s'
|
51
51
|
|
52
52
|
# @!method several_include_examples?(node)
|
53
53
|
def_node_matcher :several_include_examples?, <<-PATTERN
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Sort RSpec metadata alphabetically.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# describe 'Something', :b, :a
|
11
|
+
# context 'Something', foo: 'bar', baz: true
|
12
|
+
# it 'works', :b, :a, foo: 'bar', baz: true
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# describe 'Something', :a, :b
|
16
|
+
# context 'Something', baz: true, foo: 'bar'
|
17
|
+
# it 'works', :a, :b, baz: true, foo: 'bar'
|
18
|
+
#
|
19
|
+
class SortMetadata < Base
|
20
|
+
extend AutoCorrector
|
21
|
+
include RangeHelp
|
22
|
+
|
23
|
+
MSG = 'Sort metadata alphabetically.'
|
24
|
+
|
25
|
+
# @!method rspec_metadata(node)
|
26
|
+
def_node_matcher :rspec_metadata, <<~PATTERN
|
27
|
+
(block
|
28
|
+
(send
|
29
|
+
#rspec? {#Examples.all #ExampleGroups.all #SharedGroups.all #Hooks.all #Includes.all}
|
30
|
+
_ ${send str sym}* (hash $...)?)
|
31
|
+
...)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
# @!method rspec_configure(node)
|
35
|
+
def_node_matcher :rspec_configure, <<~PATTERN
|
36
|
+
(block (send #rspec? :configure) (args (arg $_)) ...)
|
37
|
+
PATTERN
|
38
|
+
|
39
|
+
# @!method metadata_in_block(node)
|
40
|
+
def_node_search :metadata_in_block, <<~PATTERN
|
41
|
+
(send (lvar %) #Hooks.all _ ${send str sym}* (hash $...)?)
|
42
|
+
PATTERN
|
43
|
+
|
44
|
+
def on_block(node)
|
45
|
+
rspec_configure(node) do |block_var|
|
46
|
+
metadata_in_block(node, block_var) do |symbols, pairs|
|
47
|
+
investigate(symbols, pairs.flatten)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
rspec_metadata(node) do |symbols, pairs|
|
52
|
+
investigate(symbols, pairs.flatten)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
alias on_numblock on_block
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def investigate(symbols, pairs)
|
61
|
+
return if sorted?(symbols, pairs)
|
62
|
+
|
63
|
+
crime_scene = crime_scene(symbols, pairs)
|
64
|
+
add_offense(crime_scene) do |corrector|
|
65
|
+
corrector.replace(crime_scene, replacement(symbols, pairs))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def crime_scene(symbols, pairs)
|
70
|
+
metadata = symbols + pairs
|
71
|
+
|
72
|
+
range_between(
|
73
|
+
metadata.first.loc.expression.begin_pos,
|
74
|
+
metadata.last.loc.expression.end_pos
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def replacement(symbols, pairs)
|
79
|
+
(sort_symbols(symbols) + sort_pairs(pairs)).map(&:source).join(', ')
|
80
|
+
end
|
81
|
+
|
82
|
+
def sorted?(symbols, pairs)
|
83
|
+
symbols == sort_symbols(symbols) && pairs == sort_pairs(pairs)
|
84
|
+
end
|
85
|
+
|
86
|
+
def sort_pairs(pairs)
|
87
|
+
pairs.sort_by { |pair| pair.key.source.downcase }
|
88
|
+
end
|
89
|
+
|
90
|
+
def sort_symbols(symbols)
|
91
|
+
symbols.sort_by do |symbol|
|
92
|
+
if %i[str sym].include?(symbol.type)
|
93
|
+
symbol.value.to_s.downcase
|
94
|
+
else
|
95
|
+
symbol.source.downcase
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
|
26
26
|
# @!method offensive_subject_declaration?(node)
|
27
27
|
def_node_matcher :offensive_subject_declaration?, <<~PATTERN
|
28
|
-
(send nil? ${#Subjects.all #Helpers.all} {
|
28
|
+
(send nil? ${#Subjects.all #Helpers.all} ({sym str} #Subjects.all) ...)
|
29
29
|
PATTERN
|
30
30
|
|
31
31
|
def on_send(node)
|
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
require_relative 'rspec/capybara/current_path_expectation'
|
4
4
|
require_relative 'rspec/capybara/feature_methods'
|
5
|
+
require_relative 'rspec/capybara/negation_matcher'
|
6
|
+
require_relative 'rspec/capybara/specific_actions'
|
5
7
|
require_relative 'rspec/capybara/specific_finders'
|
6
8
|
require_relative 'rspec/capybara/specific_matcher'
|
7
9
|
require_relative 'rspec/capybara/visibility_matcher'
|
8
10
|
|
9
11
|
require_relative 'rspec/factory_bot/attribute_defined_statically'
|
12
|
+
require_relative 'rspec/factory_bot/consistent_parentheses_style'
|
10
13
|
require_relative 'rspec/factory_bot/create_list'
|
11
14
|
require_relative 'rspec/factory_bot/factory_class_name'
|
12
15
|
require_relative 'rspec/factory_bot/syntax_methods'
|
@@ -18,6 +21,7 @@ begin
|
|
18
21
|
rescue LoadError
|
19
22
|
# Rails/HttpStatus cannot be loaded if rack/utils is unavailable.
|
20
23
|
end
|
24
|
+
require_relative 'rspec/rails/inferred_spec_type'
|
21
25
|
|
22
26
|
require_relative 'rspec/align_left_let_brace'
|
23
27
|
require_relative 'rspec/align_right_let_brace'
|
@@ -97,6 +101,7 @@ require_relative 'rspec/scattered_setup'
|
|
97
101
|
require_relative 'rspec/shared_context'
|
98
102
|
require_relative 'rspec/shared_examples'
|
99
103
|
require_relative 'rspec/single_argument_message_chain'
|
104
|
+
require_relative 'rspec/sort_metadata'
|
100
105
|
require_relative 'rspec/stubbed_mock'
|
101
106
|
require_relative 'rspec/subject_declaration'
|
102
107
|
require_relative 'rspec/subject_stub'
|
@@ -7,6 +7,26 @@ module RuboCop
|
|
7
7
|
module Language
|
8
8
|
extend RuboCop::NodePattern::Macros
|
9
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
|
+
|
10
30
|
# @!method factory_bot?(node)
|
11
31
|
def_node_matcher :factory_bot?, <<~PATTERN
|
12
32
|
(const {nil? cbase} {:FactoryGirl :FactoryBot})
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -23,6 +23,8 @@ require_relative 'rubocop/cop/rspec/mixin/empty_line_separation'
|
|
23
23
|
require_relative 'rubocop/cop/rspec/mixin/inside_example_group'
|
24
24
|
require_relative 'rubocop/cop/rspec/mixin/namespace'
|
25
25
|
require_relative 'rubocop/cop/rspec/mixin/css_selector'
|
26
|
+
require_relative 'rubocop/cop/rspec/mixin/skip_or_pending'
|
27
|
+
require_relative 'rubocop/cop/rspec/mixin/capybara_help'
|
26
28
|
|
27
29
|
require_relative 'rubocop/rspec/concept'
|
28
30
|
require_relative 'rubocop/rspec/example_group'
|
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.14.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: 2022-
|
13
|
+
date: 2022-10-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -58,6 +58,8 @@ files:
|
|
58
58
|
- lib/rubocop/cop/rspec/before_after_all.rb
|
59
59
|
- lib/rubocop/cop/rspec/capybara/current_path_expectation.rb
|
60
60
|
- lib/rubocop/cop/rspec/capybara/feature_methods.rb
|
61
|
+
- lib/rubocop/cop/rspec/capybara/negation_matcher.rb
|
62
|
+
- lib/rubocop/cop/rspec/capybara/specific_actions.rb
|
61
63
|
- lib/rubocop/cop/rspec/capybara/specific_finders.rb
|
62
64
|
- lib/rubocop/cop/rspec/capybara/specific_matcher.rb
|
63
65
|
- lib/rubocop/cop/rspec/capybara/visibility_matcher.rb
|
@@ -87,6 +89,7 @@ files:
|
|
87
89
|
- lib/rubocop/cop/rspec/expect_in_hook.rb
|
88
90
|
- lib/rubocop/cop/rspec/expect_output.rb
|
89
91
|
- lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb
|
92
|
+
- lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb
|
90
93
|
- lib/rubocop/cop/rspec/factory_bot/create_list.rb
|
91
94
|
- lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb
|
92
95
|
- lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb
|
@@ -110,12 +113,14 @@ files:
|
|
110
113
|
- lib/rubocop/cop/rspec/message_expectation.rb
|
111
114
|
- lib/rubocop/cop/rspec/message_spies.rb
|
112
115
|
- lib/rubocop/cop/rspec/missing_example_group_argument.rb
|
116
|
+
- lib/rubocop/cop/rspec/mixin/capybara_help.rb
|
113
117
|
- lib/rubocop/cop/rspec/mixin/comments_help.rb
|
114
118
|
- lib/rubocop/cop/rspec/mixin/css_selector.rb
|
115
119
|
- lib/rubocop/cop/rspec/mixin/empty_line_separation.rb
|
116
120
|
- lib/rubocop/cop/rspec/mixin/final_end_location.rb
|
117
121
|
- lib/rubocop/cop/rspec/mixin/inside_example_group.rb
|
118
122
|
- lib/rubocop/cop/rspec/mixin/namespace.rb
|
123
|
+
- lib/rubocop/cop/rspec/mixin/skip_or_pending.rb
|
119
124
|
- lib/rubocop/cop/rspec/mixin/top_level_group.rb
|
120
125
|
- lib/rubocop/cop/rspec/mixin/variable.rb
|
121
126
|
- lib/rubocop/cop/rspec/multiple_describes.rb
|
@@ -132,6 +137,7 @@ files:
|
|
132
137
|
- lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb
|
133
138
|
- lib/rubocop/cop/rspec/rails/have_http_status.rb
|
134
139
|
- lib/rubocop/cop/rspec/rails/http_status.rb
|
140
|
+
- lib/rubocop/cop/rspec/rails/inferred_spec_type.rb
|
135
141
|
- lib/rubocop/cop/rspec/receive_counts.rb
|
136
142
|
- lib/rubocop/cop/rspec/receive_never.rb
|
137
143
|
- lib/rubocop/cop/rspec/repeated_description.rb
|
@@ -145,6 +151,7 @@ files:
|
|
145
151
|
- lib/rubocop/cop/rspec/shared_context.rb
|
146
152
|
- lib/rubocop/cop/rspec/shared_examples.rb
|
147
153
|
- lib/rubocop/cop/rspec/single_argument_message_chain.rb
|
154
|
+
- lib/rubocop/cop/rspec/sort_metadata.rb
|
148
155
|
- lib/rubocop/cop/rspec/stubbed_mock.rb
|
149
156
|
- lib/rubocop/cop/rspec/subject_declaration.rb
|
150
157
|
- lib/rubocop/cop/rspec/subject_stub.rb
|