rubocop-rspec 3.6.0 → 3.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e4727f136d1a399d3108fd010c76ac61f7fce57e3c89cb2d97ad121d558af44
4
- data.tar.gz: dcc8c7f61c420d5938807dae3a610f53c6be8c657687e38542f701db2aec4ce2
3
+ metadata.gz: 645fbfddd891af3477e31993bc8da92fc57300cbcfcd8274ee0f68cfbbe97983
4
+ data.tar.gz: 6a97e91acb933ecbe09691c090efbff715ca12adcaef7027e8d324411ec0d78d
5
5
  SHA512:
6
- metadata.gz: 651f8b53a0b70738f9dc084df5bdf471ce65ae4d7f0c2db8cc2eb557178fd541f317bee36ae062b8109aed72b452f69eb1c965db923d5d9875c86de9ab84f23e
7
- data.tar.gz: f189ec83b4b663df4e3aca303f2f273fded6d5529e689d7f9421f379dd46203da95236a4f649414466b0f6050b0d9e7d952df003b4b63ed45722c1764fd1a094
6
+ metadata.gz: ca10e4b0b7e285136c60aa0035a018407263968fcced15155999ef5e2b6ac4edac45bcbd6c82dd355616a40ef110f9191cc986d5a8922aaab42c8118bff55c89
7
+ data.tar.gz: 7a22acf8143f309128504884a1634e23504b40821aabf14d9b20392c6c11ce7a34ad3ab48945e1b023594a794677bdf6526e7236f705fd331ab244a746375453
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 3.7.0 (2025-09-01)
6
+
7
+ - Mark `RSpec/IncludeExamples` as `SafeAutoCorrect: false`. ([@yujideveloper])
8
+ - Fix a false positive for `RSpec/LeakyConstantDeclaration` when defining constants in explicit namespaces. ([@naveg])
9
+ - Add support for error matchers (`raise_exception` and `raise_error`) to `RSpec/Dialect`. ([@lovro-bikic])
10
+ - Don't register offenses for `RSpec/DescribedClass` within `Data.define` blocks. ([@lovro-bikic])
11
+ - Add autocorrection support for `RSpec/IteratedExpectation` for single expectations. ([@lovro-bikic])
12
+ - Exclude all cops from inspecting factorybot files, except if explicitly included. ([@Mth0158])
13
+ - Fix a false positive for `RSpec/ExcessiveDocstringSpacing` when receivers are not RSpec methods. ([@ydah])
14
+
5
15
  ## 3.6.0 (2025-04-18)
6
16
 
7
17
  - Fix false positive in `RSpec/Pending`, where it would mark the default block `it` as an offense. ([@bquorning])
@@ -1021,6 +1031,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
1021
1031
  [@mlarraz]: https://github.com/mlarraz
1022
1032
  [@mockdeep]: https://github.com/mockdeep
1023
1033
  [@mothonmars]: https://github.com/MothOnMars
1034
+ [@mth0158]: https://github.com/Mth0158
1024
1035
  [@mvz]: https://github.com/mvz
1025
1036
  [@naveg]: https://github.com/naveg
1026
1037
  [@nc-holodakg]: https://github.com/nc-holodakg
@@ -1073,5 +1084,6 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
1073
1084
  [@ydah]: https://github.com/ydah
1074
1085
  [@yevhene]: https://github.com/yevhene
1075
1086
  [@ypresto]: https://github.com/ypresto
1087
+ [@yujideveloper]: https://github.com/yujideveloper
1076
1088
  [@zdennis]: https://github.com/zdennis
1077
1089
  [@zverok]: https://github.com/zverok
data/config/default.yml CHANGED
@@ -6,6 +6,10 @@ RSpec:
6
6
  Include:
7
7
  - "**/*_spec.rb"
8
8
  - "**/spec/**/*"
9
+ Exclude:
10
+ - "**/spec/factories.rb"
11
+ - "**/spec/factories/**/*.rb"
12
+ - "**/features/support/factories/**/*.rb"
9
13
  Language:
10
14
  inherit_mode:
11
15
  merge:
@@ -79,6 +83,9 @@ RSpec:
79
83
  - prepend_after
80
84
  - after
81
85
  - append_after
86
+ ErrorMatchers:
87
+ - raise_error
88
+ - raise_exception
82
89
  Includes:
83
90
  inherit_mode:
84
91
  merge:
@@ -535,7 +542,9 @@ RSpec/ImplicitSubject:
535
542
  RSpec/IncludeExamples:
536
543
  Description: Checks for usage of `include_examples`.
537
544
  Enabled: pending
545
+ SafeAutoCorrect: false
538
546
  VersionAdded: '3.6'
547
+ VersionChanged: '3.7'
539
548
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IncludeExamples
540
549
 
541
550
  RSpec/IndexedLet:
@@ -782,7 +791,7 @@ RSpec/ReceiveCounts:
782
791
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts
783
792
 
784
793
  RSpec/ReceiveMessages:
785
- Description: Checks for multiple messages stubbed on the same object.
794
+ Description: Prefer `receive_messages` over multiple `receive`s on the same object.
786
795
  Enabled: true
787
796
  SafeAutoCorrect: false
788
797
  VersionAdded: '2.23'
@@ -13,6 +13,20 @@ module RuboCop
13
13
  # `OnlyStaticConstants` is only relevant when `EnforcedStyle` is
14
14
  # `described_class`.
15
15
  #
16
+ # There's a known caveat with rspec-rails's `controller` helper that
17
+ # runs its block in a different context, and `described_class` is not
18
+ # available to it. `SkipBlocks` option excludes detection in all
19
+ # non-RSpec related blocks.
20
+ #
21
+ # To narrow down this setting to only a specific directory, it is
22
+ # possible to use an overriding configuration file local to that
23
+ # directory.
24
+ #
25
+ # @safety
26
+ # Autocorrection is unsafe when `SkipBlocks: false` because
27
+ # `described_class` might not be available within the block (for
28
+ # example, in rspec-rails's `controller` helper).
29
+ #
16
30
  # @example `EnforcedStyle: described_class` (default)
17
31
  # # bad
18
32
  # describe MyClass do
@@ -47,15 +61,6 @@ module RuboCop
47
61
  # subject { MyClass.do_something }
48
62
  # end
49
63
  #
50
- # There's a known caveat with rspec-rails's `controller` helper that
51
- # runs its block in a different context, and `described_class` is not
52
- # available to it. `SkipBlocks` option excludes detection in all
53
- # non-RSpec related blocks.
54
- #
55
- # To narrow down this setting to only a specific directory, it is
56
- # possible to use an overriding configuration file local to that
57
- # directory.
58
- #
59
64
  # @example `SkipBlocks: true`
60
65
  # # spec/controllers/.rubocop.yml
61
66
  # # RSpec/DescribedClass:
@@ -78,7 +83,13 @@ module RuboCop
78
83
 
79
84
  # @!method common_instance_exec_closure?(node)
80
85
  def_node_matcher :common_instance_exec_closure?, <<~PATTERN
81
- (block (send (const nil? {:Class :Module :Struct}) :new ...) ...)
86
+ (block
87
+ {
88
+ (send (const nil? {:Class :Module :Struct}) :new ...)
89
+ (send (const nil? :Data) :define ...)
90
+ }
91
+ ...
92
+ )
82
93
  PATTERN
83
94
 
84
95
  # @!method rspec_block?(node)
@@ -21,6 +21,7 @@ module RuboCop
21
21
  # - let, let!
22
22
  # - subject, subject!
23
23
  # - expect, is_expected, expect_any_instance_of
24
+ # - raise_error, raise_exception
24
25
  #
25
26
  # By default all of the RSpec methods and aliases are allowed. By setting
26
27
  # a config like:
@@ -30,7 +30,7 @@ module RuboCop
30
30
 
31
31
  # @!method example_description(node)
32
32
  def_node_matcher :example_description, <<~PATTERN
33
- (send _ {#Examples.all #ExampleGroups.all} ${
33
+ (send #rspec? {#Examples.all #ExampleGroups.all} ${
34
34
  $str
35
35
  $(dstr ({str dstr `sym} ...) ...)
36
36
  } ...)
@@ -12,6 +12,57 @@ module RuboCop
12
12
  #
13
13
  # Prefer using `it_behaves_like` instead.
14
14
  #
15
+ # @safety
16
+ # `include_examples` and `it_behaves_like` have different scoping
17
+ # behaviors.
18
+ # Changing `include_examples` to `it_behaves_like` creates a new
19
+ # context, altering setup dependencies, which can lead to unexpected
20
+ # test failures.
21
+ # Specifically, the scope of hooks (`before`, `after`, `around`)
22
+ # changes, which may prevent expected setup from being inherited
23
+ # correctly.
24
+ #
25
+ # Additionally, `let` and `subject` are affected by scoping rules.
26
+ # When `include_examples` is used, `let` and `subject` defined within
27
+ # `shared_examples` are evaluated in the caller's context, allowing
28
+ # access to their values.
29
+ # In contrast, `it_behaves_like` creates a new context, preventing
30
+ # access to `let` or `subject` values from the caller's context.
31
+ #
32
+ # [source,ruby]
33
+ # ----
34
+ # shared_examples "mock behavior" do
35
+ # before do
36
+ # allow(service).to receive(:call).and_return("mocked response")
37
+ # end
38
+ #
39
+ # it "returns mocked response" do
40
+ # expect(service.call).to eq "mocked response"
41
+ # end
42
+ # end
43
+ #
44
+ # context "working example with include_examples" do
45
+ # let(:service) { double(:service) }
46
+ #
47
+ # include_examples "mock behavior"
48
+ #
49
+ # it "uses the mocked service" do
50
+ # expect(service.call).to eq "mocked response" # Passes
51
+ # end
52
+ # end
53
+ #
54
+ # context "broken example with it_behaves_like" do
55
+ # let(:service) { double(:service) }
56
+ #
57
+ # it_behaves_like "mock behavior"
58
+ #
59
+ # it "unexpectedly does not use the mocked service" do
60
+ # # Fails because `it_behaves_like` does not apply the mock setup
61
+ # expect(service.call).to eq "mocked response"
62
+ # end
63
+ # end
64
+ # ----
65
+ #
15
66
  # @example
16
67
  # # bad
17
68
  # include_examples 'examples'
@@ -17,6 +17,8 @@ module RuboCop
17
17
  # end
18
18
  #
19
19
  class IteratedExpectation < Base
20
+ extend AutoCorrector
21
+
20
22
  MSG = 'Prefer using the `all` matcher instead ' \
21
23
  'of iterating over an array.'
22
24
 
@@ -25,14 +27,14 @@ module RuboCop
25
27
  (block
26
28
  (send ... :each)
27
29
  (args (arg $_))
28
- $(...)
30
+ (...)
29
31
  )
30
32
  PATTERN
31
33
 
32
34
  # @!method each_numblock?(node)
33
35
  def_node_matcher :each_numblock?, <<~PATTERN
34
36
  (numblock
35
- (send ... :each) _ $(...)
37
+ (send ... :each) _ (...)
36
38
  )
37
39
  PATTERN
38
40
 
@@ -42,23 +44,43 @@ module RuboCop
42
44
  PATTERN
43
45
 
44
46
  def on_block(node)
45
- each?(node) do |arg, body|
46
- if single_expectation?(body, arg) || only_expectations?(body, arg)
47
- add_offense(node.send_node)
48
- end
47
+ each?(node) do |arg|
48
+ check_offense(node, arg)
49
49
  end
50
50
  end
51
51
 
52
52
  def on_numblock(node)
53
- each_numblock?(node) do |body|
54
- if single_expectation?(body, :_1) || only_expectations?(body, :_1)
55
- add_offense(node.send_node)
56
- end
53
+ each_numblock?(node) do
54
+ check_offense(node, :_1)
57
55
  end
58
56
  end
59
57
 
60
58
  private
61
59
 
60
+ def check_offense(node, argument)
61
+ if single_expectation?(node.body, argument)
62
+ add_offense(node.send_node) do |corrector|
63
+ next unless node.body.arguments.one?
64
+ next if uses_argument_in_matcher?(node, argument)
65
+
66
+ corrector.replace(node, single_expectation_replacement(node))
67
+ end
68
+ elsif only_expectations?(node.body, argument)
69
+ add_offense(node.send_node)
70
+ end
71
+ end
72
+
73
+ def single_expectation_replacement(node)
74
+ collection = node.receiver.source
75
+ matcher = node.body.first_argument.source
76
+
77
+ "expect(#{collection}).to all(#{matcher})"
78
+ end
79
+
80
+ def uses_argument_in_matcher?(node, argument)
81
+ node.body.first_argument.each_descendant.any?(s(:lvar, argument))
82
+ end
83
+
62
84
  def single_expectation?(body, arg)
63
85
  expectation?(body, arg)
64
86
  end
@@ -100,18 +100,21 @@ module RuboCop
100
100
 
101
101
  def on_casgn(node)
102
102
  return unless inside_describe_block?(node)
103
+ return if explicit_namespace?(node.namespace)
103
104
 
104
105
  add_offense(node, message: MSG_CONST)
105
106
  end
106
107
 
107
108
  def on_class(node)
108
109
  return unless inside_describe_block?(node)
110
+ return if explicit_namespace?(node.identifier.namespace)
109
111
 
110
112
  add_offense(node, message: MSG_CLASS)
111
113
  end
112
114
 
113
115
  def on_module(node)
114
116
  return unless inside_describe_block?(node)
117
+ return if explicit_namespace?(node.identifier.namespace)
115
118
 
116
119
  add_offense(node, message: MSG_MODULE)
117
120
  end
@@ -121,6 +124,10 @@ module RuboCop
121
124
  def inside_describe_block?(node)
122
125
  node.each_ancestor(:block).any? { |ancestor| spec_group?(ancestor) }
123
126
  end
127
+
128
+ def explicit_namespace?(namespace)
129
+ !namespace.nil?
130
+ end
124
131
  end
125
132
  end
126
133
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # Checks for multiple messages stubbed on the same object.
6
+ # Prefer `receive_messages` over multiple `receive`s on the same object.
7
7
  #
8
8
  # @safety
9
9
  # The autocorrection is marked as unsafe, because it may change the
@@ -72,6 +72,12 @@ module RuboCop
72
72
  # @!method subject?(node)
73
73
  def_node_matcher :subject?, '(block (send nil? #Subjects.all ...) ...)'
74
74
 
75
+ module ErrorMatchers # :nodoc:
76
+ def self.all(element)
77
+ Language.config['ErrorMatchers'].include?(element.to_s)
78
+ end
79
+ end
80
+
75
81
  module ExampleGroups # :nodoc:
76
82
  class << self
77
83
  def all(element)
@@ -200,14 +206,14 @@ module RuboCop
200
206
  # This is used in Dialect and DescribeClass cops to detect RSpec blocks.
201
207
  module ALL # :nodoc:
202
208
  def self.all(element)
203
- [ExampleGroups, Examples, Expectations, Helpers, Hooks, Includes,
204
- Runners, SharedGroups, Subjects]
209
+ [ErrorMatchers, ExampleGroups, Examples, Expectations, Helpers, Hooks,
210
+ Includes, Runners, SharedGroups, Subjects]
205
211
  .find { |concept| concept.all(element) }
206
212
  end
207
213
  end
208
214
 
209
- private_constant :ExampleGroups, :Examples, :Expectations, :Hooks,
210
- :Includes, :Runners, :SharedGroups, :ALL
215
+ private_constant :ErrorMatchers, :ExampleGroups, :Examples, :Expectations,
216
+ :Hooks, :Includes, :Runners, :SharedGroups, :ALL
211
217
  end
212
218
  end
213
219
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '3.6.0'
7
+ STRING = '3.7.0'
8
8
  end
9
9
  end
10
10
  end
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: 3.6.0
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Backus
@@ -227,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
227
  - !ruby/object:Gem::Version
228
228
  version: '0'
229
229
  requirements: []
230
- rubygems_version: 3.6.7
230
+ rubygems_version: 3.6.9
231
231
  specification_version: 4
232
232
  summary: Code style checking for RSpec files
233
233
  test_files: []