rubocop-rspec 2.18.1 → 2.19.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 +17 -0
- data/README.md +1 -1
- data/config/default.yml +31 -0
- data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
- data/lib/rubocop/cop/rspec/change_by_zero.rb +3 -3
- data/lib/rubocop/cop/rspec/contain_exactly.rb +45 -0
- data/lib/rubocop/cop/rspec/context_wording.rb +13 -5
- data/lib/rubocop/cop/rspec/describe_method.rb +16 -8
- data/lib/rubocop/cop/rspec/described_class.rb +2 -1
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +3 -1
- data/lib/rubocop/cop/rspec/dialect.rb +1 -1
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_example_group.rb +7 -7
- data/lib/rubocop/cop/rspec/empty_hook.rb +2 -2
- data/lib/rubocop/cop/rspec/example_wording.rb +1 -1
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +2 -2
- data/lib/rubocop/cop/rspec/file_path.rb +1 -1
- data/lib/rubocop/cop/rspec/focus.rb +4 -5
- data/lib/rubocop/cop/rspec/hook_argument.rb +12 -9
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +5 -3
- data/lib/rubocop/cop/rspec/let_before_examples.rb +4 -4
- data/lib/rubocop/cop/rspec/let_setup.rb +6 -8
- data/lib/rubocop/cop/rspec/match_array.rb +41 -0
- data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +1 -2
- data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +20 -4
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +2 -1
- data/lib/rubocop/cop/rspec/named_subject.rb +6 -4
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +2 -5
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +3 -1
- data/lib/rubocop/cop/rspec/pending.rb +12 -12
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +65 -36
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +9 -34
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +4 -4
- data/lib/rubocop/cop/rspec/rails/travel_around.rb +92 -0
- data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
- data/lib/rubocop/cop/rspec/redundant_around.rb +69 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +3 -6
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +3 -6
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -4
- data/lib/rubocop/cop/rspec/shared_context.rb +12 -13
- data/lib/rubocop/cop/rspec/shared_examples.rb +6 -4
- data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
- data/lib/rubocop/cop/rspec/sort_metadata.rb +2 -2
- data/lib/rubocop/cop/rspec/variable_definition.rb +3 -0
- data/lib/rubocop/cop/rspec/variable_name.rb +4 -1
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +3 -3
- data/lib/rubocop/cop/rspec_cops.rb +5 -0
- data/lib/rubocop/rspec/example_group.rb +6 -8
- data/lib/rubocop/rspec/language/node_pattern.rb +26 -0
- data/lib/rubocop/rspec/language.rb +25 -16
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +1 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44e3a236fcd4869222a8e50780c5ef50671968fe82661b22f34d93315116c36b
|
4
|
+
data.tar.gz: 22c11a55d5d29ae10f2ec8fc4a3c95a3bd7f2b1bb5a0b049a9e47d3328178e7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bbfab487662a025737c213ab0f9c0a4c54d1d93fe3a3c05a344b20dcd2f83900aef723f07d0ecdade3c616afa15bee4a6cb975345ea9d8a80e3ba0a64c715a05
|
7
|
+
data.tar.gz: a1f112ce509e7a938a7d0377ac2fcf0a5c723fbac2299f5246ab84b4d989d8223b7a608c5952368094515085d4a106695d3baf71b5f8b02769cdbbf4965d9cd4
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,22 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.19.0 (2023-03-06)
|
6
|
+
|
7
|
+
- Fix a false positive for `RSpec/ContextWording` when context is interpolated string literal or execute string. ([@ydah])
|
8
|
+
- Fix a false positive for `RSpec/DescribeMethod` when multi-line describe without `#` and `.` at the beginning. ([@ydah], [@pirj])
|
9
|
+
- Fix a false positive for `RSpec/VariableName` when inside non-spec code. ([@ydah])
|
10
|
+
- Fix a false positive for `RSpec/VariableDefinition` when inside non-spec code. ([@ydah])
|
11
|
+
- Add new `RSpec/PendingBlockInsideExample` cop. ([@ydah])
|
12
|
+
- Add `RSpec/RedundantAround` cop. ([@r7kamura])
|
13
|
+
- Add `RSpec/Rails/TravelAround` cop. ([@r7kamura])
|
14
|
+
- Add `RSpec/ContainExactly` and `RSpec/MatchArray` cops. ([@faucct])
|
15
|
+
- Fix a false positive for `RSpec/PendingWithoutReason` when not inside example and pending/skip with block. ([@ydah], [@pirj])
|
16
|
+
- Fix a false positive for `RSpec/PendingWithoutReason` when `skip` is passed a block inside example. ([@ydah], [@pirj])
|
17
|
+
- Rename `RSpec/PendingBlockInsideExample` cop to `RSpec/SkipBlockInsideExample`. ([@pirj])
|
18
|
+
- Deprecate `send_pattern`/`block_pattern`/`numblock_pattern` helpers in favour of using node pattern explicitly. ([@pirj], [@ydah])
|
19
|
+
- Fix an incorrect autocorrect for `RSpec/VerifiedDoubleReference` when namespaced class. ([@ydah])
|
20
|
+
|
5
21
|
## 2.18.1 (2023-01-19)
|
6
22
|
|
7
23
|
- Add `rubocop-capybara` version constraint to prevent sudden cop enabling when it hits 3.0. ([@pirj])
|
@@ -751,6 +767,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
751
767
|
[@elebow]: https://github.com/elebow
|
752
768
|
[@elisefitz15]: https://github.com/EliseFitz15
|
753
769
|
[@elliterate]: https://github.com/elliterate
|
770
|
+
[@faucct]: https://github.com/faucct
|
754
771
|
[@foton]: https://github.com/foton
|
755
772
|
[@francois-ferrandis]: https://github.com/francois-ferrandis
|
756
773
|
[@g-rath]: https://github.com/G-Rath
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[](https://rubygems.org/gems/rubocop-rspec)
|
5
5
|

|
6
6
|
|
7
|
-
RSpec-specific analysis for your projects, as an extension to
|
7
|
+
[RSpec](https://rspec.info/)-specific analysis for your projects, as an extension to
|
8
8
|
[RuboCop](https://github.com/rubocop/rubocop).
|
9
9
|
|
10
10
|
## Installation
|
data/config/default.yml
CHANGED
@@ -201,6 +201,12 @@ RSpec/ClassCheck:
|
|
201
201
|
- be_kind_of
|
202
202
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ClassCheck
|
203
203
|
|
204
|
+
RSpec/ContainExactly:
|
205
|
+
Description: Prefer `match_array` when matching array values.
|
206
|
+
Enabled: true
|
207
|
+
VersionAdded: '2.19'
|
208
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContainExactly
|
209
|
+
|
204
210
|
RSpec/ContextMethod:
|
205
211
|
Description: "`context` should not be used for specifying methods."
|
206
212
|
Enabled: true
|
@@ -556,6 +562,12 @@ RSpec/LetSetup:
|
|
556
562
|
VersionAdded: '1.7'
|
557
563
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup
|
558
564
|
|
565
|
+
RSpec/MatchArray:
|
566
|
+
Description: Prefer `contain_exactly` when matching an array literal.
|
567
|
+
Enabled: true
|
568
|
+
VersionAdded: '2.19'
|
569
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MatchArray
|
570
|
+
|
559
571
|
RSpec/MessageChain:
|
560
572
|
Description: Check that chains of messages are not being stubbed.
|
561
573
|
Enabled: true
|
@@ -706,6 +718,12 @@ RSpec/ReceiveNever:
|
|
706
718
|
VersionAdded: '1.28'
|
707
719
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever
|
708
720
|
|
721
|
+
RSpec/RedundantAround:
|
722
|
+
Description: Remove redundant `around` hook.
|
723
|
+
Enabled: pending
|
724
|
+
VersionAdded: '2.19'
|
725
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantAround
|
726
|
+
|
709
727
|
RSpec/RepeatedDescription:
|
710
728
|
Description: Check for repeated description strings in example groups.
|
711
729
|
Enabled: true
|
@@ -779,6 +797,12 @@ RSpec/SingleArgumentMessageChain:
|
|
779
797
|
VersionChanged: '1.10'
|
780
798
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain
|
781
799
|
|
800
|
+
RSpec/SkipBlockInsideExample:
|
801
|
+
Description: Checks for passing a block to `skip` within examples.
|
802
|
+
Enabled: pending
|
803
|
+
VersionAdded: '2.19'
|
804
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SkipBlockInsideExample
|
805
|
+
|
782
806
|
RSpec/SortMetadata:
|
783
807
|
Description: Sort RSpec metadata alphabetically.
|
784
808
|
Enabled: pending
|
@@ -1056,3 +1080,10 @@ RSpec/Rails/MinitestAssertions:
|
|
1056
1080
|
Enabled: pending
|
1057
1081
|
VersionAdded: '2.17'
|
1058
1082
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions
|
1083
|
+
|
1084
|
+
RSpec/Rails/TravelAround:
|
1085
|
+
Description: Prefer to travel in `before` rather than `around`.
|
1086
|
+
Enabled: pending
|
1087
|
+
Safe: false
|
1088
|
+
VersionAdded: '2.19'
|
1089
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/TravelAround
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
57
57
|
return unless be_nil_matcher?(node)
|
58
58
|
|
59
59
|
add_offense(node, message: BE_MSG) do |corrector|
|
60
|
-
corrector.replace(node.
|
60
|
+
corrector.replace(node.source_range, 'be(nil)')
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
return unless nil_value_expectation?(node)
|
66
66
|
|
67
67
|
add_offense(node, message: BE_NIL_MSG) do |corrector|
|
68
|
-
corrector.replace(node.
|
68
|
+
corrector.replace(node.source_range, 'be_nil')
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
private
|
100
100
|
|
101
101
|
def check_offense(node)
|
102
|
-
expression = node.
|
102
|
+
expression = node.source_range
|
103
103
|
if compound_expectations?(node)
|
104
104
|
add_offense(expression, message: message_compound) do |corrector|
|
105
105
|
autocorrect_compound(corrector, node)
|
@@ -117,7 +117,7 @@ module RuboCop
|
|
117
117
|
|
118
118
|
def autocorrect(corrector, node)
|
119
119
|
corrector.replace(node.parent.loc.selector, 'not_to')
|
120
|
-
range = node.loc.dot.with(end_pos: node.
|
120
|
+
range = node.loc.dot.with(end_pos: node.source_range.end_pos)
|
121
121
|
corrector.remove(range)
|
122
122
|
end
|
123
123
|
|
@@ -126,7 +126,7 @@ module RuboCop
|
|
126
126
|
|
127
127
|
change_nodes(node) do |change_node|
|
128
128
|
corrector.replace(change_node.loc.selector, negated_matcher)
|
129
|
-
range = node.loc.dot.with(end_pos: node.
|
129
|
+
range = node.loc.dot.with(end_pos: node.source_range.end_pos)
|
130
130
|
corrector.remove(range)
|
131
131
|
end
|
132
132
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Prefer `match_array` when matching array values.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# it { is_expected.to contain_exactly(*array1, *array2) }
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# it { is_expected.to match_array(array1 + array2) }
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# it { is_expected.to contain_exactly(content, *array) }
|
17
|
+
class ContainExactly < Base
|
18
|
+
extend AutoCorrector
|
19
|
+
|
20
|
+
MSG = 'Prefer `match_array` when matching array values.'
|
21
|
+
RESTRICT_ON_SEND = %i[contain_exactly].freeze
|
22
|
+
|
23
|
+
def on_send(node)
|
24
|
+
return unless node.each_child_node.all?(&:splat_type?)
|
25
|
+
|
26
|
+
add_offense(node) do |corrector|
|
27
|
+
autocorrect(node, corrector)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def autocorrect(node, corrector)
|
34
|
+
arrays = node.arguments.map do |splat_node|
|
35
|
+
splat_node.children.first
|
36
|
+
end
|
37
|
+
corrector.replace(
|
38
|
+
node.source_range,
|
39
|
+
"match_array(#{arrays.map(&:source).join(' + ')})"
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -62,12 +62,12 @@ module RuboCop
|
|
62
62
|
|
63
63
|
# @!method context_wording(node)
|
64
64
|
def_node_matcher :context_wording, <<-PATTERN
|
65
|
-
(block (send #rspec? { :context :shared_context } $(str
|
65
|
+
(block (send #rspec? { :context :shared_context } $({str dstr xstr} ...) ...) ...)
|
66
66
|
PATTERN
|
67
67
|
|
68
68
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
69
|
-
context_wording(node) do |context
|
70
|
-
if bad_pattern?(
|
69
|
+
context_wording(node) do |context|
|
70
|
+
if bad_pattern?(context)
|
71
71
|
message = format(MSG, patterns: expect_patterns)
|
72
72
|
add_offense(context, message: message)
|
73
73
|
end
|
@@ -84,10 +84,18 @@ module RuboCop
|
|
84
84
|
@prefix_regexes ||= prefixes.map { |pre| /^#{Regexp.escape(pre)}\b/ }
|
85
85
|
end
|
86
86
|
|
87
|
-
def bad_pattern?(
|
87
|
+
def bad_pattern?(node)
|
88
88
|
return false if allowed_patterns.empty?
|
89
89
|
|
90
|
-
!matches_allowed_pattern?(description)
|
90
|
+
!matches_allowed_pattern?(description(node))
|
91
|
+
end
|
92
|
+
|
93
|
+
def description(context)
|
94
|
+
if context.xstr_type?
|
95
|
+
context.value.value
|
96
|
+
else
|
97
|
+
context.value
|
98
|
+
end
|
91
99
|
end
|
92
100
|
|
93
101
|
def expect_patterns
|
@@ -23,20 +23,28 @@ module RuboCop
|
|
23
23
|
MSG = 'The second argument to describe should be the method ' \
|
24
24
|
"being tested. '#instance' or '.class'."
|
25
25
|
|
26
|
-
# @!method
|
27
|
-
def_node_matcher :
|
26
|
+
# @!method second_string_literal_argument(node)
|
27
|
+
def_node_matcher :second_string_literal_argument, <<~PATTERN
|
28
28
|
(block
|
29
|
-
(send #rspec? :describe _first_argument $
|
30
|
-
)
|
29
|
+
(send #rspec? :describe _first_argument ${str dstr} ...)
|
30
|
+
...)
|
31
|
+
PATTERN
|
32
|
+
|
33
|
+
# @!method method_name?(node)
|
34
|
+
def_node_matcher :method_name?, <<~PATTERN
|
35
|
+
{(str #method_name_prefix?) (dstr (str #method_name_prefix?) ...)}
|
31
36
|
PATTERN
|
32
37
|
|
33
38
|
def on_top_level_group(node)
|
34
|
-
|
39
|
+
second_string_literal_argument(node) do |argument|
|
40
|
+
add_offense(argument) unless method_name?(argument)
|
41
|
+
end
|
42
|
+
end
|
35
43
|
|
36
|
-
|
37
|
-
return if second_argument.str_content.start_with?('#', '.')
|
44
|
+
private
|
38
45
|
|
39
|
-
|
46
|
+
def method_name_prefix?(description)
|
47
|
+
description.start_with?('.', '#')
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -68,7 +68,8 @@ module RuboCop
|
|
68
68
|
PATTERN
|
69
69
|
|
70
70
|
# @!method rspec_block?(node)
|
71
|
-
def_node_matcher :rspec_block?,
|
71
|
+
def_node_matcher :rspec_block?,
|
72
|
+
'({block numblock} (send #rspec? #ALL.all ...) ...)'
|
72
73
|
|
73
74
|
# @!method scope_changing_syntax?(node)
|
74
75
|
def_node_matcher :scope_changing_syntax?, '{def class module}'
|
@@ -23,7 +23,9 @@ module RuboCop
|
|
23
23
|
MSG = 'Avoid opening modules and defining specs within them.'
|
24
24
|
|
25
25
|
# @!method find_rspec_blocks(node)
|
26
|
-
def_node_search :find_rspec_blocks,
|
26
|
+
def_node_search :find_rspec_blocks, <<~PATTERN
|
27
|
+
(block (send #explicit_rspec? #ExampleGroups.all ...) ...)
|
28
|
+
PATTERN
|
27
29
|
|
28
30
|
def on_module(node)
|
29
31
|
find_rspec_blocks(node) do
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
|
50
50
|
|
51
51
|
# @!method rspec_method?(node)
|
52
|
-
def_node_matcher :rspec_method?,
|
52
|
+
def_node_matcher :rspec_method?, '(send #rspec? #ALL.all ...)'
|
53
53
|
|
54
54
|
def on_send(node)
|
55
55
|
return unless rspec_method?(node)
|
@@ -53,7 +53,7 @@ module RuboCop
|
|
53
53
|
# @param node [RuboCop::AST::Node]
|
54
54
|
# @yield [RuboCop::AST::Node] example group body
|
55
55
|
def_node_matcher :example_group_body, <<~PATTERN
|
56
|
-
(block
|
56
|
+
(block (send #rspec? #ExampleGroups.all ...) args $_)
|
57
57
|
PATTERN
|
58
58
|
|
59
59
|
# @!method example_or_group_or_include?(node)
|
@@ -72,10 +72,10 @@ module RuboCop
|
|
72
72
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
73
73
|
def_node_matcher :example_or_group_or_include?, <<~PATTERN
|
74
74
|
{
|
75
|
-
|
76
|
-
|
77
|
-
)
|
78
|
-
|
75
|
+
(block
|
76
|
+
(send #rspec? {#Examples.all #ExampleGroups.all #Includes.all} ...)
|
77
|
+
...)
|
78
|
+
(send nil? {#Examples.all #Includes.all} ...)
|
79
79
|
}
|
80
80
|
PATTERN
|
81
81
|
|
@@ -95,7 +95,7 @@ module RuboCop
|
|
95
95
|
# @param node [RuboCop::AST::Node]
|
96
96
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
97
97
|
def_node_matcher :examples_inside_block?, <<~PATTERN
|
98
|
-
(block
|
98
|
+
(block !(send nil? #Hooks.all ...) _ #examples?)
|
99
99
|
PATTERN
|
100
100
|
|
101
101
|
# @!method examples_directly_or_in_block?(node)
|
@@ -174,7 +174,7 @@ module RuboCop
|
|
174
174
|
|
175
175
|
def removed_range(node)
|
176
176
|
range_by_whole_lines(
|
177
|
-
node.
|
177
|
+
node.source_range,
|
178
178
|
include_final_newline: true
|
179
179
|
)
|
180
180
|
end
|
@@ -31,14 +31,14 @@ module RuboCop
|
|
31
31
|
|
32
32
|
# @!method empty_hook?(node)
|
33
33
|
def_node_matcher :empty_hook?, <<~PATTERN
|
34
|
-
(block
|
34
|
+
(block $(send nil? #Hooks.all ...) _ nil?)
|
35
35
|
PATTERN
|
36
36
|
|
37
37
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
38
38
|
empty_hook?(node) do |hook|
|
39
39
|
add_offense(hook) do |corrector|
|
40
40
|
corrector.remove(
|
41
|
-
range_with_surrounding_space(node.
|
41
|
+
range_with_surrounding_space(node.source_range, side: :left)
|
42
42
|
)
|
43
43
|
end
|
44
44
|
end
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
|
26
26
|
|
27
27
|
# @!method expectation(node)
|
28
|
-
def_node_search :expectation,
|
28
|
+
def_node_search :expectation, '(send nil? #Expectations.all ...)'
|
29
29
|
|
30
30
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
31
31
|
return unless hook?(node)
|
@@ -96,7 +96,7 @@ module RuboCop
|
|
96
96
|
left_braces, right_braces = braces(node)
|
97
97
|
|
98
98
|
argument = node.first_argument
|
99
|
-
expression = argument.
|
99
|
+
expression = argument.source_range
|
100
100
|
corrector.insert_before(expression, left_braces)
|
101
101
|
corrector.insert_after(expression, right_braces)
|
102
102
|
end
|
@@ -71,14 +71,14 @@ module RuboCop
|
|
71
71
|
|
72
72
|
def crime_scene(node)
|
73
73
|
range_between(
|
74
|
-
node.
|
74
|
+
node.source_range.begin_pos,
|
75
75
|
node.loc.selector.end_pos
|
76
76
|
)
|
77
77
|
end
|
78
78
|
|
79
79
|
def offense(node)
|
80
80
|
range_between(
|
81
|
-
node.
|
81
|
+
node.source_range.begin_pos,
|
82
82
|
node.loc.selector.begin_pos
|
83
83
|
)
|
84
84
|
end
|
@@ -61,10 +61,9 @@ module RuboCop
|
|
61
61
|
PATTERN
|
62
62
|
|
63
63
|
# @!method focused_block?(node)
|
64
|
-
def_node_matcher :focused_block?,
|
65
|
-
|
66
|
-
|
67
|
-
PATTERN
|
64
|
+
def_node_matcher :focused_block?, <<~PATTERN
|
65
|
+
(send #rspec? {#ExampleGroups.focused #Examples.focused} ...)
|
66
|
+
PATTERN
|
68
67
|
|
69
68
|
def on_send(node)
|
70
69
|
focus_metadata(node) do |focus|
|
@@ -88,7 +87,7 @@ module RuboCop
|
|
88
87
|
|
89
88
|
def with_surrounding(focus)
|
90
89
|
range_with_space =
|
91
|
-
range_with_surrounding_space(focus.
|
90
|
+
range_with_surrounding_space(focus.source_range, side: :left)
|
92
91
|
|
93
92
|
range_with_surrounding_comma(range_with_space, :left)
|
94
93
|
end
|
@@ -83,8 +83,7 @@ module RuboCop
|
|
83
83
|
style_detected(scope_name)
|
84
84
|
msg = explicit_message(scope_name)
|
85
85
|
add_offense(method_send, message: msg) do |corrector|
|
86
|
-
|
87
|
-
corrector.replace(argument_range(method_send), scope)
|
86
|
+
autocorrect(corrector, node, method_send)
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
@@ -93,6 +92,13 @@ module RuboCop
|
|
93
92
|
|
94
93
|
private
|
95
94
|
|
95
|
+
def autocorrect(corrector, _node, method_send)
|
96
|
+
scope = implicit_style? ? '' : "(#{style.inspect})"
|
97
|
+
corrector.replace(
|
98
|
+
LocationHelp.arguments_with_whitespace(method_send), scope
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
96
102
|
def check_implicit(method_send)
|
97
103
|
style_detected(:implicit)
|
98
104
|
return if implicit_style?
|
@@ -100,7 +106,10 @@ module RuboCop
|
|
100
106
|
msg = explicit_message(nil)
|
101
107
|
add_offense(method_send.loc.selector, message: msg) do |corrector|
|
102
108
|
scope = "(#{style.inspect})"
|
103
|
-
corrector.replace(
|
109
|
+
corrector.replace(
|
110
|
+
LocationHelp.arguments_with_whitespace(method_send),
|
111
|
+
scope
|
112
|
+
)
|
104
113
|
end
|
105
114
|
end
|
106
115
|
|
@@ -119,12 +128,6 @@ module RuboCop
|
|
119
128
|
def hook(node, &block)
|
120
129
|
scoped_hook(node, &block) || unscoped_hook(node, &block)
|
121
130
|
end
|
122
|
-
|
123
|
-
def argument_range(send_node)
|
124
|
-
send_node.loc.selector.end.with(
|
125
|
-
end_pos: send_node.loc.expression.end_pos
|
126
|
-
)
|
127
|
-
end
|
128
131
|
end
|
129
132
|
end
|
130
133
|
end
|
@@ -30,9 +30,11 @@ module RuboCop
|
|
30
30
|
# @!method example_or_group?(node)
|
31
31
|
def_node_matcher :example_or_group?, <<-PATTERN
|
32
32
|
{
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
({block numblock} {
|
34
|
+
(send #rspec? #ExampleGroups.all ...)
|
35
|
+
(send nil? #Examples.all ...)
|
36
|
+
} ...)
|
37
|
+
(send nil? #Includes.examples ...)
|
36
38
|
}
|
37
39
|
PATTERN
|
38
40
|
|
@@ -38,16 +38,16 @@ module RuboCop
|
|
38
38
|
# @!method example_or_group?(node)
|
39
39
|
def_node_matcher :example_or_group?, <<-PATTERN
|
40
40
|
{
|
41
|
-
|
42
|
-
|
41
|
+
(block (send nil? {#ExampleGroups.all #Examples.all} ...) ...)
|
42
|
+
(send nil? #Includes.examples ...)
|
43
43
|
}
|
44
44
|
PATTERN
|
45
45
|
|
46
46
|
# @!method include_examples?(node)
|
47
47
|
def_node_matcher :include_examples?, <<~PATTERN
|
48
48
|
{
|
49
|
-
|
50
|
-
|
49
|
+
(block (send nil? :include_examples ...) ...)
|
50
|
+
(send nil? :include_examples ...)
|
51
51
|
}
|
52
52
|
PATTERN
|
53
53
|
|
@@ -29,14 +29,12 @@ module RuboCop
|
|
29
29
|
MSG = 'Do not use `let!` to setup objects not referenced in tests.'
|
30
30
|
|
31
31
|
# @!method example_or_shared_group_or_including?(node)
|
32
|
-
def_node_matcher :example_or_shared_group_or_including?,
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
}
|
39
|
-
PATTERN
|
32
|
+
def_node_matcher :example_or_shared_group_or_including?, <<~PATTERN
|
33
|
+
(block {
|
34
|
+
(send #rspec? {#SharedGroups.all #ExampleGroups.all} ...)
|
35
|
+
(send nil? #Includes.all ...)
|
36
|
+
} ...)
|
37
|
+
PATTERN
|
40
38
|
|
41
39
|
# @!method let_bang(node)
|
42
40
|
def_node_matcher :let_bang, <<-PATTERN
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Prefer `contain_exactly` when matching an array literal.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# it { is_expected.to match_array([content1, content2]) }
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# it { is_expected.to contain_exactly(content1, content2) }
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# it { is_expected.to match_array([content] + array) }
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# it { is_expected.to match_array(%w(tremble in fear foolish mortals)) }
|
20
|
+
class MatchArray < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Prefer `contain_exactly` when matching an array literal.'
|
24
|
+
RESTRICT_ON_SEND = %i[match_array].freeze
|
25
|
+
|
26
|
+
def on_send(node)
|
27
|
+
return unless node.first_argument.array_type?
|
28
|
+
return if node.first_argument.percent_literal?
|
29
|
+
|
30
|
+
add_offense(node) do |corrector|
|
31
|
+
array_contents = node.arguments.flat_map(&:to_a)
|
32
|
+
corrector.replace(
|
33
|
+
node.source_range,
|
34
|
+
"contain_exactly(#{array_contents.map(&:source).join(', ')})"
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -25,8 +25,7 @@ module RuboCop
|
|
25
25
|
|
26
26
|
def missing_separating_line(node)
|
27
27
|
line = final_end_line = final_end_location(node).line
|
28
|
-
|
29
|
-
while comment_line?(processed_source[line])
|
28
|
+
while processed_source.line_with_comment?(line + 1)
|
30
29
|
line += 1
|
31
30
|
comment = processed_source.comment_at_line(line)
|
32
31
|
if DirectiveComment.new(comment).enabled?
|