rubocop-rspec 2.14.2 → 2.15.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: bbd70ea9708a7d87e0a1307234e3ac5cc37cc6197e6b1cc72487342b772ec6f1
4
- data.tar.gz: 0c50303e8a0d4218508c51e778d5cb6633b54fe6f823951ea5f8df68d162dfda
3
+ metadata.gz: 1e120f8d06ef760cbe4f3a3d077ca6cd8ceeb274a26042a6e1469fe9a280c969
4
+ data.tar.gz: 0c80cc155e8f64b03a97de1327e454d9ff2efb1a75b02e3b098f868afed30d17
5
5
  SHA512:
6
- metadata.gz: 2e1a6e55fb7aeef036448fe57f03b2d80b796e6971fbd22cd63db496e61b1e211a64e89e987cccc74f5124746713581fb621c805d458f7ff273d436432599483
7
- data.tar.gz: 76655025092f103fbd6ca3eda6d466236a8a9857f207e11bc3f8e51c38238367346971c4a0f3feeca6b9069a53fa48bf8281d5dff61f68c6562edce4405a10f0
6
+ metadata.gz: e982f97a23de2473c5cae6cd20bb653bcbcee806abddf0dda09c7b30692193858fc105c7b46ce3c004f28a7f680d1b3a475298c7b10d0e1499d5b80333fde504
7
+ data.tar.gz: c3b79b39a2c98d9103cb4edbf6c2d8e2cc957790fd8fa617e1fdece172f3dfaaf652bf482e7236a1da663f3b9afae943c17efee1e4a5f0293acc771bbc1c3c43
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 2.15.0 (2022-11-03)
6
+
7
+ - Fix a false positive for `RSpec/RepeatedDescription` when different its block expectations are used. ([@ydah])
8
+ - Add `named_only` style to `RSpec/NamedSubject`. ([@kuahyeow])
9
+ - Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls without the first positional argument. ([@pirj])
10
+ - Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls inside a Hash or an Array. ([@pirj])
11
+ - Fix `RSpec/NestedGroups` to correctly use `AllowedGroups` config. ([@samrjenkins])
12
+ - Remove `Runners` and `HookScopes` RSpec DSL elements from configuration. ([@pirj])
13
+ - Add `with default RSpec/Language config` helper to `lib` (under `rubocop/rspec/shared_contexts/default_rspec_language_config_context`), to allow use for downstream cops based on `RuboCop::Cop::RSpec::Base`. ([@smcgivern])
14
+
5
15
  ## 2.14.2 (2022-10-25)
6
16
 
7
17
  - Fix an incorrect autocorrect for `FactoryBot/ConsistentParenthesesStyle` with `omit_parentheses` option when method name and first argument are not on same line. ([@ydah])
@@ -724,6 +734,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
724
734
  [@jtannas]: https://github.com/jtannas
725
735
  [@kellysutton]: https://github.com/kellysutton
726
736
  [@koic]: https://github.com/koic
737
+ [@kuahyeow]: https://github.com/kuahyeow
727
738
  [@lazycoder9]: https://github.com/lazycoder9
728
739
  [@leoarnold]: https://github.com/leoarnold
729
740
  [@liberatys]: https://github.com/Liberatys
@@ -760,9 +771,11 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
760
771
  [@rrosenblum]: https://github.com/rrosenblum
761
772
  [@rspeicher]: https://github.com/rspeicher
762
773
  [@rst-j]: https://github.com/RST-J
774
+ [@samrjenkins]: https://github.com/samrjenkins
763
775
  [@schmijos]: https://github.com/schmijos
764
776
  [@seanpdoyle]: https://github.com/seanpdoyle
765
777
  [@sl4vr]: https://github.com/sl4vr
778
+ [@smcgivern]: https://github.com/smcgivern
766
779
  [@stephannv]: https://github.com/stephannv
767
780
  [@t3h2mas]: https://github.com/t3h2mas
768
781
  [@tdeo]: https://github.com/tdeo
data/config/default.yml CHANGED
@@ -12,8 +12,6 @@ RSpec:
12
12
  - Expectations
13
13
  - Helpers
14
14
  - Hooks
15
- - HookScopes
16
- - Runners
17
15
  - Subjects
18
16
  ExampleGroups:
19
17
  inherit_mode:
@@ -81,12 +79,6 @@ RSpec:
81
79
  - prepend_after
82
80
  - after
83
81
  - append_after
84
- HookScopes:
85
- - each
86
- - example
87
- - context
88
- - all
89
- - suite
90
82
  Includes:
91
83
  inherit_mode:
92
84
  merge:
@@ -98,10 +90,6 @@ RSpec:
98
90
  - include_examples
99
91
  Context:
100
92
  - include_context
101
- Runners:
102
- - to
103
- - to_not
104
- - not_to
105
93
  SharedGroups:
106
94
  inherit_mode:
107
95
  merge:
@@ -624,8 +612,13 @@ RSpec/MultipleSubjects:
624
612
  RSpec/NamedSubject:
625
613
  Description: Checks for explicitly referenced test subjects.
626
614
  Enabled: true
615
+ EnforcedStyle: always
616
+ SupportedStyles:
617
+ - always
618
+ - named_only
627
619
  IgnoreSharedExamples: true
628
620
  VersionAdded: 1.5.3
621
+ VersionChanged: '2.15'
629
622
  StyleGuide: https://rspec.rubystyle.guide/#use-subject
630
623
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject
631
624
 
@@ -55,15 +55,18 @@ module RuboCop
55
55
 
56
56
  FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
57
57
 
58
+ RESTRICT_ON_SEND = FACTORY_CALLS
59
+
58
60
  # @!method factory_call(node)
59
61
  def_node_matcher :factory_call, <<-PATTERN
60
- (send
61
- ${#factory_bot? nil?} %FACTORY_CALLS
62
- $...)
62
+ (send
63
+ {#factory_bot? nil?} %FACTORY_CALLS
64
+ {sym str send lvar} _*
65
+ )
63
66
  PATTERN
64
67
 
65
68
  def on_send(node)
66
- return if nested_call?(node) # prevent from nested matching
69
+ return if ambiguous_without_parentheses?(node)
67
70
 
68
71
  factory_call(node) do
69
72
  if node.parenthesized?
@@ -93,8 +96,10 @@ module RuboCop
93
96
  end
94
97
  end
95
98
 
96
- def nested_call?(node)
97
- node.parent&.send_type?
99
+ def ambiguous_without_parentheses?(node)
100
+ node.parent&.send_type? ||
101
+ node.parent&.pair_type? ||
102
+ node.parent&.array_type?
98
103
  end
99
104
 
100
105
  private
@@ -12,11 +12,11 @@ module RuboCop
12
12
  # should be the most important object in your tests so they deserve
13
13
  # a descriptive name.
14
14
  #
15
- # This cop can be configured in your configuration using the
16
- # `IgnoreSharedExamples` which will not report offenses for implicit
15
+ # This cop can be configured in your configuration using `EnforcedStyle`,
16
+ # and `IgnoreSharedExamples` which will not report offenses for implicit
17
17
  # subjects in shared example groups.
18
18
  #
19
- # @example
19
+ # @example `EnforcedStyle: always` (default)
20
20
  # # bad
21
21
  # RSpec.describe User do
22
22
  # subject { described_class.new }
@@ -27,7 +27,7 @@ module RuboCop
27
27
  # end
28
28
  #
29
29
  # # good
30
- # RSpec.describe Foo do
30
+ # RSpec.describe User do
31
31
  # subject(:user) { described_class.new }
32
32
  #
33
33
  # it 'is valid' do
@@ -36,13 +36,49 @@ module RuboCop
36
36
  # end
37
37
  #
38
38
  # # also good
39
- # RSpec.describe Foo do
39
+ # RSpec.describe User do
40
+ # subject(:user) { described_class.new }
41
+ #
42
+ # it { is_expected.to be_valid }
43
+ # end
44
+ #
45
+ # @example `EnforcedStyle: named_only`
46
+ # # bad
47
+ # RSpec.describe User do
48
+ # subject(:user) { described_class.new }
49
+ #
50
+ # it 'is valid' do
51
+ # expect(subject.valid?).to be(true)
52
+ # end
53
+ # end
54
+ #
55
+ # # good
56
+ # RSpec.describe User do
40
57
  # subject(:user) { described_class.new }
41
58
  #
59
+ # it 'is valid' do
60
+ # expect(user.valid?).to be(true)
61
+ # end
62
+ # end
63
+ #
64
+ # # also good
65
+ # RSpec.describe User do
66
+ # subject { described_class.new }
67
+ #
42
68
  # it { is_expected.to be_valid }
43
69
  # end
44
70
  #
71
+ # # acceptable
72
+ # RSpec.describe User do
73
+ # subject { described_class.new }
74
+ #
75
+ # it 'is valid' do
76
+ # expect(subject.valid?).to be(true)
77
+ # end
78
+ # end
45
79
  class NamedSubject < Base
80
+ include ConfigurableEnforcedStyle
81
+
46
82
  MSG = 'Name your test subject if you need to reference it explicitly.'
47
83
 
48
84
  # @!method example_or_hook_block?(node)
@@ -62,14 +98,53 @@ module RuboCop
62
98
  end
63
99
 
64
100
  subject_usage(node) do |subject_node|
65
- add_offense(subject_node.loc.selector)
101
+ check_explicit_subject(subject_node)
66
102
  end
67
103
  end
68
104
 
105
+ private
106
+
69
107
  def ignored_shared_example?(node)
70
108
  cop_config['IgnoreSharedExamples'] &&
71
109
  node.each_ancestor(:block).any?(&method(:shared_example?))
72
110
  end
111
+
112
+ def check_explicit_subject(node)
113
+ return if allow_explicit_subject?(node)
114
+
115
+ add_offense(node.loc.selector)
116
+ end
117
+
118
+ def allow_explicit_subject?(node)
119
+ !always? && !named_only?(node)
120
+ end
121
+
122
+ def always?
123
+ style == :always
124
+ end
125
+
126
+ def named_only?(node)
127
+ style == :named_only &&
128
+ subject_definition_is_named?(node)
129
+ end
130
+
131
+ def subject_definition_is_named?(node)
132
+ subject = nearest_subject(node)
133
+
134
+ subject&.send_node&.arguments?
135
+ end
136
+
137
+ def nearest_subject(node)
138
+ node
139
+ .each_ancestor(:block)
140
+ .lazy
141
+ .map { |block_node| find_subject(block_node) }
142
+ .find(&:itself)
143
+ end
144
+
145
+ def find_subject(block_node)
146
+ block_node.body.child_nodes.find { |send_node| subject?(send_node) }
147
+ end
73
148
  end
74
149
  end
75
150
  end
@@ -133,7 +133,7 @@ module RuboCop
133
133
  def count_up_nesting?(node, example_group)
134
134
  example_group &&
135
135
  (node.block_type? &&
136
- !allowed_groups.include?(node.method_name))
136
+ !allowed_groups.include?(node.method_name.to_s))
137
137
  end
138
138
 
139
139
  def message(nesting)
@@ -45,8 +45,12 @@ module RuboCop
45
45
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
46
46
  return unless example_group?(node)
47
47
 
48
- repeated_descriptions(node).each do |repeated_description|
49
- add_offense(repeated_description)
48
+ repeated_descriptions(node).each do |description|
49
+ add_offense(description)
50
+ end
51
+
52
+ repeated_its(node).each do |its|
53
+ add_offense(its)
50
54
  end
51
55
  end
52
56
 
@@ -57,6 +61,7 @@ module RuboCop
57
61
  grouped_examples =
58
62
  RuboCop::RSpec::ExampleGroup.new(node)
59
63
  .examples
64
+ .reject { |n| n.definition.method?(:its) }
60
65
  .group_by { |example| example_signature(example) }
61
66
 
62
67
  grouped_examples
@@ -66,9 +71,27 @@ module RuboCop
66
71
  .map(&:definition)
67
72
  end
68
73
 
74
+ def repeated_its(node)
75
+ grouped_its =
76
+ RuboCop::RSpec::ExampleGroup.new(node)
77
+ .examples
78
+ .select { |n| n.definition.method?(:its) }
79
+ .group_by { |example| its_signature(example) }
80
+
81
+ grouped_its
82
+ .select { |signatures, group| signatures.any? && group.size > 1 }
83
+ .values
84
+ .flatten
85
+ .map(&:to_node)
86
+ end
87
+
69
88
  def example_signature(example)
70
89
  [example.metadata, example.doc_string]
71
90
  end
91
+
92
+ def its_signature(example)
93
+ [example.doc_string, example]
94
+ end
72
95
  end
73
96
  end
74
97
  end
@@ -135,8 +135,9 @@ module RuboCop
135
135
  end
136
136
 
137
137
  module HookScopes # :nodoc:
138
+ ALL = %i[each example context all suite].freeze
138
139
  def self.all(element)
139
- Language.config['HookScopes'].include?(element.to_s)
140
+ ALL.include?(element)
140
141
  end
141
142
  end
142
143
 
@@ -158,8 +159,9 @@ module RuboCop
158
159
  end
159
160
 
160
161
  module Runners # :nodoc:
162
+ ALL = %i[to to_not not_to].freeze
161
163
  def self.all(element)
162
- Language.config['Runners'].include?(element.to_s)
164
+ ALL.include?(element)
163
165
  end
164
166
  end
165
167
 
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.shared_context 'with default RSpec/Language config' do
4
+ include_context 'config'
5
+
6
+ # Deep duplication is needed to prevent config leakage between examples
7
+ let(:other_cops) do
8
+ default_language = RuboCop::ConfigLoader
9
+ .default_configuration['RSpec']['Language']
10
+ default_include = RuboCop::ConfigLoader
11
+ .default_configuration['RSpec']['Include']
12
+ { 'RSpec' =>
13
+ {
14
+ 'Include' => default_include,
15
+ 'Language' => deep_dup(default_language)
16
+ } }
17
+ end
18
+
19
+ def deep_dup(object)
20
+ case object
21
+ when Array
22
+ object.map { |item| deep_dup(item) }
23
+ when Hash
24
+ object.transform_values(&method(:deep_dup))
25
+ else
26
+ object # only collections undergo modifications and need duping
27
+ end
28
+ end
29
+ 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 = '2.14.2'
7
+ STRING = '2.15.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: 2.14.2
4
+ version: 2.15.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: 2022-10-25 00:00:00.000000000 Z
13
+ date: 2022-11-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -178,6 +178,7 @@ files:
178
178
  - lib/rubocop/rspec/language.rb
179
179
  - lib/rubocop/rspec/language/node_pattern.rb
180
180
  - lib/rubocop/rspec/node.rb
181
+ - lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb
181
182
  - lib/rubocop/rspec/version.rb
182
183
  - lib/rubocop/rspec/wording.rb
183
184
  homepage: https://github.com/rubocop/rubocop-rspec