Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Obsolete StringAsInstanceDoubleConstant in favor of VerifiedDoubleReference for constants only #1968

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,3 @@ Style/StringChars: {Enabled: true}
Style/SuperWithArgsParentheses: {Enabled: true}
Style/SwapValues: {Enabled: true}
Style/YAMLFileRead: {Enabled: true}

# Enable our own pending cops.
#
RSpec/StringAsInstanceDoubleConstant:
Enabled: true
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Fix `RSpec/VoidExpect` to only operate inside an example block. ([@corsonknowles])
- Change `RSpec/ContextWording` cop to always report an offense when both `Prefixes` and `AllowedPatterns` are empty. ([@ydah])
- Add support for `and` and `or` compound matchers to `RSpec/ChangeByZero` cop. ([@ydah])
- Replace `RSpec/StringAsInstanceDoubleConstant` with `RSpecVerifiedDoubleReference` configured to only support constant class references. ([@corsonknowles])

## 3.1.0 (2024-10-01)

Expand Down
13 changes: 1 addition & 12 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -930,13 +930,6 @@ RSpec/SpecFilePathSuffix:
- "**/spec/**/*"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathSuffix

RSpec/StringAsInstanceDoubleConstant:
Description: Do not use a string as `instance_double` constant.
Enabled: pending
Safe: false
VersionAdded: '3.1'
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StringAsInstanceDoubleConstant

RSpec/StubbedMock:
Description: Checks that message expectations do not have a configured response.
Enabled: true
Expand Down Expand Up @@ -995,12 +988,8 @@ RSpec/VerifiedDoubleReference:
Description: Checks for consistent verified double reference style.
Enabled: true
SafeAutoCorrect: false
EnforcedStyle: constant
SupportedStyles:
- constant
- string
VersionAdded: 2.10.0
VersionChanged: '2.12'
VersionChanged: "<<next>>"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubleReference

RSpec/VerifiedDoubles:
Expand Down
10 changes: 10 additions & 0 deletions config/obsoletion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

# Cop parameters that have been changed
# Can be treated as a warning instead of a failure with `severity: warning`
changed_enforced_styles:
- cops: RSpec/VerifiedDoubleReference
parameters: EnforcedStyle
value: string
reason: String references are not verifying unless the class is loaded.
severity: warning

changed_parameters:
- cops:
- RSpec/VariableName
Expand All @@ -28,3 +35,6 @@ extracted:
RSpec/Rails/*: rubocop-rspec_rails
RSpec/FactoryBot/*: rubocop-factory_bot
RSpec/Capybara/*: rubocop-capybara

renamed:
RSpec/StringAsInstanceDoubleConstant: RSpec/VerifiedDoubleReference
1 change: 0 additions & 1 deletion docs/modules/ROOT/pages/cops.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@
* xref:cops_rspec.adoc#rspecsortmetadata[RSpec/SortMetadata]
* xref:cops_rspec.adoc#rspecspecfilepathformat[RSpec/SpecFilePathFormat]
* xref:cops_rspec.adoc#rspecspecfilepathsuffix[RSpec/SpecFilePathSuffix]
* xref:cops_rspec.adoc#rspecstringasinstancedoubleconstant[RSpec/StringAsInstanceDoubleConstant]
* xref:cops_rspec.adoc#rspecstubbedmock[RSpec/StubbedMock]
* xref:cops_rspec.adoc#rspecsubjectdeclaration[RSpec/SubjectDeclaration]
* xref:cops_rspec.adoc#rspecsubjectstub[RSpec/SubjectStub]
Expand Down
83 changes: 8 additions & 75 deletions docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5907,45 +5907,6 @@ spec/models/user.rb # shared_examples_for 'foo'

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathSuffix

[#rspecstringasinstancedoubleconstant]
== RSpec/StringAsInstanceDoubleConstant

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| No
| Always (Unsafe)
| 3.1
| -
|===

Do not use a string as `instance_double` constant.

[#safety-rspecstringasinstancedoubleconstant]
=== Safety

This cop is unsafe because the correction requires loading the class.
Loading before stubbing causes RSpec to only allow instance methods
to be stubbed.

[#examples-rspecstringasinstancedoubleconstant]
=== Examples

[source,ruby]
----
# bad
instance_double('User', name: 'John')

# good
instance_double(User, name: 'John')
----

[#references-rspecstringasinstancedoubleconstant]
=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StringAsInstanceDoubleConstant

[#rspecstubbedmock]
== RSpec/StubbedMock

Expand Down Expand Up @@ -6357,22 +6318,21 @@ let(:userFood_2) { 'fettuccine' }
| Yes
| Always (Unsafe)
| 2.10.0
| 2.12
| <<next>>
|===

Checks for consistent verified double reference style.

Only investigates references that are one of the supported styles.
[#safety-rspecverifieddoublereference]
=== Safety

This cop can be configured in your configuration using the
`EnforcedStyle` option and supports `--auto-gen-config`.
This cop is unsafe because the correction requires loading the class.
Loading before stubbing causes RSpec to only allow instance methods
to be stubbed.

[#examples-rspecverifieddoublereference]
=== Examples

[#_enforcedstyle_-constant_-_default_-rspecverifieddoublereference]
==== `EnforcedStyle: constant` (default)

[source,ruby]
----
# bad
Expand All @@ -6386,24 +6346,8 @@ let(:foo) do
end
----

[#_enforcedstyle_-string_-rspecverifieddoublereference]
==== `EnforcedStyle: string`

[source,ruby]
----
# bad
let(:foo) do
instance_double(ClassName, method_name: 'returned_value')
end

# good
let(:foo) do
instance_double('ClassName', method_name: 'returned_value')
end
----

[#reference-is-not-in-the-supported-style-list_-no-enforcement-rspecverifieddoublereference]
==== Reference is not in the supported style list. No enforcement
[#reference-is-any-dynamic-variable_-no-enforcement-rspecverifieddoublereference]
==== Reference is any dynamic variable. No enforcement

[source,ruby]
----
Expand All @@ -6413,17 +6357,6 @@ let(:foo) do
end
----

[#configurable-attributes-rspecverifieddoublereference]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `constant`
| `constant`, `string`
|===

[#references-rspecverifieddoublereference]
=== References

Expand Down
45 changes: 0 additions & 45 deletions lib/rubocop/cop/rspec/string_as_instance_double_constant.rb

This file was deleted.

67 changes: 14 additions & 53 deletions lib/rubocop/cop/rspec/verified_double_reference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ module Cop
module RSpec
# Checks for consistent verified double reference style.
#
# Only investigates references that are one of the supported styles.
#
# @see https://rspec.info/features/3-12/rspec-mocks/verifying-doubles
#
# This cop can be configured in your configuration using the
# `EnforcedStyle` option and supports `--auto-gen-config`.
# @safety
# This cop is unsafe because the correction requires loading the class.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

# Loading before stubbing causes RSpec to only allow instance methods
# to be stubbed.
#
# @example `EnforcedStyle: constant` (default)
# @example
# # bad
# let(:foo) do
# instance_double('ClassName', method_name: 'returned_value')
Expand All @@ -23,28 +23,17 @@ module RSpec
# instance_double(ClassName, method_name: 'returned_value')
# end
#
# @example `EnforcedStyle: string`
# # bad
# let(:foo) do
# instance_double(ClassName, method_name: 'returned_value')
# end
#
# # good
# let(:foo) do
# instance_double('ClassName', method_name: 'returned_value')
# end
#
# @example Reference is not in the supported style list. No enforcement
# @example Reference is any dynamic variable. No enforcement
#
# # good
# let(:foo) do
# instance_double(@klass, method_name: 'returned_value')
# end
class VerifiedDoubleReference < Base
extend AutoCorrector
include ConfigurableEnforcedStyle

MSG = 'Use a %<style>s class reference for verified doubles.'
MSG = 'Use a constant class reference for verified doubles. ' \
'String references are not verifying unless the class is loaded.'

RESTRICT_ON_SEND = Set[
:class_double,
Expand All @@ -57,53 +46,25 @@ class VerifiedDoubleReference < Base
:stub_model
].freeze

REFERENCE_TYPE_STYLES = {
str: :string,
const: :constant
}.freeze

# @!method verified_double(node)
def_node_matcher :verified_double, <<~PATTERN
(send
nil?
RESTRICT_ON_SEND
$_class_reference
$str
...)
PATTERN

def on_send(node)
verified_double(node) do |class_reference|
break correct_style_detected unless opposing_style?(class_reference)

message = format(MSG, style: style)
expression = class_reference.source_range

add_offense(expression, message: message) do |corrector|
offense = class_reference.source
corrector.replace(expression, correct_style(offense))

opposite_style_detected
verified_double(node) do |string_argument_node|
add_offense(string_argument_node) do |corrector|
autocorrect(corrector, string_argument_node)
end
end
end

private

def opposing_style?(class_reference)
class_reference_style = REFERENCE_TYPE_STYLES[class_reference.type]

# Only enforce supported styles
return false unless class_reference_style

class_reference_style != style
end

def correct_style(offense)
if style == :string
"'#{offense}'"
else
offense.gsub(/^['"]|['"]$/, '')
end
def autocorrect(corrector, node)
corrector.replace(node, node.value)
end
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/rubocop/cop/rspec_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@
require_relative 'rspec/sort_metadata'
require_relative 'rspec/spec_file_path_format'
require_relative 'rspec/spec_file_path_suffix'
require_relative 'rspec/string_as_instance_double_constant'
require_relative 'rspec/stubbed_mock'
require_relative 'rspec/subject_declaration'
require_relative 'rspec/subject_stub'
Expand Down

This file was deleted.

Loading