rubocop-rspec 2.0.0.pre → 2.0.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 -2
- data/README.md +4 -0
- data/config/default.yml +100 -18
- data/lib/rubocop-rspec.rb +7 -8
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +7 -3
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +7 -3
- data/lib/rubocop/cop/rspec/base.rb +6 -55
- data/lib/rubocop/cop/rspec/be.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +2 -2
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +3 -2
- data/lib/rubocop/cop/rspec/describe_class.rb +1 -1
- data/lib/rubocop/cop/rspec/describe_method.rb +1 -1
- data/lib/rubocop/cop/rspec/described_class.rb +1 -2
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -2
- data/lib/rubocop/cop/rspec/dialect.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_example_group.rb +6 -45
- data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/expect_actual.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/file_path.rb +1 -1
- data/lib/rubocop/cop/rspec/focus.rb +13 -7
- data/lib/rubocop/cop/rspec/hook_argument.rb +2 -4
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +2 -2
- data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +2 -2
- data/lib/rubocop/cop/rspec/let_setup.rb +7 -4
- data/lib/rubocop/cop/rspec/message_spies.rb +1 -1
- data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +51 -0
- data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
- data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
- data/lib/rubocop/cop/rspec/mixin/variable.rb +20 -0
- data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +3 -1
- data/lib/rubocop/cop/rspec/named_subject.rb +8 -12
- data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +2 -1
- data/lib/rubocop/cop/rspec/pending.rb +13 -5
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +3 -3
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -2
- data/lib/rubocop/cop/rspec/shared_context.rb +16 -6
- data/lib/rubocop/cop/rspec/shared_examples.rb +3 -1
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +2 -2
- data/lib/rubocop/cop/rspec/variable_definition.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_name.rb +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +0 -1
- data/lib/rubocop/rspec/align_let_brace.rb +1 -1
- data/lib/rubocop/rspec/concept.rb +2 -2
- data/lib/rubocop/rspec/config_formatter.rb +3 -3
- data/lib/rubocop/rspec/corrector/move_node.rb +1 -1
- data/lib/rubocop/rspec/example_group.rb +15 -5
- data/lib/rubocop/rspec/hook.rb +1 -1
- data/lib/rubocop/rspec/inject.rb +4 -2
- data/lib/rubocop/rspec/language.rb +143 -109
- data/lib/rubocop/rspec/language/node_pattern.rb +7 -24
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +22 -12
- data/lib/rubocop/cop/rspec/cop.rb +0 -10
- data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +0 -41
- data/lib/rubocop/rspec.rb +0 -12
- data/lib/rubocop/rspec/empty_line_separation.rb +0 -48
- data/lib/rubocop/rspec/final_end_location.rb +0 -17
- data/lib/rubocop/rspec/top_level_describe.rb +0 -52
- data/lib/rubocop/rspec/top_level_group.rb +0 -57
- data/lib/rubocop/rspec/variable.rb +0 -16
@@ -22,8 +22,7 @@ module RuboCop
|
|
22
22
|
class DescribedClassModuleWrapping < Base
|
23
23
|
MSG = 'Avoid opening modules and defining specs within them.'
|
24
24
|
|
25
|
-
def_node_search :find_rspec_blocks,
|
26
|
-
ExampleGroups::ALL.block_pattern
|
25
|
+
def_node_search :find_rspec_blocks, block_pattern('#ExampleGroups.all')
|
27
26
|
|
28
27
|
def on_module(node)
|
29
28
|
find_rspec_blocks(node) do
|
@@ -5,8 +5,6 @@ module RuboCop
|
|
5
5
|
module RSpec
|
6
6
|
# Checks if an example group does not include any tests.
|
7
7
|
#
|
8
|
-
# This cop is configurable using the `CustomIncludeMethods` option
|
9
|
-
#
|
10
8
|
# @example usage
|
11
9
|
#
|
12
10
|
# # bad
|
@@ -37,31 +35,6 @@ module RuboCop
|
|
37
35
|
# describe Bacon do
|
38
36
|
# pending 'will add tests later'
|
39
37
|
# end
|
40
|
-
#
|
41
|
-
# @example configuration
|
42
|
-
#
|
43
|
-
# # .rubocop.yml
|
44
|
-
# # RSpec/EmptyExampleGroup:
|
45
|
-
# # CustomIncludeMethods:
|
46
|
-
# # - include_tests
|
47
|
-
#
|
48
|
-
# # spec_helper.rb
|
49
|
-
# RSpec.configure do |config|
|
50
|
-
# config.alias_it_behaves_like_to(:include_tests)
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# # bacon_spec.rb
|
54
|
-
# describe Bacon do
|
55
|
-
# let(:bacon) { Bacon.new(chunkiness) }
|
56
|
-
# let(:chunkiness) { false }
|
57
|
-
#
|
58
|
-
# context 'extra chunky' do # not flagged by rubocop
|
59
|
-
# let(:chunkiness) { true }
|
60
|
-
#
|
61
|
-
# include_tests 'shared tests'
|
62
|
-
# end
|
63
|
-
# end
|
64
|
-
#
|
65
38
|
class EmptyExampleGroup < Base
|
66
39
|
MSG = 'Empty example group detected.'
|
67
40
|
|
@@ -76,7 +49,7 @@ module RuboCop
|
|
76
49
|
# @param node [RuboCop::AST::Node]
|
77
50
|
# @yield [RuboCop::AST::Node] example group body
|
78
51
|
def_node_matcher :example_group_body, <<~PATTERN
|
79
|
-
(block #{ExampleGroups
|
52
|
+
(block #{send_pattern('#ExampleGroups.all')} args $_)
|
80
53
|
PATTERN
|
81
54
|
|
82
55
|
# @!method example_or_group_or_include?(node)
|
@@ -95,12 +68,10 @@ module RuboCop
|
|
95
68
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
96
69
|
def_node_matcher :example_or_group_or_include?, <<~PATTERN
|
97
70
|
{
|
98
|
-
#{
|
99
|
-
|
100
|
-
|
101
|
-
#{Includes
|
102
|
-
#{Includes::ALL.block_pattern}
|
103
|
-
(send nil? #custom_include? ...)
|
71
|
+
#{block_pattern(
|
72
|
+
'{#Examples.all #ExampleGroups.all #Includes.all}'
|
73
|
+
)}
|
74
|
+
#{send_pattern('{#Examples.all #Includes.all}')}
|
104
75
|
}
|
105
76
|
PATTERN
|
106
77
|
|
@@ -120,7 +91,7 @@ module RuboCop
|
|
120
91
|
# @param node [RuboCop::AST::Node]
|
121
92
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
122
93
|
def_node_matcher :examples_inside_block?, <<~PATTERN
|
123
|
-
(block !#{Hooks
|
94
|
+
(block !#{send_pattern('#Hooks.all')} _ #examples?)
|
124
95
|
PATTERN
|
125
96
|
|
126
97
|
# @!method examples_directly_or_in_block?(node)
|
@@ -192,16 +163,6 @@ module RuboCop
|
|
192
163
|
def examples_in_branches?(if_node)
|
193
164
|
if_node.branches.any? { |branch| examples?(branch) }
|
194
165
|
end
|
195
|
-
|
196
|
-
def custom_include?(method_name)
|
197
|
-
custom_include_methods.include?(method_name)
|
198
|
-
end
|
199
|
-
|
200
|
-
def custom_include_methods
|
201
|
-
cop_config
|
202
|
-
.fetch('CustomIncludeMethods', [])
|
203
|
-
.map(&:to_sym)
|
204
|
-
end
|
205
166
|
end
|
206
167
|
end
|
207
168
|
end
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
# let(:foo) { bar }
|
17
17
|
class EmptyLineAfterSubject < Base
|
18
18
|
extend AutoCorrector
|
19
|
-
include
|
19
|
+
include EmptyLineSeparation
|
20
20
|
|
21
21
|
MSG = 'Add an empty line after `%<subject>s`.'
|
22
22
|
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
32
32
|
|
33
33
|
def in_spec_block?(node)
|
34
34
|
node.each_ancestor(:block).any? do |ancestor|
|
35
|
-
Examples
|
35
|
+
Examples.all(ancestor.method_name)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -23,7 +23,7 @@ module RuboCop
|
|
23
23
|
class ExpectInHook < Base
|
24
24
|
MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
|
25
25
|
|
26
|
-
def_node_search :expectation, Expectations
|
26
|
+
def_node_search :expectation, send_pattern('#Expectations.all')
|
27
27
|
|
28
28
|
def on_block(node)
|
29
29
|
return unless hook?(node)
|
@@ -22,19 +22,25 @@ module RuboCop
|
|
22
22
|
class Focus < Base
|
23
23
|
MSG = 'Focused spec found.'
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
def_node_matcher :focusable_selector?, <<-PATTERN
|
26
|
+
{
|
27
|
+
#ExampleGroups.regular
|
28
|
+
#ExampleGroups.skipped
|
29
|
+
#Examples.regular
|
30
|
+
#Examples.skipped
|
31
|
+
#Examples.pending
|
32
|
+
}
|
33
|
+
PATTERN
|
31
34
|
|
32
35
|
def_node_matcher :metadata, <<-PATTERN
|
33
36
|
{(send #rspec? #focusable_selector? <$(sym :focus) ...>)
|
34
37
|
(send #rspec? #focusable_selector? ... (hash <$(pair (sym :focus) true) ...>))}
|
35
38
|
PATTERN
|
36
39
|
|
37
|
-
def_node_matcher :focused_block?,
|
40
|
+
def_node_matcher :focused_block?,
|
41
|
+
send_pattern(<<~PATTERN)
|
42
|
+
{#ExampleGroups.focused #Examples.focused}
|
43
|
+
PATTERN
|
38
44
|
|
39
45
|
def on_send(node)
|
40
46
|
focus_metadata(node) do |focus|
|
@@ -64,13 +64,11 @@ module RuboCop
|
|
64
64
|
IMPLICIT_MSG = 'Omit the default `%<scope>p` argument for RSpec hooks.'
|
65
65
|
EXPLICIT_MSG = 'Use `%<scope>p` for RSpec hooks.'
|
66
66
|
|
67
|
-
def_node_matcher :hook?, Hooks::ALL.node_pattern_union
|
68
|
-
|
69
67
|
def_node_matcher :scoped_hook, <<-PATTERN
|
70
|
-
(block $(send _ #
|
68
|
+
(block $(send _ #Hooks.all (sym ${:each :example})) ...)
|
71
69
|
PATTERN
|
72
70
|
|
73
|
-
def_node_matcher :unscoped_hook, '(block $(send _ #
|
71
|
+
def_node_matcher :unscoped_hook, '(block $(send _ #Hooks.all) ...)'
|
74
72
|
|
75
73
|
def on_block(node)
|
76
74
|
hook(node) do |method_send, scope_name|
|
@@ -30,8 +30,8 @@ module RuboCop
|
|
30
30
|
|
31
31
|
def_node_matcher :example_or_group?, <<-PATTERN
|
32
32
|
{
|
33
|
-
#{(
|
34
|
-
#{Includes
|
33
|
+
#{block_pattern('{#ExampleGroups.all #Examples.all}')}
|
34
|
+
#{send_pattern('#Includes.examples')}
|
35
35
|
}
|
36
36
|
PATTERN
|
37
37
|
|
@@ -37,8 +37,8 @@ module RuboCop
|
|
37
37
|
|
38
38
|
def_node_matcher :example_or_group?, <<-PATTERN
|
39
39
|
{
|
40
|
-
#{(
|
41
|
-
#{Includes
|
40
|
+
#{block_pattern('{#ExampleGroups.all #Examples.all}')}
|
41
|
+
#{send_pattern('#Includes.examples')}
|
42
42
|
}
|
43
43
|
PATTERN
|
44
44
|
|
@@ -29,10 +29,13 @@ module RuboCop
|
|
29
29
|
MSG = 'Do not use `let!` to setup objects not referenced in tests.'
|
30
30
|
|
31
31
|
def_node_matcher :example_or_shared_group_or_including?,
|
32
|
-
(
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
block_pattern(<<~PATTERN)
|
33
|
+
{
|
34
|
+
#SharedGroups.all
|
35
|
+
#ExampleGroups.all
|
36
|
+
#Includes.all
|
37
|
+
}
|
38
|
+
PATTERN
|
36
39
|
|
37
40
|
def_node_matcher :let_bang, <<-PATTERN
|
38
41
|
{
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
SUPPORTED_STYLES = %w[have_received receive].freeze
|
37
37
|
|
38
38
|
def_node_matcher :message_expectation, %(
|
39
|
-
(send (send nil? :expect $_) #
|
39
|
+
(send (send nil? :expect $_) #Runners.all ...)
|
40
40
|
)
|
41
41
|
|
42
42
|
def_node_search :receive_message, %(
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Helps determine the offending location if there is not an empty line
|
7
|
+
# following the node. Allows comments to follow directly after.
|
8
|
+
module EmptyLineSeparation
|
9
|
+
include FinalEndLocation
|
10
|
+
include RangeHelp
|
11
|
+
|
12
|
+
def missing_separating_line_offense(node)
|
13
|
+
return if last_child?(node)
|
14
|
+
|
15
|
+
missing_separating_line(node) do |location|
|
16
|
+
msg = yield(node.method_name)
|
17
|
+
add_offense(location, message: msg) do |corrector|
|
18
|
+
corrector.insert_after(location.end, "\n")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def missing_separating_line(node)
|
24
|
+
line = final_end_location(node).line
|
25
|
+
|
26
|
+
line += 1 while comment_line?(processed_source[line])
|
27
|
+
|
28
|
+
return if processed_source[line].blank?
|
29
|
+
|
30
|
+
yield offending_loc(line)
|
31
|
+
end
|
32
|
+
|
33
|
+
def offending_loc(last_line)
|
34
|
+
offending_line = processed_source[last_line - 1]
|
35
|
+
|
36
|
+
content_length = offending_line.lstrip.length
|
37
|
+
start = offending_line.length - content_length
|
38
|
+
|
39
|
+
source_range(processed_source.buffer,
|
40
|
+
last_line, start, content_length)
|
41
|
+
end
|
42
|
+
|
43
|
+
def last_child?(node)
|
44
|
+
return true unless node.parent&.begin_type?
|
45
|
+
|
46
|
+
node.equal?(node.parent.children.last)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Helps find the true end location of nodes which might contain heredocs.
|
7
|
+
module FinalEndLocation
|
8
|
+
def final_end_location(start_node)
|
9
|
+
heredoc_endings =
|
10
|
+
start_node.each_node(:str, :dstr, :xstr)
|
11
|
+
.select(&:heredoc?)
|
12
|
+
.map { |node| node.loc.heredoc_end }
|
13
|
+
|
14
|
+
[start_node.loc.end, *heredoc_endings].max_by(&:line)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Helper methods for top level example group cops
|
7
|
+
module TopLevelGroup
|
8
|
+
extend RuboCop::NodePattern::Macros
|
9
|
+
|
10
|
+
def on_new_investigation
|
11
|
+
super
|
12
|
+
|
13
|
+
top_level_groups.each do |node|
|
14
|
+
on_top_level_example_group(node) if example_group?(node)
|
15
|
+
on_top_level_group(node)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def top_level_groups
|
20
|
+
@top_level_groups ||=
|
21
|
+
top_level_nodes(root_node).select { |n| spec_group?(n) }
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Dummy methods to be overridden in the consumer
|
27
|
+
def on_top_level_example_group(_node); end
|
28
|
+
|
29
|
+
def on_top_level_group(_node); end
|
30
|
+
|
31
|
+
def top_level_group?(node)
|
32
|
+
top_level_groups.include?(node)
|
33
|
+
end
|
34
|
+
|
35
|
+
def top_level_nodes(node)
|
36
|
+
return [] if node.nil?
|
37
|
+
|
38
|
+
case node.type
|
39
|
+
when :begin
|
40
|
+
node.children
|
41
|
+
when :module, :class
|
42
|
+
top_level_nodes(node.body)
|
43
|
+
else
|
44
|
+
[node]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def root_node
|
49
|
+
processed_source.ast
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|