rubocop-rspec 2.16.0 → 2.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +124 -9
- data/README.md +3 -3
- data/config/default.yml +145 -18
- data/config/obsoletion.yml +15 -0
- data/lib/rubocop/cop/rspec/be_empty.rb +44 -0
- data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +29 -115
- data/lib/rubocop/cop/rspec/capybara/match_style.rb +38 -0
- data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +23 -96
- data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +19 -75
- data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +14 -83
- data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +25 -69
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +26 -63
- data/lib/rubocop/cop/rspec/change_by_zero.rb +33 -23
- data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
- data/lib/rubocop/cop/rspec/context_method.rb +5 -1
- data/lib/rubocop/cop/rspec/context_wording.rb +13 -6
- data/lib/rubocop/cop/rspec/describe_method.rb +16 -8
- data/lib/rubocop/cop/rspec/described_class.rb +2 -1
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +7 -5
- data/lib/rubocop/cop/rspec/dialect.rb +1 -1
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +2 -2
- data/lib/rubocop/cop/rspec/empty_example_group.rb +10 -7
- data/lib/rubocop/cop/rspec/empty_hook.rb +2 -2
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
- data/lib/rubocop/cop/rspec/eq.rb +47 -0
- data/lib/rubocop/cop/rspec/example_wording.rb +1 -1
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +14 -5
- data/lib/rubocop/cop/rspec/expect_actual.rb +4 -4
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +25 -118
- data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +40 -107
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +30 -250
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +19 -46
- data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +23 -64
- data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +45 -79
- data/lib/rubocop/cop/rspec/file_path.rb +8 -2
- data/lib/rubocop/cop/rspec/focus.rb +19 -5
- data/lib/rubocop/cop/rspec/hook_argument.rb +12 -9
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +5 -3
- data/lib/rubocop/cop/rspec/indexed_let.rb +112 -0
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +8 -4
- data/lib/rubocop/cop/rspec/let_setup.rb +6 -8
- data/lib/rubocop/cop/rspec/match_array.rb +59 -0
- data/lib/rubocop/cop/rspec/metadata_style.rb +197 -0
- data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +1 -2
- data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
- data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +21 -7
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +20 -4
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +2 -1
- data/lib/rubocop/cop/rspec/named_subject.rb +7 -5
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +2 -5
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +3 -1
- data/lib/rubocop/cop/rspec/pending.rb +23 -13
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +72 -36
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +49 -40
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +11 -6
- data/lib/rubocop/cop/rspec/rails/http_status.rb +107 -34
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +4 -4
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +60 -0
- data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +102 -0
- data/lib/rubocop/cop/rspec/rails/travel_around.rb +92 -0
- data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
- data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +3 -6
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +3 -6
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -4
- data/lib/rubocop/cop/rspec/scattered_setup.rb +23 -6
- data/lib/rubocop/cop/rspec/shared_context.rb +12 -13
- data/lib/rubocop/cop/rspec/shared_examples.rb +6 -4
- data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
- data/lib/rubocop/cop/rspec/sort_metadata.rb +4 -3
- data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
- data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +0 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +5 -2
- data/lib/rubocop/cop/rspec/variable_name.rb +4 -1
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +7 -7
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
- data/lib/rubocop/cop/rspec/void_expect.rb +2 -1
- data/lib/rubocop/cop/rspec_cops.rb +16 -0
- data/lib/rubocop/rspec/config_formatter.rb +16 -0
- data/lib/rubocop/rspec/example_group.rb +6 -8
- data/lib/rubocop/rspec/language/node_pattern.rb +26 -0
- data/lib/rubocop/rspec/language.rb +25 -16
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +4 -5
- metadata +50 -8
- data/lib/rubocop/cop/rspec/mixin/capybara_help.rb +0 -80
- data/lib/rubocop/cop/rspec/mixin/css_selector.rb +0 -146
- data/lib/rubocop/rspec/factory_bot/language.rb +0 -37
- data/lib/rubocop/rspec/factory_bot.rb +0 -64
| @@ -4,52 +4,25 @@ module RuboCop | |
| 4 4 | 
             
              module Cop
         | 
| 5 5 | 
             
                module RSpec
         | 
| 6 6 | 
             
                  module FactoryBot
         | 
| 7 | 
            -
                    #  | 
| 8 | 
            -
                    #
         | 
| 9 | 
            -
                    # | 
| 10 | 
            -
                    #  | 
| 11 | 
            -
                    #  | 
| 12 | 
            -
                    #  | 
| 13 | 
            -
                    #
         | 
| 14 | 
            -
                    # | 
| 15 | 
            -
                    #   #  | 
| 16 | 
            -
                    #    | 
| 17 | 
            -
                    #    | 
| 18 | 
            -
                    #
         | 
| 19 | 
            -
                    #   # | 
| 20 | 
            -
                    #    | 
| 21 | 
            -
                    #    | 
| 22 | 
            -
                    #
         | 
| 23 | 
            -
                     | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                      MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
         | 
| 27 | 
            -
                            'constant.'
         | 
| 28 | 
            -
                      ALLOWED_CONSTANTS = %w[Hash OpenStruct].freeze
         | 
| 29 | 
            -
                      RESTRICT_ON_SEND = %i[factory].freeze
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                      # @!method class_name(node)
         | 
| 32 | 
            -
                      def_node_matcher :class_name, <<~PATTERN
         | 
| 33 | 
            -
                        (send _ :factory _ (hash <(pair (sym :class) $(const ...)) ...>))
         | 
| 34 | 
            -
                      PATTERN
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                      def on_send(node)
         | 
| 37 | 
            -
                        class_name(node) do |cn|
         | 
| 38 | 
            -
                          next if allowed?(cn.const_name)
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                          msg = format(MSG, class_name: cn.const_name)
         | 
| 41 | 
            -
                          add_offense(cn, message: msg) do |corrector|
         | 
| 42 | 
            -
                            corrector.replace(cn, "'#{cn.source}'")
         | 
| 43 | 
            -
                          end
         | 
| 44 | 
            -
                        end
         | 
| 45 | 
            -
                      end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                      private
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                      def allowed?(const_name)
         | 
| 50 | 
            -
                        ALLOWED_CONSTANTS.include?(const_name)
         | 
| 51 | 
            -
                      end
         | 
| 52 | 
            -
                    end
         | 
| 7 | 
            +
                    # @!parse
         | 
| 8 | 
            +
                    #   # Use string value when setting the class attribute explicitly.
         | 
| 9 | 
            +
                    #   #
         | 
| 10 | 
            +
                    #   # This cop would promote faster tests by lazy-loading of
         | 
| 11 | 
            +
                    #   # application files. Also, this could help you suppress potential
         | 
| 12 | 
            +
                    #   # bugs in combination with external libraries by avoiding a preload
         | 
| 13 | 
            +
                    #   # of application files from the factory files.
         | 
| 14 | 
            +
                    #   #
         | 
| 15 | 
            +
                    #   # @example
         | 
| 16 | 
            +
                    #   #   # bad
         | 
| 17 | 
            +
                    #   #   factory :foo, class: Foo do
         | 
| 18 | 
            +
                    #   #   end
         | 
| 19 | 
            +
                    #   #
         | 
| 20 | 
            +
                    #   #   # good
         | 
| 21 | 
            +
                    #   #   factory :foo, class: 'Foo' do
         | 
| 22 | 
            +
                    #   #   end
         | 
| 23 | 
            +
                    #   #
         | 
| 24 | 
            +
                    #   class FactoryClassName < ::RuboCop::Cop::Base; end
         | 
| 25 | 
            +
                    FactoryClassName = ::RuboCop::Cop::FactoryBot::FactoryClassName
         | 
| 53 26 | 
             
                  end
         | 
| 54 27 | 
             
                end
         | 
| 55 28 | 
             
              end
         | 
| @@ -4,70 +4,29 @@ module RuboCop | |
| 4 4 | 
             
              module Cop
         | 
| 5 5 | 
             
                module RSpec
         | 
| 6 6 | 
             
                  module FactoryBot
         | 
| 7 | 
            -
                    #  | 
| 8 | 
            -
                    #
         | 
| 9 | 
            -
                    # | 
| 10 | 
            -
                    #   #  | 
| 11 | 
            -
                    #    | 
| 12 | 
            -
                    #    | 
| 13 | 
            -
                    #
         | 
| 14 | 
            -
                    #   # | 
| 15 | 
            -
                    #    | 
| 16 | 
            -
                    #    | 
| 17 | 
            -
                    #
         | 
| 18 | 
            -
                    # | 
| 19 | 
            -
                    #   #  | 
| 20 | 
            -
                    #    | 
| 21 | 
            -
                    #    | 
| 22 | 
            -
                    #
         | 
| 23 | 
            -
                    #   # | 
| 24 | 
            -
                    #    | 
| 25 | 
            -
                    #    | 
| 26 | 
            -
                    #
         | 
| 27 | 
            -
                     | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
                      include RuboCop::RSpec::FactoryBot::Language
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                      MSG = 'Use %<prefer>s to refer to a factory.'
         | 
| 33 | 
            -
                      FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
         | 
| 34 | 
            -
                      RESTRICT_ON_SEND = FACTORY_CALLS
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                      # @!method factory_call(node)
         | 
| 37 | 
            -
                      def_node_matcher :factory_call, <<-PATTERN
         | 
| 38 | 
            -
                      (send
         | 
| 39 | 
            -
                        {#factory_bot? nil?} %FACTORY_CALLS
         | 
| 40 | 
            -
                        ${str sym} ...
         | 
| 41 | 
            -
                      )
         | 
| 42 | 
            -
                      PATTERN
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                      def on_send(node)
         | 
| 45 | 
            -
                        factory_call(node) do |name|
         | 
| 46 | 
            -
                          if offense_for_symbol_style?(name)
         | 
| 47 | 
            -
                            register_offense(name, name.value.to_sym.inspect)
         | 
| 48 | 
            -
                          elsif offense_for_string_style?(name)
         | 
| 49 | 
            -
                            register_offense(name, name.value.to_s.inspect)
         | 
| 50 | 
            -
                          end
         | 
| 51 | 
            -
                        end
         | 
| 52 | 
            -
                      end
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                      private
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                      def offense_for_symbol_style?(name)
         | 
| 57 | 
            -
                        name.str_type? && style == :symbol
         | 
| 58 | 
            -
                      end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                      def offense_for_string_style?(name)
         | 
| 61 | 
            -
                        name.sym_type? && style == :string
         | 
| 62 | 
            -
                      end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                      def register_offense(name, prefer)
         | 
| 65 | 
            -
                        add_offense(name,
         | 
| 66 | 
            -
                                    message: format(MSG, prefer: style.to_s)) do |corrector|
         | 
| 67 | 
            -
                          corrector.replace(name, prefer)
         | 
| 68 | 
            -
                        end
         | 
| 69 | 
            -
                      end
         | 
| 70 | 
            -
                    end
         | 
| 7 | 
            +
                    # @!parse
         | 
| 8 | 
            +
                    #   # Checks for name style for argument of FactoryBot::Syntax::Methods.
         | 
| 9 | 
            +
                    #   #
         | 
| 10 | 
            +
                    #   # @example EnforcedStyle: symbol (default)
         | 
| 11 | 
            +
                    #   #   # bad
         | 
| 12 | 
            +
                    #   #   create('user')
         | 
| 13 | 
            +
                    #   #   build "user", username: "NAME"
         | 
| 14 | 
            +
                    #   #
         | 
| 15 | 
            +
                    #   #   # good
         | 
| 16 | 
            +
                    #   #   create(:user)
         | 
| 17 | 
            +
                    #   #   build :user, username: "NAME"
         | 
| 18 | 
            +
                    #   #
         | 
| 19 | 
            +
                    #   # @example EnforcedStyle: string
         | 
| 20 | 
            +
                    #   #   # bad
         | 
| 21 | 
            +
                    #   #   create(:user)
         | 
| 22 | 
            +
                    #   #   build :user, username: "NAME"
         | 
| 23 | 
            +
                    #   #
         | 
| 24 | 
            +
                    #   #   # good
         | 
| 25 | 
            +
                    #   #   create('user')
         | 
| 26 | 
            +
                    #   #   build "user", username: "NAME"
         | 
| 27 | 
            +
                    #   #
         | 
| 28 | 
            +
                    #   class FactoryNameStyle < ::RuboCop::Cop::Base; end
         | 
| 29 | 
            +
                    FactoryNameStyle = ::RuboCop::Cop::FactoryBot::FactoryNameStyle
         | 
| 71 30 | 
             
                  end
         | 
| 72 31 | 
             
                end
         | 
| 73 32 | 
             
              end
         | 
| @@ -4,85 +4,51 @@ module RuboCop | |
| 4 4 | 
             
              module Cop
         | 
| 5 5 | 
             
                module RSpec
         | 
| 6 6 | 
             
                  module FactoryBot
         | 
| 7 | 
            -
                    #  | 
| 8 | 
            -
                    #
         | 
| 9 | 
            -
                    # | 
| 10 | 
            -
                    #    | 
| 11 | 
            -
                    #    | 
| 12 | 
            -
                    #    | 
| 13 | 
            -
                    #
         | 
| 14 | 
            -
                    #    | 
| 15 | 
            -
                    #    | 
| 16 | 
            -
                    #   ` | 
| 17 | 
            -
                    #
         | 
| 18 | 
            -
                    #    | 
| 19 | 
            -
                    #    | 
| 20 | 
            -
                    #    | 
| 21 | 
            -
                    # | 
| 22 | 
            -
                    #    | 
| 23 | 
            -
                    #    | 
| 24 | 
            -
                    #
         | 
| 25 | 
            -
                    #    | 
| 26 | 
            -
                    #
         | 
| 27 | 
            -
                    #    | 
| 28 | 
            -
                    #    | 
| 29 | 
            -
                    #    | 
| 30 | 
            -
                    # | 
| 31 | 
            -
                    #
         | 
| 32 | 
            -
                    # | 
| 33 | 
            -
                    # | 
| 34 | 
            -
                    # | 
| 35 | 
            -
                    #   end
         | 
| 36 | 
            -
                    #    | 
| 37 | 
            -
                    #
         | 
| 38 | 
            -
                    # | 
| 39 | 
            -
                    #   #  | 
| 40 | 
            -
                    #    | 
| 41 | 
            -
                    #   FactoryBot. | 
| 42 | 
            -
                    #   FactoryBot. | 
| 43 | 
            -
                    #
         | 
| 44 | 
            -
                    #   # | 
| 45 | 
            -
                    #    | 
| 46 | 
            -
                    #    | 
| 47 | 
            -
                    #    | 
| 48 | 
            -
                    #
         | 
| 49 | 
            -
                     | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
                      include RangeHelp
         | 
| 53 | 
            -
                      include RuboCop::RSpec::FactoryBot::Language
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                      MSG = 'Use `%<method>s` from `FactoryBot::Syntax::Methods`.'
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                      RESTRICT_ON_SEND = RuboCop::RSpec::FactoryBot::Language::METHODS
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                      def on_send(node)
         | 
| 60 | 
            -
                        return unless factory_bot?(node.receiver)
         | 
| 61 | 
            -
                        return unless inside_example_group?(node)
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                        message = format(MSG, method: node.method_name)
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                        add_offense(crime_scene(node), message: message) do |corrector|
         | 
| 66 | 
            -
                          corrector.remove(offense(node))
         | 
| 67 | 
            -
                        end
         | 
| 68 | 
            -
                      end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                      private
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                      def crime_scene(node)
         | 
| 73 | 
            -
                        range_between(
         | 
| 74 | 
            -
                          node.loc.expression.begin_pos,
         | 
| 75 | 
            -
                          node.loc.selector.end_pos
         | 
| 76 | 
            -
                        )
         | 
| 77 | 
            -
                      end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                      def offense(node)
         | 
| 80 | 
            -
                        range_between(
         | 
| 81 | 
            -
                          node.loc.expression.begin_pos,
         | 
| 82 | 
            -
                          node.loc.selector.begin_pos
         | 
| 83 | 
            -
                        )
         | 
| 84 | 
            -
                      end
         | 
| 85 | 
            -
                    end
         | 
| 7 | 
            +
                    # @!parse
         | 
| 8 | 
            +
                    #   # Use shorthands from `FactoryBot::Syntax::Methods` in your specs.
         | 
| 9 | 
            +
                    #   #
         | 
| 10 | 
            +
                    #   # @safety
         | 
| 11 | 
            +
                    #   #   The autocorrection is marked as unsafe because the cop
         | 
| 12 | 
            +
                    #   #   cannot verify whether you already include
         | 
| 13 | 
            +
                    #   #   `FactoryBot::Syntax::Methods` in your test suite.
         | 
| 14 | 
            +
                    #   #
         | 
| 15 | 
            +
                    #   #   If you're using Rails, add the following configuration to
         | 
| 16 | 
            +
                    #   #   `spec/support/factory_bot.rb` and be sure to require that file
         | 
| 17 | 
            +
                    #   #   in `rails_helper.rb`:
         | 
| 18 | 
            +
                    #   #
         | 
| 19 | 
            +
                    #   #   [source,ruby]
         | 
| 20 | 
            +
                    #   #   ----
         | 
| 21 | 
            +
                    #   #   RSpec.configure do |config|
         | 
| 22 | 
            +
                    #   #     config.include FactoryBot::Syntax::Methods
         | 
| 23 | 
            +
                    #   #   end
         | 
| 24 | 
            +
                    #   #   ----
         | 
| 25 | 
            +
                    #   #
         | 
| 26 | 
            +
                    #   #   If you're not using Rails:
         | 
| 27 | 
            +
                    #   #
         | 
| 28 | 
            +
                    #   #   [source,ruby]
         | 
| 29 | 
            +
                    #   #   ----
         | 
| 30 | 
            +
                    #   #   RSpec.configure do |config|
         | 
| 31 | 
            +
                    #   #     config.include FactoryBot::Syntax::Methods
         | 
| 32 | 
            +
                    #   #
         | 
| 33 | 
            +
                    #   #     config.before(:suite) do
         | 
| 34 | 
            +
                    #   #       FactoryBot.find_definitions
         | 
| 35 | 
            +
                    #   #     end
         | 
| 36 | 
            +
                    #   #   end
         | 
| 37 | 
            +
                    #   #   ----
         | 
| 38 | 
            +
                    #   #
         | 
| 39 | 
            +
                    #   # @example
         | 
| 40 | 
            +
                    #   #   # bad
         | 
| 41 | 
            +
                    #   #   FactoryBot.create(:bar)
         | 
| 42 | 
            +
                    #   #   FactoryBot.build(:bar)
         | 
| 43 | 
            +
                    #   #   FactoryBot.attributes_for(:bar)
         | 
| 44 | 
            +
                    #   #
         | 
| 45 | 
            +
                    #   #   # good
         | 
| 46 | 
            +
                    #   #   create(:bar)
         | 
| 47 | 
            +
                    #   #   build(:bar)
         | 
| 48 | 
            +
                    #   #   attributes_for(:bar)
         | 
| 49 | 
            +
                    #   #
         | 
| 50 | 
            +
                    #   class SyntaxMethods < ::RuboCop::Cop::Base; end
         | 
| 51 | 
            +
                    SyntaxMethods = ::RuboCop::Cop::FactoryBot::SyntaxMethods
         | 
| 86 52 | 
             
                  end
         | 
| 87 53 | 
             
                end
         | 
| 88 54 | 
             
              end
         | 
| @@ -5,8 +5,14 @@ module RuboCop | |
| 5 5 | 
             
                module RSpec
         | 
| 6 6 | 
             
                  # Checks that spec file paths are consistent and well-formed.
         | 
| 7 7 | 
             
                  #
         | 
| 8 | 
            +
                  # This cop is deprecated.
         | 
| 9 | 
            +
                  # We plan to remove it in the next major version update to 3.0.
         | 
| 10 | 
            +
                  # The migration targets are `RSpec/SpecFilePathSuffix`
         | 
| 11 | 
            +
                  # and `RSpec/SpecFilePathFormat`.
         | 
| 12 | 
            +
                  # If you are using this cop, please plan for migration.
         | 
| 13 | 
            +
                  #
         | 
| 8 14 | 
             
                  # By default, this checks that spec file paths are consistent with the
         | 
| 9 | 
            -
                  # test subject and  | 
| 15 | 
            +
                  # test subject and enforces that it reflects the described
         | 
| 10 16 | 
             
                  # class/module and its optionally called out method.
         | 
| 11 17 | 
             
                  #
         | 
| 12 18 | 
             
                  # With the configuration option `IgnoreMethods` the called out method will
         | 
| @@ -165,7 +171,7 @@ module RuboCop | |
| 165 171 | 
             
                    end
         | 
| 166 172 |  | 
| 167 173 | 
             
                    def expanded_file_path
         | 
| 168 | 
            -
                      File.expand_path(processed_source. | 
| 174 | 
            +
                      File.expand_path(processed_source.file_path)
         | 
| 169 175 | 
             
                    end
         | 
| 170 176 | 
             
                  end
         | 
| 171 177 | 
             
                end
         | 
| @@ -34,6 +34,18 @@ module RuboCop | |
| 34 34 | 
             
                  #   # good
         | 
| 35 35 | 
             
                  #   describe 'test' do; end
         | 
| 36 36 | 
             
                  #
         | 
| 37 | 
            +
                  #   # bad
         | 
| 38 | 
            +
                  #   shared_examples 'test', focus: true do; end
         | 
| 39 | 
            +
                  #
         | 
| 40 | 
            +
                  #   # good
         | 
| 41 | 
            +
                  #   shared_examples 'test' do; end
         | 
| 42 | 
            +
                  #
         | 
| 43 | 
            +
                  #   # bad
         | 
| 44 | 
            +
                  #   shared_context 'test', focus: true do; end
         | 
| 45 | 
            +
                  #
         | 
| 46 | 
            +
                  #   # good
         | 
| 47 | 
            +
                  #   shared_context 'test' do; end
         | 
| 48 | 
            +
                  #
         | 
| 37 49 | 
             
                  #   # bad (does not support autocorrection)
         | 
| 38 50 | 
             
                  #   focus 'test' do; end
         | 
| 39 51 | 
             
                  #
         | 
| @@ -51,6 +63,7 @@ module RuboCop | |
| 51 63 | 
             
                        #Examples.regular
         | 
| 52 64 | 
             
                        #Examples.skipped
         | 
| 53 65 | 
             
                        #Examples.pending
         | 
| 66 | 
            +
                        #SharedGroups.all
         | 
| 54 67 | 
             
                      }
         | 
| 55 68 | 
             
                    PATTERN
         | 
| 56 69 |  | 
| @@ -61,12 +74,13 @@ module RuboCop | |
| 61 74 | 
             
                    PATTERN
         | 
| 62 75 |  | 
| 63 76 | 
             
                    # @!method focused_block?(node)
         | 
| 64 | 
            -
                    def_node_matcher :focused_block?,
         | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
                                     PATTERN
         | 
| 77 | 
            +
                    def_node_matcher :focused_block?, <<~PATTERN
         | 
| 78 | 
            +
                      (send #rspec? {#ExampleGroups.focused #Examples.focused} ...)
         | 
| 79 | 
            +
                    PATTERN
         | 
| 68 80 |  | 
| 69 81 | 
             
                    def on_send(node)
         | 
| 82 | 
            +
                      return if node.chained? || node.each_ancestor(:def, :defs).any?
         | 
| 83 | 
            +
             | 
| 70 84 | 
             
                      focus_metadata(node) do |focus|
         | 
| 71 85 | 
             
                        add_offense(focus) do |corrector|
         | 
| 72 86 | 
             
                          if focus.pair_type? || focus.str_type? || focus.sym_type?
         | 
| @@ -88,7 +102,7 @@ module RuboCop | |
| 88 102 |  | 
| 89 103 | 
             
                    def with_surrounding(focus)
         | 
| 90 104 | 
             
                      range_with_space =
         | 
| 91 | 
            -
                        range_with_surrounding_space(focus. | 
| 105 | 
            +
                        range_with_surrounding_space(focus.source_range, side: :left)
         | 
| 92 106 |  | 
| 93 107 | 
             
                      range_with_surrounding_comma(range_with_space, :left)
         | 
| 94 108 | 
             
                    end
         | 
| @@ -83,8 +83,7 @@ module RuboCop | |
| 83 83 | 
             
                        style_detected(scope_name)
         | 
| 84 84 | 
             
                        msg = explicit_message(scope_name)
         | 
| 85 85 | 
             
                        add_offense(method_send, message: msg) do |corrector|
         | 
| 86 | 
            -
                           | 
| 87 | 
            -
                          corrector.replace(argument_range(method_send), scope)
         | 
| 86 | 
            +
                          autocorrect(corrector, node, method_send)
         | 
| 88 87 | 
             
                        end
         | 
| 89 88 | 
             
                      end
         | 
| 90 89 | 
             
                    end
         | 
| @@ -93,6 +92,13 @@ module RuboCop | |
| 93 92 |  | 
| 94 93 | 
             
                    private
         | 
| 95 94 |  | 
| 95 | 
            +
                    def autocorrect(corrector, _node, method_send)
         | 
| 96 | 
            +
                      scope = implicit_style? ? '' : "(#{style.inspect})"
         | 
| 97 | 
            +
                      corrector.replace(
         | 
| 98 | 
            +
                        LocationHelp.arguments_with_whitespace(method_send), scope
         | 
| 99 | 
            +
                      )
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
             | 
| 96 102 | 
             
                    def check_implicit(method_send)
         | 
| 97 103 | 
             
                      style_detected(:implicit)
         | 
| 98 104 | 
             
                      return if implicit_style?
         | 
| @@ -100,7 +106,10 @@ module RuboCop | |
| 100 106 | 
             
                      msg = explicit_message(nil)
         | 
| 101 107 | 
             
                      add_offense(method_send.loc.selector, message: msg) do |corrector|
         | 
| 102 108 | 
             
                        scope = "(#{style.inspect})"
         | 
| 103 | 
            -
                        corrector.replace( | 
| 109 | 
            +
                        corrector.replace(
         | 
| 110 | 
            +
                          LocationHelp.arguments_with_whitespace(method_send),
         | 
| 111 | 
            +
                          scope
         | 
| 112 | 
            +
                        )
         | 
| 104 113 | 
             
                      end
         | 
| 105 114 | 
             
                    end
         | 
| 106 115 |  | 
| @@ -119,12 +128,6 @@ module RuboCop | |
| 119 128 | 
             
                    def hook(node, &block)
         | 
| 120 129 | 
             
                      scoped_hook(node, &block) || unscoped_hook(node, &block)
         | 
| 121 130 | 
             
                    end
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                    def argument_range(send_node)
         | 
| 124 | 
            -
                      send_node.loc.selector.end.with(
         | 
| 125 | 
            -
                        end_pos: send_node.loc.expression.end_pos
         | 
| 126 | 
            -
                      )
         | 
| 127 | 
            -
                    end
         | 
| 128 131 | 
             
                  end
         | 
| 129 132 | 
             
                end
         | 
| 130 133 | 
             
              end
         | 
| @@ -30,9 +30,11 @@ module RuboCop | |
| 30 30 | 
             
                    # @!method example_or_group?(node)
         | 
| 31 31 | 
             
                    def_node_matcher :example_or_group?, <<-PATTERN
         | 
| 32 32 | 
             
                      {
         | 
| 33 | 
            -
                         | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 33 | 
            +
                        ({block numblock} {
         | 
| 34 | 
            +
                          (send #rspec? #ExampleGroups.all ...)
         | 
| 35 | 
            +
                          (send nil? #Examples.all ...)
         | 
| 36 | 
            +
                        } ...)
         | 
| 37 | 
            +
                        (send nil? #Includes.examples ...)
         | 
| 36 38 | 
             
                      }
         | 
| 37 39 | 
             
                    PATTERN
         | 
| 38 40 |  | 
| @@ -0,0 +1,112 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module RuboCop
         | 
| 4 | 
            +
              module Cop
         | 
| 5 | 
            +
                module RSpec
         | 
| 6 | 
            +
                  # Do not set up test data using indexes (e.g., `item_1`, `item_2`).
         | 
| 7 | 
            +
                  #
         | 
| 8 | 
            +
                  # It makes reading the test harder because it's not clear what exactly
         | 
| 9 | 
            +
                  # is tested by this particular example.
         | 
| 10 | 
            +
                  #
         | 
| 11 | 
            +
                  # The configurable options `AllowedIdentifiers` and `AllowedPatterns`
         | 
| 12 | 
            +
                  # will also read those set in `Naming/VariableNumber`.
         | 
| 13 | 
            +
                  #
         | 
| 14 | 
            +
                  # @example `Max: 1 (default)`
         | 
| 15 | 
            +
                  #   # bad
         | 
| 16 | 
            +
                  #   let(:item_1) { create(:item) }
         | 
| 17 | 
            +
                  #   let(:item_2) { create(:item) }
         | 
| 18 | 
            +
                  #
         | 
| 19 | 
            +
                  #   let(:item1) { create(:item) }
         | 
| 20 | 
            +
                  #   let(:item2) { create(:item) }
         | 
| 21 | 
            +
                  #
         | 
| 22 | 
            +
                  #   # good
         | 
| 23 | 
            +
                  #
         | 
| 24 | 
            +
                  #   let(:visible_item) { create(:item, visible: true) }
         | 
| 25 | 
            +
                  #   let(:invisible_item) { create(:item, visible: false) }
         | 
| 26 | 
            +
                  #
         | 
| 27 | 
            +
                  # @example `Max: 2`
         | 
| 28 | 
            +
                  #   # bad
         | 
| 29 | 
            +
                  #   let(:item_1) { create(:item) }
         | 
| 30 | 
            +
                  #   let(:item_2) { create(:item) }
         | 
| 31 | 
            +
                  #   let(:item_3) { create(:item) }
         | 
| 32 | 
            +
                  #
         | 
| 33 | 
            +
                  #   # good
         | 
| 34 | 
            +
                  #   let(:item_1) { create(:item) }
         | 
| 35 | 
            +
                  #   let(:item_2) { create(:item) }
         | 
| 36 | 
            +
                  #
         | 
| 37 | 
            +
                  # @example `AllowedIdentifiers: ['item_1', 'item_2']`
         | 
| 38 | 
            +
                  #   # good
         | 
| 39 | 
            +
                  #   let(:item_1) { create(:item) }
         | 
| 40 | 
            +
                  #   let(:item_2) { create(:item) }
         | 
| 41 | 
            +
                  #
         | 
| 42 | 
            +
                  # @example `AllowedPatterns: ['item']`
         | 
| 43 | 
            +
                  #   # good
         | 
| 44 | 
            +
                  #   let(:item_1) { create(:item) }
         | 
| 45 | 
            +
                  #   let(:item_2) { create(:item) }
         | 
| 46 | 
            +
                  #
         | 
| 47 | 
            +
                  class IndexedLet < Base
         | 
| 48 | 
            +
                    include AllowedIdentifiers
         | 
| 49 | 
            +
                    include AllowedPattern
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    MSG = 'This `let` statement uses index in its name. Please give it ' \
         | 
| 52 | 
            +
                          'a meaningful name.'
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    # @!method let_name(node)
         | 
| 55 | 
            +
                    def_node_matcher :let_name, <<~PATTERN
         | 
| 56 | 
            +
                      {
         | 
| 57 | 
            +
                        (block (send nil? #Helpers.all ({str sym} $_) ...) ...)
         | 
| 58 | 
            +
                        (send nil? #Helpers.all ({str sym} $_) block_pass)
         | 
| 59 | 
            +
                      }
         | 
| 60 | 
            +
                    PATTERN
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
         | 
| 63 | 
            +
                      return unless spec_group?(node)
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                      children = node.body&.child_nodes
         | 
| 66 | 
            +
                      return unless children
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                      filter_indexed_lets(children).each do |let_node|
         | 
| 69 | 
            +
                        add_offense(let_node)
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    private
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    SUFFIX_INDEX_REGEX = /_?\d+$/.freeze
         | 
| 76 | 
            +
                    INDEX_REGEX = /\d+/.freeze
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    def filter_indexed_lets(candidates)
         | 
| 79 | 
            +
                      candidates
         | 
| 80 | 
            +
                        .filter { |node| indexed_let?(node) }
         | 
| 81 | 
            +
                        .group_by { |node| let_name_stripped_index(node) }
         | 
| 82 | 
            +
                        .values
         | 
| 83 | 
            +
                        .filter { |lets| lets.length > cop_config['Max'] }
         | 
| 84 | 
            +
                        .flatten
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                    def indexed_let?(node)
         | 
| 88 | 
            +
                      let?(node) &&
         | 
| 89 | 
            +
                        SUFFIX_INDEX_REGEX.match?(let_name(node)) &&
         | 
| 90 | 
            +
                        !allowed_identifier?(let_name(node).to_s) &&
         | 
| 91 | 
            +
                        !matches_allowed_pattern?(let_name(node).to_s)
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                    def let_name_stripped_index(node)
         | 
| 95 | 
            +
                      let_name(node).to_s.gsub(INDEX_REGEX, '')
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    def cop_config_patterns_values
         | 
| 99 | 
            +
                      Array(config.for_cop('Naming/VariableNumber')
         | 
| 100 | 
            +
                        .fetch('AllowedPatterns', [])) +
         | 
| 101 | 
            +
                        Array(cop_config.fetch('AllowedPatterns', []))
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    def allowed_identifiers
         | 
| 105 | 
            +
                      Array(config.for_cop('Naming/VariableNumber')
         | 
| 106 | 
            +
                        .fetch('AllowedIdentifiers', [])) +
         | 
| 107 | 
            +
                        Array(cop_config.fetch('AllowedIdentifiers', []))
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
            end
         | 
| @@ -48,7 +48,7 @@ module RuboCop | |
| 48 48 | 
             
                  class InstanceVariable < Base
         | 
| 49 49 | 
             
                    include TopLevelGroup
         | 
| 50 50 |  | 
| 51 | 
            -
                    MSG = 'Avoid instance variables  | 
| 51 | 
            +
                    MSG = 'Avoid instance variables - use let, ' \
         | 
| 52 52 | 
             
                          'a method call, or a local variable (if possible).'
         | 
| 53 53 |  | 
| 54 54 | 
             
                    # @!method dynamic_class?(node)
         | 
| @@ -17,7 +17,7 @@ module RuboCop | |
| 17 17 | 
             
                  # Anonymous classes are fine, since they don't result in global
         | 
| 18 18 | 
             
                  # namespace name clashes.
         | 
| 19 19 | 
             
                  #
         | 
| 20 | 
            -
                  # @see https:// | 
| 20 | 
            +
                  # @see https://rspec.info/features/3-12/rspec-mocks/mutating-constants
         | 
| 21 21 | 
             
                  #
         | 
| 22 22 | 
             
                  # @example Constants leak between examples
         | 
| 23 23 | 
             
                  #   # bad
         | 
| @@ -38,19 +38,23 @@ module RuboCop | |
| 38 38 | 
             
                    # @!method example_or_group?(node)
         | 
| 39 39 | 
             
                    def_node_matcher :example_or_group?, <<-PATTERN
         | 
| 40 40 | 
             
                      {
         | 
| 41 | 
            -
                         | 
| 42 | 
            -
                         | 
| 41 | 
            +
                        (block (send nil? {#ExampleGroups.all #Examples.all} ...) ...)
         | 
| 42 | 
            +
                        (send nil? #Includes.examples ...)
         | 
| 43 43 | 
             
                      }
         | 
| 44 44 | 
             
                    PATTERN
         | 
| 45 45 |  | 
| 46 46 | 
             
                    # @!method include_examples?(node)
         | 
| 47 47 | 
             
                    def_node_matcher :include_examples?, <<~PATTERN
         | 
| 48 48 | 
             
                      {
         | 
| 49 | 
            -
                         | 
| 50 | 
            -
                         | 
| 49 | 
            +
                        (block (send nil? :include_examples ...) ...)
         | 
| 50 | 
            +
                        (send nil? :include_examples ...)
         | 
| 51 51 | 
             
                      }
         | 
| 52 52 | 
             
                    PATTERN
         | 
| 53 53 |  | 
| 54 | 
            +
                    def self.autocorrect_incompatible_with
         | 
| 55 | 
            +
                      [RSpec::ScatteredLet]
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 54 58 | 
             
                    def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
         | 
| 55 59 | 
             
                      return unless example_group_with_body?(node)
         | 
| 56 60 |  | 
| @@ -29,14 +29,12 @@ module RuboCop | |
| 29 29 | 
             
                    MSG = 'Do not use `let!` to setup objects not referenced in tests.'
         | 
| 30 30 |  | 
| 31 31 | 
             
                    # @!method example_or_shared_group_or_including?(node)
         | 
| 32 | 
            -
                    def_node_matcher :example_or_shared_group_or_including?,
         | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
                                       }
         | 
| 39 | 
            -
                                     PATTERN
         | 
| 32 | 
            +
                    def_node_matcher :example_or_shared_group_or_including?, <<~PATTERN
         | 
| 33 | 
            +
                      (block {
         | 
| 34 | 
            +
                        (send #rspec? {#SharedGroups.all #ExampleGroups.all} ...)
         | 
| 35 | 
            +
                        (send nil? #Includes.all ...)
         | 
| 36 | 
            +
                      } ...)
         | 
| 37 | 
            +
                    PATTERN
         | 
| 40 38 |  | 
| 41 39 | 
             
                    # @!method let_bang(node)
         | 
| 42 40 | 
             
                    def_node_matcher :let_bang, <<-PATTERN
         |