Merge pull request #6497 from Homebrew/dependabot/bundler/Library/Homebrew/rubocop-rspec-1.36.0

build: bump rubocop-rspec from 1.35.0 to 1.36.0 in /Library/Homebrew
This commit is contained in:
Mike McQuaid 2019-09-27 17:07:25 +01:00 committed by GitHub
commit ab152a9b5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
103 changed files with 352 additions and 167 deletions

View File

@ -89,8 +89,8 @@ GEM
unicode-display_width (>= 1.4.0, < 1.7) unicode-display_width (>= 1.4.0, < 1.7)
rubocop-performance (1.4.1) rubocop-performance (1.4.1)
rubocop (>= 0.71.0) rubocop (>= 0.71.0)
rubocop-rspec (1.35.0) rubocop-rspec (1.36.0)
rubocop (>= 0.60.0) rubocop (>= 0.68.1)
ruby-macho (2.2.0) ruby-macho (2.2.0)
ruby-progressbar (1.10.1) ruby-progressbar (1.10.1)
simplecov (0.16.1) simplecov (0.16.1)

View File

@ -39,7 +39,7 @@ describe Requirement do
end end
describe "#fatal?" do describe "#fatal?" do
context "#fatal true is specified" do describe "#fatal true is specified" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
fatal true fatal true
@ -49,13 +49,13 @@ describe Requirement do
it { is_expected.to be_fatal } it { is_expected.to be_fatal }
end end
context "#fatal is omitted" do describe "#fatal is omitted" do
it { is_expected.not_to be_fatal } it { is_expected.not_to be_fatal }
end end
end end
describe "#satisfied?" do describe "#satisfied?" do
context "#satisfy with block and build_env returns true" do describe "#satisfy with block and build_env returns true" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
satisfy(build_env: false) do satisfy(build_env: false) do
@ -67,7 +67,7 @@ describe Requirement do
it { is_expected.to be_satisfied } it { is_expected.to be_satisfied }
end end
context "#satisfy with block and build_env returns false" do describe "#satisfy with block and build_env returns false" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
satisfy(build_env: false) do satisfy(build_env: false) do
@ -79,7 +79,7 @@ describe Requirement do
it { is_expected.not_to be_satisfied } it { is_expected.not_to be_satisfied }
end end
context "#satisfy returns true" do describe "#satisfy returns true" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
satisfy true satisfy true
@ -89,7 +89,7 @@ describe Requirement do
it { is_expected.to be_satisfied } it { is_expected.to be_satisfied }
end end
context "#satisfy returns false" do describe "#satisfy returns false" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
satisfy false satisfy false
@ -99,7 +99,7 @@ describe Requirement do
it { is_expected.not_to be_satisfied } it { is_expected.not_to be_satisfied }
end end
context "#satisfy with block returning true and without :build_env" do describe "#satisfy with block returning true and without :build_env" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
satisfy do satisfy do
@ -114,7 +114,7 @@ describe Requirement do
end end
end end
context "#satisfy with block returning true and :build_env set to false" do describe "#satisfy with block returning true and :build_env set to false" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
satisfy(build_env: false) do satisfy(build_env: false) do
@ -129,7 +129,7 @@ describe Requirement do
end end
end end
context "#satisfy with block returning path and without :build_env" do describe "#satisfy with block returning path and without :build_env" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do
satisfy do satisfy do
@ -153,7 +153,7 @@ describe Requirement do
it { is_expected.to be_a_build_requirement } it { is_expected.to be_a_build_requirement }
end end
context "#build omitted" do describe "#build omitted" do
it { is_expected.not_to be_a_build_requirement } it { is_expected.not_to be_a_build_requirement }
end end
end end

View File

@ -5,7 +5,7 @@ ruby_version = RbConfig::CONFIG["ruby_version"]
path = File.expand_path('..', __FILE__) path = File.expand_path('..', __FILE__)
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.5/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.6.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.6.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.11.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.12.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.5/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-5.2.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-5.2.3/lib"
@ -32,20 +32,20 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/hpricot-0.8.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/http-cookie-1.0.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/http-cookie-1.0.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-18/2.3.0/jaro_winkler-1.5.3" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-18/2.3.0/jaro_winkler-1.5.3"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/jaro_winkler-1.5.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/jaro_winkler-1.5.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-data-3.2019.0331/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-data-3.2019.0904/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-3.2.2/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-3.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-digest_auth-1.4.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-digest_auth-1.4.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-persistent-3.1.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-persistent-3.1.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mini_portile2-2.4.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mini_portile2-2.4.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-18/2.3.0/nokogiri-1.10.3" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-18/2.3.0/nokogiri-1.10.4"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/nokogiri-1.10.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/nokogiri-1.10.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ntlm-http-0.1.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ntlm-http-0.1.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/webrobots-0.1.2/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/webrobots-0.1.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mechanize-2.7.6/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mechanize-2.7.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mustache-1.1.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mustache-1.1.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.17.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.17.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-2.29.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-2.29.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.6.3.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.6.4.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-18/2.3.0/rdiscount-2.2.0.1" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-18/2.3.0/rdiscount-2.2.0.1"
@ -63,6 +63,6 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.6.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.6.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.74.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.74.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.4.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.4.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.35.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.36.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-cobertura-1.3.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-cobertura-1.3.1/lib"

View File

@ -1,72 +0,0 @@
# frozen_string_literal: true
module RuboCop
module Cop
module RSpec
# Checks for any pending or skipped examples.
#
# @example
# # bad
# describe MyClass do
# it "should be true"
# end
#
# describe MyClass do
# it "should be true" do
# pending
# end
# end
#
# describe MyClass do
# xit "should be true" do
# end
# end
#
# # good
# describe MyClass do
# end
class Pending < Cop
MSG = 'Pending spec found.'
PENDING_EXAMPLES = Examples::PENDING + Examples::SKIPPED \
+ ExampleGroups::SKIPPED
SKIPPABLE_EXAMPLES = ExampleGroups::GROUPS + Examples::EXAMPLES
SKIPPABLE_SELECTORS = SKIPPABLE_EXAMPLES.node_pattern_union
SKIP_SYMBOL = s(:sym, :skip)
PENDING_SYMBOL = s(:sym, :pending)
def_node_matcher :metadata, <<-PATTERN
{(send #{RSPEC} #{SKIPPABLE_SELECTORS} ... (hash $...))
(send #{RSPEC} #{SKIPPABLE_SELECTORS} $...)}
PATTERN
def_node_matcher :pending_block?, PENDING_EXAMPLES.send_pattern
def on_send(node)
return unless pending_block?(node) || skipped_from_metadata?(node)
add_offense(node)
end
private
def skipped_from_metadata?(node)
(metadata(node) || []).any? { |n| skip_node?(n) }
end
def skip_node?(node)
if node.respond_to?(:key)
skip_symbol?(node.key) && node.value.truthy_literal?
else
skip_symbol?(node)
end
end
def skip_symbol?(symbol_node)
[SKIP_SYMBOL, PENDING_SYMBOL].include?(symbol_node)
end
end
end
end
end

View File

@ -49,6 +49,11 @@ RSpec/BeforeAfterAll:
- spec/support/**/*.rb - spec/support/**/*.rb
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
RSpec/ContextMethod:
Description: "`context` should not be used for specifying methods."
Enabled: true
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod
RSpec/ContextWording: RSpec/ContextWording:
Description: Checks that `context` docstring starts with an allowed prefix. Description: Checks that `context` docstring starts with an allowed prefix.
Enabled: true Enabled: true
@ -95,6 +100,12 @@ RSpec/EmptyExampleGroup:
CustomIncludeMethods: [] CustomIncludeMethods: []
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup
RSpec/EmptyLineAfterExample:
Description: Checks if there is an empty line after example blocks.
Enabled: true
AllowConsecutiveOneLiners: true
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample
RSpec/EmptyLineAfterExampleGroup: RSpec/EmptyLineAfterExampleGroup:
Description: Checks if there is an empty line after example group blocks. Description: Checks if there is an empty line after example group blocks.
Enabled: true Enabled: true

View File

@ -78,6 +78,7 @@ module RuboCop
'have_no_current_path' 'have_no_current_path'
end end
corrector.replace(matcher_node.loc.selector, matcher_method) corrector.replace(matcher_node.loc.selector, matcher_method)
add_ignore_query_options(corrector, node)
end end
def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str) def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str)
@ -85,6 +86,21 @@ module RuboCop
regexp_expr = Regexp.new(regexp_str).inspect regexp_expr = Regexp.new(regexp_str).inspect
corrector.replace(str_node.loc.expression, regexp_expr) corrector.replace(str_node.loc.expression, regexp_expr)
end end
# `have_current_path` with no options will include the querystring
# while `page.current_path` does not.
# This ensures the option `ignore_query: true` is added
# except when the expectation is a regexp or string
def add_ignore_query_options(corrector, node)
expectation_node = node.parent.last_argument
expectation_last_child = expectation_node.children.last
return if %i[regexp str].include?(expectation_last_child.type)
corrector.insert_after(
expectation_last_child.loc.expression,
', ignore_query: true'
)
end
end end
end end
end end

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
module RuboCop
module Cop
module RSpec
# `context` should not be used for specifying methods.
#
# @example
# # bad
# context '#foo_bar' do
# # ...
# end
#
# context '.foo_bar' do
# # ...
# end
#
# # good
# describe '#foo_bar' do
# # ...
# end
#
# describe '.foo_bar' do
# # ...
# end
class ContextMethod < Cop
MSG = 'Use `describe` for testing methods.'
def_node_matcher :context_method, <<-PATTERN
(block (send #{RSPEC} :context $(str #method_name?) ...) ...)
PATTERN
def on_block(node)
context_method(node) do |context|
add_offense(context)
end
end
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.parent.loc.selector, 'describe')
end
end
private
def method_name?(description)
description.start_with?('.', '#')
end
end
end
end
end

View File

@ -29,17 +29,17 @@ module RuboCop
} }
PATTERN PATTERN
def_node_matcher :describe_with_metadata, <<-PATTERN def_node_matcher :describe_with_rails_metadata?, <<-PATTERN
(send #{RSPEC} :describe (send #{RSPEC} :describe !const ...
!const (hash <#rails_metadata? ...>)
... )
(hash $...))
PATTERN PATTERN
def_node_matcher :rails_metadata?, <<-PATTERN def_node_matcher :rails_metadata?, <<-PATTERN
(pair (pair
(sym :type) (sym :type)
(sym {:request :feature :system :routing :view})) (sym {:request :feature :system :routing :view})
)
PATTERN PATTERN
def_node_matcher :shared_group?, SharedGroups::ALL.block_pattern def_node_matcher :shared_group?, SharedGroups::ALL.block_pattern
@ -47,10 +47,7 @@ module RuboCop
def on_top_level_describe(node, args) def on_top_level_describe(node, args)
return if shared_group?(root_node) return if shared_group?(root_node)
return if valid_describe?(node) return if valid_describe?(node)
return if describe_with_rails_metadata?(node)
describe_with_metadata(node) do |pairs|
return if pairs.any?(&method(:rails_metadata?))
end
add_offense(args.first) add_offense(args.first)
end end

View File

@ -8,7 +8,8 @@ module RuboCop
# If the first argument of describe is a class, the class is exposed to # If the first argument of describe is a class, the class is exposed to
# each example via described_class. # each example via described_class.
# #
# This cop can be configured using the `EnforcedStyle` option # This cop can be configured using the `EnforcedStyle` and `SkipBlocks`
# options.
# #
# @example `EnforcedStyle: described_class` # @example `EnforcedStyle: described_class`
# # bad # # bad
@ -32,6 +33,27 @@ module RuboCop
# subject { MyClass.do_something } # subject { MyClass.do_something }
# end # end
# #
# There's a known caveat with rspec-rails's `controller` helper that
# runs its block in a different context, and `described_class` is not
# available to it. `SkipBlocks` option excludes detection in all
# non-RSpec related blocks.
#
# To narrow down this setting to only a specific directory, it is
# possible to use an overriding configuration file local to that
# directory.
#
# @example `SkipBlocks: true`
# # spec/controllers/.rubocop.yml
# # RSpec/DescribedClass:
# # SkipBlocks: true
#
# # acceptable
# describe MyConcern do
# controller(ApplicationController) do
# include MyConcern
# end
# end
#
class DescribedClass < Cop class DescribedClass < Cop
include ConfigurableEnforcedStyle include ConfigurableEnforcedStyle
@ -51,6 +73,10 @@ module RuboCop
(block (send _ :describe $(const ...) ...) (args) $_) (block (send _ :describe $(const ...) ...) (args) $_)
PATTERN PATTERN
def_node_search :contains_described_class?, <<-PATTERN
(send nil? :described_class)
PATTERN
def on_block(node) def on_block(node)
# In case the explicit style is used, we need to remember what's # In case the explicit style is used, we need to remember what's
# being described. # being described.
@ -119,6 +145,8 @@ module RuboCop
def offensive_described_class?(node) def offensive_described_class?(node)
return unless node.const_type? return unless node.const_type?
# E.g. `described_class::CONSTANT`
return if contains_described_class?(node)
nearest_described_class, = node.each_ancestor(:block) nearest_described_class, = node.each_ancestor(:block)
.map { |ancestor| described_constant(ancestor) }.find(&:itself) .map { |ancestor| described_constant(ancestor) }.find(&:itself)

View File

@ -0,0 +1,87 @@
# frozen_string_literal: true
module RuboCop
module Cop
module RSpec
# Checks if there is an empty line after example blocks.
#
# @example
# # bad
# RSpec.describe Foo do
# it 'does this' do
# end
# it 'does that' do
# end
# end
#
# # good
# RSpec.describe Foo do
# it 'does this' do
# end
#
# it 'does that' do
# end
# end
#
# # fair - it's ok to have non-separated one-liners
# RSpec.describe Foo do
# it { one }
# it { two }
# end
#
# @example with AllowConsecutiveOneLiners configuration
#
# # rubocop.yml
# # RSpec/EmptyLineAfterExample:
# # AllowConsecutiveOneLiners: false
#
# # bad
# RSpec.describe Foo do
# it { one }
# it { two }
# end
#
class EmptyLineAfterExample < Cop
include RuboCop::RSpec::BlankLineSeparation
MSG = 'Add an empty line after `%<example>s`.'
def on_block(node)
return unless example?(node)
return if last_child?(node)
return if allowed_one_liner?(node)
missing_separating_line(node) do |location|
add_offense(node,
location: location,
message: format(MSG, example: node.method_name))
end
end
def allowed_one_liner?(node)
consecutive_one_liner?(node) && allow_consecutive_one_liners?
end
def allow_consecutive_one_liners?
cop_config['AllowConsecutiveOneLiners']
end
def consecutive_one_liner?(node)
node.line_count == 1 && next_one_line_example?(node)
end
def next_one_line_example?(node)
next_sibling = next_sibling(node)
return unless next_sibling
return unless example?(next_sibling)
next_sibling.line_count == 1
end
def next_sibling(node)
node.parent.children[node.sibling_index + 1]
end
end
end
end
end

View File

@ -53,27 +53,30 @@ module RuboCop
end end
end end
def autocorrect(range) def autocorrect(node)
->(corrector) { corrector.replace(range, replacement_text(range)) } lambda do |corrector|
corrector.replace(docstring(node), replacement_text(node))
end
end end
private private
def add_wording_offense(node, message) def add_wording_offense(node, message)
expr = node.loc.expression add_offense(node, location: docstring(node), message: message)
docstring =
Parser::Source::Range.new(
expr.source_buffer,
expr.begin_pos + 1,
expr.end_pos - 1
)
add_offense(docstring, location: docstring, message: message)
end end
def replacement_text(range) def docstring(node)
text = range.source expr = node.loc.expression
Parser::Source::Range.new(
expr.source_buffer,
expr.begin_pos + 1,
expr.end_pos - 1
)
end
def replacement_text(node)
text = text(node)
if text =~ SHOULD_PREFIX if text =~ SHOULD_PREFIX
RuboCop::RSpec::Wording.new( RuboCop::RSpec::Wording.new(
@ -86,6 +89,19 @@ module RuboCop
end end
end end
# Recursive processing is required to process nested dstr nodes
# that is the case for \-separated multiline strings with interpolation.
def text(node)
case node.type
when :dstr
node.node_parts.map { |child_node| text(child_node) }.join
when :str
node.value
when :begin
node.source
end
end
def custom_transform def custom_transform
cop_config.fetch('CustomTransform', {}) cop_config.fetch('CustomTransform', {})
end end

View File

@ -12,22 +12,22 @@ module RuboCop
# #
# @example `EnforcedStyle: block` # @example `EnforcedStyle: block`
# # bad # # bad
# expect(run).to change(Foo, :bar) # expect { run }.to change(Foo, :bar)
# #
# # good # # good
# expect(run).to change { Foo.bar } # expect { run }.to change { Foo.bar }
# #
# @example `EnforcedStyle: method_call` # @example `EnforcedStyle: method_call`
# # bad # # bad
# expect(run).to change { Foo.bar } # expect { run }.to change { Foo.bar }
# expect(run).to change { foo.baz } # expect { run }.to change { foo.baz }
# #
# # good # # good
# expect(run).to change(Foo, :bar) # expect { run }.to change(Foo, :bar)
# expect(run).to change(foo, :baz) # expect { run }.to change(foo, :baz)
# # also good when there are arguments or chained method calls # # also good when there are arguments or chained method calls
# expect(run).to change { Foo.bar(:count) } # expect { run }.to change { Foo.bar(:count) }
# expect(run).to change { user.reload.name } # expect { run }.to change { user.reload.name }
# #
class ExpectChange < Cop class ExpectChange < Cop
include ConfigurableEnforcedStyle include ConfigurableEnforcedStyle

View File

@ -38,7 +38,7 @@ module RuboCop
def on_block(node) def on_block(node)
factory_attributes(node).to_a.flatten.each do |attribute| factory_attributes(node).to_a.flatten.each do |attribute|
next unless offensive_receiver?(attribute.receiver, node) next unless offensive_receiver?(attribute.receiver, node)
next if proc?(attribute) || association?(attribute) next if proc?(attribute) || association?(attribute.first_argument)
add_offense(attribute) add_offense(attribute)
end end
@ -72,14 +72,7 @@ module RuboCop
value_matcher(attribute).to_a.all?(&:block_pass_type?) value_matcher(attribute).to_a.all?(&:block_pass_type?)
end end
def association?(attribute) def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
argument = attribute.first_argument
argument.hash_type? && factory_key?(argument)
end
def factory_key?(hash_node)
hash_node.keys.any? { |key| key.sym_type? && key.value == :factory }
end
def autocorrect_replacing_parens(node) def autocorrect_replacing_parens(node)
left_braces, right_braces = braces(node) left_braces, right_braces = braces(node)

View File

@ -26,18 +26,16 @@ module RuboCop
ExampleGroups::GROUPS + ExampleGroups::GROUPS +
ExampleGroups::SKIPPED + ExampleGroups::SKIPPED +
Examples::EXAMPLES + Examples::EXAMPLES +
Examples::SKIPPED Examples::SKIPPED +
Examples::PENDING
focused = ExampleGroups::FOCUSED + Examples::FOCUSED focused = ExampleGroups::FOCUSED + Examples::FOCUSED
FOCUSABLE_SELECTORS = focusable.node_pattern_union FOCUSABLE_SELECTORS = focusable.node_pattern_union
FOCUS_SYMBOL = s(:sym, :focus)
FOCUS_TRUE = s(:pair, FOCUS_SYMBOL, s(:true))
def_node_matcher :metadata, <<-PATTERN def_node_matcher :metadata, <<-PATTERN
{(send #{RSPEC} #{FOCUSABLE_SELECTORS} ... (hash $...)) {(send #{RSPEC} #{FOCUSABLE_SELECTORS} <$(sym :focus) ...>)
(send #{RSPEC} #{FOCUSABLE_SELECTORS} $...)} (send #{RSPEC} #{FOCUSABLE_SELECTORS} ... (hash <$(pair (sym :focus) true) ...>))}
PATTERN PATTERN
def_node_matcher :focused_block?, focused.send_pattern def_node_matcher :focused_block?, focused.send_pattern
@ -53,10 +51,7 @@ module RuboCop
def focus_metadata(node, &block) def focus_metadata(node, &block)
yield(node) if focused_block?(node) yield(node) if focused_block?(node)
metadata(node) do |matches| metadata(node, &block)
matches.grep(FOCUS_SYMBOL, &block)
matches.grep(FOCUS_TRUE, &block)
end
end end
end end
end end

View File

@ -47,7 +47,8 @@ module RuboCop
# end # end
# #
class InstanceVariable < Cop class InstanceVariable < Cop
MSG = 'Replace instance variable with local variable or `let`.' MSG = 'Avoid instance variables use let, ' \
'a method call, or a local variable (if possible).'
EXAMPLE_GROUP_METHODS = ExampleGroups::ALL + SharedGroups::ALL EXAMPLE_GROUP_METHODS = ExampleGroups::ALL + SharedGroups::ALL

View File

@ -50,14 +50,23 @@ module RuboCop
MSG = 'Example has too many expectations [%<total>d/%<max>d].' MSG = 'Example has too many expectations [%<total>d/%<max>d].'
def_node_search :with_aggregate_failures?, '(sym :aggregate_failures)' def_node_matcher :aggregate_failures?, <<-PATTERN
def_node_search :disabled_aggregate_failures?, <<-PATTERN (block {
(pair (sym :aggregate_failures) (false)) (send _ _ <(sym :aggregate_failures) ...>)
(send _ _ ... (hash <(pair (sym :aggregate_failures) true) ...>))
} ...)
PATTERN
def_node_matcher :aggregate_failures_present?, <<-PATTERN
(block {
(send _ _ <(sym :aggregate_failures) ...>)
(send _ _ ... (hash <(pair (sym :aggregate_failures) _) ...>))
} ...)
PATTERN PATTERN
def_node_matcher :expect?, Expectations::ALL.send_pattern def_node_matcher :expect?, Expectations::ALL.send_pattern
def_node_matcher :aggregate_failures_block?, <<-PATTERN def_node_matcher :aggregate_failures_block?, <<-PATTERN
(block (send _ :aggregate_failures ...) ...) (block (send nil? :aggregate_failures ...) ...)
PATTERN PATTERN
def on_block(node) def on_block(node)
@ -88,23 +97,6 @@ module RuboCop
.find { |block_node| aggregate_failures_present?(block_node) } .find { |block_node| aggregate_failures_present?(block_node) }
end end
def aggregate_failures_present?(node)
metadata(node)&.any?(&method(:with_aggregate_failures?))
end
def aggregate_failures?(example_or_group_node)
metadata(example_or_group_node)&.any? do |metadata|
with_aggregate_failures?(metadata) &&
!disabled_aggregate_failures?(metadata)
end
end
def metadata(example_or_group_node)
RuboCop::RSpec::Example
.new(example_or_group_node)
.metadata
end
def find_expectation(node, &block) def find_expectation(node, &block)
yield if expect?(node) || aggregate_failures_block?(node) yield if expect?(node) || aggregate_failures_block?(node)

View File

@ -0,0 +1,66 @@
# frozen_string_literal: true
module RuboCop
module Cop
module RSpec
# Checks for any pending or skipped examples.
#
# @example
# # bad
# describe MyClass do
# it "should be true"
# end
#
# describe MyClass do
# it "should be true", skip: true do
# expect(1).to eq(2)
# end
# end
#
# describe MyClass do
# it "should be true" do
# pending
# end
# end
#
# describe MyClass do
# xit "should be true" do
# end
# end
#
# # good
# describe MyClass do
# end
class Pending < Cop
MSG = 'Pending spec found.'
PENDING = Examples::PENDING + Examples::SKIPPED + ExampleGroups::SKIPPED
SKIPPABLE = ExampleGroups::GROUPS + Examples::EXAMPLES
def_node_matcher :skippable?, SKIPPABLE.send_pattern
def_node_matcher :skipped_in_metadata?, <<-PATTERN
{
(send _ _ <#skip_or_pending? ...>)
(send _ _ ... (hash <(pair #skip_or_pending? true) ...>))
}
PATTERN
def_node_matcher :skip_or_pending?, '{(sym :skip) (sym :pending)}'
def_node_matcher :pending_block?, PENDING.send_pattern
def on_send(node)
return unless pending_block?(node) || skipped?(node)
add_offense(node)
end
private
def skipped?(node)
skippable?(node) && skipped_in_metadata?(node)
end
end
end
end
end

View File

@ -19,6 +19,7 @@ require_relative 'rspec/around_block'
require_relative 'rspec/be' require_relative 'rspec/be'
require_relative 'rspec/be_eql' require_relative 'rspec/be_eql'
require_relative 'rspec/before_after_all' require_relative 'rspec/before_after_all'
require_relative 'rspec/context_method'
require_relative 'rspec/context_wording' require_relative 'rspec/context_wording'
require_relative 'rspec/describe_class' require_relative 'rspec/describe_class'
require_relative 'rspec/describe_method' require_relative 'rspec/describe_method'
@ -26,6 +27,7 @@ require_relative 'rspec/describe_symbol'
require_relative 'rspec/described_class' require_relative 'rspec/described_class'
require_relative 'rspec/dialect' require_relative 'rspec/dialect'
require_relative 'rspec/empty_example_group' require_relative 'rspec/empty_example_group'
require_relative 'rspec/empty_line_after_example'
require_relative 'rspec/empty_line_after_example_group' require_relative 'rspec/empty_line_after_example_group'
require_relative 'rspec/empty_line_after_final_let' require_relative 'rspec/empty_line_after_final_let'
require_relative 'rspec/empty_line_after_hook' require_relative 'rspec/empty_line_after_hook'

Some files were not shown because too many files have changed in this diff Show More