rubocop-rspec 2.23.2 → 2.25.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 +35 -13
- data/config/default.yml +48 -1
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
- data/lib/rubocop/cop/rspec/eq.rb +47 -0
- data/lib/rubocop/cop/rspec/example_length.rb +11 -5
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +3 -1
- data/lib/rubocop/cop/rspec/file_path.rb +6 -0
- data/lib/rubocop/cop/rspec/focus.rb +2 -0
- data/lib/rubocop/cop/rspec/metadata_style.rb +202 -0
- data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +21 -7
- data/lib/rubocop/cop/rspec/rails/http_status.rb +28 -17
- data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +6 -0
- data/lib/rubocop/cop/rspec/receive_messages.rb +1 -1
- data/lib/rubocop/cop/rspec/sort_metadata.rb +2 -1
- data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
- data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
- data/lib/rubocop/cop/rspec/variable_definition.rb +2 -2
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +5 -5
- data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +5 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +1 -0
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afb5cf0c88af50530fc023549eb7e9083db3ca2314553f1fca912ea2a3c47bdb
|
4
|
+
data.tar.gz: ba30f926d9cd3056e786f724140ac4358af527496b2e783fcc5c8e541adc9d13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd7955549b3b95b481eb5dea24b98f72e1b802546f8e090695a782a20b0ee8d1d0bcca9a6089f3a46718c5a14967de6c8473709ecea72d8aa5eae85e2cb5bd6f
|
7
|
+
data.tar.gz: 2beb193cf65884c363c2ece1a3a7ba5db39eecc3a579724bd39f29696ab29276def06261363b6a6290d378743e0b79d414e056b65f0a8a9e2e4215a417d9b978
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,26 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.25.0 (2023-10-27)
|
6
|
+
|
7
|
+
- Add support single quoted string and percent string and heredoc for `RSpec/Rails/HttpStatus`. ([@ydah])
|
8
|
+
- Change to be inline disable for `RSpec/SpecFilePathFormat` like `RSpec/FilePath`. ([@ydah])
|
9
|
+
- Fix a false positive for `RSpec/MetadataStyle` with example groups having multiple string arguments. ([@franzliedke])
|
10
|
+
|
11
|
+
## 2.24.1 (2023-09-23)
|
12
|
+
|
13
|
+
- Fix an error when using `RSpec/FilePath` and revert to enabled by default. If you have already moved to `RSpec/SpecFilePathSuffix` and `RSpec/SpecFilePathFormat`, disable `RSpec/FilePath` explicitly as `Enabled: false`. The `RSpec/FilePath` before migration and the `RSpec/SpecFilePathSuffix` and `RSpec/SpecFilePathFormat` as the target are available respectively. ([@ydah])
|
14
|
+
|
15
|
+
## 2.24.0 (2023-09-08)
|
16
|
+
|
17
|
+
- Split `RSpec/FilePath` into `RSpec/SpecFilePathSuffix` and `RSpec/SpecFilePathFormat`. `RSpec/FilePath` cop is disabled by default and the two new cops are pending and need to be enabled explicitly. ([@ydah])
|
18
|
+
- Add new `RSpec/Eq` cop. ([@ydah])
|
19
|
+
- Add `RSpec/MetadataStyle` and `RSpec/EmptyMetadata` cops. ([@r7kamura])
|
20
|
+
- Add support `RSpec/Rails/HttpStatus` when `have_http_status` with string argument. ([@ydah])
|
21
|
+
- Fix an infinite loop error when `RSpec/ExcessiveDocstringSpacing` finds a description with non-ASCII leading/trailing whitespace. ([@bcgraham])
|
22
|
+
- Fix an incorrect autocorrect for `RSpec/ReceiveMessages` when return values declared between stubs. ([@marocchino])
|
23
|
+
- Fix a false positive `RSpec/Focus` when chained method call and inside define method. ([@ydah])
|
24
|
+
|
5
25
|
## 2.23.2 (2023-08-09)
|
6
26
|
|
7
27
|
- Fix an incorrect autocorrect for `RSpec/ReceiveMessages` when method is only non-word character. ([@marocchino])
|
@@ -9,7 +29,7 @@
|
|
9
29
|
|
10
30
|
## 2.23.1 (2023-08-07)
|
11
31
|
|
12
|
-
- Mark to `Safe: false` for `RSpec/Rails/NegationBeValid`
|
32
|
+
- Mark to `Safe: false` for `RSpec/Rails/NegationBeValid` cop. ([@ydah])
|
13
33
|
- Declare autocorrect as unsafe for `RSpec/ReceiveMessages`. ([@bquorning])
|
14
34
|
|
15
35
|
## 2.23.0 (2023-07-30)
|
@@ -18,13 +38,13 @@
|
|
18
38
|
- Fix a false negative for `RSpec/ExcessiveDocstringSpacing` when finds description with em space. ([@ydah])
|
19
39
|
- Fix a false positive for `RSpec/EmptyExampleGroup` when example group with examples defined in `if` branch inside iterator. ([@ydah])
|
20
40
|
- Update the message output of `RSpec/ExpectActual` to include the word 'value'. ([@corydiamand])
|
21
|
-
- Fix a false negative for `RSpec/Pending` when
|
41
|
+
- Fix a false negative for `RSpec/Pending` when `it` without body. ([@ydah])
|
22
42
|
- Add new `RSpec/ReceiveMessages` cop. ([@ydah])
|
23
43
|
- Change default.yml path to use `**/spec/*` instead of `spec/*`. ([@ydah])
|
24
|
-
- Add `AllowedIdentifiers` and `AllowedPatterns` configuration option to `RSpec/IndexedLet`.
|
44
|
+
- Add `AllowedIdentifiers` and `AllowedPatterns` configuration option to `RSpec/IndexedLet`. ([@ydah])
|
25
45
|
- Fix `RSpec/NamedSubject` when block has no body. ([@splattael])
|
26
46
|
- Fix `RSpec/LetBeforeExamples` autocorrect incompatible with `RSpec/ScatteredLet` autocorrect. ([@ydah])
|
27
|
-
- Update `RSpec/Focus` to support `shared_context` and `shared_examples
|
47
|
+
- Update `RSpec/Focus` to support `shared_context` and `shared_examples`. ([@tmaier])
|
28
48
|
|
29
49
|
## 2.22.0 (2023-05-06)
|
30
50
|
|
@@ -46,9 +66,9 @@
|
|
46
66
|
- Add support `be_status` style for `RSpec/Rails/HttpStatus`. ([@ydah])
|
47
67
|
- Add support for shared example groups to `RSpec/EmptyLineAfterExampleGroup`. ([@pirj])
|
48
68
|
- Add support for `RSpec/HaveHttpStatus` when using `response.code`. ([@ydah])
|
49
|
-
- Fix order of expected and actual in correction for `RSpec/Rails/MinitestAssertions
|
69
|
+
- Fix order of expected and actual in correction for `RSpec/Rails/MinitestAssertions`. ([@mvz])
|
50
70
|
- Fix a false positive for `RSpec/DescribedClassModuleWrapping` when RSpec.describe numblock is nested within a module. ([@ydah])
|
51
|
-
- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` inside `&&`, `||` and `:?` when `omit_parentheses` is on ([@dmitrytsepelev])
|
71
|
+
- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` inside `&&`, `||` and `:?` when `omit_parentheses` is on. ([@dmitrytsepelev])
|
52
72
|
- Fix a false positive for `RSpec/PendingWithoutReason` when pending/skip has a reason inside an example group. ([@ydah])
|
53
73
|
- Fix a false negative for `RSpec/RedundantAround` when redundant numblock `around`. ([@ydah])
|
54
74
|
- Change `RSpec/ContainExactly` to ignore calls with no arguments, and change `RSpec/MatchArray` to ignore calls with an empty array literal argument. ([@ydah], [@bquorning])
|
@@ -101,7 +121,7 @@
|
|
101
121
|
- Improved processing speed for `RSpec/Be`, `RSpec/ExpectActual`, `RSpec/ImplicitExpect`, `RSpec/MessageSpies`, `RSpec/PredicateMatcher` and `RSpec/Rails/HaveHttpStatus`. ([@ydah])
|
102
122
|
- Fix wrong autocorrection in `n_times` style on `RSpec/FactoryBot/CreateList`. ([@r7kamura])
|
103
123
|
- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` when using `generate` with multiple arguments. ([@ydah])
|
104
|
-
- Mark `RSpec/BeEq` as `Safe: false
|
124
|
+
- Mark `RSpec/BeEq` as `Safe: false`. ([@r7kamura])
|
105
125
|
- Add `RSpec/DuplicatedMetadata` cop. ([@r7kamura])
|
106
126
|
- Mark `RSpec/BeEql` as `Safe: false`. ([@r7kamura])
|
107
127
|
- Add `RSpec/PendingWithoutReason` cop. ([@r7kamura])
|
@@ -134,8 +154,8 @@
|
|
134
154
|
- Fix a false positive for `RSpec/Capybara/SpecificMatcher` when `have_css("a")` without attribute. ([@ydah])
|
135
155
|
- Update `RSpec/ExampleWording` cop to raise error for insufficient descriptions. ([@akrox58])
|
136
156
|
- Add new `RSpec/Capybara/NegationMatcher` cop. ([@ydah])
|
137
|
-
- Add `AllowedPatterns` configuration option to `RSpec/NoExpectationExample`.
|
138
|
-
- Improve `RSpec/NoExpectationExample` cop to ignore examples skipped or pending via metadata.
|
157
|
+
- Add `AllowedPatterns` configuration option to `RSpec/NoExpectationExample`. ([@ydah])
|
158
|
+
- Improve `RSpec/NoExpectationExample` cop to ignore examples skipped or pending via metadata. ([@pirj])
|
139
159
|
- Add `RSpec/FactoryBot/ConsistentParenthesesStyle` cop. ([@Liberatys])
|
140
160
|
- Add `RSpec/Rails/InferredSpecType` cop. ([@r7kamura])
|
141
161
|
- Add new `RSpec/Capybara/SpecificActions` cop. ([@ydah])
|
@@ -451,7 +471,7 @@
|
|
451
471
|
- Add config to `RSpec/VerifiedDoubles` to enforcement of verification on unnamed doubles. ([@BrentWheeldon])
|
452
472
|
- Fix `FactoryBot/AttributeDefinedStatically` not working when there is a non-symbol key. ([@vzvu3k6k])
|
453
473
|
- Fix false positive in `RSpec/ImplicitSubject` when `is_expected` is used inside `its()` block. ([@Darhazer])
|
454
|
-
- Add `single_statement_only` style to
|
474
|
+
- Add `single_statement_only` style to `RSpec/ImplicitSubject` as a more relaxed alternative to `single_line_only`. ([@Darhazer])
|
455
475
|
- Add `RSpec/UnspecifiedException` as a default cop to encourage more-specific `expect{}.to raise_error(ExceptionType)`, or `raise_exception` style handling of exceptions. ([@daveworth])
|
456
476
|
|
457
477
|
## 1.29.1 (2018-09-01)
|
@@ -486,14 +506,14 @@
|
|
486
506
|
|
487
507
|
## 1.26.0 (2018-06-06)
|
488
508
|
|
489
|
-
- Fix false positive in `RSpec/EmptyExampleGroup` cop when methods named like a RSpec method are used.
|
509
|
+
- Fix false positive in `RSpec/EmptyExampleGroup` cop when methods named like a RSpec method are used. ([@Darhazer])
|
490
510
|
- Fix `Capybara/FeatureMethods` not working when there is require before the spec. ([@Darhazer])
|
491
511
|
- Fix `RSpec/EmptyLineAfterFinalLet`: allow a comment to be placed after latest let, requiring empty line after the comment. ([@Darhazer])
|
492
512
|
- Add `RSpec/ReceiveCounts` cop to enforce usage of :once and :twice matchers. ([@Darhazer])
|
493
513
|
|
494
514
|
## 1.25.1 (2018-04-10)
|
495
515
|
|
496
|
-
- Fix false positive in `RSpec/Pending` cop when pending is used as a method name.
|
516
|
+
- Fix false positive in `RSpec/Pending` cop when pending is used as a method name. ([@Darhazer])
|
497
517
|
- Fix `FactoryBot/DynamicAttributeDefinedStatically` false positive when using symbol proc argument for a sequence. ([@tdeo])
|
498
518
|
|
499
519
|
## 1.25.0 (2018-04-07)
|
@@ -501,7 +521,7 @@
|
|
501
521
|
- Add `RSpec/SharedExamples` cop to enforce consistent usage of string to titleize shared examples. ([@anthony-robin])
|
502
522
|
- Add `RSpec/Be` cop to enforce passing argument to the generic `be` matcher. ([@Darhazer])
|
503
523
|
- Fix false positives in `StaticAttributeDefinedDynamically` and `ReturnFromStub` when a const is used in an array or hash. ([@Darhazer])
|
504
|
-
- Add `RSpec/Pending` cop to enforce no existing pending or skipped examples.
|
524
|
+
- Add `RSpec/Pending` cop to enforce no existing pending or skipped examples. This is disabled by default. ([@patrickomatic])
|
505
525
|
- Fix `RSpec/NestedGroups` cop support --auto-gen-config. ([@walf443])
|
506
526
|
- Fix false positives in `Capybara/FeatureMethods` when feature methods are used as property names in a factory. ([@Darhazer])
|
507
527
|
- Allow configuring enabled methods in `Capybara/FeatureMethods`. ([@Darhazer])
|
@@ -797,6 +817,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
797
817
|
[@aried3r]: https://github.com/aried3r
|
798
818
|
[@baberthal]: https://github.com/baberthal
|
799
819
|
[@backus]: https://github.com/backus
|
820
|
+
[@bcgraham]: https://github.com/bcgraham
|
800
821
|
[@biinari]: https://github.com/biinari
|
801
822
|
[@bmorrall]: https://github.com/bmorrall
|
802
823
|
[@bquorning]: https://github.com/bquorning
|
@@ -824,6 +845,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
824
845
|
[@faucct]: https://github.com/faucct
|
825
846
|
[@foton]: https://github.com/foton
|
826
847
|
[@francois-ferrandis]: https://github.com/francois-ferrandis
|
848
|
+
[@franzliedke]: https://github.com/franzliedke
|
827
849
|
[@g-rath]: https://github.com/G-Rath
|
828
850
|
[@geniou]: https://github.com/geniou
|
829
851
|
[@gsamokovarov]: https://github.com/gsamokovarov
|
data/config/default.yml
CHANGED
@@ -359,6 +359,18 @@ RSpec/EmptyLineAfterSubject:
|
|
359
359
|
StyleGuide: https://rspec.rubystyle.guide/#empty-line-after-let
|
360
360
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject
|
361
361
|
|
362
|
+
RSpec/EmptyMetadata:
|
363
|
+
Description: Avoid empty metadata hash.
|
364
|
+
Enabled: pending
|
365
|
+
VersionAdded: '2.24'
|
366
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyMetadata
|
367
|
+
|
368
|
+
RSpec/Eq:
|
369
|
+
Description: Use `eq` instead of `be ==` to compare objects.
|
370
|
+
Enabled: pending
|
371
|
+
VersionAdded: '2.24'
|
372
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Eq
|
373
|
+
|
362
374
|
RSpec/ExampleLength:
|
363
375
|
Description: Checks for long examples.
|
364
376
|
Enabled: true
|
@@ -446,7 +458,7 @@ RSpec/FilePath:
|
|
446
458
|
IgnoreMethods: false
|
447
459
|
SpecSuffixOnly: false
|
448
460
|
VersionAdded: '1.2'
|
449
|
-
VersionChanged: '
|
461
|
+
VersionChanged: '2.24'
|
450
462
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FilePath
|
451
463
|
|
452
464
|
RSpec/Focus:
|
@@ -613,6 +625,16 @@ RSpec/MessageSpies:
|
|
613
625
|
VersionAdded: '1.9'
|
614
626
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageSpies
|
615
627
|
|
628
|
+
RSpec/MetadataStyle:
|
629
|
+
Description: Use consistent metadata style.
|
630
|
+
Enabled: pending
|
631
|
+
EnforcedStyle: symbol
|
632
|
+
SupportedStyles:
|
633
|
+
- hash
|
634
|
+
- symbol
|
635
|
+
VersionAdded: '2.24'
|
636
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MetadataStyle
|
637
|
+
|
616
638
|
RSpec/MissingExampleGroupArgument:
|
617
639
|
Description: Checks that the first argument to an example group is not empty.
|
618
640
|
Enabled: true
|
@@ -834,6 +856,31 @@ RSpec/SortMetadata:
|
|
834
856
|
VersionAdded: '2.14'
|
835
857
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SortMetadata
|
836
858
|
|
859
|
+
RSpec/SpecFilePathFormat:
|
860
|
+
Description: Checks that spec file paths are consistent and well-formed.
|
861
|
+
Enabled: pending
|
862
|
+
Include:
|
863
|
+
- "**/*_spec.rb"
|
864
|
+
Exclude:
|
865
|
+
- "**/spec/routing/**/*"
|
866
|
+
CustomTransform:
|
867
|
+
RuboCop: rubocop
|
868
|
+
RSpec: rspec
|
869
|
+
IgnoreMethods: false
|
870
|
+
IgnoreMetadata:
|
871
|
+
type: routing
|
872
|
+
VersionAdded: '2.24'
|
873
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathFormat
|
874
|
+
|
875
|
+
RSpec/SpecFilePathSuffix:
|
876
|
+
Description: Checks that spec file paths suffix are consistent and well-formed.
|
877
|
+
Enabled: pending
|
878
|
+
VersionAdded: '2.24'
|
879
|
+
Include:
|
880
|
+
- "**/*_spec*rb*"
|
881
|
+
- "**/spec/**/*"
|
882
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathSuffix
|
883
|
+
|
837
884
|
RSpec/StubbedMock:
|
838
885
|
Description: Checks that message expectations do not have a configured response.
|
839
886
|
Enabled: true
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Avoid empty metadata hash.
|
7
|
+
#
|
8
|
+
# @example EnforcedStyle: symbol (default)
|
9
|
+
# # bad
|
10
|
+
# describe 'Something', {}
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# describe 'Something'
|
14
|
+
class EmptyMetadata < Base
|
15
|
+
extend AutoCorrector
|
16
|
+
|
17
|
+
include Metadata
|
18
|
+
include RangeHelp
|
19
|
+
|
20
|
+
MSG = 'Avoid empty metadata hash.'
|
21
|
+
|
22
|
+
def on_metadata(_symbols, hash)
|
23
|
+
return unless hash&.pairs&.empty?
|
24
|
+
|
25
|
+
add_offense(hash) do |corrector|
|
26
|
+
remove_empty_metadata(corrector, hash)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def remove_empty_metadata(corrector, node)
|
33
|
+
corrector.remove(
|
34
|
+
range_with_surrounding_comma(
|
35
|
+
range_with_surrounding_space(
|
36
|
+
node.source_range,
|
37
|
+
side: :left
|
38
|
+
),
|
39
|
+
:left
|
40
|
+
)
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Use `eq` instead of `be ==` to compare objects.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# expect(foo).to be == 42
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# expect(foo).to eq 42
|
14
|
+
#
|
15
|
+
class Eq < Base
|
16
|
+
extend AutoCorrector
|
17
|
+
include RangeHelp
|
18
|
+
|
19
|
+
MSG = 'Use `eq` instead of `be ==` to compare objects.'
|
20
|
+
RESTRICT_ON_SEND = Runners.all
|
21
|
+
|
22
|
+
# @!method be_equals(node)
|
23
|
+
def_node_matcher :be_equals, <<~PATTERN
|
24
|
+
(send _ #Runners.all $(send (send nil? :be) :== _))
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
def on_send(node)
|
28
|
+
be_equals(node) do |matcher|
|
29
|
+
range = offense_range(matcher)
|
30
|
+
add_offense(range) do |corrector|
|
31
|
+
corrector.replace(range, 'eq')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def offense_range(matcher)
|
39
|
+
range_between(
|
40
|
+
matcher.source_range.begin_pos,
|
41
|
+
matcher.loc.selector.end_pos
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -26,11 +26,12 @@ module RuboCop
|
|
26
26
|
# expect(result).to be(true)
|
27
27
|
# end
|
28
28
|
#
|
29
|
-
# You can set
|
30
|
-
# Available are: 'array', 'hash', and '
|
31
|
-
# will be counted as one line regardless of
|
29
|
+
# You can set constructs you want to fold with `CountAsOne`.
|
30
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'.
|
31
|
+
# Each construct will be counted as one line regardless of
|
32
|
+
# its actual size.
|
32
33
|
#
|
33
|
-
# @example CountAsOne: ['array', 'heredoc']
|
34
|
+
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
34
35
|
#
|
35
36
|
# it do
|
36
37
|
# array = [ # +1
|
@@ -46,7 +47,12 @@ module RuboCop
|
|
46
47
|
# Heredoc
|
47
48
|
# content.
|
48
49
|
# HEREDOC
|
49
|
-
#
|
50
|
+
#
|
51
|
+
# foo( # +1
|
52
|
+
# 1,
|
53
|
+
# 2
|
54
|
+
# )
|
55
|
+
# end # 6 points
|
50
56
|
#
|
51
57
|
class ExampleLength < Base
|
52
58
|
include CodeLength
|
@@ -66,7 +66,9 @@ module RuboCop
|
|
66
66
|
|
67
67
|
# @param text [String]
|
68
68
|
def strip_excessive_whitespace(text)
|
69
|
-
text
|
69
|
+
text
|
70
|
+
.gsub(/[[:blank:]]{2,}/, ' ')
|
71
|
+
.gsub(/\A[[:blank:]]|[[:blank:]]\z/, '')
|
70
72
|
end
|
71
73
|
|
72
74
|
# @param node [RuboCop::AST::Node]
|
@@ -5,6 +5,12 @@ module RuboCop
|
|
5
5
|
module RSpec
|
6
6
|
# Checks that spec file paths are consistent and well-formed.
|
7
7
|
#
|
8
|
+
# This cop is deprecated.
|
9
|
+
# We plan to remove it in the next major version update to 3.0.
|
10
|
+
# The migration targets are `RSpec/SpecFilePathSuffix`
|
11
|
+
# and `RSpec/SpecFilePathFormat`.
|
12
|
+
# If you are using this cop, please plan for migration.
|
13
|
+
#
|
8
14
|
# By default, this checks that spec file paths are consistent with the
|
9
15
|
# test subject and enforces that it reflects the described
|
10
16
|
# class/module and its optionally called out method.
|
@@ -0,0 +1,202 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Use consistent metadata style.
|
7
|
+
#
|
8
|
+
# This cop does not support autocorrection in the case of
|
9
|
+
# `EnforcedStyle: hash` where the trailing metadata type is ambiguous.
|
10
|
+
# (e.g. `describe 'Something', :a, b`)
|
11
|
+
#
|
12
|
+
# @example EnforcedStyle: symbol (default)
|
13
|
+
# # bad
|
14
|
+
# describe 'Something', a: true
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# describe 'Something', :a
|
18
|
+
#
|
19
|
+
# @example EnforcedStyle: hash
|
20
|
+
# # bad
|
21
|
+
# describe 'Something', :a
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# describe 'Something', a: true
|
25
|
+
class MetadataStyle < Base # rubocop:disable Metrics/ClassLength
|
26
|
+
extend AutoCorrector
|
27
|
+
|
28
|
+
include ConfigurableEnforcedStyle
|
29
|
+
include Metadata
|
30
|
+
include RangeHelp
|
31
|
+
|
32
|
+
# @!method extract_metadata_hash(node)
|
33
|
+
def_node_matcher :extract_metadata_hash, <<~PATTERN
|
34
|
+
(send _ _ _ ... $hash)
|
35
|
+
PATTERN
|
36
|
+
|
37
|
+
# @!method match_boolean_metadata_pair?(node)
|
38
|
+
def_node_matcher :match_boolean_metadata_pair?, <<~PATTERN
|
39
|
+
(pair sym true)
|
40
|
+
PATTERN
|
41
|
+
|
42
|
+
# @!method match_ambiguous_trailing_metadata?(node)
|
43
|
+
def_node_matcher :match_ambiguous_trailing_metadata?, <<~PATTERN
|
44
|
+
(send _ _ _ ... !{hash sym})
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
def on_metadata(symbols, hash)
|
48
|
+
# RSpec example groups accept two string arguments. In such a case,
|
49
|
+
# the rspec_metadata matcher will interpret the second string
|
50
|
+
# argument as a metadata symbol.
|
51
|
+
symbols.shift if symbols.first&.str_type?
|
52
|
+
|
53
|
+
symbols.each do |symbol|
|
54
|
+
on_metadata_symbol(symbol)
|
55
|
+
end
|
56
|
+
|
57
|
+
return unless hash
|
58
|
+
|
59
|
+
hash.pairs.each do |pair|
|
60
|
+
on_metadata_pair(pair)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def autocorrect_pair(corrector, node)
|
67
|
+
remove_pair(corrector, node)
|
68
|
+
insert_symbol(corrector, node)
|
69
|
+
end
|
70
|
+
|
71
|
+
def autocorrect_symbol(corrector, node)
|
72
|
+
return if match_ambiguous_trailing_metadata?(node.parent)
|
73
|
+
|
74
|
+
remove_symbol(corrector, node)
|
75
|
+
insert_pair(corrector, node)
|
76
|
+
end
|
77
|
+
|
78
|
+
def bad_metadata_pair?(node)
|
79
|
+
style == :symbol && match_boolean_metadata_pair?(node)
|
80
|
+
end
|
81
|
+
|
82
|
+
def bad_metadata_symbol?(_node)
|
83
|
+
style == :hash
|
84
|
+
end
|
85
|
+
|
86
|
+
def format_symbol_to_pair_source(node)
|
87
|
+
"#{node.value}: true"
|
88
|
+
end
|
89
|
+
|
90
|
+
def insert_pair(corrector, node)
|
91
|
+
hash_node = extract_metadata_hash(node.parent)
|
92
|
+
if hash_node.nil?
|
93
|
+
insert_pair_as_last_argument(corrector, node)
|
94
|
+
elsif hash_node.pairs.any?
|
95
|
+
insert_pair_to_non_empty_hash_metadata(corrector, node, hash_node)
|
96
|
+
else
|
97
|
+
insert_pair_to_empty_hash_metadata(corrector, node, hash_node)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def insert_pair_as_last_argument(corrector, node)
|
102
|
+
corrector.insert_before(
|
103
|
+
node.parent.location.end || node.parent.source_range.with(
|
104
|
+
begin_pos: node.parent.source_range.end_pos
|
105
|
+
),
|
106
|
+
", #{format_symbol_to_pair_source(node)}"
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
def insert_pair_to_empty_hash_metadata(corrector, node, hash_node)
|
111
|
+
corrector.insert_after(
|
112
|
+
hash_node.location.begin,
|
113
|
+
" #{format_symbol_to_pair_source(node)} "
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
def insert_pair_to_non_empty_hash_metadata(corrector, node, hash_node)
|
118
|
+
corrector.insert_after(
|
119
|
+
hash_node.children.last,
|
120
|
+
", #{format_symbol_to_pair_source(node)}"
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def insert_symbol(corrector, node)
|
125
|
+
corrector.insert_after(
|
126
|
+
node.parent.left_sibling,
|
127
|
+
", #{node.key.value.inspect}"
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
def message_for_style
|
132
|
+
format(
|
133
|
+
'Use %<style>s style for metadata.',
|
134
|
+
style: style
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
def on_metadata_pair(node)
|
139
|
+
return unless bad_metadata_pair?(node)
|
140
|
+
|
141
|
+
add_offense(node, message: message_for_style) do |corrector|
|
142
|
+
autocorrect_pair(corrector, node)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def on_metadata_symbol(node)
|
147
|
+
return unless bad_metadata_symbol?(node)
|
148
|
+
|
149
|
+
add_offense(node, message: message_for_style) do |corrector|
|
150
|
+
autocorrect_symbol(corrector, node)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def remove_pair(corrector, node)
|
155
|
+
if !node.parent.braces? || node.left_siblings.any?
|
156
|
+
remove_pair_following(corrector, node)
|
157
|
+
elsif node.right_siblings.any?
|
158
|
+
remove_pair_preceding(corrector, node)
|
159
|
+
else
|
160
|
+
corrector.remove(node)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def remove_pair_following(corrector, node)
|
165
|
+
corrector.remove(
|
166
|
+
range_with_surrounding_comma(
|
167
|
+
range_with_surrounding_space(
|
168
|
+
node.source_range,
|
169
|
+
side: :left
|
170
|
+
),
|
171
|
+
:left
|
172
|
+
)
|
173
|
+
)
|
174
|
+
end
|
175
|
+
|
176
|
+
def remove_pair_preceding(corrector, node)
|
177
|
+
corrector.remove(
|
178
|
+
range_with_surrounding_space(
|
179
|
+
range_with_surrounding_comma(
|
180
|
+
node.source_range,
|
181
|
+
:right
|
182
|
+
),
|
183
|
+
side: :right
|
184
|
+
)
|
185
|
+
)
|
186
|
+
end
|
187
|
+
|
188
|
+
def remove_symbol(corrector, node)
|
189
|
+
corrector.remove(
|
190
|
+
range_with_surrounding_comma(
|
191
|
+
range_with_surrounding_space(
|
192
|
+
node.source_range,
|
193
|
+
side: :left
|
194
|
+
),
|
195
|
+
:left
|
196
|
+
)
|
197
|
+
)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
13
13
|
def_node_matcher :rspec_metadata, <<~PATTERN
|
14
14
|
(block
|
15
15
|
(send
|
16
|
-
#rspec? {#Examples.all #ExampleGroups.all #SharedGroups.all #Hooks.all} _
|
16
|
+
#rspec? {#Examples.all #ExampleGroups.all #SharedGroups.all #Hooks.all} _ $...)
|
17
17
|
...)
|
18
18
|
PATTERN
|
19
19
|
|
@@ -24,25 +24,39 @@ module RuboCop
|
|
24
24
|
|
25
25
|
# @!method metadata_in_block(node)
|
26
26
|
def_node_search :metadata_in_block, <<~PATTERN
|
27
|
-
(send (lvar %) #Hooks.all _
|
27
|
+
(send (lvar %) #Hooks.all _ $...)
|
28
28
|
PATTERN
|
29
29
|
|
30
30
|
def on_block(node)
|
31
31
|
rspec_configure(node) do |block_var|
|
32
|
-
metadata_in_block(node, block_var) do |
|
33
|
-
|
32
|
+
metadata_in_block(node, block_var) do |metadata_arguments|
|
33
|
+
on_metadata_arguments(metadata_arguments)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
rspec_metadata(node) do |
|
38
|
-
|
37
|
+
rspec_metadata(node) do |metadata_arguments|
|
38
|
+
on_metadata_arguments(metadata_arguments)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
alias on_numblock on_block
|
42
42
|
|
43
|
-
def on_metadata(_symbols,
|
43
|
+
def on_metadata(_symbols, _hash)
|
44
44
|
raise ::NotImplementedError
|
45
45
|
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def on_metadata_arguments(metadata_arguments)
|
50
|
+
*symbols, last = metadata_arguments
|
51
|
+
hash = nil
|
52
|
+
case last&.type
|
53
|
+
when :hash
|
54
|
+
hash = last
|
55
|
+
when :sym
|
56
|
+
symbols << last
|
57
|
+
end
|
58
|
+
on_metadata(symbols, hash)
|
59
|
+
end
|
46
60
|
end
|
47
61
|
end
|
48
62
|
end
|
@@ -17,10 +17,12 @@ module RuboCop
|
|
17
17
|
# # bad
|
18
18
|
# it { is_expected.to have_http_status 200 }
|
19
19
|
# it { is_expected.to have_http_status 404 }
|
20
|
+
# it { is_expected.to have_http_status "403" }
|
20
21
|
#
|
21
22
|
# # good
|
22
23
|
# it { is_expected.to have_http_status :ok }
|
23
24
|
# it { is_expected.to have_http_status :not_found }
|
25
|
+
# it { is_expected.to have_http_status :forbidden }
|
24
26
|
# it { is_expected.to have_http_status :success }
|
25
27
|
# it { is_expected.to have_http_status :error }
|
26
28
|
#
|
@@ -28,10 +30,12 @@ module RuboCop
|
|
28
30
|
# # bad
|
29
31
|
# it { is_expected.to have_http_status :ok }
|
30
32
|
# it { is_expected.to have_http_status :not_found }
|
33
|
+
# it { is_expected.to have_http_status "forbidden" }
|
31
34
|
#
|
32
35
|
# # good
|
33
36
|
# it { is_expected.to have_http_status 200 }
|
34
37
|
# it { is_expected.to have_http_status 404 }
|
38
|
+
# it { is_expected.to have_http_status 403 }
|
35
39
|
# it { is_expected.to have_http_status :success }
|
36
40
|
# it { is_expected.to have_http_status :error }
|
37
41
|
#
|
@@ -39,8 +43,10 @@ module RuboCop
|
|
39
43
|
# # bad
|
40
44
|
# it { is_expected.to have_http_status :ok }
|
41
45
|
# it { is_expected.to have_http_status :not_found }
|
46
|
+
# it { is_expected.to have_http_status "forbidden" }
|
42
47
|
# it { is_expected.to have_http_status 200 }
|
43
48
|
# it { is_expected.to have_http_status 404 }
|
49
|
+
# it { is_expected.to have_http_status "403" }
|
44
50
|
#
|
45
51
|
# # good
|
46
52
|
# it { is_expected.to be_ok }
|
@@ -55,11 +61,13 @@ module RuboCop
|
|
55
61
|
|
56
62
|
# @!method http_status(node)
|
57
63
|
def_node_matcher :http_status, <<-PATTERN
|
58
|
-
(send nil? :have_http_status ${int sym})
|
64
|
+
(send nil? :have_http_status ${int sym str})
|
59
65
|
PATTERN
|
60
66
|
|
61
67
|
def on_send(node)
|
62
68
|
http_status(node) do |arg|
|
69
|
+
return if arg.str_type? && arg.heredoc?
|
70
|
+
|
63
71
|
checker = checker_class.new(arg)
|
64
72
|
return unless checker.offensive?
|
65
73
|
|
@@ -99,6 +107,10 @@ module RuboCop
|
|
99
107
|
format(MSG, prefer: prefer, current: current)
|
100
108
|
end
|
101
109
|
|
110
|
+
def current
|
111
|
+
offense_range.source
|
112
|
+
end
|
113
|
+
|
102
114
|
def offense_range
|
103
115
|
node
|
104
116
|
end
|
@@ -123,10 +135,6 @@ module RuboCop
|
|
123
135
|
symbol.inspect
|
124
136
|
end
|
125
137
|
|
126
|
-
def current
|
127
|
-
number.inspect
|
128
|
-
end
|
129
|
-
|
130
138
|
private
|
131
139
|
|
132
140
|
def symbol
|
@@ -134,7 +142,7 @@ module RuboCop
|
|
134
142
|
end
|
135
143
|
|
136
144
|
def number
|
137
|
-
node.
|
145
|
+
node.value.to_i
|
138
146
|
end
|
139
147
|
end
|
140
148
|
|
@@ -148,10 +156,6 @@ module RuboCop
|
|
148
156
|
number.to_s
|
149
157
|
end
|
150
158
|
|
151
|
-
def current
|
152
|
-
symbol.inspect
|
153
|
-
end
|
154
|
-
|
155
159
|
private
|
156
160
|
|
157
161
|
def symbol
|
@@ -159,7 +163,7 @@ module RuboCop
|
|
159
163
|
end
|
160
164
|
|
161
165
|
def number
|
162
|
-
::Rack::Utils::SYMBOL_TO_STATUS_CODE[symbol]
|
166
|
+
::Rack::Utils::SYMBOL_TO_STATUS_CODE[symbol.to_sym]
|
163
167
|
end
|
164
168
|
end
|
165
169
|
|
@@ -177,15 +181,13 @@ module RuboCop
|
|
177
181
|
def prefer
|
178
182
|
if node.sym_type?
|
179
183
|
"be_#{node.value}"
|
180
|
-
|
184
|
+
elsif node.int_type?
|
181
185
|
"be_#{symbol}"
|
186
|
+
elsif node.str_type?
|
187
|
+
"be_#{normalize_str}"
|
182
188
|
end
|
183
189
|
end
|
184
190
|
|
185
|
-
def current
|
186
|
-
offense_range.source
|
187
|
-
end
|
188
|
-
|
189
191
|
private
|
190
192
|
|
191
193
|
def symbol
|
@@ -193,7 +195,16 @@ module RuboCop
|
|
193
195
|
end
|
194
196
|
|
195
197
|
def number
|
196
|
-
node.
|
198
|
+
node.value.to_i
|
199
|
+
end
|
200
|
+
|
201
|
+
def normalize_str
|
202
|
+
str = node.value.to_s
|
203
|
+
if str.match?(/\A\d+\z/)
|
204
|
+
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(str.to_i)
|
205
|
+
else
|
206
|
+
str
|
207
|
+
end
|
197
208
|
end
|
198
209
|
end
|
199
210
|
end
|
@@ -17,6 +17,9 @@ module RuboCop
|
|
17
17
|
# # good
|
18
18
|
# expect(foo).not_to be_valid
|
19
19
|
#
|
20
|
+
# # good (with method chain)
|
21
|
+
# expect(foo).to be_invalid.and be_odd
|
22
|
+
#
|
20
23
|
# @example EnforcedStyle: be_invalid
|
21
24
|
# # bad
|
22
25
|
# expect(foo).not_to be_valid
|
@@ -24,6 +27,9 @@ module RuboCop
|
|
24
27
|
# # good
|
25
28
|
# expect(foo).to be_invalid
|
26
29
|
#
|
30
|
+
# # good (with method chain)
|
31
|
+
# expect(foo).to be_invalid.or be_even
|
32
|
+
#
|
27
33
|
class NegationBeValid < Base
|
28
34
|
extend AutoCorrector
|
29
35
|
include ConfigurableEnforcedStyle
|
@@ -124,7 +124,7 @@ module RuboCop
|
|
124
124
|
|
125
125
|
def register_offense(item, repeated_lines, args)
|
126
126
|
add_offense(item, message: message(repeated_lines)) do |corrector|
|
127
|
-
if item.loc.line
|
127
|
+
if item.loc.line > repeated_lines.max
|
128
128
|
replace_to_receive_messages(corrector, item, args)
|
129
129
|
else
|
130
130
|
corrector.remove(item_range_by_whole_lines(item))
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that spec file paths are consistent and well-formed.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# whatever_spec.rb # describe MyClass
|
11
|
+
# my_class_spec.rb # describe MyClass, '#method'
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# my_class_spec.rb # describe MyClass
|
15
|
+
# my_class_method_spec.rb # describe MyClass, '#method'
|
16
|
+
# my_class/method_spec.rb # describe MyClass, '#method'
|
17
|
+
#
|
18
|
+
# @example `CustomTransform: {RuboCop=>rubocop, RSpec=>rspec}` (default)
|
19
|
+
# # good
|
20
|
+
# rubocop_spec.rb # describe RuboCop
|
21
|
+
# rspec_spec.rb # describe RSpec
|
22
|
+
#
|
23
|
+
# @example `IgnoreMethods: false` (default)
|
24
|
+
# # bad
|
25
|
+
# my_class_spec.rb # describe MyClass, '#method'
|
26
|
+
#
|
27
|
+
# @example `IgnoreMethods: true`
|
28
|
+
# # good
|
29
|
+
# my_class_spec.rb # describe MyClass, '#method'
|
30
|
+
#
|
31
|
+
# @example `IgnoreMetadata: {type=>routing}` (default)
|
32
|
+
# # good
|
33
|
+
# whatever_spec.rb # describe MyClass, type: :routing do; end
|
34
|
+
#
|
35
|
+
class SpecFilePathFormat < Base
|
36
|
+
include TopLevelGroup
|
37
|
+
include Namespace
|
38
|
+
include FileHelp
|
39
|
+
|
40
|
+
MSG = 'Spec path should end with `%<suffix>s`.'
|
41
|
+
|
42
|
+
# @!method example_group_arguments(node)
|
43
|
+
def_node_matcher :example_group_arguments, <<~PATTERN
|
44
|
+
(block $(send #rspec? #ExampleGroups.all $_ $...) ...)
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
# @!method metadata_key_value(node)
|
48
|
+
def_node_search :metadata_key_value, '(pair (sym $_key) (sym $_value))'
|
49
|
+
|
50
|
+
def on_top_level_example_group(node)
|
51
|
+
return unless top_level_groups.one?
|
52
|
+
|
53
|
+
example_group_arguments(node) do |send_node, class_name, arguments|
|
54
|
+
next if !class_name.const_type? || ignore_metadata?(arguments)
|
55
|
+
|
56
|
+
ensure_correct_file_path(send_node, class_name, arguments)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def ensure_correct_file_path(send_node, class_name, arguments)
|
63
|
+
pattern = correct_path_pattern(class_name, arguments)
|
64
|
+
return if filename_ends_with?(pattern)
|
65
|
+
|
66
|
+
# For the suffix shown in the offense message, modify the regular
|
67
|
+
# expression pattern to resemble a glob pattern for clearer error
|
68
|
+
# messages.
|
69
|
+
suffix = pattern.sub('.*', '*').sub('[^/]*', '*').sub('\.', '.')
|
70
|
+
add_offense(send_node, message: format(MSG, suffix: suffix))
|
71
|
+
end
|
72
|
+
|
73
|
+
def ignore_metadata?(arguments)
|
74
|
+
arguments.any? do |argument|
|
75
|
+
metadata_key_value(argument).any? do |key, value|
|
76
|
+
ignore_metadata.values_at(key.to_s).include?(value.to_s)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def correct_path_pattern(class_name, arguments)
|
82
|
+
path = [expected_path(class_name)]
|
83
|
+
path << '.*' unless ignore?(arguments.first)
|
84
|
+
path << [name_pattern(arguments.first), '[^/]*_spec\.rb']
|
85
|
+
path.join
|
86
|
+
end
|
87
|
+
|
88
|
+
def name_pattern(method_name)
|
89
|
+
return if ignore?(method_name)
|
90
|
+
|
91
|
+
method_name.str_content.gsub(/\s/, '_').gsub(/\W/, '')
|
92
|
+
end
|
93
|
+
|
94
|
+
def ignore?(method_name)
|
95
|
+
!method_name&.str_type? || ignore_methods?
|
96
|
+
end
|
97
|
+
|
98
|
+
def expected_path(constant)
|
99
|
+
constants = namespace(constant) + constant.const_name.split('::')
|
100
|
+
|
101
|
+
File.join(
|
102
|
+
constants.map do |name|
|
103
|
+
custom_transform.fetch(name) { camel_to_snake_case(name) }
|
104
|
+
end
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def camel_to_snake_case(string)
|
109
|
+
string
|
110
|
+
.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
|
111
|
+
.gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
|
112
|
+
.downcase
|
113
|
+
end
|
114
|
+
|
115
|
+
def custom_transform
|
116
|
+
cop_config.fetch('CustomTransform', {})
|
117
|
+
end
|
118
|
+
|
119
|
+
def ignore_methods?
|
120
|
+
cop_config['IgnoreMethods']
|
121
|
+
end
|
122
|
+
|
123
|
+
def ignore_metadata
|
124
|
+
cop_config.fetch('IgnoreMetadata', {})
|
125
|
+
end
|
126
|
+
|
127
|
+
def filename_ends_with?(pattern)
|
128
|
+
expanded_file_path.match?("#{pattern}$")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that spec file paths suffix are consistent and well-formed.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# my_class/foo_specorb.rb # describe MyClass
|
11
|
+
# spec/models/user.rb # describe User
|
12
|
+
# spec/models/user_specxrb # describe User
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# my_class_spec.rb # describe MyClass
|
16
|
+
#
|
17
|
+
# # good - shared examples are allowed
|
18
|
+
# spec/models/user.rb # shared_examples_for 'foo'
|
19
|
+
#
|
20
|
+
class SpecFilePathSuffix < Base
|
21
|
+
include TopLevelGroup
|
22
|
+
include FileHelp
|
23
|
+
|
24
|
+
MSG = 'Spec path should end with `_spec.rb`.'
|
25
|
+
|
26
|
+
def on_top_level_example_group(node)
|
27
|
+
example_group?(node) do
|
28
|
+
add_global_offense(MSG) unless correct_path?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def correct_path?
|
35
|
+
expanded_file_path.end_with?('_spec.rb')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
35
35
|
return unless inside_example_group?(node)
|
36
36
|
|
37
37
|
variable_definition?(node) do |variable|
|
38
|
-
next unless
|
38
|
+
next unless style_offense?(variable)
|
39
39
|
|
40
40
|
add_offense(
|
41
41
|
variable,
|
@@ -59,7 +59,7 @@ module RuboCop
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
62
|
+
def style_offense?(variable)
|
63
63
|
style == :symbols && string?(variable) ||
|
64
64
|
style == :strings && symbol?(variable)
|
65
65
|
end
|
@@ -79,8 +79,8 @@ module RuboCop
|
|
79
79
|
expression = class_reference.source_range
|
80
80
|
|
81
81
|
add_offense(expression, message: message) do |corrector|
|
82
|
-
|
83
|
-
corrector.replace(expression, correct_style(
|
82
|
+
offense = class_reference.source
|
83
|
+
corrector.replace(expression, correct_style(offense))
|
84
84
|
|
85
85
|
opposite_style_detected
|
86
86
|
end
|
@@ -98,11 +98,11 @@ module RuboCop
|
|
98
98
|
class_reference_style != style
|
99
99
|
end
|
100
100
|
|
101
|
-
def correct_style(
|
101
|
+
def correct_style(offense)
|
102
102
|
if style == :string
|
103
|
-
"'#{
|
103
|
+
"'#{offense}'"
|
104
104
|
else
|
105
|
-
|
105
|
+
offense.gsub(/^['"]|['"]$/, '')
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
@@ -57,6 +57,8 @@ require_relative 'rspec/empty_line_after_example_group'
|
|
57
57
|
require_relative 'rspec/empty_line_after_final_let'
|
58
58
|
require_relative 'rspec/empty_line_after_hook'
|
59
59
|
require_relative 'rspec/empty_line_after_subject'
|
60
|
+
require_relative 'rspec/empty_metadata'
|
61
|
+
require_relative 'rspec/eq'
|
60
62
|
require_relative 'rspec/example_length'
|
61
63
|
require_relative 'rspec/example_without_description'
|
62
64
|
require_relative 'rspec/example_wording'
|
@@ -86,6 +88,7 @@ require_relative 'rspec/match_array'
|
|
86
88
|
require_relative 'rspec/message_chain'
|
87
89
|
require_relative 'rspec/message_expectation'
|
88
90
|
require_relative 'rspec/message_spies'
|
91
|
+
require_relative 'rspec/metadata_style'
|
89
92
|
require_relative 'rspec/missing_example_group_argument'
|
90
93
|
require_relative 'rspec/multiple_describes'
|
91
94
|
require_relative 'rspec/multiple_expectations'
|
@@ -116,6 +119,8 @@ require_relative 'rspec/shared_examples'
|
|
116
119
|
require_relative 'rspec/single_argument_message_chain'
|
117
120
|
require_relative 'rspec/skip_block_inside_example'
|
118
121
|
require_relative 'rspec/sort_metadata'
|
122
|
+
require_relative 'rspec/spec_file_path_format'
|
123
|
+
require_relative 'rspec/spec_file_path_suffix'
|
119
124
|
require_relative 'rspec/stubbed_mock'
|
120
125
|
require_relative 'rspec/subject_declaration'
|
121
126
|
require_relative 'rspec/subject_stub'
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -17,6 +17,7 @@ require_relative 'rubocop/rspec/wording'
|
|
17
17
|
# Dependent on `RuboCop::RSpec::Language::NodePattern`.
|
18
18
|
require_relative 'rubocop/rspec/language'
|
19
19
|
|
20
|
+
require_relative 'rubocop/cop/rspec/mixin/file_help'
|
20
21
|
require_relative 'rubocop/cop/rspec/mixin/final_end_location'
|
21
22
|
require_relative 'rubocop/cop/rspec/mixin/inside_example_group'
|
22
23
|
require_relative 'rubocop/cop/rspec/mixin/location_help'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Backus
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-10-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '1.
|
21
|
+
version: '1.40'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: '1.
|
28
|
+
version: '1.40'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: rubocop-capybara
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,6 +112,8 @@ files:
|
|
112
112
|
- lib/rubocop/cop/rspec/empty_line_after_final_let.rb
|
113
113
|
- lib/rubocop/cop/rspec/empty_line_after_hook.rb
|
114
114
|
- lib/rubocop/cop/rspec/empty_line_after_subject.rb
|
115
|
+
- lib/rubocop/cop/rspec/empty_metadata.rb
|
116
|
+
- lib/rubocop/cop/rspec/eq.rb
|
115
117
|
- lib/rubocop/cop/rspec/example_length.rb
|
116
118
|
- lib/rubocop/cop/rspec/example_without_description.rb
|
117
119
|
- lib/rubocop/cop/rspec/example_wording.rb
|
@@ -147,9 +149,11 @@ files:
|
|
147
149
|
- lib/rubocop/cop/rspec/message_chain.rb
|
148
150
|
- lib/rubocop/cop/rspec/message_expectation.rb
|
149
151
|
- lib/rubocop/cop/rspec/message_spies.rb
|
152
|
+
- lib/rubocop/cop/rspec/metadata_style.rb
|
150
153
|
- lib/rubocop/cop/rspec/missing_example_group_argument.rb
|
151
154
|
- lib/rubocop/cop/rspec/mixin/comments_help.rb
|
152
155
|
- lib/rubocop/cop/rspec/mixin/empty_line_separation.rb
|
156
|
+
- lib/rubocop/cop/rspec/mixin/file_help.rb
|
153
157
|
- lib/rubocop/cop/rspec/mixin/final_end_location.rb
|
154
158
|
- lib/rubocop/cop/rspec/mixin/inside_example_group.rb
|
155
159
|
- lib/rubocop/cop/rspec/mixin/location_help.rb
|
@@ -194,6 +198,8 @@ files:
|
|
194
198
|
- lib/rubocop/cop/rspec/single_argument_message_chain.rb
|
195
199
|
- lib/rubocop/cop/rspec/skip_block_inside_example.rb
|
196
200
|
- lib/rubocop/cop/rspec/sort_metadata.rb
|
201
|
+
- lib/rubocop/cop/rspec/spec_file_path_format.rb
|
202
|
+
- lib/rubocop/cop/rspec/spec_file_path_suffix.rb
|
197
203
|
- lib/rubocop/cop/rspec/stubbed_mock.rb
|
198
204
|
- lib/rubocop/cop/rspec/subject_declaration.rb
|
199
205
|
- lib/rubocop/cop/rspec/subject_stub.rb
|
@@ -243,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
249
|
- !ruby/object:Gem::Version
|
244
250
|
version: '0'
|
245
251
|
requirements: []
|
246
|
-
rubygems_version: 3.4.
|
252
|
+
rubygems_version: 3.4.17
|
247
253
|
signing_key:
|
248
254
|
specification_version: 4
|
249
255
|
summary: Code style checking for RSpec files
|