rubocop-rspec 1.25.1 → 1.26.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 +7 -0
 - data/README.md +43 -6
 - data/config/default.yml +5 -0
 - data/lib/rubocop/cop/rspec/align_left_let_brace.rb +2 -0
 - data/lib/rubocop/cop/rspec/align_right_let_brace.rb +2 -0
 - data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +14 -3
 - data/lib/rubocop/cop/rspec/describe_class.rb +1 -3
 - data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +25 -8
 - data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +1 -1
 - data/lib/rubocop/cop/rspec/instance_spy.rb +1 -3
 - data/lib/rubocop/cop/rspec/leading_subject.rb +1 -1
 - data/lib/rubocop/cop/rspec/let_before_examples.rb +2 -1
 - data/lib/rubocop/cop/rspec/message_chain.rb +3 -1
 - data/lib/rubocop/cop/rspec/named_subject.rb +1 -11
 - data/lib/rubocop/cop/rspec/overwriting_setup.rb +12 -6
 - data/lib/rubocop/cop/rspec/pending.rb +0 -3
 - data/lib/rubocop/cop/rspec/receive_counts.rb +86 -0
 - data/lib/rubocop/cop/rspec/scattered_let.rb +1 -1
 - data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +1 -1
 - data/lib/rubocop/cop/rspec_cops.rb +1 -0
 - data/lib/rubocop/rspec/align_let_brace.rb +1 -1
 - data/lib/rubocop/rspec/example_group.rb +5 -7
 - data/lib/rubocop/rspec/language.rb +1 -5
 - data/lib/rubocop/rspec/version.rb +1 -1
 - data/rubocop-rspec.gemspec +2 -2
 - data/spec/rubocop/cop/rspec/align_left_let_brace_spec.rb +4 -0
 - data/spec/rubocop/cop/rspec/align_right_let_brace_spec.rb +4 -0
 - data/spec/rubocop/cop/rspec/capybara/feature_methods_spec.rb +9 -0
 - data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +14 -0
 - data/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb +49 -0
 - data/spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb +21 -1
 - data/spec/rubocop/cop/rspec/overwriting_setup_spec.rb +22 -0
 - data/spec/rubocop/cop/rspec/receive_counts_spec.rb +88 -0
 - data/spec/rubocop/rspec/language/selector_set_spec.rb +4 -2
 - metadata +7 -4
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 25c78adb48d8a15bb6229d1d8140abcd3f2e455c846288276ad01cedba024b4a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 0e2fbf154570fca1aaf0a32cf7866902424bab10da2854038f5674c8664a2d11
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 7cc9ec95f341241d6c02083673e09ebd861929d846baae085c927a185998da95f573a18f0e7f3b9e7cdaba7f62812d7b80338534742fb2bde205df2fe29e0f3b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 891e9714f685e8a3b1bee0ef80395cc11fe87eccb3226cd1bef201a90379e4424cbc5bd937cc632ba11efb7463f0654d756450e4ba44556e93dde7ef0838ab1a
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -2,6 +2,13 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            ## Master (Unreleased)
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
            ## 1.26.0 (2018-06-06)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            * Fix false positive in `RSpec/EmptyExampleGroup` cop when methods named like a RSpec method are used.  ([@Darhazer][])
         
     | 
| 
      
 8 
     | 
    
         
            +
            * Fix `Capybara/FeatureMethods` not working when there is require before the spec. ([@Darhazer][])
         
     | 
| 
      
 9 
     | 
    
         
            +
            * Fix `RSpec/EmptyLineAfterFinalLet`: allow a comment to be placed after latest let, requiring empty line after the comment. ([@Darhazer][])
         
     | 
| 
      
 10 
     | 
    
         
            +
            * Add `RSpec/ReceiveCounts` cop to enforce usage of :once and :twice matchers. ([@Darhazer][])
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       5 
12 
     | 
    
         
             
            ## 1.25.1 (2018-04-10)
         
     | 
| 
       6 
13 
     | 
    
         | 
| 
       7 
14 
     | 
    
         
             
            * Fix false positive in `RSpec/Pending` cop when pending is used as a method name.  ([@Darhazer][])
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -2,14 +2,13 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            [](https://gitter.im/rubocop-rspec/Lobby)
         
     | 
| 
       4 
4 
     | 
    
         
             
            [](https://rubygems.org/gems/rubocop-rspec)
         
     | 
| 
       5 
     | 
    
         
            -
            [](https://circleci.com/gh/rubocop-hq/rubocop-rspec)
         
     | 
| 
      
 6 
     | 
    
         
            +
            [](https://codeclimate.com/github/rubocop-hq/rubocop-rspec/test_coverage)
         
     | 
| 
      
 7 
     | 
    
         
            +
            [](https://codeclimate.com/github/rubocop-hq/rubocop-rspec/maintainability)
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            RSpec-specific analysis for your projects, as an extension to
         
     | 
| 
       10 
10 
     | 
    
         
             
            [RuboCop](https://github.com/bbatsov/rubocop).
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
12 
     | 
    
         
             
            ## Installation
         
     | 
| 
       14 
13 
     | 
    
         | 
| 
       15 
14 
     | 
    
         
             
            Just install the `rubocop-rspec` gem
         
     | 
| 
         @@ -24,7 +23,6 @@ or if you use bundler put this in your `Gemfile` 
     | 
|
| 
       24 
23 
     | 
    
         
             
            gem 'rubocop-rspec'
         
     | 
| 
       25 
24 
     | 
    
         
             
            ```
         
     | 
| 
       26 
25 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
26 
     | 
    
         
             
            ## Usage
         
     | 
| 
       29 
27 
     | 
    
         | 
| 
       30 
28 
     | 
    
         
             
            You need to tell RuboCop to load the RSpec extension. There are three
         
     | 
| 
         @@ -98,10 +96,49 @@ RSpec/FilePath: 
     | 
|
| 
       98 
96 
     | 
    
         
             
                - spec/my_poorly_named_spec_file.rb
         
     | 
| 
       99 
97 
     | 
    
         
             
            ```
         
     | 
| 
       100 
98 
     | 
    
         | 
| 
      
 99 
     | 
    
         
            +
            ## Non-goals of RuboCop RSpec
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
            ### Enforcing `should` vs. `expect` syntax
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            Enforcing
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 106 
     | 
    
         
            +
            expect(calculator.compute(line_item)).to eq(5)
         
     | 
| 
      
 107 
     | 
    
         
            +
            ```
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            over
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 112 
     | 
    
         
            +
            calculator.compute(line_item).should == 5
         
     | 
| 
      
 113 
     | 
    
         
            +
            ```
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            is a feature of RSpec itself – you can read about it in the [RSpec Documentation](https://relishapp.com/rspec/rspec-expectations/docs/syntax-configuration#disable-should-syntax)
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            ### Enforcing an explicit RSpec receiver for top-level methods (disabling monkey patching)
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            Enforcing
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 122 
     | 
    
         
            +
            Rspec.describe MyClass do
         
     | 
| 
      
 123 
     | 
    
         
            +
              ...
         
     | 
| 
      
 124 
     | 
    
         
            +
            end
         
     | 
| 
      
 125 
     | 
    
         
            +
            ```
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
            over
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 130 
     | 
    
         
            +
            describe MyClass do
         
     | 
| 
      
 131 
     | 
    
         
            +
              ...
         
     | 
| 
      
 132 
     | 
    
         
            +
            end
         
     | 
| 
      
 133 
     | 
    
         
            +
            ```
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
            can be achieved using RSpec's `disable_monkey_patching!` method, which you can read more about in the [RSpec Documentation](https://relishapp.com/rspec/rspec-core/v/3-7/docs/configuration/zero-monkey-patching-mode#monkey-patched-methods-are-undefined-with-%60disable-monkey-patching!%60). This will also prevent `should` from being defined on every object in your system.
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            Before disabling `should` you will need all your specs to use the `expect` syntax. You can use [Transpec](http://yujinakayama.me/transpec/), which will do the conversion for you.
         
     | 
| 
       101 
138 
     | 
    
         | 
| 
       102 
139 
     | 
    
         
             
            ## Contributing
         
     | 
| 
       103 
140 
     | 
    
         | 
| 
       104 
     | 
    
         
            -
            Checkout the [contribution guidelines](.github/CONTRIBUTING.md)
         
     | 
| 
      
 141 
     | 
    
         
            +
            Checkout the [contribution guidelines](.github/CONTRIBUTING.md).
         
     | 
| 
       105 
142 
     | 
    
         | 
| 
       106 
143 
     | 
    
         
             
            ## License
         
     | 
| 
       107 
144 
     | 
    
         | 
    
        data/config/default.yml
    CHANGED
    
    | 
         @@ -299,6 +299,11 @@ RSpec/Pending: 
     | 
|
| 
       299 
299 
     | 
    
         
             
              Description: Checks for any pending or skipped examples.
         
     | 
| 
       300 
300 
     | 
    
         
             
              StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending
         
     | 
| 
       301 
301 
     | 
    
         | 
| 
      
 302 
     | 
    
         
            +
            RSpec/ReceiveCounts:
         
     | 
| 
      
 303 
     | 
    
         
            +
              Enabled: true
         
     | 
| 
      
 304 
     | 
    
         
            +
              Description: Check for `once` and `twice` receive counts matchers usage.
         
     | 
| 
      
 305 
     | 
    
         
            +
              StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
       302 
307 
     | 
    
         
             
            RSpec/RepeatedDescription:
         
     | 
| 
       303 
308 
     | 
    
         
             
              Enabled: true
         
     | 
| 
       304 
309 
     | 
    
         
             
              Description: Check for repeated description strings in example groups.
         
     | 
| 
         @@ -66,7 +66,7 @@ module RuboCop 
     | 
|
| 
       66 
66 
     | 
    
         
             
                      PATTERN
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
68 
     | 
    
         
             
                      def on_block(node)
         
     | 
| 
       69 
     | 
    
         
            -
                        return unless  
     | 
| 
      
 69 
     | 
    
         
            +
                        return unless inside_spec?(node)
         
     | 
| 
       70 
70 
     | 
    
         | 
| 
       71 
71 
     | 
    
         
             
                        feature_method(node) do |send_node, match|
         
     | 
| 
       72 
72 
     | 
    
         
             
                          next if enabled?(match)
         
     | 
| 
         @@ -87,8 +87,19 @@ module RuboCop 
     | 
|
| 
       87 
87 
     | 
    
         | 
| 
       88 
88 
     | 
    
         
             
                      private
         
     | 
| 
       89 
89 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
                      def  
     | 
| 
       91 
     | 
    
         
            -
                         
     | 
| 
      
 90 
     | 
    
         
            +
                      def inside_spec?(node)
         
     | 
| 
      
 91 
     | 
    
         
            +
                        return spec?(node) if root_node?(node)
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                        root = node.ancestors.find { |parent| root_node?(parent) }
         
     | 
| 
      
 94 
     | 
    
         
            +
                        spec?(root)
         
     | 
| 
      
 95 
     | 
    
         
            +
                      end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      def root_node?(node)
         
     | 
| 
      
 98 
     | 
    
         
            +
                        node.parent.nil? || root_with_siblings?(node.parent)
         
     | 
| 
      
 99 
     | 
    
         
            +
                      end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                      def root_with_siblings?(node)
         
     | 
| 
      
 102 
     | 
    
         
            +
                        node.begin_type? && node.parent.nil?
         
     | 
| 
       92 
103 
     | 
    
         
             
                      end
         
     | 
| 
       93 
104 
     | 
    
         | 
| 
       94 
105 
     | 
    
         
             
                      def enabled?(method_name)
         
     | 
| 
         @@ -39,9 +39,7 @@ module RuboCop 
     | 
|
| 
       39 
39 
     | 
    
         
             
                        (sym {:request :feature :system :routing :view}))
         
     | 
| 
       40 
40 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                    def_node_matcher :shared_group?,  
     | 
| 
       43 
     | 
    
         
            -
                      (block (send {(const nil? :RSpec) nil?} #{SharedGroups::ALL.node_pattern_union} ...) ...)
         
     | 
| 
       44 
     | 
    
         
            -
                    PATTERN
         
     | 
| 
      
 42 
     | 
    
         
            +
                    def_node_matcher :shared_group?, SharedGroups::ALL.block_pattern
         
     | 
| 
       45 
43 
     | 
    
         | 
| 
       46 
44 
     | 
    
         
             
                    def on_top_level_describe(node, args)
         
     | 
| 
       47 
45 
     | 
    
         
             
                      return if shared_group?(root_node)
         
     | 
| 
         @@ -17,9 +17,11 @@ module RuboCop 
     | 
|
| 
       17 
17 
     | 
    
         
             
                  #
         
     | 
| 
       18 
18 
     | 
    
         
             
                  #   it { does_something }
         
     | 
| 
       19 
19 
     | 
    
         
             
                  class EmptyLineAfterFinalLet < Cop
         
     | 
| 
      
 20 
     | 
    
         
            +
                    include RangeHelp
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
       20 
22 
     | 
    
         
             
                    MSG = 'Add an empty line after the last `let` block.'.freeze
         
     | 
| 
       21 
23 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                    def_node_matcher :let?,  
     | 
| 
      
 24 
     | 
    
         
            +
                    def_node_matcher :let?, Helpers::ALL.block_pattern
         
     | 
| 
       23 
25 
     | 
    
         | 
| 
       24 
26 
     | 
    
         
             
                    def on_block(node)
         
     | 
| 
       25 
27 
     | 
    
         
             
                      return unless example_group_with_body?(node)
         
     | 
| 
         @@ -29,24 +31,28 @@ module RuboCop 
     | 
|
| 
       29 
31 
     | 
    
         
             
                      return if latest_let.nil?
         
     | 
| 
       30 
32 
     | 
    
         
             
                      return if latest_let.equal?(node.body.children.last)
         
     | 
| 
       31 
33 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                      no_new_line_after(latest_let) do
         
     | 
| 
       33 
     | 
    
         
            -
                        add_offense(latest_let, location:  
     | 
| 
      
 34 
     | 
    
         
            +
                      no_new_line_after(latest_let) do |location|
         
     | 
| 
      
 35 
     | 
    
         
            +
                        add_offense(latest_let, location: location)
         
     | 
| 
       34 
36 
     | 
    
         
             
                      end
         
     | 
| 
       35 
37 
     | 
    
         
             
                    end
         
     | 
| 
       36 
38 
     | 
    
         | 
| 
       37 
39 
     | 
    
         
             
                    def autocorrect(node)
         
     | 
| 
       38 
     | 
    
         
            -
                       
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 40 
     | 
    
         
            +
                      lambda do |corrector|
         
     | 
| 
      
 41 
     | 
    
         
            +
                        no_new_line_after(node) do |location|
         
     | 
| 
      
 42 
     | 
    
         
            +
                          corrector.insert_after(location.end, "\n")
         
     | 
| 
      
 43 
     | 
    
         
            +
                        end
         
     | 
| 
      
 44 
     | 
    
         
            +
                      end
         
     | 
| 
       40 
45 
     | 
    
         
             
                    end
         
     | 
| 
       41 
46 
     | 
    
         | 
| 
       42 
47 
     | 
    
         
             
                    private
         
     | 
| 
       43 
48 
     | 
    
         | 
| 
       44 
49 
     | 
    
         
             
                    def no_new_line_after(node)
         
     | 
| 
       45 
50 
     | 
    
         
             
                      loc = last_node_loc(node)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      line = loc.line
         
     | 
| 
      
 52 
     | 
    
         
            +
                      line += 1 while comment_line?(processed_source[line])
         
     | 
| 
       46 
53 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
                       
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                      yield unless next_line.blank?
         
     | 
| 
      
 54 
     | 
    
         
            +
                      return if processed_source[line].blank?
         
     | 
| 
      
 55 
     | 
    
         
            +
                      yield offending_loc(node, line)
         
     | 
| 
       50 
56 
     | 
    
         
             
                    end
         
     | 
| 
       51 
57 
     | 
    
         | 
| 
       52 
58 
     | 
    
         
             
                    def last_node_loc(node)
         
     | 
| 
         @@ -62,6 +68,17 @@ module RuboCop 
     | 
|
| 
       62 
68 
     | 
    
         | 
| 
       63 
69 
     | 
    
         
             
                      node.each_child_node { |child| heredoc_line(child, &block) }
         
     | 
| 
       64 
70 
     | 
    
         
             
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    def offending_loc(node, last_line)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      offending_line = processed_source[last_line - 1]
         
     | 
| 
      
 74 
     | 
    
         
            +
                      if comment_line?(offending_line)
         
     | 
| 
      
 75 
     | 
    
         
            +
                        start = offending_line.index('#')
         
     | 
| 
      
 76 
     | 
    
         
            +
                        length = offending_line.length - start
         
     | 
| 
      
 77 
     | 
    
         
            +
                        source_range(processed_source.buffer, last_line, start, length)
         
     | 
| 
      
 78 
     | 
    
         
            +
                      else
         
     | 
| 
      
 79 
     | 
    
         
            +
                        node.loc.expression
         
     | 
| 
      
 80 
     | 
    
         
            +
                      end
         
     | 
| 
      
 81 
     | 
    
         
            +
                    end
         
     | 
| 
       65 
82 
     | 
    
         
             
                  end
         
     | 
| 
       66 
83 
     | 
    
         
             
                end
         
     | 
| 
       67 
84 
     | 
    
         
             
              end
         
     | 
| 
         @@ -17,7 +17,7 @@ module RuboCop 
     | 
|
| 
       17 
17 
     | 
    
         
             
                  class EmptyLineAfterSubject < Cop
         
     | 
| 
       18 
18 
     | 
    
         
             
                    MSG = 'Add empty line after `subject`.'.freeze
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                    def_node_matcher :subject?,  
     | 
| 
      
 20 
     | 
    
         
            +
                    def_node_matcher :subject?, Subject::ALL.block_pattern
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                    def on_block(node)
         
     | 
| 
       23 
23 
     | 
    
         
             
                      return unless subject?(node) && !in_spec_block?(node)
         
     | 
| 
         @@ -22,9 +22,7 @@ module RuboCop 
     | 
|
| 
       22 
22 
     | 
    
         
             
                    MSG = 'Use `instance_spy` when you check your double '\
         
     | 
| 
       23 
23 
     | 
    
         
             
                          'with `have_received`.'.freeze
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                     
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                    def_node_matcher :example?, "(block $(send nil? #{EXAMPLES}) ...)"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    def_node_matcher :example?, Examples::ALL.block_pattern
         
     | 
| 
       28 
26 
     | 
    
         | 
| 
       29 
27 
     | 
    
         
             
                    def_node_search :null_double, <<-PATTERN
         
     | 
| 
       30 
28 
     | 
    
         
             
                      (lvasgn $_
         
     | 
| 
         @@ -31,7 +31,7 @@ module RuboCop 
     | 
|
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
                    MSG = 'Declare `subject` above any other `let` declarations.'.freeze
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                    def_node_matcher :subject?,  
     | 
| 
      
 34 
     | 
    
         
            +
                    def_node_matcher :subject?, Subject::ALL.block_pattern
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
36 
     | 
    
         
             
                    def on_block(node)
         
     | 
| 
       37 
37 
     | 
    
         
             
                      return unless subject?(node) && !in_spec_block?(node)
         
     | 
| 
         @@ -35,7 +35,8 @@ module RuboCop 
     | 
|
| 
       35 
35 
     | 
    
         | 
| 
       36 
36 
     | 
    
         
             
                    MSG = 'Move `let` before the examples in the group.'.freeze
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
                    def_node_matcher :let?,  
     | 
| 
      
 38 
     | 
    
         
            +
                    def_node_matcher :let?, Helpers::ALL.block_pattern
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
       39 
40 
     | 
    
         
             
                    def_node_matcher :example_or_group?, <<-PATTERN
         
     | 
| 
       40 
41 
     | 
    
         
             
                      {
         
     | 
| 
       41 
42 
     | 
    
         
             
                        #{(Examples::ALL + ExampleGroups::ALL).block_pattern}
         
     | 
| 
         @@ -14,7 +14,9 @@ module RuboCop 
     | 
|
| 
       14 
14 
     | 
    
         
             
                  class MessageChain < Cop
         
     | 
| 
       15 
15 
     | 
    
         
             
                    MSG = 'Avoid stubbing using `%<method>s`.'.freeze
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                    def_node_matcher :message_chain,  
     | 
| 
      
 17 
     | 
    
         
            +
                    def_node_matcher :message_chain, <<-PATTERN
         
     | 
| 
      
 18 
     | 
    
         
            +
                      (send _ {:receive_message_chain :stub_chain} ...)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
       19 
21 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       20 
22 
     | 
    
         
             
                      message_chain(node) { add_offense(node, location: :selector) }
         
     | 
| 
         @@ -48,7 +48,7 @@ module RuboCop 
     | 
|
| 
       48 
48 
     | 
    
         
             
                      }
         
     | 
| 
       49 
49 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
                     
     | 
| 
      
 51 
     | 
    
         
            +
                    def_node_search :subject_usage, '$(send nil? :subject)'
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
53 
     | 
    
         
             
                    def on_block(node)
         
     | 
| 
       54 
54 
     | 
    
         
             
                      return unless rspec_block?(node)
         
     | 
| 
         @@ -57,16 +57,6 @@ module RuboCop 
     | 
|
| 
       57 
57 
     | 
    
         
             
                        add_offense(subject_node, location: :selector)
         
     | 
| 
       58 
58 
     | 
    
         
             
                      end
         
     | 
| 
       59 
59 
     | 
    
         
             
                    end
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                    private
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                    def subject_usage(node, &block)
         
     | 
| 
       64 
     | 
    
         
            -
                      unnamed_subject(node, &block)
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                      node.each_child_node do |child|
         
     | 
| 
       67 
     | 
    
         
            -
                        subject_usage(child, &block)
         
     | 
| 
       68 
     | 
    
         
            -
                      end
         
     | 
| 
       69 
     | 
    
         
            -
                    end
         
     | 
| 
       70 
60 
     | 
    
         
             
                  end
         
     | 
| 
       71 
61 
     | 
    
         
             
                end
         
     | 
| 
       72 
62 
     | 
    
         
             
              end
         
     | 
| 
         @@ -22,11 +22,11 @@ module RuboCop 
     | 
|
| 
       22 
22 
     | 
    
         
             
                  #   let(:baz) { baz }
         
     | 
| 
       23 
23 
     | 
    
         
             
                  #   let!(:other) { other }
         
     | 
| 
       24 
24 
     | 
    
         
             
                  class OverwritingSetup < Cop
         
     | 
| 
      
 25 
     | 
    
         
            +
                    include RuboCop::RSpec::Util
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       25 
27 
     | 
    
         
             
                    MSG = '`%<name>s` is already defined.'.freeze
         
     | 
| 
       26 
28 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                    def_node_matcher :setup?,  
     | 
| 
       28 
     | 
    
         
            -
                      (block (send nil? {:let :let! :subject} (sym $_)) ...)
         
     | 
| 
       29 
     | 
    
         
            -
                    PATTERN
         
     | 
| 
      
 29 
     | 
    
         
            +
                    def_node_matcher :setup?, (Helpers::ALL + Subject::ALL).block_pattern
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
                    def on_block(node)
         
     | 
| 
       32 
32 
     | 
    
         
             
                      return unless example_group_with_body?(node)
         
     | 
| 
         @@ -45,9 +45,15 @@ module RuboCop 
     | 
|
| 
       45 
45 
     | 
    
         
             
                    def find_duplicates(node)
         
     | 
| 
       46 
46 
     | 
    
         
             
                      setup_expressions = Set.new
         
     | 
| 
       47 
47 
     | 
    
         
             
                      node.each_child_node do |child|
         
     | 
| 
       48 
     | 
    
         
            -
                        setup?(child) 
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                         
     | 
| 
      
 48 
     | 
    
         
            +
                        next unless setup?(child)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                        name = if child.send_node.arguments?
         
     | 
| 
      
 51 
     | 
    
         
            +
                                 child.send_node.first_argument.value
         
     | 
| 
      
 52 
     | 
    
         
            +
                               else
         
     | 
| 
      
 53 
     | 
    
         
            +
                                 :subject
         
     | 
| 
      
 54 
     | 
    
         
            +
                               end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                        yield child, name unless setup_expressions.add?(name)
         
     | 
| 
       51 
57 
     | 
    
         
             
                      end
         
     | 
| 
       52 
58 
     | 
    
         
             
                    end
         
     | 
| 
       53 
59 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -43,11 +43,8 @@ module RuboCop 
     | 
|
| 
       43 
43 
     | 
    
         | 
| 
       44 
44 
     | 
    
         
             
                    def_node_matcher :pending_block?, PENDING_EXAMPLES.send_pattern
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                    def_node_matcher :rspec?, '(send {(const nil? :RSpec) nil?} ...)'
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
46 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       49 
47 
     | 
    
         
             
                      return unless pending_block?(node) || skipped_from_metadata?(node)
         
     | 
| 
       50 
     | 
    
         
            -
                      return unless rspec?(node)
         
     | 
| 
       51 
48 
     | 
    
         | 
| 
       52 
49 
     | 
    
         
             
                      add_offense(node, location: :expression)
         
     | 
| 
       53 
50 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Cop
         
     | 
| 
      
 3 
     | 
    
         
            +
                module RSpec
         
     | 
| 
      
 4 
     | 
    
         
            +
                  # Check for `once` and `twice` receive counts matchers usage.
         
     | 
| 
      
 5 
     | 
    
         
            +
                  #
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #     # bad
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).exactly(1).times
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).exactly(2).times
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_least(1).times
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_least(2).times
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_most(1).times
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_most(2).times
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #     # good
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).once
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).twice
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_least(:once)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_least(:twice)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_most(:once)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #     expect(foo).to receive(:bar).at_most(:twice).times
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #
         
     | 
| 
      
 24 
     | 
    
         
            +
                  class ReceiveCounts < Cop
         
     | 
| 
      
 25 
     | 
    
         
            +
                    include RangeHelp
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    MSG = 'Use `%<alternative>s` instead of `%<original>s`.'.freeze
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    def_node_matcher :receive_counts, <<-PATTERN
         
     | 
| 
      
 30 
     | 
    
         
            +
                      (send $(send _ {:exactly :at_least :at_most} (int {1 2})) :times)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    def on_send(node)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      receive_counts(node) do |offending_node|
         
     | 
| 
      
 35 
     | 
    
         
            +
                        offending_range = range(node, offending_node)
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                        add_offense(
         
     | 
| 
      
 38 
     | 
    
         
            +
                          offending_node,
         
     | 
| 
      
 39 
     | 
    
         
            +
                          message: message_for(offending_node, offending_range.source),
         
     | 
| 
      
 40 
     | 
    
         
            +
                          location: offending_range
         
     | 
| 
      
 41 
     | 
    
         
            +
                        )
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    def autocorrect(node)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      lambda do |corrector|
         
     | 
| 
      
 47 
     | 
    
         
            +
                        replacement = matcher_for(
         
     | 
| 
      
 48 
     | 
    
         
            +
                          node.method_name,
         
     | 
| 
      
 49 
     | 
    
         
            +
                          node.first_argument.source.to_i
         
     | 
| 
      
 50 
     | 
    
         
            +
                        )
         
     | 
| 
      
 51 
     | 
    
         
            +
                        corrector.replace(
         
     | 
| 
      
 52 
     | 
    
         
            +
                          range(node.parent, node),
         
     | 
| 
      
 53 
     | 
    
         
            +
                          replacement
         
     | 
| 
      
 54 
     | 
    
         
            +
                        )
         
     | 
| 
      
 55 
     | 
    
         
            +
                      end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    private
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    def message_for(node, source)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      alternative = matcher_for(
         
     | 
| 
      
 62 
     | 
    
         
            +
                        node.method_name,
         
     | 
| 
      
 63 
     | 
    
         
            +
                        node.first_argument.source.to_i
         
     | 
| 
      
 64 
     | 
    
         
            +
                      )
         
     | 
| 
      
 65 
     | 
    
         
            +
                      format(MSG, alternative: alternative, original: source)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    def matcher_for(method, count)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      matcher = count == 1 ? 'once' : 'twice'
         
     | 
| 
      
 70 
     | 
    
         
            +
                      if method == :exactly
         
     | 
| 
      
 71 
     | 
    
         
            +
                        ".#{matcher}"
         
     | 
| 
      
 72 
     | 
    
         
            +
                      else
         
     | 
| 
      
 73 
     | 
    
         
            +
                        ".#{method}(:#{matcher})"
         
     | 
| 
      
 74 
     | 
    
         
            +
                      end
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                    def range(node, offending_node)
         
     | 
| 
      
 78 
     | 
    
         
            +
                      range_between(
         
     | 
| 
      
 79 
     | 
    
         
            +
                        offending_node.loc.selector.begin_pos - 1, # match the dot as well
         
     | 
| 
      
 80 
     | 
    
         
            +
                        node.loc.expression.end_pos
         
     | 
| 
      
 81 
     | 
    
         
            +
                      )
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -29,7 +29,7 @@ module RuboCop 
     | 
|
| 
       29 
29 
     | 
    
         
             
                  class ScatteredLet < Cop
         
     | 
| 
       30 
30 
     | 
    
         
             
                    MSG = 'Group all let/let! blocks in the example group together.'.freeze
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                    def_node_matcher :let?,  
     | 
| 
      
 32 
     | 
    
         
            +
                    def_node_matcher :let?, Helpers::ALL.block_pattern
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
34 
     | 
    
         
             
                    def on_block(node)
         
     | 
| 
       35 
35 
     | 
    
         
             
                      return unless example_group_with_body?(node)
         
     | 
| 
         @@ -19,7 +19,7 @@ module RuboCop 
     | 
|
| 
       19 
19 
     | 
    
         
             
                          '`%<called>s` with a single argument.'.freeze
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                    def_node_matcher :message_chain, <<-PATTERN
         
     | 
| 
       22 
     | 
    
         
            -
                      (send _  
     | 
| 
      
 22 
     | 
    
         
            +
                      (send _ {:receive_message_chain :stub_chain} $_)
         
     | 
| 
       23 
23 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
                    def_node_matcher :single_key_hash?, '(hash pair)'
         
     | 
| 
         @@ -57,6 +57,7 @@ require_relative 'rspec/not_to_not' 
     | 
|
| 
       57 
57 
     | 
    
         
             
            require_relative 'rspec/overwriting_setup'
         
     | 
| 
       58 
58 
     | 
    
         
             
            require_relative 'rspec/pending'
         
     | 
| 
       59 
59 
     | 
    
         
             
            require_relative 'rspec/predicate_matcher'
         
     | 
| 
      
 60 
     | 
    
         
            +
            require_relative 'rspec/receive_counts'
         
     | 
| 
       60 
61 
     | 
    
         
             
            require_relative 'rspec/repeated_description'
         
     | 
| 
       61 
62 
     | 
    
         
             
            require_relative 'rspec/repeated_example'
         
     | 
| 
       62 
63 
     | 
    
         
             
            require_relative 'rspec/return_from_stub'
         
     | 
| 
         @@ -14,14 +14,12 @@ module RuboCop 
     | 
|
| 
       14 
14 
     | 
    
         
             
                    ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL
         
     | 
| 
       15 
15 
     | 
    
         
             
                  ).block_pattern
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                  # @!method hook(node)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  # @!method hook?(node)
         
     | 
| 
       18 
18 
     | 
    
         
             
                  #
         
     | 
| 
       19 
19 
     | 
    
         
             
                  #   Detect if node is `before`, `after`, `around`
         
     | 
| 
       20 
     | 
    
         
            -
                  def_node_matcher :hook 
     | 
| 
       21 
     | 
    
         
            -
                    (block {$(send nil? #{Hooks::ALL.node_pattern_union} ...)} ...)
         
     | 
| 
       22 
     | 
    
         
            -
                  PATTERN
         
     | 
| 
      
 20 
     | 
    
         
            +
                  def_node_matcher :hook?, Hooks::ALL.block_pattern
         
     | 
| 
       23 
21 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                  def_node_matcher :subject 
     | 
| 
      
 22 
     | 
    
         
            +
                  def_node_matcher :subject?, Subject::ALL.block_pattern
         
     | 
| 
       25 
23 
     | 
    
         | 
| 
       26 
24 
     | 
    
         
             
                  def subjects
         
     | 
| 
       27 
25 
     | 
    
         
             
                    subjects_in_scope(node)
         
     | 
| 
         @@ -46,7 +44,7 @@ module RuboCop 
     | 
|
| 
       46 
44 
     | 
    
         
             
                  def find_subjects(node)
         
     | 
| 
       47 
45 
     | 
    
         
             
                    return [] if scope_change?(node)
         
     | 
| 
       48 
46 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
                    if subject(node)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    if subject?(node)
         
     | 
| 
       50 
48 
     | 
    
         
             
                      [node]
         
     | 
| 
       51 
49 
     | 
    
         
             
                    else
         
     | 
| 
       52 
50 
     | 
    
         
             
                      subjects_in_scope(node)
         
     | 
| 
         @@ -62,7 +60,7 @@ module RuboCop 
     | 
|
| 
       62 
60 
     | 
    
         
             
                  def find_hooks(node)
         
     | 
| 
       63 
61 
     | 
    
         
             
                    return [] if scope_change?(node) || example?(node)
         
     | 
| 
       64 
62 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
                    if hook(node)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    if hook?(node)
         
     | 
| 
       66 
64 
     | 
    
         
             
                      [node]
         
     | 
| 
       67 
65 
     | 
    
         
             
                    else
         
     | 
| 
       68 
66 
     | 
    
         
             
                      hooks_in_scope(node)
         
     | 
| 
         @@ -27,7 +27,7 @@ module RuboCop 
     | 
|
| 
       27 
27 
     | 
    
         
             
                    end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                    def send_pattern
         
     | 
| 
       30 
     | 
    
         
            -
                      "(send  
     | 
| 
      
 30 
     | 
    
         
            +
                      "(send {(const nil? :RSpec) nil?} #{node_pattern_union} ...)"
         
     | 
| 
       31 
31 
     | 
    
         
             
                    end
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                    def node_pattern_union
         
     | 
| 
         @@ -43,10 +43,6 @@ module RuboCop 
     | 
|
| 
       43 
43 
     | 
    
         
             
                    attr_reader :selectors
         
     | 
| 
       44 
44 
     | 
    
         
             
                  end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                  module Matchers
         
     | 
| 
       47 
     | 
    
         
            -
                    MESSAGE_CHAIN = SelectorSet.new(%i[receive_message_chain stub_chain])
         
     | 
| 
       48 
     | 
    
         
            -
                  end
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
46 
     | 
    
         
             
                  module ExampleGroups
         
     | 
| 
       51 
47 
     | 
    
         
             
                    GROUPS  = SelectorSet.new(%i[describe context feature example_group])
         
     | 
| 
       52 
48 
     | 
    
         
             
                    SKIPPED = SelectorSet.new(%i[xdescribe xcontext xfeature])
         
     | 
    
        data/rubocop-rspec.gemspec
    CHANGED
    
    | 
         @@ -8,7 +8,7 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       8 
8 
     | 
    
         
             
                Code style checking for RSpec files.
         
     | 
| 
       9 
9 
     | 
    
         
             
                A plugin for the RuboCop code style enforcing & linting tool.
         
     | 
| 
       10 
10 
     | 
    
         
             
              DESCRIPTION
         
     | 
| 
       11 
     | 
    
         
            -
              spec.homepage = 'https://github.com/rubocop- 
     | 
| 
      
 11 
     | 
    
         
            +
              spec.homepage = 'https://github.com/rubocop-hq/rubocop-rspec'
         
     | 
| 
       12 
12 
     | 
    
         
             
              spec.authors = ['John Backus', 'Ian MacLeod', 'Nils Gemeinhardt']
         
     | 
| 
       13 
13 
     | 
    
         
             
              spec.email = [
         
     | 
| 
       14 
14 
     | 
    
         
             
                'johncbackus@gmail.com',
         
     | 
| 
         @@ -33,7 +33,7 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       33 
33 
     | 
    
         
             
              spec.extra_rdoc_files = ['MIT-LICENSE.md', 'README.md']
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
              spec.metadata = {
         
     | 
| 
       36 
     | 
    
         
            -
                'changelog_uri' => 'https://github.com/rubocop- 
     | 
| 
      
 36 
     | 
    
         
            +
                'changelog_uri' => 'https://github.com/rubocop-hq/rubocop-rspec/blob/master/CHANGELOG.md',
         
     | 
| 
       37 
37 
     | 
    
         
             
                'documentation_uri' => 'https://rubocop-rspec.readthedocs.io/'
         
     | 
| 
       38 
38 
     | 
    
         
             
              }
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
         @@ -76,6 +76,15 @@ RSpec.describe RuboCop::Cop::RSpec::Capybara::FeatureMethods, :config do 
     | 
|
| 
       76 
76 
     | 
    
         
             
                RUBY
         
     | 
| 
       77 
77 
     | 
    
         
             
              end
         
     | 
| 
       78 
78 
     | 
    
         | 
| 
      
 79 
     | 
    
         
            +
              it 'allows includes before the spec' do
         
     | 
| 
      
 80 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  require 'rails_helper'
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  RSpec.feature 'Foo' do; end
         
     | 
| 
      
 84 
     | 
    
         
            +
                        ^^^^^^^ Use `describe` instead of `feature`.
         
     | 
| 
      
 85 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
       79 
88 
     | 
    
         
             
              context 'with configured `EnabledMethods`' do
         
     | 
| 
       80 
89 
     | 
    
         
             
                let(:cop_config) { { 'EnabledMethods' => %w[feature] } }
         
     | 
| 
       81 
90 
     | 
    
         | 
| 
         @@ -49,6 +49,20 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyExampleGroup, :config do 
     | 
|
| 
       49 
49 
     | 
    
         
             
                RUBY
         
     | 
| 
       50 
50 
     | 
    
         
             
              end
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
      
 52 
     | 
    
         
            +
              it 'does not flag methods matching example group names' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                expect_no_offenses(<<-RUBY)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  describe Foo do
         
     | 
| 
      
 55 
     | 
    
         
            +
                    it 'yields a block when given' do
         
     | 
| 
      
 56 
     | 
    
         
            +
                      value = nil
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                      helper.feature('whatevs') { value = 5 }
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                      expect(value).to be 5
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
       52 
66 
     | 
    
         
             
              it 'does not recognize custom include methods by default' do
         
     | 
| 
       53 
67 
     | 
    
         
             
                expect_offense(<<-RUBY)
         
     | 
| 
       54 
68 
     | 
    
         
             
                  describe Foo do
         
     | 
| 
         @@ -38,6 +38,30 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterFinalLet do 
     | 
|
| 
       38 
38 
     | 
    
         
             
                RUBY
         
     | 
| 
       39 
39 
     | 
    
         
             
              end
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
      
 41 
     | 
    
         
            +
              it 'allows comment followed by an empty line after let' do
         
     | 
| 
      
 42 
     | 
    
         
            +
                expect_no_offenses(<<-RUBY)
         
     | 
| 
      
 43 
     | 
    
         
            +
                RSpec.describe User do
         
     | 
| 
      
 44 
     | 
    
         
            +
                  let(:a) { a }
         
     | 
| 
      
 45 
     | 
    
         
            +
                  let(:b) { b }
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # end of setup
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  it { expect(a).to eq(b) }
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              it 'flags missing empty line after the comment that comes after last let' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  RSpec.describe User do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    let(:a) { a }
         
     | 
| 
      
 57 
     | 
    
         
            +
                    let(:b) { b }
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # end of setup
         
     | 
| 
      
 59 
     | 
    
         
            +
                    ^^^^^^^^^^^^^^ Add an empty line after the last `let` block.
         
     | 
| 
      
 60 
     | 
    
         
            +
                    it { expect(a).to eq(b) }
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
       41 
65 
     | 
    
         
             
              it 'ignores empty lines between the lets' do
         
     | 
| 
       42 
66 
     | 
    
         
             
                expect_offense(<<-RUBY)
         
     | 
| 
       43 
67 
     | 
    
         
             
                  RSpec.describe User do
         
     | 
| 
         @@ -136,6 +160,31 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterFinalLet do 
     | 
|
| 
       136 
160 
     | 
    
         
             
              end
         
     | 
| 
       137 
161 
     | 
    
         
             
              RUBY
         
     | 
| 
       138 
162 
     | 
    
         | 
| 
      
 163 
     | 
    
         
            +
              include_examples 'autocorrect',
         
     | 
| 
      
 164 
     | 
    
         
            +
                               bad_example,
         
     | 
| 
      
 165 
     | 
    
         
            +
                               good_example
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
              bad_example = <<-RUBY
         
     | 
| 
      
 168 
     | 
    
         
            +
              RSpec.describe User do
         
     | 
| 
      
 169 
     | 
    
         
            +
                let(:params) { foo }
         
     | 
| 
      
 170 
     | 
    
         
            +
                # a multiline comment marking
         
     | 
| 
      
 171 
     | 
    
         
            +
                # the end of setup
         
     | 
| 
      
 172 
     | 
    
         
            +
                it 'has a new line' do
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
              end
         
     | 
| 
      
 175 
     | 
    
         
            +
              RUBY
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
              good_example = <<-RUBY
         
     | 
| 
      
 178 
     | 
    
         
            +
              RSpec.describe User do
         
     | 
| 
      
 179 
     | 
    
         
            +
                let(:params) { foo }
         
     | 
| 
      
 180 
     | 
    
         
            +
                # a multiline comment marking
         
     | 
| 
      
 181 
     | 
    
         
            +
                # the end of setup
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                it 'has a new line' do
         
     | 
| 
      
 184 
     | 
    
         
            +
                end
         
     | 
| 
      
 185 
     | 
    
         
            +
              end
         
     | 
| 
      
 186 
     | 
    
         
            +
              RUBY
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
       139 
188 
     | 
    
         
             
              include_examples 'autocorrect',
         
     | 
| 
       140 
189 
     | 
    
         
             
                               bad_example,
         
     | 
| 
       141 
190 
     | 
    
         
             
                               good_example
         
     | 
| 
         @@ -13,6 +13,16 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterSubject do 
     | 
|
| 
       13 
13 
     | 
    
         
             
                RUBY
         
     | 
| 
       14 
14 
     | 
    
         
             
              end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
      
 16 
     | 
    
         
            +
              it 'checks for empty line after subject!' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  RSpec.describe User do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    subject! { described_class.new }
         
     | 
| 
      
 20 
     | 
    
         
            +
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add empty line after `subject`.
         
     | 
| 
      
 21 
     | 
    
         
            +
                    let(:params) { foo }
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       16 
26 
     | 
    
         
             
              it 'approves empty line after subject' do
         
     | 
| 
       17 
27 
     | 
    
         
             
                expect_no_offenses(<<-RUBY)
         
     | 
| 
       18 
28 
     | 
    
         
             
                  RSpec.describe User do
         
     | 
| 
         @@ -23,6 +33,16 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterSubject do 
     | 
|
| 
       23 
33 
     | 
    
         
             
                RUBY
         
     | 
| 
       24 
34 
     | 
    
         
             
              end
         
     | 
| 
       25 
35 
     | 
    
         | 
| 
      
 36 
     | 
    
         
            +
              it 'approves empty line after subject!' do
         
     | 
| 
      
 37 
     | 
    
         
            +
                expect_no_offenses(<<-RUBY)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  RSpec.describe User do
         
     | 
| 
      
 39 
     | 
    
         
            +
                    subject! { described_class.new }
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    let(:params) { foo }
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       26 
46 
     | 
    
         
             
              it 'handles subjects in tests' do
         
     | 
| 
       27 
47 
     | 
    
         
             
                expect_no_offenses(<<-RUBY)
         
     | 
| 
       28 
48 
     | 
    
         
             
                  RSpec.describe User do
         
     | 
| 
         @@ -48,7 +68,7 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterSubject do 
     | 
|
| 
       48 
68 
     | 
    
         
             
                RUBY
         
     | 
| 
       49 
69 
     | 
    
         
             
              end
         
     | 
| 
       50 
70 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
              it 'handles  
     | 
| 
      
 71 
     | 
    
         
            +
              it 'handles subject being the latest node' do
         
     | 
| 
       52 
72 
     | 
    
         
             
                expect_no_offenses(<<-RUBY)
         
     | 
| 
       53 
73 
     | 
    
         
             
                  RSpec.describe User do
         
     | 
| 
       54 
74 
     | 
    
         
             
                    subject { described_user }
         
     | 
| 
         @@ -22,6 +22,17 @@ RSpec.describe RuboCop::Cop::RSpec::OverwritingSetup do 
     | 
|
| 
       22 
22 
     | 
    
         
             
                RUBY
         
     | 
| 
       23 
23 
     | 
    
         
             
              end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
      
 25 
     | 
    
         
            +
              it 'works with `subject!` and `let!`' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  RSpec.describe User do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    subject!(:a) { a }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    let!(:a) { b }
         
     | 
| 
      
 31 
     | 
    
         
            +
                    ^^^^^^^^^^^^^^ `a` is already defined.
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       25 
36 
     | 
    
         
             
              it 'finds `let!` overwriting `let`' do
         
     | 
| 
       26 
37 
     | 
    
         
             
                expect_offense(<<-RUBY)
         
     | 
| 
       27 
38 
     | 
    
         
             
                  RSpec.describe User do
         
     | 
| 
         @@ -44,6 +55,17 @@ RSpec.describe RuboCop::Cop::RSpec::OverwritingSetup do 
     | 
|
| 
       44 
55 
     | 
    
         
             
                RUBY
         
     | 
| 
       45 
56 
     | 
    
         
             
              end
         
     | 
| 
       46 
57 
     | 
    
         | 
| 
      
 58 
     | 
    
         
            +
              it 'handles unnamed subjects' do
         
     | 
| 
      
 59 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  RSpec.describe User do
         
     | 
| 
      
 61 
     | 
    
         
            +
                    subject { a }
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    let(:subject) { b }
         
     | 
| 
      
 64 
     | 
    
         
            +
                    ^^^^^^^^^^^^^^^^^^^ `subject` is already defined.
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
       47 
69 
     | 
    
         
             
              it 'does not encounter an error when handling an empty describe' do
         
     | 
| 
       48 
70 
     | 
    
         
             
                expect { inspect_source('RSpec.describe(User) do end', 'a_spec.rb') }
         
     | 
| 
       49 
71 
     | 
    
         
             
                  .not_to raise_error
         
     | 
| 
         @@ -0,0 +1,88 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe RuboCop::Cop::RSpec::ReceiveCounts do
         
     | 
| 
      
 4 
     | 
    
         
            +
              subject(:cop) { described_class.new }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              it 'flags usage of `exactly(1).times`' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  expect(foo).to receive(:bar).exactly(1).times
         
     | 
| 
      
 9 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^ Use `.once` instead of `.exactly(1).times`.
         
     | 
| 
      
 10 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              it 'flags usage of `exactly(2).times`' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  expect(foo).to receive(:bar).exactly(2).times
         
     | 
| 
      
 16 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^ Use `.twice` instead of `.exactly(2).times`.
         
     | 
| 
      
 17 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              it 'allows `exactly(3).times`' do
         
     | 
| 
      
 21 
     | 
    
         
            +
                expect_no_offenses(<<-RUBY)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  expect(foo).to receive(:bar).exactly(3).times
         
     | 
| 
      
 23 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              it 'allows `exactly(n).times`' do
         
     | 
| 
      
 27 
     | 
    
         
            +
                expect_no_offenses(<<-RUBY)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  expect(foo).to receive(:bar).exactly(n).times
         
     | 
| 
      
 29 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              it 'flags usage of `exactly(1).times` after `with`' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  expect(foo).to receive(:bar).with(baz).exactly(1).times
         
     | 
| 
      
 35 
     | 
    
         
            +
                                                        ^^^^^^^^^^^^^^^^^ Use `.once` instead of `.exactly(1).times`.
         
     | 
| 
      
 36 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              it 'flags usage of `exactly(1).times` with return value' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  expect(foo).to receive(:bar).exactly(1).times.and_return(true)
         
     | 
| 
      
 42 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^ Use `.once` instead of `.exactly(1).times`.
         
     | 
| 
      
 43 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              it 'flags usage of `exactly(1).times` with a block' do
         
     | 
| 
      
 47 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  expect(foo).to receive(:bar).exactly(1).times { true }
         
     | 
| 
      
 49 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^ Use `.once` instead of `.exactly(1).times`.
         
     | 
| 
      
 50 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              it 'flags usage of `at_least(1).times`' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  expect(foo).to receive(:bar).at_least(1).times
         
     | 
| 
      
 56 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^^ Use `.at_least(:once)` instead of `.at_least(1).times`.
         
     | 
| 
      
 57 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              it 'flags usage of `at_least(2).times`' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  expect(foo).to receive(:bar).at_least(2).times
         
     | 
| 
      
 63 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^^ Use `.at_least(:twice)` instead of `.at_least(2).times`.
         
     | 
| 
      
 64 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              it 'flags usage of `at_most(1).times`' do
         
     | 
| 
      
 68 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  expect(foo).to receive(:bar).at_most(1).times
         
     | 
| 
      
 70 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^ Use `.at_most(:once)` instead of `.at_most(1).times`.
         
     | 
| 
      
 71 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              it 'flags usage of `at_most(2).times`' do
         
     | 
| 
      
 75 
     | 
    
         
            +
                expect_offense(<<-RUBY)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  expect(foo).to receive(:bar).at_most(2).times
         
     | 
| 
      
 77 
     | 
    
         
            +
                                              ^^^^^^^^^^^^^^^^^ Use `.at_most(:twice)` instead of `.at_most(2).times`.
         
     | 
| 
      
 78 
     | 
    
         
            +
                RUBY
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              include_examples 'autocorrect',
         
     | 
| 
      
 82 
     | 
    
         
            +
                               'expect(foo).to receive(:bar).exactly(1).times { true }',
         
     | 
| 
      
 83 
     | 
    
         
            +
                               'expect(foo).to receive(:bar).once { true }'
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
              include_examples 'autocorrect',
         
     | 
| 
      
 86 
     | 
    
         
            +
                               'expect(foo).to receive(:bar).at_least(2).times { true }',
         
     | 
| 
      
 87 
     | 
    
         
            +
                               'expect(foo).to receive(:bar).at_least(:twice) { true }'
         
     | 
| 
      
 88 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -35,14 +35,16 @@ RSpec.describe RuboCop::RSpec::Language::SelectorSet do 
     | 
|
| 
       35 
35 
     | 
    
         | 
| 
       36 
36 
     | 
    
         
             
              describe '#send_pattern' do
         
     | 
| 
       37 
37 
     | 
    
         
             
                it 'builds a send matching pattern' do
         
     | 
| 
       38 
     | 
    
         
            -
                  expect(selector_set.send_pattern).to eql( 
     | 
| 
      
 38 
     | 
    
         
            +
                  expect(selector_set.send_pattern).to eql(
         
     | 
| 
      
 39 
     | 
    
         
            +
                    '(send {(const nil? :RSpec) nil?} {:foo :bar} ...)'
         
     | 
| 
      
 40 
     | 
    
         
            +
                  )
         
     | 
| 
       39 
41 
     | 
    
         
             
                end
         
     | 
| 
       40 
42 
     | 
    
         
             
              end
         
     | 
| 
       41 
43 
     | 
    
         | 
| 
       42 
44 
     | 
    
         
             
              describe '#block_pattern' do
         
     | 
| 
       43 
45 
     | 
    
         
             
                it 'builds a block matching pattern' do
         
     | 
| 
       44 
46 
     | 
    
         
             
                  expect(selector_set.block_pattern).to eql(
         
     | 
| 
       45 
     | 
    
         
            -
                    '(block (send  
     | 
| 
      
 47 
     | 
    
         
            +
                    '(block (send {(const nil? :RSpec) nil?} {:foo :bar} ...) ...)'
         
     | 
| 
       46 
48 
     | 
    
         
             
                  )
         
     | 
| 
       47 
49 
     | 
    
         
             
                end
         
     | 
| 
       48 
50 
     | 
    
         
             
              end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: rubocop-rspec
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.26.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - John Backus
         
     | 
| 
         @@ -10,7 +10,7 @@ authors: 
     | 
|
| 
       10 
10 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       11 
11 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       12 
12 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       13 
     | 
    
         
            -
            date: 2018- 
     | 
| 
      
 13 
     | 
    
         
            +
            date: 2018-06-06 00:00:00.000000000 Z
         
     | 
| 
       14 
14 
     | 
    
         
             
            dependencies:
         
     | 
| 
       15 
15 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       16 
16 
     | 
    
         
             
              name: rubocop
         
     | 
| 
         @@ -169,6 +169,7 @@ files: 
     | 
|
| 
       169 
169 
     | 
    
         
             
            - lib/rubocop/cop/rspec/pending.rb
         
     | 
| 
       170 
170 
     | 
    
         
             
            - lib/rubocop/cop/rspec/predicate_matcher.rb
         
     | 
| 
       171 
171 
     | 
    
         
             
            - lib/rubocop/cop/rspec/rails/http_status.rb
         
     | 
| 
      
 172 
     | 
    
         
            +
            - lib/rubocop/cop/rspec/receive_counts.rb
         
     | 
| 
       172 
173 
     | 
    
         
             
            - lib/rubocop/cop/rspec/repeated_description.rb
         
     | 
| 
       173 
174 
     | 
    
         
             
            - lib/rubocop/cop/rspec/repeated_example.rb
         
     | 
| 
       174 
175 
     | 
    
         
             
            - lib/rubocop/cop/rspec/return_from_stub.rb
         
     | 
| 
         @@ -256,6 +257,7 @@ files: 
     | 
|
| 
       256 
257 
     | 
    
         
             
            - spec/rubocop/cop/rspec/pending_spec.rb
         
     | 
| 
       257 
258 
     | 
    
         
             
            - spec/rubocop/cop/rspec/predicate_matcher_spec.rb
         
     | 
| 
       258 
259 
     | 
    
         
             
            - spec/rubocop/cop/rspec/rails/http_status_spec.rb
         
     | 
| 
      
 260 
     | 
    
         
            +
            - spec/rubocop/cop/rspec/receive_counts_spec.rb
         
     | 
| 
       259 
261 
     | 
    
         
             
            - spec/rubocop/cop/rspec/repeated_description_spec.rb
         
     | 
| 
       260 
262 
     | 
    
         
             
            - spec/rubocop/cop/rspec/repeated_example_spec.rb
         
     | 
| 
       261 
263 
     | 
    
         
             
            - spec/rubocop/cop/rspec/return_from_stub_spec.rb
         
     | 
| 
         @@ -279,11 +281,11 @@ files: 
     | 
|
| 
       279 
281 
     | 
    
         
             
            - spec/shared/detects_style_behavior.rb
         
     | 
| 
       280 
282 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
       281 
283 
     | 
    
         
             
            - spec/support/expect_offense.rb
         
     | 
| 
       282 
     | 
    
         
            -
            homepage: https://github.com/rubocop- 
     | 
| 
      
 284 
     | 
    
         
            +
            homepage: https://github.com/rubocop-hq/rubocop-rspec
         
     | 
| 
       283 
285 
     | 
    
         
             
            licenses:
         
     | 
| 
       284 
286 
     | 
    
         
             
            - MIT
         
     | 
| 
       285 
287 
     | 
    
         
             
            metadata:
         
     | 
| 
       286 
     | 
    
         
            -
              changelog_uri: https://github.com/rubocop- 
     | 
| 
      
 288 
     | 
    
         
            +
              changelog_uri: https://github.com/rubocop-hq/rubocop-rspec/blob/master/CHANGELOG.md
         
     | 
| 
       287 
289 
     | 
    
         
             
              documentation_uri: https://rubocop-rspec.readthedocs.io/
         
     | 
| 
       288 
290 
     | 
    
         
             
            post_install_message: 
         
     | 
| 
       289 
291 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
         @@ -362,6 +364,7 @@ test_files: 
     | 
|
| 
       362 
364 
     | 
    
         
             
            - spec/rubocop/cop/rspec/pending_spec.rb
         
     | 
| 
       363 
365 
     | 
    
         
             
            - spec/rubocop/cop/rspec/predicate_matcher_spec.rb
         
     | 
| 
       364 
366 
     | 
    
         
             
            - spec/rubocop/cop/rspec/rails/http_status_spec.rb
         
     | 
| 
      
 367 
     | 
    
         
            +
            - spec/rubocop/cop/rspec/receive_counts_spec.rb
         
     | 
| 
       365 
368 
     | 
    
         
             
            - spec/rubocop/cop/rspec/repeated_description_spec.rb
         
     | 
| 
       366 
369 
     | 
    
         
             
            - spec/rubocop/cop/rspec/repeated_example_spec.rb
         
     | 
| 
       367 
370 
     | 
    
         
             
            - spec/rubocop/cop/rspec/return_from_stub_spec.rb
         
     |