rubocop-rspec 2.10.0 → 2.11.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: 8d0bedaa464141123a49b02ad1a31ed8a63b9960304014c0ef5e52f96fb78176
4
- data.tar.gz: e310236f596a19629629c70d9f94fcb46a39183c43908b5864860efb2abd7602
3
+ metadata.gz: 8b1c8f65ec3429d357c99302f307f318750117e2329719e4cffc60123546a356
4
+ data.tar.gz: 178b52063271fe727162e196b6a364254e86a7343233ee8d15ad2d27f812367d
5
5
  SHA512:
6
- metadata.gz: 7cd82a374f1cd9362070fe6561f9c04927a2ac33f5e1b5ee97a80bc443b0a4c3c90a75d93778e7bf6f439ff759b60857cdeccc2a7b51bfdc8feebccc519e36c8
7
- data.tar.gz: 19bbbdd2d38ef4802be62f44a18e95e83caaf6899c654dff281fe7058fc9bdf6f776cf0491b825b274f67450388a7aef292c2ee51033f6ae96a9d8671829c5e4
6
+ metadata.gz: fdc010e5813ab0d100c50da5686ce10dfff440fb279c01a0f7c0a99f5066202cea53789cbee6d3792b75cc22ce1574e6f06f216822a7ebb960e39f8ad8994139
7
+ data.tar.gz: 055a453f761b8d6ebda211002f2d0265deb4cdc2f8b5567d71cf28d25bcba7d34a1be7f88bd3e7768e29671bb278aa9af4bb6bc910e42008ee083c4c33525cc4
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 2.11.0 (2022-05-18)
6
+
7
+ * Drop Ruby 2.5 support. ([@ydah][])
8
+ * Add new `RSpec/ChangeByZero` cop. ([@ydah][])
9
+ * Improve `RSpec/ExpectChange` to detect namespaced and top-level constants. ([@M-Yamashita01][])
10
+ * Introduce an amendment to `Metrics/BlockLength` to exclude spec files. ([@luke-hill][])
11
+
5
12
  ## 2.10.0 (2022-04-19)
6
13
 
7
14
  * Fix a false positive for `RSpec/EmptyExampleGroup` when expectations in case statement. ([@ydah][])
@@ -681,3 +688,5 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
681
688
  [@oshiro3]: https://github.com/oshiro3
682
689
  [@ydah]: https://github.com/ydah
683
690
  [@t3h2mas]: https://github.com/t3h2mas
691
+ [@M-Yamashita01]: https://github.com/M-Yamashita01
692
+ [@luke-hill]: https://github.com/luke-hill
data/config/default.yml CHANGED
@@ -110,6 +110,14 @@ RSpec:
110
110
  - subject
111
111
  - subject!
112
112
 
113
+ Metrics/BlockLength:
114
+ inherit_mode:
115
+ merge:
116
+ - Exclude
117
+ Exclude:
118
+ - "**/*_spec.rb"
119
+ - "**/spec/**/*"
120
+
113
121
  RSpec/AlignLeftLetBrace:
114
122
  Description: Checks that left braces for adjacent single line lets are aligned.
115
123
  Enabled: false
@@ -176,6 +184,12 @@ RSpec/BeforeAfterAll:
176
184
  StyleGuide: https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope
177
185
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
178
186
 
187
+ RSpec/ChangeByZero:
188
+ Description: Prefer negated matchers over `to change.by(0)`.
189
+ Enabled: pending
190
+ VersionAdded: 2.11.0
191
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ChangeByZero
192
+
179
193
  RSpec/ContextMethod:
180
194
  Description: "`context` should not be used for specifying methods."
181
195
  Enabled: true
@@ -256,7 +270,7 @@ RSpec/DescribedClassModuleWrapping:
256
270
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping
257
271
 
258
272
  RSpec/Dialect:
259
- Description: This cop enforces custom RSpec dialects.
273
+ Description: Enforces custom RSpec dialects.
260
274
  Enabled: false
261
275
  PreferredMethods: {}
262
276
  VersionAdded: '1.33'
@@ -787,13 +801,13 @@ RSpec/VerifiedDoubles:
787
801
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles
788
802
 
789
803
  RSpec/VoidExpect:
790
- Description: This cop checks void `expect()`.
804
+ Description: Checks void `expect()`.
791
805
  Enabled: true
792
806
  VersionAdded: '1.16'
793
807
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect
794
808
 
795
809
  RSpec/Yield:
796
- Description: This cop checks for calling a block within a stub.
810
+ Description: Checks for calling a block within a stub.
797
811
  Enabled: true
798
812
  VersionAdded: '1.32'
799
813
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield
@@ -46,7 +46,7 @@ module RuboCop
46
46
 
47
47
  MSG = 'Use `%<replacement>s` instead of `%<method>s`.'
48
48
 
49
- # https://git.io/v7Kwr
49
+ # https://github.com/teamcapybara/capybara/blob/e283c1aeaa72441f5403963577e16333bf111a81/lib/capybara/rspec/features.rb#L31-L36
50
50
  MAP = {
51
51
  background: :before,
52
52
  scenario: :it,
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Prefer negated matchers over `to change.by(0)`.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # expect { run }.to change(Foo, :bar).by(0)
11
+ # expect { run }.to change { Foo.bar }.by(0)
12
+ # expect { run }
13
+ # .to change(Foo, :bar).by(0)
14
+ # .and change(Foo, :baz).by(0)
15
+ # expect { run }
16
+ # .to change { Foo.bar }.by(0)
17
+ # .and change { Foo.baz }.by(0)
18
+ #
19
+ # # good
20
+ # expect { run }.not_to change(Foo, :bar)
21
+ # expect { run }.not_to change { Foo.bar }
22
+ # expect { run }
23
+ # .to not_change(Foo, :bar)
24
+ # .and not_change(Foo, :baz)
25
+ # expect { run }
26
+ # .to not_change { Foo.bar }
27
+ # .and not_change { Foo.baz }
28
+ #
29
+ class ChangeByZero < Base
30
+ extend AutoCorrector
31
+ MSG = 'Prefer `not_to change` over `to change.by(0)`.'
32
+ MSG_COMPOUND = 'Prefer negated matchers with compound expectations ' \
33
+ 'over `change.by(0)`.'
34
+ RESTRICT_ON_SEND = %i[change].freeze
35
+
36
+ # @!method expect_change_with_arguments(node)
37
+ def_node_matcher :expect_change_with_arguments, <<-PATTERN
38
+ (send
39
+ (send nil? :change ...) :by
40
+ (int 0))
41
+ PATTERN
42
+
43
+ # @!method expect_change_with_block(node)
44
+ def_node_matcher :expect_change_with_block, <<-PATTERN
45
+ (send
46
+ (block
47
+ (send nil? :change)
48
+ (args)
49
+ (send (...) $_)) :by
50
+ (int 0))
51
+ PATTERN
52
+
53
+ def on_send(node)
54
+ expect_change_with_arguments(node.parent) do
55
+ check_offence(node.parent)
56
+ end
57
+
58
+ expect_change_with_block(node.parent.parent) do
59
+ check_offence(node.parent.parent)
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def check_offence(node)
66
+ expression = node.loc.expression
67
+ if compound_expectations?(node)
68
+ add_offense(expression, message: MSG_COMPOUND)
69
+ else
70
+ add_offense(expression) do |corrector|
71
+ autocorrect(corrector, node)
72
+ end
73
+ end
74
+ end
75
+
76
+ def compound_expectations?(node)
77
+ %i[and or].include?(node.parent.method_name)
78
+ end
79
+
80
+ def autocorrect(corrector, node)
81
+ corrector.replace(node.parent.loc.selector, 'not_to')
82
+ range = node.loc.dot.with(end_pos: node.loc.expression.end_pos)
83
+ corrector.remove(range)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -78,9 +78,8 @@ module RuboCop
78
78
  PATTERN
79
79
 
80
80
  # @!method contains_described_class?(node)
81
- def_node_search :contains_described_class?, <<-PATTERN
82
- (send nil? :described_class)
83
- PATTERN
81
+ def_node_search :contains_described_class?,
82
+ '(send nil? :described_class)'
84
83
 
85
84
  def on_block(node)
86
85
  # In case the explicit style is used, we need to remember what's
@@ -129,17 +128,13 @@ module RuboCop
129
128
  end
130
129
 
131
130
  def scope_change?(node)
132
- scope_changing_syntax?(node) ||
131
+ scope_changing_syntax?(node) ||
133
132
  common_instance_exec_closure?(node) ||
134
133
  skippable_block?(node)
135
134
  end
136
135
 
137
136
  def skippable_block?(node)
138
- node.block_type? && !rspec_block?(node) && skip_blocks?
139
- end
140
-
141
- def skip_blocks?
142
- cop_config['SkipBlocks']
137
+ node.block_type? && !rspec_block?(node) && cop_config['SkipBlocks']
143
138
  end
144
139
 
145
140
  def offensive?(node)
@@ -152,6 +147,7 @@ module RuboCop
152
147
 
153
148
  def offensive_described_class?(node)
154
149
  return unless node.const_type?
150
+
155
151
  # E.g. `described_class::CONSTANT`
156
152
  return if contains_described_class?(node)
157
153
 
@@ -172,14 +168,13 @@ module RuboCop
172
168
  # @return [Array<Symbol>]
173
169
  # @example
174
170
  # # nil represents base constant
175
- # collapse_namespace([], :C) # => [:C]
176
- # collapse_namespace([:A, :B], [:C) # => [:A, :B, :C]
177
- # collapse_namespace([:A, :B], [:B, :C) # => [:A, :B, :C]
178
- # collapse_namespace([:A, :B], [nil, :C) # => [nil, :C]
179
- # collapse_namespace([:A, :B], [nil, :B, :C) # => [nil, :B, :C]
171
+ # collapse_namespace([], [:C]) # => [:C]
172
+ # collapse_namespace([:A, :B], [:C]) # => [:A, :B, :C]
173
+ # collapse_namespace([:A, :B], [:B, :C]) # => [:A, :B, :C]
174
+ # collapse_namespace([:A, :B], [nil, :C]) # => [nil, :C]
175
+ # collapse_namespace([:A, :B], [nil, :B, :C]) # => [nil, :B, :C]
180
176
  def collapse_namespace(namespace, const)
181
- return const if namespace.empty?
182
- return const if const.first.nil?
177
+ return const if namespace.empty? || const.first.nil?
183
178
 
184
179
  start = [0, (namespace.length - const.length)].max
185
180
  max = namespace.length
@@ -196,9 +191,7 @@ module RuboCop
196
191
  # const_name(s(:const, s(:const, nil, :M), :C)) # => [:M, :C]
197
192
  # const_name(s(:const, s(:cbase), :C)) # => [nil, :C]
198
193
  def const_name(node)
199
- # rubocop:disable InternalAffairs/NodeDestructuring
200
- namespace, name = *node
201
- # rubocop:enable InternalAffairs/NodeDestructuring
194
+ namespace, name = *node # rubocop:disable InternalAffairs/NodeDestructuring
202
195
  if !namespace
203
196
  [name]
204
197
  elsif namespace.const_type?
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # This cop enforces custom RSpec dialects.
6
+ # Enforces custom RSpec dialects.
7
7
  #
8
8
  # A dialect can be based on the following RSpec methods:
9
9
  #
@@ -39,7 +39,7 @@ module RuboCop
39
39
 
40
40
  # @!method expect_change_with_arguments(node)
41
41
  def_node_matcher :expect_change_with_arguments, <<-PATTERN
42
- (send nil? :change $_ (sym $_))
42
+ (send nil? :change $_ ({sym str} $_))
43
43
  PATTERN
44
44
 
45
45
  # @!method expect_change_with_block(node)
@@ -47,7 +47,7 @@ module RuboCop
47
47
  (block
48
48
  (send nil? :change)
49
49
  (args)
50
- (send ({const send} nil? $_) $_)
50
+ (send $_ $_)
51
51
  )
52
52
  PATTERN
53
53
 
@@ -67,9 +67,9 @@ module RuboCop
67
67
  return unless style == :method_call
68
68
 
69
69
  expect_change_with_block(node) do |receiver, message|
70
- msg = format(MSG_BLOCK, obj: receiver, attr: message)
70
+ msg = format(MSG_BLOCK, obj: receiver.source, attr: message)
71
71
  add_offense(node, message: msg) do |corrector|
72
- replacement = "change(#{receiver}, :#{message})"
72
+ replacement = "change(#{receiver.source}, :#{message})"
73
73
  corrector.replace(node, replacement)
74
74
  end
75
75
  end
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # rubocop:disable InternalAffairs/NodeDestructuring
25
25
  variable_name, _rhs = *node
26
26
  # rubocop:enable InternalAffairs/NodeDestructuring
27
- name = variable_name[1..-1]
27
+ name = variable_name[1..]
28
28
  return unless name.eql?('stdout') || name.eql?('stderr')
29
29
 
30
30
  add_offense(node.loc.name, message: format(MSG, name: name))
@@ -47,7 +47,7 @@ module RuboCop
47
47
  def correct_variable(variable)
48
48
  case variable.type
49
49
  when :dsym
50
- variable.source[1..-1]
50
+ variable.source[1..]
51
51
  when :sym
52
52
  variable.value.to_s.inspect
53
53
  else
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # This cop checks void `expect()`.
6
+ # Checks void `expect()`.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # This cop checks for calling a block within a stub.
6
+ # Checks for calling a block within a stub.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -25,6 +25,7 @@ require_relative 'rspec/be_eq'
25
25
  require_relative 'rspec/be_eql'
26
26
  require_relative 'rspec/be_nil'
27
27
  require_relative 'rspec/before_after_all'
28
+ require_relative 'rspec/change_by_zero'
28
29
  require_relative 'rspec/context_method'
29
30
  require_relative 'rspec/context_wording'
30
31
  require_relative 'rspec/describe_class'
@@ -8,6 +8,7 @@ module RuboCop
8
8
  class ConfigFormatter
9
9
  EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
10
10
  SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails)
11
+ AMENDMENTS = %(Metrics/BlockLength)
11
12
  COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/'
12
13
 
13
14
  def initialize(config, descriptions)
@@ -18,6 +19,7 @@ module RuboCop
18
19
  def dump
19
20
  YAML.dump(unified_config)
20
21
  .gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
22
+ .gsub(*AMENDMENTS, "\n\\0")
21
23
  .gsub(/^(\s+)- /, '\1 - ')
22
24
  end
23
25
 
@@ -26,6 +28,7 @@ module RuboCop
26
28
  def unified_config
27
29
  cops.each_with_object(config.dup) do |cop, unified|
28
30
  next if SUBDEPARTMENTS.include?(cop)
31
+ next if AMENDMENTS.include?(cop)
29
32
 
30
33
  unified[cop].merge!(descriptions.fetch(cop))
31
34
  unified[cop]['Reference'] = COP_DOC_BASE_URL + cop.sub('RSpec/', '')
@@ -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.10.0'
7
+ STRING = '2.11.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.10.0
4
+ version: 2.11.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-04-19 00:00:00.000000000 Z
13
+ date: 2022-05-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -142,6 +142,7 @@ files:
142
142
  - lib/rubocop/cop/rspec/capybara/current_path_expectation.rb
143
143
  - lib/rubocop/cop/rspec/capybara/feature_methods.rb
144
144
  - lib/rubocop/cop/rspec/capybara/visibility_matcher.rb
145
+ - lib/rubocop/cop/rspec/change_by_zero.rb
145
146
  - lib/rubocop/cop/rspec/context_method.rb
146
147
  - lib/rubocop/cop/rspec/context_wording.rb
147
148
  - lib/rubocop/cop/rspec/describe_class.rb
@@ -262,14 +263,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
262
263
  requirements:
263
264
  - - ">="
264
265
  - !ruby/object:Gem::Version
265
- version: 2.5.0
266
+ version: 2.6.0
266
267
  required_rubygems_version: !ruby/object:Gem::Requirement
267
268
  requirements:
268
269
  - - ">="
269
270
  - !ruby/object:Gem::Version
270
271
  version: '0'
271
272
  requirements: []
272
- rubygems_version: 3.3.1
273
+ rubygems_version: 3.1.6
273
274
  signing_key:
274
275
  specification_version: 4
275
276
  summary: Code style checking for RSpec files