pax_global_header00006660000000000000000000000064137017014750014517gustar00rootroot0000000000000052 comment=cd692281c1b3367de4ec54304ef45cc72ff7ef75 rubocop-rspec-1.42.0/000077500000000000000000000000001370170147500143665ustar00rootroot00000000000000rubocop-rspec-1.42.0/.circleci/000077500000000000000000000000001370170147500162215ustar00rootroot00000000000000rubocop-rspec-1.42.0/.circleci/config.yml000066400000000000000000000051731370170147500202170ustar00rootroot00000000000000version: 2.1 jobs: confirm_config_and_documentation: docker: - image: circleci/ruby steps: - checkout - run: bundle install - run: rake confirm_config documentation_syntax_check confirm_documentation rspec: parameters: ruby: type: string docker: - image: circleci/ruby:<> steps: - checkout - run: bundle install - run: rake spec rubocop: parameters: ruby: type: string docker: - image: circleci/ruby:<> steps: - checkout - run: bundle install - run: rake internal_investigation edge-rubocop: docker: - image: circleci/ruby steps: - checkout - run: name: Use latest RuboCop from `master` command: | echo "gem 'rubocop', github: 'rubocop-hq/rubocop'" > Gemfile.local - run: bundle install --no-cache - run: rake spec - run: rake internal_investigation # JRuby jruby: docker: - image: circleci/jruby:9 steps: - checkout - run: sudo apt-get install -y make - run: bundle lock - restore_cache: keys: - bundle-v2-{{ checksum "Gemfile.lock" }} - bundle-v2- - run: bundle install --path vendor/bundle - save_cache: key: bundle-v2-{{ checksum "Gemfile.lock" }} paths: - vendor/bundle - run: rake internal_investigation spec code-climate: docker: - image: circleci/ruby steps: - checkout - run: bundle install - run: name: Setup Code Climate test-reporter command: | curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter chmod +x ./cc-test-reporter - run: name: Run specs command: | ./cc-test-reporter before-build rake coverage ./cc-test-reporter after-build --exit-code $? workflows: version: 2 build: jobs: - confirm_config_and_documentation # Use `requires: [confirm_config_and_documentation]` to trick Circle CI into starting the slow jruby job early. - rspec: requires: [confirm_config_and_documentation] matrix: parameters: ruby: ['2.4', '2.5', '2.6', '2.7'] - rubocop: requires: [confirm_config_and_documentation] matrix: parameters: ruby: ['2.4', '2.5', '2.6', '2.7'] - edge-rubocop: requires: [confirm_config_and_documentation] - jruby - code-climate rubocop-rspec-1.42.0/.gitattributes000066400000000000000000000000311370170147500172530ustar00rootroot00000000000000CHANGELOG.md merge=union rubocop-rspec-1.42.0/.github/000077500000000000000000000000001370170147500157265ustar00rootroot00000000000000rubocop-rspec-1.42.0/.github/CONTRIBUTING.md000066400000000000000000000036131370170147500201620ustar00rootroot00000000000000# Contributing If you encounter problems or have ideas for improvements or new features, please report them to the [issue tracker](https://github.com/rubocop-hq/rubocop-rspec/issues) or submit a pull request. Please, try to follow these guidelines when you do so. ## Issue reporting * Check that the issue has not already been reported. * Check that the issue has not already been fixed in the latest code (a.k.a. `master`). * Check if the issue is a non-goal of RuboCop RSpec. * Be clear, concise, and precise in your description of the problem. * Open an issue with a descriptive title and a summary in grammatically correct, complete sentences. * Report the versions of `rubocop-rspec`, as well as the output of `rubocop -V`. * Include any relevant code to the issue summary. ## Pull requests 1. Fork the project. 2. Create a feature branch. 3. Make sure to add tests. 4. Make sure the test suite passes (run `rake`). 5. Add a [changelog](https://github.com/rubocop-hq/rubocop-rspec/blob/master/CHANGELOG.md) entry. 6. Commit your changes. 7. Push to the branch. 8. Create new Pull Request. ## Creating new cops * Document examples of good and bad code in your cop. * Add an entry to `config/default.yml`. It's an ordered list, so be sure to insert at the appropriate place. * Run `bundle exec rake`. This will verify that the build passes as well as generate documentation and ensure that `config/default.yml` is up to date (don't forget to commit the documentation). * Add tests for as many use cases as you can think of. Always add tests for both bad code that should register an offense and good code that should not. * Common pitfalls: * If your cop inspects code outside of an example, check for false positives when similarly named variables are used inside of the example. * If your cop inspects code inside of an example, check that it works when the example is empty (empty `describe`, `it`, etc.). rubocop-rspec-1.42.0/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000017741370170147500215400ustar00rootroot00000000000000**Replace this text with a summary of the changes in your PR. The more detailed you are, the better.** --- Before submitting the PR make sure the following are checked: * [ ] Feature branch is up-to-date with `master` (if not - rebase it). * [ ] Squashed related commits together. * [ ] Added tests. * [ ] Updated documentation. * [ ] Added an entry to the `CHANGELOG.md` if the new code introduces user-observable changes. * [ ] The build (`bundle exec rake`) passes (be sure to run this locally, since it may produce updated documentation that you will need to commit). If you have created a new cop: * [ ] Added the new cop to `config/default.yml`. * [ ] The cop documents examples of good and bad code. * [ ] The tests assert both that bad code is reported and that good code is not reported. * [ ] Set `VersionAdded` in `default/config.yml` to the next minor version. If you have modified an existing cop's configuration options: * [ ] Set `VersionChanged` in `default/config.yml` to the next major version. rubocop-rspec-1.42.0/.gitignore000066400000000000000000000003111370170147500163510ustar00rootroot00000000000000# rcov generated coverage coverage.data # rdoc generated rdoc # yard generated doc .yardoc # bundler .bundle Gemfile.lock Gemfile.local # jeweler generated pkg /vendor .ruby-gemset .ruby-version rubocop-rspec-1.42.0/.rspec000066400000000000000000000000651370170147500155040ustar00rootroot00000000000000--require spec_helper --color --format documentation rubocop-rspec-1.42.0/.rubocop.yml000066400000000000000000000017001370170147500166360ustar00rootroot00000000000000inherit_from: .rubocop_todo.yml require: - rubocop-rspec - rubocop/cop/internal_affairs AllCops: DisplayCopNames: true TargetRubyVersion: 2.4 Exclude: - 'vendor/**/*' - 'spec/fixtures/**/*' - 'tmp/**/*' - 'spec/smoke_tests/**/*.rb' # See https://github.com/rubocop-hq/rubocop/issues/6410 Layout/HashAlignment: Enabled: false Layout/LineLength: Max: 80 # default: 120 Layout/MultilineMethodCallIndentation: EnforcedStyle: indented Layout/MultilineOperationIndentation: EnforcedStyle: indented Lint/BooleanSymbol: Exclude: - lib/rubocop/cop/rspec/expect_actual.rb - lib/rubocop/cop/rspec/focus.rb Lint/InterpolationCheck: Exclude: - spec/**/*.rb Metrics/BlockLength: Exclude: - rubocop-rspec.gemspec - Rakefile - '**/*.rake' - spec/**/*.rb Naming/FileName: Exclude: - lib/rubocop-rspec.rb RSpec/ExampleLength: Max: 30 RSpec/DescribeClass: Exclude: - spec/project/**/*.rb rubocop-rspec-1.42.0/.rubocop_todo.yml000066400000000000000000000011121370170147500176600ustar00rootroot00000000000000# This configuration was generated by # `rubocop --auto-gen-config` # on 2019-12-12 15:15:34 +0200 using RuboCop version 0.77.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 9 # Cop supports --auto-correct. InternalAffairs/MethodNameEqual: Enabled: false # Offense count: 1 # Configuration parameters: CountComments. Metrics/ClassLength: Max: 106 rubocop-rspec-1.42.0/CHANGELOG.md000066400000000000000000000650051370170147500162050ustar00rootroot00000000000000# Change log ## Master (Unreleased) ## 1.42.0 (2020-07-09) * Update RuboCop dependency to 0.87.0 because of changes to internal APIs. ([@bquorning][], [@Darhazer][]) ## 1.41.0 (2020-07-03) * Extend the list of Rails spec types for `RSpec/DescribeClass`. ([@pirj][]) * Fix `FactoryBot/AttributeDefinedStatically` to allow `#traits_for_enum` without a block. ([@harrylewis][]) * Improve the performance of `FactoryBot/AttributeDefinedStatically`, `RSpec/InstanceVariable`, `RSpec/LetSetup`, `RSpec/NestedGroups` and `RSpec/ReturnFromStub`. ([@andrykonchin][]) ## 1.40.0 (2020-06-11) * Add new `RSpec/VariableName` cop. ([@tejasbubane][]) * Add new `RSpec/VariableDefinition` cop. ([@tejasbubane][]) * Expand `Capybara/VisibilityMatcher` to support more than just `have_selector`. ([@twalpole][]) * Add new `SpecSuffixOnly` option to `RSpec/FilePath` cop. ([@zdennis][]) * Allow `RSpec/RepeatedExampleGroupBody` to differ only by described_class. ([@robotdana][]) * Fix `RSpec/FilePath` detection across sibling directories. ([@rolfschmidt][]) * Improve the performance of `RSpec/SubjectStub` by an order of magnitude. ([@andrykonchin][]) ## 1.39.0 (2020-05-01) * Fix `RSpec/FilePath` detection when absolute path includes test subject. ([@eitoball][]) * Add new `Capybara/VisibilityMatcher` cop. ([@aried3r][]) * Ignore String constants by `RSpec/Describe`. ([@AlexWayfer][]) * Drop support for ruby 2.3. ([@bquorning][]) * Fix multiple cops to detect `let` with proc argument. ([@tejasbubane][]) * Add autocorrect support for `RSpec/ScatteredLet`. ([@Darhazer][]) * Add new `RSpec/EmptyHook` cop. ([@tejasbubane][]) ## 1.38.1 (2020-02-15) * Fix `RSpec/RepeatedDescription` to detect descriptions with interpolation and methods. ([@lazycoder9][]) ## 1.38.0 (2020-02-11) * Fix `RSpec/InstanceVariable` detection inside custom matchers. ([@pirj][]) * Fix `RSpec/ScatteredSetup` to distinguish hooks with different metadata. ([@pirj][]) * Add autocorrect support for `RSpec/ExpectActual` cop. ([@dduugg][], [@pirj][]) * Add `RSpec/RepeatedExampleGroupBody` cop. ([@lazycoder9][]) * Add `RSpec/RepeatedExampleGroupDescription` cop. ([@lazycoder9][]) * Add block name and other lines to `RSpec/ScatteredSetup` message. ([@elebow][]) * Fix `RSpec/RepeatedDescription` to take into account example metadata. ([@lazycoder9][]) ## 1.37.1 (2019-12-16) * Improve message and description of `FactoryBot/FactoryClassName`. ([@ybiquitous][]) * Fix `FactoryBot/FactoryClassName` to ignore `Hash` and `OpenStruct`. ([@jfragoulis][]) ## 1.37.0 (2019-11-25) * Implement `RSpec/DescribedClassModuleWrapping` to disallow RSpec statements within a module. ([@kellysutton][]) * Fix documentation rake task to support Rubocop 0.75. ([@nickcampbell18][]) * Fix `RSpec/SubjectStub` to detect implicit subjects stubbed. ([@QQism][]) * Fix `RSpec/Pending` not flagging `skip` with string values. ([@pirj][]) * Add `AllowedExplicitMatchers` config option for `RSpec/PredicateMatcher`. ([@mkrawc][]) * Add `FactoryBot/FactoryClassName` cop. ([@jfragoulis][]) ## 1.36.0 (2019-09-27) * Fix `RSpec/DescribedClass`'s error when `described_class` is used as part of a constant. ([@pirj][]) * Fix `RSpec/ExampleWording` autocorrect of multi-line docstrings. ([@pirj][]) * Add `RSpec/ContextMethod` cop, to detect method names in `context`. ([@geniou][]) * Update RuboCop dependency to 0.68.1 with support for children matching node pattern syntax. ([@pirj][]) * Add `RSpec/EmptyLineAfterExample` cop to check that there is an empty line after example blocks. ([@pirj][]) * Fix `Capybara/CurrentPathExpectation` auto-corrector, to include option `ignore_query: true`. ([@onumis][]) * Fix `RSpec/Focus` detecting mixed array/hash metadata. ([@dgollahon][]) * Fix `RSpec/Focus` to also detect `pending` examples. ([@dgollahon][]) ## 1.35.0 (2019-08-02) * Add `RSpec/ImplicitBlockExpectation` cop. ([@pirj][]) ## 1.34.1 (2019-07-31) * Fix `RSpec/DescribedClass`'s error when a local variable is part of the namespace. ([@pirj][]) ## 1.34.0 (2019-07-23) * Remove `AggregateFailuresByDefault` config option of `RSpec/MultipleExpectations`. ([@pirj][]) * Add `RSpec/LeakyConstantDeclaration` cop. ([@jonatas][], [@pirj][]) * Improve `aggregate_failures` metadata detection of `RSpec/MultipleExpectations`. ([@pirj][]) * Improve `RSpec/SubjectStub` detection and message. ([@pirj][]) * Change message of `RSpec/LetSetup` cop to be more descriptive. ([@foton][]) * Improve `RSpec/ExampleWording` to handle interpolated example messages. ([@nc-holodakg][]) * Improve detection by allowing the use of `RSpec` as a top-level constant. ([@pirj][]) * Fix `RSpec/DescribedClass`'s incorrect detection. ([@pirj][]) * Improve `RSpec/DescribedClass`'s ability to detect inside modules and classes. ([@pirj][]) ## 1.33.0 (2019-05-13) * Let `RSpec/DescribedClass` pass `Struct` instantiation closures. ([@schmijos][]) * Fixed `RSpec/ContextWording` missing `context`s with metadata. ([@pirj][]) * Fix `FactoryBot/AttributeDefinedStatically` not working with an explicit receiver. ([@composerinteralia][]) * Add `RSpec/Dialect` enforces custom RSpec dialects. ([@gsamokovarov][]) * Fix redundant blank lines in `RSpec/MultipleSubjects`'s autocorrect. ([@pirj][]) * Drop support for ruby `2.2`. ([@bquorning][]) ## 1.32.0 (2019-01-27) * Add `RSpec/Yield` cop, suggesting using the `and_yield` method when stubbing a method, accepting a block. ([@Darhazer][]) * Fix `FactoryBot/CreateList` autocorrect crashing when the factory is called with a block=. ([@Darhazer][]) * Fixed `RSpec/Focus` not flagging some cases of `RSpec.describe` with `focus: true`. ([@Darhazer][]) * Fixed `RSpec/Pending` not flagging some cases of `RSpec.describe` with `:skip`. ([@Darhazer][]) * Fix false positive in `RSpec/ReceiveCounts` when method name `exactly`, `at_least` or `at_most` is used along with `times`, without being an RSpec API. ([@Darhazer][]) ## 1.31.0 (2019-01-02) * Add `IgnoreSharedExamples` option for `RSpec/NamedSubject`. ([@RST-J][]) * Add autocorrect support for `Capybara/CurrentPathExpectation` cop. ([@ypresto][]) * Add support for built-in `exists` matcher for `RSpec/PredicateMatcher` cop. ([@mkenyon][]) * `SingleArgumentMessageChain` no longer reports an array as it's only argument as an offense. ([@Darhazer][]) ## 1.30.1 (2018-11-01) * `FactoryBot/CreateList` now ignores `times` blocks with an argument. ([@Darhazer][]) ## 1.30.0 (2018-10-08) * Add config to `RSpec/VerifiedDoubles` to enforcement of verification on unnamed doubles. ([@BrentWheeldon][]) * Fix `FactoryBot/AttributeDefinedStatically` not working when there is a non-symbol key. ([@vzvu3k6k][]) * Fix false positive in `RSpec/ImplicitSubject` when `is_expected` is used inside `its()` block. ([@Darhazer][]) * Add `single_statement_only` style to `RSpec/ImplicitSubject` as a more relaxed alternative to `single_line_only`. ([@Darhazer][]) * Add `RSpec/UnspecifiedException` as a default cop to encourage more-specific `expect{}.to raise_error(ExceptionType)`, or `raise_exception` style handling of exceptions. ([@daveworth][]) ## 1.29.1 (2018-09-01) * Fix false negative in `FactoryBot/AttributeDefinedStatically` when attribute is defined on `self`. ([@Darhazer][]) * `RSpec/FactoryBot` cops will now also inspect the `spec/factories.rb` path by default. ([@bquorning][]) ## 1.29.0 (2018-08-25) * `RSpec/InstanceVariable` - Recommend local variables in addition to `let`. ([@jaredbeck][]) * Add `RSpec/ImplicitSubject` cop. ([@Darhazer][]) * Add `RSpec/HooksBeforeExamples` cop. ([@Darhazer][]) ## 1.28.0 (2018-08-14) * Add `RSpec/ReceiveNever` cop enforcing usage of `not_to receive` instead of `never` matcher. ([@Darhazer][]) * Fix false positive in `RSpec/EmptyLineAfterExampleGroup` cop when example is inside `if`. ([@Darhazer][]) * Add `RSpec/MissingExampleGroupArgument` to enforce first argument for an example group. ([@geniou][]) * Drop support for ruby `2.1`. ([@bquorning][]) * Add `FactoryBot/AttributeDefinedStatically` cop to help FactoryBot users with the deprecation of static attributes. ([@composerinteralia][], [@seanpdoyle][]) * Remove `FactoryBot/DynamicAttributeDefinedStatically` and `FactoryBot/StaticAttributeDefinedDynamically` cops. ([@composerinteralia][]) ## 1.27.0 (2018-06-14) * `RSpec/LeadingSubject` now enforces subject to be before any examples, hooks or let declarations. ([@Darhazer][]) * Fix `RSpec/NotToNot` to highlight only the selector (`not_to` or `to_not`), so it works also on `expect { ... }` blocks. ([@bquorning][]) * Add `RSpec/EmptyLineAfterHook` cop. ([@bquorning][]) * Add `RSpec/EmptyLineAfterExampleGroup` cop to check that there is an empty line after example group blocks. ([@bquorning][]) * Fix `RSpec/DescribeClass` crashing on `RSpec.describe` without arguments. ([@Darhazer][]) * Bump RuboCop requirement to v0.56.0. ([@bquorning][]) * Fix `RSpec/OverwritingSetup` crashing if a variable is used as an argument for `let`. ([@Darhazer][]) ## 1.26.0 (2018-06-06) * Fix false positive in `RSpec/EmptyExampleGroup` cop when methods named like a RSpec method are used. ([@Darhazer][]) * Fix `Capybara/FeatureMethods` not working when there is require before the spec. ([@Darhazer][]) * Fix `RSpec/EmptyLineAfterFinalLet`: allow a comment to be placed after latest let, requiring empty line after the comment. ([@Darhazer][]) * Add `RSpec/ReceiveCounts` cop to enforce usage of :once and :twice matchers. ([@Darhazer][]) ## 1.25.1 (2018-04-10) * Fix false positive in `RSpec/Pending` cop when pending is used as a method name. ([@Darhazer][]) * Fix `FactoryBot/DynamicAttributeDefinedStatically` false positive when using symbol proc argument for a sequence. ([@tdeo][]) ## 1.25.0 (2018-04-07) * Add `RSpec/SharedExamples` cop to enforce consistent usage of string to titleize shared examples. ([@anthony-robin][]) * Add `RSpec/Be` cop to enforce passing argument to the generic `be` matcher. ([@Darhazer][]) * Fix false positives in `StaticAttributeDefinedDynamically` and `ReturnFromStub` when a const is used in an array or hash. ([@Darhazer][]) * Add `RSpec/Pending` cop to enforce no existing pending or skipped examples. This is disabled by default. ([@patrickomatic][]) * Fix `RSpec/NestedGroups` cop support --auto-gen-config. ([@walf443][]) * Fix false positives in `Capybara/FeatureMethods` when feature methods are used as property names in a factory. ([@Darhazer][]) * Allow configuring enabled methods in `Capybara/FeatureMethods`. ([@Darhazer][]) * Add `FactoryBot/CreateList` cop. ([@Darhazer][]) ## 1.24.0 (2018-03-06) * Compatibility with RuboCop v0.53.0. ([@bquorning][]) * The `Rails/HttpStatus` cop is unavailable if the `rack` gem cannot be loaded. ([@bquorning][]) * Fix `Rails/HttpStatus` not working with custom HTTP status codes. ([@bquorning][]) * Fix `FactoryBot/StaticAttributeDefinedDynamically` to handle empty block. ([@abrom][]) * Fix false positive in `FactoryBot/DynamicAttributeDefinedStatically` when a before/after callback has a symbol proc argument. ([@abrom][]) ## 1.23.0 (2018-02-23) * Add `RSpec/Rails/HttpStatus` cop to enforce consistent usage of the status format (numeric or symbolic). ([@anthony-robin][], [@jojos003][]) * Fix false negative in `RSpec/ReturnFromStub` when a constant is being returned by the stub. ([@Darhazer][]) * Fix `FactoryBot/DynamicAttributeDefinedStatically` to handle dynamic attributes inside arrays/hashes. ([@abrom][]) * Add `FactoryBot/StaticAttributeDefinedDynamically` (based on dynamic attribute cop). ([@abrom][]) ## 1.22.2 (2018-02-01) * Fix error in `RSpec/DescribedClass` when working on an empty `describe` block. ([@bquorning][]) ## 1.22.1 (2018-01-17) * Fix false positives in `RSpec/ReturnFromStub`. ([@Darhazer][]) ## 1.22.0 (2018-01-10) * Updates `describe_class` to account for RSpecs `:system` wrapper of rails system tests. ([@EliseFitz15][]) * Add `RSpec/ExpectChange` cop to enforce consistent usage of the change matcher. ([@Darhazer][]) * Add autocorrect support to `RSpec/LetBeforeExamples`. ([@Darhazer][]) * Fix `RSpec/InstanceVariable` flagging instance variables inside dynamically defined class. ([@Darhazer][]) * Add autocorrect support for `RSpec/ReturnFromStub` cop. ([@bquorning][]) * Add `RSpec/ExampleWithoutDescription` cop. ([@Darhazer][]) ## 1.21.0 (2017-12-13) * Compatibility with RuboCop v0.52.0. ([@bquorning][]) * Improve performance when user does not override default RSpec Pattern config. ([@walf443][]) * Add `AggregateFailuresByDefault` configuration for `RSpec/MultipleExpectations` cop. ([@onk][]) ## 1.20.1 (2017-11-15) * Add "without" to list of default allowed prefixes for `RSpec/ContextWording`. ([@bquorning][]) ## 1.20.0 (2017-11-09) * Rename namespace `FactoryGirl` to `FactoryBot` following original library update. ([@walf443][]) * Fix exception in `RSpec/ReturnFromStub` on empty block. ([@yevhene][]) * Add `RSpec/ContextWording` cop. ([@pirj][], [@telmofcosta][]) * Fix `RSpec/SubjectStub` cop matches receive message inside all matcher. ([@walf443][]) ## 1.19.0 (2017-10-18) Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. ## 1.18.0 (2017-09-29) * Fix false positive in `Capybara/FeatureMethods`. ([@Darhazer][]) * Add `RSpec/Capybara/CurrentPathExpectation` cop for feature specs, disallowing setting expectations on `current_path`. ([@timrogers][]) * Fix false positive in `RSpec/LetBeforeExamples` cop when example group contains single let. ([@Darhazer][]) ## 1.17.1 (2017-09-20) * Improved `RSpec/ReturnFromStub` to handle string interpolation, hashes and do..end blocks. ([@Darhazer][]) * Fixed compatibility with JRuby. ([@zverok][]) ## 1.17.0 (2017-09-14) * Add `RSpec/Capybara` namespace including the first cop for feature specs: `Capybara/FeatureMethods`. ([@rspeicher][]) * Update to RuboCop 0.50.0. ([@bquorning][]) ## 1.16.0 (2017-09-06) * Add `RSpec/FactoryGirl` namespace including the first cop for factories: `FactoryGirl/DynamicAttributeDefinedStatically`. ([@jonatas][]) * Add disabled by default `RSpec/AlignLeftLetBrace`. ([@backus][]) * Add disabled by default `RSpec/AlignRightLetBrace`. ([@backus][]) * Add `RSpec/LetBeforeExamples` cop. ([@Darhazer][]) * Add `RSpec/MultipleSubjects` cop. ([@backus][]) * Add `RSpec/ReturnFromStub` cop. ([@Darhazer][]) * Add `RSpec/VoidExpect` cop. ([@pocke][]) * Add `RSpec/InvalidPredicateMatcher` cop. ([@pocke][]) * Change HookArgument cop to detect when hook has a receiver. ([@pocke][]) * Add `RSpec/PredicateMatcher` cop. ([@pocke][]) * Add `RSpec/ExpectInHook` cop. ([@pocke][]) * `RSpec/MultipleExpectations` now detects usage of expect_any_instance_of. ([@Darhazer][]) * `RSpec/MultipleExpectations` now detects usage of is_expected. ([@bmorrall][]) ## 1.15.1 (2017-04-30) * Fix the handling of various edge cases in the `RSpec/ExampleWording` cop, including one that would cause autocorrect to crash. ([@dgollahon][]) * Fix `RSpec/IteratedExpectation` crashing when there is an assignment in the iteration. ([@Darhazer][]) * Fix false positive in `RSpec/SingleArgumentMessageChain` cop when the single argument is a hash. ([@Darhazer][]) ## 1.15.0 (2017-03-24) * Add `RSpec/DescribeSymbol` cop. ([@rspeicher][]) * Fix error when `RSpec/OverwritingSetup` and `RSpec/ScatteredLet` analyzed empty example groups. ([@backus][]) ## 1.14.0 (2017-03-24) * Add `RSpec/OverwritingSetup` cop. ([@Darhazer][]) * Add autocorrect support for `RSpec/LeadingSubject` cop. ([@Darhazer][]) * Add `RSpec/ScatteredLet` cop. ([@Darhazer][]) * Add `RSpec/IteratedExpectation` cop. ([@Darhazer][]) * Add `RSpec/EmptyLineAfterSubject` cop. ([@Darhazer][]) * Add `RSpec/EmptyLineAfterFinalLet` cop. ([@Darhazer][]) ## 1.13.0 (2017-03-07) * Add repeated 'it' detection to `RSpec/ExampleWording` cop. ([@dgollahon][]) * Add [observed_nesting/max_nesting] info to `RSpec/NestedGroups` messages. ([@dgollahon][]) * Add `RSpec/ItBehavesLike` cop. ([@dgollahon][]) * Add `RSpec/SharedContext` cop. ([@Darhazer][]) * `RSpec/MultipleExpectations`: Count aggregate_failures block as single expectation. ([@Darhazer][]) * Fix `ExpectActual` cop flagging `rspec-rails` routing specs. ([@backus][]) * Fix `FilePath` cop not registering offenses for files like `spec/blog/user.rb` when it should be `spec/blog/user_spec.rb`. ([@backus][]) ## 1.12.0 (2017-02-21) * Add `RSpec/InstanceSpy` cop. ([@Darhazer][]) * Add `RSpec/BeforeAfterAll` for avoiding leaky global test setup. ([@cfabianski][]) ## 1.11.0 (2017-02-16) * Add `AroundBlock` cop. ([@Darhazer][]) * Add `EnforcedStyle` configuration for `RSpec/DescribedClass` cop. ([@Darhazer][]) * Fix false positive for `RSpec/RepeatedExample` cop. ([@redross][]) ## 1.10.0 (2017-01-15) * Fix false negative for `RSpec/MessageSpies` cop. ([@onk][]) * Fix internal dependencies on RuboCop to be compatible with 0.47 release. ([@backus][]) * Add autocorrect support for `SingleArgumentMessageChain` cop. ([@bquorning][]) * Rename `NestedGroups`' configuration key from `MaxNesting` to `Max` in order to be consistent with other cop configuration. ([@backus][]) * Add `RepeatedExample` cop for detecting repeated examples within example groups. ([@backus][]) * Add `ScatteredSetup` cop for enforcing that only one `before`, `around`, and `after` hook are used per example group scope. ([@backus][]) * Add `ExpectOutput` cop for recommending `expect { ... }.to output(...).to_stdout`. ([@backus][]) ## 1.9.1 (2017-01-02) * Fix unintentional regression change in `NestedGroups` reported in #270. ([@backus][]) * Change `MaxNesting` for `NestedGroups` from 2 to 3. ([@backus][]) ## 1.9.0 (2016-12-29) * Add `MessageSpies` cop for enforcing consistent style of either `expect(...).to have_received` or `expect(...).to receive`, intended as a replacement for the `MessageExpectation` cop. ([@bquorning][]) * Fix `DescribeClass` to not flag `describe` at the top of a block of shared examples. ([@clupprich][]) * Add `SingleArgumentMessageChain` cop for recommending use of `receive` instead of `receive_message_chain` where possible. ([@bquorning][]) * Add `RepeatedDescription` cop for detecting repeated example descriptions within example groups. ([@backus][]) ## 1.8.0 (2016-10-27) * Optionally ignore method names in the `describe` argument when running the `FilePath` cop. ([@bquorning][]) * Fix regression in how `FilePath` converts alphanumeric class names into paths. ([@bquorning][]) * Add `ImplicitExpect` cop for enforcing `should` vs. `is_expected.to`. ([@backus][]) * Disable `MessageExpectation` cop in the default configuration. ([@bquorning][]) ## 1.7.0 (2016-08-24) * Add support for checking all example groups with `ExampleLength`. ([@backus][]) * Add support for checking shared example groups for `DescribedClass`. ([@backus][]) * Add support for checking `its` from [rspec-its](https://github.com/rspec/rspec-its). ([@backus][]) * Add `EmptyExampleGroup` cop for detecting `describe`s and `context`s without any tests inside. ([@backus][]) * Add `CustomIncludeMethods` configuration option for `EmptyExampleGroup`. ([@backus][]) * Add `NestedGroups` cop for detecting excessive example group nesting. ([@backus][]) * Add `MaxNesting` configuration option for `NestedGroups` cop. ([@backus][]) * Add `ExpectActual` cop for detecting literal values within `expect(...)`. ([@backus][]) * Add `MultipleExpectations` cop for detecting multiple `expect(...)` calls within one example. ([@backus][]) * Add `Max` configuration option for `MultipleExpectations`. ([@backus][]) * Add `SubjectStub` cop for testing stubbed test subjects. ([@backus][]) * Add `LetSetup` cop for detecting cases where `let!` is used for test setup. ([@backus][]) * Change all cops to only inspect files with names following rspec convention (`*/spec/*` and/or `_spec.rb`). ([@backus][]) * Add `AllCops/RSpec` configuration option for specifying custom spec file patterns. ([@backus][]) * Add `AssignmentOnly` configuration option for `RSpec/InstanceVariable` cop. ([@backus][]) * Add `BeEql` cop which looks for expectations that can use `be(...)` instead of `eql(...)`. ([@backus][]) * Add autocorrect support for `BeEql` cop. ([@backus][]) * Add `MessageExpectation` cop for enforcing consistent style of either `expect(...).to receive` or `allow(...).to receive`. ([@backus][]) * Add `MessageChain` cop. ([@bquorning][]) ## 1.6.0 (2016-08-03) * Add `SkipBlocks` option for `DescribedClass` cop. ([@backus][]) ## 1.5.3 (2016-08-02) * Add `RSpec/NamedSubject` cop. ([@backus][]) ## 1.5.2 (2016-08-01) * Drop support for ruby `2.0.0` and `2.1.0`. ([@backus][]) * Internal refactorings and improved test coverage. ([@backus][]) ## 1.5.1 (2016-07-20) * Fix `unrecognized parameter RSpec/VerifiedDoubles:IgnoreSymbolicNames` warning. ([@jeffreyc][]) * Update to rubocop 0.41.2. ([@backus][]) ## 1.5.0 (2016-05-17) * Expand `VerifiedDoubles` cop to check for `spy` as well as `double`. ([@andyw8][]) * Enable `VerifiedDoubles` cop by default. ([@andyw8][]) * Add `IgnoreSymbolicNames` option for `VerifiedDoubles` cop. ([@andyw8][]) * Add `RSpec::ExampleLength` cop. ([@andyw8][]) * Handle alphanumeric class names in `FilePath` cop. ([@andyw8][]) * Skip `DescribeClass` cop for view specs. ([@andyw8][]) * Skip `FilePath` cop for Rails routing specs. ([@andyw8][]) * Add cop to check for focused specs. ([@renanborgescampos][], [@jaredmoody][]) * Clean-up `RSpec::NotToNot` to use same configuration semantics as other Rubocop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal][]) * Update to rubocop 0.40.0. ([@nijikon][]) ## 1.4.1 (2016-04-03) * Ignore routing specs for DescribeClass cop. ([@nijikon][]) * Move rubocop dependency to runtime. ([@nijikon][]) * Update to rubocop 0.39.0. ([@nijikon][]) ## 1.4.0 (2016-02-15) * Update to rubocop 0.37.2. ([@nijikon][]) * Update ruby versions we test against. ([@nijikon][]) * Add `RSpec::NotToNot` cop. ([@miguelfteixeira][]) * Add `RSpec/AnyInstance` cop. ([@mlarraz][]) ## 1.3.1 * Fix auto correction issue - syntax had changed in RuboCop v0.31. ([@bquorning][]) * Add RuboCop clone to vendor folder - see #39 for details. ([@bquorning][]) ## 1.3.0 * Ignore non string arguments for FilePathCop - thanks to @deivid-rodriguez. ([@geniou][]) * Skip DescribeMethod cop for tagged specs. ([@deivid-rodriguez][]) * Skip DescribeClass cop for feature/request specs. ([@deivid-rodriguez][]) ## 1.2.2 * Make `RSpec::ExampleWording` case insensitive. ([@geniou][]) ## 1.2.1 * Add `RSpec::VerifiedDoubles` cop. ([@andyw8][]) ## 1.2.0 * Drop support of ruby `1.9.2`. ([@geniou][]) * Update to RuboCop `~> 0.24`. ([@geniou][]) * Add `autocorrect` to `RSpec::ExampleWording`. This experimental - use with care and check the changes. ([@geniou][]) * Fix config loader debug output. ([@geniou][]) * Rename `FileName` cop to `FilePath` as a workaround - see [#19](https://github.com/nevir/rubocop-rspec/issues/19). ([@geniou][]) ## 1.1.0 * Add `autocorrect` to `RSpec::DescribedClass` cop. ([@geniou][]) ## 1.0.1 * Add `config` folder to gemspec. ([@pstengel][]) ## 1.0.rc3 * Update to RuboCop `>= 0.23`. ([@geniou][]) * Add configuration option for `CustomTransformation` to `FileName` cop. ([@geniou][]) ## 1.0.rc2 * Gem is no longer 20MB (sorry!). ([@nevir][]) * `RspecFileName` cop allows for method specs to organized into directories by class and type. ([@nevir][]) ## 1.0.rc1 * Update code to work with rubocop `>= 0.19`. ([@geniou][]) * Split `UnitSpecNaming` cop into `RSpecDescribeClass`, `RSpecDescribeMethod` and `RSpecFileName` and enabled them all by default. ([@geniou][]) * Add `RSpecExampleWording` cop to prevent to use of should at the beginning of the spec description. ([@geniou][]) * Fix `RSpecFileName` cop for non-class specs. ([@geniou][]) * Adapt `RSpecFileName` cop to commen naming convention and skip spec with multiple top level describes. ([@geniou][]) * Add `RSpecMultipleDescribes` cop to check for multiple top level describes. ([@geniou][]) * Add `RSpecDescribedClass` to promote the use of `described_class`. ([@geniou][]) * Add `RSpecInstanceVariable` cop to check for the usage of instance variables. ([@geniou][]) [@andyw8]: https://github.com/andyw8 [@backus]: https://github.com/backus [@bquorning]: https://github.com/bquorning [@deivid-rodriguez]: https://github.com/deivid-rodriguez [@geniou]: https://github.com/geniou [@jaredbeck]: https://github.com/jaredbeck [@jawshooah]: https://github.com/jawshooah [@nevir]: https://github.com/nevir [@nijikon]: https://github.com/nijikon [@pstengel]: https://github.com/pstengel [@miguelfteixeira]: https://github.com/miguelfteixeira [@mlarraz]: https://github.com/mlarraz [@renanborgescampos]: https://github.com/renanborgescampos [@jaredmoody]: https://github.com/jaredmoody [@baberthal]: https://github.com/baberthal [@jeffreyc]: https://github.com/jeffreyc [@clupprich]: https://github.com/clupprich [@onk]: https://github.com/onk [@Darhazer]: https://github.com/Darhazer [@redross]: https://github.com/redross [@cfabianski]: https://github.com/cfabianski [@dgollahon]: https://github.com/dgollahon [@rspeicher]: https://github.com/rspeicher [@jonatas]: https://github.com/jonatas [@pocke]: https://github.com/pocke [@bmorrall]: https:/github.com/bmorrall [@zverok]: https:/github.com/zverok [@timrogers]: https://github.com/timrogers [@yevhene]: https://github.com/yevhene [@walf443]: https://github.com/walf443 [@pirj]: https://github.com/pirj [@telmofcosta]: https://github.com/telmofcosta [@EliseFitz15]: https://github.com/EliseFitz15 [@anthony-robin]: https://github.com/anthony-robin [@jojos003]: https://github.com/jojos003 [@abrom]: https://github.com/abrom [@patrickomatic]: https://github.com/patrickomatic [@tdeo]: https://github.com/tdeo [@composerinteralia]: https://github.com/composerinteralia [@seanpdoyle]: https://github.com/seanpdoyle [@vzvu3k6k]: https://github.com/vzvu3k6k [@BrentWheeldon]: https://github.com/BrentWheeldon [@daveworth]: https://github.com/daveworth [@RST-J]: https://github.com/RST-J [@ypresto]: https://github.com/ypresto [@mkenyon]: https://github.com/mkenyon [@gsamokovarov]: https://github.com/gsamokovarov [@schmijos]: https://github.com/schmijos [@foton]: https://github.com/foton [@nc-holodakg]: https://github.com/nc-holodakg [@onumis]: https://github.com/onumis [@nickcampbell18]: https://github.com/nickcampbell18 [@QQism]: https://github.com/QQism [@kellysutton]: https://github.com/kellysutton [@mkrawc]: https://github.com/mkrawc [@jfragoulis]: https://github.com/jfragoulis [@ybiquitous]: https://github.com/ybiquitous [@dduugg]: https://github.com/dduugg [@lazycoder9]: https://github.com/lazycoder9 [@elebow]: https://github.com/elebow [@eitoball]: https://github.com/eitoball [@aried3r]: https://github.com/aried3r [@AlexWayfer]: https://github.com/AlexWayfer [@tejasbubane]: https://github.com/tejasbubane [@twalpole]: https://github.com/twalpole [@zdennis]: https://github.com/zdennis [@robotdana]: https://github.com/robotdana [@rolfschmidt]: https://github.com/rolfschmidt [@andrykonchin]: https://github.com/andrykonchin [@harrylewis]: https://github.com/harrylewis rubocop-rspec-1.42.0/CODE_OF_CONDUCT.md000066400000000000000000000015711370170147500171710ustar00rootroot00000000000000# The RuboCop Community Code of Conduct **Note:** We have picked the following code of conduct based on [Ruby's own code of conduct](https://www.ruby-lang.org/en/conduct/). This document provides a few simple community guidelines for a safe, respectful, productive, and collaborative place for any person who is willing to contribute to the RuboCop community. It applies to all "collaborative spaces", which are defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.). * Participants will be tolerant of opposing views. * Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. * When interpreting the words and actions of others, participants should always assume good intentions. * Behaviour which can be reasonably considered harassment will not be tolerated. rubocop-rspec-1.42.0/Gemfile000066400000000000000000000003131370170147500156560ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec local_gemfile = 'Gemfile.local' if File.exist?(local_gemfile) eval(File.read(local_gemfile)) # rubocop:disable Security/Eval end rubocop-rspec-1.42.0/MIT-LICENSE.md000066400000000000000000000021341370170147500164210ustar00rootroot00000000000000The MIT License (MIT) ===================== Copyright (c) 2014 Ian MacLeod Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rubocop-rspec-1.42.0/README.md000066400000000000000000000046151370170147500156530ustar00rootroot00000000000000# RuboCop RSpec [![Join the chat at https://gitter.im/rubocop-rspec/Lobby](https://badges.gitter.im/rubocop-rspec/Lobby.svg)](https://gitter.im/rubocop-rspec/Lobby) [![Gem Version](https://badge.fury.io/rb/rubocop-rspec.svg)](https://rubygems.org/gems/rubocop-rspec) [![CircleCI](https://circleci.com/gh/rubocop-hq/rubocop-rspec.svg?style=svg)](https://circleci.com/gh/rubocop-hq/rubocop-rspec) [![Test Coverage](https://api.codeclimate.com/v1/badges/8ffaabf633c968c22bdd/test_coverage)](https://codeclimate.com/github/rubocop-hq/rubocop-rspec/test_coverage) [![Maintainability](https://api.codeclimate.com/v1/badges/8ffaabf633c968c22bdd/maintainability)](https://codeclimate.com/github/rubocop-hq/rubocop-rspec/maintainability) RSpec-specific analysis for your projects, as an extension to [RuboCop](https://github.com/rubocop-hq/rubocop). ## Installation Just install the `rubocop-rspec` gem ```bash gem install rubocop-rspec ``` or if you use bundler put this in your `Gemfile` ``` gem 'rubocop-rspec', require: false ``` ## Usage You need to tell RuboCop to load the RSpec extension. There are three ways to do this: ### RuboCop configuration file Put this into your `.rubocop.yml`. ```yaml require: rubocop-rspec ``` Alternatively, use the following array notation when specifying multiple extensions. ```yaml require: - rubocop-other-extension - rubocop-rspec ``` Now you can run `rubocop` and it will automatically load the RuboCop RSpec cops together with the standard cops. ### Command line ```bash rubocop --require rubocop-rspec ``` ### Rake task ```ruby RuboCop::RakeTask.new do |task| task.requires << 'rubocop-rspec' end ``` ### Code Climate rubocop-rspec is available on Code Climate as part of the rubocop engine. [Learn More](https://codeclimate.com/changelog/55a433bbe30ba00852000fac). ## Documentation You can read more about RuboCop-RSpec in its [official manual](https://docs.rubocop.org/rubocop-rspec). ## The Cops All cops are located under [`lib/rubocop/cop/rspec`](lib/rubocop/cop/rspec), and contain examples/documentation. In your `.rubocop.yml`, you may treat the RSpec cops just like any other cop. For example: ```yaml RSpec/FilePath: Exclude: - spec/my_poorly_named_spec_file.rb ``` ## Contributing Checkout the [contribution guidelines](.github/CONTRIBUTING.md). ## License `rubocop-rspec` is MIT licensed. [See the accompanying file](MIT-LICENSE.md) for the full text. rubocop-rspec-1.42.0/Rakefile000066400000000000000000000044711370170147500160410ustar00rootroot00000000000000# frozen_string_literal: true require 'open3' require 'bundler' require 'bundler/gem_tasks' begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e warn e.message warn 'Run `bundle install` to install missing gems' exit e.status_code end require 'rspec/core/rake_task' Dir['tasks/**/*.rake'].each { |t| load t } RSpec::Core::RakeTask.new(:spec) do |spec| spec.pattern = FileList['spec/**/*_spec.rb'] end desc 'Run RSpec with code coverage' task :coverage do ENV['COVERAGE'] = 'true' Rake::Task['spec'].execute end desc 'Run RuboCop over this gem' task :internal_investigation do sh('bundle exec rubocop --require rubocop-rspec') end desc 'Build config/default.yml' task :build_config do sh('bin/build_config') end desc 'Confirm config/default.yml is up to date' task confirm_config: :build_config do _, stdout, _, process = Open3.popen3('git diff --exit-code config/default.yml') raise <<~ERROR unless process.value.success? default.yml is out of sync: #{stdout.read} Run bin/build_config ERROR end desc 'Confirm documentation is up to date' task confirm_documentation: :generate_cops_documentation do _, _, _, process = Open3.popen3('git diff --exit-code manual/') unless process.value.success? raise 'Please run `rake generate_cops_documentation` ' \ 'and add manual/ to the commit.' end end task default: %i[build_config coverage internal_investigation confirm_config documentation_syntax_check confirm_documentation] desc 'Generate a new cop template' task :new_cop, [:cop] do |_task, args| require 'rubocop' cop_name = args.fetch(:cop) do warn 'usage: bundle exec rake new_cop[Department/Name]' exit! end github_user = `git config github.user`.chop github_user = 'your_id' if github_user.empty? generator = RuboCop::Cop::Generator.new(cop_name, github_user) generator.write_source generator.write_spec generator.inject_require(root_file_path: 'lib/rubocop/cop/rspec_cops.rb') generator.inject_config(config_file_path: 'config/default.yml', version_added: bump_minor_version) puts generator.todo end def bump_minor_version major, minor, _patch = RuboCop::RSpec::Version::STRING.split('.') "#{major}.#{minor.succ}.0" end rubocop-rspec-1.42.0/bin/000077500000000000000000000000001370170147500151365ustar00rootroot00000000000000rubocop-rspec-1.42.0/bin/build_config000077500000000000000000000020151370170147500175060ustar00rootroot00000000000000#!/usr/bin/env ruby # frozen_string_literal: true $LOAD_PATH.unshift(File.join(__dir__, '..', 'lib')) require 'yard' require 'rubocop-rspec' require 'rubocop/rspec/description_extractor' require 'rubocop/rspec/config_formatter' glob = File.join('lib', 'rubocop', 'cop', 'rspec', '{,capybara,factory_bot,rails}', '*.rb') # Due to YARD's sensitivity to file require order (as of 0.9.25), # we have to prepend the list with our base cop, RuboCop::Cop::RSpec::Cop. # Otherwise, cop's parent class for cops loaded before our base cop class # are detected as RuboCop::Cop::Cop, and that complicates the detection # of their relation with RuboCop RSpec. rspec_cop_path = File.join('lib', 'rubocop', 'cop', 'rspec', 'cop.rb') YARD.parse(Dir[glob].prepend(rspec_cop_path), []) descriptions = RuboCop::RSpec::DescriptionExtractor.new(YARD::Registry.all).to_h current_config = YAML.load_file('config/default.yml') File.write( 'config/default.yml', RuboCop::RSpec::ConfigFormatter.new(current_config, descriptions).dump ) rubocop-rspec-1.42.0/config/000077500000000000000000000000001370170147500156335ustar00rootroot00000000000000rubocop-rspec-1.42.0/config/default.yml000066400000000000000000000517421370170147500200130ustar00rootroot00000000000000--- AllCops: RSpec: Patterns: - _spec.rb - "(?:^|/)spec/" RSpec/FactoryBot: Patterns: - spec/factories.rb - spec/factories/**/*.rb - features/support/factories/**/*.rb RSpec/AlignLeftLetBrace: Description: Checks that left braces for adjacent single line lets are aligned. Enabled: false VersionAdded: '1.16' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignLeftLetBrace RSpec/AlignRightLetBrace: Description: Checks that right braces for adjacent single line lets are aligned. Enabled: false VersionAdded: '1.16' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignRightLetBrace RSpec/AnyInstance: Description: Check that instances are not being stubbed globally. Enabled: true VersionAdded: '1.4' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance RSpec/AroundBlock: Description: Checks that around blocks actually run the test. Enabled: true VersionAdded: '1.11' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AroundBlock RSpec/Be: Description: Check for expectations where `be` is used without argument. Enabled: true VersionAdded: '1.25' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be RSpec/BeEql: Description: Check for expectations where `be(...)` can replace `eql(...)`. Enabled: true VersionAdded: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql RSpec/BeforeAfterAll: Description: Check that before/after(:all) isn't being used. Enabled: true Exclude: - spec/spec_helper.rb - spec/rails_helper.rb - spec/support/**/*.rb VersionAdded: '1.12' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll RSpec/ContextMethod: Description: "`context` should not be used for specifying methods." Enabled: true VersionAdded: '1.36' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod RSpec/ContextWording: Description: Checks that `context` docstring starts with an allowed prefix. Enabled: true Prefixes: - when - with - without VersionAdded: '1.20' VersionChanged: 1.20.1 StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording RSpec/DescribeClass: Description: Check that the first argument to the top level describe is a constant. Enabled: true VersionAdded: '1.0' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass RSpec/DescribeMethod: Description: Checks that the second argument to `describe` specifies a method. Enabled: true VersionAdded: '1.0' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeMethod RSpec/DescribeSymbol: Description: Avoid describing symbols. Enabled: true VersionAdded: '1.15' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol RSpec/DescribedClass: Description: Checks that tests use `described_class`. Enabled: true SkipBlocks: false EnforcedStyle: described_class SupportedStyles: - described_class - explicit SafeAutoCorrect: false VersionAdded: '1.0' VersionChanged: '1.11' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass RSpec/DescribedClassModuleWrapping: Description: Avoid opening modules and defining specs within them. Enabled: false VersionAdded: '1.37' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping RSpec/Dialect: Description: This cop enforces custom RSpec dialects. Enabled: false PreferredMethods: {} VersionAdded: '1.33' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect RSpec/EmptyExampleGroup: Description: Checks if an example group does not include any tests. Enabled: true CustomIncludeMethods: [] VersionAdded: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup RSpec/EmptyHook: Description: Checks for empty before and after hooks. Enabled: true VersionAdded: '1.39' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook RSpec/EmptyLineAfterExample: Description: Checks if there is an empty line after example blocks. Enabled: true AllowConsecutiveOneLiners: true VersionAdded: '1.36' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample RSpec/EmptyLineAfterExampleGroup: Description: Checks if there is an empty line after example group blocks. Enabled: true VersionAdded: '1.27' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExampleGroup RSpec/EmptyLineAfterFinalLet: Description: Checks if there is an empty line after the last let block. Enabled: true VersionAdded: '1.14' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterFinalLet RSpec/EmptyLineAfterHook: Description: Checks if there is an empty line after hook blocks. Enabled: true VersionAdded: '1.27' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook RSpec/EmptyLineAfterSubject: Description: Checks if there is an empty line after subject block. Enabled: true VersionAdded: '1.14' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject RSpec/ExampleLength: Description: Checks for long examples. Enabled: true Max: 5 VersionAdded: '1.5' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength RSpec/ExampleWithoutDescription: Description: Checks for examples without a description. Enabled: true EnforcedStyle: always_allow SupportedStyles: - always_allow - single_line_only - disallow VersionAdded: '1.22' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription RSpec/ExampleWording: Description: Checks for common mistakes in example descriptions. Enabled: true CustomTransform: be: is BE: IS have: has HAVE: HAS IgnoredWords: [] VersionAdded: '1.0' VersionChanged: '1.2' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording RSpec/ExpectActual: Description: Checks for `expect(...)` calls containing literal values. Enabled: true Exclude: - spec/routing/**/* VersionAdded: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectActual RSpec/ExpectChange: Description: Checks for consistent style of change matcher. Enabled: true EnforcedStyle: method_call SupportedStyles: - method_call - block VersionAdded: '1.22' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectChange RSpec/ExpectInHook: Description: Do not use `expect` in hooks such as `before`. Enabled: true VersionAdded: '1.16' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectInHook RSpec/ExpectOutput: Description: Checks for opportunities to use `expect { ... }.to output`. Enabled: true VersionAdded: '1.10' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectOutput RSpec/FilePath: Description: Checks that spec file paths are consistent and well-formed. Enabled: true CustomTransform: RuboCop: rubocop RSpec: rspec IgnoreMethods: false SpecSuffixOnly: false VersionAdded: '1.2' VersionChanged: '1.40' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FilePath RSpec/Focus: Description: Checks if examples are focused. Enabled: true VersionAdded: '1.5' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Focus RSpec/HookArgument: Description: Checks the arguments passed to `before`, `around`, and `after`. Enabled: true EnforcedStyle: implicit SupportedStyles: - implicit - each - example VersionAdded: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HookArgument RSpec/HooksBeforeExamples: Description: Checks for before/around/after hooks that come after an example. Enabled: true VersionAdded: '1.29' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples RSpec/ImplicitBlockExpectation: Description: Check that implicit block expectation syntax is not used. Enabled: true VersionAdded: '1.35' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitBlockExpectation RSpec/ImplicitExpect: Description: Check that a consistent implicit expectation style is used. Enabled: true EnforcedStyle: is_expected SupportedStyles: - is_expected - should VersionAdded: '1.8' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitExpect RSpec/ImplicitSubject: Description: Checks for usage of implicit subject (`is_expected` / `should`). Enabled: true EnforcedStyle: single_line_only SupportedStyles: - single_line_only - single_statement_only - disallow VersionAdded: '1.29' VersionChanged: '1.30' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject RSpec/InstanceSpy: Description: Checks for `instance_double` used with `have_received`. Enabled: true VersionAdded: '1.12' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceSpy RSpec/InstanceVariable: Description: Checks for instance variable usage in specs. Enabled: true AssignmentOnly: false VersionAdded: '1.0' VersionChanged: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceVariable RSpec/InvalidPredicateMatcher: Description: Checks invalid usage for predicate matcher. Enabled: true VersionAdded: '1.16' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InvalidPredicateMatcher RSpec/ItBehavesLike: Description: Checks that only one `it_behaves_like` style is used. Enabled: true EnforcedStyle: it_behaves_like SupportedStyles: - it_behaves_like - it_should_behave_like VersionAdded: '1.13' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike RSpec/IteratedExpectation: Description: Check that `all` matcher is used instead of iterating over an array. Enabled: true VersionAdded: '1.14' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IteratedExpectation RSpec/LeadingSubject: Description: Enforce that subject is the first definition in the test. Enabled: true VersionAdded: '1.7' VersionChanged: '1.14' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject RSpec/LeakyConstantDeclaration: Description: Checks that no class, module, or constant is declared. Enabled: true VersionAdded: '1.35' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeakyConstantDeclaration RSpec/LetBeforeExamples: Description: Checks for `let` definitions that come after an example. Enabled: true VersionAdded: '1.16' VersionChanged: '1.22' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetBeforeExamples RSpec/LetSetup: Description: Checks unreferenced `let!` calls being used for test setup. Enabled: true VersionAdded: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup RSpec/MessageChain: Description: Check that chains of messages are not being stubbed. Enabled: true VersionAdded: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageChain RSpec/MessageExpectation: Description: Checks for consistent message expectation style. Enabled: false EnforcedStyle: allow SupportedStyles: - allow - expect VersionAdded: '1.7' VersionChanged: '1.8' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageExpectation RSpec/MessageSpies: Description: Checks that message expectations are set using spies. Enabled: true EnforcedStyle: have_received SupportedStyles: - have_received - receive VersionAdded: '1.9' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageSpies RSpec/MissingExampleGroupArgument: Description: Checks that the first argument to an example group is not empty. Enabled: true VersionAdded: '1.28' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument RSpec/MultipleDescribes: Description: Checks for multiple top level describes. Enabled: true VersionAdded: '1.0' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes RSpec/MultipleExpectations: Description: Checks if examples contain too many `expect` calls. Enabled: true Max: 1 VersionAdded: '1.7' VersionChanged: '1.21' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations RSpec/MultipleSubjects: Description: Checks if an example group defines `subject` multiple times. Enabled: true VersionAdded: '1.16' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleSubjects RSpec/NamedSubject: Description: Checks for explicitly referenced test subjects. Enabled: true IgnoreSharedExamples: true VersionAdded: 1.5.3 StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject RSpec/NestedGroups: Description: Checks for nested example groups. Enabled: true Max: 3 VersionAdded: '1.7' VersionChanged: '1.10' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups RSpec/NotToNot: Description: Checks for consistent method usage for negating expectations. Enabled: true EnforcedStyle: not_to SupportedStyles: - not_to - to_not VersionAdded: '1.4' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NotToNot RSpec/OverwritingSetup: Description: Checks if there is a let/subject that overwrites an existing one. Enabled: true VersionAdded: '1.14' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/OverwritingSetup RSpec/Pending: Description: Checks for any pending or skipped examples. Enabled: false VersionAdded: '1.25' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending RSpec/PredicateMatcher: Description: Prefer using predicate matcher over using predicate method directly. Enabled: true Strict: true EnforcedStyle: inflected AllowedExplicitMatchers: [] SupportedStyles: - inflected - explicit SafeAutoCorrect: false VersionAdded: '1.16' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher RSpec/ReceiveCounts: Description: Check for `once` and `twice` receive counts matchers usage. Enabled: true VersionAdded: '1.26' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts RSpec/ReceiveNever: Description: Prefer `not_to receive(...)` over `receive(...).never`. Enabled: true VersionAdded: '1.28' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever RSpec/RepeatedDescription: Description: Check for repeated description strings in example groups. Enabled: true VersionAdded: '1.9' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedDescription RSpec/RepeatedExample: Description: Check for repeated examples within example groups. Enabled: true VersionAdded: '1.10' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExample RSpec/RepeatedExampleGroupBody: Description: Check for repeated describe and context block body. Enabled: true VersionAdded: '1.38' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupBody RSpec/RepeatedExampleGroupDescription: Description: Check for repeated example group descriptions. Enabled: true VersionAdded: '1.38' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription RSpec/ReturnFromStub: Description: Checks for consistent style of stub's return setting. Enabled: true EnforcedStyle: and_return SupportedStyles: - and_return - block VersionAdded: '1.16' VersionChanged: '1.22' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReturnFromStub RSpec/ScatteredLet: Description: Checks for let scattered across the example group. Enabled: true VersionAdded: '1.14' VersionChanged: '1.39' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet RSpec/ScatteredSetup: Description: Checks for setup scattered across multiple hooks in an example group. Enabled: true VersionAdded: '1.10' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredSetup RSpec/SharedContext: Description: Checks for proper shared_context and shared_examples usage. Enabled: true VersionAdded: '1.13' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedContext RSpec/SharedExamples: Description: Enforces use of string to titleize shared examples. Enabled: true VersionAdded: '1.25' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedExamples RSpec/SingleArgumentMessageChain: Description: Checks that chains of messages contain more than one element. Enabled: true VersionAdded: '1.9' VersionChanged: '1.10' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain RSpec/SubjectStub: Description: Checks for stubbed test subjects. Enabled: true VersionAdded: '1.7' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectStub RSpec/UnspecifiedException: Description: Checks for a specified error in checking raised errors. Enabled: true VersionAdded: '1.30' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UnspecifiedException RSpec/VariableDefinition: Description: Checks that memoized helpers names are symbols or strings. Enabled: true EnforcedStyle: symbols SupportedStyles: - symbols - strings VersionAdded: '1.40' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableDefinition RSpec/VariableName: Description: Checks that memoized helper names use the configured style. Enabled: true EnforcedStyle: snake_case SupportedStyles: - snake_case - camelCase VersionAdded: '1.40' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName RSpec/VerifiedDoubles: Description: Prefer using verifying doubles over normal doubles. Enabled: true IgnoreNameless: true IgnoreSymbolicNames: false VersionAdded: 1.2.1 VersionChanged: '1.5' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles RSpec/VoidExpect: Description: This cop checks void `expect()`. Enabled: true VersionAdded: '1.16' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect RSpec/Yield: Description: This cop checks for calling a block within a stub. Enabled: true VersionAdded: '1.32' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield Capybara/CurrentPathExpectation: Description: Checks that no expectations are set on Capybara's `current_path`. Enabled: true VersionAdded: '1.18' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/CurrentPathExpectation Capybara/FeatureMethods: Description: Checks for consistent method usage in feature specs. Enabled: true EnabledMethods: [] VersionAdded: '1.17' VersionChanged: '1.25' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/FeatureMethods Capybara/VisibilityMatcher: Description: Checks for boolean visibility in capybara finders. Enabled: true VersionAdded: '1.39' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/VisibilityMatcher FactoryBot/AttributeDefinedStatically: Description: Always declare attribute values as blocks. Enabled: true VersionAdded: '1.28' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/AttributeDefinedStatically FactoryBot/CreateList: Description: Checks for create_list usage. Enabled: true EnforcedStyle: create_list SupportedStyles: - create_list - n_times VersionAdded: '1.25' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList FactoryBot/FactoryClassName: Description: Use string value when setting the class attribute explicitly. Enabled: true VersionAdded: '1.37' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName Rails/HttpStatus: Description: Enforces use of symbolic or numeric value to describe HTTP status. Enabled: true EnforcedStyle: symbolic SupportedStyles: - numeric - symbolic VersionAdded: '1.23' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus rubocop-rspec-1.42.0/docs/000077500000000000000000000000001370170147500153165ustar00rootroot00000000000000rubocop-rspec-1.42.0/docs/antora.yml000066400000000000000000000001261370170147500173240ustar00rootroot00000000000000name: rubocop-rspec title: RuboCop RSpec version: master nav: - modules/ROOT/nav.adoc rubocop-rspec-1.42.0/docs/modules/000077500000000000000000000000001370170147500167665ustar00rootroot00000000000000rubocop-rspec-1.42.0/docs/modules/ROOT/000077500000000000000000000000001370170147500175515ustar00rootroot00000000000000rubocop-rspec-1.42.0/docs/modules/ROOT/nav.adoc000066400000000000000000000004201370170147500211610ustar00rootroot00000000000000* xref:index.adoc[Home] * xref:installation.adoc[Installation] * xref:usage.adoc[Usage] * xref:cops.adoc[Cops] * Cops Documentation ** xref:cops_capybara.adoc[Capybara] ** xref:cops_factorybot.adoc[FactoryBot] ** xref:cops_rails.adoc[Rails] ** xref:cops_rspec.adoc[RSpec] rubocop-rspec-1.42.0/docs/modules/ROOT/pages/000077500000000000000000000000001370170147500206505ustar00rootroot00000000000000rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops.adoc000066400000000000000000000135051370170147500224500ustar00rootroot00000000000000// START_COP_LIST ==== Department xref:cops_capybara.adoc[Capybara] * link:cops_capybara.md#capybaracurrentpathexpectation[Capybara/CurrentPathExpectation] * link:cops_capybara.md#capybarafeaturemethods[Capybara/FeatureMethods] * link:cops_capybara.md#capybaravisibilitymatcher[Capybara/VisibilityMatcher] ==== Department xref:cops_factorybot.adoc[FactoryBot] * link:cops_factorybot.md#factorybotattributedefinedstatically[FactoryBot/AttributeDefinedStatically] * link:cops_factorybot.md#factorybotcreatelist[FactoryBot/CreateList] * link:cops_factorybot.md#factorybotfactoryclassname[FactoryBot/FactoryClassName] ==== Department xref:cops_rspec.adoc[RSpec] * link:cops_rspec.adoc#rspecalignleftletbrace[RSpec/AlignLeftLetBrace] * link:cops_rspec.adoc#rspecalignrightletbrace[RSpec/AlignRightLetBrace] * link:cops_rspec.adoc#rspecanyinstance[RSpec/AnyInstance] * link:cops_rspec.adoc#rspecaroundblock[RSpec/AroundBlock] * link:cops_rspec.adoc#rspecbe[RSpec/Be] * link:cops_rspec.adoc#rspecbeeql[RSpec/BeEql] * link:cops_rspec.adoc#rspecbeforeafterall[RSpec/BeforeAfterAll] * link:cops_rspec.adoc#rspeccontextmethod[RSpec/ContextMethod] * link:cops_rspec.adoc#rspeccontextwording[RSpec/ContextWording] * link:cops_rspec.adoc#rspecdescribeclass[RSpec/DescribeClass] * link:cops_rspec.adoc#rspecdescribemethod[RSpec/DescribeMethod] * link:cops_rspec.adoc#rspecdescribesymbol[RSpec/DescribeSymbol] * link:cops_rspec.adoc#rspecdescribedclass[RSpec/DescribedClass] * link:cops_rspec.adoc#rspecdescribedclassmodulewrapping[RSpec/DescribedClassModuleWrapping] * link:cops_rspec.adoc#rspecdialect[RSpec/Dialect] * link:cops_rspec.adoc#rspecemptyexamplegroup[RSpec/EmptyExampleGroup] * link:cops_rspec.adoc#rspecemptyhook[RSpec/EmptyHook] * link:cops_rspec.adoc#rspecemptylineafterexample[RSpec/EmptyLineAfterExample] * link:cops_rspec.adoc#rspecemptylineafterexamplegroup[RSpec/EmptyLineAfterExampleGroup] * link:cops_rspec.adoc#rspecemptylineafterfinallet[RSpec/EmptyLineAfterFinalLet] * link:cops_rspec.adoc#rspecemptylineafterhook[RSpec/EmptyLineAfterHook] * link:cops_rspec.adoc#rspecemptylineaftersubject[RSpec/EmptyLineAfterSubject] * link:cops_rspec.adoc#rspecexamplelength[RSpec/ExampleLength] * link:cops_rspec.adoc#rspecexamplewithoutdescription[RSpec/ExampleWithoutDescription] * link:cops_rspec.adoc#rspecexamplewording[RSpec/ExampleWording] * link:cops_rspec.adoc#rspecexpectactual[RSpec/ExpectActual] * link:cops_rspec.adoc#rspecexpectchange[RSpec/ExpectChange] * link:cops_rspec.adoc#rspecexpectinhook[RSpec/ExpectInHook] * link:cops_rspec.adoc#rspecexpectoutput[RSpec/ExpectOutput] * link:cops_rspec.adoc#rspecfilepath[RSpec/FilePath] * link:cops_rspec.adoc#rspecfocus[RSpec/Focus] * link:cops_rspec.adoc#rspechookargument[RSpec/HookArgument] * link:cops_rspec.adoc#rspechooksbeforeexamples[RSpec/HooksBeforeExamples] * link:cops_rspec.adoc#rspecimplicitblockexpectation[RSpec/ImplicitBlockExpectation] * link:cops_rspec.adoc#rspecimplicitexpect[RSpec/ImplicitExpect] * link:cops_rspec.adoc#rspecimplicitsubject[RSpec/ImplicitSubject] * link:cops_rspec.adoc#rspecinstancespy[RSpec/InstanceSpy] * link:cops_rspec.adoc#rspecinstancevariable[RSpec/InstanceVariable] * link:cops_rspec.adoc#rspecinvalidpredicatematcher[RSpec/InvalidPredicateMatcher] * link:cops_rspec.adoc#rspecitbehaveslike[RSpec/ItBehavesLike] * link:cops_rspec.adoc#rspeciteratedexpectation[RSpec/IteratedExpectation] * link:cops_rspec.adoc#rspecleadingsubject[RSpec/LeadingSubject] * link:cops_rspec.adoc#rspecleakyconstantdeclaration[RSpec/LeakyConstantDeclaration] * link:cops_rspec.adoc#rspecletbeforeexamples[RSpec/LetBeforeExamples] * link:cops_rspec.adoc#rspecletsetup[RSpec/LetSetup] * link:cops_rspec.adoc#rspecmessagechain[RSpec/MessageChain] * link:cops_rspec.adoc#rspecmessageexpectation[RSpec/MessageExpectation] * link:cops_rspec.adoc#rspecmessagespies[RSpec/MessageSpies] * link:cops_rspec.adoc#rspecmissingexamplegroupargument[RSpec/MissingExampleGroupArgument] * link:cops_rspec.adoc#rspecmultipledescribes[RSpec/MultipleDescribes] * link:cops_rspec.adoc#rspecmultipleexpectations[RSpec/MultipleExpectations] * link:cops_rspec.adoc#rspecmultiplesubjects[RSpec/MultipleSubjects] * link:cops_rspec.adoc#rspecnamedsubject[RSpec/NamedSubject] * link:cops_rspec.adoc#rspecnestedgroups[RSpec/NestedGroups] * link:cops_rspec.adoc#rspecnottonot[RSpec/NotToNot] * link:cops_rspec.adoc#rspecoverwritingsetup[RSpec/OverwritingSetup] * link:cops_rspec.adoc#rspecpending[RSpec/Pending] * link:cops_rspec.adoc#rspecpredicatematcher[RSpec/PredicateMatcher] * link:cops_rspec.adoc#rspecreceivecounts[RSpec/ReceiveCounts] * link:cops_rspec.adoc#rspecreceivenever[RSpec/ReceiveNever] * link:cops_rspec.adoc#rspecrepeateddescription[RSpec/RepeatedDescription] * link:cops_rspec.adoc#rspecrepeatedexample[RSpec/RepeatedExample] * link:cops_rspec.adoc#rspecrepeatedexamplegroupbody[RSpec/RepeatedExampleGroupBody] * link:cops_rspec.adoc#rspecrepeatedexamplegroupdescription[RSpec/RepeatedExampleGroupDescription] * link:cops_rspec.adoc#rspecreturnfromstub[RSpec/ReturnFromStub] * link:cops_rspec.adoc#rspecscatteredlet[RSpec/ScatteredLet] * link:cops_rspec.adoc#rspecscatteredsetup[RSpec/ScatteredSetup] * link:cops_rspec.adoc#rspecsharedcontext[RSpec/SharedContext] * link:cops_rspec.adoc#rspecsharedexamples[RSpec/SharedExamples] * link:cops_rspec.adoc#rspecsingleargumentmessagechain[RSpec/SingleArgumentMessageChain] * link:cops_rspec.adoc#rspecsubjectstub[RSpec/SubjectStub] * link:cops_rspec.adoc#rspecunspecifiedexception[RSpec/UnspecifiedException] * link:cops_rspec.adoc#rspecvariabledefinition[RSpec/VariableDefinition] * link:cops_rspec.adoc#rspecvariablename[RSpec/VariableName] * link:cops_rspec.adoc#rspecverifieddoubles[RSpec/VerifiedDoubles] * link:cops_rspec.adoc#rspecvoidexpect[RSpec/VoidExpect] * link:cops_rspec.adoc#rspecyield[RSpec/Yield] ==== Department xref:cops_rails.adoc[Rails] * link:cops_rails.adoc#railshttpstatus[Rails/HttpStatus] // END_COP_LIST rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_capybara.adoc000066400000000000000000000065121370170147500243120ustar00rootroot00000000000000= Capybara == Capybara/CurrentPathExpectation |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks that no expectations are set on Capybara's `current_path`. The `have_current_path` matcher (https://www.rubydoc.info/github/ teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path- instance_method) should be used on `page` to set expectations on Capybara's current path, since it uses Capybara's waiting functionality (https://github.com/teamcapybara/capybara/blob/master/ README.md#asynchronous-javascript-ajax-and-friends) which ensures that preceding actions (like `click_link`) have completed. === Examples [source,ruby] ---- # bad expect(current_path).to eq('/callback') expect(page.current_path).to match(/widgets/) # good expect(page).to have_current_path("/callback") expect(page).to have_current_path(/widgets/) ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/CurrentPathExpectation == Capybara/FeatureMethods |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for consistent method usage in feature specs. By default, the cop disables all Capybara-specific methods that have the same native RSpec method (e.g. are just aliases). Some teams however may prefer using some of the Capybara methods (like `feature`) to make it obvious that the test uses Capybara, while still disable the rest of the methods, like `given` (alias for `let`), `background` (alias for `before`), etc. You can configure which of the methods to be enabled by using the EnabledMethods configuration option. === Examples [source,ruby] ---- # bad feature 'User logs in' do given(:user) { User.new } background do visit new_session_path end scenario 'with OAuth' do # ... end end # good describe 'User logs in' do let(:user) { User.new } before do visit new_session_path end it 'with OAuth' do # ... end end ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnabledMethods | `[]` | Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/FeatureMethods == Capybara/VisibilityMatcher |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for boolean visibility in capybara finders. Capybara lets you find elements that match a certain visibility using the `:visible` option. `:visible` accepts both boolean and symbols as values, however using booleans can have unwanted effects. `visible: false` does not find just invisible elements, but both visible and invisible elements. For expressiveness and clarity, use one of the symbol values, `:all`, `:hidden` or `:visible`. (https://www.rubydoc.info/gems/capybara/Capybara%2FNode%2FFinders:all) === Examples [source,ruby] ---- # bad expect(page).to have_selector('.foo', visible: false) expect(page).to have_css('.foo', visible: true) expect(page).to have_link('my link', visible: false) # good expect(page).to have_selector('.foo', visible: :visible) expect(page).to have_css('.foo', visible: :all) expect(page).to have_link('my link', visible: :hidden) ---- === Configurable attributes |=== | Name | Default value | Configurable values | VersionAdded | `1.39` | String |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/VisibilityMatcher rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_factorybot.adoc000066400000000000000000000035571370170147500247120ustar00rootroot00000000000000= FactoryBot == FactoryBot/AttributeDefinedStatically |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Always declare attribute values as blocks. === Examples [source,ruby] ---- # bad kind [:active, :rejected].sample # good kind { [:active, :rejected].sample } # bad closed_at 1.day.from_now # good closed_at { 1.day.from_now } # bad count 1 # good count { 1 } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/AttributeDefinedStatically == FactoryBot/CreateList |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for create_list usage. This cop can be configured using the `EnforcedStyle` option === Examples ==== `EnforcedStyle: create_list` [source,ruby] ---- # bad 3.times { create :user } # good create_list :user, 3 # good 3.times { |n| create :user, created_at: n.months.ago } ---- ==== `EnforcedStyle: n_times` [source,ruby] ---- # bad create_list :user, 3 # good 3.times { create :user } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `create_list` | `create_list`, `n_times` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList == FactoryBot/FactoryClassName |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Use string value when setting the class attribute explicitly. This cop would promote faster tests by lazy-loading of application files. Also, this could help you suppress potential bugs in combination with external libraries by avoiding a preload of application files from the factory files. === Examples [source,ruby] ---- # bad factory :foo, class: Foo do end # good factory :foo, class: 'Foo' do end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rails.adoc000066400000000000000000000021401370170147500236330ustar00rootroot00000000000000= Rails == Rails/HttpStatus |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Enforces use of symbolic or numeric value to describe HTTP status. === Examples ==== `EnforcedStyle: symbolic` (default) [source,ruby] ---- # bad it { is_expected.to have_http_status 200 } it { is_expected.to have_http_status 404 } # good it { is_expected.to have_http_status :ok } it { is_expected.to have_http_status :not_found } it { is_expected.to have_http_status :success } it { is_expected.to have_http_status :error } ---- ==== `EnforcedStyle: numeric` [source,ruby] ---- # bad it { is_expected.to have_http_status :ok } it { is_expected.to have_http_status :not_found } # good it { is_expected.to have_http_status 200 } it { is_expected.to have_http_status 404 } it { is_expected.to have_http_status :success } it { is_expected.to have_http_status :error } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `symbolic` | `numeric`, `symbolic` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec.adoc000066400000000000000000001623061370170147500236500ustar00rootroot00000000000000= RSpec == RSpec/AlignLeftLetBrace |=== | Enabled by default | Supports autocorrection | Disabled | Yes |=== Checks that left braces for adjacent single line lets are aligned. === Examples [source,ruby] ---- # bad let(:foobar) { blahblah } let(:baz) { bar } let(:a) { b } # good let(:foobar) { blahblah } let(:baz) { bar } let(:a) { b } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignLeftLetBrace == RSpec/AlignRightLetBrace |=== | Enabled by default | Supports autocorrection | Disabled | Yes |=== Checks that right braces for adjacent single line lets are aligned. === Examples [source,ruby] ---- # bad let(:foobar) { blahblah } let(:baz) { bar } let(:a) { b } # good let(:foobar) { blahblah } let(:baz) { bar } let(:a) { b } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignRightLetBrace == RSpec/AnyInstance |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check that instances are not being stubbed globally. Prefer instance doubles over stubbing any instance of a class === Examples [source,ruby] ---- # bad describe MyClass do before { allow_any_instance_of(MyClass).to receive(:foo) } end # good describe MyClass do let(:my_instance) { instance_double(MyClass) } before do allow(MyClass).to receive(:new).and_return(my_instance) allow(my_instance).to receive(:foo) end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance == RSpec/AroundBlock |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that around blocks actually run the test. === Examples [source,ruby] ---- # bad around do some_method end around do |test| some_method end # good around do |test| some_method test.call end around do |test| some_method test.run end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AroundBlock == RSpec/Be |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check for expectations where `be` is used without argument. The `be` matcher is too generic, as it pass on everything that is not nil or false. If that is the exact intend, use `be_truthy`. In all other cases it's better to specify what exactly is the expected value. === Examples [source,ruby] ---- # bad expect(foo).to be # good expect(foo).to be_truthy expect(foo).to be 1.0 expect(foo).to be(true) ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be == RSpec/BeEql |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Check for expectations where `+be(...)+` can replace `+eql(...)+`. The `be` matcher compares by identity while the `eql` matcher compares using `eql?`. Integers, floats, booleans, symbols, and nil can be compared by identity and therefore the `be` matcher is preferable as it is a more strict test. This cop only looks for instances of `+expect(...).to eql(...)+`. We do not check `to_not` or `not_to` since `!eql?` is more strict than `!equal?`. We also do not try to flag `eq` because if `a == b`, and `b` is comparable by identity, `a` is still not necessarily the same type as `b` since the `#==` operator can coerce objects for comparison. === Examples [source,ruby] ---- # bad expect(foo).to eql(1) expect(foo).to eql(1.0) expect(foo).to eql(true) expect(foo).to eql(false) expect(foo).to eql(:bar) expect(foo).to eql(nil) # good expect(foo).to be(1) expect(foo).to be(1.0) expect(foo).to be(true) expect(foo).to be(false) expect(foo).to be(:bar) expect(foo).to be(nil) ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql == RSpec/BeforeAfterAll |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check that before/after(:all) isn't being used. === Examples [source,ruby] ---- # bad # # Faster but risk of state leaking between examples # describe MyClass do before(:all) { Widget.create } after(:all) { Widget.delete_all } end # good # # Slower but examples are properly isolated # describe MyClass do before(:each) { Widget.create } after(:each) { Widget.delete_all } end ---- === Configurable attributes |=== | Name | Default value | Configurable values | Exclude | `spec/spec_helper.rb`, `spec/rails_helper.rb`, `+spec/support/**/*.rb+` | Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll == RSpec/ContextMethod |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== `context` should not be used for specifying methods. === Examples [source,ruby] ---- # bad context '#foo_bar' do # ... end context '.foo_bar' do # ... end # good describe '#foo_bar' do # ... end describe '.foo_bar' do # ... end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod == RSpec/ContextWording |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that `context` docstring starts with an allowed prefix. The default list of prefixes is minimal. Users are encouraged to tailor the configuration to meet project needs. Other acceptable prefixes may include `if`, `unless`, `for`, `before`, `after`, or `during`. === Examples ==== `Prefixes` configuration [source,ruby] ---- # .rubocop.yml # RSpec/ContextWording: # Prefixes: # - when # - with # - without # - if # - unless # - for ---- [source,ruby] ---- # bad context 'the display name not present' do # ... end # good context 'when the display name is not present' do # ... end ---- === Configurable attributes |=== | Name | Default value | Configurable values | Prefixes | `when`, `with`, `without` | Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording == RSpec/DescribeClass |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check that the first argument to the top level describe is a constant. === Examples [source,ruby] ---- # bad describe 'Do something' do end # good describe TestedClass do subject { described_class } end describe 'TestedClass::VERSION' do subject { Object.const_get(self.class.description) } end describe "A feature example", type: :feature do end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass == RSpec/DescribeMethod |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that the second argument to `describe` specifies a method. === Examples [source,ruby] ---- # bad describe MyClass, 'do something' do end # good describe MyClass, '#my_instance_method' do end describe MyClass, '.my_class_method' do end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeMethod == RSpec/DescribeSymbol |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Avoid describing symbols. === Examples [source,ruby] ---- # bad describe :my_method do # ... end # good describe '#my_method' do # ... end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol == RSpec/DescribedClass |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks that tests use `described_class`. If the first argument of describe is a class, the class is exposed to each example via described_class. This cop can be configured using the `EnforcedStyle` and `SkipBlocks` options. There's a known caveat with rspec-rails's `controller` helper that runs its block in a different context, and `described_class` is not available to it. `SkipBlocks` option excludes detection in all non-RSpec related blocks. To narrow down this setting to only a specific directory, it is possible to use an overriding configuration file local to that directory. === Examples ==== `EnforcedStyle: described_class` [source,ruby] ---- # bad describe MyClass do subject { MyClass.do_something } end # good describe MyClass do subject { described_class.do_something } end ---- ==== `EnforcedStyle: explicit` [source,ruby] ---- # bad describe MyClass do subject { described_class.do_something } end # good describe MyClass do subject { MyClass.do_something } end ---- ==== `SkipBlocks: true` [source,ruby] ---- # spec/controllers/.rubocop.yml # RSpec/DescribedClass: # SkipBlocks: true # acceptable describe MyConcern do controller(ApplicationController) do include MyConcern end end ---- === Configurable attributes |=== | Name | Default value | Configurable values | SkipBlocks | `false` | Boolean | EnforcedStyle | `described_class` | `described_class`, `explicit` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass == RSpec/DescribedClassModuleWrapping |=== | Enabled by default | Supports autocorrection | Disabled | No |=== Avoid opening modules and defining specs within them. === Examples [source,ruby] ---- # bad module MyModule RSpec.describe MyClass do # ... end end # good RSpec.describe MyModule::MyClass do # ... end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping == RSpec/Dialect |=== | Enabled by default | Supports autocorrection | Disabled | Yes |=== This cop enforces custom RSpec dialects. A dialect can be based on the following RSpec methods: * describe, context, feature, example_group * xdescribe, xcontext, xfeature * fdescribe, fcontext, ffeature * shared_examples, shared_examples_for, shared_context * it, specify, example, scenario, its * fit, fspecify, fexample, fscenario, focus * xit, xspecify, xexample, xscenario, skip * pending * prepend_before, before, append_before, * around * prepend_after, after, append_after * let, let! * subject, subject! * expect, is_expected, expect_any_instance_of By default all of the RSpec methods and aliases are allowed. By setting a config like: RSpec/Dialect: PreferredMethods: context: describe You can expect the following behavior: === Examples [source,ruby] ---- # bad context 'display name presence' do # ... end # good describe 'display name presence' do # ... end ---- === Configurable attributes |=== | Name | Default value | Configurable values | PreferredMethods | `{}` | |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect == RSpec/EmptyExampleGroup |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks if an example group does not include any tests. This cop is configurable using the `CustomIncludeMethods` option === Examples ==== usage [source,ruby] ---- # bad describe Bacon do let(:bacon) { Bacon.new(chunkiness) } let(:chunkiness) { false } context 'extra chunky' do # flagged by rubocop let(:chunkiness) { true } end it 'is chunky' do expect(bacon.chunky?).to be_truthy end end # good describe Bacon do let(:bacon) { Bacon.new(chunkiness) } let(:chunkiness) { false } it 'is chunky' do expect(bacon.chunky?).to be_truthy end end ---- ==== configuration [source,ruby] ---- # .rubocop.yml # RSpec/EmptyExampleGroup: # CustomIncludeMethods: # - include_tests # spec_helper.rb RSpec.configure do |config| config.alias_it_behaves_like_to(:include_tests) end # bacon_spec.rb describe Bacon do let(:bacon) { Bacon.new(chunkiness) } let(:chunkiness) { false } context 'extra chunky' do # not flagged by rubocop let(:chunkiness) { true } include_tests 'shared tests' end end ---- === Configurable attributes |=== | Name | Default value | Configurable values | CustomIncludeMethods | `[]` | Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup == RSpec/EmptyHook |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for empty before and after hooks. === Examples [source,ruby] ---- # bad before {} after do; end before(:all) do end after(:all) { } # good before { create_users } after do cleanup_users end before(:all) do create_feed end after(:all) { cleanup_feed } ---- === Configurable attributes |=== | Name | Default value | Configurable values | VersionAdded | `1.39.0` | String |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook == RSpec/EmptyLineAfterExample |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks if there is an empty line after example blocks. === Examples [source,ruby] ---- # bad RSpec.describe Foo do it 'does this' do end it 'does that' do end end # good RSpec.describe Foo do it 'does this' do end it 'does that' do end end # fair - it's ok to have non-separated one-liners RSpec.describe Foo do it { one } it { two } end ---- ==== with AllowConsecutiveOneLiners configuration [source,ruby] ---- # rubocop.yml # RSpec/EmptyLineAfterExample: # AllowConsecutiveOneLiners: false # bad RSpec.describe Foo do it { one } it { two } end ---- === Configurable attributes |=== | Name | Default value | Configurable values | AllowConsecutiveOneLiners | `true` | Boolean |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample == RSpec/EmptyLineAfterExampleGroup |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks if there is an empty line after example group blocks. === Examples [source,ruby] ---- # bad RSpec.describe Foo do describe '#bar' do end describe '#baz' do end end # good RSpec.describe Foo do describe '#bar' do end describe '#baz' do end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExampleGroup == RSpec/EmptyLineAfterFinalLet |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks if there is an empty line after the last let block. === Examples [source,ruby] ---- # bad let(:foo) { bar } let(:something) { other } it { does_something } # good let(:foo) { bar } let(:something) { other } it { does_something } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterFinalLet == RSpec/EmptyLineAfterHook |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks if there is an empty line after hook blocks. === Examples [source,ruby] ---- # bad before { do_something } it { does_something } # bad after { do_something } it { does_something } # bad around { |test| test.run } it { does_something } # good before { do_something } it { does_something } # good after { do_something } it { does_something } # good around { |test| test.run } it { does_something } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook == RSpec/EmptyLineAfterSubject |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks if there is an empty line after subject block. === Examples [source,ruby] ---- # bad subject(:obj) { described_class } let(:foo) { bar } # good subject(:obj) { described_class } let(:foo) { bar } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject == RSpec/ExampleLength |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for long examples. A long example is usually more difficult to understand. Consider extracting out some behaviour, e.g. with a `let` block, or a helper method. === Examples [source,ruby] ---- # bad it do service = described_class.new more_setup more_setup result = service.call expect(result).to be(true) end # good it do service = described_class.new result = service.call expect(result).to be(true) end ---- === Configurable attributes |=== | Name | Default value | Configurable values | Max | `5` | Integer |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength == RSpec/ExampleWithoutDescription |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for examples without a description. RSpec allows for auto-generated example descriptions when there is no description provided or the description is an empty one. This cop removes empty descriptions. It also defines whether auto-generated description is allowed, based on the configured style. This cop can be configured using the `EnforcedStyle` option === Examples ==== `EnforcedStyle: always_allow` [source,ruby] ---- # bad it('') { is_expected.to be_good } it '' do result = service.call expect(result).to be(true) end # good it { is_expected.to be_good } it do result = service.call expect(result).to be(true) end ---- ==== `EnforcedStyle: single_line_only` [source,ruby] ---- # bad it('') { is_expected.to be_good } it do result = service.call expect(result).to be(true) end # good it { is_expected.to be_good } ---- ==== `EnforcedStyle: disallow` [source,ruby] ---- # bad it { is_expected.to be_good } it do result = service.call expect(result).to be(true) end ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `always_allow` | `always_allow`, `single_line_only`, `disallow` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription == RSpec/ExampleWording |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for common mistakes in example descriptions. This cop will correct docstrings that begin with 'should' and 'it'. The autocorrect is experimental - use with care! It can be configured with CustomTransform (e.g. have \=> has) and IgnoredWords (e.g. only). === Examples [source,ruby] ---- # bad it 'should find nothing' do end # good it 'finds nothing' do end ---- [source,ruby] ---- # bad it 'it does things' do end # good it 'does things' do end ---- === Configurable attributes |=== | Name | Default value | Configurable values | CustomTransform | `+{"be"=>"is", "BE"=>"IS", "have"=>"has", "HAVE"=>"HAS"}+` | | IgnoredWords | `[]` | Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording == RSpec/ExpectActual |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for `+expect(...)+` calls containing literal values. === Examples [source,ruby] ---- # bad expect(5).to eq(price) expect(/foo/).to eq(pattern) expect("John").to eq(name) # good expect(price).to eq(5) expect(pattern).to eq(/foo/) expect(name).to eq("John") ---- === Configurable attributes |=== | Name | Default value | Configurable values | Exclude | `+spec/routing/**/*+` | Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectActual == RSpec/ExpectChange |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for consistent style of change matcher. Enforces either passing object and attribute as arguments to the matcher or passing a block that reads the attribute value. This cop can be configured using the `EnforcedStyle` option. === Examples ==== `EnforcedStyle: block` [source,ruby] ---- # bad expect { run }.to change(Foo, :bar) # good expect { run }.to change { Foo.bar } ---- ==== `EnforcedStyle: method_call` [source,ruby] ---- # bad expect { run }.to change { Foo.bar } expect { run }.to change { foo.baz } # good expect { run }.to change(Foo, :bar) expect { run }.to change(foo, :baz) # also good when there are arguments or chained method calls expect { run }.to change { Foo.bar(:count) } expect { run }.to change { user.reload.name } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `method_call` | `method_call`, `block` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectChange == RSpec/ExpectInHook |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Do not use `expect` in hooks such as `before`. === Examples [source,ruby] ---- # bad before do expect(something).to eq 'foo' end # bad after do expect_any_instance_of(Something).to receive(:foo) end # good it do expect(something).to eq 'foo' end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectInHook == RSpec/ExpectOutput |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for opportunities to use `+expect { ... }.to output+`. === Examples [source,ruby] ---- # bad $stdout = StringIO.new my_app.print_report $stdout = STDOUT expect($stdout.string).to eq('Hello World') # good expect { my_app.print_report }.to output('Hello World').to_stdout ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectOutput == RSpec/FilePath |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that spec file paths are consistent and well-formed. By default, this checks that spec file paths are consistent with the test subject and and enforces that it reflects the described class/module and its optionally called out method. With the configuration option `IgnoreMethods` the called out method will be ignored when determining the enforced path. With the configuration option `CustomTransform` modules or classes can be specified that should not as usual be transformed from CamelCase to snake_case (e.g. 'RuboCop' \=> 'rubocop' ). With the configuration option `SpecSuffixOnly` test files will only be checked to ensure they end in '_spec.rb'. This option disables checking for consistency in the test subject or test methods. === Examples [source,ruby] ---- # bad whatever_spec.rb # describe MyClass # bad my_class_spec.rb # describe MyClass, '#method' # good my_class_spec.rb # describe MyClass # good my_class_method_spec.rb # describe MyClass, '#method' # good my_class/method_spec.rb # describe MyClass, '#method' ---- ==== when configuration is `IgnoreMethods: true` [source,ruby] ---- # bad whatever_spec.rb # describe MyClass # good my_class_spec.rb # describe MyClass # good my_class_spec.rb # describe MyClass, '#method' ---- ==== when configuration is `SpecSuffixOnly: true` [source,ruby] ---- # good whatever_spec.rb # describe MyClass # good my_class_spec.rb # describe MyClass # good my_class_spec.rb # describe MyClass, '#method' ---- === Configurable attributes |=== | Name | Default value | Configurable values | CustomTransform | `+{"RuboCop"=>"rubocop", "RSpec"=>"rspec"}+` | | IgnoreMethods | `false` | Boolean | SpecSuffixOnly | `false` | Boolean |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FilePath == RSpec/Focus |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks if examples are focused. === Examples [source,ruby] ---- # bad describe MyClass, focus: true do end describe MyClass, :focus do end fdescribe MyClass do end # good describe MyClass do end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Focus == RSpec/HookArgument |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks the arguments passed to `before`, `around`, and `after`. This cop checks for consistent style when specifying RSpec hooks which run for each example. There are three supported styles: "implicit", "each", and "example." All styles have the same behavior. === Examples ==== when configuration is `EnforcedStyle: implicit` [source,ruby] ---- # bad before(:each) do # ... end # bad before(:example) do # ... end # good before do # ... end ---- ==== when configuration is `EnforcedStyle: each` [source,ruby] ---- # bad before(:example) do # ... end # good before do # ... end # good before(:each) do # ... end ---- ==== when configuration is `EnforcedStyle: example` [source,ruby] ---- # bad before(:each) do # ... end # bad before do # ... end # good before(:example) do # ... end ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `implicit` | `implicit`, `each`, `example` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HookArgument == RSpec/HooksBeforeExamples |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for before/around/after hooks that come after an example. === Examples [source,ruby] ---- # Bad it 'checks what foo does' do expect(foo).to be end before { prepare } after { clean_up } # Good before { prepare } after { clean_up } it 'checks what foo does' do expect(foo).to be end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples == RSpec/ImplicitBlockExpectation |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check that implicit block expectation syntax is not used. Prefer using explicit block expectations. === Examples [source,ruby] ---- # bad subject { -> { do_something } } it { is_expected.to change(something).to(new_value) } # good it 'changes something to a new value' do expect { do_something }.to change(something).to(new_value) end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitBlockExpectation == RSpec/ImplicitExpect |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Check that a consistent implicit expectation style is used. This cop can be configured using the `EnforcedStyle` option and supports the `--auto-gen-config` flag. === Examples ==== `EnforcedStyle: is_expected` [source,ruby] ---- # bad it { should be_truthy } # good it { is_expected.to be_truthy } ---- ==== `EnforcedStyle: should` [source,ruby] ---- # bad it { is_expected.to be_truthy } # good it { should be_truthy } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `is_expected` | `is_expected`, `should` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitExpect == RSpec/ImplicitSubject |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for usage of implicit subject (`is_expected` / `should`). This cop can be configured using the `EnforcedStyle` option === Examples ==== `EnforcedStyle: single_line_only` [source,ruby] ---- # bad it do is_expected.to be_truthy end # good it { is_expected.to be_truthy } it do expect(subject).to be_truthy end ---- ==== `EnforcedStyle: disallow` [source,ruby] ---- # bad it { is_expected.to be_truthy } # good it { expect(subject).to be_truthy } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `single_line_only` | `single_line_only`, `single_statement_only`, `disallow` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject == RSpec/InstanceSpy |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for `instance_double` used with `have_received`. === Examples [source,ruby] ---- # bad it do foo = instance_double(Foo).as_null_object expect(foo).to have_received(:bar) end # good it do foo = instance_spy(Foo) expect(foo).to have_received(:bar) end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceSpy == RSpec/InstanceVariable |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for instance variable usage in specs. This cop can be configured with the option `AssignmentOnly` which will configure the cop to only register offenses on instance variable usage if the instance variable is also assigned within the spec === Examples [source,ruby] ---- # bad describe MyClass do before { @foo = [] } it { expect(@foo).to be_empty } end # good describe MyClass do let(:foo) { [] } it { expect(foo).to be_empty } end ---- ==== with AssignmentOnly configuration [source,ruby] ---- # rubocop.yml # RSpec/InstanceVariable: # AssignmentOnly: false # bad describe MyClass do before { @foo = [] } it { expect(@foo).to be_empty } end # allowed describe MyClass do it { expect(@foo).to be_empty } end # good describe MyClass do let(:foo) { [] } it { expect(foo).to be_empty } end ---- === Configurable attributes |=== | Name | Default value | Configurable values | AssignmentOnly | `false` | Boolean |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceVariable == RSpec/InvalidPredicateMatcher |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks invalid usage for predicate matcher. Predicate matcher does not need a question. This cop checks an unnecessary question in predicate matcher. === Examples [source,ruby] ---- # bad expect(foo).to be_something? # good expect(foo).to be_something ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InvalidPredicateMatcher == RSpec/ItBehavesLike |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks that only one `it_behaves_like` style is used. === Examples ==== when configuration is `EnforcedStyle: it_behaves_like` [source,ruby] ---- # bad it_should_behave_like 'a foo' # good it_behaves_like 'a foo' ---- ==== when configuration is `EnforcedStyle: it_should_behave_like` [source,ruby] ---- # bad it_behaves_like 'a foo' # good it_should_behave_like 'a foo' ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `it_behaves_like` | `it_behaves_like`, `it_should_behave_like` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike == RSpec/IteratedExpectation |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check that `all` matcher is used instead of iterating over an array. === Examples [source,ruby] ---- # bad it 'validates users' do [user1, user2, user3].each { |user| expect(user).to be_valid } end # good it 'validates users' do expect([user1, user2, user3]).to all(be_valid) end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IteratedExpectation == RSpec/LeadingSubject |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Enforce that subject is the first definition in the test. === Examples [source,ruby] ---- # bad let(:params) { blah } subject { described_class.new(params) } before { do_something } subject { described_class.new(params) } it { expect_something } subject { described_class.new(params) } it { expect_something_else } # good subject { described_class.new(params) } let(:params) { blah } # good subject { described_class.new(params) } before { do_something } # good subject { described_class.new(params) } it { expect_something } it { expect_something_else } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject == RSpec/LeakyConstantDeclaration |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that no class, module, or constant is declared. Constants, including classes and modules, when declared in a block scope, are defined in global namespace, and leak between examples. If several examples may define a `DummyClass`, instead of being a blank slate class as it will be in the first example, subsequent examples will be reopening it and modifying its behaviour in unpredictable ways. Even worse when a class that exists in the codebase is reopened. Anonymous classes are fine, since they don't result in global namespace name clashes. === Examples ==== Constants leak between examples [source,ruby] ---- # bad describe SomeClass do OtherClass = Struct.new CONSTANT_HERE = 'I leak into global namespace' end # good describe SomeClass do before do stub_const('OtherClass', Struct.new) stub_const('CONSTANT_HERE', 'I only exist during this example') end end ---- [source,ruby] ---- # bad describe SomeClass do class FooClass < described_class def double_that some_base_method * 2 end end it { expect(FooClass.new.double_that).to eq(4) } end # good - anonymous class, no constant needs to be defined describe SomeClass do let(:foo_class) do Class.new(described_class) do def double_that some_base_method * 2 end end end it { expect(foo_class.new.double_that).to eq(4) } end # good - constant is stubbed describe SomeClass do before do foo_class = Class.new(described_class) do def do_something end end stub_const('FooClass', foo_class) end it { expect(FooClass.new.double_that).to eq(4) } end ---- [source,ruby] ---- # bad describe SomeClass do module SomeModule class SomeClass def do_something end end end end # good describe SomeClass do before do foo_class = Class.new(described_class) do def do_something end end stub_const('SomeModule::SomeClass', foo_class) end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeakyConstantDeclaration == RSpec/LetBeforeExamples |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for `let` definitions that come after an example. === Examples [source,ruby] ---- # Bad let(:foo) { bar } it 'checks what foo does' do expect(foo).to be end let(:some) { other } it 'checks what some does' do expect(some).to be end # Good let(:foo) { bar } let(:some) { other } it 'checks what foo does' do expect(foo).to be end it 'checks what some does' do expect(some).to be end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetBeforeExamples == RSpec/LetSetup |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks unreferenced `let!` calls being used for test setup. === Examples [source,ruby] ---- # Bad let!(:my_widget) { create(:widget) } it 'counts widgets' do expect(Widget.count).to eq(1) end # Good it 'counts widgets' do create(:widget) expect(Widget.count).to eq(1) end # Good before { create(:widget) } it 'counts widgets' do expect(Widget.count).to eq(1) end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup == RSpec/MessageChain |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check that chains of messages are not being stubbed. === Examples [source,ruby] ---- # bad allow(foo).to receive_message_chain(:bar, :baz).and_return(42) # better thing = Thing.new(baz: 42) allow(foo).to receive(:bar).and_return(thing) ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageChain == RSpec/MessageExpectation |=== | Enabled by default | Supports autocorrection | Disabled | No |=== Checks for consistent message expectation style. This cop can be configured in your configuration using the `EnforcedStyle` option and supports `--auto-gen-config`. === Examples ==== `EnforcedStyle: allow` [source,ruby] ---- # bad expect(foo).to receive(:bar) # good allow(foo).to receive(:bar) ---- ==== `EnforcedStyle: expect` [source,ruby] ---- # bad allow(foo).to receive(:bar) # good expect(foo).to receive(:bar) ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `allow` | `allow`, `expect` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageExpectation == RSpec/MessageSpies |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that message expectations are set using spies. This cop can be configured in your configuration using the `EnforcedStyle` option and supports `--auto-gen-config`. === Examples ==== `EnforcedStyle: have_received` [source,ruby] ---- # bad expect(foo).to receive(:bar) # good expect(foo).to have_received(:bar) ---- ==== `EnforcedStyle: receive` [source,ruby] ---- # bad expect(foo).to have_received(:bar) # good expect(foo).to receive(:bar) ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `have_received` | `have_received`, `receive` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageSpies == RSpec/MissingExampleGroupArgument |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that the first argument to an example group is not empty. === Examples [source,ruby] ---- # bad describe do end RSpec.describe do end # good describe TestedClass do end describe "A feature example" do end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument == RSpec/MultipleDescribes |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for multiple top level describes. Multiple descriptions for the same class or module should either be nested or separated into different test files. === Examples [source,ruby] ---- # bad describe MyClass, '.do_something' do end describe MyClass, '.do_something_else' do end # good describe MyClass do describe '.do_something' do end describe '.do_something_else' do end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes == RSpec/MultipleExpectations |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks if examples contain too many `expect` calls. This cop is configurable using the `Max` option and works with `--auto-gen-config`. === Examples [source,ruby] ---- # bad describe UserCreator do it 'builds a user' do expect(user.name).to eq("John") expect(user.age).to eq(22) end end # good describe UserCreator do it 'sets the users name' do expect(user.name).to eq("John") end it 'sets the users age' do expect(user.age).to eq(22) end end ---- ==== configuration [source,ruby] ---- # .rubocop.yml # RSpec/MultipleExpectations: # Max: 2 # not flagged by rubocop describe UserCreator do it 'builds a user' do expect(user.name).to eq("John") expect(user.age).to eq(22) end end ---- === Configurable attributes |=== | Name | Default value | Configurable values | Max | `1` | Integer |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations == RSpec/MultipleSubjects |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks if an example group defines `subject` multiple times. The autocorrect behavior for this cop depends on the type of duplication: * If multiple named subjects are defined then this probably indicates that the overwritten subjects (all subjects except the last definition) are effectively being used to define helpers. In this case they are replaced with `let`. * If multiple unnamed subjects are defined though then this can _only_ be dead code and we remove the overwritten subject definitions. * If subjects are defined with `subject!` then we don't autocorrect. This is enough of an edge case that people can just move this to a `before` hook on their own === Examples [source,ruby] ---- # bad describe Foo do subject(:user) { User.new } subject(:post) { Post.new } end # good describe Foo do let(:user) { User.new } subject(:post) { Post.new } end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleSubjects == RSpec/NamedSubject |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for explicitly referenced test subjects. RSpec lets you declare an "implicit subject" using `+subject { ... }+` which allows for tests like `it { is_expected.to be_valid }`. If you need to reference your test subject you should explicitly name it using `+subject(:your_subject_name) { ... }+`. Your test subjects should be the most important object in your tests so they deserve a descriptive name. This cop can be configured in your configuration using the `IgnoreSharedExamples` which will not report offenses for implicit subjects in shared example groups. === Examples [source,ruby] ---- # bad RSpec.describe User do subject { described_class.new } it 'is valid' do expect(subject.valid?).to be(true) end end # good RSpec.describe Foo do subject(:user) { described_class.new } it 'is valid' do expect(user.valid?).to be(true) end end # also good RSpec.describe Foo do subject(:user) { described_class.new } it { is_expected.to be_valid } end ---- === Configurable attributes |=== | Name | Default value | Configurable values | IgnoreSharedExamples | `true` | Boolean |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject == RSpec/NestedGroups |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for nested example groups. This cop is configurable using the `Max` option and supports `--auto-gen-config === Examples [source,ruby] ---- # bad context 'when using some feature' do let(:some) { :various } let(:feature) { :setup } context 'when user is signed in' do # flagged by rubocop let(:user) do UserCreate.call(user_attributes) end let(:user_attributes) do { name: 'John', age: 22, role: role } end context 'when user is an admin' do # flagged by rubocop let(:role) { 'admin' } it 'blah blah' it 'yada yada' end end end # better context 'using some feature as an admin' do let(:some) { :various } let(:feature) { :setup } let(:user) do UserCreate.call( name: 'John', age: 22, role: 'admin' ) end it 'blah blah' it 'yada yada' end ---- ==== configuration [source,ruby] ---- # .rubocop.yml # RSpec/NestedGroups: # Max: 2 context 'when using some feature' do let(:some) { :various } let(:feature) { :setup } context 'when user is signed in' do let(:user) do UserCreate.call(user_attributes) end let(:user_attributes) do { name: 'John', age: 22, role: role } end context 'when user is an admin' do # flagged by rubocop let(:role) { 'admin' } it 'blah blah' it 'yada yada' end end end ---- === Configurable attributes |=== | Name | Default value | Configurable values | Max | `3` | Integer |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups == RSpec/NotToNot |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for consistent method usage for negating expectations. === Examples [source,ruby] ---- # bad it '...' do expect(false).to_not be_true end # good it '...' do expect(false).not_to be_true end ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `not_to` | `not_to`, `to_not` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NotToNot == RSpec/OverwritingSetup |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks if there is a let/subject that overwrites an existing one. === Examples [source,ruby] ---- # bad let(:foo) { bar } let(:foo) { baz } subject(:foo) { bar } let(:foo) { baz } let(:foo) { bar } let!(:foo) { baz } # good subject(:test) { something } let(:foo) { bar } let(:baz) { baz } let!(:other) { other } ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/OverwritingSetup == RSpec/Pending |=== | Enabled by default | Supports autocorrection | Disabled | No |=== Checks for any pending or skipped examples. === Examples [source,ruby] ---- # bad describe MyClass do it "should be true" end describe MyClass do it "should be true", skip: true do expect(1).to eq(2) end end describe MyClass do it "should be true" do pending end end describe MyClass do xit "should be true" do end end # good describe MyClass do end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending == RSpec/PredicateMatcher |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Prefer using predicate matcher over using predicate method directly. RSpec defines magic matchers for predicate methods. This cop recommends to use the predicate matcher instead of using predicate method directly. === Examples ==== Strict: true, EnforcedStyle: inflected (default) [source,ruby] ---- # bad expect(foo.something?).to be_truthy # good expect(foo).to be_something # also good - It checks "true" strictly. expect(foo).to be(true) ---- ==== Strict: false, EnforcedStyle: inflected [source,ruby] ---- # bad expect(foo.something?).to be_truthy expect(foo).to be(true) # good expect(foo).to be_something ---- ==== Strict: true, EnforcedStyle: explicit [source,ruby] ---- # bad expect(foo).to be_something # good - the above code is rewritten to it by this cop expect(foo.something?).to be(true) ---- ==== Strict: false, EnforcedStyle: explicit [source,ruby] ---- # bad expect(foo).to be_something # good - the above code is rewritten to it by this cop expect(foo.something?).to be_truthy ---- === Configurable attributes |=== | Name | Default value | Configurable values | Strict | `true` | Boolean | EnforcedStyle | `inflected` | `inflected`, `explicit` | AllowedExplicitMatchers | `[]` | Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher == RSpec/ReceiveCounts |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Check for `once` and `twice` receive counts matchers usage. === Examples [source,ruby] ---- # bad expect(foo).to receive(:bar).exactly(1).times expect(foo).to receive(:bar).exactly(2).times expect(foo).to receive(:bar).at_least(1).times expect(foo).to receive(:bar).at_least(2).times expect(foo).to receive(:bar).at_most(1).times expect(foo).to receive(:bar).at_most(2).times # good expect(foo).to receive(:bar).once expect(foo).to receive(:bar).twice expect(foo).to receive(:bar).at_least(:once) expect(foo).to receive(:bar).at_least(:twice) expect(foo).to receive(:bar).at_most(:once) expect(foo).to receive(:bar).at_most(:twice).times ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts == RSpec/ReceiveNever |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Prefer `+not_to receive(...)+` over `+receive(...).never+`. === Examples [source,ruby] ---- # bad expect(foo).to receive(:bar).never # good expect(foo).not_to receive(:bar) ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever == RSpec/RepeatedDescription |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check for repeated description strings in example groups. === Examples [source,ruby] ---- # bad RSpec.describe User do it 'is valid' do # ... end it 'is valid' do # ... end end # good RSpec.describe User do it 'is valid when first and last name are present' do # ... end it 'is valid when last name only is present' do # ... end end # good RSpec.describe User do it 'is valid' do # ... end it 'is valid', :flag do # ... end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedDescription == RSpec/RepeatedExample |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check for repeated examples within example groups. === Examples [source,ruby] ---- it 'is valid' do expect(user).to be_valid end it 'validates the user' do expect(user).to be_valid end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExample == RSpec/RepeatedExampleGroupBody |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check for repeated describe and context block body. === Examples [source,ruby] ---- # bad describe 'cool feature x' do it { cool_predicate } end describe 'cool feature y' do it { cool_predicate } end # good describe 'cool feature' do it { cool_predicate } end describe 'another cool feature' do it { another_predicate } end # good context 'when case x', :tag do it { cool_predicate } end context 'when case y' do it { cool_predicate } end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupBody == RSpec/RepeatedExampleGroupDescription |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Check for repeated example group descriptions. === Examples [source,ruby] ---- # bad describe 'cool feature' do # example group end describe 'cool feature' do # example group end # bad context 'when case x' do # example group end describe 'when case x' do # example group end # good describe 'cool feature' do # example group end describe 'another cool feature' do # example group end # good context 'when case x' do # example group end context 'when another case' do # example group end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription == RSpec/ReturnFromStub |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for consistent style of stub's return setting. Enforces either `and_return` or block-style return in the cases where the returned value is constant. Ignores dynamic returned values are the result would be different This cop can be configured using the `EnforcedStyle` option === Examples ==== `EnforcedStyle: block` [source,ruby] ---- # bad allow(Foo).to receive(:bar).and_return("baz") expect(Foo).to receive(:bar).and_return("baz") # good allow(Foo).to receive(:bar) { "baz" } expect(Foo).to receive(:bar) { "baz" } # also good as the returned value is dynamic allow(Foo).to receive(:bar).and_return(bar.baz) ---- ==== `EnforcedStyle: and_return` [source,ruby] ---- # bad allow(Foo).to receive(:bar) { "baz" } expect(Foo).to receive(:bar) { "baz" } # good allow(Foo).to receive(:bar).and_return("baz") expect(Foo).to receive(:bar).and_return("baz") # also good as the returned value is dynamic allow(Foo).to receive(:bar) { bar.baz } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `and_return` | `and_return`, `block` |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReturnFromStub == RSpec/ScatteredLet |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for let scattered across the example group. Group lets together === Examples [source,ruby] ---- # bad describe Foo do let(:foo) { 1 } subject { Foo } let(:bar) { 2 } before { prepare } let!(:baz) { 3 } end # good describe Foo do subject { Foo } before { prepare } let(:foo) { 1 } let(:bar) { 2 } let!(:baz) { 3 } end ---- === Configurable attributes |=== | Name | Default value | Configurable values | VersionChanged | `1.39` | String |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet == RSpec/ScatteredSetup |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for setup scattered across multiple hooks in an example group. Unify `before`, `after`, and `around` hooks when possible. === Examples [source,ruby] ---- # bad describe Foo do before { setup1 } before { setup2 } end # good describe Foo do before do setup1 setup2 end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredSetup == RSpec/SharedContext |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks for proper shared_context and shared_examples usage. If there are no examples defined, use shared_context. If there is no setup defined, use shared_examples. === Examples [source,ruby] ---- # bad RSpec.shared_context 'only examples here' do it 'does x' do end it 'does y' do end end # good RSpec.shared_examples 'only examples here' do it 'does x' do end it 'does y' do end end ---- [source,ruby] ---- # bad RSpec.shared_examples 'only setup here' do subject(:foo) { :bar } let(:baz) { :bazz } before do something end end # good RSpec.shared_context 'only setup here' do subject(:foo) { :bar } let(:baz) { :bazz } before do something end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedContext == RSpec/SharedExamples |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Enforces use of string to titleize shared examples. === Examples [source,ruby] ---- # bad it_behaves_like :foo_bar_baz it_should_behave_like :foo_bar_baz shared_examples :foo_bar_baz shared_examples_for :foo_bar_baz include_examples :foo_bar_baz # good it_behaves_like 'foo bar baz' it_should_behave_like 'foo bar baz' shared_examples 'foo bar baz' shared_examples_for 'foo bar baz' include_examples 'foo bar baz' ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedExamples == RSpec/SingleArgumentMessageChain |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== Checks that chains of messages contain more than one element. === Examples [source,ruby] ---- # bad allow(foo).to receive_message_chain(:bar).and_return(42) # good allow(foo).to receive(:bar).and_return(42) # also good allow(foo).to receive(:bar, :baz) allow(foo).to receive("bar.baz") ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain == RSpec/SubjectStub |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for stubbed test subjects. === Examples [source,ruby] ---- # bad describe Foo do subject(:bar) { baz } before do allow(bar).to receive(:qux?).and_return(true) end end ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectStub == RSpec/UnspecifiedException |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks for a specified error in checking raised errors. Enforces one of an Exception type, a string, or a regular expression to match against the exception message as a parameter to `raise_error` === Examples [source,ruby] ---- # bad expect { raise StandardError.new('error') }.to raise_error # good expect { raise StandardError.new('error') }.to raise_error(StandardError) expect { raise StandardError.new('error') }.to raise_error('error') expect { raise StandardError.new('error') }.to raise_error(/err/) expect { do_something }.not_to raise_error ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UnspecifiedException == RSpec/VariableDefinition |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that memoized helpers names are symbols or strings. === Examples ==== EnforcedStyle: symbols (default) [source,ruby] ---- # bad let('user_name') { 'Adam' } subject('user') { create_user } # good let(:user_name) { 'Adam' } subject(:user) { create_user } ---- ==== EnforcedStyle: strings [source,ruby] ---- # bad let(:user_name) { 'Adam' } subject(:user) { create_user } # good let('user_name') { 'Adam' } subject('user') { create_user } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `symbols` | `symbols`, `strings` | VersionAdded | `1.40` | String |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableDefinition == RSpec/VariableName |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Checks that memoized helper names use the configured style. === Examples ==== EnforcedStyle: snake_case (default) [source,ruby] ---- # bad let(:userName) { 'Adam' } subject(:userName) { 'Adam' } # good let(:user_name) { 'Adam' } subject(:user_name) { 'Adam' } ---- ==== EnforcedStyle: camelCase [source,ruby] ---- # bad let(:user_name) { 'Adam' } subject(:user_name) { 'Adam' } # good let(:userName) { 'Adam' } subject(:userName) { 'Adam' } ---- === Configurable attributes |=== | Name | Default value | Configurable values | EnforcedStyle | `snake_case` | `snake_case`, `camelCase` | VersionAdded | `1.40` | String |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName == RSpec/VerifiedDoubles |=== | Enabled by default | Supports autocorrection | Enabled | No |=== Prefer using verifying doubles over normal doubles. === Examples [source,ruby] ---- # bad let(:foo) do double(method_name: 'returned value') end # bad let(:foo) do double("ClassName", method_name: 'returned value') end # good let(:foo) do instance_double("ClassName", method_name: 'returned value') end ---- === Configurable attributes |=== | Name | Default value | Configurable values | IgnoreNameless | `true` | Boolean | IgnoreSymbolicNames | `false` | Boolean |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles == RSpec/VoidExpect |=== | Enabled by default | Supports autocorrection | Enabled | No |=== This cop checks void `expect()`. === Examples [source,ruby] ---- # bad expect(something) # good expect(something).to be(1) ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect == RSpec/Yield |=== | Enabled by default | Supports autocorrection | Enabled | Yes |=== This cop checks for calling a block within a stub. === Examples [source,ruby] ---- # bad allow(foo).to receive(:bar) { |&block| block.call(1) } # good expect(foo).to be(:bar).and_yield(1) ---- === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield rubocop-rspec-1.42.0/docs/modules/ROOT/pages/index.adoc000066400000000000000000000027451370170147500226170ustar00rootroot00000000000000= RuboCop RSpec RSpec-specific analysis for your projects, as an extension to https://github.com/rubocop-hq/rubocop[RuboCop]. == Project Goals * Enforce the guidelines and best practices outlined in the community https://rspec.rubystyle.guide[RSpec style guide] * Simplify the process of adopting new RSpec functionality == Non-goals of RuboCop RSpec === Enforcing `should` vs. `expect` syntax Enforcing [source,ruby] ---- expect(calculator.compute(line_item)).to eq(5) ---- over [source,ruby] ---- calculator.compute(line_item).should == 5 ---- is a feature of RSpec itself – you can read about it in the https://relishapp.com/rspec/rspec-expectations/docs/syntax-configuration#disable-should-syntax[RSpec Documentation]. === Enforcing an explicit RSpec receiver for top-level methods (disabling monkey patching) Enforcing [source,ruby] ---- RSpec.describe MyClass do ... end ---- over [source,ruby] ---- describe MyClass do ... end ---- can be achieved using RSpec's `disable_monkey_patching!` method, which you can read more about in the 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[RSpec Documentation]. This will also prevent `should` from being defined on every object in your system. Before disabling `should` you will need all your specs to use the `expect` syntax. You can use http://yujinakayama.me/transpec/[Transpec], which will do the conversion for you. rubocop-rspec-1.42.0/docs/modules/ROOT/pages/installation.adoc000066400000000000000000000003071370170147500242010ustar00rootroot00000000000000= Installation Just install the `rubocop-rspec` gem [source,bash] ---- gem install rubocop-rspec ---- or if you use bundler put this in your `Gemfile` [source,ruby] ---- gem 'rubocop-rspec' ---- rubocop-rspec-1.42.0/docs/modules/ROOT/pages/usage.adoc000066400000000000000000000021311370170147500226010ustar00rootroot00000000000000= Usage You need to tell RuboCop to load the RSpec extension. There are three ways to do this: == RuboCop configuration file Put this into your `.rubocop.yml`. ---- require: rubocop-rspec ---- Now you can run `rubocop` and it will automatically load the RuboCop RSpec cops together with the standard cops. == Command line [source,bash] ---- $ rubocop --require rubocop-rspec ---- == Rake task [source,ruby] ---- RuboCop::RakeTask.new do |task| task.requires << 'rubocop-rspec' end ---- == Code Climate `rubocop-rspec` is available on Code Climate as part of the rubocop engine. https://codeclimate.com/changelog/55a433bbe30ba00852000fac[Learn More]. == Inspecting files that don't end with `_spec.rb` By default, `rubocop-rspec` only inspects code within paths ending in `_spec.rb` or including `spec/`. You can override this setting in your config file by specifying one or more patterns: [source,yaml] ---- # Inspect all files AllCops: RSpec: Patterns: - '.+' ---- [source,yaml] ---- # Inspect only files ending with `_test.rb` AllCops: RSpec: Patterns: - '_test.rb$' ---- rubocop-rspec-1.42.0/lib/000077500000000000000000000000001370170147500151345ustar00rootroot00000000000000rubocop-rspec-1.42.0/lib/rubocop-rspec.rb000066400000000000000000000027131370170147500202470ustar00rootroot00000000000000# frozen_string_literal: true require 'pathname' require 'yaml' require 'rubocop' require_relative 'rubocop/rspec' require_relative 'rubocop/rspec/version' require_relative 'rubocop/rspec/inject' require_relative 'rubocop/rspec/node' require_relative 'rubocop/rspec/top_level_describe' require_relative 'rubocop/rspec/wording' require_relative 'rubocop/rspec/language' require_relative 'rubocop/rspec/language/node_pattern' require_relative 'rubocop/rspec/top_level_group' require_relative 'rubocop/rspec/concept' require_relative 'rubocop/rspec/example_group' require_relative 'rubocop/rspec/example' require_relative 'rubocop/rspec/hook' require_relative 'rubocop/rspec/variable' require_relative 'rubocop/cop/rspec/cop' require_relative 'rubocop/rspec/align_let_brace' require_relative 'rubocop/rspec/factory_bot' require_relative 'rubocop/rspec/final_end_location' require_relative 'rubocop/rspec/blank_line_separation' require_relative 'rubocop/rspec/corrector/move_node' RuboCop::RSpec::Inject.defaults! require_relative 'rubocop/cop/rspec_cops' # We have to register our autocorrect incompatibilies in RuboCop's cops as well # so we do not hit infinite loops module RuboCop module Cop module Layout class ExtraSpacing # rubocop:disable Style/Documentation def self.autocorrect_incompatible_with [RSpec::AlignLeftLetBrace, RSpec::AlignRightLetBrace] end end end end end RuboCop::AST::Node.include(RuboCop::RSpec::Node) rubocop-rspec-1.42.0/lib/rubocop/000077500000000000000000000000001370170147500166055ustar00rootroot00000000000000rubocop-rspec-1.42.0/lib/rubocop/cop/000077500000000000000000000000001370170147500173665ustar00rootroot00000000000000rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/000077500000000000000000000000001370170147500205025ustar00rootroot00000000000000rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/align_left_let_brace.rb000066400000000000000000000021221370170147500251300ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that left braces for adjacent single line lets are aligned. # # @example # # # bad # let(:foobar) { blahblah } # let(:baz) { bar } # let(:a) { b } # # # good # let(:foobar) { blahblah } # let(:baz) { bar } # let(:a) { b } # class AlignLeftLetBrace < Cop extend AutoCorrector MSG = 'Align left let brace' def self.autocorrect_incompatible_with [Layout::ExtraSpacing] end def on_new_investigation return if processed_source.blank? token_aligner = RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin) token_aligner.offending_tokens.each do |let| add_offense(let.loc.begin) do |corrector| corrector.insert_before( let.loc.begin, token_aligner.indent_for(let) ) end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/align_right_let_brace.rb000066400000000000000000000021431370170147500253160ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that right braces for adjacent single line lets are aligned. # # @example # # # bad # let(:foobar) { blahblah } # let(:baz) { bar } # let(:a) { b } # # # good # let(:foobar) { blahblah } # let(:baz) { bar } # let(:a) { b } # class AlignRightLetBrace < Cop extend AutoCorrector MSG = 'Align right let brace' def self.autocorrect_incompatible_with [Layout::ExtraSpacing] end def on_new_investigation return if processed_source.blank? token_aligner = RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end) token_aligner.offending_tokens.each do |let| add_offense(let.loc.end) do |corrector| corrector.insert_before( let.loc.end, token_aligner.indent_for(let) ) end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/any_instance.rb000066400000000000000000000021631370170147500235040ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check that instances are not being stubbed globally. # # Prefer instance doubles over stubbing any instance of a class # # @example # # bad # describe MyClass do # before { allow_any_instance_of(MyClass).to receive(:foo) } # end # # # good # describe MyClass do # let(:my_instance) { instance_double(MyClass) } # # before do # allow(MyClass).to receive(:new).and_return(my_instance) # allow(my_instance).to receive(:foo) # end # end class AnyInstance < Cop MSG = 'Avoid stubbing using `%s`.' def_node_matcher :disallowed_stub, <<-PATTERN (send _ ${:any_instance :allow_any_instance_of :expect_any_instance_of} ...) PATTERN def on_send(node) disallowed_stub(node) do |method| add_offense( node, message: format(MSG, method: method) ) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/around_block.rb000066400000000000000000000032741370170147500234770ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that around blocks actually run the test. # # @example # # bad # around do # some_method # end # # around do |test| # some_method # end # # # good # around do |test| # some_method # test.call # end # # around do |test| # some_method # test.run # end class AroundBlock < Cop MSG_NO_ARG = 'Test object should be passed to around block.' MSG_UNUSED_ARG = 'You should call `%s.call` '\ 'or `%s.run`.' def_node_matcher :hook, <<-PATTERN (block {(send nil? :around) (send nil? :around sym)} (args $...) ...) PATTERN def_node_search :find_arg_usage, <<-PATTERN {(send $... {:call :run}) (send _ _ $...) (yield $...) (block-pass $...)} PATTERN def on_block(node) hook(node) do |(example_proxy)| if example_proxy.nil? add_no_arg_offense(node) else check_for_unused_proxy(node, example_proxy) end end end private def add_no_arg_offense(node) add_offense(node, message: MSG_NO_ARG) end def check_for_unused_proxy(block, proxy) name, = *proxy find_arg_usage(block) do |usage| return if usage.include?(s(:lvar, name)) end add_offense( proxy, message: format(MSG_UNUSED_ARG, arg: name) ) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be.rb000066400000000000000000000017271370170147500214240ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check for expectations where `be` is used without argument. # # The `be` matcher is too generic, as it pass on everything that is not # nil or false. If that is the exact intend, use `be_truthy`. In all other # cases it's better to specify what exactly is the expected value. # # @example # # # bad # expect(foo).to be # # # good # expect(foo).to be_truthy # expect(foo).to be 1.0 # expect(foo).to be(true) # class Be < Cop MSG = 'Don\'t use `be` without an argument.' def_node_matcher :be_without_args, <<-PATTERN (send _ #{Runners::ALL.node_pattern_union} $(send nil? :be)) PATTERN def on_send(node) be_without_args(node) do |matcher| add_offense(matcher.loc.selector) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be_eql.rb000066400000000000000000000034271370170147500222640ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check for expectations where `be(...)` can replace `eql(...)`. # # The `be` matcher compares by identity while the `eql` matcher # compares using `eql?`. Integers, floats, booleans, symbols, and nil # can be compared by identity and therefore the `be` matcher is # preferable as it is a more strict test. # # @example # # # bad # expect(foo).to eql(1) # expect(foo).to eql(1.0) # expect(foo).to eql(true) # expect(foo).to eql(false) # expect(foo).to eql(:bar) # expect(foo).to eql(nil) # # # good # expect(foo).to be(1) # expect(foo).to be(1.0) # expect(foo).to be(true) # expect(foo).to be(false) # expect(foo).to be(:bar) # expect(foo).to be(nil) # # This cop only looks for instances of `expect(...).to eql(...)`. We # do not check `to_not` or `not_to` since `!eql?` is more strict # than `!equal?`. We also do not try to flag `eq` because if # `a == b`, and `b` is comparable by identity, `a` is still not # necessarily the same type as `b` since the `#==` operator can # coerce objects for comparison. # class BeEql < Cop extend AutoCorrector MSG = 'Prefer `be` over `eql`.' def_node_matcher :eql_type_with_identity, <<-PATTERN (send _ :to $(send nil? :eql {true false int float sym nil_type?})) PATTERN def on_send(node) eql_type_with_identity(node) do |eql| add_offense(eql.loc.selector) do |corrector| corrector.replace(eql.loc.selector, 'be') end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/before_after_all.rb000066400000000000000000000024561370170147500243110ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check that before/after(:all) isn't being used. # # @example # # bad # # # # Faster but risk of state leaking between examples # # # describe MyClass do # before(:all) { Widget.create } # after(:all) { Widget.delete_all } # end # # # good # # # # Slower but examples are properly isolated # # # describe MyClass do # before(:each) { Widget.create } # after(:each) { Widget.delete_all } # end class BeforeAfterAll < Cop MSG = 'Beware of using `%s` as it may cause state to leak '\ 'between tests. If you are using `rspec-rails`, and '\ '`use_transactional_fixtures` is enabled, then records created '\ 'in `%s` are not automatically rolled back.' def_node_matcher :before_or_after_all, <<-PATTERN $(send _ {:before :after} (sym {:all :context})) PATTERN def on_send(node) before_or_after_all(node) do |hook| add_offense( node, message: format(MSG, hook: hook.source) ) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/000077500000000000000000000000001370170147500222645ustar00rootroot00000000000000rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb000066400000000000000000000103271370170147500277150ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec module Capybara # Checks that no expectations are set on Capybara's `current_path`. # # The `have_current_path` matcher (https://www.rubydoc.info/github/ # teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path- # instance_method) should be used on `page` to set expectations on # Capybara's current path, since it uses Capybara's waiting # functionality (https://github.com/teamcapybara/capybara/blob/master/ # README.md#asynchronous-javascript-ajax-and-friends) which ensures that # preceding actions (like `click_link`) have completed. # # @example # # bad # expect(current_path).to eq('/callback') # expect(page.current_path).to match(/widgets/) # # # good # expect(page).to have_current_path("/callback") # expect(page).to have_current_path(/widgets/) # class CurrentPathExpectation < Cop extend AutoCorrector MSG = 'Do not set an RSpec expectation on `current_path` in ' \ 'Capybara feature specs - instead, use the ' \ '`have_current_path` matcher on `page`' def_node_matcher :expectation_set_on_current_path, <<-PATTERN (send nil? :expect (send {(send nil? :page) nil?} :current_path)) PATTERN # Supported matchers: eq(...) / match(/regexp/) / match('regexp') def_node_matcher :as_is_matcher, <<-PATTERN (send #expectation_set_on_current_path $#{Runners::ALL.node_pattern_union} ${(send nil? :eq ...) (send nil? :match (regexp ...))}) PATTERN def_node_matcher :regexp_str_matcher, <<-PATTERN (send #expectation_set_on_current_path $#{Runners::ALL.node_pattern_union} $(send nil? :match (str $_))) PATTERN def on_send(node) expectation_set_on_current_path(node) do add_offense(node.loc.selector) do |corrector| next unless node.chained? autocorrect(corrector, node) end end end private def autocorrect(corrector, node) as_is_matcher(node.parent) do |to_sym, matcher_node| rewrite_expectation(corrector, node, to_sym, matcher_node) end regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp| rewrite_expectation(corrector, node, to_sym, matcher_node) convert_regexp_str_to_literal(corrector, matcher_node, regexp) end end def rewrite_expectation(corrector, node, to_symbol, matcher_node) current_path_node = node.first_argument corrector.replace(current_path_node, 'page') corrector.replace(node.parent.loc.selector, 'to') matcher_method = if to_symbol == :to 'have_current_path' else 'have_no_current_path' end corrector.replace(matcher_node.loc.selector, matcher_method) add_ignore_query_options(corrector, node) end def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str) str_node = matcher_node.first_argument regexp_expr = Regexp.new(regexp_str).inspect corrector.replace(str_node, regexp_expr) end # `have_current_path` with no options will include the querystring # while `page.current_path` does not. # This ensures the option `ignore_query: true` is added # except when the expectation is a regexp or string def add_ignore_query_options(corrector, node) expectation_node = node.parent.last_argument expectation_last_child = expectation_node.children.last return if %i[regexp str].include?(expectation_last_child.type) corrector.insert_after( expectation_last_child, ', ignore_query: true' ) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/feature_methods.rb000066400000000000000000000063171370170147500257760ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec module Capybara # Checks for consistent method usage in feature specs. # # By default, the cop disables all Capybara-specific methods that have # the same native RSpec method (e.g. are just aliases). Some teams # however may prefer using some of the Capybara methods (like `feature`) # to make it obvious that the test uses Capybara, while still disable # the rest of the methods, like `given` (alias for `let`), `background` # (alias for `before`), etc. You can configure which of the methods to # be enabled by using the EnabledMethods configuration option. # # @example # # bad # feature 'User logs in' do # given(:user) { User.new } # # background do # visit new_session_path # end # # scenario 'with OAuth' do # # ... # end # end # # # good # describe 'User logs in' do # let(:user) { User.new } # # before do # visit new_session_path # end # # it 'with OAuth' do # # ... # end # end class FeatureMethods < Cop extend AutoCorrector MSG = 'Use `%s` instead of `%s`.' # https://git.io/v7Kwr MAP = { background: :before, scenario: :it, xscenario: :xit, given: :let, given!: :let!, feature: :describe }.freeze def_node_matcher :spec?, <<-PATTERN (block (send #{RSPEC} {:describe :feature} ...) ...) PATTERN def_node_matcher :feature_method, <<-PATTERN (block $(send #{RSPEC} ${#{MAP.keys.map(&:inspect).join(' ')}} ...) ...) PATTERN def on_block(node) return unless inside_spec?(node) feature_method(node) do |send_node, match| next if enabled?(match) add_offense(send_node.loc.selector) do |corrector| corrector.replace(send_node.loc.selector, MAP[match].to_s) end end end def message(range) name = range.source.to_sym format(MSG, method: name, replacement: MAP[name]) end private def inside_spec?(node) return spec?(node) if root_node?(node) root = node.ancestors.find { |parent| root_node?(parent) } spec?(root) end def root_node?(node) node.parent.nil? || root_with_siblings?(node.parent) end def root_with_siblings?(node) node.begin_type? && node.parent.nil? end def enabled?(method_name) enabled_methods.include?(method_name) end def enabled_methods cop_config .fetch('EnabledMethods', []) .map(&:to_sym) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb000066400000000000000000000045451370170147500265130ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec module Capybara # Checks for boolean visibility in capybara finders. # # Capybara lets you find elements that match a certain visibility using # the `:visible` option. `:visible` accepts both boolean and symbols as # values, however using booleans can have unwanted effects. `visible: # false` does not find just invisible elements, but both visible and # invisible elements. For expressiveness and clarity, use one of the # symbol values, `:all`, `:hidden` or `:visible`. # (https://www.rubydoc.info/gems/capybara/Capybara%2FNode%2FFinders:all) # # @example # # # bad # expect(page).to have_selector('.foo', visible: false) # expect(page).to have_css('.foo', visible: true) # expect(page).to have_link('my link', visible: false) # # # good # expect(page).to have_selector('.foo', visible: :visible) # expect(page).to have_css('.foo', visible: :all) # expect(page).to have_link('my link', visible: :hidden) # class VisibilityMatcher < Cop MSG_FALSE = 'Use `:all` or `:hidden` instead of `false`.' MSG_TRUE = 'Use `:visible` instead of `true`.' CAPYBARA_MATCHER_METHODS = %i[ have_selector have_css have_xpath have_link have_button have_field have_select have_table have_checked_field have_unchecked_field have_text have_content ].freeze def_node_matcher :visible_true?, <<~PATTERN (send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) true) ...>)) PATTERN def_node_matcher :visible_false?, <<~PATTERN (send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) false) ...>)) PATTERN def on_send(node) visible_false?(node) { |arg| add_offense(arg, message: MSG_FALSE) } visible_true?(node) { |arg| add_offense(arg, message: MSG_TRUE) } end private def capybara_matcher?(method_name) CAPYBARA_MATCHER_METHODS.include? method_name end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/context_method.rb000066400000000000000000000021241370170147500240520ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # `context` should not be used for specifying methods. # # @example # # bad # context '#foo_bar' do # # ... # end # # context '.foo_bar' do # # ... # end # # # good # describe '#foo_bar' do # # ... # end # # describe '.foo_bar' do # # ... # end class ContextMethod < Cop extend AutoCorrector MSG = 'Use `describe` for testing methods.' def_node_matcher :context_method, <<-PATTERN (block (send #{RSPEC} :context $(str #method_name?) ...) ...) PATTERN def on_block(node) context_method(node) do |context| add_offense(context) do |corrector| corrector.replace(node.send_node.loc.selector, 'describe') end end end private def method_name?(description) description.start_with?('.', '#') end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/context_wording.rb000066400000000000000000000036141370170147500242500ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that `context` docstring starts with an allowed prefix. # # The default list of prefixes is minimal. Users are encouraged to tailor # the configuration to meet project needs. Other acceptable prefixes may # include `if`, `unless`, `for`, `before`, `after`, or `during`. # # @see https://rspec.rubystyle.guide/#context-descriptions # @see http://www.betterspecs.org/#contexts # # @example `Prefixes` configuration # # # .rubocop.yml # # RSpec/ContextWording: # # Prefixes: # # - when # # - with # # - without # # - if # # - unless # # - for # # @example # # bad # context 'the display name not present' do # # ... # end # # # good # context 'when the display name is not present' do # # ... # end class ContextWording < Cop MSG = 'Start context description with %s.' def_node_matcher :context_wording, <<-PATTERN (block (send #{RSPEC} { :context :shared_context } $(str #bad_prefix?) ...) ...) PATTERN def on_block(node) context_wording(node) do |context| add_offense(context, message: format(MSG, prefixes: joined_prefixes)) end end private def bad_prefix?(description) !prefixes.include?(description.split.first) end def joined_prefixes quoted = prefixes.map { |prefix| "'#{prefix}'" } return quoted.first if quoted.size == 1 quoted << "or #{quoted.pop}" quoted.join(', ') end def prefixes cop_config['Prefixes'] || [] end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/cop.rb000066400000000000000000000037631370170147500216210ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # @abstract parent class to RSpec cops # # The criteria for whether rubocop-rspec analyzes a certain ruby file # is configured via `AllCops/RSpec`. For example, if you want to # customize your project to scan all files within a `test/` directory # then you could add this to your configuration: # # @example configuring analyzed paths # # .rubocop.yml # # AllCops: # # RSpec: # # Patterns: # # - '_test.rb$' # # - '(?:^|/)test/' class Cop < ::RuboCop::Cop::Base include RuboCop::RSpec::Language include RuboCop::RSpec::Language::NodePattern DEFAULT_CONFIGURATION = RuboCop::RSpec::CONFIG.fetch('AllCops').fetch('RSpec') DEFAULT_PATTERN_RE = Regexp.union( DEFAULT_CONFIGURATION.fetch('Patterns') .map(&Regexp.public_method(:new)) ) # Invoke the original inherited hook so our cops are recognized def self.inherited(subclass) RuboCop::Cop::Cop.inherited(subclass) end def relevant_file?(file) relevant_rubocop_rspec_file?(file) && super end private def relevant_rubocop_rspec_file?(file) rspec_pattern =~ file end def rspec_pattern if rspec_pattern_config? Regexp.union(rspec_pattern_config.map(&Regexp.public_method(:new))) else DEFAULT_PATTERN_RE end end def all_cops_config config .for_all_cops end def rspec_pattern_config? return unless all_cops_config.key?('RSpec') all_cops_config.fetch('RSpec').key?('Patterns') end def rspec_pattern_config all_cops_config .fetch('RSpec', DEFAULT_CONFIGURATION) .fetch('Patterns') end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_class.rb000066400000000000000000000036641370170147500240050ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check that the first argument to the top level describe is a constant. # # @example # # bad # describe 'Do something' do # end # # # good # describe TestedClass do # subject { described_class } # end # # describe 'TestedClass::VERSION' do # subject { Object.const_get(self.class.description) } # end # # describe "A feature example", type: :feature do # end class DescribeClass < Cop include RuboCop::RSpec::TopLevelDescribe MSG = 'The first argument to describe should be '\ 'the class or module being tested.' def_node_matcher :valid_describe?, <<-PATTERN { (send #{RSPEC} :describe const ...) (send #{RSPEC} :describe) } PATTERN def_node_matcher :describe_with_rails_metadata?, <<-PATTERN (send #{RSPEC} :describe !const ... (hash <#rails_metadata? ...>) ) PATTERN def_node_matcher :rails_metadata?, <<-PATTERN (pair (sym :type) (sym { :channel :controller :helper :job :mailer :model :request :routing :view :feature :system :mailbox } ) ) PATTERN def on_top_level_describe(node, (described_value, _)) return if shared_group?(root_node) return if valid_describe?(node) return if describe_with_rails_metadata?(node) return if string_constant_describe?(described_value) add_offense(described_value) end private def string_constant_describe?(described_value) described_value.str_type? && described_value.value =~ /^((::)?[A-Z]\w*)+$/ end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_method.rb000066400000000000000000000015451370170147500241540ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that the second argument to `describe` specifies a method. # # @example # # bad # describe MyClass, 'do something' do # end # # # good # describe MyClass, '#my_instance_method' do # end # # describe MyClass, '.my_class_method' do # end class DescribeMethod < Cop include RuboCop::RSpec::TopLevelDescribe MSG = 'The second argument to describe should be the method '\ "being tested. '#instance' or '.class'." def on_top_level_describe(_node, (_, second_arg)) return unless second_arg&.str_type? return if second_arg.str_content.start_with?('#', '.') add_offense(second_arg) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_symbol.rb000066400000000000000000000013251370170147500241750ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Avoid describing symbols. # # @example # # bad # describe :my_method do # # ... # end # # # good # describe '#my_method' do # # ... # end # # @see https://github.com/rspec/rspec-core/issues/1610 class DescribeSymbol < Cop MSG = 'Avoid describing symbols.' def_node_matcher :describe_symbol?, <<-PATTERN (send #{RSPEC} :describe $sym ...) PATTERN def on_send(node) describe_symbol?(node) do |match| add_offense(match) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/described_class.rb000066400000000000000000000156621370170147500241520ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that tests use `described_class`. # # If the first argument of describe is a class, the class is exposed to # each example via described_class. # # This cop can be configured using the `EnforcedStyle` and `SkipBlocks` # options. # # @example `EnforcedStyle: described_class` # # bad # describe MyClass do # subject { MyClass.do_something } # end # # # good # describe MyClass do # subject { described_class.do_something } # end # # @example `EnforcedStyle: explicit` # # bad # describe MyClass do # subject { described_class.do_something } # end # # # good # describe MyClass do # subject { MyClass.do_something } # end # # There's a known caveat with rspec-rails's `controller` helper that # runs its block in a different context, and `described_class` is not # available to it. `SkipBlocks` option excludes detection in all # non-RSpec related blocks. # # To narrow down this setting to only a specific directory, it is # possible to use an overriding configuration file local to that # directory. # # @example `SkipBlocks: true` # # spec/controllers/.rubocop.yml # # RSpec/DescribedClass: # # SkipBlocks: true # # # acceptable # describe MyConcern do # controller(ApplicationController) do # include MyConcern # end # end # class DescribedClass < Cop extend AutoCorrector include ConfigurableEnforcedStyle DESCRIBED_CLASS = 'described_class' MSG = 'Use `%s` instead of `%s`.' def_node_matcher :common_instance_exec_closure?, <<-PATTERN (block (send (const nil? {:Class :Module :Struct}) :new ...) ...) PATTERN def_node_matcher :rspec_block?, RuboCop::RSpec::Language::ALL.block_pattern def_node_matcher :scope_changing_syntax?, '{def class module}' def_node_matcher :described_constant, <<-PATTERN (block (send _ :describe $(const ...) ...) (args) $_) PATTERN def_node_search :contains_described_class?, <<-PATTERN (send nil? :described_class) PATTERN def on_block(node) # In case the explicit style is used, we need to remember what's # being described. @described_class, body = described_constant(node) return unless body find_usage(body) do |match| msg = message(match.const_name) add_offense(match, message: msg) do |corrector| autocorrect(corrector, match) end end end private def autocorrect(corrector, match) replacement = if style == :described_class DESCRIBED_CLASS else @described_class.const_name end corrector.replace(match, replacement) end def find_usage(node, &block) yield(node) if offensive?(node) return if scope_change?(node) || node.const_type? node.each_child_node do |child| find_usage(child, &block) end end def message(offense) if style == :described_class format(MSG, replacement: DESCRIBED_CLASS, src: offense) else format(MSG, replacement: @described_class.const_name, src: DESCRIBED_CLASS) end end def scope_change?(node) scope_changing_syntax?(node) || common_instance_exec_closure?(node) || skippable_block?(node) end def skippable_block?(node) node.block_type? && !rspec_block?(node) && skip_blocks? end def skip_blocks? cop_config['SkipBlocks'] end def offensive?(node) if style == :described_class offensive_described_class?(node) else node.send_type? && node.method_name == :described_class end end def offensive_described_class?(node) return unless node.const_type? # E.g. `described_class::CONSTANT` return if contains_described_class?(node) nearest_described_class, = node.each_ancestor(:block) .map { |ancestor| described_constant(ancestor) }.find(&:itself) return if nearest_described_class.equal?(node) full_const_name(nearest_described_class) == full_const_name(node) end def full_const_name(node) collapse_namespace(namespace(node), const_name(node)) end # @param namespace [Array] # @param const [Array] # @return [Array] # @example # # nil represents base constant # collapse_namespace([], :C) # => [:C] # collapse_namespace([:A, :B], [:C) # => [:A, :B, :C] # collapse_namespace([:A, :B], [:B, :C) # => [:A, :B, :C] # collapse_namespace([:A, :B], [nil, :C) # => [nil, :C] # collapse_namespace([:A, :B], [nil, :B, :C) # => [nil, :B, :C] def collapse_namespace(namespace, const) return const if namespace.empty? return const if const.first.nil? start = [0, (namespace.length - const.length)].max max = namespace.length intersection = (start..max).find do |shift| namespace[shift, max - shift] == const[0, max - shift] end [*namespace[0, intersection], *const] end # @param node [RuboCop::AST::Node] # @return [Array] # @example # const_name(s(:const, nil, :C)) # => [:C] # const_name(s(:const, s(:const, nil, :M), :C)) # => [:M, :C] # const_name(s(:const, s(:cbase), :C)) # => [nil, :C] def const_name(node) # rubocop:disable InternalAffairs/NodeDestructuring namespace, name = *node # rubocop:enable InternalAffairs/NodeDestructuring if !namespace [name] elsif namespace.const_type? [*const_name(namespace), name] elsif namespace.lvar_type? || namespace.cbase_type? [nil, name] end end # @param node [RuboCop::AST::Node] # @return [Array] # @example # namespace(node) # => [:A, :B, :C] def namespace(node) node .each_ancestor(:class, :module) .reverse_each .flat_map { |ancestor| ancestor.defined_module_name.split('::') } .map(&:to_sym) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/described_class_module_wrapping.rb000066400000000000000000000015111370170147500274120ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Avoid opening modules and defining specs within them. # # @example # # bad # module MyModule # RSpec.describe MyClass do # # ... # end # end # # # good # RSpec.describe MyModule::MyClass do # # ... # end # # @see https://github.com/rubocop-hq/rubocop-rspec/issues/735 class DescribedClassModuleWrapping < Cop MSG = 'Avoid opening modules and defining specs within them.' def_node_search :find_rspec_blocks, ExampleGroups::ALL.block_pattern def on_module(node) find_rspec_blocks(node) do add_offense(node) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/dialect.rb000066400000000000000000000037001370170147500224340ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # This cop enforces custom RSpec dialects. # # A dialect can be based on the following RSpec methods: # # - describe, context, feature, example_group # - xdescribe, xcontext, xfeature # - fdescribe, fcontext, ffeature # - shared_examples, shared_examples_for, shared_context # - it, specify, example, scenario, its # - fit, fspecify, fexample, fscenario, focus # - xit, xspecify, xexample, xscenario, skip # - pending # - prepend_before, before, append_before, # - around # - prepend_after, after, append_after # - let, let! # - subject, subject! # - expect, is_expected, expect_any_instance_of # # By default all of the RSpec methods and aliases are allowed. By setting # a config like: # # RSpec/Dialect: # PreferredMethods: # context: describe # # You can expect the following behavior: # # @example # # bad # context 'display name presence' do # # ... # end # # # good # describe 'display name presence' do # # ... # end class Dialect < Cop extend AutoCorrector include MethodPreference MSG = 'Prefer `%s` over `%s`.' def_node_matcher :rspec_method?, ALL.send_pattern def on_send(node) return unless rspec_method?(node) return unless preferred_methods[node.method_name] msg = format(MSG, prefer: preferred_method(node.method_name), current: node.method_name) add_offense(node, message: msg) do |corrector| current = node.loc.selector preferred = preferred_method(current.source) corrector.replace(current, preferred) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_example_group.rb000066400000000000000000000044701370170147500251210ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks if an example group does not include any tests. # # This cop is configurable using the `CustomIncludeMethods` option # # @example usage # # # bad # describe Bacon do # let(:bacon) { Bacon.new(chunkiness) } # let(:chunkiness) { false } # # context 'extra chunky' do # flagged by rubocop # let(:chunkiness) { true } # end # # it 'is chunky' do # expect(bacon.chunky?).to be_truthy # end # end # # # good # describe Bacon do # let(:bacon) { Bacon.new(chunkiness) } # let(:chunkiness) { false } # # it 'is chunky' do # expect(bacon.chunky?).to be_truthy # end # end # # @example configuration # # # .rubocop.yml # # RSpec/EmptyExampleGroup: # # CustomIncludeMethods: # # - include_tests # # # spec_helper.rb # RSpec.configure do |config| # config.alias_it_behaves_like_to(:include_tests) # end # # # bacon_spec.rb # describe Bacon do # let(:bacon) { Bacon.new(chunkiness) } # let(:chunkiness) { false } # # context 'extra chunky' do # not flagged by rubocop # let(:chunkiness) { true } # # include_tests 'shared tests' # end # end # class EmptyExampleGroup < Cop MSG = 'Empty example group detected.' def_node_search :contains_example?, <<-PATTERN { #{(Examples::ALL + Includes::ALL).send_pattern} (send _ #custom_include? ...) } PATTERN def on_block(node) return unless example_group?(node) && !contains_example?(node) add_offense(node.send_node) end private def custom_include?(method_name) custom_include_methods.include?(method_name) end def custom_include_methods cop_config .fetch('CustomIncludeMethods', []) .map(&:to_sym) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_hook.rb000066400000000000000000000020331370170147500232030ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for empty before and after hooks. # # @example # # bad # before {} # after do; end # before(:all) do # end # after(:all) { } # # # good # before { create_users } # after do # cleanup_users # end # before(:all) do # create_feed # end # after(:all) { cleanup_feed } class EmptyHook < Cop extend AutoCorrector include RuboCop::Cop::RangeHelp MSG = 'Empty hook detected.' def_node_matcher :empty_hook?, <<~PATTERN (block $#{Hooks::ALL.send_pattern} _ nil?) PATTERN def on_block(node) empty_hook?(node) do |hook| add_offense(hook) do |corrector| range = range_with_surrounding_space(range: node.loc.expression) corrector.remove(range) end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_example.rb000066400000000000000000000043211370170147500260700ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks if there is an empty line after example blocks. # # @example # # bad # RSpec.describe Foo do # it 'does this' do # end # it 'does that' do # end # end # # # good # RSpec.describe Foo do # it 'does this' do # end # # it 'does that' do # end # end # # # fair - it's ok to have non-separated one-liners # RSpec.describe Foo do # it { one } # it { two } # end # # @example with AllowConsecutiveOneLiners configuration # # # rubocop.yml # # RSpec/EmptyLineAfterExample: # # AllowConsecutiveOneLiners: false # # # bad # RSpec.describe Foo do # it { one } # it { two } # end # class EmptyLineAfterExample < Cop extend AutoCorrector include RuboCop::RSpec::BlankLineSeparation MSG = 'Add an empty line after `%s`.' def on_block(node) return unless example?(node) return if last_child?(node) return if allowed_one_liner?(node) missing_separating_line(node) do |location| msg = format(MSG, example: node.method_name) add_offense(location, message: msg) do |corrector| corrector.insert_after(location.end, "\n") end end end def allowed_one_liner?(node) consecutive_one_liner?(node) && allow_consecutive_one_liners? end def allow_consecutive_one_liners? cop_config['AllowConsecutiveOneLiners'] end def consecutive_one_liner?(node) node.line_count == 1 && next_one_line_example?(node) end def next_one_line_example?(node) next_sibling = next_sibling(node) return unless next_sibling return unless example?(next_sibling) next_sibling.line_count == 1 end def next_sibling(node) node.parent.children[node.sibling_index + 1] end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_example_group.rb000066400000000000000000000021321370170147500273020ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks if there is an empty line after example group blocks. # # @example # # bad # RSpec.describe Foo do # describe '#bar' do # end # describe '#baz' do # end # end # # # good # RSpec.describe Foo do # describe '#bar' do # end # # describe '#baz' do # end # end # class EmptyLineAfterExampleGroup < Cop extend AutoCorrector include RuboCop::RSpec::BlankLineSeparation MSG = 'Add an empty line after `%s`.' def on_block(node) return unless example_group?(node) return if last_child?(node) missing_separating_line(node) do |location| msg = format(MSG, example_group: node.method_name) add_offense(location, message: msg) do |corrector| corrector.insert_after(location.end, "\n") end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_final_let.rb000066400000000000000000000020651370170147500263750ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks if there is an empty line after the last let block. # # @example # # bad # let(:foo) { bar } # let(:something) { other } # it { does_something } # # # good # let(:foo) { bar } # let(:something) { other } # # it { does_something } class EmptyLineAfterFinalLet < Cop extend AutoCorrector include RuboCop::RSpec::BlankLineSeparation MSG = 'Add an empty line after the last `let` block.' def on_block(node) return unless example_group_with_body?(node) latest_let = node.body.child_nodes.select { |child| let?(child) }.last return if latest_let.nil? return if last_child?(latest_let) missing_separating_line(latest_let) do |location| add_offense(location) do |corrector| corrector.insert_after(location.end, "\n") end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_hook.rb000066400000000000000000000024301370170147500253740ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks if there is an empty line after hook blocks. # # @example # # bad # before { do_something } # it { does_something } # # # bad # after { do_something } # it { does_something } # # # bad # around { |test| test.run } # it { does_something } # # # good # before { do_something } # # it { does_something } # # # good # after { do_something } # # it { does_something } # # # good # around { |test| test.run } # # it { does_something } # class EmptyLineAfterHook < Cop extend AutoCorrector include RuboCop::RSpec::BlankLineSeparation MSG = 'Add an empty line after `%s`.' def on_block(node) return unless hook?(node) return if last_child?(node) missing_separating_line(node) do |location| msg = format(MSG, hook: node.method_name) add_offense(location, message: msg) do |corrector| corrector.insert_after(location.end, "\n") end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_subject.rb000066400000000000000000000020651370170147500260770ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks if there is an empty line after subject block. # # @example # # bad # subject(:obj) { described_class } # let(:foo) { bar } # # # good # subject(:obj) { described_class } # # let(:foo) { bar } class EmptyLineAfterSubject < Cop extend AutoCorrector include RuboCop::RSpec::BlankLineSeparation MSG = 'Add empty line after `subject`.' def on_block(node) return unless subject?(node) && !in_spec_block?(node) return if last_child?(node) missing_separating_line(node) do |location| add_offense(location) do |corrector| corrector.insert_after(location.end, "\n") end end end private def in_spec_block?(node) node.each_ancestor(:block).any? do |ancestor| Examples::ALL.include?(ancestor.method_name) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_length.rb000066400000000000000000000024041370170147500240230ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for long examples. # # A long example is usually more difficult to understand. Consider # extracting out some behaviour, e.g. with a `let` block, or a helper # method. # # @example # # bad # it do # service = described_class.new # more_setup # more_setup # result = service.call # expect(result).to be(true) # end # # # good # it do # service = described_class.new # result = service.call # expect(result).to be(true) # end class ExampleLength < Cop include CodeLength MSG = 'Example has too many lines [%d/%d].' def on_block(node) return unless example?(node) length = code_length(node) return unless length > max_length add_offense(node, message: message(length)) end private def code_length(node) node.source.lines[1..-2].count { |line| !irrelevant_line(line) } end def message(length) format(MSG, total: length, max: max_length) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_without_description.rb000066400000000000000000000047261370170147500266610ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for examples without a description. # # RSpec allows for auto-generated example descriptions when there is no # description provided or the description is an empty one. # # This cop removes empty descriptions. # It also defines whether auto-generated description is allowed, based # on the configured style. # # This cop can be configured using the `EnforcedStyle` option # # @example `EnforcedStyle: always_allow` # # bad # it('') { is_expected.to be_good } # it '' do # result = service.call # expect(result).to be(true) # end # # # good # it { is_expected.to be_good } # it do # result = service.call # expect(result).to be(true) # end # # @example `EnforcedStyle: single_line_only` # # bad # it('') { is_expected.to be_good } # it do # result = service.call # expect(result).to be(true) # end # # # good # it { is_expected.to be_good } # # @example `EnforcedStyle: disallow` # # bad # it { is_expected.to be_good } # it do # result = service.call # expect(result).to be(true) # end class ExampleWithoutDescription < Cop include ConfigurableEnforcedStyle MSG_DEFAULT_ARGUMENT = 'Omit the argument when you want to ' \ 'have auto-generated description.' MSG_ADD_DESCRIPTION = 'Add a description.' def_node_matcher :example_description, '(send nil? _ $(str $_))' def on_block(node) return unless example?(node) check_example_without_description(node.send_node) example_description(node.send_node) do |message_node, message| return unless message.to_s.empty? add_offense(message_node, message: MSG_DEFAULT_ARGUMENT) end end private def check_example_without_description(node) return if node.arguments? return unless disallow_empty_description?(node) add_offense(node, message: MSG_ADD_DESCRIPTION) end def disallow_empty_description?(node) style == :disallow || (style == :single_line_only && node.parent.multiline?) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_wording.rb000066400000000000000000000056701370170147500242230ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for common mistakes in example descriptions. # # This cop will correct docstrings that begin with 'should' and 'it'. # # @see http://betterspecs.org/#should # # The autocorrect is experimental - use with care! It can be configured # with CustomTransform (e.g. have => has) and IgnoredWords (e.g. only). # # @example # # bad # it 'should find nothing' do # end # # # good # it 'finds nothing' do # end # # @example # # bad # it 'it does things' do # end # # # good # it 'does things' do # end class ExampleWording < Cop extend AutoCorrector MSG_SHOULD = 'Do not use should when describing your tests.' MSG_IT = "Do not repeat 'it' when describing your tests." SHOULD_PREFIX = /\Ashould(?:n't)?\b/i.freeze IT_PREFIX = /\Ait /i.freeze def_node_matcher :it_description, <<-PATTERN (block (send _ :it ${ (str $_) (dstr (str $_ ) ...) } ...) ...) PATTERN def on_block(node) it_description(node) do |description_node, message| if message =~ SHOULD_PREFIX add_wording_offense(description_node, MSG_SHOULD) elsif message =~ IT_PREFIX add_wording_offense(description_node, MSG_IT) end end end private def add_wording_offense(node, message) docstring = docstring(node) add_offense(docstring, message: message) do |corrector| corrector.replace(docstring, replacement_text(node)) end end def docstring(node) expr = node.loc.expression Parser::Source::Range.new( expr.source_buffer, expr.begin_pos + 1, expr.end_pos - 1 ) end def replacement_text(node) text = text(node) if text =~ SHOULD_PREFIX RuboCop::RSpec::Wording.new( text, ignore: ignored_words, replace: custom_transform ).rewrite else text.sub(IT_PREFIX, '') end end # Recursive processing is required to process nested dstr nodes # that is the case for \-separated multiline strings with interpolation. def text(node) case node.type when :dstr node.node_parts.map { |child_node| text(child_node) }.join when :str node.value when :begin node.source end end def custom_transform cop_config.fetch('CustomTransform', {}) end def ignored_words cop_config.fetch('IgnoredWords', []) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_actual.rb000066400000000000000000000043731370170147500236570ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for `expect(...)` calls containing literal values. # # @example # # bad # expect(5).to eq(price) # expect(/foo/).to eq(pattern) # expect("John").to eq(name) # # # good # expect(price).to eq(5) # expect(pattern).to eq(/foo/) # expect(name).to eq("John") # class ExpectActual < Cop extend AutoCorrector MSG = 'Provide the actual you are testing to `expect(...)`.' SIMPLE_LITERALS = %i[ true false nil int float str sym complex rational regopt ].freeze COMPLEX_LITERALS = %i[ array hash pair irange erange regexp ].freeze SUPPORTED_MATCHERS = %i[eq eql equal be].freeze def_node_matcher :expect_literal, <<~PATTERN (send (send nil? :expect $#literal?) #{Runners::ALL.node_pattern_union} { (send (send nil? $:be) :== $_) (send nil? $_ $_ ...) } ) PATTERN def on_send(node) expect_literal(node) do |actual, matcher, expected| add_offense(actual.source_range) do |corrector| next unless SUPPORTED_MATCHERS.include?(matcher) swap(corrector, actual, expected) end end end private # This is not implement using a NodePattern because it seems # to not be able to match against an explicit (nil) sexp def literal?(node) node && (simple_literal?(node) || complex_literal?(node)) end def simple_literal?(node) SIMPLE_LITERALS.include?(node.type) end def complex_literal?(node) COMPLEX_LITERALS.include?(node.type) && node.each_child_node.all?(&method(:literal?)) end def swap(corrector, actual, expected) corrector.replace(actual.source_range, expected.source) corrector.replace(expected.source_range, actual.source) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_change.rb000066400000000000000000000046161370170147500236330ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for consistent style of change matcher. # # Enforces either passing object and attribute as arguments to the matcher # or passing a block that reads the attribute value. # # This cop can be configured using the `EnforcedStyle` option. # # @example `EnforcedStyle: block` # # bad # expect { run }.to change(Foo, :bar) # # # good # expect { run }.to change { Foo.bar } # # @example `EnforcedStyle: method_call` # # bad # expect { run }.to change { Foo.bar } # expect { run }.to change { foo.baz } # # # good # expect { run }.to change(Foo, :bar) # expect { run }.to change(foo, :baz) # # also good when there are arguments or chained method calls # expect { run }.to change { Foo.bar(:count) } # expect { run }.to change { user.reload.name } # class ExpectChange < Cop extend AutoCorrector include ConfigurableEnforcedStyle MSG_BLOCK = 'Prefer `change(%s, :%s)`.' MSG_CALL = 'Prefer `change { %s.%s }`.' def_node_matcher :expect_change_with_arguments, <<-PATTERN (send nil? :change ({const send} nil? $_) (sym $_)) PATTERN def_node_matcher :expect_change_with_block, <<-PATTERN (block (send nil? :change) (args) (send ({const send} nil? $_) $_) ) PATTERN def on_send(node) return unless style == :block expect_change_with_arguments(node) do |receiver, message| msg = format(MSG_CALL, obj: receiver, attr: message) add_offense(node, message: msg) do |corrector| replacement = "change { #{receiver}.#{message} }" corrector.replace(node, replacement) end end end def on_block(node) return unless style == :method_call expect_change_with_block(node) do |receiver, message| msg = format(MSG_BLOCK, obj: receiver, attr: message) add_offense(node, message: msg) do |corrector| replacement = "change(#{receiver}, :#{message})" corrector.replace(node, replacement) end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_in_hook.rb000066400000000000000000000020471370170147500240300ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Do not use `expect` in hooks such as `before`. # # @example # # bad # before do # expect(something).to eq 'foo' # end # # # bad # after do # expect_any_instance_of(Something).to receive(:foo) # end # # # good # it do # expect(something).to eq 'foo' # end class ExpectInHook < Cop MSG = 'Do not use `%s` in `%s` hook' def_node_search :expectation, Expectations::ALL.send_pattern def on_block(node) return unless hook?(node) return if node.body.nil? expectation(node.body) do |expect| add_offense(expect.loc.selector, message: message(expect, node)) end end private def message(expect, hook) format(MSG, expect: expect.method_name, hook: hook.method_name) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_output.rb000066400000000000000000000032361370170147500237430ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for opportunities to use `expect { ... }.to output`. # # @example # # bad # $stdout = StringIO.new # my_app.print_report # $stdout = STDOUT # expect($stdout.string).to eq('Hello World') # # # good # expect { my_app.print_report }.to output('Hello World').to_stdout class ExpectOutput < Cop MSG = 'Use `expect { ... }.to output(...).to_%s` '\ 'instead of mutating $%s.' def on_gvasgn(node) return unless inside_example_scope?(node) # rubocop:disable InternalAffairs/NodeDestructuring variable_name, _rhs = *node # rubocop:enable InternalAffairs/NodeDestructuring name = variable_name[1..-1] return unless name.eql?('stdout') || name.eql?('stderr') add_offense(node.loc.name, message: format(MSG, name: name)) end private # Detect if we are inside the scope of a single example # # We want to encourage using `expect { ... }.to output` so # we only care about situations where you would replace with # an expectation. Therefore, assignments to stderr or stdout # within a `before(:all)` or otherwise outside of an example # don't matter. def inside_example_scope?(node) return false if node.nil? || example_group?(node) return true if example?(node) return RuboCop::RSpec::Hook.new(node).example? if hook?(node) inside_example_scope?(node.parent) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/000077500000000000000000000000001370170147500230155ustar00rootroot00000000000000rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb000066400000000000000000000071601370170147500312600ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec module FactoryBot # Always declare attribute values as blocks. # # @example # # bad # kind [:active, :rejected].sample # # # good # kind { [:active, :rejected].sample } # # # bad # closed_at 1.day.from_now # # # good # closed_at { 1.day.from_now } # # # bad # count 1 # # # good # count { 1 } class AttributeDefinedStatically < Cop extend AutoCorrector MSG = 'Use a block to declare attribute values.' def_node_matcher :value_matcher, <<-PATTERN (send _ !#reserved_method? $...) PATTERN def_node_matcher :factory_attributes, <<-PATTERN (block (send _ #attribute_defining_method? ...) _ { (begin $...) $(send ...) } ) PATTERN def on_block(node) attributes = factory_attributes(node) || [] attributes = [attributes] unless attributes.is_a?(Array) attributes.each do |attribute| next unless offensive_receiver?(attribute.receiver, node) next if proc?(attribute) || association?(attribute.first_argument) add_offense(attribute) do |corrector| autocorrect(corrector, attribute) end end end private def autocorrect(corrector, node) if node.parenthesized? autocorrect_replacing_parens(corrector, node) else autocorrect_without_parens(corrector, node) end end def offensive_receiver?(receiver, node) receiver.nil? || receiver.self_type? || receiver_matches_first_block_argument?(receiver, node) end def receiver_matches_first_block_argument?(receiver, node) first_block_argument = node.arguments.first !first_block_argument.nil? && receiver.lvar_type? && receiver.node_parts == first_block_argument.node_parts end def proc?(attribute) value_matcher(attribute).to_a.all?(&:block_pass_type?) end def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)' def autocorrect_replacing_parens(corrector, node) left_braces, right_braces = braces(node) corrector.replace(node.location.begin, ' ' + left_braces) corrector.replace(node.location.end, right_braces) end def autocorrect_without_parens(corrector, node) left_braces, right_braces = braces(node) argument = node.first_argument expression = argument.location.expression corrector.insert_before(expression, left_braces) corrector.insert_after(expression, right_braces) end def braces(node) if value_hash_without_braces?(node.first_argument) ['{ { ', ' } }'] else ['{ ', ' }'] end end def value_hash_without_braces?(node) node.hash_type? && !node.braces? end def reserved_method?(method_name) RuboCop::RSpec::FactoryBot.reserved_methods.include?(method_name) end def attribute_defining_method?(method_name) RuboCop::RSpec::FactoryBot.attribute_defining_methods .include?(method_name) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/create_list.rb000066400000000000000000000141561370170147500256470ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec module FactoryBot # Checks for create_list usage. # # This cop can be configured using the `EnforcedStyle` option # # @example `EnforcedStyle: create_list` # # bad # 3.times { create :user } # # # good # create_list :user, 3 # # # good # 3.times { |n| create :user, created_at: n.months.ago } # # @example `EnforcedStyle: n_times` # # bad # create_list :user, 3 # # # good # 3.times { create :user } class CreateList < Cop extend AutoCorrector include ConfigurableEnforcedStyle MSG_CREATE_LIST = 'Prefer create_list.' MSG_N_TIMES = 'Prefer %s.times.' def_node_matcher :n_times_block_without_arg?, <<-PATTERN (block (send (int _) :times) (args) ... ) PATTERN def_node_matcher :factory_call, <<-PATTERN (send ${(const nil? {:FactoryGirl :FactoryBot}) nil?} :create (sym $_) $...) PATTERN def_node_matcher :factory_list_call, <<-PATTERN (send ${(const nil? {:FactoryGirl :FactoryBot}) nil?} :create_list (sym $_) (int $_) $...) PATTERN def on_block(node) return unless style == :create_list return unless n_times_block_without_arg?(node) return unless contains_only_factory?(node.body) add_offense(node.send_node, message: MSG_CREATE_LIST) do |corrector| CreateListCorrector.new(node.send_node).call(corrector) end end def on_send(node) return unless style == :n_times factory_list_call(node) do |_receiver, _factory, count, _| message = format(MSG_N_TIMES, number: count) add_offense(node.loc.selector, message: message) do |corrector| TimesCorrector.new(node).call(corrector) end end end private def contains_only_factory?(node) if node.block_type? factory_call(node.send_node) else factory_call(node) end end # :nodoc class Corrector private def build_options_string(options) options.map(&:source).join(', ') end def format_method_call(node, method, arguments) if node.block_type? || node.parenthesized? "#{method}(#{arguments})" else "#{method} #{arguments}" end end def format_receiver(receiver) return '' unless receiver "#{receiver.source}." end end # :nodoc class TimesCorrector < Corrector def initialize(node) @node = node end def call(corrector) replacement = generate_n_times_block(node) corrector.replace(node, replacement) end private attr_reader :node def generate_n_times_block(node) factory, count, *options = node.arguments arguments = factory.source options = build_options_string(options) arguments += ", #{options}" unless options.empty? replacement = format_receiver(node.receiver) replacement += format_method_call(node, 'create', arguments) "#{count.source}.times { #{replacement} }" end end # :nodoc: class CreateListCorrector < Corrector def initialize(node) @node = node.parent end def call(corrector) replacement = if node.body.block_type? call_with_block_replacement(node) else call_replacement(node) end corrector.replace(node, replacement) end private attr_reader :node def call_with_block_replacement(node) block = node.body arguments = build_arguments(block, node.receiver.source) replacement = format_receiver(block.send_node.receiver) replacement += format_method_call(block, 'create_list', arguments) replacement += format_block(block) replacement end def build_arguments(node, count) factory, *options = *node.send_node.arguments arguments = ":#{factory.value}, #{count}" options = build_options_string(options) arguments += ", #{options}" unless options.empty? arguments end def call_replacement(node) block = node.body factory, *options = *block.arguments arguments = "#{factory.source}, #{node.receiver.source}" options = build_options_string(options) arguments += ", #{options}" unless options.empty? replacement = format_receiver(block.receiver) replacement += format_method_call(block, 'create_list', arguments) replacement end def format_block(node) if node.body.begin_type? format_multiline_block(node) else format_singeline_block(node) end end def format_multiline_block(node) indent = ' ' * node.body.loc.column indent_end = ' ' * node.parent.loc.column " do #{node.arguments.source}\n" \ "#{indent}#{node.body.source}\n" \ "#{indent_end}end" end def format_singeline_block(node) " { #{node.arguments.source} #{node.body.source} }" end end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb000066400000000000000000000027551370170147500272070ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec module FactoryBot # Use string value when setting the class attribute explicitly. # # This cop would promote faster tests by lazy-loading of # application files. Also, this could help you suppress potential bugs # in combination with external libraries by avoiding a preload of # application files from the factory files. # # @example # # bad # factory :foo, class: Foo do # end # # # good # factory :foo, class: 'Foo' do # end class FactoryClassName < Cop extend AutoCorrector MSG = "Pass '%s' string instead of `%s` " \ 'constant.' ALLOWED_CONSTANTS = %w[Hash OpenStruct].freeze def_node_matcher :class_name, <<~PATTERN (send _ :factory _ (hash <(pair (sym :class) $(const ...)) ...>)) PATTERN def on_send(node) class_name(node) do |cn| next if allowed?(cn.const_name) msg = format(MSG, class_name: cn.const_name) add_offense(cn, message: msg) do |corrector| corrector.replace(cn, "'#{cn.source}'") end end end private def allowed?(const_name) ALLOWED_CONSTANTS.include?(const_name) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/file_path.rb000066400000000000000000000101731370170147500227640ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that spec file paths are consistent and well-formed. # # By default, this checks that spec file paths are consistent with the # test subject and and enforces that it reflects the described # class/module and its optionally called out method. # # With the configuration option `IgnoreMethods` the called out method will # be ignored when determining the enforced path. # # With the configuration option `CustomTransform` modules or classes can # be specified that should not as usual be transformed from CamelCase to # snake_case (e.g. 'RuboCop' => 'rubocop' ). # # With the configuration option `SpecSuffixOnly` test files will only # be checked to ensure they end in '_spec.rb'. This option disables # checking for consistency in the test subject or test methods. # # @example # # bad # whatever_spec.rb # describe MyClass # # # bad # my_class_spec.rb # describe MyClass, '#method' # # # good # my_class_spec.rb # describe MyClass # # # good # my_class_method_spec.rb # describe MyClass, '#method' # # # good # my_class/method_spec.rb # describe MyClass, '#method' # # @example when configuration is `IgnoreMethods: true` # # bad # whatever_spec.rb # describe MyClass # # # good # my_class_spec.rb # describe MyClass # # # good # my_class_spec.rb # describe MyClass, '#method' # # @example when configuration is `SpecSuffixOnly: true` # # good # whatever_spec.rb # describe MyClass # # # good # my_class_spec.rb # describe MyClass # # # good # my_class_spec.rb # describe MyClass, '#method' # class FilePath < Cop include RuboCop::RSpec::TopLevelDescribe MSG = 'Spec path should end with `%s`.' def_node_search :const_described?, '(send _ :describe (const ...) ...)' def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))' def on_top_level_describe(node, args) return unless const_described?(node) && single_top_level_describe? return if routing_spec?(args) glob = glob_for(args) return if filename_ends_with?(glob) add_offense( node, message: format(MSG, suffix: glob) ) end private def routing_spec?(args) args.any?(&method(:routing_metadata?)) end def glob_for((described_class, method_name)) return glob_for_spec_suffix_only? if spec_suffix_only? "#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb" end def glob_for_spec_suffix_only? '*_spec.rb' end def name_glob(name) return unless name&.str_type? "*#{name.str_content.gsub(/\W/, '')}" unless ignore_methods? end def expected_path(constant) File.join( constant.const_name.split('::').map do |name| custom_transform.fetch(name) { camel_to_snake_case(name) } end ) end def camel_to_snake_case(string) string .gsub(/([^A-Z])([A-Z]+)/, '\1_\2') .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2') .downcase end def custom_transform cop_config.fetch('CustomTransform', {}) end def ignore_methods? cop_config['IgnoreMethods'] end def filename_ends_with?(glob) filename = RuboCop::PathUtil.relative_path(processed_source.buffer.name) .gsub('../', '') File.fnmatch?("*#{glob}", filename) end def relevant_rubocop_rspec_file?(_file) true end def spec_suffix_only? cop_config['SpecSuffixOnly'] end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/focus.rb000066400000000000000000000025241370170147500221510ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks if examples are focused. # # @example # # bad # describe MyClass, focus: true do # end # # describe MyClass, :focus do # end # # fdescribe MyClass do # end # # # good # describe MyClass do # end class Focus < Cop MSG = 'Focused spec found.' focusable = ExampleGroups::GROUPS + ExampleGroups::SKIPPED + Examples::EXAMPLES + Examples::SKIPPED + Examples::PENDING focused = ExampleGroups::FOCUSED + Examples::FOCUSED FOCUSABLE_SELECTORS = focusable.node_pattern_union def_node_matcher :metadata, <<-PATTERN {(send #{RSPEC} #{FOCUSABLE_SELECTORS} <$(sym :focus) ...>) (send #{RSPEC} #{FOCUSABLE_SELECTORS} ... (hash <$(pair (sym :focus) true) ...>))} PATTERN def_node_matcher :focused_block?, focused.send_pattern def on_send(node) focus_metadata(node) do |focus| add_offense(focus) end end private def focus_metadata(node, &block) yield(node) if focused_block?(node) metadata(node, &block) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/hook_argument.rb000066400000000000000000000064141370170147500236760ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks the arguments passed to `before`, `around`, and `after`. # # This cop checks for consistent style when specifying RSpec # hooks which run for each example. There are three supported # styles: "implicit", "each", and "example." All styles have # the same behavior. # # @example when configuration is `EnforcedStyle: implicit` # # bad # before(:each) do # # ... # end # # # bad # before(:example) do # # ... # end # # # good # before do # # ... # end # # @example when configuration is `EnforcedStyle: each` # # bad # before(:example) do # # ... # end # # # good # before do # # ... # end # # # good # before(:each) do # # ... # end # # @example when configuration is `EnforcedStyle: example` # # bad # before(:each) do # # ... # end # # # bad # before do # # ... # end # # # good # before(:example) do # # ... # end class HookArgument < Cop extend AutoCorrector include ConfigurableEnforcedStyle IMPLICIT_MSG = 'Omit the default `%p` ' \ 'argument for RSpec hooks.' EXPLICIT_MSG = 'Use `%p` for RSpec hooks.' HOOKS = Hooks::ALL.node_pattern_union.freeze def_node_matcher :scoped_hook, <<-PATTERN (block $(send _ #{HOOKS} (sym ${:each :example})) ...) PATTERN def_node_matcher :unscoped_hook, "(block $(send _ #{HOOKS}) ...)" def on_block(node) hook(node) do |method_send, scope_name| return correct_style_detected if scope_name.equal?(style) return check_implicit(method_send) unless scope_name style_detected(scope_name) msg = explicit_message(scope_name) add_offense(method_send, message: msg) do |corrector| scope = implicit_style? ? '' : "(#{style.inspect})" corrector.replace(argument_range(method_send), scope) end end end private def check_implicit(method_send) style_detected(:implicit) return if implicit_style? msg = explicit_message(nil) add_offense(method_send.loc.selector, message: msg) do |corrector| scope = "(#{style.inspect})" corrector.replace(argument_range(method_send), scope) end end def explicit_message(scope) if implicit_style? format(IMPLICIT_MSG, scope: scope) else format(EXPLICIT_MSG, scope: style) end end def implicit_style? style.equal?(:implicit) end def hook(node, &block) scoped_hook(node, &block) || unscoped_hook(node, &block) end def argument_range(send_node) send_node.loc.selector.end.with( end_pos: send_node.loc.expression.end_pos ) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/hooks_before_examples.rb000066400000000000000000000036561370170147500254040ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for before/around/after hooks that come after an example. # # @example # # Bad # # it 'checks what foo does' do # expect(foo).to be # end # # before { prepare } # after { clean_up } # # # Good # before { prepare } # after { clean_up } # # it 'checks what foo does' do # expect(foo).to be # end # class HooksBeforeExamples < Cop extend AutoCorrector MSG = 'Move `%s` above the examples in the group.' def_node_matcher :example_or_group?, <<-PATTERN { #{(Examples::ALL + ExampleGroups::ALL).block_pattern} #{Includes::EXAMPLES.send_pattern} } PATTERN def on_block(node) return unless example_group_with_body?(node) check_hooks(node.body) if multiline_block?(node.body) end private def multiline_block?(block) block.begin_type? end def check_hooks(node) first_example = find_first_example(node) return unless first_example node.each_child_node do |child| next if child.sibling_index < first_example.sibling_index next unless hook?(child) msg = format(MSG, hook: child.method_name) add_offense(child, message: msg) do |corrector| autocorrect(corrector, child, first_example) end end end def find_first_example(node) node.children.find { |sibling| example_or_group?(sibling) } end def autocorrect(corrector, node, first_example) RuboCop::RSpec::Corrector::MoveNode.new( node, corrector, processed_source ).move_before(first_example) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_block_expectation.rb000066400000000000000000000034261370170147500264230ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check that implicit block expectation syntax is not used. # # Prefer using explicit block expectations. # # @example # # bad # subject { -> { do_something } } # it { is_expected.to change(something).to(new_value) } # # # good # it 'changes something to a new value' do # expect { do_something }.to change(something).to(new_value) # end class ImplicitBlockExpectation < Cop MSG = 'Avoid implicit block expectations.' def_node_matcher :lambda?, <<-PATTERN { (send (const nil? :Proc) :new) (send nil? :proc) (send nil? :lambda) } PATTERN def_node_matcher :lambda_subject?, '(block #lambda? ...)' def_node_matcher :implicit_expect, <<-PATTERN $(send nil? {:is_expected :should :should_not} ...) PATTERN def on_send(node) implicit_expect(node) do |implicit_expect| subject = nearest_subject(implicit_expect) add_offense(implicit_expect) if lambda_subject?(subject&.body) end end private def nearest_subject(node) node .each_ancestor(:block) .lazy .select { |block_node| multi_statement_example_group?(block_node) } .map { |block_node| find_subject(block_node) } .find(&:itself) end def multi_statement_example_group?(node) example_group_with_body?(node) && node.body.begin_type? end def find_subject(block_node) block_node.body.child_nodes.find { |send_node| subject?(send_node) } end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_expect.rb000066400000000000000000000053051370170147500242140ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check that a consistent implicit expectation style is used. # # This cop can be configured using the `EnforcedStyle` option # and supports the `--auto-gen-config` flag. # # @example `EnforcedStyle: is_expected` # # # bad # it { should be_truthy } # # # good # it { is_expected.to be_truthy } # # @example `EnforcedStyle: should` # # # bad # it { is_expected.to be_truthy } # # # good # it { should be_truthy } # class ImplicitExpect < Cop extend AutoCorrector include ConfigurableEnforcedStyle MSG = 'Prefer `%s` over `%s`.' def_node_matcher :implicit_expect, <<-PATTERN { (send nil? ${:should :should_not} ...) (send (send nil? $:is_expected) #{Runners::ALL.node_pattern_union} ...) } PATTERN alternatives = { 'is_expected.to' => 'should', 'is_expected.not_to' => 'should_not', 'is_expected.to_not' => 'should_not' } ENFORCED_REPLACEMENTS = alternatives.merge(alternatives.invert).freeze def on_send(node) # rubocop:disable Metrics/MethodLength return unless (source_range = offending_expect(node)) expectation_source = source_range.source if expectation_source.start_with?(style.to_s) correct_style_detected else opposite_style_detected msg = offense_message(expectation_source) add_offense(source_range, message: msg) do |corrector| replacement = replacement_source(expectation_source) corrector.replace(source_range, replacement) end end end private def offending_expect(node) case implicit_expect(node) when :is_expected is_expected_range(node.loc) when :should, :should_not node.loc.selector end end def is_expected_range(source_map) # rubocop:disable Naming/PredicateName Parser::Source::Range.new( source_map.expression.source_buffer, source_map.expression.begin_pos, source_map.selector.end_pos ) end def offense_message(offending_source) format( MSG, good: replacement_source(offending_source), bad: offending_source ) end def replacement_source(offending_source) ENFORCED_REPLACEMENTS.fetch(offending_source) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_subject.rb000066400000000000000000000040111370170147500243540ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for usage of implicit subject (`is_expected` / `should`). # # This cop can be configured using the `EnforcedStyle` option # # @example `EnforcedStyle: single_line_only` # # bad # it do # is_expected.to be_truthy # end # # # good # it { is_expected.to be_truthy } # it do # expect(subject).to be_truthy # end # # @example `EnforcedStyle: disallow` # # bad # it { is_expected.to be_truthy } # # # good # it { expect(subject).to be_truthy } # class ImplicitSubject < Cop extend AutoCorrector include ConfigurableEnforcedStyle MSG = "Don't use implicit subject." def_node_matcher :implicit_subject?, <<-PATTERN (send nil? {:should :should_not :is_expected} ...) PATTERN def on_send(node) return unless implicit_subject?(node) return if valid_usage?(node) add_offense(node) do |corrector| autocorrect(corrector, node) end end private def autocorrect(corrector, node) replacement = 'expect(subject)' if node.method_name == :should replacement += '.to' elsif node.method_name == :should_not replacement += '.not_to' end corrector.replace(node.loc.selector, replacement) end def valid_usage?(node) example = node.ancestors.find { |parent| example?(parent) } return false if example.nil? example.method_name == :its || allowed_by_style?(example) end def allowed_by_style?(example) if style == :single_line_only example.single_line? elsif style == :single_statement_only !example.body.begin_type? else false end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/instance_spy.rb000066400000000000000000000034071370170147500235320ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for `instance_double` used with `have_received`. # # @example # # bad # it do # foo = instance_double(Foo).as_null_object # expect(foo).to have_received(:bar) # end # # # good # it do # foo = instance_spy(Foo) # expect(foo).to have_received(:bar) # end # class InstanceSpy < Cop extend AutoCorrector MSG = 'Use `instance_spy` when you check your double '\ 'with `have_received`.' def_node_search :null_double, <<-PATTERN (lvasgn $_ (send $(send nil? :instance_double ...) :as_null_object)) PATTERN def_node_search :have_received_usage, <<-PATTERN (send (send nil? :expect (lvar $_)) :to (send nil? :have_received ...) ...) PATTERN def on_block(node) return unless example?(node) null_double(node) do |var, receiver| have_received_usage(node) do |expected| next if expected != var add_offense(receiver) do |corrector| autocorrect(corrector, receiver) end end end end private def autocorrect(corrector, node) replacement = 'instance_spy' corrector.replace(node.loc.selector, replacement) double_source_map = node.parent.loc as_null_object_range = double_source_map .dot .join(double_source_map.selector) corrector.remove(as_null_object_range) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/instance_variable.rb000066400000000000000000000046131370170147500245040ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for instance variable usage in specs. # # This cop can be configured with the option `AssignmentOnly` which # will configure the cop to only register offenses on instance # variable usage if the instance variable is also assigned within # the spec # # @example # # bad # describe MyClass do # before { @foo = [] } # it { expect(@foo).to be_empty } # end # # # good # describe MyClass do # let(:foo) { [] } # it { expect(foo).to be_empty } # end # # @example with AssignmentOnly configuration # # # rubocop.yml # # RSpec/InstanceVariable: # # AssignmentOnly: false # # # bad # describe MyClass do # before { @foo = [] } # it { expect(@foo).to be_empty } # end # # # allowed # describe MyClass do # it { expect(@foo).to be_empty } # end # # # good # describe MyClass do # let(:foo) { [] } # it { expect(foo).to be_empty } # end # class InstanceVariable < Cop include RuboCop::RSpec::TopLevelGroup MSG = 'Avoid instance variables – use let, ' \ 'a method call, or a local variable (if possible).' def_node_matcher :dynamic_class?, <<-PATTERN (block (send (const nil? :Class) :new ...) ...) PATTERN def_node_matcher :custom_matcher?, <<-PATTERN (block { (send nil? :matcher sym) (send (const (const nil? :RSpec) :Matchers) :define sym) } ...) PATTERN def_node_search :ivar_usage, '$(ivar $_)' def_node_search :ivar_assigned?, '(ivasgn % ...)' def on_top_level_group(node) ivar_usage(node) do |ivar, name| next if valid_usage?(ivar) next if assignment_only? && !ivar_assigned?(node, name) add_offense(ivar) end end private def valid_usage?(node) node.each_ancestor(:block).any? do |block| dynamic_class?(block) || custom_matcher?(block) end end def assignment_only? cop_config['AssignmentOnly'] end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb000066400000000000000000000020731370170147500262020ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks invalid usage for predicate matcher. # # Predicate matcher does not need a question. # This cop checks an unnecessary question in predicate matcher. # # @example # # # bad # expect(foo).to be_something? # # # good # expect(foo).to be_something class InvalidPredicateMatcher < Cop MSG = 'Omit `?` from `%s`.' def_node_matcher :invalid_predicate_matcher?, <<-PATTERN (send (send nil? :expect ...) #{Runners::ALL.node_pattern_union} $(send nil? #predicate?)) PATTERN def on_send(node) invalid_predicate_matcher?(node) do |predicate| add_offense(predicate, message: format(MSG, matcher: predicate.method_name)) end end private def predicate?(name) name = name.to_s name.start_with?('be_', 'have_') && name.end_with?('?') end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/it_behaves_like.rb000066400000000000000000000023161370170147500241460ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that only one `it_behaves_like` style is used. # # @example when configuration is `EnforcedStyle: it_behaves_like` # # bad # it_should_behave_like 'a foo' # # # good # it_behaves_like 'a foo' # # @example when configuration is `EnforcedStyle: it_should_behave_like` # # bad # it_behaves_like 'a foo' # # # good # it_should_behave_like 'a foo' class ItBehavesLike < Cop extend AutoCorrector include ConfigurableEnforcedStyle MSG = 'Prefer `%s` over `%s` when including '\ 'examples in a nested context.' def_node_matcher :example_inclusion_offense, '(send _ % ...)' def on_send(node) example_inclusion_offense(node, alternative_style) do add_offense(node) do |corrector| corrector.replace(node.loc.selector, style.to_s) end end end private def message(_node) format(MSG, replacement: style, original: alternative_style) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/iterated_expectation.rb000066400000000000000000000025341370170147500252370ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check that `all` matcher is used instead of iterating over an array. # # @example # # bad # it 'validates users' do # [user1, user2, user3].each { |user| expect(user).to be_valid } # end # # # good # it 'validates users' do # expect([user1, user2, user3]).to all(be_valid) # end class IteratedExpectation < Cop MSG = 'Prefer using the `all` matcher instead ' \ 'of iterating over an array.' def_node_matcher :each?, <<-PATTERN (block (send ... :each) (args (arg $_)) $(...) ) PATTERN def_node_matcher :expectation?, <<-PATTERN (send (send nil? :expect (lvar %)) :to ...) PATTERN def on_block(node) each?(node) do |arg, body| if single_expectation?(body, arg) || only_expectations?(body, arg) add_offense(node.send_node) end end end private def single_expectation?(body, arg) expectation?(body, arg) end def only_expectations?(body, arg) body.each_child_node.all? { |child| expectation?(child, arg) } end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/leading_subject.rb000066400000000000000000000043241370170147500241540ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Enforce that subject is the first definition in the test. # # @example # # bad # let(:params) { blah } # subject { described_class.new(params) } # # before { do_something } # subject { described_class.new(params) } # # it { expect_something } # subject { described_class.new(params) } # it { expect_something_else } # # # # good # subject { described_class.new(params) } # let(:params) { blah } # # # good # subject { described_class.new(params) } # before { do_something } # # # good # subject { described_class.new(params) } # it { expect_something } # it { expect_something_else } # class LeadingSubject < Cop extend AutoCorrector MSG = 'Declare `subject` above any other `%s` declarations.' def on_block(node) return unless subject?(node) && !in_spec_block?(node) check_previous_nodes(node) end def check_previous_nodes(node) node.parent.each_child_node do |sibling| if offending?(sibling) msg = format(MSG, offending: sibling.method_name) add_offense(node, message: msg) do |corrector| autocorrect(corrector, node) end end break if offending?(sibling) || sibling.equal?(node) end end private def autocorrect(corrector, node) first_node = find_first_offending_node(node) RuboCop::RSpec::Corrector::MoveNode.new( node, corrector, processed_source ).move_before(first_node) end def offending?(node) let?(node) || hook?(node) || example?(node) end def find_first_offending_node(node) node.parent.children.find { |sibling| offending?(sibling) } end def in_spec_block?(node) node.each_ancestor(:block).any? do |ancestor| example?(ancestor) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/leaky_constant_declaration.rb000066400000000000000000000073251370170147500264210ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks that no class, module, or constant is declared. # # Constants, including classes and modules, when declared in a block # scope, are defined in global namespace, and leak between examples. # # If several examples may define a `DummyClass`, instead of being a # blank slate class as it will be in the first example, subsequent # examples will be reopening it and modifying its behaviour in # unpredictable ways. # Even worse when a class that exists in the codebase is reopened. # # Anonymous classes are fine, since they don't result in global # namespace name clashes. # # @see https://relishapp.com/rspec/rspec-mocks/docs/mutating-constants # # @example Constants leak between examples # # bad # describe SomeClass do # OtherClass = Struct.new # CONSTANT_HERE = 'I leak into global namespace' # end # # # good # describe SomeClass do # before do # stub_const('OtherClass', Struct.new) # stub_const('CONSTANT_HERE', 'I only exist during this example') # end # end # # @example # # bad # describe SomeClass do # class FooClass < described_class # def double_that # some_base_method * 2 # end # end # # it { expect(FooClass.new.double_that).to eq(4) } # end # # # good - anonymous class, no constant needs to be defined # describe SomeClass do # let(:foo_class) do # Class.new(described_class) do # def double_that # some_base_method * 2 # end # end # end # # it { expect(foo_class.new.double_that).to eq(4) } # end # # # good - constant is stubbed # describe SomeClass do # before do # foo_class = Class.new(described_class) do # def do_something # end # end # stub_const('FooClass', foo_class) # end # # it { expect(FooClass.new.double_that).to eq(4) } # end # # @example # # bad # describe SomeClass do # module SomeModule # class SomeClass # def do_something # end # end # end # end # # # good # describe SomeClass do # before do # foo_class = Class.new(described_class) do # def do_something # end # end # stub_const('SomeModule::SomeClass', foo_class) # end # end class LeakyConstantDeclaration < Cop MSG_CONST = 'Stub constant instead of declaring explicitly.' MSG_CLASS = 'Stub class constant instead of declaring explicitly.' MSG_MODULE = 'Stub module constant instead of declaring explicitly.' def on_casgn(node) return unless inside_describe_block?(node) add_offense(node, message: MSG_CONST) end def on_class(node) return unless inside_describe_block?(node) add_offense(node, message: MSG_CLASS) end def on_module(node) return unless inside_describe_block?(node) add_offense(node, message: MSG_MODULE) end private def inside_describe_block?(node) node.each_ancestor(:block).any?(&method(:spec_group?)) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/let_before_examples.rb000066400000000000000000000040441370170147500250350ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for `let` definitions that come after an example. # # @example # # Bad # let(:foo) { bar } # # it 'checks what foo does' do # expect(foo).to be # end # # let(:some) { other } # # it 'checks what some does' do # expect(some).to be # end # # # Good # let(:foo) { bar } # let(:some) { other } # # it 'checks what foo does' do # expect(foo).to be # end # # it 'checks what some does' do # expect(some).to be # end class LetBeforeExamples < Cop extend AutoCorrector MSG = 'Move `let` before the examples in the group.' def_node_matcher :example_or_group?, <<-PATTERN { #{(Examples::ALL + ExampleGroups::ALL).block_pattern} #{Includes::EXAMPLES.send_pattern} } PATTERN def on_block(node) return unless example_group_with_body?(node) check_let_declarations(node.body) if multiline_block?(node.body) end private def multiline_block?(block) block.begin_type? end def check_let_declarations(node) first_example = find_first_example(node) return unless first_example node.each_child_node do |child| next if child.sibling_index < first_example.sibling_index next unless let?(child) add_offense(child) do |corrector| autocorrect(corrector, child, first_example) end end end def find_first_example(node) node.children.find { |sibling| example_or_group?(sibling) } end def autocorrect(corrector, node, first_example) RuboCop::RSpec::Corrector::MoveNode.new( node, corrector, processed_source ).move_before(first_example) end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/let_setup.rb000066400000000000000000000033331370170147500230350ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks unreferenced `let!` calls being used for test setup. # # @example # # Bad # let!(:my_widget) { create(:widget) } # # it 'counts widgets' do # expect(Widget.count).to eq(1) # end # # # Good # it 'counts widgets' do # create(:widget) # expect(Widget.count).to eq(1) # end # # # Good # before { create(:widget) } # # it 'counts widgets' do # expect(Widget.count).to eq(1) # end class LetSetup < Cop MSG = 'Do not use `let!` to setup objects not referenced in tests.' def_node_matcher :example_or_shared_group_or_including?, ( ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL ).block_pattern def_node_matcher :let_bang, <<-PATTERN (block $(send nil? :let! (sym $_)) args ...) PATTERN def_node_search :method_called?, '(send nil? %)' def on_block(node) return unless example_or_shared_group_or_including?(node) unused_let_bang(node) do |let| add_offense(let) end end private def unused_let_bang(node) child_let_bang(node) do |method_send, method_name| yield(method_send) unless method_called?(node, method_name) end end def child_let_bang(node, &block) RuboCop::RSpec::ExampleGroup.new(node).lets.each do |let| let_bang(let, &block) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/message_chain.rb000066400000000000000000000015051370170147500236160ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Check that chains of messages are not being stubbed. # # @example # # bad # allow(foo).to receive_message_chain(:bar, :baz).and_return(42) # # # better # thing = Thing.new(baz: 42) # allow(foo).to receive(:bar).and_return(thing) # class MessageChain < Cop MSG = 'Avoid stubbing using `%s`.' def_node_matcher :message_chain, <<-PATTERN (send _ {:receive_message_chain :stub_chain} ...) PATTERN def on_send(node) message_chain(node) do add_offense( node.loc.selector, message: format(MSG, method: node.method_name) ) end end end end end end rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/message_expectation.rb000066400000000000000000000027771370170147500250730ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module RSpec # Checks for consistent message expectation style. # # This cop can be configured in your configuration using the # `EnforcedStyle` option and supports `--auto-gen-config`. # # @example `EnforcedStyle: allow` # # # bad # expect(foo).to receive(:bar) # # # good # allow(foo).to receive(:bar) # # @example `EnforcedStyle: expect` # # # bad # allow(foo).to receive(:bar) # # # good # expect(foo).to receive(:bar) # class MessageExpectation < Cop include ConfigurableEnforcedStyle MSG = 'Prefer `%