rubocop-rspec 2.25.0 → 2.27.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/config/default.yml +39 -4
- data/lib/rubocop/cop/rspec/around_block.rb +3 -3
- data/lib/rubocop/cop/rspec/be.rb +1 -1
- data/lib/rubocop/cop/rspec/be_empty.rb +1 -0
- data/lib/rubocop/cop/rspec/be_eq.rb +1 -1
- data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
- data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
- data/lib/rubocop/cop/rspec/before_after_all.rb +7 -13
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +2 -2
- data/lib/rubocop/cop/rspec/change_by_zero.rb +30 -4
- data/lib/rubocop/cop/rspec/context_method.rb +2 -2
- data/lib/rubocop/cop/rspec/context_wording.rb +1 -1
- data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -1
- data/lib/rubocop/cop/rspec/described_class.rb +33 -11
- data/lib/rubocop/cop/rspec/empty_example_group.rb +2 -2
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +2 -2
- data/lib/rubocop/cop/rspec/example_without_description.rb +11 -2
- data/lib/rubocop/cop/rspec/example_wording.rb +11 -2
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_actual.rb +5 -2
- data/lib/rubocop/cop/rspec/expect_change.rb +2 -2
- data/lib/rubocop/cop/rspec/expect_output.rb +1 -4
- data/lib/rubocop/cop/rspec/focus.rb +2 -2
- data/lib/rubocop/cop/rspec/hook_argument.rb +2 -2
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -2
- data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/instance_spy.rb +2 -2
- data/lib/rubocop/cop/rspec/instance_variable.rb +2 -2
- data/lib/rubocop/cop/rspec/is_expected_specify.rb +45 -0
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +3 -3
- data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/let_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/message_expectation.rb +1 -2
- data/lib/rubocop/cop/rspec/message_spies.rb +0 -2
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +2 -2
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +12 -7
- data/lib/rubocop/cop/rspec/pending.rb +1 -1
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +1 -1
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +6 -6
- data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +34 -10
- data/lib/rubocop/cop/rspec/rails/http_status.rb +1 -1
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +314 -22
- data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_messages.rb +1 -1
- data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +67 -0
- data/lib/rubocop/cop/rspec/remove_const.rb +40 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +2 -2
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_subject_call.rb +124 -0
- data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_examples.rb +66 -20
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +2 -3
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +4 -4
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -2
- data/lib/rubocop/cop/rspec/variable_definition.rb +2 -2
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
- data/lib/rubocop/cop/rspec/void_expect.rb +2 -2
- data/lib/rubocop/cop/rspec_cops.rb +4 -0
- data/lib/rubocop/rspec/language.rb +8 -8
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop/rspec/wording.rb +8 -0
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 629669f9a1d9d41dae7bc62c630f3a6cdae80623d3213c8e79ac8eb207f79e59
|
4
|
+
data.tar.gz: 5005161c3684fcd8b794284bcaeedc50253a545d649be9e0e0a82958fdd125b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8af331d4b31697228397a1122cbe331223d3f040f44d2260e5148d73177df5ba08ae2aea1d481b27f698b5d59c9522d1c5f4c5e08e14b473a548de75ccf218c6
|
7
|
+
data.tar.gz: 0f86ea257bcd14e73c57b2e431f618e0959cf9dbeca6e22c4b75bd8d4945f670d8fdb65212ff12969b351b62c35f845ca28041d4b1b30627e7d64dda5932b365
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,35 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.27.1 (2024-03-03)
|
6
|
+
|
7
|
+
- Fix a false positive for `RSpec/RepeatedSubjectCall` when `subject.method_call`. ([@ydah])
|
8
|
+
- Add configuration option `OnlyStaticConstants` to `RSpec/DescribedClass`. ([@ydah])
|
9
|
+
|
10
|
+
## 2.27.0 (2024-03-01)
|
11
|
+
|
12
|
+
- Add new `RSpec/IsExpectedSpecify` cop. ([@ydah])
|
13
|
+
- Add new `RSpec/RepeatedSubjectCall` cop. ([@drcapulet])
|
14
|
+
- Add support for `assert_true`, `assert_false`, `assert_not_equal`, `assert_not_nil`, `*_empty`, `*_predicate`, `*_kind_of`, `*_in_delta`, `*_match`, `*_instance_of` and `*_includes` assertions in `RSpec/Rails/MinitestAssertions`. ([@ydah], [@G-Rath])
|
15
|
+
- Support asserts with messages in `Rspec/BeEmpty`. ([@G-Rath])
|
16
|
+
- Fix a false positive for `RSpec/ExpectActual` when used with rspec-rails routing matchers. ([@naveg])
|
17
|
+
- Add configuration option `ResponseMethods` to `RSpec/Rails/HaveHttpStatus`. ([@ydah])
|
18
|
+
- Fix a false negative for `RSpec/DescribedClass` when class with constant. ([@ydah])
|
19
|
+
- Fix a false positive for `RSpec/ExampleWithoutDescription` when `specify` with multi-line block and missing description. ([@ydah])
|
20
|
+
- Fix an incorrect autocorrect for `RSpec/ChangeByZero` when compound expectations with line break before `.by(0)`. ([@ydah])
|
21
|
+
|
22
|
+
## 2.26.1 (2024-01-05)
|
23
|
+
|
24
|
+
- Fix an error for `RSpec/SharedExamples` when using examples without argument. ([@ydah])
|
25
|
+
|
26
|
+
## 2.26.0 (2024-01-04)
|
27
|
+
|
28
|
+
- Add new `RSpec/RedundantPredicateMatcher` cop. ([@ydah])
|
29
|
+
- Add new `RSpec/RemoveConst` cop. ([@swelther])
|
30
|
+
- Add support for correcting "it will" (future tense) for `RSpec/ExampleWording`. ([@jdufresne])
|
31
|
+
- Add support for `symbol` style for `RSpec/SharedExamples`. ([@jessieay])
|
32
|
+
- Ensure `PendingWithoutReason` can detect violations inside shared groups. ([@robinaugh])
|
33
|
+
|
5
34
|
## 2.25.0 (2023-10-27)
|
6
35
|
|
7
36
|
- Add support single quoted string and percent string and heredoc for `RSpec/Rails/HttpStatus`. ([@ydah])
|
@@ -833,6 +862,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
833
862
|
[@deivid-rodriguez]: https://github.com/deivid-rodriguez
|
834
863
|
[@dgollahon]: https://github.com/dgollahon
|
835
864
|
[@dmitrytsepelev]: https://github.com/dmitrytsepelev
|
865
|
+
[@drcapulet]: https://github.com/drcapulet
|
836
866
|
[@drowze]: https://github.com/Drowze
|
837
867
|
[@dswij]: https://github.com/dswij
|
838
868
|
[@dvandersluis]: https://github.com/dvandersluis
|
@@ -855,7 +885,9 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
855
885
|
[@ignaciovillaverde]: https://github.com/ignaciovillaverde
|
856
886
|
[@jaredbeck]: https://github.com/jaredbeck
|
857
887
|
[@jaredmoody]: https://github.com/jaredmoody
|
888
|
+
[@jdufresne]: https://github.com/jdufresne
|
858
889
|
[@jeffreyc]: https://github.com/jeffreyc
|
890
|
+
[@jessieay]: https://github.com/jessieay
|
859
891
|
[@jfragoulis]: https://github.com/jfragoulis
|
860
892
|
[@johnny-miyake]: https://github.com/johnny-miyake
|
861
893
|
[@jojos003]: https://github.com/jojos003
|
@@ -878,6 +910,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
878
910
|
[@mockdeep]: https://github.com/mockdeep
|
879
911
|
[@mothonmars]: https://github.com/MothOnMars
|
880
912
|
[@mvz]: https://github.com/mvz
|
913
|
+
[@naveg]: https://github.com/naveg
|
881
914
|
[@nc-holodakg]: https://github.com/nc-holodakg
|
882
915
|
[@nevir]: https://github.com/nevir
|
883
916
|
[@ngouy]: https://github.com/ngouy
|
@@ -897,6 +930,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
897
930
|
[@rafix02]: https://github.com/Rafix02
|
898
931
|
[@redross]: https://github.com/redross
|
899
932
|
[@renanborgescampos]: https://github.com/renanborgescampos
|
933
|
+
[@robinaugh]: https://github.com/robinaugh
|
900
934
|
[@robotdana]: https://github.com/robotdana
|
901
935
|
[@rolfschmidt]: https://github.com/rolfschmidt
|
902
936
|
[@rrosenblum]: https://github.com/rrosenblum
|
@@ -909,6 +943,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
909
943
|
[@smcgivern]: https://github.com/smcgivern
|
910
944
|
[@splattael]: https://github.com/splattael
|
911
945
|
[@stephannv]: https://github.com/stephannv
|
946
|
+
[@swelther]: https://github.com/swelther
|
912
947
|
[@t3h2mas]: https://github.com/t3h2mas
|
913
948
|
[@tdeo]: https://github.com/tdeo
|
914
949
|
[@tejasbubane]: https://github.com/tejasbubane
|
data/config/default.yml
CHANGED
@@ -178,7 +178,7 @@ RSpec/BeNil:
|
|
178
178
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeNil
|
179
179
|
|
180
180
|
RSpec/BeforeAfterAll:
|
181
|
-
Description: Check that before/after(:all) isn't being used.
|
181
|
+
Description: Check that before/after(:all/:context) isn't being used.
|
182
182
|
Enabled: true
|
183
183
|
Exclude:
|
184
184
|
- "**/spec/spec_helper.rb"
|
@@ -283,9 +283,10 @@ RSpec/DescribedClass:
|
|
283
283
|
SupportedStyles:
|
284
284
|
- described_class
|
285
285
|
- explicit
|
286
|
+
OnlyStaticConstants: true
|
286
287
|
SafeAutoCorrect: false
|
287
288
|
VersionAdded: '1.0'
|
288
|
-
VersionChanged: '
|
289
|
+
VersionChanged: '2.27'
|
289
290
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass
|
290
291
|
|
291
292
|
RSpec/DescribedClassModuleWrapping:
|
@@ -548,6 +549,13 @@ RSpec/InstanceVariable:
|
|
548
549
|
StyleGuide: https://rspec.rubystyle.guide/#instance-variables
|
549
550
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceVariable
|
550
551
|
|
552
|
+
RSpec/IsExpectedSpecify:
|
553
|
+
Description: Check for `specify` with `is_expected` and one-liner expectations.
|
554
|
+
Enabled: pending
|
555
|
+
VersionAdded: '2.27'
|
556
|
+
StyleGuide: https://rspec.rubystyle.guide/#it-and-specify
|
557
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IsExpectedSpecify
|
558
|
+
|
551
559
|
RSpec/ItBehavesLike:
|
552
560
|
Description: Checks that only one `it_behaves_like` style is used.
|
553
561
|
Enabled: true
|
@@ -771,6 +779,18 @@ RSpec/RedundantAround:
|
|
771
779
|
VersionAdded: '2.19'
|
772
780
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantAround
|
773
781
|
|
782
|
+
RSpec/RedundantPredicateMatcher:
|
783
|
+
Description: Checks for redundant predicate matcher.
|
784
|
+
Enabled: pending
|
785
|
+
VersionAdded: '2.26'
|
786
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantPredicateMatcher
|
787
|
+
|
788
|
+
RSpec/RemoveConst:
|
789
|
+
Description: Checks that `remove_const` is not used in specs.
|
790
|
+
Enabled: pending
|
791
|
+
VersionAdded: '2.26'
|
792
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RemoveConst
|
793
|
+
|
774
794
|
RSpec/RepeatedDescription:
|
775
795
|
Description: Check for repeated description strings in example groups.
|
776
796
|
Enabled: true
|
@@ -801,6 +821,12 @@ RSpec/RepeatedIncludeExample:
|
|
801
821
|
VersionAdded: '1.44'
|
802
822
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedIncludeExample
|
803
823
|
|
824
|
+
RSpec/RepeatedSubjectCall:
|
825
|
+
Description: Checks for repeated calls to subject missing that it is memoized.
|
826
|
+
Enabled: pending
|
827
|
+
VersionAdded: '2.27'
|
828
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedSubjectCall
|
829
|
+
|
804
830
|
RSpec/ReturnFromStub:
|
805
831
|
Description: Checks for consistent style of stub's return setting.
|
806
832
|
Enabled: true
|
@@ -832,9 +858,14 @@ RSpec/SharedContext:
|
|
832
858
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedContext
|
833
859
|
|
834
860
|
RSpec/SharedExamples:
|
835
|
-
Description:
|
861
|
+
Description: Checks for consistent style for shared example names.
|
836
862
|
Enabled: true
|
863
|
+
EnforcedStyle: string
|
864
|
+
SupportedStyles:
|
865
|
+
- string
|
866
|
+
- symbol
|
837
867
|
VersionAdded: '1.25'
|
868
|
+
VersionChanged: '2.26'
|
838
869
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedExamples
|
839
870
|
|
840
871
|
RSpec/SingleArgumentMessageChain:
|
@@ -1109,8 +1140,12 @@ RSpec/Rails/AvoidSetupHook:
|
|
1109
1140
|
RSpec/Rails/HaveHttpStatus:
|
1110
1141
|
Description: Checks that tests use `have_http_status` instead of equality matchers.
|
1111
1142
|
Enabled: pending
|
1143
|
+
ResponseMethods:
|
1144
|
+
- response
|
1145
|
+
- last_response
|
1112
1146
|
SafeAutoCorrect: false
|
1113
1147
|
VersionAdded: '2.12'
|
1148
|
+
VersionChanged: '2.27'
|
1114
1149
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HaveHttpStatus
|
1115
1150
|
|
1116
1151
|
RSpec/Rails/HttpStatus:
|
@@ -1149,7 +1184,7 @@ RSpec/Rails/InferredSpecType:
|
|
1149
1184
|
views: view
|
1150
1185
|
|
1151
1186
|
RSpec/Rails/MinitestAssertions:
|
1152
|
-
Description: Check if using Minitest matchers.
|
1187
|
+
Description: Check if using Minitest-like matchers.
|
1153
1188
|
Enabled: pending
|
1154
1189
|
VersionAdded: '2.17'
|
1155
1190
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions
|
@@ -32,17 +32,17 @@ module RuboCop
|
|
32
32
|
'or `%<arg>s.run`.'
|
33
33
|
|
34
34
|
# @!method hook_block(node)
|
35
|
-
def_node_matcher :hook_block,
|
35
|
+
def_node_matcher :hook_block, <<~PATTERN
|
36
36
|
(block (send nil? :around sym ?) (args $...) ...)
|
37
37
|
PATTERN
|
38
38
|
|
39
39
|
# @!method hook_numblock(node)
|
40
|
-
def_node_matcher :hook_numblock,
|
40
|
+
def_node_matcher :hook_numblock, <<~PATTERN
|
41
41
|
(numblock (send nil? :around sym ?) ...)
|
42
42
|
PATTERN
|
43
43
|
|
44
44
|
# @!method find_arg_usage(node)
|
45
|
-
def_node_search :find_arg_usage,
|
45
|
+
def_node_search :find_arg_usage, <<~PATTERN
|
46
46
|
{(send $... {:call :run}) (send _ _ $...) (yield $...) (block-pass $...)}
|
47
47
|
PATTERN
|
48
48
|
|
data/lib/rubocop/cop/rspec/be.rb
CHANGED
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
RESTRICT_ON_SEND = %i[to].freeze
|
45
45
|
|
46
46
|
# @!method eql_type_with_identity(node)
|
47
|
-
def_node_matcher :eql_type_with_identity,
|
47
|
+
def_node_matcher :eql_type_with_identity, <<~PATTERN
|
48
48
|
(send _ :to $(send nil? :eql {true false int float sym nil}))
|
49
49
|
PATTERN
|
50
50
|
|
@@ -33,12 +33,12 @@ module RuboCop
|
|
33
33
|
RESTRICT_ON_SEND = %i[be be_nil].freeze
|
34
34
|
|
35
35
|
# @!method be_nil_matcher?(node)
|
36
|
-
def_node_matcher :be_nil_matcher?,
|
36
|
+
def_node_matcher :be_nil_matcher?, <<~PATTERN
|
37
37
|
(send nil? :be_nil)
|
38
38
|
PATTERN
|
39
39
|
|
40
40
|
# @!method nil_value_expectation?(node)
|
41
|
-
def_node_matcher :nil_value_expectation?,
|
41
|
+
def_node_matcher :nil_value_expectation?, <<~PATTERN
|
42
42
|
(send nil? :be nil)
|
43
43
|
PATTERN
|
44
44
|
|
@@ -3,22 +3,16 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
# Check that before/after(:all) isn't being used.
|
6
|
+
# Check that before/after(:all/:context) isn't being used.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
-
# # bad
|
10
|
-
# #
|
11
|
-
# # Faster but risk of state leaking between examples
|
12
|
-
# #
|
9
|
+
# # bad - Faster but risk of state leaking between examples
|
13
10
|
# describe MyClass do
|
14
11
|
# before(:all) { Widget.create }
|
15
|
-
# after(:
|
12
|
+
# after(:context) { Widget.delete_all }
|
16
13
|
# end
|
17
14
|
#
|
18
|
-
# # good
|
19
|
-
# #
|
20
|
-
# # Slower but examples are properly isolated
|
21
|
-
# #
|
15
|
+
# # good - Slower but examples are properly isolated
|
22
16
|
# describe MyClass do
|
23
17
|
# before(:each) { Widget.create }
|
24
18
|
# after(:each) { Widget.delete_all }
|
@@ -30,11 +24,11 @@ module RuboCop
|
|
30
24
|
'`use_transactional_fixtures` is enabled, then records created ' \
|
31
25
|
'in `%<hook>s` are not automatically rolled back.'
|
32
26
|
|
33
|
-
RESTRICT_ON_SEND =
|
27
|
+
RESTRICT_ON_SEND = Set[:before, :after].freeze
|
34
28
|
|
35
29
|
# @!method before_or_after_all(node)
|
36
|
-
def_node_matcher :before_or_after_all,
|
37
|
-
$(send _
|
30
|
+
def_node_matcher :before_or_after_all, <<~PATTERN
|
31
|
+
$(send _ RESTRICT_ON_SEND (sym {:all :context}))
|
38
32
|
PATTERN
|
39
33
|
|
40
34
|
def on_send(node)
|
@@ -58,12 +58,12 @@ module RuboCop
|
|
58
58
|
}.freeze
|
59
59
|
|
60
60
|
# @!method capybara_speak(node)
|
61
|
-
def_node_matcher :capybara_speak,
|
61
|
+
def_node_matcher :capybara_speak, <<~PATTERN
|
62
62
|
{#{MAP.keys.map(&:inspect).join(' ')}}
|
63
63
|
PATTERN
|
64
64
|
|
65
65
|
# @!method feature_method(node)
|
66
|
-
def_node_matcher :feature_method,
|
66
|
+
def_node_matcher :feature_method, <<~PATTERN
|
67
67
|
(block
|
68
68
|
$(send #rspec? $#capybara_speak ...)
|
69
69
|
...)
|
@@ -59,6 +59,8 @@ module RuboCop
|
|
59
59
|
#
|
60
60
|
class ChangeByZero < Base
|
61
61
|
extend AutoCorrector
|
62
|
+
include RangeHelp
|
63
|
+
|
62
64
|
MSG = 'Prefer `not_to change` over `to %<method>s.by(0)`.'
|
63
65
|
MSG_COMPOUND = 'Prefer %<preferred>s with compound expectations ' \
|
64
66
|
'over `%<method>s.by(0)`.'
|
@@ -66,14 +68,14 @@ module RuboCop
|
|
66
68
|
RESTRICT_ON_SEND = CHANGE_METHODS.freeze
|
67
69
|
|
68
70
|
# @!method expect_change_with_arguments(node)
|
69
|
-
def_node_matcher :expect_change_with_arguments,
|
71
|
+
def_node_matcher :expect_change_with_arguments, <<~PATTERN
|
70
72
|
(send
|
71
73
|
$(send nil? CHANGE_METHODS ...) :by
|
72
74
|
(int 0))
|
73
75
|
PATTERN
|
74
76
|
|
75
77
|
# @!method expect_change_with_block(node)
|
76
|
-
def_node_matcher :expect_change_with_block,
|
78
|
+
def_node_matcher :expect_change_with_block, <<~PATTERN
|
77
79
|
(send
|
78
80
|
(block
|
79
81
|
$(send nil? CHANGE_METHODS)
|
@@ -83,7 +85,7 @@ module RuboCop
|
|
83
85
|
PATTERN
|
84
86
|
|
85
87
|
# @!method change_nodes(node)
|
86
|
-
def_node_search :change_nodes,
|
88
|
+
def_node_search :change_nodes, <<~PATTERN
|
87
89
|
$(send nil? CHANGE_METHODS ...)
|
88
90
|
PATTERN
|
89
91
|
|
@@ -140,8 +142,32 @@ module RuboCop
|
|
140
142
|
|
141
143
|
change_nodes(node) do |change_node|
|
142
144
|
corrector.replace(change_node.loc.selector, negated_matcher)
|
143
|
-
|
145
|
+
insert_operator(corrector, node, change_node)
|
146
|
+
remove_by_zero(corrector, node, change_node)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def insert_operator(corrector, node, change_node)
|
151
|
+
operator = node.right_siblings.first
|
152
|
+
return unless %i[& |].include?(operator)
|
153
|
+
|
154
|
+
corrector.insert_after(
|
155
|
+
replace_node(node, change_node), " #{operator}"
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
def replace_node(node, change_node)
|
160
|
+
expect_change_with_arguments(node) ? change_node : change_node.parent
|
161
|
+
end
|
162
|
+
|
163
|
+
def remove_by_zero(corrector, node, change_node)
|
164
|
+
range = node.loc.dot.with(end_pos: node.source_range.end_pos)
|
165
|
+
if change_node.loc.line == range.line
|
144
166
|
corrector.remove(range)
|
167
|
+
else
|
168
|
+
corrector.remove(
|
169
|
+
range_by_whole_lines(range, include_final_newline: true)
|
170
|
+
)
|
145
171
|
end
|
146
172
|
end
|
147
173
|
|
@@ -30,7 +30,7 @@ module RuboCop
|
|
30
30
|
MSG = 'Use `describe` for testing methods.'
|
31
31
|
|
32
32
|
# @!method context_method(node)
|
33
|
-
def_node_matcher :context_method,
|
33
|
+
def_node_matcher :context_method, <<~PATTERN
|
34
34
|
(block
|
35
35
|
(send #rspec? :context
|
36
36
|
${(str #method_name?) (dstr (str #method_name?) ...)}
|
@@ -38,7 +38,7 @@ module RuboCop
|
|
38
38
|
...)
|
39
39
|
PATTERN
|
40
40
|
|
41
|
-
def on_block(node)
|
41
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
42
42
|
context_method(node) do |context|
|
43
43
|
add_offense(context) do |corrector|
|
44
44
|
corrector.replace(node.send_node.loc.selector, 'describe')
|
@@ -61,7 +61,7 @@ module RuboCop
|
|
61
61
|
MSG = 'Context description should match %<patterns>s.'
|
62
62
|
|
63
63
|
# @!method context_wording(node)
|
64
|
-
def_node_matcher :context_wording,
|
64
|
+
def_node_matcher :context_wording, <<~PATTERN
|
65
65
|
(block (send #rspec? { :context :shared_context } $({str dstr xstr} ...) ...) ...)
|
66
66
|
PATTERN
|
67
67
|
|
@@ -8,8 +8,10 @@ module RuboCop
|
|
8
8
|
# If the first argument of describe is a class, the class is exposed to
|
9
9
|
# each example via described_class.
|
10
10
|
#
|
11
|
-
# This cop can be configured using the `EnforcedStyle
|
12
|
-
# options.
|
11
|
+
# This cop can be configured using the `EnforcedStyle`, `SkipBlocks`
|
12
|
+
# and `OnlyStaticConstants` options.
|
13
|
+
# `OnlyStaticConstants` is only relevant when `EnforcedStyle` is
|
14
|
+
# `described_class`.
|
13
15
|
#
|
14
16
|
# @example `EnforcedStyle: described_class` (default)
|
15
17
|
# # bad
|
@@ -22,6 +24,18 @@ module RuboCop
|
|
22
24
|
# subject { described_class.do_something }
|
23
25
|
# end
|
24
26
|
#
|
27
|
+
# @example `OnlyStaticConstants: true` (default)
|
28
|
+
# # good
|
29
|
+
# describe MyClass do
|
30
|
+
# subject { MyClass::CONSTANT }
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @example `OnlyStaticConstants: false`
|
34
|
+
# # bad
|
35
|
+
# describe MyClass do
|
36
|
+
# subject { MyClass::CONSTANT }
|
37
|
+
# end
|
38
|
+
#
|
25
39
|
# @example `EnforcedStyle: explicit`
|
26
40
|
# # bad
|
27
41
|
# describe MyClass do
|
@@ -54,7 +68,7 @@ module RuboCop
|
|
54
68
|
# end
|
55
69
|
# end
|
56
70
|
#
|
57
|
-
class DescribedClass < Base
|
71
|
+
class DescribedClass < Base # rubocop:disable Metrics/ClassLength
|
58
72
|
extend AutoCorrector
|
59
73
|
include ConfigurableEnforcedStyle
|
60
74
|
include Namespace
|
@@ -63,7 +77,7 @@ module RuboCop
|
|
63
77
|
MSG = 'Use `%<replacement>s` instead of `%<src>s`.'
|
64
78
|
|
65
79
|
# @!method common_instance_exec_closure?(node)
|
66
|
-
def_node_matcher :common_instance_exec_closure?,
|
80
|
+
def_node_matcher :common_instance_exec_closure?, <<~PATTERN
|
67
81
|
(block (send (const nil? {:Class :Module :Struct}) :new ...) ...)
|
68
82
|
PATTERN
|
69
83
|
|
@@ -75,7 +89,7 @@ module RuboCop
|
|
75
89
|
def_node_matcher :scope_changing_syntax?, '{def class module}'
|
76
90
|
|
77
91
|
# @!method described_constant(node)
|
78
|
-
def_node_matcher :described_constant,
|
92
|
+
def_node_matcher :described_constant, <<~PATTERN
|
79
93
|
(block (send _ :describe $(const ...) ...) (args) $_)
|
80
94
|
PATTERN
|
81
95
|
|
@@ -112,14 +126,17 @@ module RuboCop
|
|
112
126
|
|
113
127
|
def find_usage(node, &block)
|
114
128
|
yield(node) if offensive?(node)
|
115
|
-
|
116
|
-
return if scope_change?(node) || node.const_type?
|
129
|
+
return if scope_change?(node) || allowed?(node)
|
117
130
|
|
118
131
|
node.each_child_node do |child|
|
119
132
|
find_usage(child, &block)
|
120
133
|
end
|
121
134
|
end
|
122
135
|
|
136
|
+
def allowed?(node)
|
137
|
+
node.const_type? && only_static_constants?
|
138
|
+
end
|
139
|
+
|
123
140
|
def message(offense)
|
124
141
|
if style == :described_class
|
125
142
|
format(MSG, replacement: DESCRIBED_CLASS, src: offense)
|
@@ -139,6 +156,10 @@ module RuboCop
|
|
139
156
|
node.block_type? && !rspec_block?(node) && cop_config['SkipBlocks']
|
140
157
|
end
|
141
158
|
|
159
|
+
def only_static_constants?
|
160
|
+
cop_config.fetch('OnlyStaticConstants', true)
|
161
|
+
end
|
162
|
+
|
142
163
|
def offensive?(node)
|
143
164
|
if style == :described_class
|
144
165
|
offensive_described_class?(node)
|
@@ -148,15 +169,15 @@ module RuboCop
|
|
148
169
|
end
|
149
170
|
|
150
171
|
def offensive_described_class?(node)
|
151
|
-
return unless node.const_type?
|
172
|
+
return false unless node.const_type?
|
152
173
|
|
153
174
|
# E.g. `described_class::CONSTANT`
|
154
|
-
return if contains_described_class?(node)
|
175
|
+
return false if contains_described_class?(node)
|
155
176
|
|
156
177
|
nearest_described_class, = node.each_ancestor(:block)
|
157
178
|
.map { |ancestor| described_constant(ancestor) }.find(&:itself)
|
158
179
|
|
159
|
-
return if nearest_described_class.equal?(node)
|
180
|
+
return false if nearest_described_class.equal?(node)
|
160
181
|
|
161
182
|
full_const_name(nearest_described_class) == full_const_name(node)
|
162
183
|
end
|
@@ -194,7 +215,8 @@ module RuboCop
|
|
194
215
|
# const_name(s(:const, s(:const, nil, :M), :C)) # => [:M, :C]
|
195
216
|
# const_name(s(:const, s(:cbase), :C)) # => [nil, :C]
|
196
217
|
def const_name(node)
|
197
|
-
namespace
|
218
|
+
namespace = node.namespace
|
219
|
+
name = node.short_name
|
198
220
|
if !namespace
|
199
221
|
[name]
|
200
222
|
elsif namespace.const_type?
|
@@ -162,7 +162,7 @@ module RuboCop
|
|
162
162
|
end
|
163
163
|
|
164
164
|
def conditionals_with_examples?(body)
|
165
|
-
return unless body.begin_type? || body.case_type?
|
165
|
+
return false unless body.begin_type? || body.case_type?
|
166
166
|
|
167
167
|
body.each_descendant(:if, :case).any? do |condition_node|
|
168
168
|
examples_in_branches?(condition_node)
|
@@ -170,7 +170,7 @@ module RuboCop
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def examples_in_branches?(condition_node)
|
173
|
-
return if !condition_node.if_type? && !condition_node.case_type?
|
173
|
+
return false if !condition_node.if_type? && !condition_node.case_type?
|
174
174
|
|
175
175
|
condition_node.branches.any? { |branch| examples?(branch) }
|
176
176
|
end
|
@@ -71,8 +71,8 @@ module RuboCop
|
|
71
71
|
|
72
72
|
def next_one_line_example?(node)
|
73
73
|
next_sibling = node.right_sibling
|
74
|
-
return unless next_sibling
|
75
|
-
return unless example?(next_sibling)
|
74
|
+
return false unless next_sibling
|
75
|
+
return false unless example?(next_sibling)
|
76
76
|
|
77
77
|
next_sibling.single_line?
|
78
78
|
end
|
@@ -7,6 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# RSpec allows for auto-generated example descriptions when there is no
|
9
9
|
# description provided or the description is an empty one.
|
10
|
+
# It is acceptable to use `specify` without a description
|
10
11
|
#
|
11
12
|
# This cop removes empty descriptions.
|
12
13
|
# It also defines whether auto-generated description is allowed, based
|
@@ -14,17 +15,24 @@ module RuboCop
|
|
14
15
|
#
|
15
16
|
# This cop can be configured using the `EnforcedStyle` option
|
16
17
|
#
|
18
|
+
# @example
|
19
|
+
# # always good
|
20
|
+
# specify do
|
21
|
+
# result = service.call
|
22
|
+
# expect(result).to be(true)
|
23
|
+
# end
|
24
|
+
#
|
17
25
|
# @example `EnforcedStyle: always_allow` (default)
|
18
26
|
# # bad
|
19
27
|
# it('') { is_expected.to be_good }
|
20
|
-
#
|
28
|
+
# specify '' do
|
21
29
|
# result = service.call
|
22
30
|
# expect(result).to be(true)
|
23
31
|
# end
|
24
32
|
#
|
25
33
|
# # good
|
26
34
|
# it { is_expected.to be_good }
|
27
|
-
#
|
35
|
+
# specify do
|
28
36
|
# result = service.call
|
29
37
|
# expect(result).to be(true)
|
30
38
|
# end
|
@@ -75,6 +83,7 @@ module RuboCop
|
|
75
83
|
def check_example_without_description(node)
|
76
84
|
return if node.arguments?
|
77
85
|
return unless disallow_empty_description?(node)
|
86
|
+
return if node.method?(:specify) && node.parent.multiline?
|
78
87
|
|
79
88
|
add_offense(node, message: MSG_ADD_DESCRIPTION)
|
80
89
|
end
|