-
-
Notifications
You must be signed in to change notification settings - Fork 277
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New Cop:
RSpec/UnusedImplicitSubject
- Loading branch information
Showing
7 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module RSpec | ||
# Checks for usage of explicit subject that could be implicit. | ||
# | ||
# This Cop is not safe as it might be confused by what is the subject. | ||
# | ||
# # bad | ||
# subject(:foo) { :bar } | ||
# it { expect(foo).to eq :bar } | ||
# it { foo.should eq :bar } | ||
# | ||
# # good | ||
# subject(:foo) { :bar } | ||
# it { is_expected.to eq :bar } | ||
# it { should eq :bar } | ||
# | ||
# # also good | ||
# it { expect { foo }.to raise_error } | ||
# it { expect(foo.to_s).to eq 'bar' } | ||
# | ||
class UnusedImplicitSubject < Base | ||
extend AutoCorrector | ||
|
||
MSG = 'Use implicit subject.' | ||
RESTRICT_ON_SEND = %i[expect should subject subject!].freeze | ||
|
||
def_node_matcher :subject_definition, | ||
'(send #rspec? {:subject :subject!} (sym $_name))' | ||
def_node_matcher :subject_should?, | ||
'(send (send nil? %subject) :should ...)' | ||
def_node_matcher :expect_subject?, | ||
'(send nil? :expect (send nil? %subject))' | ||
|
||
def on_send(node) | ||
send(node.method_name, node) | ||
end | ||
|
||
private | ||
|
||
def subject(node) | ||
@cur_subject = subject_definition(node) | ||
end | ||
alias subject! subject | ||
|
||
def should(node) | ||
return unless subject_should?(node, subject: @cur_subject) | ||
|
||
range = node.receiver.loc.expression.join(node.loc.selector) | ||
add_offense(range) { |c| c.replace(range, 'should') } | ||
end | ||
|
||
def expect(node) | ||
return unless expect_subject?(node, subject: @cur_subject) | ||
|
||
add_offense(node) { |c| c.replace(node, 'is_expected') } | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::RSpec::UnusedImplicitSubject, :config do | ||
context 'with a subject that can be used implicitly' do | ||
it 'flags expect(that_subject)' do | ||
expect_offense(<<-RUBY) | ||
subject(:example) {} | ||
it { expect(example).to be_good } | ||
^^^^^^^^^^^^^^^ Use implicit subject. | ||
RUBY | ||
|
||
expect_correction(<<-RUBY) | ||
subject(:example) {} | ||
it { is_expected.to be_good } | ||
RUBY | ||
end | ||
|
||
it 'flags that_subject.should' do | ||
expect_offense(<<-RUBY) | ||
subject(:example) {} | ||
it { example.should be_good } | ||
^^^^^^^^^^^^^^ Use implicit subject. | ||
it { example.should == 42 } | ||
^^^^^^^^^^^^^^ Use implicit subject. | ||
RUBY | ||
|
||
expect_correction(<<-RUBY) | ||
subject(:example) {} | ||
it { should be_good } | ||
it { should == 42 } | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with a subject that can not be used implicitly' do | ||
it 'does not flag similar cases' do | ||
expect_no_offenses(<<-RUBY) | ||
let(:example) {} | ||
it { expect(example).to be_good } | ||
it { example.should be_good } | ||
RUBY | ||
end | ||
|
||
it 'does not flag non-simplifyable cases' do | ||
expect_no_offenses(<<-RUBY) | ||
subject(:example) {} | ||
it { expect(example.foo).to be_good } | ||
it { example.foo.should be_good } | ||
it { expect { example }.to be_good } | ||
RUBY | ||
end | ||
end | ||
end |