rubocop-rspec 1.4.1 → 1.5.0
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 +19 -3
- data/README.md +1 -1
- data/config/default.yml +14 -2
- data/lib/rubocop-rspec.rb +2 -0
- data/lib/rubocop/cop/rspec/any_instance.rb +8 -5
- data/lib/rubocop/cop/rspec/describe_class.rb +2 -1
- data/lib/rubocop/cop/rspec/example_length.rb +60 -0
- data/lib/rubocop/cop/rspec/file_path.rb +13 -3
- data/lib/rubocop/cop/rspec/focus.rb +67 -0
- data/lib/rubocop/cop/rspec/not_to_not.rb +21 -20
- data/lib/rubocop/cop/rspec/verified_doubles.rb +12 -2
- data/lib/rubocop/rspec/version.rb +1 -1
- data/rubocop-rspec.gemspec +1 -1
- data/spec/rubocop/cop/rspec/any_instance_spec.rb +24 -9
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +28 -8
- data/spec/rubocop/cop/rspec/described_class_spec.rb +107 -53
- data/spec/rubocop/cop/rspec/example_length_spec.rb +83 -0
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +12 -5
- data/spec/rubocop/cop/rspec/file_path_spec.rb +121 -61
- data/spec/rubocop/cop/rspec/focus_spec.rb +70 -0
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +18 -9
- data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +22 -7
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +15 -5
- data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +41 -3
- metadata +12 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7f7a58ee16af46402f371a3a3be9ae83752a7555
         | 
| 4 | 
            +
              data.tar.gz: 15ecddf6c683fe294fb914faeadd45eabbbabba6
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ca7b87e0e9210d37795f29ebba6b5398c5e5583b9b68e3a1519c4f9208d18228d99378fba6114a6381c8bf579bf21cf755a3b9ef438765065965b381d9a1e3ca
         | 
| 7 | 
            +
              data.tar.gz: f515ccc02aace366c6ec987aaf258450d8d7f0d2e740382d303a4480633b031de8150ca198369b2059c5856cb94d121afe7161bb10dfe1e70f7bdc1a60ed6f5d
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -2,13 +2,26 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            ## master (unreleased)
         | 
| 4 4 |  | 
| 5 | 
            -
            ## 1. | 
| 5 | 
            +
            ## 1.5.0 (2016-05-17)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Expand `VerifiedDoubles` cop to check for `spy` as well as `double`. ([@andyw8][])
         | 
| 8 | 
            +
            * Enable `VerifiedDoubles` cop by default. ([@andyw8][])
         | 
| 9 | 
            +
            * Add `IgnoreSymbolicNames` option for `VerifiedDoubles` cop. ([@andyw8][])
         | 
| 10 | 
            +
            * Add `RSpec::ExampleLength` cop. ([@andyw8][])
         | 
| 11 | 
            +
            * Handle alphanumeric class names in `FilePath` cop. ([@andyw8][])
         | 
| 12 | 
            +
            * Skip `DescribeClass` cop for view specs. ([@andyw8][])
         | 
| 13 | 
            +
            * Skip `FilePath` cop for Rails routing specs. ([@andyw8][])
         | 
| 14 | 
            +
            * Add cop to check for focused specs. ([@renanborgescampos][], [@jaredmoody][])
         | 
| 15 | 
            +
            * Clean-up `RSpec::NotToNot` to use same configuration semantics as other Rubocop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal][])
         | 
| 16 | 
            +
            * Update to rubocop 0.40.0. ([@nijikon][])
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ## 1.4.1 (2016-04-03)
         | 
| 6 19 |  | 
| 7 20 | 
             
            * Ignore routing specs for DescribeClass cop. ([@nijikon][])
         | 
| 8 21 | 
             
            * Move rubocop dependency to runtime. ([@nijikon][])
         | 
| 9 22 | 
             
            * Update to rubocop 0.39.0. ([@nijikon][])
         | 
| 10 23 |  | 
| 11 | 
            -
            ## 1.4.0 (15 | 
| 24 | 
            +
            ## 1.4.0 (2016-02-15)
         | 
| 12 25 |  | 
| 13 26 | 
             
            * Update to rubocop 0.37.2. ([@nijikon][])
         | 
| 14 27 | 
             
            * Update ruby versions we test against. ([@nijikon][])
         | 
| @@ -73,7 +86,7 @@ | |
| 73 86 |  | 
| 74 87 | 
             
            <!-- Contributors -->
         | 
| 75 88 |  | 
| 76 | 
            -
            [@andyw8]: https://github.com/ | 
| 89 | 
            +
            [@andyw8]: https://github.com/andyw8
         | 
| 77 90 | 
             
            [@bquorning]: https://github.com/bquorning
         | 
| 78 91 | 
             
            [@deivid-rodriguez]: https://github.com/deivid-rodriguez
         | 
| 79 92 | 
             
            [@geniou]: https://github.com/geniou
         | 
| @@ -83,3 +96,6 @@ | |
| 83 96 | 
             
            [@pstengel]: https://github.com/pstengel
         | 
| 84 97 | 
             
            [@miguelfteixeira]: https://github.com/miguelfteixeira
         | 
| 85 98 | 
             
            [@mlarraz]: https://github.com/mlarraz
         | 
| 99 | 
            +
            [@renanborgescampos]: https://github.com/renanborgescampos
         | 
| 100 | 
            +
            [@jaredmoody]: https://github.com/jaredmoody
         | 
| 101 | 
            +
            [@baberthal]: https://github.com/baberthal
         | 
    
        data/README.md
    CHANGED
    
    
    
        data/config/default.yml
    CHANGED
    
    | @@ -41,9 +41,21 @@ RSpec/FilePath: | |
| 41 41 |  | 
| 42 42 | 
             
            RSpec/VerifiedDoubles:
         | 
| 43 43 | 
             
              Description: 'Prefer using verifying doubles over normal doubles.'
         | 
| 44 | 
            -
              Enabled:  | 
| 44 | 
            +
              Enabled: true
         | 
| 45 45 |  | 
| 46 46 | 
             
            RSpec/NotToNot:
         | 
| 47 47 | 
             
              Description: 'Enforces the usage of the same method on all negative message expectations.'
         | 
| 48 | 
            +
              EnforcedStyle: not_to
         | 
| 49 | 
            +
              SupportedStyles:
         | 
| 50 | 
            +
                - not_to
         | 
| 51 | 
            +
                - to_not
         | 
| 52 | 
            +
              Enabled: true
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            RSpec/Focus:
         | 
| 55 | 
            +
              Description: 'Checks if there are focused specs.'
         | 
| 56 | 
            +
              Enabled: true
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            RSpec/ExampleLength:
         | 
| 59 | 
            +
              Description: 'Checks for long example'
         | 
| 48 60 | 
             
              Enabled: true
         | 
| 49 | 
            -
               | 
| 61 | 
            +
              Max: 5
         | 
    
        data/lib/rubocop-rspec.rb
    CHANGED
    
    | @@ -15,7 +15,9 @@ require 'rubocop/cop/rspec/describe_method' | |
| 15 15 | 
             
            require 'rubocop/cop/rspec/described_class'
         | 
| 16 16 | 
             
            require 'rubocop/cop/rspec/example_wording'
         | 
| 17 17 | 
             
            require 'rubocop/cop/rspec/file_path'
         | 
| 18 | 
            +
            require 'rubocop/cop/rspec/focus'
         | 
| 18 19 | 
             
            require 'rubocop/cop/rspec/instance_variable'
         | 
| 20 | 
            +
            require 'rubocop/cop/rspec/example_length'
         | 
| 19 21 | 
             
            require 'rubocop/cop/rspec/multiple_describes'
         | 
| 20 22 | 
             
            require 'rubocop/cop/rspec/not_to_not'
         | 
| 21 23 | 
             
            require 'rubocop/cop/rspec/verified_doubles'
         | 
| @@ -33,11 +33,14 @@ module RuboCop | |
| 33 33 | 
             
                      _receiver, method_name, *_args = *node
         | 
| 34 34 | 
             
                      return unless ANY_INSTANCE_METHODS.include?(method_name)
         | 
| 35 35 |  | 
| 36 | 
            -
                      add_offense( | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 36 | 
            +
                      add_offense(
         | 
| 37 | 
            +
                        node,
         | 
| 38 | 
            +
                        :expression,
         | 
| 39 | 
            +
                        format(
         | 
| 40 | 
            +
                          MESSAGE % { method: method_name },
         | 
| 41 | 
            +
                          node.loc.expression.source
         | 
| 42 | 
            +
                        )
         | 
| 43 | 
            +
                      )
         | 
| 41 44 | 
             
                    end
         | 
| 42 45 | 
             
                  end
         | 
| 43 46 | 
             
                end
         | 
| @@ -24,6 +24,7 @@ module RuboCop | |
| 24 24 | 
             
                    REQUEST_PAIR = s(:pair, s(:sym, :type), s(:sym, :request))
         | 
| 25 25 | 
             
                    FEATURE_PAIR = s(:pair, s(:sym, :type), s(:sym, :feature))
         | 
| 26 26 | 
             
                    ROUTING_PAIR = s(:pair, s(:sym, :type), s(:sym, :routing))
         | 
| 27 | 
            +
                    VIEW_PAIR = s(:pair, s(:sym, :type), s(:sym, :view))
         | 
| 27 28 |  | 
| 28 29 | 
             
                    MESSAGE = 'The first argument to describe should be the class or ' \
         | 
| 29 30 | 
             
                              'module being tested.'.freeze
         | 
| @@ -34,7 +35,7 @@ module RuboCop | |
| 34 35 | 
             
                      return if args[1..-1].any? do |arg|
         | 
| 35 36 | 
             
                        next unless arg.hash_type?
         | 
| 36 37 | 
             
                        arg.children.any? do |n|
         | 
| 37 | 
            -
                          [REQUEST_PAIR, FEATURE_PAIR, ROUTING_PAIR].include?(n)
         | 
| 38 | 
            +
                          [REQUEST_PAIR, FEATURE_PAIR, ROUTING_PAIR, VIEW_PAIR].include?(n)
         | 
| 38 39 | 
             
                        end
         | 
| 39 40 | 
             
                      end
         | 
| 40 41 |  | 
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module RuboCop
         | 
| 5 | 
            +
              module Cop
         | 
| 6 | 
            +
                module RSpec
         | 
| 7 | 
            +
                  # A long example is usually more difficult to understand. Consider
         | 
| 8 | 
            +
                  # extracting out some behaviour, e.g. with a `let` block, or a helper
         | 
| 9 | 
            +
                  # method.
         | 
| 10 | 
            +
                  #
         | 
| 11 | 
            +
                  # @example
         | 
| 12 | 
            +
                  #   # bad
         | 
| 13 | 
            +
                  #   it do
         | 
| 14 | 
            +
                  #     service = described_class.new
         | 
| 15 | 
            +
                  #     more_setup
         | 
| 16 | 
            +
                  #     more_setup
         | 
| 17 | 
            +
                  #     result = service.call
         | 
| 18 | 
            +
                  #     expect(result).to be(true)
         | 
| 19 | 
            +
                  #   end
         | 
| 20 | 
            +
                  #
         | 
| 21 | 
            +
                  #   # good
         | 
| 22 | 
            +
                  #   it do
         | 
| 23 | 
            +
                  #     service = described_class.new
         | 
| 24 | 
            +
                  #     result = service.call
         | 
| 25 | 
            +
                  #     expect(result).to be(true)
         | 
| 26 | 
            +
                  #   end
         | 
| 27 | 
            +
                  class ExampleLength < Cop
         | 
| 28 | 
            +
                    include CodeLength
         | 
| 29 | 
            +
                    EXAMPLE_BLOCKS = [:it, :specify].freeze
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def on_block(node)
         | 
| 32 | 
            +
                      method, _args, _body = *node
         | 
| 33 | 
            +
                      _receiver, method_name, _object = *method
         | 
| 34 | 
            +
                      return unless EXAMPLE_BLOCKS.include?(method_name)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                      length = code_length(node)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      return unless length > max
         | 
| 39 | 
            +
                      add_offense(node, :expression, message(length, max))
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    private
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    def max
         | 
| 45 | 
            +
                      cop_config['Max']
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    def code_length(node)
         | 
| 49 | 
            +
                      lines = node.source.lines.to_a[1..-2] || []
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      lines.count { |line| !irrelevant_line(line) }
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    def message(length, max_length)
         | 
| 55 | 
            +
                      format('Example has too many lines. [%d/%d]', length, max_length)
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
            end
         | 
| @@ -7,8 +7,8 @@ module RuboCop | |
| 7 7 | 
             
                  # Checks the path of the spec file and enforces that it reflects the
         | 
| 8 8 | 
             
                  # described class/module and its optionally called out method.
         | 
| 9 9 | 
             
                  #
         | 
| 10 | 
            -
                  # With the configuration option `CustomTransform` modules or  | 
| 11 | 
            -
                  # specified that should not as usual be transformed from CamelCase to
         | 
| 10 | 
            +
                  # With the configuration option `CustomTransform` modules or classes can
         | 
| 11 | 
            +
                  # be specified that should not as usual be transformed from CamelCase to
         | 
| 12 12 | 
             
                  # snake_case (e.g. 'RuboCop' => 'rubocop' ).
         | 
| 13 13 | 
             
                  #
         | 
| 14 14 | 
             
                  # @example
         | 
| @@ -20,8 +20,11 @@ module RuboCop | |
| 20 20 |  | 
| 21 21 | 
             
                    MESSAGE = 'Spec path should end with `%s`'.freeze
         | 
| 22 22 | 
             
                    METHOD_STRING_MATCHER = /^[\#\.].+/
         | 
| 23 | 
            +
                    ROUTING_PAIR = s(:pair, s(:sym, :type), s(:sym, :routing))
         | 
| 23 24 |  | 
| 24 25 | 
             
                    def on_top_level_describe(node, args)
         | 
| 26 | 
            +
                      return if routing_spec?(args)
         | 
| 27 | 
            +
             | 
| 25 28 | 
             
                      return unless single_top_level_describe?
         | 
| 26 29 | 
             
                      object = args.first.const_name
         | 
| 27 30 | 
             
                      return unless object
         | 
| @@ -34,6 +37,13 @@ module RuboCop | |
| 34 37 |  | 
| 35 38 | 
             
                    private
         | 
| 36 39 |  | 
| 40 | 
            +
                    def routing_spec?(args)
         | 
| 41 | 
            +
                      args[1..-1].any? do |arg|
         | 
| 42 | 
            +
                        next unless arg.hash_type?
         | 
| 43 | 
            +
                        arg.children.include?(ROUTING_PAIR)
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 37 47 | 
             
                    def matcher(object, method)
         | 
| 38 48 | 
             
                      path = File.join(parts(object))
         | 
| 39 49 | 
             
                      if method && method.type == :str
         | 
| @@ -56,7 +66,7 @@ module RuboCop | |
| 56 66 | 
             
                    def camel_to_underscore(string)
         | 
| 57 67 | 
             
                      string.dup.tap do |result|
         | 
| 58 68 | 
             
                        result.gsub!(/([^A-Z])([A-Z]+)/, '\\1_\\2')
         | 
| 59 | 
            -
                        result.gsub!(/([A-Z])([A-Z][^A-Z]+)/, '\\1_\\2')
         | 
| 69 | 
            +
                        result.gsub!(/([A-Z])([A-Z\d][^A-Z\d]+)/, '\\1_\\2')
         | 
| 60 70 | 
             
                        result.downcase!
         | 
| 61 71 | 
             
                      end
         | 
| 62 72 | 
             
                    end
         | 
| @@ -0,0 +1,67 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module RuboCop
         | 
| 5 | 
            +
              module Cop
         | 
| 6 | 
            +
                module RSpec
         | 
| 7 | 
            +
                  # Checks if test is focused.
         | 
| 8 | 
            +
                  #
         | 
| 9 | 
            +
                  # @example
         | 
| 10 | 
            +
                  #   # bad
         | 
| 11 | 
            +
                  #   describe MyClass, focus: true do
         | 
| 12 | 
            +
                  #   end
         | 
| 13 | 
            +
                  #
         | 
| 14 | 
            +
                  #   describe MyClass, :focus do
         | 
| 15 | 
            +
                  #   end
         | 
| 16 | 
            +
                  #
         | 
| 17 | 
            +
                  #   fdescribe MyClass do
         | 
| 18 | 
            +
                  #   end
         | 
| 19 | 
            +
                  #
         | 
| 20 | 
            +
                  #   # good
         | 
| 21 | 
            +
                  #   describe MyClass do
         | 
| 22 | 
            +
                  #   end
         | 
| 23 | 
            +
                  class Focus < Cop
         | 
| 24 | 
            +
                    MESSAGE = 'Focused spec found.'.freeze
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    FOCUSABLE_BLOCKS = [
         | 
| 27 | 
            +
                      :example_group, :describe, :context, :xdescribe, :xcontext,
         | 
| 28 | 
            +
                      :it, :example, :specify, :xit, :xexample, :xspecify,
         | 
| 29 | 
            +
                      :feature, :scenario, :xfeature, :xscenario
         | 
| 30 | 
            +
                    ].freeze
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    FOCUSED_BLOCKS = [
         | 
| 33 | 
            +
                      :fdescribe, :fcontext,
         | 
| 34 | 
            +
                      :focus, :fexample, :fit, :fspecify,
         | 
| 35 | 
            +
                      :ffeature, :fscenario
         | 
| 36 | 
            +
                    ].freeze
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    FOCUS_KEY = s(:sym, :focus)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    FOCUS_TRUE_PAIR = s(:pair, FOCUS_KEY, s(:true))
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    def on_send(node)
         | 
| 43 | 
            +
                      _receiver, method_name, *_args = *node
         | 
| 44 | 
            +
                      @focusable_block = FOCUSABLE_BLOCKS.include?(method_name)
         | 
| 45 | 
            +
                      if FOCUSED_BLOCKS.include?(method_name)
         | 
| 46 | 
            +
                        add_offense(node, :expression, MESSAGE)
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      # check for :focus
         | 
| 50 | 
            +
                      return unless @focusable_block
         | 
| 51 | 
            +
                      node.children.any? do |n|
         | 
| 52 | 
            +
                        add_offense(n, :expression, MESSAGE) if n == FOCUS_KEY
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    def on_hash(node)
         | 
| 57 | 
            +
                      return unless @focusable_block
         | 
| 58 | 
            +
                      return if node.children.any? do |n|
         | 
| 59 | 
            +
                        if [FOCUS_TRUE_PAIR].include?(n)
         | 
| 60 | 
            +
                          add_offense(n, :expression, MESSAGE)
         | 
| 61 | 
            +
                        end
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
            end
         | 
| @@ -17,36 +17,37 @@ module RuboCop | |
| 17 17 | 
             
                  #     expect(false).not_to be_true
         | 
| 18 18 | 
             
                  #   end
         | 
| 19 19 | 
             
                  class NotToNot < Cop
         | 
| 20 | 
            -
                     | 
| 20 | 
            +
                    include RuboCop::Cop::ConfigurableEnforcedStyle
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    MSG = 'Prefer `%s` over `%s`'.freeze
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    METHOD_NAMES = [:not_to, :to_not].freeze
         | 
| 21 25 |  | 
| 22 26 | 
             
                    def on_send(node)
         | 
| 23 27 | 
             
                      _receiver, method_name, *_args = *node
         | 
| 24 28 |  | 
| 25 | 
            -
                       | 
| 26 | 
            -
                        add_offense(node, :expression, offense_message)
         | 
| 27 | 
            -
                      end
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                    private
         | 
| 29 | 
            +
                      return unless METHOD_NAMES.include?(method_name)
         | 
| 31 30 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
                       | 
| 34 | 
            -
             | 
| 31 | 
            +
                      return if style == method_name
         | 
| 32 | 
            +
                      add_offense(node, :expression)
         | 
| 33 | 
            +
                    end
         | 
| 35 34 |  | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
                        end
         | 
| 35 | 
            +
                    def message(node)
         | 
| 36 | 
            +
                      _receiver, method_name, *_args = *node
         | 
| 39 37 |  | 
| 40 | 
            -
             | 
| 38 | 
            +
                      if method_name == :not_to
         | 
| 39 | 
            +
                        format(MSG, 'to_not', 'not_to')
         | 
| 40 | 
            +
                      else
         | 
| 41 | 
            +
                        format(MSG, 'not_to', 'to_not')
         | 
| 41 42 | 
             
                      end
         | 
| 42 43 | 
             
                    end
         | 
| 43 44 |  | 
| 44 | 
            -
                    def  | 
| 45 | 
            -
                       | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
                       | 
| 45 | 
            +
                    def autocorrect(node)
         | 
| 46 | 
            +
                      _receiver, method_name, *_args = *node
         | 
| 47 | 
            +
                      lambda do |corrector|
         | 
| 48 | 
            +
                        corrector.replace(node.loc.selector,
         | 
| 49 | 
            +
                                          method_name == :not_to ? 'to_not' : 'not_to')
         | 
| 50 | 
            +
                      end
         | 
| 50 51 | 
             
                    end
         | 
| 51 52 | 
             
                  end
         | 
| 52 53 | 
             
                end
         | 
| @@ -19,14 +19,24 @@ module RuboCop | |
| 19 19 | 
             
                  #   end
         | 
| 20 20 | 
             
                  class VerifiedDoubles < Cop
         | 
| 21 21 | 
             
                    MSG = 'Prefer using verifying doubles over normal doubles.'.freeze
         | 
| 22 | 
            +
                    DOUBLE_TYPES = [:double, :spy].freeze
         | 
| 22 23 |  | 
| 23 24 | 
             
                    def on_send(node)
         | 
| 24 | 
            -
                      _receiver, method_name, * | 
| 25 | 
            -
                       | 
| 25 | 
            +
                      _receiver, method_name, *args = *node
         | 
| 26 | 
            +
                      name, *_stubs = *args
         | 
| 27 | 
            +
                      return unless DOUBLE_TYPES.include?(method_name)
         | 
| 28 | 
            +
                      return if name.nil?
         | 
| 29 | 
            +
                      return if name_is_symbol?(name) && cop_config['IgnoreSymbolicNames']
         | 
| 26 30 | 
             
                      add_offense(node,
         | 
| 27 31 | 
             
                                  :expression,
         | 
| 28 32 | 
             
                                  format(MSG, node.loc.expression.source))
         | 
| 29 33 | 
             
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    private
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def name_is_symbol?(name)
         | 
| 38 | 
            +
                      name.children.first.is_a? Symbol
         | 
| 39 | 
            +
                    end
         | 
| 30 40 | 
             
                  end
         | 
| 31 41 | 
             
                end
         | 
| 32 42 | 
             
              end
         | 
    
        data/rubocop-rspec.gemspec
    CHANGED
    
    | @@ -30,7 +30,7 @@ Gem::Specification.new do |spec| | |
| 30 30 | 
             
              spec.test_files = spec.files.grep(%r{^spec/})
         | 
| 31 31 | 
             
              spec.extra_rdoc_files = ['MIT-LICENSE.md', 'README.md']
         | 
| 32 32 |  | 
| 33 | 
            -
              spec.add_runtime_dependency 'rubocop', '0. | 
| 33 | 
            +
              spec.add_runtime_dependency 'rubocop', '>= 0.40.0'
         | 
| 34 34 |  | 
| 35 35 | 
             
              spec.add_development_dependency 'rake'
         | 
| 36 36 | 
             
              spec.add_development_dependency 'rspec', '>= 3.4'
         | 
| @@ -4,9 +4,14 @@ describe RuboCop::Cop::RSpec::AnyInstance do | |
| 4 4 | 
             
              subject(:cop) { described_class.new }
         | 
| 5 5 |  | 
| 6 6 | 
             
              it 'finds `allow_any_instance_of` instead of an instance double' do
         | 
| 7 | 
            -
                inspect_source( | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 7 | 
            +
                inspect_source(
         | 
| 8 | 
            +
                  cop,
         | 
| 9 | 
            +
                  [
         | 
| 10 | 
            +
                    'before do',
         | 
| 11 | 
            +
                    '  allow_any_instance_of(Object).to receive(:foo)',
         | 
| 12 | 
            +
                    'end'
         | 
| 13 | 
            +
                  ]
         | 
| 14 | 
            +
                )
         | 
| 10 15 | 
             
                expect(cop.messages)
         | 
| 11 16 | 
             
                  .to eq(['Avoid stubbing using `allow_any_instance_of`'])
         | 
| 12 17 | 
             
                expect(cop.highlights).to eq(['allow_any_instance_of(Object)'])
         | 
| @@ -14,9 +19,14 @@ describe RuboCop::Cop::RSpec::AnyInstance do | |
| 14 19 | 
             
              end
         | 
| 15 20 |  | 
| 16 21 | 
             
              it 'finds `expect_any_instance_of` instead of an instance double' do
         | 
| 17 | 
            -
                inspect_source( | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 22 | 
            +
                inspect_source(
         | 
| 23 | 
            +
                  cop,
         | 
| 24 | 
            +
                  [
         | 
| 25 | 
            +
                    'before do',
         | 
| 26 | 
            +
                    '  expect_any_instance_of(Object).to receive(:foo)',
         | 
| 27 | 
            +
                    'end'
         | 
| 28 | 
            +
                  ]
         | 
| 29 | 
            +
                )
         | 
| 20 30 | 
             
                expect(cop.messages)
         | 
| 21 31 | 
             
                  .to eq(['Avoid stubbing using `expect_any_instance_of`'])
         | 
| 22 32 | 
             
                expect(cop.highlights).to eq(['expect_any_instance_of(Object)'])
         | 
| @@ -24,9 +34,14 @@ describe RuboCop::Cop::RSpec::AnyInstance do | |
| 24 34 | 
             
              end
         | 
| 25 35 |  | 
| 26 36 | 
             
              it 'finds old `any_instance` syntax instead of an instance double' do
         | 
| 27 | 
            -
                inspect_source( | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 37 | 
            +
                inspect_source(
         | 
| 38 | 
            +
                  cop,
         | 
| 39 | 
            +
                  [
         | 
| 40 | 
            +
                    'before do',
         | 
| 41 | 
            +
                    '  Object.any_instance.should_receive(:foo)',
         | 
| 42 | 
            +
                    'end'
         | 
| 43 | 
            +
                  ]
         | 
| 44 | 
            +
                )
         | 
| 30 45 | 
             
                expect(cop.messages)
         | 
| 31 46 | 
             
                  .to eq(['Avoid stubbing using `any_instance`'])
         | 
| 32 47 | 
             
                expect(cop.highlights).to eq(['Object.any_instance'])
         |