Skip to content

Commit

Permalink
Allow expect_offense to have variables
Browse files Browse the repository at this point in the history
  • Loading branch information
marcandre committed May 31, 2020
1 parent c92378a commit 4e0f9b4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 49 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
### New features

* [#6289](https://github.com/rubocop-hq/rubocop/issues/6289): Add new `CheckDefinitionPathHierarchy` option for `Naming/FileName`. ([@jschneid][])
* [#8069](https://github.com/rubocop-hq/rubocop/issues/8069): New option for `expect_offense` to help format offense templates. ([@marcandre][])

### Bug fixes

Expand Down
20 changes: 19 additions & 1 deletion lib/rubocop/rspec/expect_offense.rb
Expand Up @@ -71,9 +71,27 @@ module RSpec
# RUBY
#
# expect_no_corrections
#
# If your code has variables of different lengths, you can use `%{foo}`
# and `^{foo}` to format your template:
#
# %w[raise fail].each do |keyword|
# expect_offense(<<~RUBY, keyword: keyword)
# %{keyword}(RuntimeError, msg)
# ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument can be removed.
# RUBY
module ExpectOffense
def format_offense(source, **replacements)
replacements.each do |keyword, value|
source = source.gsub("%{#{keyword}}", value)
.gsub("^{#{keyword}}", '^' * value.size)
end
source
end

# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def expect_offense(source, file = nil)
def expect_offense(source, file = nil, **replacements)
source = format_offense(source, **replacements)
RuboCop::Formatter::DisabledConfigFormatter
.config_to_allow_offenses = {}
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
Expand Down
84 changes: 36 additions & 48 deletions spec/rubocop/cop/style/redundant_exception_spec.rb
Expand Up @@ -5,67 +5,55 @@

shared_examples 'common behavior' do |keyword|
it "reports an offense for a #{keyword} with RuntimeError" do
src = "#{keyword} RuntimeError, msg"
inspect_source(src)
expect(cop.highlights).to eq([src])
expect(cop.messages)
.to eq(['Redundant `RuntimeError` argument can be removed.'])
end
expect_offense(<<~RUBY, keyword: keyword)
%{keyword} RuntimeError, msg
^{keyword}^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument can be removed.
RUBY

it "reports an offense for a #{keyword} with RuntimeError.new" do
src = "#{keyword} RuntimeError.new(msg)"
inspect_source(src)
expect(cop.highlights).to eq([src])
expect(cop.messages)
.to eq(['Redundant `RuntimeError.new` call can be replaced with ' \
'just the message.'])
expect_correction(<<~RUBY)
#{keyword} msg
RUBY
end

it "accepts a #{keyword} with RuntimeError if it does not have 2 args" do
expect_no_offenses("#{keyword} RuntimeError, msg, caller")
end
it "reports an offense for a #{keyword} with RuntimeError and ()" do
expect_offense(<<~RUBY, keyword: keyword)
%{keyword}(RuntimeError, msg)
^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument can be removed.
RUBY

it "auto-corrects a #{keyword} RuntimeError by removing RuntimeError" do
src = "#{keyword} RuntimeError, msg"
result_src = "#{keyword} msg"
new_src = autocorrect_source(src)
expect(new_src).to eq(result_src)
expect_correction(<<~RUBY)
#{keyword}(msg)
RUBY
end

it "auto-corrects a #{keyword} RuntimeError and leaves parentheses" do
src = "#{keyword}(RuntimeError, msg)"
result_src = "#{keyword}(msg)"
new_src = autocorrect_source(src)
expect(new_src).to eq(result_src)
end
it "reports an offense for a #{keyword} with RuntimeError.new" do
expect_offense(<<~RUBY, keyword: keyword)
%{keyword} RuntimeError.new msg
^{keyword}^^^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError.new` call can be replaced with just the message.
RUBY

it "auto-corrects a #{keyword} RuntimeError.new with parentheses by " \
'removing RuntimeError.new' do
src = "#{keyword} RuntimeError.new(msg)"
result_src = "#{keyword} msg"
new_src = autocorrect_source(src)
expect(new_src).to eq(result_src)
expect_correction(<<~RUBY)
#{keyword} msg
RUBY
end

it "auto-corrects a #{keyword} RuntimeError.new without parentheses by " \
'removing RuntimeError.new' do
src = "#{keyword} RuntimeError.new msg"
result_src = "#{keyword} msg"
new_src = autocorrect_source(src)
expect(new_src).to eq(result_src)
it "reports an offense for a #{keyword} with RuntimeError.new" do
expect_offense(<<~RUBY, keyword: keyword)
%{keyword} RuntimeError.new(msg)
^{keyword}^^^^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError.new` call can be replaced with just the message.
RUBY

expect_correction(<<~RUBY)
#{keyword} msg
RUBY
end

it "does not modify #{keyword} w/ RuntimeError if it does not have 2 " \
'args' do
src = "#{keyword} runtimeError, msg, caller"
new_src = autocorrect_source(src)
expect(new_src).to eq(src)
it "accepts a #{keyword} with RuntimeError if it does not have 2 args" do
expect_no_offenses("#{keyword} RuntimeError, msg, caller")
end

it 'does not modify rescue w/ non redundant error' do
src = "#{keyword} OtherError, msg"
new_src = autocorrect_source(src)
expect(new_src).to eq(src)
it 'accepts rescue w/ non redundant error' do
expect_no_offenses "#{keyword} OtherError, msg"
end
end

Expand Down

0 comments on commit 4e0f9b4

Please sign in to comment.