-
-
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.
In response to the review comments, I added the following changes later: - Prefer x_type? to is_a? - Use RSpec.Language.Examples - Add are_expected to expectation method names - Prefer on_block to on_send - Add more methods to RSpec.Language.Expectations - Use RSpec.Language.Expectations - Replace with clearer custom method names - Add some missing \@return comments
- Loading branch information
Showing
8 changed files
with
284 additions
and
1 deletion.
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
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,90 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module RSpec | ||
# Checks if an example includes any expectation. | ||
# | ||
# All RSpec's example and expectation methods are covered by default. | ||
# If you are using your own custom methods, | ||
# add the following configuration: | ||
# | ||
# RSpec: | ||
# Language: | ||
# Examples: | ||
# Regular: | ||
# - custom_it | ||
# Expectations: | ||
# - custom_expect | ||
# | ||
# @example | ||
# | ||
# # bad | ||
# it do | ||
# a? | ||
# end | ||
# | ||
# # good | ||
# it do | ||
# expect(a?).to be(true) | ||
# end | ||
class NoExpectationExample < Base | ||
extend AutoCorrector | ||
|
||
include RangeHelp | ||
|
||
MSG = 'No expectation found in this example.' | ||
|
||
# @!method expectation_method_call?(node) | ||
# @param [RuboCop::AST::Node] node | ||
# @return [Boolean] | ||
def_node_matcher( | ||
:expectation_method_call?, | ||
send_pattern('#Expectations.all') | ||
) | ||
|
||
# @param [RuboCop::AST::BlockNode] node | ||
def on_block(node) | ||
return unless example_method_call?(node) | ||
return if including_any_expectation?(node) | ||
|
||
add_offense(node) do |corrector| | ||
corrector.remove(removed_range(node)) | ||
end | ||
end | ||
|
||
private | ||
|
||
# @param [RuboCop::AST::BlockNode] node | ||
# @return [Boolean] | ||
def example_method_call?(node) | ||
Examples.all(node.method_name) | ||
end | ||
|
||
# Recursively checks if the given node includes any expectation. | ||
# @param [RuboCop::AST::Node] node | ||
# @return [Boolean] | ||
def including_any_expectation?(node) | ||
if !node.is_a?(::RuboCop::AST::Node) | ||
false | ||
elsif expectation_method_call?(node) | ||
true | ||
else | ||
node.children.any? do |child| | ||
including_any_expectation?(child) | ||
end | ||
end | ||
end | ||
|
||
# @param [RuboCop::AST::Node] node | ||
# @return [Parser::Source::Range] | ||
def removed_range(node) | ||
range_by_whole_lines( | ||
node.location.expression, | ||
include_final_newline: true | ||
) | ||
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,120 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::RSpec::NoExpectationExample do | ||
context 'with empty example with it' do | ||
it 'registers an offense' do | ||
expect_offense(<<~RUBY) | ||
RSpec.describe Foo do | ||
it { bar } | ||
^^^^^^^^^^ No expectation found in this example. | ||
it { expect(baz).to be_truthy } | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
RSpec.describe Foo do | ||
it { expect(baz).to be_truthy } | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with empty example with specify' do | ||
it 'registers an offense' do | ||
expect_offense(<<~RUBY) | ||
specify { bar } | ||
^^^^^^^^^^^^^^^ No expectation found in this example. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with non-empty example with should' do | ||
it 'registers no offenses' do | ||
expect_no_offenses(<<~RUBY) | ||
it { should be_truthy } | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with empty examples' do | ||
it 'registers offenses' do | ||
expect_offense(<<~RUBY) | ||
it { bar } | ||
^^^^^^^^^^ No expectation found in this example. | ||
it { baz } | ||
^^^^^^^^^^ No expectation found in this example. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with non-empty example with custom expectation' do | ||
it 'registers an offense' do | ||
expect_offense(<<~RUBY) | ||
it { custom_expect(bar) } | ||
^^^^^^^^^^^^^^^^^^^^^^^^^ No expectation found in this example. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with non-empty example with configured custom expectation' do | ||
before do | ||
other_cops.dig('RSpec', 'Language', 'Expectations').push('custom_expect') | ||
end | ||
|
||
it 'registers no offenses' do | ||
expect_no_offenses(<<~RUBY) | ||
it { custom_expect(bar) } | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with empty example with custom example method' do | ||
it 'registers no offenses' do | ||
expect_no_offenses(<<~RUBY) | ||
custom_it { foo } | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with empty example with configured custom example method' do | ||
before do | ||
other_cops.dig( | ||
'RSpec', | ||
'Language', | ||
'Examples', | ||
'Regular' | ||
).push('custom_it') | ||
end | ||
|
||
it 'registers an offense' do | ||
expect_offense(<<~RUBY) | ||
custom_it { foo } | ||
^^^^^^^^^^^^^^^^^ No expectation found in this example. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with block-less example in block' do | ||
it 'registers no offenses' do | ||
expect_no_offenses(<<~RUBY) | ||
RSpec.describe Foo do | ||
pending 'not implemented' | ||
end | ||
RUBY | ||
end | ||
end | ||
end |