rubocop-rspec 2.18.1 → 2.20.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 +37 -2
- data/README.md +1 -1
- data/config/default.yml +46 -1
- data/lib/rubocop/cop/rspec/be_empty.rb +44 -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 +56 -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 +7 -5
- 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/empty_line_after_example_group.rb +1 -1
- 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_actual.rb +2 -2
- 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/consistent_parentheses_style.rb +3 -3
- 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/indexed_let.rb +76 -0
- 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 +59 -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 +74 -36
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +9 -35
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +8 -5
- data/lib/rubocop/cop/rspec/rails/http_status.rb +89 -33
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +4 -4
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +5 -5
- 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 +65 -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/scattered_setup.rb +23 -6
- 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 +7 -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 +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ebfcc955ecfa8b3437defde668d955020f03a2dbba2c9337f0b75a8fb9a3c26
|
4
|
+
data.tar.gz: 7a547b1e24c278de072b2c912be27e1dc5fb1450b6fa65d563278d0f054d6d1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8942cdf262718de32bfbc765e3f2aac9eae49e364d7a2d866300b77e0bd39fd24b168d513577a1a95a82ce10a0f325a66c6b2914da71dd3951011c2399b0b3e
|
7
|
+
data.tar.gz: 89c8fce01b42c53c50460b9411cd44f96b99663ce3a2e7735e6cb0f260c1cc3a86ba0daba553b4ebeba25625dde25f41d8b2129929cf92514e06e0f0f8191ec5
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,38 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.20.0 (2023-04-18)
|
6
|
+
|
7
|
+
- Add new `RSpec/IndexedLet` cop. ([@dmitrytsepelev])
|
8
|
+
- Add new `RSpec/BeEmpty` cop. ([@ydah], [@bquorning])
|
9
|
+
- Add autocorrect support for `RSpec/ScatteredSetup`. ([@ydah])
|
10
|
+
- Add support `be_status` style for `RSpec/Rails/HttpStatus`. ([@ydah])
|
11
|
+
- Add support for shared example groups to `RSpec/EmptyLineAfterExampleGroup`. ([@pirj])
|
12
|
+
- Add support for `RSpec/HaveHttpStatus` when using `response.code`. ([@ydah])
|
13
|
+
- Fix order of expected and actual in correction for `RSpec/Rails/MinitestAssertions` ([@mvz])
|
14
|
+
- Fix a false positive for `RSpec/DescribedClassModuleWrapping` when RSpec.describe numblock is nested within a module. ([@ydah])
|
15
|
+
- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` inside `&&`, `||` and `:?` when `omit_parentheses` is on ([@dmitrytsepelev])
|
16
|
+
- Fix a false positive for `RSpec/PendingWithoutReason` when pending/skip has a reason inside an example group. ([@ydah])
|
17
|
+
- Fix a false negative for `RSpec/RedundantAround` when redundant numblock `around`. ([@ydah])
|
18
|
+
- Change `RSpec/ContainExactly` to ignore calls with no arguments, and change `RSpec/MatchArray` to ignore calls with an empty array literal argument. ([@ydah], [@bquorning])
|
19
|
+
- Make `RSpec/MatchArray` and `RSpec/ContainExactly` pending. ([@ydah])
|
20
|
+
|
21
|
+
## 2.19.0 (2023-03-06)
|
22
|
+
|
23
|
+
- Fix a false positive for `RSpec/ContextWording` when context is interpolated string literal or execute string. ([@ydah])
|
24
|
+
- Fix a false positive for `RSpec/DescribeMethod` when multi-line describe without `#` and `.` at the beginning. ([@ydah], [@pirj])
|
25
|
+
- Fix a false positive for `RSpec/VariableName` when inside non-spec code. ([@ydah])
|
26
|
+
- Fix a false positive for `RSpec/VariableDefinition` when inside non-spec code. ([@ydah])
|
27
|
+
- Add new `RSpec/PendingBlockInsideExample` cop. ([@ydah])
|
28
|
+
- Add `RSpec/RedundantAround` cop. ([@r7kamura])
|
29
|
+
- Add `RSpec/Rails/TravelAround` cop. ([@r7kamura])
|
30
|
+
- Add `RSpec/ContainExactly` and `RSpec/MatchArray` cops. ([@faucct])
|
31
|
+
- Fix a false positive for `RSpec/PendingWithoutReason` when not inside example and pending/skip with block. ([@ydah], [@pirj])
|
32
|
+
- Fix a false positive for `RSpec/PendingWithoutReason` when `skip` is passed a block inside example. ([@ydah], [@pirj])
|
33
|
+
- Rename `RSpec/PendingBlockInsideExample` cop to `RSpec/SkipBlockInsideExample`. ([@pirj])
|
34
|
+
- Deprecate `send_pattern`/`block_pattern`/`numblock_pattern` helpers in favour of using node pattern explicitly. ([@pirj], [@ydah])
|
35
|
+
- Fix an incorrect autocorrect for `RSpec/VerifiedDoubleReference` when namespaced class. ([@ydah])
|
36
|
+
|
5
37
|
## 2.18.1 (2023-01-19)
|
6
38
|
|
7
39
|
- Add `rubocop-capybara` version constraint to prevent sudden cop enabling when it hits 3.0. ([@pirj])
|
@@ -313,7 +345,7 @@
|
|
313
345
|
## 1.37.0 (2019-11-25)
|
314
346
|
|
315
347
|
- Implement `RSpec/DescribedClassModuleWrapping` to disallow RSpec statements within a module. ([@kellysutton])
|
316
|
-
- Fix documentation rake task to support
|
348
|
+
- Fix documentation rake task to support RuboCop 0.75. ([@nickcampbell18])
|
317
349
|
- Fix `RSpec/SubjectStub` to detect implicit subjects stubbed. ([@QQism])
|
318
350
|
- Fix `RSpec/Pending` not flagging `skip` with string values. ([@pirj])
|
319
351
|
- Add `AllowedExplicitMatchers` config option for `RSpec/PredicateMatcher`. ([@mkrawc])
|
@@ -644,7 +676,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
644
676
|
- Skip `DescribeClass` cop for view specs. ([@andyw8])
|
645
677
|
- Skip `FilePath` cop for Rails routing specs. ([@andyw8])
|
646
678
|
- Add cop to check for focused specs. ([@renanborgescampos], [@jaredmoody])
|
647
|
-
- Clean-up `RSpec::NotToNot` to use same configuration semantics as other
|
679
|
+
- Clean-up `RSpec::NotToNot` to use same configuration semantics as other RuboCop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal])
|
648
680
|
- Update to rubocop 0.40.0. ([@nijikon])
|
649
681
|
|
650
682
|
## 1.4.1 (2016-04-03)
|
@@ -742,6 +774,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
742
774
|
[@dduugg]: https://github.com/dduugg
|
743
775
|
[@deivid-rodriguez]: https://github.com/deivid-rodriguez
|
744
776
|
[@dgollahon]: https://github.com/dgollahon
|
777
|
+
[@dmitrytsepelev]: https://github.com/dmitrytsepelev
|
745
778
|
[@drowze]: https://github.com/Drowze
|
746
779
|
[@dswij]: https://github.com/dswij
|
747
780
|
[@dvandersluis]: https://github.com/dvandersluis
|
@@ -751,6 +784,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
751
784
|
[@elebow]: https://github.com/elebow
|
752
785
|
[@elisefitz15]: https://github.com/EliseFitz15
|
753
786
|
[@elliterate]: https://github.com/elliterate
|
787
|
+
[@faucct]: https://github.com/faucct
|
754
788
|
[@foton]: https://github.com/foton
|
755
789
|
[@francois-ferrandis]: https://github.com/francois-ferrandis
|
756
790
|
[@g-rath]: https://github.com/G-Rath
|
@@ -783,6 +817,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
783
817
|
[@mlarraz]: https://github.com/mlarraz
|
784
818
|
[@mockdeep]: https://github.com/mockdeep
|
785
819
|
[@mothonmars]: https://github.com/MothOnMars
|
820
|
+
[@mvz]: https://github.com/mvz
|
786
821
|
[@nc-holodakg]: https://github.com/nc-holodakg
|
787
822
|
[@nevir]: https://github.com/nevir
|
788
823
|
[@ngouy]: https://github.com/ngouy
|
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
@@ -144,6 +144,12 @@ RSpec/Be:
|
|
144
144
|
StyleGuide: https://rspec.rubystyle.guide/#be-matcher
|
145
145
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be
|
146
146
|
|
147
|
+
RSpec/BeEmpty:
|
148
|
+
Description: Prefer using `be_empty` when checking for an empty array.
|
149
|
+
Enabled: pending
|
150
|
+
VersionAdded: '2.20'
|
151
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEmpty
|
152
|
+
|
147
153
|
RSpec/BeEq:
|
148
154
|
Description: Check for expectations where `be(...)` can replace `eq(...)`.
|
149
155
|
Enabled: pending
|
@@ -201,6 +207,12 @@ RSpec/ClassCheck:
|
|
201
207
|
- be_kind_of
|
202
208
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ClassCheck
|
203
209
|
|
210
|
+
RSpec/ContainExactly:
|
211
|
+
Description: Checks where `contain_exactly` is used.
|
212
|
+
Enabled: pending
|
213
|
+
VersionAdded: '2.19'
|
214
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContainExactly
|
215
|
+
|
204
216
|
RSpec/ContextMethod:
|
205
217
|
Description: "`context` should not be used for specifying methods."
|
206
218
|
Enabled: true
|
@@ -497,6 +509,13 @@ RSpec/ImplicitSubject:
|
|
497
509
|
VersionChanged: '2.13'
|
498
510
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject
|
499
511
|
|
512
|
+
RSpec/IndexedLet:
|
513
|
+
Description: Do not set up test data using indexes (e.g., `item_1`, `item_2`).
|
514
|
+
Enabled: pending
|
515
|
+
VersionAdded: '2.20'
|
516
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IndexedLet
|
517
|
+
Max: 1
|
518
|
+
|
500
519
|
RSpec/InstanceSpy:
|
501
520
|
Description: Checks for `instance_double` used with `have_received`.
|
502
521
|
Enabled: true
|
@@ -556,6 +575,12 @@ RSpec/LetSetup:
|
|
556
575
|
VersionAdded: '1.7'
|
557
576
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup
|
558
577
|
|
578
|
+
RSpec/MatchArray:
|
579
|
+
Description: Checks where `match_array` is used.
|
580
|
+
Enabled: pending
|
581
|
+
VersionAdded: '2.19'
|
582
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MatchArray
|
583
|
+
|
559
584
|
RSpec/MessageChain:
|
560
585
|
Description: Check that chains of messages are not being stubbed.
|
561
586
|
Enabled: true
|
@@ -706,6 +731,12 @@ RSpec/ReceiveNever:
|
|
706
731
|
VersionAdded: '1.28'
|
707
732
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever
|
708
733
|
|
734
|
+
RSpec/RedundantAround:
|
735
|
+
Description: Remove redundant `around` hook.
|
736
|
+
Enabled: pending
|
737
|
+
VersionAdded: '2.19'
|
738
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantAround
|
739
|
+
|
709
740
|
RSpec/RepeatedDescription:
|
710
741
|
Description: Check for repeated description strings in example groups.
|
711
742
|
Enabled: true
|
@@ -779,6 +810,12 @@ RSpec/SingleArgumentMessageChain:
|
|
779
810
|
VersionChanged: '1.10'
|
780
811
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain
|
781
812
|
|
813
|
+
RSpec/SkipBlockInsideExample:
|
814
|
+
Description: Checks for passing a block to `skip` within examples.
|
815
|
+
Enabled: pending
|
816
|
+
VersionAdded: '2.19'
|
817
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SkipBlockInsideExample
|
818
|
+
|
782
819
|
RSpec/SortMetadata:
|
783
820
|
Description: Sort RSpec metadata alphabetically.
|
784
821
|
Enabled: pending
|
@@ -1024,8 +1061,9 @@ RSpec/Rails/HttpStatus:
|
|
1024
1061
|
SupportedStyles:
|
1025
1062
|
- numeric
|
1026
1063
|
- symbolic
|
1064
|
+
- be_status
|
1027
1065
|
VersionAdded: '1.23'
|
1028
|
-
VersionChanged: '2.
|
1066
|
+
VersionChanged: '2.20'
|
1029
1067
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus
|
1030
1068
|
|
1031
1069
|
RSpec/Rails/InferredSpecType:
|
@@ -1056,3 +1094,10 @@ RSpec/Rails/MinitestAssertions:
|
|
1056
1094
|
Enabled: pending
|
1057
1095
|
VersionAdded: '2.17'
|
1058
1096
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions
|
1097
|
+
|
1098
|
+
RSpec/Rails/TravelAround:
|
1099
|
+
Description: Prefer to travel in `before` rather than `around`.
|
1100
|
+
Enabled: pending
|
1101
|
+
Safe: false
|
1102
|
+
VersionAdded: '2.19'
|
1103
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/TravelAround
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Prefer using `be_empty` when checking for an empty array.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# expect(array).to contain_exactly
|
11
|
+
# expect(array).to match_array([])
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# expect(array).to be_empty
|
15
|
+
#
|
16
|
+
class BeEmpty < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
19
|
+
MSG = 'Use `be_empty` matchers for checking an empty array.'
|
20
|
+
RESTRICT_ON_SEND = %i[contain_exactly match_array].freeze
|
21
|
+
|
22
|
+
# @!method expect_array_matcher?(node)
|
23
|
+
def_node_matcher :expect_array_matcher?, <<~PATTERN
|
24
|
+
(send
|
25
|
+
(send nil? :expect _)
|
26
|
+
#Runners.all
|
27
|
+
${
|
28
|
+
(send nil? :match_array (array))
|
29
|
+
(send nil? :contain_exactly)
|
30
|
+
}
|
31
|
+
)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_send(node)
|
35
|
+
expect_array_matcher?(node.parent) do |expect|
|
36
|
+
add_offense(expect) do |corrector|
|
37
|
+
corrector.replace(expect, 'be_empty')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -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, '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, '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,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks where `contain_exactly` is used.
|
7
|
+
#
|
8
|
+
# This cop checks for the following:
|
9
|
+
# - Prefer `match_array` when matching array values.
|
10
|
+
# - Prefer `be_empty` when using `contain_exactly` with no arguments.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # bad
|
14
|
+
# it { is_expected.to contain_exactly(*array1, *array2) }
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# it { is_expected.to match_array(array1 + array2) }
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# it { is_expected.to contain_exactly(content, *array) }
|
21
|
+
#
|
22
|
+
class ContainExactly < Base
|
23
|
+
extend AutoCorrector
|
24
|
+
|
25
|
+
MSG = 'Prefer `match_array` when matching array values.'
|
26
|
+
RESTRICT_ON_SEND = %i[contain_exactly].freeze
|
27
|
+
|
28
|
+
def on_send(node)
|
29
|
+
return if node.arguments.empty?
|
30
|
+
|
31
|
+
check_populated_collection(node)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def check_populated_collection(node)
|
37
|
+
return unless node.each_child_node.all?(&:splat_type?)
|
38
|
+
|
39
|
+
add_offense(node) do |corrector|
|
40
|
+
autocorrect_for_populated_array(node, corrector)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def autocorrect_for_populated_array(node, corrector)
|
45
|
+
arrays = node.arguments.map do |splat_node|
|
46
|
+
splat_node.children.first
|
47
|
+
end
|
48
|
+
corrector.replace(
|
49
|
+
node,
|
50
|
+
"match_array(#{arrays.map(&:source).join(' + ')})"
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
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}'
|
@@ -22,13 +22,15 @@ module RuboCop
|
|
22
22
|
class DescribedClassModuleWrapping < Base
|
23
23
|
MSG = 'Avoid opening modules and defining specs within them.'
|
24
24
|
|
25
|
-
# @!method
|
26
|
-
def_node_search :
|
25
|
+
# @!method include_rspec_blocks?(node)
|
26
|
+
def_node_search :include_rspec_blocks?, <<~PATTERN
|
27
|
+
({block numblock} (send #explicit_rspec? #ExampleGroups.all ...) ...)
|
28
|
+
PATTERN
|
27
29
|
|
28
30
|
def on_module(node)
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
return unless include_rspec_blocks?(node)
|
32
|
+
|
33
|
+
add_offense(node)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
@@ -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
|
@@ -30,7 +30,7 @@ module RuboCop
|
|
30
30
|
MSG = 'Add an empty line after `%<example_group>s`.'
|
31
31
|
|
32
32
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
33
|
-
return unless
|
33
|
+
return unless spec_group?(node)
|
34
34
|
|
35
35
|
missing_separating_line_offense(node) do |method|
|
36
36
|
format(MSG, example_group: method)
|
@@ -93,8 +93,8 @@ module RuboCop
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def swap(corrector, actual, expected)
|
96
|
-
corrector.replace(actual
|
97
|
-
corrector.replace(expected
|
96
|
+
corrector.replace(actual, expected.source)
|
97
|
+
corrector.replace(expected, actual.source)
|
98
98
|
end
|
99
99
|
end
|
100
100
|
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
|
@@ -100,10 +100,10 @@ module RuboCop
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
AMBIGUOUS_TYPES = %i[send pair array and or if].freeze
|
104
|
+
|
103
105
|
def ambiguous_without_parentheses?(node)
|
104
|
-
node.parent
|
105
|
-
node.parent&.pair_type? ||
|
106
|
-
node.parent&.array_type?
|
106
|
+
node.parent && AMBIGUOUS_TYPES.include?(node.parent.type)
|
107
107
|
end
|
108
108
|
|
109
109
|
def remove_parentheses(corrector, node)
|
@@ -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
|