rubocop-rspec 2.14.2 → 2.15.0

Sign up to get free protection for your applications and to get access to all the features.
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