rubocop-rspec 1.41.0 → 1.44.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -2
  3. data/config/default.yml +41 -3
  4. data/lib/rubocop-rspec.rb +2 -1
  5. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +12 -19
  6. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +12 -19
  7. data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
  8. data/lib/rubocop/cop/rspec/around_block.rb +2 -2
  9. data/lib/rubocop/cop/rspec/base.rb +76 -0
  10. data/lib/rubocop/cop/rspec/be.rb +2 -2
  11. data/lib/rubocop/cop/rspec/be_eql.rb +6 -6
  12. data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
  13. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +19 -17
  14. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +14 -12
  15. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
  16. data/lib/rubocop/cop/rspec/context_method.rb +7 -9
  17. data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
  18. data/lib/rubocop/cop/rspec/cop.rb +2 -66
  19. data/lib/rubocop/cop/rspec/describe_class.rb +40 -30
  20. data/lib/rubocop/cop/rspec/describe_method.rb +14 -6
  21. data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
  22. data/lib/rubocop/cop/rspec/described_class.rb +12 -9
  23. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
  24. data/lib/rubocop/cop/rspec/dialect.rb +5 -12
  25. data/lib/rubocop/cop/rspec/empty_example_group.rb +124 -6
  26. data/lib/rubocop/cop/rspec/empty_hook.rb +6 -10
  27. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +5 -7
  28. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +5 -9
  29. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +8 -8
  30. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +5 -9
  31. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +6 -6
  32. data/lib/rubocop/cop/rspec/example_length.rb +1 -1
  33. data/lib/rubocop/cop/rspec/example_without_description.rb +1 -1
  34. data/lib/rubocop/cop/rspec/example_wording.rb +10 -11
  35. data/lib/rubocop/cop/rspec/expect_actual.rb +8 -11
  36. data/lib/rubocop/cop/rspec/expect_change.rb +10 -35
  37. data/lib/rubocop/cop/rspec/expect_in_hook.rb +3 -3
  38. data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
  39. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +20 -20
  40. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +20 -22
  41. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +7 -8
  42. data/lib/rubocop/cop/rspec/file_path.rb +25 -17
  43. data/lib/rubocop/cop/rspec/focus.rb +7 -11
  44. data/lib/rubocop/cop/rspec/hook_argument.rb +16 -23
  45. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +13 -14
  46. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -3
  47. data/lib/rubocop/cop/rspec/implicit_expect.rb +7 -15
  48. data/lib/rubocop/cop/rspec/implicit_subject.rb +16 -11
  49. data/lib/rubocop/cop/rspec/instance_spy.rb +18 -12
  50. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  51. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +3 -6
  52. data/lib/rubocop/cop/rspec/it_behaves_like.rb +5 -6
  53. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  54. data/lib/rubocop/cop/rspec/leading_subject.rb +27 -20
  55. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
  56. data/lib/rubocop/cop/rspec/let_before_examples.rb +13 -11
  57. data/lib/rubocop/cop/rspec/let_setup.rb +6 -3
  58. data/lib/rubocop/cop/rspec/message_chain.rb +7 -6
  59. data/lib/rubocop/cop/rspec/message_expectation.rb +2 -2
  60. data/lib/rubocop/cop/rspec/message_spies.rb +2 -3
  61. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -1
  62. data/lib/rubocop/cop/rspec/multiple_describes.rb +11 -8
  63. data/lib/rubocop/cop/rspec/multiple_expectations.rb +7 -11
  64. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +148 -0
  65. data/lib/rubocop/cop/rspec/multiple_subjects.rb +18 -19
  66. data/lib/rubocop/cop/rspec/named_subject.rb +2 -2
  67. data/lib/rubocop/cop/rspec/nested_groups.rb +4 -4
  68. data/lib/rubocop/cop/rspec/not_to_not.rb +5 -6
  69. data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
  70. data/lib/rubocop/cop/rspec/pending.rb +1 -1
  71. data/lib/rubocop/cop/rspec/predicate_matcher.rb +30 -67
  72. data/lib/rubocop/cop/rspec/rails/http_status.rb +5 -9
  73. data/lib/rubocop/cop/rspec/receive_counts.rb +15 -17
  74. data/lib/rubocop/cop/rspec/receive_never.rb +12 -12
  75. data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
  76. data/lib/rubocop/cop/rspec/repeated_example.rb +2 -2
  77. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +1 -1
  78. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
  79. data/lib/rubocop/cop/rspec/repeated_include_example.rb +103 -0
  80. data/lib/rubocop/cop/rspec/return_from_stub.rb +9 -20
  81. data/lib/rubocop/cop/rspec/scattered_let.rb +8 -11
  82. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  83. data/lib/rubocop/cop/rspec/shared_context.rb +8 -21
  84. data/lib/rubocop/cop/rspec/shared_examples.rb +6 -9
  85. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +15 -18
  86. data/lib/rubocop/cop/rspec/stubbed_mock.rb +172 -0
  87. data/lib/rubocop/cop/rspec/subject_stub.rb +6 -6
  88. data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
  89. data/lib/rubocop/cop/rspec/variable_definition.rb +6 -6
  90. data/lib/rubocop/cop/rspec/variable_name.rb +28 -9
  91. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
  92. data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
  93. data/lib/rubocop/cop/rspec/yield.rb +14 -11
  94. data/lib/rubocop/cop/rspec_cops.rb +3 -0
  95. data/lib/rubocop/rspec/corrector/move_node.rb +7 -5
  96. data/lib/rubocop/rspec/description_extractor.rb +1 -1
  97. data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -10
  98. data/lib/rubocop/rspec/example_group.rb +2 -2
  99. data/lib/rubocop/rspec/hook.rb +1 -5
  100. data/lib/rubocop/rspec/language.rb +12 -5
  101. data/lib/rubocop/rspec/language/node_pattern.rb +6 -1
  102. data/lib/rubocop/rspec/top_level_describe.rb +2 -2
  103. data/lib/rubocop/rspec/top_level_group.rb +26 -13
  104. data/lib/rubocop/rspec/variable.rb +1 -1
  105. data/lib/rubocop/rspec/version.rb +1 -1
  106. metadata +40 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4899c717a87d579939d5c1420800d2fe6c150e4421908e75b9d52c57c8362e60
4
- data.tar.gz: 1155018e6595c843c1ade5cdecb748af349c1c2f94dbcd5b17fb4a4fb5d324be
3
+ metadata.gz: 93297f5bb7dfcb8e201365ec296afe22e5e3bbc7150b7a48e7991a22739debdd
4
+ data.tar.gz: 6343b337cf3d879a50553d09c3f4e30e4ff320285c16b533b8fbd73b8732bcd4
5
5
  SHA512:
6
- metadata.gz: 79d9dc291018b0551b52c85dc6b09a1151356e1c85fe4e6a8a7aca5ade036be690f9b5aae7301cf232a0d067b18c0321be44f9915d5485dcaf993786ed07d328
7
- data.tar.gz: cd9db102d912c42b484c7a514f5954b5f35d29bb7f0f3e186ed946898ba1134de5bf452611812465103aa2effc67016e4536bfc6dd365681aa90b2f4c1957f39
6
+ metadata.gz: 7c3eabc2946eb2b36bdb7a2be61eda35605b32f6ba0a6433cd3bde30982e13f909ea3330111631293c89cbf0237a46d3e3782610448396cdcf6dd77726e5cbda
7
+ data.tar.gz: da8f502adeb29f94294eb5a947ee455168dcfb44e23a5ad83365e4503dcdf39225b46bdb5e8357f40a231a4644fc97e8ddb85933fbc78159c43d40bbf5dddc94
@@ -2,6 +2,41 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 1.44.0 (2020-10-20)
6
+
7
+ * Move our documentation from rubocop-rspec.readthedocs.io to docs.rubocop.org/rubocop-rspec. ([@bquorning][])
8
+ * Add `RSpec/RepeatedIncludeExample` cop. ([@biinari][])
9
+ * Add `RSpec/StubbedMock` cop. ([@bquorning][], [@pirj][])
10
+ * Add `IgnoredMetadata` configuration option to `RSpec/DescribeClass`. ([@Rafix02][])
11
+ * Fix false positives in `RSpec/EmptyExampleGroup`. ([@pirj][])
12
+ * Fix a false positive for `RSpec/EmptyExampleGroup` when example is defined in an `if` branch. ([@koic][])
13
+
14
+ ## 1.43.2 (2020-08-25)
15
+
16
+ * Fix `RSpec/FilePath` when checking a file with a shared example. ([@pirj][])
17
+ * Fix subject nesting detection in `RSpec/LeadingSubject`. ([@pirj][])
18
+
19
+ ## 1.43.1 (2020-08-17)
20
+
21
+ * Fix `RSpec/FilePath` when checking a file defining e.g. an empty class. ([@bquorning][])
22
+
23
+ ## 1.43.0 (2020-08-17)
24
+
25
+ * Add a new base cop class `::RuboCop::Cop::RSpec::Base`. The old base class `::RuboCop::Cop::RSpec::Cop` is deprecated, and will be removed in the next major release. ([@bquorning][])
26
+ * Add support for subject detection after includes and example groups in `RSpec/LeadingSubject`. ([@pirj][])
27
+ * Ignore trailing punctuation in context description prefix. ([@elliterate][])
28
+ * Relax `RSpec/VariableDefinition` cop so interpolated and multiline strings are accepted even when configured to enforce the `symbol` style. ([@bquorning][])
29
+ * Fix `RSpec/EmptyExampleGroup` to flag example groups with examples in invalid scopes. ([@mlarraz][])
30
+ * Fix `RSpec/EmptyExampleGroup` to ignore examples groups with examples defined inside iterators. ([@pirj][])
31
+ * Improve `RSpec/NestedGroups`, `RSpec/FilePath`, `RSpec/DescribeMethod`, `RSpec/MultipleDescribes`, `RSpec/DescribeClass`'s top-level example group detection. ([@pirj][])
32
+ * Add detection of `let!` with a block-pass or a string literal to `RSpec/LetSetup`. ([@pirj][])
33
+ * Add `IgnoredPatterns` configuration option to `RSpec/VariableName`. ([@jtannas][])
34
+ * Add `RSpec/MultipleMemoizedHelpers` cop. ([@mockdeep][])
35
+
36
+ ## 1.42.0 (2020-07-09)
37
+
38
+ * Update RuboCop dependency to 0.87.0 because of changes to internal APIs. ([@bquorning][], [@Darhazer][])
39
+
5
40
  ## 1.41.0 (2020-07-03)
6
41
 
7
42
  * Extend the list of Rails spec types for `RSpec/DescribeClass`. ([@pirj][])
@@ -480,8 +515,8 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
480
515
  [@rspeicher]: https://github.com/rspeicher
481
516
  [@jonatas]: https://github.com/jonatas
482
517
  [@pocke]: https://github.com/pocke
483
- [@bmorrall]: https:/github.com/bmorrall
484
- [@zverok]: https:/github.com/zverok
518
+ [@bmorrall]: https://github.com/bmorrall
519
+ [@zverok]: https://github.com/zverok
485
520
  [@timrogers]: https://github.com/timrogers
486
521
  [@yevhene]: https://github.com/yevhene
487
522
  [@walf443]: https://github.com/walf443
@@ -525,3 +560,9 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
525
560
  [@rolfschmidt]: https://github.com/rolfschmidt
526
561
  [@andrykonchin]: https://github.com/andrykonchin
527
562
  [@harrylewis]: https://github.com/harrylewis
563
+ [@elliterate]: https://github.com/elliterate
564
+ [@jtannas]: https://github.com/jtannas
565
+ [@mockdeep]: https://github.com/mockdeep
566
+ [@biinari]: https://github.com/biinari
567
+ [@koic]: https://github.com/koic
568
+ [@Rafix02]: https://github.com/Rafix02
@@ -74,9 +74,25 @@ RSpec/ContextWording:
74
74
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording
75
75
 
76
76
  RSpec/DescribeClass:
77
- Description: Check that the first argument to the top level describe is a constant.
78
- Enabled: true
77
+ Description: Check that the first argument to the top-level describe is a constant.
78
+ Enabled: true
79
+ IgnoredMetadata:
80
+ type:
81
+ - channel
82
+ - controller
83
+ - helper
84
+ - job
85
+ - mailer
86
+ - model
87
+ - request
88
+ - routing
89
+ - view
90
+ - feature
91
+ - system
92
+ - mailbox
93
+ - aruba
79
94
  VersionAdded: '1.0'
95
+ VersionChanged: '1.44'
80
96
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass
81
97
 
82
98
  RSpec/DescribeMethod:
@@ -381,7 +397,7 @@ RSpec/MissingExampleGroupArgument:
381
397
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument
382
398
 
383
399
  RSpec/MultipleDescribes:
384
- Description: Checks for multiple top level describes.
400
+ Description: Checks for multiple top-level example groups.
385
401
  Enabled: true
386
402
  VersionAdded: '1.0'
387
403
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes
@@ -394,6 +410,14 @@ RSpec/MultipleExpectations:
394
410
  VersionChanged: '1.21'
395
411
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations
396
412
 
413
+ RSpec/MultipleMemoizedHelpers:
414
+ Description: Checks if example groups contain too many `let` and `subject` calls.
415
+ Enabled: true
416
+ AllowSubject: true
417
+ Max: 5
418
+ VersionAdded: '1.43'
419
+ StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers
420
+
397
421
  RSpec/MultipleSubjects:
398
422
  Description: Checks if an example group defines `subject` multiple times.
399
423
  Enabled: true
@@ -486,6 +510,12 @@ RSpec/RepeatedExampleGroupDescription:
486
510
  VersionAdded: '1.38'
487
511
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription
488
512
 
513
+ RSpec/RepeatedIncludeExample:
514
+ Description: Check for repeated include of shared examples.
515
+ Enabled: true
516
+ VersionAdded: '1.44'
517
+ StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedIncludeExample
518
+
489
519
  RSpec/ReturnFromStub:
490
520
  Description: Checks for consistent style of stub's return setting.
491
521
  Enabled: true
@@ -529,6 +559,12 @@ RSpec/SingleArgumentMessageChain:
529
559
  VersionChanged: '1.10'
530
560
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain
531
561
 
562
+ RSpec/StubbedMock:
563
+ Description: Checks that message expectations do not have a configured response.
564
+ Enabled: pending
565
+ VersionAdded: '1.44'
566
+ StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StubbedMock
567
+
532
568
  RSpec/SubjectStub:
533
569
  Description: Checks for stubbed test subjects.
534
570
  Enabled: true
@@ -558,7 +594,9 @@ RSpec/VariableName:
558
594
  SupportedStyles:
559
595
  - snake_case
560
596
  - camelCase
597
+ IgnoredPatterns: []
561
598
  VersionAdded: '1.40'
599
+ VersionChanged: '1.43'
562
600
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName
563
601
 
564
602
  RSpec/VerifiedDoubles:
@@ -19,11 +19,12 @@ require_relative 'rubocop/rspec/example_group'
19
19
  require_relative 'rubocop/rspec/example'
20
20
  require_relative 'rubocop/rspec/hook'
21
21
  require_relative 'rubocop/rspec/variable'
22
+ require_relative 'rubocop/cop/rspec/base'
22
23
  require_relative 'rubocop/cop/rspec/cop'
23
24
  require_relative 'rubocop/rspec/align_let_brace'
24
25
  require_relative 'rubocop/rspec/factory_bot'
25
26
  require_relative 'rubocop/rspec/final_end_location'
26
- require_relative 'rubocop/rspec/blank_line_separation'
27
+ require_relative 'rubocop/rspec/empty_line_separation'
27
28
  require_relative 'rubocop/rspec/corrector/move_node'
28
29
 
29
30
  RuboCop::RSpec::Inject.defaults!
@@ -17,36 +17,29 @@ module RuboCop
17
17
  # let(:baz) { bar }
18
18
  # let(:a) { b }
19
19
  #
20
- class AlignLeftLetBrace < Cop
20
+ class AlignLeftLetBrace < Base
21
+ extend AutoCorrector
22
+
21
23
  MSG = 'Align left let brace'
22
24
 
23
25
  def self.autocorrect_incompatible_with
24
26
  [Layout::ExtraSpacing]
25
27
  end
26
28
 
27
- def investigate(_processed_source)
29
+ def on_new_investigation
28
30
  return if processed_source.blank?
29
31
 
30
- token_aligner.offending_tokens.each do |let|
31
- add_offense(let, location: :begin)
32
- end
33
- end
32
+ token_aligner =
33
+ RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin)
34
34
 
35
- def autocorrect(let)
36
- lambda do |corrector|
37
- corrector.insert_before(
38
- let.loc.begin,
39
- token_aligner.indent_for(let)
40
- )
35
+ token_aligner.offending_tokens.each do |let|
36
+ add_offense(let.loc.begin) do |corrector|
37
+ corrector.insert_before(
38
+ let.loc.begin, token_aligner.indent_for(let)
39
+ )
40
+ end
41
41
  end
42
42
  end
43
-
44
- private
45
-
46
- def token_aligner
47
- @token_aligner ||=
48
- RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin)
49
- end
50
43
  end
51
44
  end
52
45
  end
@@ -17,36 +17,29 @@ module RuboCop
17
17
  # let(:baz) { bar }
18
18
  # let(:a) { b }
19
19
  #
20
- class AlignRightLetBrace < Cop
20
+ class AlignRightLetBrace < Base
21
+ extend AutoCorrector
22
+
21
23
  MSG = 'Align right let brace'
22
24
 
23
25
  def self.autocorrect_incompatible_with
24
26
  [Layout::ExtraSpacing]
25
27
  end
26
28
 
27
- def investigate(_processed_source)
29
+ def on_new_investigation
28
30
  return if processed_source.blank?
29
31
 
30
- token_aligner.offending_tokens.each do |let|
31
- add_offense(let, location: :end)
32
- end
33
- end
32
+ token_aligner =
33
+ RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end)
34
34
 
35
- def autocorrect(let)
36
- lambda do |corrector|
37
- corrector.insert_before(
38
- let.loc.end,
39
- token_aligner.indent_for(let)
40
- )
35
+ token_aligner.offending_tokens.each do |let|
36
+ add_offense(let.loc.end) do |corrector|
37
+ corrector.insert_before(
38
+ let.loc.end, token_aligner.indent_for(let)
39
+ )
40
+ end
41
41
  end
42
42
  end
43
-
44
- private
45
-
46
- def token_aligner
47
- @token_aligner ||=
48
- RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end)
49
- end
50
43
  end
51
44
  end
52
45
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  # allow(my_instance).to receive(:foo)
23
23
  # end
24
24
  # end
25
- class AnyInstance < Cop
25
+ class AnyInstance < Base
26
26
  MSG = 'Avoid stubbing using `%<method>s`.'
27
27
 
28
28
  def_node_matcher :disallowed_stub, <<-PATTERN
@@ -25,13 +25,13 @@ module RuboCop
25
25
  # some_method
26
26
  # test.run
27
27
  # end
28
- class AroundBlock < Cop
28
+ class AroundBlock < Base
29
29
  MSG_NO_ARG = 'Test object should be passed to around block.'
30
30
  MSG_UNUSED_ARG = 'You should call `%<arg>s.call` '\
31
31
  'or `%<arg>s.run`.'
32
32
 
33
33
  def_node_matcher :hook, <<-PATTERN
34
- (block {(send nil? :around) (send nil? :around sym)} (args $...) ...)
34
+ (block (send nil? :around sym ?) (args $...) ...)
35
35
  PATTERN
36
36
 
37
37
  def_node_search :find_arg_usage, <<-PATTERN
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # @abstract parent class to RSpec cops
7
+ #
8
+ # The criteria for whether rubocop-rspec analyzes a certain ruby file
9
+ # is configured via `AllCops/RSpec`. For example, if you want to
10
+ # customize your project to scan all files within a `test/` directory
11
+ # then you could add this to your configuration:
12
+ #
13
+ # @example configuring analyzed paths
14
+ # # .rubocop.yml
15
+ # # AllCops:
16
+ # # RSpec:
17
+ # # Patterns:
18
+ # # - '_test.rb$'
19
+ # # - '(?:^|/)test/'
20
+ class Base < ::RuboCop::Cop::Base
21
+ include RuboCop::RSpec::Language
22
+ include RuboCop::RSpec::Language::NodePattern
23
+
24
+ DEFAULT_CONFIGURATION =
25
+ RuboCop::RSpec::CONFIG.fetch('AllCops').fetch('RSpec')
26
+
27
+ DEFAULT_PATTERN_RE = Regexp.union(
28
+ DEFAULT_CONFIGURATION.fetch('Patterns')
29
+ .map(&Regexp.public_method(:new))
30
+ )
31
+
32
+ exclude_from_registry
33
+
34
+ # Invoke the original inherited hook so our cops are recognized
35
+ def self.inherited(subclass) # rubocop:disable Lint/MissingSuper
36
+ RuboCop::Cop::Base.inherited(subclass)
37
+ end
38
+
39
+ def relevant_file?(file)
40
+ relevant_rubocop_rspec_file?(file) && super
41
+ end
42
+
43
+ private
44
+
45
+ def relevant_rubocop_rspec_file?(file)
46
+ rspec_pattern.match?(file)
47
+ end
48
+
49
+ def rspec_pattern
50
+ if rspec_pattern_config?
51
+ Regexp.union(rspec_pattern_config.map(&Regexp.public_method(:new)))
52
+ else
53
+ DEFAULT_PATTERN_RE
54
+ end
55
+ end
56
+
57
+ def all_cops_config
58
+ config
59
+ .for_all_cops
60
+ end
61
+
62
+ def rspec_pattern_config?
63
+ return unless all_cops_config.key?('RSpec')
64
+
65
+ all_cops_config.fetch('RSpec').key?('Patterns')
66
+ end
67
+
68
+ def rspec_pattern_config
69
+ all_cops_config
70
+ .fetch('RSpec', DEFAULT_CONFIGURATION)
71
+ .fetch('Patterns')
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -19,7 +19,7 @@ module RuboCop
19
19
  # expect(foo).to be 1.0
20
20
  # expect(foo).to be(true)
21
21
  #
22
- class Be < Cop
22
+ class Be < Base
23
23
  MSG = 'Don\'t use `be` without an argument.'
24
24
 
25
25
  def_node_matcher :be_without_args, <<-PATTERN
@@ -28,7 +28,7 @@ module RuboCop
28
28
 
29
29
  def on_send(node)
30
30
  be_without_args(node) do |matcher|
31
- add_offense(matcher, location: :selector)
31
+ add_offense(matcher.loc.selector)
32
32
  end
33
33
  end
34
34
  end
@@ -35,7 +35,9 @@ module RuboCop
35
35
  # necessarily the same type as `b` since the `#==` operator can
36
36
  # coerce objects for comparison.
37
37
  #
38
- class BeEql < Cop
38
+ class BeEql < Base
39
+ extend AutoCorrector
40
+
39
41
  MSG = 'Prefer `be` over `eql`.'
40
42
 
41
43
  def_node_matcher :eql_type_with_identity, <<-PATTERN
@@ -44,13 +46,11 @@ module RuboCop
44
46
 
45
47
  def on_send(node)
46
48
  eql_type_with_identity(node) do |eql|
47
- add_offense(eql, location: :selector)
49
+ add_offense(eql.loc.selector) do |corrector|
50
+ corrector.replace(eql.loc.selector, 'be')
51
+ end
48
52
  end
49
53
  end
50
-
51
- def autocorrect(node)
52
- ->(corrector) { corrector.replace(node.loc.selector, 'be') }
53
- end
54
54
  end
55
55
  end
56
56
  end
@@ -23,7 +23,7 @@ module RuboCop
23
23
  # before(:each) { Widget.create }
24
24
  # after(:each) { Widget.delete_all }
25
25
  # end
26
- class BeforeAfterAll < Cop
26
+ class BeforeAfterAll < Base
27
27
  MSG = 'Beware of using `%<hook>s` as it may cause state to leak '\
28
28
  'between tests. If you are using `rspec-rails`, and '\
29
29
  '`use_transactional_fixtures` is enabled, then records created '\
@@ -23,7 +23,9 @@ module RuboCop
23
23
  # expect(page).to have_current_path("/callback")
24
24
  # expect(page).to have_current_path(/widgets/)
25
25
  #
26
- class CurrentPathExpectation < Cop
26
+ class CurrentPathExpectation < Base
27
+ extend AutoCorrector
28
+
27
29
  MSG = 'Do not set an RSpec expectation on `current_path` in ' \
28
30
  'Capybara feature specs - instead, use the ' \
29
31
  '`have_current_path` matcher on `page`'
@@ -47,30 +49,30 @@ module RuboCop
47
49
 
48
50
  def on_send(node)
49
51
  expectation_set_on_current_path(node) do
50
- add_offense(node, location: :selector)
52
+ add_offense(node.loc.selector) do |corrector|
53
+ next unless node.chained?
54
+
55
+ autocorrect(corrector, node)
56
+ end
51
57
  end
52
58
  end
53
59
 
54
- def autocorrect(node)
55
- lambda do |corrector|
56
- return unless node.chained?
60
+ private
57
61
 
58
- as_is_matcher(node.parent) do |to_sym, matcher_node|
59
- rewrite_expectation(corrector, node, to_sym, matcher_node)
60
- end
62
+ def autocorrect(corrector, node)
63
+ as_is_matcher(node.parent) do |to_sym, matcher_node|
64
+ rewrite_expectation(corrector, node, to_sym, matcher_node)
65
+ end
61
66
 
62
- regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp|
63
- rewrite_expectation(corrector, node, to_sym, matcher_node)
64
- convert_regexp_str_to_literal(corrector, matcher_node, regexp)
65
- end
67
+ regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp|
68
+ rewrite_expectation(corrector, node, to_sym, matcher_node)
69
+ convert_regexp_str_to_literal(corrector, matcher_node, regexp)
66
70
  end
67
71
  end
68
72
 
69
- private
70
-
71
73
  def rewrite_expectation(corrector, node, to_symbol, matcher_node)
72
74
  current_path_node = node.first_argument
73
- corrector.replace(current_path_node.loc.expression, 'page')
75
+ corrector.replace(current_path_node, 'page')
74
76
  corrector.replace(node.parent.loc.selector, 'to')
75
77
  matcher_method = if to_symbol == :to
76
78
  'have_current_path'
@@ -84,7 +86,7 @@ module RuboCop
84
86
  def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str)
85
87
  str_node = matcher_node.first_argument
86
88
  regexp_expr = Regexp.new(regexp_str).inspect
87
- corrector.replace(str_node.loc.expression, regexp_expr)
89
+ corrector.replace(str_node, regexp_expr)
88
90
  end
89
91
 
90
92
  # `have_current_path` with no options will include the querystring
@@ -97,7 +99,7 @@ module RuboCop
97
99
  return if %i[regexp str].include?(expectation_last_child.type)
98
100
 
99
101
  corrector.insert_after(
100
- expectation_last_child.loc.expression,
102
+ expectation_last_child,
101
103
  ', ignore_query: true'
102
104
  )
103
105
  end