Merge pull request #8373 from Homebrew/dependabot/bundler/Library/Homebrew/rubocop-rspec-1.43.1
build(deps): bump rubocop-rspec from 1.42.0 to 1.43.1 in /Library/Homebrew
This commit is contained in:
commit
97b57393cc
@ -43,3 +43,5 @@ RSpec/MultipleExpectations:
|
|||||||
Max: 26
|
Max: 26
|
||||||
RSpec/NestedGroups:
|
RSpec/NestedGroups:
|
||||||
Max: 5
|
Max: 5
|
||||||
|
RSpec/MultipleMemoizedHelpers:
|
||||||
|
Max: 12
|
||||||
|
|||||||
@ -112,8 +112,8 @@ GEM
|
|||||||
parser (>= 2.7.1.4)
|
parser (>= 2.7.1.4)
|
||||||
rubocop-performance (1.7.1)
|
rubocop-performance (1.7.1)
|
||||||
rubocop (>= 0.82.0)
|
rubocop (>= 0.82.0)
|
||||||
rubocop-rspec (1.42.0)
|
rubocop-rspec (1.43.1)
|
||||||
rubocop (>= 0.87.0)
|
rubocop (~> 0.87)
|
||||||
ruby-macho (2.2.0)
|
ruby-macho (2.2.0)
|
||||||
ruby-progressbar (1.10.1)
|
ruby-progressbar (1.10.1)
|
||||||
simplecov (0.19.0)
|
simplecov (0.19.0)
|
||||||
|
|||||||
@ -51,7 +51,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.19.2/lib"
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.1.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.1.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.4/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}/gems/sorbet-runtime-0.5.5866/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.5869/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.2.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.2.0/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"
|
||||||
@ -74,9 +74,9 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.88.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.88.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.7.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.7.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.42.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.43.1/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/sorbet-static-0.5.5866-universal-darwin-19/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.5869-universal-darwin-19/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5866/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5869/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.4.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.4.1/lib"
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module RSpec
|
|
||||||
# Check that the first argument to the top level describe is a constant.
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
# # bad
|
|
||||||
# describe 'Do something' do
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# describe TestedClass do
|
|
||||||
# subject { described_class }
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe 'TestedClass::VERSION' do
|
|
||||||
# subject { Object.const_get(self.class.description) }
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe "A feature example", type: :feature do
|
|
||||||
# end
|
|
||||||
class DescribeClass < Cop
|
|
||||||
include RuboCop::RSpec::TopLevelDescribe
|
|
||||||
|
|
||||||
MSG = 'The first argument to describe should be '\
|
|
||||||
'the class or module being tested.'
|
|
||||||
|
|
||||||
def_node_matcher :valid_describe?, <<-PATTERN
|
|
||||||
{
|
|
||||||
(send #{RSPEC} :describe const ...)
|
|
||||||
(send #{RSPEC} :describe)
|
|
||||||
}
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher :describe_with_rails_metadata?, <<-PATTERN
|
|
||||||
(send #{RSPEC} :describe !const ...
|
|
||||||
(hash <#rails_metadata? ...>)
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher :rails_metadata?, <<-PATTERN
|
|
||||||
(pair
|
|
||||||
(sym :type)
|
|
||||||
(sym {
|
|
||||||
:channel :controller :helper :job :mailer :model :request
|
|
||||||
:routing :view :feature :system :mailbox
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def on_top_level_describe(node, (described_value, _))
|
|
||||||
return if shared_group?(root_node)
|
|
||||||
return if valid_describe?(node)
|
|
||||||
return if describe_with_rails_metadata?(node)
|
|
||||||
return if string_constant_describe?(described_value)
|
|
||||||
|
|
||||||
add_offense(described_value)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def string_constant_describe?(described_value)
|
|
||||||
described_value.str_type? &&
|
|
||||||
described_value.value =~ /^((::)?[A-Z]\w*)+$/
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module RSpec
|
|
||||||
# Checks if an example group does not include any tests.
|
|
||||||
#
|
|
||||||
# This cop is configurable using the `CustomIncludeMethods` option
|
|
||||||
#
|
|
||||||
# @example usage
|
|
||||||
#
|
|
||||||
# # bad
|
|
||||||
# describe Bacon do
|
|
||||||
# let(:bacon) { Bacon.new(chunkiness) }
|
|
||||||
# let(:chunkiness) { false }
|
|
||||||
#
|
|
||||||
# context 'extra chunky' do # flagged by rubocop
|
|
||||||
# let(:chunkiness) { true }
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'is chunky' do
|
|
||||||
# expect(bacon.chunky?).to be_truthy
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# describe Bacon do
|
|
||||||
# let(:bacon) { Bacon.new(chunkiness) }
|
|
||||||
# let(:chunkiness) { false }
|
|
||||||
#
|
|
||||||
# it 'is chunky' do
|
|
||||||
# expect(bacon.chunky?).to be_truthy
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# @example configuration
|
|
||||||
#
|
|
||||||
# # .rubocop.yml
|
|
||||||
# # RSpec/EmptyExampleGroup:
|
|
||||||
# # CustomIncludeMethods:
|
|
||||||
# # - include_tests
|
|
||||||
#
|
|
||||||
# # spec_helper.rb
|
|
||||||
# RSpec.configure do |config|
|
|
||||||
# config.alias_it_behaves_like_to(:include_tests)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # bacon_spec.rb
|
|
||||||
# describe Bacon do
|
|
||||||
# let(:bacon) { Bacon.new(chunkiness) }
|
|
||||||
# let(:chunkiness) { false }
|
|
||||||
#
|
|
||||||
# context 'extra chunky' do # not flagged by rubocop
|
|
||||||
# let(:chunkiness) { true }
|
|
||||||
#
|
|
||||||
# include_tests 'shared tests'
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
class EmptyExampleGroup < Cop
|
|
||||||
MSG = 'Empty example group detected.'
|
|
||||||
|
|
||||||
def_node_search :contains_example?, <<-PATTERN
|
|
||||||
{
|
|
||||||
#{(Examples::ALL + Includes::ALL).send_pattern}
|
|
||||||
(send _ #custom_include? ...)
|
|
||||||
}
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def on_block(node)
|
|
||||||
return unless example_group?(node) && !contains_example?(node)
|
|
||||||
|
|
||||||
add_offense(node.send_node)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def custom_include?(method_name)
|
|
||||||
custom_include_methods.include?(method_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def custom_include_methods
|
|
||||||
cop_config
|
|
||||||
.fetch('CustomIncludeMethods', [])
|
|
||||||
.map(&:to_sym)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module RSpec
|
|
||||||
# Checks that memoized helper names use the configured style.
|
|
||||||
#
|
|
||||||
# @example EnforcedStyle: snake_case (default)
|
|
||||||
# # bad
|
|
||||||
# let(:userName) { 'Adam' }
|
|
||||||
# subject(:userName) { 'Adam' }
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# let(:user_name) { 'Adam' }
|
|
||||||
# subject(:user_name) { 'Adam' }
|
|
||||||
#
|
|
||||||
# @example EnforcedStyle: camelCase
|
|
||||||
# # bad
|
|
||||||
# let(:user_name) { 'Adam' }
|
|
||||||
# subject(:user_name) { 'Adam' }
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# let(:userName) { 'Adam' }
|
|
||||||
# subject(:userName) { 'Adam' }
|
|
||||||
class VariableName < Cop
|
|
||||||
include ConfigurableNaming
|
|
||||||
include RuboCop::RSpec::Variable
|
|
||||||
|
|
||||||
MSG = 'Use %<style>s for variable names.'
|
|
||||||
|
|
||||||
def on_send(node)
|
|
||||||
variable_definition?(node) do |variable|
|
|
||||||
return if variable.dstr_type? || variable.dsym_type?
|
|
||||||
|
|
||||||
check_name(node, variable.value, variable.loc.expression)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def message(style)
|
|
||||||
format(MSG, style: style)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module RSpec
|
|
||||||
# Helper methods for top level example group cops
|
|
||||||
module TopLevelGroup
|
|
||||||
extend RuboCop::NodePattern::Macros
|
|
||||||
include RuboCop::RSpec::Language
|
|
||||||
|
|
||||||
def_node_matcher :example_or_shared_group?,
|
|
||||||
(ExampleGroups::ALL + SharedGroups::ALL).block_pattern
|
|
||||||
|
|
||||||
def on_block(node)
|
|
||||||
return unless respond_to?(:on_top_level_group)
|
|
||||||
return unless top_level_group?(node)
|
|
||||||
|
|
||||||
on_top_level_group(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def top_level_group?(node)
|
|
||||||
top_level_groups.include?(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
def top_level_groups
|
|
||||||
@top_level_groups ||=
|
|
||||||
top_level_nodes.select { |n| example_or_shared_group?(n) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def top_level_nodes
|
|
||||||
if root_node.begin_type?
|
|
||||||
root_node.children
|
|
||||||
else
|
|
||||||
[root_node]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def root_node
|
|
||||||
processed_source.ast
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -74,7 +74,7 @@ RSpec/ContextWording:
|
|||||||
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording
|
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording
|
||||||
|
|
||||||
RSpec/DescribeClass:
|
RSpec/DescribeClass:
|
||||||
Description: Check that the first argument to the top level describe is a constant.
|
Description: Check that the first argument to the top-level describe is a constant.
|
||||||
Enabled: true
|
Enabled: true
|
||||||
VersionAdded: '1.0'
|
VersionAdded: '1.0'
|
||||||
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass
|
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass
|
||||||
@ -381,7 +381,7 @@ RSpec/MissingExampleGroupArgument:
|
|||||||
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument
|
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument
|
||||||
|
|
||||||
RSpec/MultipleDescribes:
|
RSpec/MultipleDescribes:
|
||||||
Description: Checks for multiple top level describes.
|
Description: Checks for multiple top-level example groups.
|
||||||
Enabled: true
|
Enabled: true
|
||||||
VersionAdded: '1.0'
|
VersionAdded: '1.0'
|
||||||
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes
|
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes
|
||||||
@ -394,6 +394,14 @@ RSpec/MultipleExpectations:
|
|||||||
VersionChanged: '1.21'
|
VersionChanged: '1.21'
|
||||||
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations
|
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations
|
||||||
|
|
||||||
|
RSpec/MultipleMemoizedHelpers:
|
||||||
|
Description: Checks if example groups contain too many `let` and `subject` calls.
|
||||||
|
Enabled: true
|
||||||
|
AllowSubject: true
|
||||||
|
Max: 5
|
||||||
|
VersionAdded: '1.43'
|
||||||
|
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers
|
||||||
|
|
||||||
RSpec/MultipleSubjects:
|
RSpec/MultipleSubjects:
|
||||||
Description: Checks if an example group defines `subject` multiple times.
|
Description: Checks if an example group defines `subject` multiple times.
|
||||||
Enabled: true
|
Enabled: true
|
||||||
@ -558,7 +566,9 @@ RSpec/VariableName:
|
|||||||
SupportedStyles:
|
SupportedStyles:
|
||||||
- snake_case
|
- snake_case
|
||||||
- camelCase
|
- camelCase
|
||||||
|
IgnoredPatterns: []
|
||||||
VersionAdded: '1.40'
|
VersionAdded: '1.40'
|
||||||
|
VersionChanged: '1.43'
|
||||||
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName
|
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName
|
||||||
|
|
||||||
RSpec/VerifiedDoubles:
|
RSpec/VerifiedDoubles:
|
||||||
@ -19,11 +19,12 @@ require_relative 'rubocop/rspec/example_group'
|
|||||||
require_relative 'rubocop/rspec/example'
|
require_relative 'rubocop/rspec/example'
|
||||||
require_relative 'rubocop/rspec/hook'
|
require_relative 'rubocop/rspec/hook'
|
||||||
require_relative 'rubocop/rspec/variable'
|
require_relative 'rubocop/rspec/variable'
|
||||||
|
require_relative 'rubocop/cop/rspec/base'
|
||||||
require_relative 'rubocop/cop/rspec/cop'
|
require_relative 'rubocop/cop/rspec/cop'
|
||||||
require_relative 'rubocop/rspec/align_let_brace'
|
require_relative 'rubocop/rspec/align_let_brace'
|
||||||
require_relative 'rubocop/rspec/factory_bot'
|
require_relative 'rubocop/rspec/factory_bot'
|
||||||
require_relative 'rubocop/rspec/final_end_location'
|
require_relative 'rubocop/rspec/final_end_location'
|
||||||
require_relative 'rubocop/rspec/blank_line_separation'
|
require_relative 'rubocop/rspec/empty_line_separation'
|
||||||
require_relative 'rubocop/rspec/corrector/move_node'
|
require_relative 'rubocop/rspec/corrector/move_node'
|
||||||
|
|
||||||
RuboCop::RSpec::Inject.defaults!
|
RuboCop::RSpec::Inject.defaults!
|
||||||
@ -17,7 +17,7 @@ module RuboCop
|
|||||||
# let(:baz) { bar }
|
# let(:baz) { bar }
|
||||||
# let(:a) { b }
|
# let(:a) { b }
|
||||||
#
|
#
|
||||||
class AlignLeftLetBrace < Cop
|
class AlignLeftLetBrace < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Align left let brace'
|
MSG = 'Align left let brace'
|
||||||
@ -17,7 +17,7 @@ module RuboCop
|
|||||||
# let(:baz) { bar }
|
# let(:baz) { bar }
|
||||||
# let(:a) { b }
|
# let(:a) { b }
|
||||||
#
|
#
|
||||||
class AlignRightLetBrace < Cop
|
class AlignRightLetBrace < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Align right let brace'
|
MSG = 'Align right let brace'
|
||||||
@ -22,7 +22,7 @@ module RuboCop
|
|||||||
# allow(my_instance).to receive(:foo)
|
# allow(my_instance).to receive(:foo)
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
class AnyInstance < Cop
|
class AnyInstance < Base
|
||||||
MSG = 'Avoid stubbing using `%<method>s`.'
|
MSG = 'Avoid stubbing using `%<method>s`.'
|
||||||
|
|
||||||
def_node_matcher :disallowed_stub, <<-PATTERN
|
def_node_matcher :disallowed_stub, <<-PATTERN
|
||||||
@ -25,7 +25,7 @@ module RuboCop
|
|||||||
# some_method
|
# some_method
|
||||||
# test.run
|
# test.run
|
||||||
# end
|
# end
|
||||||
class AroundBlock < Cop
|
class AroundBlock < Base
|
||||||
MSG_NO_ARG = 'Test object should be passed to around block.'
|
MSG_NO_ARG = 'Test object should be passed to around block.'
|
||||||
MSG_UNUSED_ARG = 'You should call `%<arg>s.call` '\
|
MSG_UNUSED_ARG = 'You should call `%<arg>s.call` '\
|
||||||
'or `%<arg>s.run`.'
|
'or `%<arg>s.run`.'
|
||||||
@ -17,7 +17,7 @@ module RuboCop
|
|||||||
# # Patterns:
|
# # Patterns:
|
||||||
# # - '_test.rb$'
|
# # - '_test.rb$'
|
||||||
# # - '(?:^|/)test/'
|
# # - '(?:^|/)test/'
|
||||||
class Cop < ::RuboCop::Cop::Base
|
class Base < ::RuboCop::Cop::Base
|
||||||
include RuboCop::RSpec::Language
|
include RuboCop::RSpec::Language
|
||||||
include RuboCop::RSpec::Language::NodePattern
|
include RuboCop::RSpec::Language::NodePattern
|
||||||
|
|
||||||
@ -30,8 +30,8 @@ module RuboCop
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Invoke the original inherited hook so our cops are recognized
|
# Invoke the original inherited hook so our cops are recognized
|
||||||
def self.inherited(subclass)
|
def self.inherited(subclass) # rubocop:disable Lint/MissingSuper
|
||||||
RuboCop::Cop::Cop.inherited(subclass)
|
RuboCop::Cop::Base.inherited(subclass)
|
||||||
end
|
end
|
||||||
|
|
||||||
def relevant_file?(file)
|
def relevant_file?(file)
|
||||||
@ -41,7 +41,7 @@ module RuboCop
|
|||||||
private
|
private
|
||||||
|
|
||||||
def relevant_rubocop_rspec_file?(file)
|
def relevant_rubocop_rspec_file?(file)
|
||||||
rspec_pattern =~ file
|
rspec_pattern.match?(file)
|
||||||
end
|
end
|
||||||
|
|
||||||
def rspec_pattern
|
def rspec_pattern
|
||||||
@ -19,7 +19,7 @@ module RuboCop
|
|||||||
# expect(foo).to be 1.0
|
# expect(foo).to be 1.0
|
||||||
# expect(foo).to be(true)
|
# expect(foo).to be(true)
|
||||||
#
|
#
|
||||||
class Be < Cop
|
class Be < Base
|
||||||
MSG = 'Don\'t use `be` without an argument.'
|
MSG = 'Don\'t use `be` without an argument.'
|
||||||
|
|
||||||
def_node_matcher :be_without_args, <<-PATTERN
|
def_node_matcher :be_without_args, <<-PATTERN
|
||||||
@ -35,7 +35,7 @@ module RuboCop
|
|||||||
# necessarily the same type as `b` since the `#==` operator can
|
# necessarily the same type as `b` since the `#==` operator can
|
||||||
# coerce objects for comparison.
|
# coerce objects for comparison.
|
||||||
#
|
#
|
||||||
class BeEql < Cop
|
class BeEql < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Prefer `be` over `eql`.'
|
MSG = 'Prefer `be` over `eql`.'
|
||||||
@ -23,7 +23,7 @@ module RuboCop
|
|||||||
# before(:each) { Widget.create }
|
# before(:each) { Widget.create }
|
||||||
# after(:each) { Widget.delete_all }
|
# after(:each) { Widget.delete_all }
|
||||||
# end
|
# end
|
||||||
class BeforeAfterAll < Cop
|
class BeforeAfterAll < Base
|
||||||
MSG = 'Beware of using `%<hook>s` as it may cause state to leak '\
|
MSG = 'Beware of using `%<hook>s` as it may cause state to leak '\
|
||||||
'between tests. If you are using `rspec-rails`, and '\
|
'between tests. If you are using `rspec-rails`, and '\
|
||||||
'`use_transactional_fixtures` is enabled, then records created '\
|
'`use_transactional_fixtures` is enabled, then records created '\
|
||||||
@ -23,7 +23,7 @@ module RuboCop
|
|||||||
# expect(page).to have_current_path("/callback")
|
# expect(page).to have_current_path("/callback")
|
||||||
# expect(page).to have_current_path(/widgets/)
|
# expect(page).to have_current_path(/widgets/)
|
||||||
#
|
#
|
||||||
class CurrentPathExpectation < Cop
|
class CurrentPathExpectation < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Do not set an RSpec expectation on `current_path` in ' \
|
MSG = 'Do not set an RSpec expectation on `current_path` in ' \
|
||||||
@ -40,7 +40,7 @@ module RuboCop
|
|||||||
# # ...
|
# # ...
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
class FeatureMethods < Cop
|
class FeatureMethods < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<replacement>s` instead of `%<method>s`.'
|
MSG = 'Use `%<replacement>s` instead of `%<method>s`.'
|
||||||
@ -55,15 +55,18 @@ module RuboCop
|
|||||||
feature: :describe
|
feature: :describe
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
def_node_matcher :capybara_speak,
|
||||||
|
SelectorSet.new(MAP.keys).node_pattern_union
|
||||||
|
|
||||||
def_node_matcher :spec?, <<-PATTERN
|
def_node_matcher :spec?, <<-PATTERN
|
||||||
(block
|
(block
|
||||||
(send #{RSPEC} {:describe :feature} ...)
|
(send #rspec? {:describe :feature} ...)
|
||||||
...)
|
...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_matcher :feature_method, <<-PATTERN
|
def_node_matcher :feature_method, <<-PATTERN
|
||||||
(block
|
(block
|
||||||
$(send #{RSPEC} ${#{MAP.keys.map(&:inspect).join(' ')}} ...)
|
$(send #rspec? $#capybara_speak ...)
|
||||||
...)
|
...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ module RuboCop
|
|||||||
# expect(page).to have_css('.foo', visible: :all)
|
# expect(page).to have_css('.foo', visible: :all)
|
||||||
# expect(page).to have_link('my link', visible: :hidden)
|
# expect(page).to have_link('my link', visible: :hidden)
|
||||||
#
|
#
|
||||||
class VisibilityMatcher < Cop
|
class VisibilityMatcher < Base
|
||||||
MSG_FALSE = 'Use `:all` or `:hidden` instead of `false`.'
|
MSG_FALSE = 'Use `:all` or `:hidden` instead of `false`.'
|
||||||
MSG_TRUE = 'Use `:visible` instead of `true`.'
|
MSG_TRUE = 'Use `:visible` instead of `true`.'
|
||||||
CAPYBARA_MATCHER_METHODS = %i[
|
CAPYBARA_MATCHER_METHODS = %i[
|
||||||
@ -23,13 +23,13 @@ module RuboCop
|
|||||||
# describe '.foo_bar' do
|
# describe '.foo_bar' do
|
||||||
# # ...
|
# # ...
|
||||||
# end
|
# end
|
||||||
class ContextMethod < Cop
|
class ContextMethod < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `describe` for testing methods.'
|
MSG = 'Use `describe` for testing methods.'
|
||||||
|
|
||||||
def_node_matcher :context_method, <<-PATTERN
|
def_node_matcher :context_method, <<-PATTERN
|
||||||
(block (send #{RSPEC} :context $(str #method_name?) ...) ...)
|
(block (send #rspec? :context $(str #method_name?) ...) ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
@ -34,11 +34,11 @@ module RuboCop
|
|||||||
# context 'when the display name is not present' do
|
# context 'when the display name is not present' do
|
||||||
# # ...
|
# # ...
|
||||||
# end
|
# end
|
||||||
class ContextWording < Cop
|
class ContextWording < Base
|
||||||
MSG = 'Start context description with %<prefixes>s.'
|
MSG = 'Start context description with %<prefixes>s.'
|
||||||
|
|
||||||
def_node_matcher :context_wording, <<-PATTERN
|
def_node_matcher :context_wording, <<-PATTERN
|
||||||
(block (send #{RSPEC} { :context :shared_context } $(str #bad_prefix?) ...) ...)
|
(block (send #rspec? { :context :shared_context } $(str #bad_prefix?) ...) ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
@ -51,7 +51,7 @@ module RuboCop
|
|||||||
private
|
private
|
||||||
|
|
||||||
def bad_prefix?(description)
|
def bad_prefix?(description)
|
||||||
!prefixes.include?(description.split.first)
|
!prefixes.include?(description.split(/\b/).first)
|
||||||
end
|
end
|
||||||
|
|
||||||
def joined_prefixes
|
def joined_prefixes
|
||||||
10
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-rspec-1.43.1/lib/rubocop/cop/rspec/cop.rb
vendored
Normal file
10
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-rspec-1.43.1/lib/rubocop/cop/rspec/cop.rb
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module RSpec
|
||||||
|
# @deprecated Use ::RuboCop::Cop::RSpec::Base instead
|
||||||
|
Cop = Base
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module RSpec
|
||||||
|
# Check that the first argument to the top-level describe is a constant.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# describe 'Do something' do
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# describe TestedClass do
|
||||||
|
# subject { described_class }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# describe 'TestedClass::VERSION' do
|
||||||
|
# subject { Object.const_get(self.class.description) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# describe "A feature example", type: :feature do
|
||||||
|
# end
|
||||||
|
class DescribeClass < Base
|
||||||
|
include RuboCop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
|
MSG = 'The first argument to describe should be '\
|
||||||
|
'the class or module being tested.'
|
||||||
|
|
||||||
|
def_node_matcher :rails_metadata?, <<-PATTERN
|
||||||
|
(pair
|
||||||
|
(sym :type)
|
||||||
|
(sym { :channel :controller :helper :job :mailer :model :request
|
||||||
|
:routing :view :feature :system :mailbox })
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def_node_matcher :example_group_with_rails_metadata?, <<~PATTERN
|
||||||
|
(send #rspec? :describe ... (hash <#rails_metadata? ...>))
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def_node_matcher :not_a_const_described, <<~PATTERN
|
||||||
|
(send #rspec? :describe $[!const !#string_constant?] ...)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_top_level_group(top_level_node)
|
||||||
|
return if example_group_with_rails_metadata?(top_level_node.send_node)
|
||||||
|
|
||||||
|
not_a_const_described(top_level_node.send_node) do |described|
|
||||||
|
add_offense(described)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def string_constant?(described)
|
||||||
|
described.str_type? &&
|
||||||
|
described.value.match?(/^(?:(?:::)?[A-Z]\w*)+$/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -16,17 +16,25 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# describe MyClass, '.my_class_method' do
|
# describe MyClass, '.my_class_method' do
|
||||||
# end
|
# end
|
||||||
class DescribeMethod < Cop
|
class DescribeMethod < Base
|
||||||
include RuboCop::RSpec::TopLevelDescribe
|
include RuboCop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
MSG = 'The second argument to describe should be the method '\
|
MSG = 'The second argument to describe should be the method '\
|
||||||
"being tested. '#instance' or '.class'."
|
"being tested. '#instance' or '.class'."
|
||||||
|
|
||||||
def on_top_level_describe(_node, (_, second_arg))
|
def_node_matcher :second_argument, <<~PATTERN
|
||||||
return unless second_arg&.str_type?
|
(block
|
||||||
return if second_arg.str_content.start_with?('#', '.')
|
(send #rspec? :describe _first_argument $(str _) ...) ...
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
add_offense(second_arg)
|
def on_top_level_group(node)
|
||||||
|
second_argument = second_argument(node)
|
||||||
|
|
||||||
|
return unless second_argument
|
||||||
|
return if second_argument.str_content.start_with?('#', '.')
|
||||||
|
|
||||||
|
add_offense(second_argument)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -17,11 +17,11 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# @see https://github.com/rspec/rspec-core/issues/1610
|
# @see https://github.com/rspec/rspec-core/issues/1610
|
||||||
class DescribeSymbol < Cop
|
class DescribeSymbol < Base
|
||||||
MSG = 'Avoid describing symbols.'
|
MSG = 'Avoid describing symbols.'
|
||||||
|
|
||||||
def_node_matcher :describe_symbol?, <<-PATTERN
|
def_node_matcher :describe_symbol?, <<-PATTERN
|
||||||
(send #{RSPEC} :describe $sym ...)
|
(send #rspec? :describe $sym ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
@ -54,7 +54,7 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class DescribedClass < Cop
|
class DescribedClass < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ module RuboCop
|
|||||||
if style == :described_class
|
if style == :described_class
|
||||||
offensive_described_class?(node)
|
offensive_described_class?(node)
|
||||||
else
|
else
|
||||||
node.send_type? && node.method_name == :described_class
|
node.send_type? && node.method?(:described_class)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# @see https://github.com/rubocop-hq/rubocop-rspec/issues/735
|
# @see https://github.com/rubocop-hq/rubocop-rspec/issues/735
|
||||||
class DescribedClassModuleWrapping < Cop
|
class DescribedClassModuleWrapping < Base
|
||||||
MSG = 'Avoid opening modules and defining specs within them.'
|
MSG = 'Avoid opening modules and defining specs within them.'
|
||||||
|
|
||||||
def_node_search :find_rspec_blocks,
|
def_node_search :find_rspec_blocks,
|
||||||
@ -41,7 +41,7 @@ module RuboCop
|
|||||||
# describe 'display name presence' do
|
# describe 'display name presence' do
|
||||||
# # ...
|
# # ...
|
||||||
# end
|
# end
|
||||||
class Dialect < Cop
|
class Dialect < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include MethodPreference
|
include MethodPreference
|
||||||
|
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module RSpec
|
||||||
|
# Checks if an example group does not include any tests.
|
||||||
|
#
|
||||||
|
# This cop is configurable using the `CustomIncludeMethods` option
|
||||||
|
#
|
||||||
|
# @example usage
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# describe Bacon do
|
||||||
|
# let(:bacon) { Bacon.new(chunkiness) }
|
||||||
|
# let(:chunkiness) { false }
|
||||||
|
#
|
||||||
|
# context 'extra chunky' do # flagged by rubocop
|
||||||
|
# let(:chunkiness) { true }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# it 'is chunky' do
|
||||||
|
# expect(bacon.chunky?).to be_truthy
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# describe Bacon do
|
||||||
|
# let(:bacon) { Bacon.new(chunkiness) }
|
||||||
|
# let(:chunkiness) { false }
|
||||||
|
#
|
||||||
|
# it 'is chunky' do
|
||||||
|
# expect(bacon.chunky?).to be_truthy
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @example configuration
|
||||||
|
#
|
||||||
|
# # .rubocop.yml
|
||||||
|
# # RSpec/EmptyExampleGroup:
|
||||||
|
# # CustomIncludeMethods:
|
||||||
|
# # - include_tests
|
||||||
|
#
|
||||||
|
# # spec_helper.rb
|
||||||
|
# RSpec.configure do |config|
|
||||||
|
# config.alias_it_behaves_like_to(:include_tests)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # bacon_spec.rb
|
||||||
|
# describe Bacon do
|
||||||
|
# let(:bacon) { Bacon.new(chunkiness) }
|
||||||
|
# let(:chunkiness) { false }
|
||||||
|
#
|
||||||
|
# context 'extra chunky' do # not flagged by rubocop
|
||||||
|
# let(:chunkiness) { true }
|
||||||
|
#
|
||||||
|
# include_tests 'shared tests'
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
class EmptyExampleGroup < Base
|
||||||
|
MSG = 'Empty example group detected.'
|
||||||
|
|
||||||
|
# @!method example_group_body(node)
|
||||||
|
# Match example group blocks and yield their body
|
||||||
|
#
|
||||||
|
# @example source that matches
|
||||||
|
# describe 'example group' do
|
||||||
|
# it { is_expected.to be }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @param node [RuboCop::AST::Node]
|
||||||
|
# @yield [RuboCop::AST::Node] example group body
|
||||||
|
def_node_matcher :example_group_body, <<~PATTERN
|
||||||
|
(block #{ExampleGroups::ALL.send_pattern} args $_)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method example_or_group_or_include?(node)
|
||||||
|
# Match examples, example groups and includes
|
||||||
|
#
|
||||||
|
# @example source that matches
|
||||||
|
# it { is_expected.to fly }
|
||||||
|
# describe('non-empty example groups too') { }
|
||||||
|
# it_behaves_like 'an animal'
|
||||||
|
# it_behaves_like('a cat') { let(:food) { 'milk' } }
|
||||||
|
# it_has_root_access
|
||||||
|
#
|
||||||
|
# @param node [RuboCop::AST::Node]
|
||||||
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
||||||
|
def_node_matcher :example_or_group_or_include?, <<~PATTERN
|
||||||
|
{
|
||||||
|
#{Examples::ALL.block_pattern}
|
||||||
|
#{ExampleGroups::ALL.block_pattern}
|
||||||
|
#{Includes::ALL.send_pattern}
|
||||||
|
#{Includes::ALL.block_pattern}
|
||||||
|
(send nil? #custom_include? ...)
|
||||||
|
}
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method examples_inside_block?(node)
|
||||||
|
# Match examples defined inside a block which is not a hook
|
||||||
|
#
|
||||||
|
# @example source that matches
|
||||||
|
# %w(r g b).each do |color|
|
||||||
|
# it { is_expected.to have_color(color) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @example source that does not match
|
||||||
|
# before do
|
||||||
|
# it { is_expected.to fall_into_oblivion }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @param node [RuboCop::AST::Node]
|
||||||
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
||||||
|
def_node_matcher :examples_inside_block?, <<~PATTERN
|
||||||
|
(block !#{Hooks::ALL.send_pattern} _ #examples?)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method examples_directly_or_in_block?(node)
|
||||||
|
# Match examples or examples inside blocks
|
||||||
|
#
|
||||||
|
# @example source that matches
|
||||||
|
# it { expect(drink).to be_cold }
|
||||||
|
# context('when winter') { it { expect(drink).to be_hot } }
|
||||||
|
# (1..5).each { |divisor| it { is_expected.to divide_by(divisor) } }
|
||||||
|
#
|
||||||
|
# @param node [RuboCop::AST::Node]
|
||||||
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
||||||
|
def_node_matcher :examples_directly_or_in_block?, <<~PATTERN
|
||||||
|
{
|
||||||
|
#example_or_group_or_include?
|
||||||
|
#examples_inside_block?
|
||||||
|
}
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method examples?(node)
|
||||||
|
# Matches examples defined in scopes where they could run
|
||||||
|
#
|
||||||
|
# @example source that matches
|
||||||
|
# it { expect(myself).to be_run }
|
||||||
|
# describe { it { i_run_as_well } }
|
||||||
|
#
|
||||||
|
# @example source that does not match
|
||||||
|
# before { it { whatever here wont run anyway } }
|
||||||
|
#
|
||||||
|
# @param node [RuboCop::AST::Node]
|
||||||
|
# @return [Array<RuboCop::AST::Node>] matching nodes
|
||||||
|
def_node_matcher :examples?, <<~PATTERN
|
||||||
|
{
|
||||||
|
#examples_directly_or_in_block?
|
||||||
|
(begin <#examples_directly_or_in_block? ...>)
|
||||||
|
}
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_block(node)
|
||||||
|
example_group_body(node) do |body|
|
||||||
|
add_offense(node.send_node) unless examples?(body)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def custom_include?(method_name)
|
||||||
|
custom_include_methods.include?(method_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def custom_include_methods
|
||||||
|
cop_config
|
||||||
|
.fetch('CustomIncludeMethods', [])
|
||||||
|
.map(&:to_sym)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -22,7 +22,7 @@ module RuboCop
|
|||||||
# create_feed
|
# create_feed
|
||||||
# end
|
# end
|
||||||
# after(:all) { cleanup_feed }
|
# after(:all) { cleanup_feed }
|
||||||
class EmptyHook < Cop
|
class EmptyHook < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RuboCop::Cop::RangeHelp
|
include RuboCop::Cop::RangeHelp
|
||||||
|
|
||||||
@ -41,22 +41,18 @@ module RuboCop
|
|||||||
# it { two }
|
# it { two }
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class EmptyLineAfterExample < Cop
|
class EmptyLineAfterExample < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RuboCop::RSpec::BlankLineSeparation
|
include RuboCop::RSpec::EmptyLineSeparation
|
||||||
|
|
||||||
MSG = 'Add an empty line after `%<example>s`.'
|
MSG = 'Add an empty line after `%<example>s`.'
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
return unless example?(node)
|
return unless example?(node)
|
||||||
return if last_child?(node)
|
|
||||||
return if allowed_one_liner?(node)
|
return if allowed_one_liner?(node)
|
||||||
|
|
||||||
missing_separating_line(node) do |location|
|
missing_separating_line_offense(node) do |method|
|
||||||
msg = format(MSG, example: node.method_name)
|
format(MSG, example: method)
|
||||||
add_offense(location, message: msg) do |corrector|
|
|
||||||
corrector.insert_after(location.end, "\n")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -23,21 +23,17 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class EmptyLineAfterExampleGroup < Cop
|
class EmptyLineAfterExampleGroup < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RuboCop::RSpec::BlankLineSeparation
|
include RuboCop::RSpec::EmptyLineSeparation
|
||||||
|
|
||||||
MSG = 'Add an empty line after `%<example_group>s`.'
|
MSG = 'Add an empty line after `%<example_group>s`.'
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
return unless example_group?(node)
|
return unless example_group?(node)
|
||||||
return if last_child?(node)
|
|
||||||
|
|
||||||
missing_separating_line(node) do |location|
|
missing_separating_line_offense(node) do |method|
|
||||||
msg = format(MSG, example_group: node.method_name)
|
format(MSG, example_group: method)
|
||||||
add_offense(location, message: msg) do |corrector|
|
|
||||||
corrector.insert_after(location.end, "\n")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -16,24 +16,21 @@ module RuboCop
|
|||||||
# let(:something) { other }
|
# let(:something) { other }
|
||||||
#
|
#
|
||||||
# it { does_something }
|
# it { does_something }
|
||||||
class EmptyLineAfterFinalLet < Cop
|
class EmptyLineAfterFinalLet < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RuboCop::RSpec::BlankLineSeparation
|
include RuboCop::RSpec::EmptyLineSeparation
|
||||||
|
|
||||||
MSG = 'Add an empty line after the last `let` block.'
|
MSG = 'Add an empty line after the last `%<let>s`.'
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
return unless example_group_with_body?(node)
|
return unless example_group_with_body?(node)
|
||||||
|
|
||||||
latest_let = node.body.child_nodes.select { |child| let?(child) }.last
|
final_let = node.body.child_nodes.reverse.find { |child| let?(child) }
|
||||||
|
|
||||||
return if latest_let.nil?
|
return if final_let.nil?
|
||||||
return if last_child?(latest_let)
|
|
||||||
|
|
||||||
missing_separating_line(latest_let) do |location|
|
missing_separating_line_offense(final_let) do |method|
|
||||||
add_offense(location) do |corrector|
|
format(MSG, let: method)
|
||||||
corrector.insert_after(location.end, "\n")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -33,21 +33,17 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# it { does_something }
|
# it { does_something }
|
||||||
#
|
#
|
||||||
class EmptyLineAfterHook < Cop
|
class EmptyLineAfterHook < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RuboCop::RSpec::BlankLineSeparation
|
include RuboCop::RSpec::EmptyLineSeparation
|
||||||
|
|
||||||
MSG = 'Add an empty line after `%<hook>s`.'
|
MSG = 'Add an empty line after `%<hook>s`.'
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
return unless hook?(node)
|
return unless hook?(node)
|
||||||
return if last_child?(node)
|
|
||||||
|
|
||||||
missing_separating_line(node) do |location|
|
missing_separating_line_offense(node) do |method|
|
||||||
msg = format(MSG, hook: node.method_name)
|
format(MSG, hook: method)
|
||||||
add_offense(location, message: msg) do |corrector|
|
|
||||||
corrector.insert_after(location.end, "\n")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -14,20 +14,17 @@ module RuboCop
|
|||||||
# subject(:obj) { described_class }
|
# subject(:obj) { described_class }
|
||||||
#
|
#
|
||||||
# let(:foo) { bar }
|
# let(:foo) { bar }
|
||||||
class EmptyLineAfterSubject < Cop
|
class EmptyLineAfterSubject < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RuboCop::RSpec::BlankLineSeparation
|
include RuboCop::RSpec::EmptyLineSeparation
|
||||||
|
|
||||||
MSG = 'Add empty line after `subject`.'
|
MSG = 'Add an empty line after `%<subject>s`.'
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
return unless subject?(node) && !in_spec_block?(node)
|
return unless subject?(node) && !in_spec_block?(node)
|
||||||
return if last_child?(node)
|
|
||||||
|
|
||||||
missing_separating_line(node) do |location|
|
missing_separating_line_offense(node) do |method|
|
||||||
add_offense(location) do |corrector|
|
format(MSG, subject: method)
|
||||||
corrector.insert_after(location.end, "\n")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ module RuboCop
|
|||||||
# result = service.call
|
# result = service.call
|
||||||
# expect(result).to be(true)
|
# expect(result).to be(true)
|
||||||
# end
|
# end
|
||||||
class ExampleLength < Cop
|
class ExampleLength < Base
|
||||||
include CodeLength
|
include CodeLength
|
||||||
|
|
||||||
MSG = 'Example has too many lines [%<total>d/%<max>d].'
|
MSG = 'Example has too many lines [%<total>d/%<max>d].'
|
||||||
@ -47,7 +47,7 @@ module RuboCop
|
|||||||
# result = service.call
|
# result = service.call
|
||||||
# expect(result).to be(true)
|
# expect(result).to be(true)
|
||||||
# end
|
# end
|
||||||
class ExampleWithoutDescription < Cop
|
class ExampleWithoutDescription < Base
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
MSG_DEFAULT_ARGUMENT = 'Omit the argument when you want to ' \
|
MSG_DEFAULT_ARGUMENT = 'Omit the argument when you want to ' \
|
||||||
@ -29,7 +29,7 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# it 'does things' do
|
# it 'does things' do
|
||||||
# end
|
# end
|
||||||
class ExampleWording < Cop
|
class ExampleWording < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG_SHOULD = 'Do not use should when describing your tests.'
|
MSG_SHOULD = 'Do not use should when describing your tests.'
|
||||||
@ -47,9 +47,9 @@ module RuboCop
|
|||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
it_description(node) do |description_node, message|
|
it_description(node) do |description_node, message|
|
||||||
if message =~ SHOULD_PREFIX
|
if message.match?(SHOULD_PREFIX)
|
||||||
add_wording_offense(description_node, MSG_SHOULD)
|
add_wording_offense(description_node, MSG_SHOULD)
|
||||||
elsif message =~ IT_PREFIX
|
elsif message.match?(IT_PREFIX)
|
||||||
add_wording_offense(description_node, MSG_IT)
|
add_wording_offense(description_node, MSG_IT)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -77,7 +77,7 @@ module RuboCop
|
|||||||
def replacement_text(node)
|
def replacement_text(node)
|
||||||
text = text(node)
|
text = text(node)
|
||||||
|
|
||||||
if text =~ SHOULD_PREFIX
|
if text.match?(SHOULD_PREFIX)
|
||||||
RuboCop::RSpec::Wording.new(
|
RuboCop::RSpec::Wording.new(
|
||||||
text,
|
text,
|
||||||
ignore: ignored_words,
|
ignore: ignored_words,
|
||||||
@ -16,7 +16,7 @@ module RuboCop
|
|||||||
# expect(pattern).to eq(/foo/)
|
# expect(pattern).to eq(/foo/)
|
||||||
# expect(name).to eq("John")
|
# expect(name).to eq("John")
|
||||||
#
|
#
|
||||||
class ExpectActual < Cop
|
class ExpectActual < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Provide the actual you are testing to `expect(...)`.'
|
MSG = 'Provide the actual you are testing to `expect(...)`.'
|
||||||
@ -29,7 +29,7 @@ module RuboCop
|
|||||||
# 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 < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ module RuboCop
|
|||||||
# it do
|
# it do
|
||||||
# expect(something).to eq 'foo'
|
# expect(something).to eq 'foo'
|
||||||
# end
|
# end
|
||||||
class ExpectInHook < Cop
|
class ExpectInHook < Base
|
||||||
MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
|
MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
|
||||||
|
|
||||||
def_node_search :expectation, Expectations::ALL.send_pattern
|
def_node_search :expectation, Expectations::ALL.send_pattern
|
||||||
@ -14,7 +14,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# expect { my_app.print_report }.to output('Hello World').to_stdout
|
# expect { my_app.print_report }.to output('Hello World').to_stdout
|
||||||
class ExpectOutput < Cop
|
class ExpectOutput < Base
|
||||||
MSG = 'Use `expect { ... }.to output(...).to_%<name>s` '\
|
MSG = 'Use `expect { ... }.to output(...).to_%<name>s` '\
|
||||||
'instead of mutating $%<name>s.'
|
'instead of mutating $%<name>s.'
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# count { 1 }
|
# count { 1 }
|
||||||
class AttributeDefinedStatically < Cop
|
class AttributeDefinedStatically < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use a block to declare attribute values.'
|
MSG = 'Use a block to declare attribute values.'
|
||||||
@ -39,7 +39,7 @@ module RuboCop
|
|||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
attributes = factory_attributes(node) || []
|
attributes = factory_attributes(node) || []
|
||||||
attributes = [attributes] unless attributes.is_a?(Array)
|
attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective
|
||||||
|
|
||||||
attributes.each do |attribute|
|
attributes.each do |attribute|
|
||||||
next unless offensive_receiver?(attribute.receiver, node)
|
next unless offensive_receiver?(attribute.receiver, node)
|
||||||
@ -84,7 +84,7 @@ module RuboCop
|
|||||||
def autocorrect_replacing_parens(corrector, node)
|
def autocorrect_replacing_parens(corrector, node)
|
||||||
left_braces, right_braces = braces(node)
|
left_braces, right_braces = braces(node)
|
||||||
|
|
||||||
corrector.replace(node.location.begin, ' ' + left_braces)
|
corrector.replace(node.location.begin, " #{left_braces}")
|
||||||
corrector.replace(node.location.end, right_braces)
|
corrector.replace(node.location.end, right_braces)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# 3.times { create :user }
|
# 3.times { create :user }
|
||||||
class CreateList < Cop
|
class CreateList < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ module RuboCop
|
|||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_matcher :factory_list_call, <<-PATTERN
|
def_node_matcher :factory_list_call, <<-PATTERN
|
||||||
(send ${(const nil? {:FactoryGirl :FactoryBot}) nil?} :create_list (sym $_) (int $_) $...)
|
(send {(const nil? {:FactoryGirl :FactoryBot}) nil?} :create_list (sym _) (int $_) ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
@ -60,7 +60,7 @@ module RuboCop
|
|||||||
def on_send(node)
|
def on_send(node)
|
||||||
return unless style == :n_times
|
return unless style == :n_times
|
||||||
|
|
||||||
factory_list_call(node) do |_receiver, _factory, count, _|
|
factory_list_call(node) do |count|
|
||||||
message = format(MSG_N_TIMES, number: count)
|
message = format(MSG_N_TIMES, number: count)
|
||||||
add_offense(node.loc.selector, message: message) do |corrector|
|
add_offense(node.loc.selector, message: message) do |corrector|
|
||||||
TimesCorrector.new(node).call(corrector)
|
TimesCorrector.new(node).call(corrector)
|
||||||
@ -79,7 +79,7 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
# :nodoc
|
# :nodoc
|
||||||
class Corrector
|
module Corrector
|
||||||
private
|
private
|
||||||
|
|
||||||
def build_options_string(options)
|
def build_options_string(options)
|
||||||
@ -102,7 +102,9 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
# :nodoc
|
# :nodoc
|
||||||
class TimesCorrector < Corrector
|
class TimesCorrector
|
||||||
|
include Corrector
|
||||||
|
|
||||||
def initialize(node)
|
def initialize(node)
|
||||||
@node = node
|
@node = node
|
||||||
end
|
end
|
||||||
@ -130,7 +132,9 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
# :nodoc:
|
# :nodoc:
|
||||||
class CreateListCorrector < Corrector
|
class CreateListCorrector
|
||||||
|
include Corrector
|
||||||
|
|
||||||
def initialize(node)
|
def initialize(node)
|
||||||
@node = node.parent
|
@node = node.parent
|
||||||
end
|
end
|
||||||
@ -19,7 +19,7 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# factory :foo, class: 'Foo' do
|
# factory :foo, class: 'Foo' do
|
||||||
# end
|
# end
|
||||||
class FactoryClassName < Cop
|
class FactoryClassName < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
|
MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
|
||||||
@ -56,35 +56,43 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# my_class_spec.rb # describe MyClass, '#method'
|
# my_class_spec.rb # describe MyClass, '#method'
|
||||||
#
|
#
|
||||||
class FilePath < Cop
|
class FilePath < Base
|
||||||
include RuboCop::RSpec::TopLevelDescribe
|
include RuboCop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
MSG = 'Spec path should end with `%<suffix>s`.'
|
MSG = 'Spec path should end with `%<suffix>s`.'
|
||||||
|
|
||||||
def_node_search :const_described?, '(send _ :describe (const ...) ...)'
|
def_node_matcher :const_described, <<~PATTERN
|
||||||
|
(block
|
||||||
|
$(send #rspec? _example_group $(const ...) $...) ...
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))'
|
def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))'
|
||||||
|
|
||||||
def on_top_level_describe(node, args)
|
def on_top_level_group(node)
|
||||||
return unless const_described?(node) && single_top_level_describe?
|
return unless top_level_groups.one?
|
||||||
return if routing_spec?(args)
|
|
||||||
|
|
||||||
glob = glob_for(args)
|
const_described(node) do |send_node, described_class, arguments|
|
||||||
|
next if routing_spec?(arguments)
|
||||||
|
|
||||||
return if filename_ends_with?(glob)
|
ensure_correct_file_path(send_node, described_class, arguments)
|
||||||
|
end
|
||||||
add_offense(
|
|
||||||
node,
|
|
||||||
message: format(MSG, suffix: glob)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def ensure_correct_file_path(send_node, described_class, arguments)
|
||||||
|
glob = glob_for(described_class, arguments.first)
|
||||||
|
return if filename_ends_with?(glob)
|
||||||
|
|
||||||
|
add_offense(send_node, message: format(MSG, suffix: glob))
|
||||||
|
end
|
||||||
|
|
||||||
def routing_spec?(args)
|
def routing_spec?(args)
|
||||||
args.any?(&method(:routing_metadata?))
|
args.any?(&method(:routing_metadata?))
|
||||||
end
|
end
|
||||||
|
|
||||||
def glob_for((described_class, method_name))
|
def glob_for(described_class, method_name)
|
||||||
return glob_for_spec_suffix_only? if spec_suffix_only?
|
return glob_for_spec_suffix_only? if spec_suffix_only?
|
||||||
|
|
||||||
"#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
|
"#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
|
||||||
@ -94,10 +102,10 @@ module RuboCop
|
|||||||
'*_spec.rb'
|
'*_spec.rb'
|
||||||
end
|
end
|
||||||
|
|
||||||
def name_glob(name)
|
def name_glob(method_name)
|
||||||
return unless name&.str_type?
|
return unless method_name&.str_type?
|
||||||
|
|
||||||
"*#{name.str_content.gsub(/\W/, '')}" unless ignore_methods?
|
"*#{method_name.str_content.gsub(/\W/, '')}" unless ignore_methods?
|
||||||
end
|
end
|
||||||
|
|
||||||
def expected_path(constant)
|
def expected_path(constant)
|
||||||
@ -19,23 +19,19 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# describe MyClass do
|
# describe MyClass do
|
||||||
# end
|
# end
|
||||||
class Focus < Cop
|
class Focus < Base
|
||||||
MSG = 'Focused spec found.'
|
MSG = 'Focused spec found.'
|
||||||
|
|
||||||
focusable =
|
|
||||||
ExampleGroups::GROUPS +
|
|
||||||
ExampleGroups::SKIPPED +
|
|
||||||
Examples::EXAMPLES +
|
|
||||||
Examples::SKIPPED +
|
|
||||||
Examples::PENDING
|
|
||||||
|
|
||||||
focused = ExampleGroups::FOCUSED + Examples::FOCUSED
|
focused = ExampleGroups::FOCUSED + Examples::FOCUSED
|
||||||
|
|
||||||
FOCUSABLE_SELECTORS = focusable.node_pattern_union
|
def_node_matcher :focusable_selector?,
|
||||||
|
(ExampleGroups::GROUPS + ExampleGroups::SKIPPED +
|
||||||
|
Examples::EXAMPLES + Examples::SKIPPED +
|
||||||
|
Examples::PENDING).node_pattern_union
|
||||||
|
|
||||||
def_node_matcher :metadata, <<-PATTERN
|
def_node_matcher :metadata, <<-PATTERN
|
||||||
{(send #{RSPEC} #{FOCUSABLE_SELECTORS} <$(sym :focus) ...>)
|
{(send #rspec? #focusable_selector? <$(sym :focus) ...>)
|
||||||
(send #{RSPEC} #{FOCUSABLE_SELECTORS} ... (hash <$(pair (sym :focus) true) ...>))}
|
(send #rspec? #focusable_selector? ... (hash <$(pair (sym :focus) true) ...>))}
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_matcher :focused_block?, focused.send_pattern
|
def_node_matcher :focused_block?, focused.send_pattern
|
||||||
@ -57,21 +57,20 @@ module RuboCop
|
|||||||
# before(:example) do
|
# before(:example) do
|
||||||
# # ...
|
# # ...
|
||||||
# end
|
# end
|
||||||
class HookArgument < Cop
|
class HookArgument < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
IMPLICIT_MSG = 'Omit the default `%<scope>p` ' \
|
IMPLICIT_MSG = 'Omit the default `%<scope>p` argument for RSpec hooks.'
|
||||||
'argument for RSpec hooks.'
|
|
||||||
EXPLICIT_MSG = 'Use `%<scope>p` for RSpec hooks.'
|
EXPLICIT_MSG = 'Use `%<scope>p` for RSpec hooks.'
|
||||||
|
|
||||||
HOOKS = Hooks::ALL.node_pattern_union.freeze
|
def_node_matcher :hook?, Hooks::ALL.node_pattern_union
|
||||||
|
|
||||||
def_node_matcher :scoped_hook, <<-PATTERN
|
def_node_matcher :scoped_hook, <<-PATTERN
|
||||||
(block $(send _ #{HOOKS} (sym ${:each :example})) ...)
|
(block $(send _ #hook? (sym ${:each :example})) ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_matcher :unscoped_hook, "(block $(send _ #{HOOKS}) ...)"
|
def_node_matcher :unscoped_hook, '(block $(send _ #hook?) ...)'
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
hook(node) do |method_send, scope_name|
|
hook(node) do |method_send, scope_name|
|
||||||
@ -23,7 +23,7 @@ module RuboCop
|
|||||||
# expect(foo).to be
|
# expect(foo).to be
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class HooksBeforeExamples < Cop
|
class HooksBeforeExamples < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Move `%<hook>s` above the examples in the group.'
|
MSG = 'Move `%<hook>s` above the examples in the group.'
|
||||||
@ -16,7 +16,7 @@ module RuboCop
|
|||||||
# it 'changes something to a new value' do
|
# it 'changes something to a new value' do
|
||||||
# expect { do_something }.to change(something).to(new_value)
|
# expect { do_something }.to change(something).to(new_value)
|
||||||
# end
|
# end
|
||||||
class ImplicitBlockExpectation < Cop
|
class ImplicitBlockExpectation < Base
|
||||||
MSG = 'Avoid implicit block expectations.'
|
MSG = 'Avoid implicit block expectations.'
|
||||||
|
|
||||||
def_node_matcher :lambda?, <<-PATTERN
|
def_node_matcher :lambda?, <<-PATTERN
|
||||||
@ -24,7 +24,7 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# it { should be_truthy }
|
# it { should be_truthy }
|
||||||
#
|
#
|
||||||
class ImplicitExpect < Cop
|
class ImplicitExpect < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# it { expect(subject).to be_truthy }
|
# it { expect(subject).to be_truthy }
|
||||||
#
|
#
|
||||||
class ImplicitSubject < Cop
|
class ImplicitSubject < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -49,9 +49,10 @@ module RuboCop
|
|||||||
|
|
||||||
def autocorrect(corrector, node)
|
def autocorrect(corrector, node)
|
||||||
replacement = 'expect(subject)'
|
replacement = 'expect(subject)'
|
||||||
if node.method_name == :should
|
case node.method_name
|
||||||
|
when :should
|
||||||
replacement += '.to'
|
replacement += '.to'
|
||||||
elsif node.method_name == :should_not
|
when :should_not
|
||||||
replacement += '.not_to'
|
replacement += '.not_to'
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -62,13 +63,14 @@ module RuboCop
|
|||||||
example = node.ancestors.find { |parent| example?(parent) }
|
example = node.ancestors.find { |parent| example?(parent) }
|
||||||
return false if example.nil?
|
return false if example.nil?
|
||||||
|
|
||||||
example.method_name == :its || allowed_by_style?(example)
|
example.method?(:its) || allowed_by_style?(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_by_style?(example)
|
def allowed_by_style?(example)
|
||||||
if style == :single_line_only
|
case style
|
||||||
|
when :single_line_only
|
||||||
example.single_line?
|
example.single_line?
|
||||||
elsif style == :single_statement_only
|
when :single_statement_only
|
||||||
!example.body.begin_type?
|
!example.body.begin_type?
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
@ -18,7 +18,7 @@ module RuboCop
|
|||||||
# expect(foo).to have_received(:bar)
|
# expect(foo).to have_received(:bar)
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class InstanceSpy < Cop
|
class InstanceSpy < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `instance_spy` when you check your double '\
|
MSG = 'Use `instance_spy` when you check your double '\
|
||||||
@ -46,7 +46,7 @@ module RuboCop
|
|||||||
# it { expect(foo).to be_empty }
|
# it { expect(foo).to be_empty }
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class InstanceVariable < Cop
|
class InstanceVariable < Base
|
||||||
include RuboCop::RSpec::TopLevelGroup
|
include RuboCop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
MSG = 'Avoid instance variables – use let, ' \
|
MSG = 'Avoid instance variables – use let, ' \
|
||||||
@ -15,7 +15,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# expect(foo).to be_something
|
# expect(foo).to be_something
|
||||||
class InvalidPredicateMatcher < Cop
|
class InvalidPredicateMatcher < Base
|
||||||
MSG = 'Omit `?` from `%<matcher>s`.'
|
MSG = 'Omit `?` from `%<matcher>s`.'
|
||||||
|
|
||||||
def_node_matcher :invalid_predicate_matcher?, <<-PATTERN
|
def_node_matcher :invalid_predicate_matcher?, <<-PATTERN
|
||||||
@ -18,7 +18,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# it_should_behave_like 'a foo'
|
# it_should_behave_like 'a foo'
|
||||||
class ItBehavesLike < Cop
|
class ItBehavesLike < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ module RuboCop
|
|||||||
# it 'validates users' do
|
# it 'validates users' do
|
||||||
# expect([user1, user2, user3]).to all(be_valid)
|
# expect([user1, user2, user3]).to all(be_valid)
|
||||||
# end
|
# end
|
||||||
class IteratedExpectation < Cop
|
class IteratedExpectation < Base
|
||||||
MSG = 'Prefer using the `all` matcher instead ' \
|
MSG = 'Prefer using the `all` matcher instead ' \
|
||||||
'of iterating over an array.'
|
'of iterating over an array.'
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ module RuboCop
|
|||||||
# it { expect_something }
|
# it { expect_something }
|
||||||
# it { expect_something_else }
|
# it { expect_something_else }
|
||||||
#
|
#
|
||||||
class LeadingSubject < Cop
|
class LeadingSubject < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Declare `subject` above any other `%<offending>s` declarations.'
|
MSG = 'Declare `subject` above any other `%<offending>s` declarations.'
|
||||||
@ -43,33 +43,36 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_previous_nodes(node)
|
def check_previous_nodes(node)
|
||||||
node.parent.each_child_node do |sibling|
|
offending_node(node) do |offender|
|
||||||
if offending?(sibling)
|
msg = format(MSG, offending: offender.method_name)
|
||||||
msg = format(MSG, offending: sibling.method_name)
|
add_offense(node, message: msg) do |corrector|
|
||||||
add_offense(node, message: msg) do |corrector|
|
autocorrect(corrector, node, offender)
|
||||||
autocorrect(corrector, node)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
break if offending?(sibling) || sibling.equal?(node)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def autocorrect(corrector, node)
|
def offending_node(node)
|
||||||
first_node = find_first_offending_node(node)
|
node.parent.each_child_node.find do |sibling|
|
||||||
|
break if sibling.equal?(node)
|
||||||
|
|
||||||
|
yield sibling if offending?(sibling)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocorrect(corrector, node, sibling)
|
||||||
RuboCop::RSpec::Corrector::MoveNode.new(
|
RuboCop::RSpec::Corrector::MoveNode.new(
|
||||||
node, corrector, processed_source
|
node, corrector, processed_source
|
||||||
).move_before(first_node)
|
).move_before(sibling)
|
||||||
end
|
end
|
||||||
|
|
||||||
def offending?(node)
|
def offending?(node)
|
||||||
let?(node) || hook?(node) || example?(node)
|
let?(node) ||
|
||||||
end
|
hook?(node) ||
|
||||||
|
example?(node) ||
|
||||||
def find_first_offending_node(node)
|
spec_group?(node) ||
|
||||||
node.parent.children.find { |sibling| offending?(sibling) }
|
include?(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
def in_spec_block?(node)
|
def in_spec_block?(node)
|
||||||
@ -93,7 +93,7 @@ module RuboCop
|
|||||||
# stub_const('SomeModule::SomeClass', foo_class)
|
# stub_const('SomeModule::SomeClass', foo_class)
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
class LeakyConstantDeclaration < Cop
|
class LeakyConstantDeclaration < Base
|
||||||
MSG_CONST = 'Stub constant instead of declaring explicitly.'
|
MSG_CONST = 'Stub constant instead of declaring explicitly.'
|
||||||
MSG_CLASS = 'Stub class constant instead of declaring explicitly.'
|
MSG_CLASS = 'Stub class constant instead of declaring explicitly.'
|
||||||
MSG_MODULE = 'Stub module constant instead of declaring explicitly.'
|
MSG_MODULE = 'Stub module constant instead of declaring explicitly.'
|
||||||
@ -30,7 +30,7 @@ module RuboCop
|
|||||||
# it 'checks what some does' do
|
# it 'checks what some does' do
|
||||||
# expect(some).to be
|
# expect(some).to be
|
||||||
# end
|
# end
|
||||||
class LetBeforeExamples < Cop
|
class LetBeforeExamples < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Move `let` before the examples in the group.'
|
MSG = 'Move `let` before the examples in the group.'
|
||||||
@ -25,7 +25,7 @@ module RuboCop
|
|||||||
# it 'counts widgets' do
|
# it 'counts widgets' do
|
||||||
# expect(Widget.count).to eq(1)
|
# expect(Widget.count).to eq(1)
|
||||||
# end
|
# end
|
||||||
class LetSetup < Cop
|
class LetSetup < Base
|
||||||
MSG = 'Do not use `let!` to setup objects not referenced in tests.'
|
MSG = 'Do not use `let!` to setup objects not referenced in tests.'
|
||||||
|
|
||||||
def_node_matcher :example_or_shared_group_or_including?,
|
def_node_matcher :example_or_shared_group_or_including?,
|
||||||
@ -35,7 +35,10 @@ module RuboCop
|
|||||||
).block_pattern
|
).block_pattern
|
||||||
|
|
||||||
def_node_matcher :let_bang, <<-PATTERN
|
def_node_matcher :let_bang, <<-PATTERN
|
||||||
(block $(send nil? :let! (sym $_)) args ...)
|
{
|
||||||
|
(block $(send nil? :let! {(sym $_) (str $_)}) ...)
|
||||||
|
$(send nil? :let! {(sym $_) (str $_)} block_pass)
|
||||||
|
}
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_search :method_called?, '(send nil? %)'
|
def_node_search :method_called?, '(send nil? %)'
|
||||||
@ -52,7 +55,7 @@ module RuboCop
|
|||||||
|
|
||||||
def unused_let_bang(node)
|
def unused_let_bang(node)
|
||||||
child_let_bang(node) do |method_send, method_name|
|
child_let_bang(node) do |method_send, method_name|
|
||||||
yield(method_send) unless method_called?(node, method_name)
|
yield(method_send) unless method_called?(node, method_name.to_sym)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ module RuboCop
|
|||||||
# thing = Thing.new(baz: 42)
|
# thing = Thing.new(baz: 42)
|
||||||
# allow(foo).to receive(:bar).and_return(thing)
|
# allow(foo).to receive(:bar).and_return(thing)
|
||||||
#
|
#
|
||||||
class MessageChain < Cop
|
class MessageChain < Base
|
||||||
MSG = 'Avoid stubbing using `%<method>s`.'
|
MSG = 'Avoid stubbing using `%<method>s`.'
|
||||||
|
|
||||||
def_node_matcher :message_chain, <<-PATTERN
|
def_node_matcher :message_chain, <<-PATTERN
|
||||||
@ -24,7 +24,7 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# expect(foo).to receive(:bar)
|
# expect(foo).to receive(:bar)
|
||||||
#
|
#
|
||||||
class MessageExpectation < Cop
|
class MessageExpectation < Base
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
MSG = 'Prefer `%<style>s` for setting message expectations.'
|
MSG = 'Prefer `%<style>s` for setting message expectations.'
|
||||||
@ -24,7 +24,7 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# expect(foo).to receive(:bar)
|
# expect(foo).to receive(:bar)
|
||||||
#
|
#
|
||||||
class MessageSpies < Cop
|
class MessageSpies < Base
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
MSG_RECEIVE = 'Prefer `receive` for setting message expectations.'
|
MSG_RECEIVE = 'Prefer `receive` for setting message expectations.'
|
||||||
@ -19,7 +19,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# describe "A feature example" do
|
# describe "A feature example" do
|
||||||
# end
|
# end
|
||||||
class MissingExampleGroupArgument < Cop
|
class MissingExampleGroupArgument < Base
|
||||||
MSG = 'The first argument to `%<method>s` should not be empty.'
|
MSG = 'The first argument to `%<method>s` should not be empty.'
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
@ -3,7 +3,7 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module RSpec
|
module RSpec
|
||||||
# Checks for multiple top level describes.
|
# Checks for multiple top-level example groups.
|
||||||
#
|
#
|
||||||
# Multiple descriptions for the same class or module should either
|
# Multiple descriptions for the same class or module should either
|
||||||
# be nested or separated into different test files.
|
# be nested or separated into different test files.
|
||||||
@ -22,17 +22,20 @@ module RuboCop
|
|||||||
# describe '.do_something_else' do
|
# describe '.do_something_else' do
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
class MultipleDescribes < Cop
|
class MultipleDescribes < Base
|
||||||
include RuboCop::RSpec::TopLevelDescribe
|
include RuboCop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
MSG = 'Do not use multiple top level describes - '\
|
MSG = 'Do not use multiple top-level example groups - '\
|
||||||
'try to nest them.'
|
'try to nest them.'
|
||||||
|
|
||||||
def on_top_level_describe(node, _args)
|
def on_top_level_group(node)
|
||||||
return if single_top_level_describe?
|
top_level_example_groups =
|
||||||
return unless top_level_nodes.first.equal?(node)
|
top_level_groups.select(&method(:example_group?))
|
||||||
|
|
||||||
add_offense(node)
|
return if top_level_example_groups.one?
|
||||||
|
return unless top_level_example_groups.first.equal?(node)
|
||||||
|
|
||||||
|
add_offense(node.send_node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -45,22 +45,18 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class MultipleExpectations < Cop
|
class MultipleExpectations < Base
|
||||||
include ConfigurableMax
|
include ConfigurableMax
|
||||||
|
|
||||||
MSG = 'Example has too many expectations [%<total>d/%<max>d].'
|
MSG = 'Example has too many expectations [%<total>d/%<max>d].'
|
||||||
|
|
||||||
|
ANYTHING = ->(_node) { true }
|
||||||
|
TRUE = ->(node) { node.true_type? }
|
||||||
|
|
||||||
def_node_matcher :aggregate_failures?, <<-PATTERN
|
def_node_matcher :aggregate_failures?, <<-PATTERN
|
||||||
(block {
|
(block {
|
||||||
(send _ _ <(sym :aggregate_failures) ...>)
|
(send _ _ <(sym :aggregate_failures) ...>)
|
||||||
(send _ _ ... (hash <(pair (sym :aggregate_failures) true) ...>))
|
(send _ _ ... (hash <(pair (sym :aggregate_failures) %1) ...>))
|
||||||
} ...)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher :aggregate_failures_present?, <<-PATTERN
|
|
||||||
(block {
|
|
||||||
(send _ _ <(sym :aggregate_failures) ...>)
|
|
||||||
(send _ _ ... (hash <(pair (sym :aggregate_failures) _) ...>))
|
|
||||||
} ...)
|
} ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
@ -89,12 +85,12 @@ module RuboCop
|
|||||||
node_with_aggregate_failures = find_aggregate_failures(example_node)
|
node_with_aggregate_failures = find_aggregate_failures(example_node)
|
||||||
return false unless node_with_aggregate_failures
|
return false unless node_with_aggregate_failures
|
||||||
|
|
||||||
aggregate_failures?(node_with_aggregate_failures)
|
aggregate_failures?(node_with_aggregate_failures, TRUE)
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_aggregate_failures(example_node)
|
def find_aggregate_failures(example_node)
|
||||||
example_node.send_node.each_ancestor(:block)
|
example_node.send_node.each_ancestor(:block)
|
||||||
.find { |block_node| aggregate_failures_present?(block_node) }
|
.find { |block_node| aggregate_failures?(block_node, ANYTHING) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_expectation(node, &block)
|
def find_expectation(node, &block)
|
||||||
@ -0,0 +1,148 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module RSpec
|
||||||
|
# Checks if example groups contain too many `let` and `subject` calls.
|
||||||
|
#
|
||||||
|
# This cop is configurable using the `Max` option and the `AllowSubject`
|
||||||
|
# which will configure the cop to only register offenses on calls to
|
||||||
|
# `let` and not calls to `subject`.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# describe MyClass do
|
||||||
|
# let(:foo) { [] }
|
||||||
|
# let(:bar) { [] }
|
||||||
|
# let!(:baz) { [] }
|
||||||
|
# let(:qux) { [] }
|
||||||
|
# let(:quux) { [] }
|
||||||
|
# let(:quuz) { {} }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# describe MyClass do
|
||||||
|
# let(:foo) { [] }
|
||||||
|
# let(:bar) { [] }
|
||||||
|
# let!(:baz) { [] }
|
||||||
|
#
|
||||||
|
# context 'when stuff' do
|
||||||
|
# let(:qux) { [] }
|
||||||
|
# let(:quux) { [] }
|
||||||
|
# let(:quuz) { {} }
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# describe MyClass do
|
||||||
|
# let(:bar) { [] }
|
||||||
|
# let!(:baz) { [] }
|
||||||
|
# let(:qux) { [] }
|
||||||
|
# let(:quux) { [] }
|
||||||
|
# let(:quuz) { {} }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# describe MyClass do
|
||||||
|
# context 'when stuff' do
|
||||||
|
# let(:foo) { [] }
|
||||||
|
# let(:bar) { [] }
|
||||||
|
# let!(:booger) { [] }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# context 'when other stuff' do
|
||||||
|
# let(:qux) { [] }
|
||||||
|
# let(:quux) { [] }
|
||||||
|
# let(:quuz) { {} }
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @example when disabling AllowSubject configuration
|
||||||
|
#
|
||||||
|
# # rubocop.yml
|
||||||
|
# # RSpec/MultipleMemoizedHelpers:
|
||||||
|
# # AllowSubject: false
|
||||||
|
#
|
||||||
|
# # bad - `subject` counts towards memoized helpers
|
||||||
|
# describe MyClass do
|
||||||
|
# subject { {} }
|
||||||
|
# let(:foo) { [] }
|
||||||
|
# let(:bar) { [] }
|
||||||
|
# let!(:baz) { [] }
|
||||||
|
# let(:qux) { [] }
|
||||||
|
# let(:quux) { [] }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @example with Max configuration
|
||||||
|
#
|
||||||
|
# # rubocop.yml
|
||||||
|
# # RSpec/MultipleMemoizedHelpers:
|
||||||
|
# # Max: 1
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# describe MyClass do
|
||||||
|
# let(:foo) { [] }
|
||||||
|
# let(:bar) { [] }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
class MultipleMemoizedHelpers < Base
|
||||||
|
include ConfigurableMax
|
||||||
|
include RuboCop::RSpec::Variable
|
||||||
|
|
||||||
|
MSG = 'Example group has too many memoized helpers [%<count>d/%<max>d]'
|
||||||
|
|
||||||
|
def on_block(node)
|
||||||
|
return unless spec_group?(node)
|
||||||
|
|
||||||
|
count = all_helpers(node).uniq.count
|
||||||
|
|
||||||
|
return if count <= max
|
||||||
|
|
||||||
|
self.max = count
|
||||||
|
add_offense(node, message: format(MSG, count: count, max: max))
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_new_investigation
|
||||||
|
@example_group_memoized_helpers = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
attr_reader :example_group_memoized_helpers
|
||||||
|
|
||||||
|
def all_helpers(node)
|
||||||
|
[
|
||||||
|
*helpers(node),
|
||||||
|
*node.each_ancestor(:block).flat_map(&method(:helpers))
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def helpers(node)
|
||||||
|
@example_group_memoized_helpers[node] ||=
|
||||||
|
variable_nodes(node).map do |variable_node|
|
||||||
|
if variable_node.block_type?
|
||||||
|
variable_definition?(variable_node.send_node)
|
||||||
|
else # block-pass (`let(:foo, &bar)`)
|
||||||
|
variable_definition?(variable_node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def variable_nodes(node)
|
||||||
|
example_group = RuboCop::RSpec::ExampleGroup.new(node)
|
||||||
|
if allow_subject?
|
||||||
|
example_group.lets
|
||||||
|
else
|
||||||
|
example_group.lets + example_group.subjects
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def max
|
||||||
|
cop_config['Max']
|
||||||
|
end
|
||||||
|
|
||||||
|
def allow_subject?
|
||||||
|
cop_config['AllowSubject']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -33,7 +33,7 @@ module RuboCop
|
|||||||
# - If subjects are defined with `subject!` then we don't autocorrect.
|
# - If subjects are defined with `subject!` then we don't autocorrect.
|
||||||
# This is enough of an edge case that people can just move this to
|
# This is enough of an edge case that people can just move this to
|
||||||
# a `before` hook on their own
|
# a `before` hook on their own
|
||||||
class MultipleSubjects < Cop
|
class MultipleSubjects < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RangeHelp
|
include RangeHelp
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# it { is_expected.to be_valid }
|
# it { is_expected.to be_valid }
|
||||||
# end
|
# end
|
||||||
class NamedSubject < Cop
|
class NamedSubject < Base
|
||||||
MSG = 'Name your test subject if you need '\
|
MSG = 'Name your test subject if you need '\
|
||||||
'to reference it explicitly.'
|
'to reference it explicitly.'
|
||||||
|
|
||||||
@ -85,9 +85,9 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class NestedGroups < Cop
|
class NestedGroups < Base
|
||||||
include ConfigurableMax
|
include ConfigurableMax
|
||||||
include RuboCop::RSpec::TopLevelDescribe
|
include RuboCop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
MSG = 'Maximum example group nesting exceeded [%<total>d/%<max>d].'
|
MSG = 'Maximum example group nesting exceeded [%<total>d/%<max>d].'
|
||||||
|
|
||||||
@ -97,8 +97,8 @@ module RuboCop
|
|||||||
"Configuration key `#{DEPRECATED_MAX_KEY}` for #{cop_name} is " \
|
"Configuration key `#{DEPRECATED_MAX_KEY}` for #{cop_name} is " \
|
||||||
'deprecated in favor of `Max`. Please use that instead.'
|
'deprecated in favor of `Max`. Please use that instead.'
|
||||||
|
|
||||||
def on_top_level_describe(node, _args)
|
def on_top_level_group(node)
|
||||||
find_nested_example_groups(node.parent) do |example_group, nesting|
|
find_nested_example_groups(node) do |example_group, nesting|
|
||||||
self.max = nesting
|
self.max = nesting
|
||||||
add_offense(
|
add_offense(
|
||||||
example_group.send_node,
|
example_group.send_node,
|
||||||
@ -15,7 +15,7 @@ module RuboCop
|
|||||||
# it '...' do
|
# it '...' do
|
||||||
# expect(false).not_to be_true
|
# expect(false).not_to be_true
|
||||||
# end
|
# end
|
||||||
class NotToNot < Cop
|
class NotToNot < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ module RuboCop
|
|||||||
# let(:foo) { bar }
|
# let(:foo) { bar }
|
||||||
# let(:baz) { baz }
|
# let(:baz) { baz }
|
||||||
# let!(:other) { other }
|
# let!(:other) { other }
|
||||||
class OverwritingSetup < Cop
|
class OverwritingSetup < Base
|
||||||
MSG = '`%<name>s` is already defined.'
|
MSG = '`%<name>s` is already defined.'
|
||||||
|
|
||||||
def_node_matcher :setup?, (Helpers::ALL + Subject::ALL).block_pattern
|
def_node_matcher :setup?, (Helpers::ALL + Subject::ALL).block_pattern
|
||||||
@ -31,7 +31,7 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# describe MyClass do
|
# describe MyClass do
|
||||||
# end
|
# end
|
||||||
class Pending < Cop
|
class Pending < Base
|
||||||
MSG = 'Pending spec found.'
|
MSG = 'Pending spec found.'
|
||||||
|
|
||||||
PENDING = Examples::PENDING + Examples::SKIPPED + ExampleGroups::SKIPPED
|
PENDING = Examples::PENDING + Examples::SKIPPED + ExampleGroups::SKIPPED
|
||||||
@ -208,18 +208,20 @@ module RuboCop
|
|||||||
'is_a?'
|
'is_a?'
|
||||||
when 'be_an_instance_of', 'be_instance_of', 'an_instance_of'
|
when 'be_an_instance_of', 'be_instance_of', 'an_instance_of'
|
||||||
'instance_of?'
|
'instance_of?'
|
||||||
when 'include', 'respond_to'
|
when 'include'
|
||||||
matcher + '?'
|
'include?'
|
||||||
|
when 'respond_to'
|
||||||
|
'respond_to?'
|
||||||
when /^have_(.+)/
|
when /^have_(.+)/
|
||||||
"has_#{Regexp.last_match(1)}?"
|
"has_#{Regexp.last_match(1)}?"
|
||||||
else
|
else
|
||||||
matcher[/^be_(.+)/, 1] + '?'
|
"#{matcher[/^be_(.+)/, 1]}?"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/MethodLength
|
# rubocop:enable Metrics/MethodLength
|
||||||
|
|
||||||
def replacement_matcher(node)
|
def replacement_matcher(node)
|
||||||
case [cop_config['Strict'], node.method_name == :to]
|
case [cop_config['Strict'], node.method?(:to)]
|
||||||
when [true, true]
|
when [true, true]
|
||||||
'be(true)'
|
'be(true)'
|
||||||
when [true, false]
|
when [true, false]
|
||||||
@ -269,7 +271,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good - the above code is rewritten to it by this cop
|
# # good - the above code is rewritten to it by this cop
|
||||||
# expect(foo.something?).to be_truthy
|
# expect(foo.something?).to be_truthy
|
||||||
class PredicateMatcher < Cop
|
class PredicateMatcher < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
include InflectedHelper
|
include InflectedHelper
|
||||||
@ -288,15 +290,6 @@ module RuboCop
|
|||||||
check_explicit(node) if style == :explicit
|
check_explicit(node) if style == :explicit
|
||||||
end
|
end
|
||||||
|
|
||||||
def autocorrect(node)
|
|
||||||
case style
|
|
||||||
when :inflected
|
|
||||||
autocorrect_inflected(node)
|
|
||||||
when :explicit
|
|
||||||
autocorrect_explicit(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# returns args location with whitespace
|
# returns args location with whitespace
|
||||||
@ -30,7 +30,7 @@ module RuboCop
|
|||||||
# it { is_expected.to have_http_status :success }
|
# it { is_expected.to have_http_status :success }
|
||||||
# it { is_expected.to have_http_status :error }
|
# it { is_expected.to have_http_status :error }
|
||||||
#
|
#
|
||||||
class HttpStatus < Cop
|
class HttpStatus < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ module RuboCop
|
|||||||
# expect(foo).to receive(:bar).at_most(:once)
|
# expect(foo).to receive(:bar).at_most(:once)
|
||||||
# expect(foo).to receive(:bar).at_most(:twice).times
|
# expect(foo).to receive(:bar).at_most(:twice).times
|
||||||
#
|
#
|
||||||
class ReceiveCounts < Cop
|
class ReceiveCounts < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<alternative>s` instead of `%<original>s`.'
|
MSG = 'Use `%<alternative>s` instead of `%<original>s`.'
|
||||||
@ -13,14 +13,14 @@ module RuboCop
|
|||||||
# # good
|
# # good
|
||||||
# expect(foo).not_to receive(:bar)
|
# expect(foo).not_to receive(:bar)
|
||||||
#
|
#
|
||||||
class ReceiveNever < Cop
|
class ReceiveNever < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
MSG = 'Use `not_to receive` instead of `never`.'
|
MSG = 'Use `not_to receive` instead of `never`.'
|
||||||
|
|
||||||
def_node_search :method_on_stub?, '(send nil? :receive ...)'
|
def_node_search :method_on_stub?, '(send nil? :receive ...)'
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
return unless node.method_name == :never && method_on_stub?(node)
|
return unless node.method?(:never) && method_on_stub?(node)
|
||||||
|
|
||||||
add_offense(node.loc.selector) do |corrector|
|
add_offense(node.loc.selector) do |corrector|
|
||||||
autocorrect(corrector, node)
|
autocorrect(corrector, node)
|
||||||
@ -40,7 +40,7 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class RepeatedDescription < Cop
|
class RepeatedDescription < Base
|
||||||
MSG = "Don't repeat descriptions within an example group."
|
MSG = "Don't repeat descriptions within an example group."
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
@ -15,7 +15,7 @@ module RuboCop
|
|||||||
# expect(user).to be_valid
|
# expect(user).to be_valid
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class RepeatedExample < Cop
|
class RepeatedExample < Base
|
||||||
MSG = "Don't repeat examples within an example group."
|
MSG = "Don't repeat examples within an example group."
|
||||||
|
|
||||||
def on_block(node)
|
def on_block(node)
|
||||||
@ -41,7 +41,7 @@ module RuboCop
|
|||||||
def example_signature(example)
|
def example_signature(example)
|
||||||
key_parts = [example.metadata, example.implementation]
|
key_parts = [example.metadata, example.implementation]
|
||||||
|
|
||||||
if example.definition.method_name == :its
|
if example.definition.method?(:its)
|
||||||
key_parts << example.definition.arguments
|
key_parts << example.definition.arguments
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ module RuboCop
|
|||||||
# it { is_expected.to respond_to :each }
|
# it { is_expected.to respond_to :each }
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class RepeatedExampleGroupBody < Cop
|
class RepeatedExampleGroupBody < Base
|
||||||
MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
|
MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
|
||||||
|
|
||||||
def_node_matcher :several_example_groups?, <<-PATTERN
|
def_node_matcher :several_example_groups?, <<-PATTERN
|
||||||
@ -43,7 +43,7 @@ module RuboCop
|
|||||||
# # example group
|
# # example group
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class RepeatedExampleGroupDescription < Cop
|
class RepeatedExampleGroupDescription < Base
|
||||||
MSG = 'Repeated %<group>s block description on line(s) %<loc>s'
|
MSG = 'Repeated %<group>s block description on line(s) %<loc>s'
|
||||||
|
|
||||||
def_node_matcher :several_example_groups?, <<-PATTERN
|
def_node_matcher :several_example_groups?, <<-PATTERN
|
||||||
@ -33,7 +33,7 @@ module RuboCop
|
|||||||
# # also good as the returned value is dynamic
|
# # also good as the returned value is dynamic
|
||||||
# allow(Foo).to receive(:bar) { bar.baz }
|
# allow(Foo).to receive(:bar) { bar.baz }
|
||||||
#
|
#
|
||||||
class ReturnFromStub < Cop
|
class ReturnFromStub < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ module RuboCop
|
|||||||
# let!(:baz) { 3 }
|
# let!(:baz) { 3 }
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class ScatteredLet < Cop
|
class ScatteredLet < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Group all let/let! blocks in the example group together.'
|
MSG = 'Group all let/let! blocks in the example group together.'
|
||||||
@ -22,7 +22,7 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class ScatteredSetup < Cop
|
class ScatteredSetup < Base
|
||||||
MSG = 'Do not define multiple `%<hook_name>s` hooks in the same '\
|
MSG = 'Do not define multiple `%<hook_name>s` hooks in the same '\
|
||||||
'example group (also defined on %<lines>s).'
|
'example group (also defined on %<lines>s).'
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class SharedContext < Cop
|
class SharedContext < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG_EXAMPLES = "Use `shared_examples` when you don't "\
|
MSG_EXAMPLES = "Use `shared_examples` when you don't "\
|
||||||
@ -20,7 +20,7 @@ module RuboCop
|
|||||||
# shared_examples_for 'foo bar baz'
|
# shared_examples_for 'foo bar baz'
|
||||||
# include_examples 'foo bar baz'
|
# include_examples 'foo bar baz'
|
||||||
#
|
#
|
||||||
class SharedExamples < Cop
|
class SharedExamples < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
def_node_matcher :shared_examples,
|
def_node_matcher :shared_examples,
|
||||||
@ -16,7 +16,7 @@ module RuboCop
|
|||||||
# allow(foo).to receive(:bar, :baz)
|
# allow(foo).to receive(:bar, :baz)
|
||||||
# allow(foo).to receive("bar.baz")
|
# allow(foo).to receive("bar.baz")
|
||||||
#
|
#
|
||||||
class SingleArgumentMessageChain < Cop
|
class SingleArgumentMessageChain < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<recommended>s` instead of calling '\
|
MSG = 'Use `%<recommended>s` instead of calling '\
|
||||||
@ -21,7 +21,7 @@ module RuboCop
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class SubjectStub < Cop
|
class SubjectStub < Base
|
||||||
include RuboCop::RSpec::TopLevelGroup
|
include RuboCop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
MSG = 'Do not stub methods of the object under test.'
|
MSG = 'Do not stub methods of the object under test.'
|
||||||
@ -39,7 +39,7 @@ module RuboCop
|
|||||||
# name # => :thing
|
# name # => :thing
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# @param node [RuboCop::Node]
|
# @param node [RuboCop::AST::Node]
|
||||||
#
|
#
|
||||||
# @yield [Symbol] subject name
|
# @yield [Symbol] subject name
|
||||||
def_node_matcher :subject, <<-PATTERN
|
def_node_matcher :subject, <<-PATTERN
|
||||||
@ -30,7 +30,7 @@ module RuboCop
|
|||||||
# }.to raise_error(/err/)
|
# }.to raise_error(/err/)
|
||||||
#
|
#
|
||||||
# expect { do_something }.not_to raise_error
|
# expect { do_something }.not_to raise_error
|
||||||
class UnspecifiedException < Cop
|
class UnspecifiedException < Base
|
||||||
MSG = 'Specify the exception being captured'
|
MSG = 'Specify the exception being captured'
|
||||||
|
|
||||||
def_node_matcher :empty_raise_error_or_exception, <<-PATTERN
|
def_node_matcher :empty_raise_error_or_exception, <<-PATTERN
|
||||||
@ -7,22 +7,22 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# @example EnforcedStyle: symbols (default)
|
# @example EnforcedStyle: symbols (default)
|
||||||
# # bad
|
# # bad
|
||||||
# let('user_name') { 'Adam' }
|
|
||||||
# subject('user') { create_user }
|
# subject('user') { create_user }
|
||||||
|
# let('user_name') { 'Adam' }
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# let(:user_name) { 'Adam' }
|
|
||||||
# subject(:user) { create_user }
|
# subject(:user) { create_user }
|
||||||
|
# let(:user_name) { 'Adam' }
|
||||||
#
|
#
|
||||||
# @example EnforcedStyle: strings
|
# @example EnforcedStyle: strings
|
||||||
# # bad
|
# # bad
|
||||||
# let(:user_name) { 'Adam' }
|
|
||||||
# subject(:user) { create_user }
|
# subject(:user) { create_user }
|
||||||
|
# let(:user_name) { 'Adam' }
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# let('user_name') { 'Adam' }
|
|
||||||
# subject('user') { create_user }
|
# subject('user') { create_user }
|
||||||
class VariableDefinition < Cop
|
# let('user_name') { 'Adam' }
|
||||||
|
class VariableDefinition < Base
|
||||||
include ConfigurableEnforcedStyle
|
include ConfigurableEnforcedStyle
|
||||||
include RuboCop::RSpec::Variable
|
include RuboCop::RSpec::Variable
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def string?(node)
|
def string?(node)
|
||||||
node.str_type? || node.dstr_type?
|
node.str_type?
|
||||||
end
|
end
|
||||||
|
|
||||||
def symbol?(node)
|
def symbol?(node)
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module RSpec
|
||||||
|
# Checks that memoized helper names use the configured style.
|
||||||
|
#
|
||||||
|
# Variables can be excluded from checking using the `IgnoredPatterns`
|
||||||
|
# option.
|
||||||
|
#
|
||||||
|
# @example EnforcedStyle: snake_case (default)
|
||||||
|
# # bad
|
||||||
|
# subject(:userName1) { 'Adam' }
|
||||||
|
# let(:userName2) { 'Adam' }
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# subject(:user_name_1) { 'Adam' }
|
||||||
|
# let(:user_name_2) { 'Adam' }
|
||||||
|
#
|
||||||
|
# @example EnforcedStyle: camelCase
|
||||||
|
# # bad
|
||||||
|
# subject(:user_name_1) { 'Adam' }
|
||||||
|
# let(:user_name_2) { 'Adam' }
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# subject(:userName1) { 'Adam' }
|
||||||
|
# let(:userName2) { 'Adam' }
|
||||||
|
#
|
||||||
|
# @example IgnoredPatterns configuration
|
||||||
|
#
|
||||||
|
# # rubocop.yml
|
||||||
|
# # RSpec/VariableName:
|
||||||
|
# # EnforcedStyle: snake_case
|
||||||
|
# # IgnoredPatterns:
|
||||||
|
# # - ^userFood
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # okay because it matches the `^userFood` regex in `IgnoredPatterns`
|
||||||
|
# subject(:userFood_1) { 'spaghetti' }
|
||||||
|
# let(:userFood_2) { 'fettuccine' }
|
||||||
|
#
|
||||||
|
class VariableName < Base
|
||||||
|
include ConfigurableNaming
|
||||||
|
include IgnoredPattern
|
||||||
|
include RuboCop::RSpec::Variable
|
||||||
|
|
||||||
|
MSG = 'Use %<style>s for variable names.'
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
variable_definition?(node) do |variable|
|
||||||
|
return if variable.dstr_type? || variable.dsym_type?
|
||||||
|
return if matches_ignored_pattern?(variable.value)
|
||||||
|
|
||||||
|
check_name(node, variable.value, variable.loc.expression)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def message(style)
|
||||||
|
format(MSG, style: style)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -22,7 +22,7 @@ module RuboCop
|
|||||||
# let(:foo) do
|
# let(:foo) do
|
||||||
# instance_double("ClassName", method_name: 'returned value')
|
# instance_double("ClassName", method_name: 'returned value')
|
||||||
# end
|
# end
|
||||||
class VerifiedDoubles < Cop
|
class VerifiedDoubles < Base
|
||||||
MSG = 'Prefer using verifying doubles over normal doubles.'
|
MSG = 'Prefer using verifying doubles over normal doubles.'
|
||||||
|
|
||||||
def_node_matcher :unverified_double, <<-PATTERN
|
def_node_matcher :unverified_double, <<-PATTERN
|
||||||
@ -11,7 +11,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# expect(something).to be(1)
|
# expect(something).to be(1)
|
||||||
class VoidExpect < Cop
|
class VoidExpect < Base
|
||||||
MSG = 'Do not use `expect()` without `.to` or `.not_to`. ' \
|
MSG = 'Do not use `expect()` without `.to` or `.not_to`. ' \
|
||||||
'Chain the methods or remove it.'
|
'Chain the methods or remove it.'
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# expect(foo).to be(:bar).and_yield(1)
|
# expect(foo).to be(:bar).and_yield(1)
|
||||||
class Yield < Cop
|
class Yield < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include RangeHelp
|
include RangeHelp
|
||||||
|
|
||||||
@ -65,6 +65,7 @@ require_relative 'rspec/message_spies'
|
|||||||
require_relative 'rspec/missing_example_group_argument'
|
require_relative 'rspec/missing_example_group_argument'
|
||||||
require_relative 'rspec/multiple_describes'
|
require_relative 'rspec/multiple_describes'
|
||||||
require_relative 'rspec/multiple_expectations'
|
require_relative 'rspec/multiple_expectations'
|
||||||
|
require_relative 'rspec/multiple_memoized_helpers'
|
||||||
require_relative 'rspec/multiple_subjects'
|
require_relative 'rspec/multiple_subjects'
|
||||||
require_relative 'rspec/named_subject'
|
require_relative 'rspec/named_subject'
|
||||||
require_relative 'rspec/nested_groups'
|
require_relative 'rspec/nested_groups'
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user