rubocop-rspec 2.25.0 → 2.27.1
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 +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
|