diff -Nru ruby-rubocop-rspec-1.42.0/bin/build_config ruby-rubocop-rspec-2.16.0/bin/build_config --- ruby-rubocop-rspec-1.42.0/bin/build_config 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/bin/build_config 2022-12-13 09:15:42.000000000 +0000 @@ -6,21 +6,27 @@ require 'yard' require 'rubocop-rspec' -require 'rubocop/rspec/description_extractor' require 'rubocop/rspec/config_formatter' +require 'rubocop/rspec/description_extractor' 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. +# we have to prepend the list with our base cop, RuboCop::Cop::RSpec::Base. # Otherwise, cop's parent class for cops loaded before our base cop class -# are detected as RuboCop::Cop::Cop, and that complicates the detection +# are detected as RuboCop::Cop::Base, and that complicates the detection # of their relation with RuboCop RSpec. -rspec_cop_path = File.join('lib', 'rubocop', 'cop', 'rspec', 'cop.rb') +rspec_cop_path = File.join('lib', 'rubocop', 'cop', 'rspec', 'base.rb') +YARD::Tags::Library.define_tag('Cop Safety Information', :safety) 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') +descriptions = + RuboCop::RSpec::DescriptionExtractor.new(YARD::Registry.all(:class)).to_h +current_config = if Psych::VERSION >= '4.0.0' # RUBY_VERSION >= '3.1.0' + YAML.unsafe_load_file('config/default.yml') + else + YAML.load_file('config/default.yml') + end File.write( 'config/default.yml', diff -Nru ruby-rubocop-rspec-1.42.0/CHANGELOG.md ruby-rubocop-rspec-2.16.0/CHANGELOG.md --- ruby-rubocop-rspec-1.42.0/CHANGELOG.md 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/CHANGELOG.md 2022-12-13 09:15:42.000000000 +0000 @@ -1,233 +1,467 @@ -# Change log +# Changelog ## Master (Unreleased) +## 2.16.0 (2022-12-13) + +- Add new `RSpec/FactoryBot/FactoryNameStyle` cop. ([@ydah]) +- Improved processing speed for `RSpec/Be`, `RSpec/ExpectActual`, `RSpec/ImplicitExpect`, `RSpec/MessageSpies`, `RSpec/PredicateMatcher` and `RSpec/Rails/HaveHttpStatus`. ([@ydah]) +- Fix wrong autocorrection in `n_times` style on `RSpec/FactoryBot/CreateList`. ([@r7kamura]) +- Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` when using `generate` with multiple arguments. ([@ydah]) +- Mark `RSpec/BeEq` as `Safe: false` ([@r7kamura]) +- Add `RSpec/DuplicatedMetadata` cop. ([@r7kamura]) +- Mark `RSpec/BeEql` as `Safe: false`. ([@r7kamura]) +- Add `RSpec/PendingWithoutReason` cop. ([@r7kamura]) + +## 2.15.0 (2022-11-03) + +- Fix a false positive for `RSpec/RepeatedDescription` when different its block expectations are used. ([@ydah]) +- Add `named_only` style to `RSpec/NamedSubject`. ([@kuahyeow]) +- Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls without the first positional argument. ([@pirj]) +- Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls inside a Hash or an Array. ([@pirj]) +- Fix `RSpec/NestedGroups` to correctly use `AllowedGroups` config. ([@samrjenkins]) +- Remove `Runners` and `HookScopes` RSpec DSL elements from configuration. ([@pirj]) +- Add `with default RSpec/Language config` helper to `lib` (under `rubocop/rspec/shared_contexts/default_rspec_language_config_context`), to allow use for downstream cops based on `RuboCop::Cop::RSpec::Base`. ([@smcgivern]) + +## 2.14.2 (2022-10-25) + +- Fix an incorrect autocorrect for `FactoryBot/ConsistentParenthesesStyle` with `omit_parentheses` option when method name and first argument are not on same line. ([@ydah]) +- Fix autocorrection loop in `RSpec/ExampleWording` for insufficient example wording. ([@pirj]) +- Fix `RSpec/SortMetadata` not to reorder arguments of `include_`/`it_behaves_like`. ([@pirj]) +- Fix a false positive for `RSpec/NoExpectationExample` when allowed pattern methods with arguments. ([@ydah]) +- Change `RSpec/FilePath` so that it only checks suffix when path is under spec/routing or type is defined as routing. ([@r7kamura]) + +## 2.14.1 (2022-10-24) + +- Fix an error for `RSpec/Rails/InferredSpecType` with redundant type before other Hash metadata. ([@ydah]) + +## 2.14.0 (2022-10-23) + +- Add `require_implicit` style to `RSpec/ImplicitSubject`. ([@r7kamura]) +- Fix a false positive for `RSpec/Capybara/SpecificMatcher` when `have_css("a")` without attribute. ([@ydah]) +- Update `RSpec/ExampleWording` cop to raise error for insufficient descriptions. ([@akrox58]) +- Add new `RSpec/Capybara/NegationMatcher` cop. ([@ydah]) +- Add `AllowedPatterns` configuration option to `RSpec/NoExpectationExample`. ([@ydah]) +- Improve `RSpec/NoExpectationExample` cop to ignore examples skipped or pending via metadata. ([@pirj]) +- Add `RSpec/FactoryBot/ConsistentParenthesesStyle` cop. ([@Liberatys]) +- Add `RSpec/Rails/InferredSpecType` cop. ([@r7kamura]) +- Add new `RSpec/Capybara/SpecificActions` cop. ([@ydah]) +- Update `config/default.yml` removing deprecated option to make the config correctable by users. ([@ignaciovillaverde]) +- Do not attempt to auto-correct example groups with `include_examples` in `RSpec/LetBeforeExamples`. ([@pirj]) +- Add new `RSpec/SortMetadata` cop. ([@leoarnold]) +- Add support for subject! method to `RSpec/SubjectDeclaration`. ([@ydah]) + +## 2.13.2 (2022-09-23) + +- Fix an error for `RSpec/Capybara/SpecificFinders` with no parentheses. ([@ydah]) +- Fix a false positive for `RSpec/NoExpectationExample` with pending using `skip` or `pending` inside an example. ([@ydah]) +- Exclude `have_text` and `have_content` that raise `ArgumentError` with `RSpec/Capybara/VisibilityMatcher` where `:visible` is an invalid option. ([@ydah]) +- Fix a false negative for `RSpec/Capybara/VisibilityMatcher` with negative matchers. ([@ydah]) + +## 2.13.1 (2022-09-12) + +- Include config/obsoletion.yml in the gemspec. ([@hosamaly]) + +## 2.13.0 (2022-09-12) + +- Fix `RSpec/FilePath` cop missing mismatched expanded namespace. ([@sl4vr]) +- Add new `AllowConsecutiveOneLiners` (default true) option for `Rspec/EmptyLineAfterHook` cop. ([@ngouy]) +- Add autocorrect support for `RSpec/EmptyExampleGroup`. ([@r7kamura]) +- Fix `RSpec/ChangeByZero` with compound expressions using `&` or `|` operators. ([@BrianHawley]) +- Add `RSpec/NoExpectationExample`. ([@r7kamura]) +- Add some expectation methods to default configuration. ([@r7kamura]) +- Fix a false positive for `RSpec/Capybara/SpecificMatcher`. ([@ydah]) +- Fix a false negative for `RSpec/Capybara/SpecificMatcher` for `have_field`. ([@ydah]) +- Fix a false positive for `RSpec/Capybara/SpecificMatcher` when may not have a `href` by `have_link`. ([@ydah]) +- Add `NegatedMatcher` configuration option to `RSpec/ChangeByZero`. ([@ydah]) +- Add new `RSpec/Capybara/SpecificFinders` cop. ([@ydah]) +- Add support for numblocks to `RSpec/AroundBlock`, `RSpec/EmptyLineAfterHook`, `RSpec/ExpectInHook`, `RSpec/HookArgument`, `RSpec/HooksBeforeExamples`, `RSpec/IteratedExpectation`, and `RSpec/NoExpectationExample`. ([@ydah]) +- Fix incorrect documentation URLs when using `rubocop --show-docs-url`. ([@r7kamura]) +- Add `AllowedGroups` configuration option to `RSpec/NestedGroups`. ([@ydah]) +- Deprecate `IgnoredPatterns` option in favor of the `AllowedPatterns` options. ([@ydah]) +- Add `AllowedPatterns` configuration option to `RSpec/ContextWording`. ([@ydah]) +- Add `RSpec/ClassCheck` cop. ([@r7kamura]) +- Fix a false positive for `RSpec/Capybara/SpecificMatcher` when pseudo-classes. ([@ydah]) +- Fix a false negative for `RSpec/SubjectStub` when the subject is declared with the `subject!` method and called by name. ([@eikes]) +- Support `Array.new(n)` on `RSpec/FactoryBot/CreateList` cop. ([@r7kamura]) + +## 2.12.1 (2022-07-03) + +- Fix a false positive for `RSpec/Capybara/SpecificMatcher`. ([@ydah]) + +## 2.12.0 (2022-07-02) + +- Fix incorrect path suggested by `RSpec/FilePath` cop when second argument contains spaces. ([@tejasbubane]) +- Fix autocorrect for EmptyLineSeparation. ([@johnny-miyake]) +- Add new `RSpec/Capybara/SpecificMatcher` cop. ([@ydah]) +- Fixed false offense detection in `FactoryBot/CreateList` when a n.times block is including method calls in the factory create arguments. ([@ngouy]) +- Fix error in `RSpec/RSpec/FactoryBot/CreateList` cop for empty block. ([@tejasbubane]) +- Update `RSpec/MultipleExpectations` cop documentation with examples of aggregate_failures use. ([@edgibbs]) +- Declare autocorrect as unsafe for `RSpec/VerifiedDoubleReference`. ([@Drowze]) +- Add new `RSpec/Rails/HaveHttpStatus` cop. ([@akiomik]) + +## 2.11.1 (2022-05-18) + +- Fix a regression in `RSpec/ExpectChange` flagging chained method calls. ([@pirj]) + +## 2.11.0 (2022-05-18) + +- Drop Ruby 2.5 support. ([@ydah]) +- Add new `RSpec/ChangeByZero` cop. ([@ydah]) +- Improve `RSpec/ExpectChange` to detect namespaced and top-level constants. ([@M-Yamashita01]) +- Introduce an amendment to `Metrics/BlockLength` to exclude spec files. ([@luke-hill]) + +## 2.10.0 (2022-04-19) + +- Fix a false positive for `RSpec/EmptyExampleGroup` when expectations in case statement. ([@ydah]) +- Add `RSpec/VerifiedDoubleReference` cop. ([@t3h2mas]) +- Make `RSpec/BeNil` cop configurable with a `be_nil` style and a `be` style. ([@bquorning]) +- Fix `Capybara/CurrentPathExpectation` autocorrect incompatible with `Style/TrailingCommaInArguments` autocorrect. ([@ydah]) + +## 2.9.0 (2022-02-28) + +- Add new `RSpec/BeNil` cop. ([@bquorning]) +- Add new `RSpec/BeEq` cop. ([@bquorning]) + +## 2.8.0 (2022-01-24) + +- Fix `RSpec/FactoryBot/SyntaxMethods` and `RSpec/Capybara/FeatureMethods` to inspect shared groups. ([@pirj]) +- Fix `RSpec/LeadingSubject` failure in non-spec code. ([@pirj]) +- Add bad example to `RSpec/SubjectStub` cop. ([@oshiro3]) +- Replace non-styleguide cops `StyleGuide` attribute with `Reference`. ([@pirj]) +- Fix `RSpec/SubjectStub` to disallow stubbing of subjects defined in parent example groups. ([@pirj]) + +## 2.7.0 (2021-12-26) + +- Add new `RSpec/FactoryBot/SyntaxMethods` cop. ([@leoarnold]) +- Exclude `task` type specs from `RSpec/DescribeClass` cop. ([@harry-graham]) + +## 2.6.0 (2021-11-08) + +- Fix merging RSpec DSL configuration from third-party gems. ([@pirj]) +- Fix `RSpec/ExcessiveDocstringSpacing` false positive for multi-line indented strings. ([@G-Rath]) +- Fix `Include` configuration for sub-departments. ([@pirj]) +- Ignore heredocs in `RSpec/ExcessiveDocstringSpacing`. ([@G-Rath]) +- Stop `RSpec/ExampleWording` from trying to correct heredocs. ([@G-Rath]) +- Add autocorrect support for `RSpec/VariableDefinition`. ([@r7kamura]) + +## 2.5.0 (2021-09-21) + +- Declare autocorrect as unsafe for `ExpectChange`. ([@francois-ferrandis]) +- Fix each example for `RSpec/HookArgument`. ([@lokhi]) +- Exclude unrelated Rails directories from `RSpec/DescribeClass`. ([@MothOnMars]) +- Add `RSpec/ExcessiveDocstringSpacing` cop. ([@G-Rath]) +- Add `RSpec/SubjectDeclaration` cop. ([@dswij]) +- Fix excessive whitespace removal in `RSpec/EmptyHook` autocorrection. ([@pirj]) +- Bump RuboCop requirement to v1.19.0. ([@pirj]) +- Fix false positive in `RSpec/IteratedExpectation` when there is single, non-expectation statement in the block body. ([@Darhazer]) + +## 2.4.0 (2021-06-09) + +- Update `RSpec/FilePath` to check suffix when given a non-constant top-level node (e.g. features). ([@topalovic]) +- Add missing documentation for `single_statement_only` style of `RSpec/ImplicitSubject` cop. ([@tejasbubane]) +- Fix an exception in `DescribedClass` when accessing a constant on a variable in a spec that is nested in a namespace. ([@rrosenblum]) +- Add new `RSpec/IdenticalEqualityAssertion` cop. ([@tejasbubane]) +- Add `RSpec/Rails/AvoidSetupHook` cop. ([@paydaylight]) +- Fix false negative in `RSpec/ExpectChange` cop with block style and chained method call. ([@tejasbubane]) + +## 2.3.0 (2021-04-28) + +- Allow `RSpec/ContextWording` to accept multi-word prefixes. ([@hosamaly]) +- Drop support for ruby 2.4. ([@bquorning]) +- Add `CountAsOne` configuration option to `RSpec/ExampleLength`. ([@stephannv]) +- Fix a false positive for `RSpec/RepeatedExampleGroupBody` when `pending` or `skip` have argument(s). ([@Tietew]) + +## 2.2.0 (2021-02-02) + +- Fix `HooksBeforeExamples`, `LeadingSubject`, `LetBeforeExamples` and `ScatteredLet` autocorrection to take into account inline comments and comments immediately before the moved node. ([@Darhazer]) +- Improve rubocop-rspec performance. ([@Darhazer], [@bquorning]) +- Include `Enabled: true` to prevent a mismatched configuration parameter warning when `RSpec` cops are explicitly enabled in the user configuration. ([@pirj]) + +## 2.1.0 (2020-12-17) + +- Fix `RSpec/FilePath` false positive for relative file path runs with long namespaces. ([@ahukkanen]) +- Update `RSpec/Focus` to have auto-correction. ([@dvandersluis]) + +## 2.0.1 (2020-12-02) + +- Fixed infinite loop in `RSpec/ExpectActual` autocorrection when both expected and actual values are literals. ([@Darhazer]) + +## 2.0.0 (2020-11-06) + +- Remove deprecated class `::RuboCop::Cop::RSpec::Cop`. ([@bquorning]) +- Retire `RSpec/InvalidPredicateMatcher` cop. ([@pirj]) +- Remove the code responsible for filtering files to inspect. ([@pirj]) +- Make RSpec language elements configurable. ([@sl4vr]) +- Remove `CustomIncludeMethods` `RSpec/EmptyExampleGroup` option in favour of the new RSpec DSL configuration. ([@pirj]) +- Enabled pending cop (`RSpec/StubbedMock`). ([@pirj]) + +## 2.0.0.pre (2020-10-22) + +- Update RuboCop dependency to v1.0.0. ([@bquorning]) +- Change namespace of several cops (`Capybara/*` -> `RSpec/Capybara/*`, `FactoryBot/*` -> `RSpec/FactoryBot/*`, `Rails/*` -> `RSpec/Rails/*`). ([@pirj], [@bquorning]) + +## 1.44.1 (2020-10-20) + +- Relax `rubocop-ast` version constraint. ([@PhilCoggins]) + +## 1.44.0 (2020-10-20) + +- Move our documentation from rubocop-rspec.readthedocs.io to docs.rubocop.org/rubocop-rspec. ([@bquorning]) +- Add `RSpec/RepeatedIncludeExample` cop. ([@biinari]) +- Add `RSpec/StubbedMock` cop. ([@bquorning], [@pirj]) +- Add `IgnoredMetadata` configuration option to `RSpec/DescribeClass`. ([@Rafix02]) +- Fix false positives in `RSpec/EmptyExampleGroup`. ([@pirj]) +- Fix a false positive for `RSpec/EmptyExampleGroup` when example is defined in an `if` branch. ([@koic]) + +## 1.43.2 (2020-08-25) + +- Fix `RSpec/FilePath` when checking a file with a shared example. ([@pirj]) +- Fix subject nesting detection in `RSpec/LeadingSubject`. ([@pirj]) + +## 1.43.1 (2020-08-17) + +- Fix `RSpec/FilePath` when checking a file defining e.g. an empty class. ([@bquorning]) + +## 1.43.0 (2020-08-17) + +- Add a new base cop class `::RuboCop::Cop::RSpec::Base`. The old base class `::RuboCop::Cop::RSpec::Cop` is deprecated, and will be removed in the next major release. ([@bquorning]) +- Add support for subject detection after includes and example groups in `RSpec/LeadingSubject`. ([@pirj]) +- Ignore trailing punctuation in context description prefix. ([@elliterate]) +- Relax `RSpec/VariableDefinition` cop so interpolated and multiline strings are accepted even when configured to enforce the `symbol` style. ([@bquorning]) +- Fix `RSpec/EmptyExampleGroup` to flag example groups with examples in invalid scopes. ([@mlarraz]) +- Fix `RSpec/EmptyExampleGroup` to ignore examples groups with examples defined inside iterators. ([@pirj]) +- Improve `RSpec/NestedGroups`, `RSpec/FilePath`, `RSpec/DescribeMethod`, `RSpec/MultipleDescribes`, `RSpec/DescribeClass`'s top-level example group detection. ([@pirj]) +- Add detection of `let!` with a block-pass or a string literal to `RSpec/LetSetup`. ([@pirj]) +- Add `IgnoredPatterns` configuration option to `RSpec/VariableName`. ([@jtannas]) +- Add `RSpec/MultipleMemoizedHelpers` cop. ([@mockdeep]) + ## 1.42.0 (2020-07-09) -* Update RuboCop dependency to 0.87.0 because of changes to internal APIs. ([@bquorning][], [@Darhazer][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- `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][]) +- 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][]) +- 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][]) +- `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][]) +- 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][]) +- `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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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) @@ -235,297 +469,338 @@ ## 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- Add `SkipBlocks` option for `DescribedClass` cop. ([@backus]) ## 1.5.3 (2016-08-02) -* Add `RSpec/NamedSubject` cop. ([@backus][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- 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][]) +- Make `RSpec::ExampleWording` case insensitive. ([@geniou]) ## 1.2.1 -* Add `RSpec::VerifiedDoubles` cop. ([@andyw8][]) +- 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][]) +- 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][]) +- Add `autocorrect` to `RSpec::DescribedClass` cop. ([@geniou]) ## 1.0.1 -* Add `config` folder to gemspec. ([@pstengel][]) +- Add `config` folder to gemspec. ([@pstengel]) ## 1.0.rc3 -* Update to RuboCop `>= 0.23`. ([@geniou][]) -* Add configuration option for `CustomTransformation` to `FileName` cop. ([@geniou][]) +- 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][]) +- 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][]) +- 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 common 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]) - + +[@abrom]: https://github.com/abrom +[@ahukkanen]: https://github.com/ahukkanen +[@akiomik]: https://github.com/akiomik +[@akrox58]: https://github.com/akrox58 +[@alexwayfer]: https://github.com/AlexWayfer +[@andrykonchin]: https://github.com/andrykonchin [@andyw8]: https://github.com/andyw8 +[@anthony-robin]: https://github.com/anthony-robin +[@aried3r]: https://github.com/aried3r +[@baberthal]: https://github.com/baberthal [@backus]: https://github.com/backus +[@biinari]: https://github.com/biinari +[@bmorrall]: https://github.com/bmorrall [@bquorning]: https://github.com/bquorning +[@brentwheeldon]: https://github.com/BrentWheeldon +[@brianhawley]: https://github.com/BrianHawley +[@cfabianski]: https://github.com/cfabianski +[@clupprich]: https://github.com/clupprich +[@composerinteralia]: https://github.com/composerinteralia +[@darhazer]: https://github.com/Darhazer +[@daveworth]: https://github.com/daveworth +[@dduugg]: https://github.com/dduugg [@deivid-rodriguez]: https://github.com/deivid-rodriguez +[@dgollahon]: https://github.com/dgollahon +[@drowze]: https://github.com/Drowze +[@dswij]: https://github.com/dswij +[@dvandersluis]: https://github.com/dvandersluis +[@edgibbs]: https://github.com/edgibbs +[@eikes]: https://github.com/eikes +[@eitoball]: https://github.com/eitoball +[@elebow]: https://github.com/elebow +[@elisefitz15]: https://github.com/EliseFitz15 +[@elliterate]: https://github.com/elliterate +[@foton]: https://github.com/foton +[@francois-ferrandis]: https://github.com/francois-ferrandis +[@g-rath]: https://github.com/G-Rath [@geniou]: https://github.com/geniou +[@gsamokovarov]: https://github.com/gsamokovarov +[@harry-graham]: https://github.com/harry-graham +[@harrylewis]: https://github.com/harrylewis +[@hosamaly]: https://github.com/hosamaly +[@ignaciovillaverde]: https://github.com/ignaciovillaverde [@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 +[@jfragoulis]: https://github.com/jfragoulis +[@johnny-miyake]: https://github.com/johnny-miyake [@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 +[@jonatas]: https://github.com/jonatas +[@jtannas]: https://github.com/jtannas +[@kellysutton]: https://github.com/kellysutton +[@koic]: https://github.com/koic +[@kuahyeow]: https://github.com/kuahyeow +[@lazycoder9]: https://github.com/lazycoder9 +[@leoarnold]: https://github.com/leoarnold +[@liberatys]: https://github.com/Liberatys +[@lokhi]: https://github.com/lokhi +[@luke-hill]: https://github.com/luke-hill +[@m-yamashita01]: https://github.com/M-Yamashita01 +[@miguelfteixeira]: https://github.com/miguelfteixeira [@mkenyon]: https://github.com/mkenyon -[@gsamokovarov]: https://github.com/gsamokovarov -[@schmijos]: https://github.com/schmijos -[@foton]: https://github.com/foton +[@mkrawc]: https://github.com/mkrawc +[@mlarraz]: https://github.com/mlarraz +[@mockdeep]: https://github.com/mockdeep +[@mothonmars]: https://github.com/MothOnMars [@nc-holodakg]: https://github.com/nc-holodakg -[@onumis]: https://github.com/onumis +[@nevir]: https://github.com/nevir +[@ngouy]: https://github.com/ngouy [@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 +[@nijikon]: https://github.com/nijikon +[@onk]: https://github.com/onk +[@onumis]: https://github.com/onumis +[@oshiro3]: https://github.com/oshiro3 +[@patrickomatic]: https://github.com/patrickomatic +[@paydaylight]: https://github.com/paydaylight +[@philcoggins]: https://github.com/PhilCoggins +[@pirj]: https://github.com/pirj +[@pocke]: https://github.com/pocke +[@pstengel]: https://github.com/pstengel +[@qqism]: https://github.com/QQism +[@r7kamura]: https://github.com/r7kamura +[@rafix02]: https://github.com/Rafix02 +[@redross]: https://github.com/redross +[@renanborgescampos]: https://github.com/renanborgescampos +[@robotdana]: https://github.com/robotdana +[@rolfschmidt]: https://github.com/rolfschmidt +[@rrosenblum]: https://github.com/rrosenblum +[@rspeicher]: https://github.com/rspeicher +[@rst-j]: https://github.com/RST-J +[@samrjenkins]: https://github.com/samrjenkins +[@schmijos]: https://github.com/schmijos +[@seanpdoyle]: https://github.com/seanpdoyle +[@sl4vr]: https://github.com/sl4vr +[@smcgivern]: https://github.com/smcgivern +[@stephannv]: https://github.com/stephannv +[@t3h2mas]: https://github.com/t3h2mas +[@tdeo]: https://github.com/tdeo [@tejasbubane]: https://github.com/tejasbubane +[@telmofcosta]: https://github.com/telmofcosta +[@tietew]: https://github.com/Tietew +[@timrogers]: https://github.com/timrogers +[@topalovic]: https://github.com/topalovic [@twalpole]: https://github.com/twalpole +[@vzvu3k6k]: https://github.com/vzvu3k6k +[@walf443]: https://github.com/walf443 +[@ybiquitous]: https://github.com/ybiquitous +[@ydah]: https://github.com/ydah +[@yevhene]: https://github.com/yevhene +[@ypresto]: https://github.com/ypresto [@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 +[@zverok]: https://github.com/zverok diff -Nru ruby-rubocop-rspec-1.42.0/.circleci/config.yml ruby-rubocop-rspec-2.16.0/.circleci/config.yml --- ruby-rubocop-rspec-1.42.0/.circleci/config.yml 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.circleci/config.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -version: 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 diff -Nru ruby-rubocop-rspec-1.42.0/CODE_OF_CONDUCT.md ruby-rubocop-rspec-2.16.0/CODE_OF_CONDUCT.md --- ruby-rubocop-rspec-1.42.0/CODE_OF_CONDUCT.md 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/CODE_OF_CONDUCT.md 2022-12-13 09:15:42.000000000 +0000 @@ -9,9 +9,9 @@ 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 +- 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 +- 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. +- Behaviour which can be reasonably considered harassment will not be tolerated. diff -Nru ruby-rubocop-rspec-1.42.0/.codespellignore ruby-rubocop-rspec-2.16.0/.codespellignore --- ruby-rubocop-rspec-1.42.0/.codespellignore 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.codespellignore 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1 @@ +xdescribe diff -Nru ruby-rubocop-rspec-1.42.0/config/default.yml ruby-rubocop-rspec-2.16.0/config/default.yml --- ruby-rubocop-rspec-1.42.0/config/default.yml 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/config/default.yml 2022-12-13 09:15:42.000000000 +0000 @@ -1,95 +1,266 @@ --- -AllCops: - RSpec: - Patterns: - - _spec.rb - - "(?:^|/)spec/" - RSpec/FactoryBot: - Patterns: - - spec/factories.rb - - spec/factories/**/*.rb - - features/support/factories/**/*.rb +RSpec: + Enabled: true + StyleGuideBaseURL: https://rspec.rubystyle.guide + DocumentationBaseURL: https://docs.rubocop.org/rubocop-rspec + Include: &1 + - "**/*_spec.rb" + - "**/spec/**/*" + Language: &2 + inherit_mode: + merge: + - Expectations + - Helpers + - Hooks + - Subjects + ExampleGroups: + inherit_mode: + merge: + - Regular + - Skipped + - Focused + Regular: + - describe + - context + - feature + - example_group + Skipped: + - xdescribe + - xcontext + - xfeature + Focused: + - fdescribe + - fcontext + - ffeature + Examples: + inherit_mode: + merge: + - Regular + - Skipped + - Focused + - Pending + Regular: + - it + - specify + - example + - scenario + - its + Focused: + - fit + - fspecify + - fexample + - fscenario + - focus + Skipped: + - xit + - xspecify + - xexample + - xscenario + - skip + Pending: + - pending + Expectations: + - are_expected + - expect + - expect_any_instance_of + - is_expected + - should + - should_not + - should_not_receive + - should_receive + Helpers: + - let + - let! + Hooks: + - prepend_before + - before + - append_before + - around + - prepend_after + - after + - append_after + Includes: + inherit_mode: + merge: + - Examples + - Context + Examples: + - it_behaves_like + - it_should_behave_like + - include_examples + Context: + - include_context + SharedGroups: + inherit_mode: + merge: + - Examples + - Context + Examples: + - shared_examples + - shared_examples_for + Context: + - shared_context + Subjects: + - subject + - subject! + +Metrics/BlockLength: + inherit_mode: + merge: + - Exclude + Exclude: + - "**/*_spec.rb" + - "**/spec/**/*" 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 + Reference: 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 + Reference: 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 + StyleGuide: https://rspec.rubystyle.guide/#any_instance_of + Reference: 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 + Reference: 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 + StyleGuide: https://rspec.rubystyle.guide/#be-matcher + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be + +RSpec/BeEq: + Description: Check for expectations where `be(...)` can replace `eq(...)`. + Enabled: pending + Safe: false + VersionAdded: 2.9.0 + VersionChanged: '2.16' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEq RSpec/BeEql: Description: Check for expectations where `be(...)` can replace `eql(...)`. Enabled: true + Safe: false VersionAdded: '1.7' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql + VersionChanged: '2.16' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql + +RSpec/BeNil: + Description: Ensures a consistent style is used when matching `nil`. + Enabled: pending + EnforcedStyle: be_nil + SupportedStyles: + - be + - be_nil + VersionAdded: 2.9.0 + VersionChanged: 2.10.0 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeNil 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 + - 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 + StyleGuide: https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll + +RSpec/ChangeByZero: + Description: Prefer negated matchers over `to change.by(0)`. + Enabled: pending + VersionAdded: '2.11' + VersionChanged: '2.14' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ChangeByZero + NegatedMatcher: ~ + +RSpec/ClassCheck: + Description: Enforces consistent use of `be_a` or `be_kind_of`. + StyleGuide: "#is-a-vs-kind-of" + Enabled: pending + VersionAdded: '2.13' + EnforcedStyle: be_a + SupportedStyles: + - be_a + - be_kind_of + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ClassCheck 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 + StyleGuide: https://rspec.rubystyle.guide/#example-group-naming + Reference: 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 + - when + - with + - without + AllowedPatterns: [] VersionAdded: '1.20' - VersionChanged: 1.20.1 - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording + VersionChanged: '2.13' + StyleGuide: https://rspec.rubystyle.guide/#context-descriptions + Reference: 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. + Description: Check that the first argument to the top-level describe is a constant. Enabled: true + Exclude: + - "**/spec/features/**/*" + - "**/spec/requests/**/*" + - "**/spec/routing/**/*" + - "**/spec/system/**/*" + - "**/spec/views/**/*" + IgnoredMetadata: + type: + - channel + - controller + - helper + - job + - mailer + - model + - request + - routing + - view + - feature + - system + - mailbox + - aruba + - task VersionAdded: '1.0' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass + VersionChanged: '2.7' + Reference: 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 + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol RSpec/DescribedClass: Description: Checks that tests use `described_class`. @@ -97,87 +268,103 @@ SkipBlocks: false EnforcedStyle: described_class SupportedStyles: - - described_class - - explicit + - described_class + - explicit SafeAutoCorrect: false VersionAdded: '1.0' VersionChanged: '1.11' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping RSpec/Dialect: - Description: This cop enforces custom RSpec dialects. + Description: Enforces custom RSpec dialects. Enabled: false PreferredMethods: {} VersionAdded: '1.33' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect + +RSpec/DuplicatedMetadata: + Description: Avoid duplicated metadata. + Enabled: pending + VersionAdded: '2.16' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DuplicatedMetadata RSpec/EmptyExampleGroup: Description: Checks if an example group does not include any tests. Enabled: true - CustomIncludeMethods: [] + SafeAutoCorrect: false VersionAdded: '1.7' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup + VersionChanged: '2.13' + Reference: 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 + Reference: 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 + StyleGuide: https://rspec.rubystyle.guide/#empty-lines-around-examples + Reference: 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 + StyleGuide: https://rspec.rubystyle.guide/#empty-lines-between-describes + Reference: 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 + StyleGuide: https://rspec.rubystyle.guide/#empty-line-after-let + Reference: 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 + VersionChanged: '2.13' + StyleGuide: https://rspec.rubystyle.guide/#empty-line-after-let + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook + AllowConsecutiveOneLiners: true 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 + StyleGuide: https://rspec.rubystyle.guide/#empty-line-after-let + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject RSpec/ExampleLength: Description: Checks for long examples. Enabled: true Max: 5 + CountAsOne: [] VersionAdded: '1.5' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength + VersionChanged: '2.3' + Reference: 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 + - always_allow + - single_line_only + - disallow VersionAdded: '1.22' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription RSpec/ExampleWording: Description: Checks for common mistakes in example descriptions. @@ -188,43 +375,57 @@ have: has HAVE: HAS IgnoredWords: [] + DisallowedExamples: + - works VersionAdded: '1.0' - VersionChanged: '1.2' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording + VersionChanged: '2.13' + StyleGuide: https://rspec.rubystyle.guide/#should-in-example-docstrings + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording + +RSpec/ExcessiveDocstringSpacing: + Description: Checks for excessive whitespace in example descriptions. + Enabled: pending + VersionAdded: '2.5' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExcessiveDocstringSpacing RSpec/ExpectActual: Description: Checks for `expect(...)` calls containing literal values. Enabled: true Exclude: - - spec/routing/**/* + - spec/routing/**/* VersionAdded: '1.7' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectActual + Reference: 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 + - method_call + - block + SafeAutoCorrect: false VersionAdded: '1.22' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectChange + VersionChanged: '2.5' + Reference: 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 + Reference: 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 + Reference: 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 + Include: + - "**/*_spec*rb*" + - "**/spec/**/*" CustomTransform: RuboCop: rubocop RSpec: rspec @@ -232,64 +433,75 @@ SpecSuffixOnly: false VersionAdded: '1.2' VersionChanged: '1.40' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FilePath + Reference: 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 + VersionChanged: '2.1' + Reference: 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 + - implicit + - each + - example VersionAdded: '1.7' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HookArgument + StyleGuide: https://rspec.rubystyle.guide/#redundant-beforeeach + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples + +RSpec/IdenticalEqualityAssertion: + Description: Checks for equality assertions with identical expressions on both sides. + Enabled: pending + VersionAdded: '2.4' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IdenticalEqualityAssertion 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 + StyleGuide: https://rspec.rubystyle.guide/#implicit-block-expectations + Reference: 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 + - is_expected + - should VersionAdded: '1.8' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitExpect + StyleGuide: https://rspec.rubystyle.guide/#use-expect + Reference: 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 + - single_line_only + - single_statement_only + - disallow + - require_implicit VersionAdded: '1.29' - VersionChanged: '1.30' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject + VersionChanged: '2.13' + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceSpy RSpec/InstanceVariable: Description: Checks for instance variable usage in specs. @@ -297,94 +509,91 @@ 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 + StyleGuide: https://rspec.rubystyle.guide/#instance-variables + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceVariable 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 + - it_behaves_like + - it_should_behave_like VersionAdded: '1.13' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike + Reference: 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 + Reference: 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 + StyleGuide: https://rspec.rubystyle.guide/#leading-subject + Reference: 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 + StyleGuide: https://rspec.rubystyle.guide/#declare-constants + Reference: 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 + Reference: 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 + Reference: 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 + Reference: 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 + - allow + - expect VersionAdded: '1.7' VersionChanged: '1.8' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageExpectation + Reference: 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 + - have_received + - receive VersionAdded: '1.9' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageSpies + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument RSpec/MultipleDescribes: - Description: Checks for multiple top level describes. + Description: Checks for multiple top-level example groups. Enabled: true VersionAdded: '1.0' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes RSpec/MultipleExpectations: Description: Checks if examples contain too many `expect` calls. @@ -392,50 +601,84 @@ Max: 1 VersionAdded: '1.7' VersionChanged: '1.21' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations + StyleGuide: https://rspec.rubystyle.guide/#expectation-per-example + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations + +RSpec/MultipleMemoizedHelpers: + Description: Checks if example groups contain too many `let` and `subject` calls. + Enabled: true + AllowSubject: true + Max: 5 + VersionAdded: '1.43' + StyleGuide: https://rspec.rubystyle.guide/#let-blocks + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleSubjects RSpec/NamedSubject: Description: Checks for explicitly referenced test subjects. Enabled: true + EnforcedStyle: always + SupportedStyles: + - always + - named_only IgnoreSharedExamples: true VersionAdded: 1.5.3 - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject + VersionChanged: '2.15' + StyleGuide: https://rspec.rubystyle.guide/#use-subject + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject RSpec/NestedGroups: Description: Checks for nested example groups. Enabled: true Max: 3 + AllowedGroups: [] VersionAdded: '1.7' - VersionChanged: '1.10' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups + VersionChanged: '2.13' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups + +RSpec/NoExpectationExample: + Description: Checks if an example contains any expectation. + Enabled: pending + Safe: false + VersionAdded: '2.13' + VersionChanged: '2.14' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NoExpectationExample + AllowedPatterns: + - "^expect_" + - "^assert_" RSpec/NotToNot: Description: Checks for consistent method usage for negating expectations. Enabled: true EnforcedStyle: not_to SupportedStyles: - - not_to - - to_not + - not_to + - to_not VersionAdded: '1.4' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NotToNot + Reference: 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 + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending + +RSpec/PendingWithoutReason: + Description: Checks for pending or skipped examples without reason. + Enabled: pending + VersionAdded: '2.16' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PendingWithoutReason RSpec/PredicateMatcher: Description: Prefer using predicate matcher over using predicate method directly. @@ -444,122 +687,163 @@ EnforcedStyle: inflected AllowedExplicitMatchers: [] SupportedStyles: - - inflected - - explicit + - inflected + - explicit SafeAutoCorrect: false VersionAdded: '1.16' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher + StyleGuide: https://rspec.rubystyle.guide/#predicate-matchers + Reference: 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 + Reference: 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 + Reference: 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 + Reference: 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 + Reference: 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 + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription + +RSpec/RepeatedIncludeExample: + Description: Check for repeated include of shared examples. + Enabled: true + VersionAdded: '1.44' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedIncludeExample RSpec/ReturnFromStub: Description: Checks for consistent style of stub's return setting. Enabled: true EnforcedStyle: and_return SupportedStyles: - - and_return - - block + - and_return + - block VersionAdded: '1.16' VersionChanged: '1.22' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReturnFromStub + Reference: 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 + Reference: 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 + Reference: 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 + Reference: 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 + Reference: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain + +RSpec/SortMetadata: + Description: Sort RSpec metadata alphabetically. + Enabled: pending + VersionAdded: '2.14' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SortMetadata + +RSpec/StubbedMock: + Description: Checks that message expectations do not have a configured response. + Enabled: true + VersionAdded: '1.44' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StubbedMock + +RSpec/SubjectDeclaration: + Description: Ensure that subject is defined using subject helper. + Enabled: pending + VersionAdded: '2.5' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectDeclaration 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 + VersionChanged: '2.8' + StyleGuide: https://rspec.rubystyle.guide/#dont-stub-subject + Reference: 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 + Reference: 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 + - symbols + - strings VersionAdded: '1.40' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableDefinition + Reference: 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 + - snake_case + - camelCase + AllowedPatterns: [] VersionAdded: '1.40' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName + VersionChanged: '2.13' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName + +RSpec/VerifiedDoubleReference: + Description: Checks for consistent verified double reference style. + Enabled: pending + SafeAutoCorrect: false + EnforcedStyle: constant + SupportedStyles: + - constant + - string + VersionAdded: 2.10.0 + VersionChanged: '2.12' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubleReference RSpec/VerifiedDoubles: Description: Prefer using verifying doubles over normal doubles. @@ -568,68 +852,195 @@ IgnoreSymbolicNames: false VersionAdded: 1.2.1 VersionChanged: '1.5' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles + StyleGuide: https://rspec.rubystyle.guide/#doubles + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles RSpec/VoidExpect: - Description: This cop checks void `expect()`. + Description: Checks void `expect()`. Enabled: true VersionAdded: '1.16' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect RSpec/Yield: - Description: This cop checks for calling a block within a stub. + Description: 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 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield + +RSpec/Capybara: + Enabled: true + Include: *1 + Language: *2 -Capybara/CurrentPathExpectation: +RSpec/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 + VersionChanged: '2.0' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/CurrentPathExpectation -Capybara/FeatureMethods: +RSpec/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 + VersionChanged: '2.0' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/FeatureMethods + +RSpec/Capybara/NegationMatcher: + Description: Enforces use of `have_no_*` or `not_to` for negated expectations. + Enabled: pending + VersionAdded: '2.14' + EnforcedStyle: not_to + SupportedStyles: + - have_no + - not_to + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/NegationMatcher + +RSpec/Capybara/SpecificActions: + Description: Checks for there is a more specific actions offered by Capybara. + Enabled: pending + VersionAdded: '2.14' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificActions + +RSpec/Capybara/SpecificFinders: + Description: Checks if there is a more specific finder offered by Capybara. + Enabled: pending + VersionAdded: '2.13' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificFinders + +RSpec/Capybara/SpecificMatcher: + Description: Checks for there is a more specific matcher offered by Capybara. + Enabled: pending + VersionAdded: '2.12' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificMatcher -Capybara/VisibilityMatcher: - Description: Checks for boolean visibility in capybara finders. +RSpec/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 + VersionChanged: '2.0' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/VisibilityMatcher -FactoryBot/AttributeDefinedStatically: +RSpec/FactoryBot: + Enabled: true + Include: *1 + Language: *2 + +RSpec/FactoryBot/AttributeDefinedStatically: Description: Always declare attribute values as blocks. Enabled: true + Include: + - spec/factories.rb + - spec/factories/**/*.rb + - features/support/factories/**/*.rb VersionAdded: '1.28' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/AttributeDefinedStatically + VersionChanged: '2.0' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/AttributeDefinedStatically + +RSpec/FactoryBot/ConsistentParenthesesStyle: + Description: Use a consistent style for parentheses in factory bot calls. + Enabled: pending + EnforcedStyle: require_parentheses + SupportedStyles: + - require_parentheses + - omit_parentheses + VersionAdded: '2.14' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/ConsistentParenthesesStyle -FactoryBot/CreateList: +RSpec/FactoryBot/CreateList: Description: Checks for create_list usage. Enabled: true + Include: + - "**/*_spec.rb" + - "**/spec/**/*" + - spec/factories.rb + - spec/factories/**/*.rb + - features/support/factories/**/*.rb EnforcedStyle: create_list SupportedStyles: - - create_list - - n_times + - create_list + - n_times VersionAdded: '1.25' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList + VersionChanged: '2.0' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList -FactoryBot/FactoryClassName: +RSpec/FactoryBot/FactoryClassName: Description: Use string value when setting the class attribute explicitly. Enabled: true + Include: + - spec/factories.rb + - spec/factories/**/*.rb + - features/support/factories/**/*.rb VersionAdded: '1.37' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName + VersionChanged: '2.0' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName + +RSpec/FactoryBot/FactoryNameStyle: + Description: Checks for name style for argument of FactoryBot::Syntax::Methods. + Enabled: pending + VersionAdded: '2.16' + EnforcedStyle: symbol + SupportedStyles: + - symbol + - string + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryNameStyle + +RSpec/FactoryBot/SyntaxMethods: + Description: Use shorthands from `FactoryBot::Syntax::Methods` in your specs. + Enabled: pending + SafeAutoCorrect: false + VersionAdded: '2.7' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/SyntaxMethods + +RSpec/Rails: + Enabled: true + Include: *1 + Language: *2 -Rails/HttpStatus: +RSpec/Rails/AvoidSetupHook: + Description: Checks that tests use RSpec `before` hook over Rails `setup` method. + Enabled: pending + VersionAdded: '2.4' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/AvoidSetupHook + +RSpec/Rails/HaveHttpStatus: + Description: Checks that tests use `have_http_status` instead of equality matchers. + Enabled: pending + SafeAutoCorrect: false + VersionAdded: '2.12' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HaveHttpStatus + +RSpec/Rails/HttpStatus: Description: Enforces use of symbolic or numeric value to describe HTTP status. Enabled: true EnforcedStyle: symbolic SupportedStyles: - - numeric - - symbolic + - numeric + - symbolic VersionAdded: '1.23' - StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus + VersionChanged: '2.0' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus + +RSpec/Rails/InferredSpecType: + Description: Identifies redundant spec type. + Enabled: pending + Safe: false + VersionAdded: '2.14' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/InferredSpecType + Inferences: + channels: channel + controllers: controller + features: feature + generator: generator + helpers: helper + jobs: job + mailboxes: mailbox + mailers: mailer + models: model + requests: request + integration: request + api: request + routing: routing + system: system + views: view diff -Nru ruby-rubocop-rspec-1.42.0/config/obsoletion.yml ruby-rubocop-rspec-2.16.0/config/obsoletion.yml --- ruby-rubocop-rspec-1.42.0/config/obsoletion.yml 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/config/obsoletion.yml 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,14 @@ +# +# Configuration of obsolete/deprecated cops used by `ConfigObsoletion`. +# +# See: https://docs.rubocop.org/rubocop/extensions.html#config-obsoletions +# + +# Cop parameters that have been changed +# Can be treated as a warning instead of a failure with `severity: warning` +changed_parameters: + - cops: + - RSpec/VariableName + parameters: IgnoredPatterns + alternative: AllowedPatterns + severity: warning diff -Nru ruby-rubocop-rspec-1.42.0/debian/changelog ruby-rubocop-rspec-2.16.0/debian/changelog --- ruby-rubocop-rspec-1.42.0/debian/changelog 2020-07-24 18:23:46.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/debian/changelog 2022-12-21 23:04:05.000000000 +0000 @@ -1,3 +1,22 @@ +ruby-rubocop-rspec (2.16.0-1) unstable; urgency=medium + + * Team upload + + [ Cédric Boutillier ] + * [ci skip] Update team name + + [ Debian Janitor ] + * Set upstream metadata fields: Bug-Database, Repository, Repository-Browse. + * debian/watch: Use GitHub /tags rather than /releases page. + * Update standards version to 4.6.1, no changes needed. + + [ Antonio Terceiro ] + * New upstream version 2.16.0 + * Refresh patches + * Add patch to fix running the test suite under autopkgtest + + -- Antonio Terceiro Wed, 21 Dec 2022 20:04:05 -0300 + ruby-rubocop-rspec (1.42.0-1) unstable; urgency=medium * New upstream version 1.42.0 diff -Nru ruby-rubocop-rspec-1.42.0/debian/control ruby-rubocop-rspec-2.16.0/debian/control --- ruby-rubocop-rspec-1.42.0/debian/control 2020-07-24 18:23:26.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/debian/control 2022-12-21 23:04:05.000000000 +0000 @@ -1,7 +1,7 @@ Source: ruby-rubocop-rspec Section: ruby Priority: optional -Maintainer: Debian Ruby Extras Maintainers +Maintainer: Debian Ruby Team Uploaders: Miguel Landaeta , Utkarsh Gupta Build-Depends: debhelper-compat (= 13), @@ -11,7 +11,7 @@ ruby-rack, ruby-rspec, yard -Standards-Version: 4.5.0 +Standards-Version: 4.6.1 Vcs-Git: https://salsa.debian.org/ruby-team/ruby-rubocop-rspec.git Vcs-Browser: https://salsa.debian.org/ruby-team/ruby-rubocop-rspec Homepage: https://github.com/rubocop-hq/rubocop-rspec diff -Nru ruby-rubocop-rspec-1.42.0/debian/patches/0002-spec_helper-require-shared-context-assuming-it-s-on-.patch ruby-rubocop-rspec-2.16.0/debian/patches/0002-spec_helper-require-shared-context-assuming-it-s-on-.patch --- ruby-rubocop-rspec-1.42.0/debian/patches/0002-spec_helper-require-shared-context-assuming-it-s-on-.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/debian/patches/0002-spec_helper-require-shared-context-assuming-it-s-on-.patch 2022-12-21 23:04:05.000000000 +0000 @@ -0,0 +1,22 @@ +From: Antonio Terceiro +Date: Wed, 21 Dec 2022 19:59:18 -0300 +Subject: spec_helper: require shared context assuming it's on $LOAD_PATH + +Forwarded: not-needed + +--- + spec/spec_helper.rb | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb +index cf19e9f..fee04fc 100644 +--- a/spec/spec_helper.rb ++++ b/spec/spec_helper.rb +@@ -12,6 +12,7 @@ Dir + .glob(File.expand_path(spec_helper_glob, __dir__)) + .sort + .each(&method(:require)) ++require 'rubocop/rspec/shared_contexts/default_rspec_language_config_context' + + RSpec.configure do |config| + # Set metadata so smoke tests are run on all cop specs diff -Nru ruby-rubocop-rspec-1.42.0/debian/patches/01-disable-bundler.patch ruby-rubocop-rspec-2.16.0/debian/patches/01-disable-bundler.patch --- ruby-rubocop-rspec-1.42.0/debian/patches/01-disable-bundler.patch 2020-07-24 18:18:50.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/debian/patches/01-disable-bundler.patch 2022-12-21 23:04:05.000000000 +0000 @@ -1,8 +1,15 @@ -Description: Disable bundler usage -Author: Miguel Landaeta +From: Miguel Landaeta +Date: Wed, 21 Dec 2022 19:59:04 -0300 +Subject: Disable bundler usage + Forwarded: no Last-Update: 2017-11-04 +--- + Rakefile | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) +diff --git a/Rakefile b/Rakefile +index 079328d..1891520 100644 --- a/Rakefile +++ b/Rakefile @@ -2,16 +2,16 @@ @@ -11,9 +18,7 @@ -require 'bundler' -require 'bundler/gem_tasks' -+# require 'bundler' -+# require 'bundler/gem_tasks' - +- -begin - Bundler.setup(:default, :development) -rescue Bundler::BundlerError => e @@ -21,6 +26,9 @@ - warn 'Run `bundle install` to install missing gems' - exit e.status_code -end ++# require 'bundler' ++# require 'bundler/gem_tasks' ++ +# begin +# Bundler.setup(:default, :development) +# rescue Bundler::BundlerError => e diff -Nru ruby-rubocop-rspec-1.42.0/debian/patches/series ruby-rubocop-rspec-2.16.0/debian/patches/series --- ruby-rubocop-rspec-1.42.0/debian/patches/series 2020-07-24 18:18:50.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/debian/patches/series 2022-12-21 23:04:05.000000000 +0000 @@ -1,2 +1,2 @@ 01-disable-bundler.patch -#02-modify-rubocop-rspec-homedir.patch +0002-spec_helper-require-shared-context-assuming-it-s-on-.patch diff -Nru ruby-rubocop-rspec-1.42.0/debian/upstream/metadata ruby-rubocop-rspec-2.16.0/debian/upstream/metadata --- ruby-rubocop-rspec-1.42.0/debian/upstream/metadata 2020-07-24 18:18:50.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/debian/upstream/metadata 2022-12-21 23:04:05.000000000 +0000 @@ -1,7 +1,7 @@ --- Archive: GitHub -Bug-Database: https://github.com/rubocop-hq/rubocop-rspec/issues +Bug-Database: https://github.com/rubocop/rubocop-rspec/issues Bug-Submit: https://github.com/rubocop-hq/rubocop-rspec/issues Changelog: https://github.com/rubocop-hq/rubocop-rspec/tags -Repository: https://github.com/rubocop-hq/rubocop-rspec.git -Repository-Browse: https://github.com/rubocop-hq/rubocop-rspec +Repository: https://github.com/rubocop/rubocop-rspec.git +Repository-Browse: https://github.com/rubocop/rubocop-rspec diff -Nru ruby-rubocop-rspec-1.42.0/debian/watch ruby-rubocop-rspec-2.16.0/debian/watch --- ruby-rubocop-rspec-1.42.0/debian/watch 2020-07-24 18:18:50.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/debian/watch 2022-12-21 23:04:05.000000000 +0000 @@ -1,2 +1,2 @@ version=4 -https://github.com/rubocop-hq/rubocop-rspec/releases .*/v(.*).tar.gz +https://github.com/rubocop-hq/rubocop-rspec/tags .*/v(.*).tar.gz diff -Nru ruby-rubocop-rspec-1.42.0/docs/antora.yml ruby-rubocop-rspec-2.16.0/docs/antora.yml --- ruby-rubocop-rspec-1.42.0/docs/antora.yml 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/antora.yml 2022-12-13 09:15:42.000000000 +0000 @@ -1,5 +1,5 @@ name: rubocop-rspec title: RuboCop RSpec -version: master +version: '2.16' nav: -- modules/ROOT/nav.adoc + - modules/ROOT/nav.adoc diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/nav.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/nav.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/nav.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/nav.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -2,8 +2,11 @@ * xref:installation.adoc[Installation] * xref:usage.adoc[Usage] * xref:cops.adoc[Cops] +* xref:upgrade_to_version_2.adoc[Upgrade to 2.x] +* xref:third_party_rspec_syntax_extensions.adoc[RSpec syntax extensions in third-party gems] +* xref:development.adoc[Development] * Cops Documentation -** xref:cops_capybara.adoc[Capybara] -** xref:cops_factorybot.adoc[FactoryBot] -** xref:cops_rails.adoc[Rails] +** xref:cops_rspec_capybara.adoc[Capybara] +** xref:cops_rspec_factorybot.adoc[FactoryBot] +** xref:cops_rspec_rails.adoc[Rails] ** xref:cops_rspec.adoc[RSpec] diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -1,99 +1,123 @@ // START_COP_LIST -==== Department xref:cops_capybara.adoc[Capybara] +=== Department xref:cops_rspec.adoc[RSpec] -* 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] +* xref:cops_rspec.adoc#rspecalignleftletbrace[RSpec/AlignLeftLetBrace] +* xref:cops_rspec.adoc#rspecalignrightletbrace[RSpec/AlignRightLetBrace] +* xref:cops_rspec.adoc#rspecanyinstance[RSpec/AnyInstance] +* xref:cops_rspec.adoc#rspecaroundblock[RSpec/AroundBlock] +* xref:cops_rspec.adoc#rspecbe[RSpec/Be] +* xref:cops_rspec.adoc#rspecbeeq[RSpec/BeEq] +* xref:cops_rspec.adoc#rspecbeeql[RSpec/BeEql] +* xref:cops_rspec.adoc#rspecbenil[RSpec/BeNil] +* xref:cops_rspec.adoc#rspecbeforeafterall[RSpec/BeforeAfterAll] +* xref:cops_rspec.adoc#rspecchangebyzero[RSpec/ChangeByZero] +* xref:cops_rspec.adoc#rspecclasscheck[RSpec/ClassCheck] +* xref:cops_rspec.adoc#rspeccontextmethod[RSpec/ContextMethod] +* xref:cops_rspec.adoc#rspeccontextwording[RSpec/ContextWording] +* xref:cops_rspec.adoc#rspecdescribeclass[RSpec/DescribeClass] +* xref:cops_rspec.adoc#rspecdescribemethod[RSpec/DescribeMethod] +* xref:cops_rspec.adoc#rspecdescribesymbol[RSpec/DescribeSymbol] +* xref:cops_rspec.adoc#rspecdescribedclass[RSpec/DescribedClass] +* xref:cops_rspec.adoc#rspecdescribedclassmodulewrapping[RSpec/DescribedClassModuleWrapping] +* xref:cops_rspec.adoc#rspecdialect[RSpec/Dialect] +* xref:cops_rspec.adoc#rspecduplicatedmetadata[RSpec/DuplicatedMetadata] +* xref:cops_rspec.adoc#rspecemptyexamplegroup[RSpec/EmptyExampleGroup] +* xref:cops_rspec.adoc#rspecemptyhook[RSpec/EmptyHook] +* xref:cops_rspec.adoc#rspecemptylineafterexample[RSpec/EmptyLineAfterExample] +* xref:cops_rspec.adoc#rspecemptylineafterexamplegroup[RSpec/EmptyLineAfterExampleGroup] +* xref:cops_rspec.adoc#rspecemptylineafterfinallet[RSpec/EmptyLineAfterFinalLet] +* xref:cops_rspec.adoc#rspecemptylineafterhook[RSpec/EmptyLineAfterHook] +* xref:cops_rspec.adoc#rspecemptylineaftersubject[RSpec/EmptyLineAfterSubject] +* xref:cops_rspec.adoc#rspecexamplelength[RSpec/ExampleLength] +* xref:cops_rspec.adoc#rspecexamplewithoutdescription[RSpec/ExampleWithoutDescription] +* xref:cops_rspec.adoc#rspecexamplewording[RSpec/ExampleWording] +* xref:cops_rspec.adoc#rspecexcessivedocstringspacing[RSpec/ExcessiveDocstringSpacing] +* xref:cops_rspec.adoc#rspecexpectactual[RSpec/ExpectActual] +* xref:cops_rspec.adoc#rspecexpectchange[RSpec/ExpectChange] +* xref:cops_rspec.adoc#rspecexpectinhook[RSpec/ExpectInHook] +* xref:cops_rspec.adoc#rspecexpectoutput[RSpec/ExpectOutput] +* xref:cops_rspec.adoc#rspecfilepath[RSpec/FilePath] +* xref:cops_rspec.adoc#rspecfocus[RSpec/Focus] +* xref:cops_rspec.adoc#rspechookargument[RSpec/HookArgument] +* xref:cops_rspec.adoc#rspechooksbeforeexamples[RSpec/HooksBeforeExamples] +* xref:cops_rspec.adoc#rspecidenticalequalityassertion[RSpec/IdenticalEqualityAssertion] +* xref:cops_rspec.adoc#rspecimplicitblockexpectation[RSpec/ImplicitBlockExpectation] +* xref:cops_rspec.adoc#rspecimplicitexpect[RSpec/ImplicitExpect] +* xref:cops_rspec.adoc#rspecimplicitsubject[RSpec/ImplicitSubject] +* xref:cops_rspec.adoc#rspecinstancespy[RSpec/InstanceSpy] +* xref:cops_rspec.adoc#rspecinstancevariable[RSpec/InstanceVariable] +* xref:cops_rspec.adoc#rspecitbehaveslike[RSpec/ItBehavesLike] +* xref:cops_rspec.adoc#rspeciteratedexpectation[RSpec/IteratedExpectation] +* xref:cops_rspec.adoc#rspecleadingsubject[RSpec/LeadingSubject] +* xref:cops_rspec.adoc#rspecleakyconstantdeclaration[RSpec/LeakyConstantDeclaration] +* xref:cops_rspec.adoc#rspecletbeforeexamples[RSpec/LetBeforeExamples] +* xref:cops_rspec.adoc#rspecletsetup[RSpec/LetSetup] +* xref:cops_rspec.adoc#rspecmessagechain[RSpec/MessageChain] +* xref:cops_rspec.adoc#rspecmessageexpectation[RSpec/MessageExpectation] +* xref:cops_rspec.adoc#rspecmessagespies[RSpec/MessageSpies] +* xref:cops_rspec.adoc#rspecmissingexamplegroupargument[RSpec/MissingExampleGroupArgument] +* xref:cops_rspec.adoc#rspecmultipledescribes[RSpec/MultipleDescribes] +* xref:cops_rspec.adoc#rspecmultipleexpectations[RSpec/MultipleExpectations] +* xref:cops_rspec.adoc#rspecmultiplememoizedhelpers[RSpec/MultipleMemoizedHelpers] +* xref:cops_rspec.adoc#rspecmultiplesubjects[RSpec/MultipleSubjects] +* xref:cops_rspec.adoc#rspecnamedsubject[RSpec/NamedSubject] +* xref:cops_rspec.adoc#rspecnestedgroups[RSpec/NestedGroups] +* xref:cops_rspec.adoc#rspecnoexpectationexample[RSpec/NoExpectationExample] +* xref:cops_rspec.adoc#rspecnottonot[RSpec/NotToNot] +* xref:cops_rspec.adoc#rspecoverwritingsetup[RSpec/OverwritingSetup] +* xref:cops_rspec.adoc#rspecpending[RSpec/Pending] +* xref:cops_rspec.adoc#rspecpendingwithoutreason[RSpec/PendingWithoutReason] +* xref:cops_rspec.adoc#rspecpredicatematcher[RSpec/PredicateMatcher] +* xref:cops_rspec.adoc#rspecreceivecounts[RSpec/ReceiveCounts] +* xref:cops_rspec.adoc#rspecreceivenever[RSpec/ReceiveNever] +* xref:cops_rspec.adoc#rspecrepeateddescription[RSpec/RepeatedDescription] +* xref:cops_rspec.adoc#rspecrepeatedexample[RSpec/RepeatedExample] +* xref:cops_rspec.adoc#rspecrepeatedexamplegroupbody[RSpec/RepeatedExampleGroupBody] +* xref:cops_rspec.adoc#rspecrepeatedexamplegroupdescription[RSpec/RepeatedExampleGroupDescription] +* xref:cops_rspec.adoc#rspecrepeatedincludeexample[RSpec/RepeatedIncludeExample] +* xref:cops_rspec.adoc#rspecreturnfromstub[RSpec/ReturnFromStub] +* xref:cops_rspec.adoc#rspecscatteredlet[RSpec/ScatteredLet] +* xref:cops_rspec.adoc#rspecscatteredsetup[RSpec/ScatteredSetup] +* xref:cops_rspec.adoc#rspecsharedcontext[RSpec/SharedContext] +* xref:cops_rspec.adoc#rspecsharedexamples[RSpec/SharedExamples] +* xref:cops_rspec.adoc#rspecsingleargumentmessagechain[RSpec/SingleArgumentMessageChain] +* xref:cops_rspec.adoc#rspecsortmetadata[RSpec/SortMetadata] +* xref:cops_rspec.adoc#rspecstubbedmock[RSpec/StubbedMock] +* xref:cops_rspec.adoc#rspecsubjectdeclaration[RSpec/SubjectDeclaration] +* xref:cops_rspec.adoc#rspecsubjectstub[RSpec/SubjectStub] +* xref:cops_rspec.adoc#rspecunspecifiedexception[RSpec/UnspecifiedException] +* xref:cops_rspec.adoc#rspecvariabledefinition[RSpec/VariableDefinition] +* xref:cops_rspec.adoc#rspecvariablename[RSpec/VariableName] +* xref:cops_rspec.adoc#rspecverifieddoublereference[RSpec/VerifiedDoubleReference] +* xref:cops_rspec.adoc#rspecverifieddoubles[RSpec/VerifiedDoubles] +* xref:cops_rspec.adoc#rspecvoidexpect[RSpec/VoidExpect] +* xref:cops_rspec.adoc#rspecyield[RSpec/Yield] + +=== Department xref:cops_rspec_capybara.adoc[RSpec/Capybara] + +* xref:cops_rspec_capybara.adoc#rspeccapybara/currentpathexpectation[RSpec/Capybara/CurrentPathExpectation] +* xref:cops_rspec_capybara.adoc#rspeccapybara/featuremethods[RSpec/Capybara/FeatureMethods] +* xref:cops_rspec_capybara.adoc#rspeccapybara/negationmatcher[RSpec/Capybara/NegationMatcher] +* xref:cops_rspec_capybara.adoc#rspeccapybara/specificactions[RSpec/Capybara/SpecificActions] +* xref:cops_rspec_capybara.adoc#rspeccapybara/specificfinders[RSpec/Capybara/SpecificFinders] +* xref:cops_rspec_capybara.adoc#rspeccapybara/specificmatcher[RSpec/Capybara/SpecificMatcher] +* xref:cops_rspec_capybara.adoc#rspeccapybara/visibilitymatcher[RSpec/Capybara/VisibilityMatcher] + +=== Department xref:cops_rspec_factorybot.adoc[RSpec/FactoryBot] + +* xref:cops_rspec_factorybot.adoc#rspecfactorybot/attributedefinedstatically[RSpec/FactoryBot/AttributeDefinedStatically] +* xref:cops_rspec_factorybot.adoc#rspecfactorybot/consistentparenthesesstyle[RSpec/FactoryBot/ConsistentParenthesesStyle] +* xref:cops_rspec_factorybot.adoc#rspecfactorybot/createlist[RSpec/FactoryBot/CreateList] +* xref:cops_rspec_factorybot.adoc#rspecfactorybot/factoryclassname[RSpec/FactoryBot/FactoryClassName] +* xref:cops_rspec_factorybot.adoc#rspecfactorybot/factorynamestyle[RSpec/FactoryBot/FactoryNameStyle] +* xref:cops_rspec_factorybot.adoc#rspecfactorybot/syntaxmethods[RSpec/FactoryBot/SyntaxMethods] + +=== Department xref:cops_rspec_rails.adoc[RSpec/Rails] + +* xref:cops_rspec_rails.adoc#rspecrails/avoidsetuphook[RSpec/Rails/AvoidSetupHook] +* xref:cops_rspec_rails.adoc#rspecrails/havehttpstatus[RSpec/Rails/HaveHttpStatus] +* xref:cops_rspec_rails.adoc#rspecrails/httpstatus[RSpec/Rails/HttpStatus] +* xref:cops_rspec_rails.adoc#rspecrails/inferredspectype[RSpec/Rails/InferredSpecType] // END_COP_LIST diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_capybara.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_capybara.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_capybara.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_capybara.adoc 1970-01-01 00:00:00.000000000 +0000 @@ -1,149 +0,0 @@ -= 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 diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_factorybot.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_factorybot.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_factorybot.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_factorybot.adoc 1970-01-01 00:00:00.000000000 +0000 @@ -1,126 +0,0 @@ -= 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 diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rails.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rails.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rails.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rails.adoc 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -= 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 diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -3,10 +3,13 @@ == RSpec/AlignLeftLetBrace |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Disabled | Yes +| Yes +| 1.16 +| - |=== Checks that left braces for adjacent single line lets are aligned. @@ -33,10 +36,13 @@ == RSpec/AlignRightLetBrace |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Disabled | Yes +| Yes +| 1.16 +| - |=== Checks that right braces for adjacent single line lets are aligned. @@ -63,10 +69,13 @@ == RSpec/AnyInstance |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.4 +| - |=== Check that instances are not being stubbed globally. @@ -95,15 +104,19 @@ === References +* https://rspec.rubystyle.guide/#any_instance_of * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance == RSpec/AroundBlock |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.11 +| - |=== Checks that around blocks actually run the test. @@ -140,10 +153,13 @@ == RSpec/Be |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.25 +| - |=== Check for expectations where `be` is used without argument. @@ -167,31 +183,80 @@ === References +* https://rspec.rubystyle.guide/#be-matcher * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be +== RSpec/BeEq + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| No +| Yes (Unsafe) +| 2.9.0 +| 2.16 +|=== + +Check for expectations where `be(...)` can replace `eq(...)`. + +The `be` matcher compares by identity while the `eq` matcher compares +using `==`. Booleans and nil can be compared by identity and therefore +the `be` matcher is preferable as it is a more strict test. + +=== Safety + +This cop is unsafe because it changes how values are compared. + +=== Examples + +[source,ruby] +---- +# bad +expect(foo).to eq(true) +expect(foo).to eq(false) +expect(foo).to eq(nil) + +# good +expect(foo).to be(true) +expect(foo).to be(false) +expect(foo).to be(nil) +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEq + == RSpec/BeEql |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled -| Yes +| No +| Yes (Unsafe) +| 1.7 +| 2.16 |=== -Check for expectations where `+be(...)+` can replace `+eql(...)+`. +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 +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. +=== Safety + +This cop is unsafe because it changes how values are compared. + === Examples [source,ruby] @@ -217,13 +282,73 @@ * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql +== RSpec/BeNil + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.9.0 +| 2.10.0 +|=== + +Ensures a consistent style is used when matching `nil`. + +You can either use the more specific `be_nil` matcher, or the more +generic `be` matcher with a `nil` argument. + +This cop can be configured using the `EnforcedStyle` option + +=== Examples + +==== `EnforcedStyle: be_nil` (default) + +[source,ruby] +---- +# bad +expect(foo).to be(nil) + +# good +expect(foo).to be_nil +---- + +==== `EnforcedStyle: be` + +[source,ruby] +---- +# bad +expect(foo).to be_nil + +# good +expect(foo).to be(nil) +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| EnforcedStyle +| `be_nil` +| `be`, `be_nil` +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeNil + == RSpec/BeforeAfterAll |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.12 +| - |=== Check that before/after(:all) isn't being used. @@ -263,15 +388,166 @@ === References +* https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll +== RSpec/ChangeByZero + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.11 +| 2.14 +|=== + +Prefer negated matchers over `to change.by(0)`. + +In the case of composite expectations, cop suggest using the +negation matchers of `RSpec::Matchers#change`. + +By default the cop does not support autocorrect of +compound expectations, but if you set the +negated matcher for `change`, e.g. `not_change` with +the `NegatedMatcher` option, the cop will perform the autocorrection. + +=== Examples + +==== NegatedMatcher: ~ (default) + +[source,ruby] +---- +# bad +expect { run }.to change(Foo, :bar).by(0) +expect { run }.to change { Foo.bar }.by(0) + +# bad - compound expectations (does not support autocorrection) +expect { run } + .to change(Foo, :bar).by(0) + .and change(Foo, :baz).by(0) +expect { run } + .to change { Foo.bar }.by(0) + .and change { Foo.baz }.by(0) + +# good +expect { run }.not_to change(Foo, :bar) +expect { run }.not_to change { Foo.bar } + +# good - compound expectations +define_negated_matcher :not_change, :change +expect { run } + .to not_change(Foo, :bar) + .and not_change(Foo, :baz) +expect { run } + .to not_change { Foo.bar } + .and not_change { Foo.baz } +---- + +==== NegatedMatcher: not_change + +[source,ruby] +---- +# bad (support autocorrection to good case) +expect { run } + .to change(Foo, :bar).by(0) + .and change(Foo, :baz).by(0) +expect { run } + .to change { Foo.bar }.by(0) + .and change { Foo.baz }.by(0) + +# good +define_negated_matcher :not_change, :change +expect { run } + .to not_change(Foo, :bar) + .and not_change(Foo, :baz) +expect { run } + .to not_change { Foo.bar } + .and not_change { Foo.baz } +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| NegatedMatcher +| `` +| +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ChangeByZero + +== RSpec/ClassCheck + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.13 +| - +|=== + +Enforces consistent use of `be_a` or `be_kind_of`. + +=== Examples + +==== EnforcedStyle: be_a (default) + +[source,ruby] +---- +# bad +expect(object).to be_kind_of(String) +expect(object).to be_a_kind_of(String) + +# good +expect(object).to be_a(String) +expect(object).to be_an(String) +---- + +==== EnforcedStyle: be_kind_of + +[source,ruby] +---- +# bad +expect(object).to be_a(String) +expect(object).to be_an(String) + +# good +expect(object).to be_kind_of(String) +expect(object).to be_a_kind_of(String) +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| EnforcedStyle +| `be_a` +| `be_a`, `be_kind_of` +|=== + +=== References + +* https://rubystyle.guide#is-a-vs-kind-of +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ClassCheck + == RSpec/ContextMethod |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.36 +| - |=== `context` should not be used for specifying methods. @@ -301,15 +577,19 @@ === References +* https://rspec.rubystyle.guide/#example-group-naming * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod == RSpec/ContextWording |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.20 +| 2.13 |=== Checks that `context` docstring starts with an allowed prefix. @@ -317,6 +597,10 @@ 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`. +They may consist of multiple words if desired. + +This cop can be customized allowed context description pattern +with `AllowedPatterns`. By default, there are no checking by pattern. === Examples @@ -348,6 +632,29 @@ end ---- +==== `AllowedPatterns` configuration + +[source,ruby] +---- +# .rubocop.yml +# RSpec/ContextWording: +# AllowedPatterns: +# - とき$ +---- + +[source,ruby] +---- +# bad +context '条件を満たす' do + # ... +end + +# good +context '条件を満たすとき' do + # ... +end +---- + === Configurable attributes |=== @@ -356,25 +663,49 @@ | Prefixes | `when`, `with`, `without` | Array + +| AllowedPatterns +| `[]` +| Array |=== === References +* https://rspec.rubystyle.guide/#context-descriptions * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording == RSpec/DescribeClass |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.0 +| 2.7 |=== -Check that the first argument to the top level describe is a constant. +Check that the first argument to the top-level describe is a constant. + +It can be configured to ignore strings when certain metadata is passed. + +Ignores Rails and Aruba `type` metadata by default. === Examples +==== `IgnoredMetadata` configuration + +[source,ruby] +---- +# .rubocop.yml +# RSpec/DescribeClass: +# IgnoredMetadata: +# type: +# - request +# - controller +---- + [source,ruby] ---- # bad @@ -394,6 +725,20 @@ end ---- +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| Exclude +| `+**/spec/features/**/*+`, `+**/spec/requests/**/*+`, `+**/spec/routing/**/*+`, `+**/spec/system/**/*+`, `+**/spec/views/**/*+` +| Array + +| IgnoredMetadata +| `{"type"=>["channel", "controller", "helper", "job", "mailer", "model", "request", "routing", "view", "feature", "system", "mailbox", "aruba", "task"]}` +| +|=== + === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass @@ -401,10 +746,13 @@ == RSpec/DescribeMethod |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.0 +| - |=== Checks that the second argument to `describe` specifies a method. @@ -432,10 +780,13 @@ == RSpec/DescribeSymbol |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.15 +| - |=== Avoid describing symbols. @@ -462,10 +813,13 @@ == RSpec/DescribedClass |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes (Unsafe) +| 1.0 +| 1.11 |=== Checks that tests use `described_class`. @@ -487,7 +841,7 @@ === Examples -==== `EnforcedStyle: described_class` +==== `EnforcedStyle: described_class` (default) [source,ruby] ---- @@ -554,10 +908,13 @@ == RSpec/DescribedClassModuleWrapping |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Disabled +| Yes | No +| 1.37 +| - |=== Avoid opening modules and defining specs within them. @@ -586,35 +943,38 @@ == RSpec/Dialect |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Disabled | Yes +| Yes +| 1.33 +| - |=== -This cop enforces custom RSpec dialects. +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 +- 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: + RSpec/Dialect: PreferredMethods: context: describe @@ -642,26 +1002,56 @@ | PreferredMethods | `{}` -| +| |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect +== RSpec/DuplicatedMetadata + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.16 +| - +|=== + +Avoid duplicated metadata. + +=== Examples + +[source,ruby] +---- +# bad +describe 'Something', :a, :a + +# good +describe 'Something', :a +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DuplicatedMetadata + == RSpec/EmptyExampleGroup |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled -| No +| Yes +| Yes (Unsafe) +| 1.7 +| 2.13 |=== Checks if an example group does not include any tests. -This cop is configurable using the `CustomIncludeMethods` option - === Examples ==== usage @@ -691,45 +1081,13 @@ 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 +# good 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 + pending 'will add tests later' end ---- -=== Configurable attributes - -|=== -| Name | Default value | Configurable values - -| CustomIncludeMethods -| `[]` -| Array -|=== - === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup @@ -737,10 +1095,13 @@ == RSpec/EmptyHook |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.39 +| - |=== Checks for empty before and after hooks. @@ -767,16 +1128,6 @@ 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 @@ -784,10 +1135,13 @@ == RSpec/EmptyLineAfterExample |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.36 +| - |=== Checks if there is an empty line after example blocks. @@ -847,15 +1201,19 @@ === References +* https://rspec.rubystyle.guide/#empty-lines-around-examples * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample == RSpec/EmptyLineAfterExampleGroup |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.27 +| - |=== Checks if there is an empty line after example group blocks. @@ -884,15 +1242,19 @@ === References +* https://rspec.rubystyle.guide/#empty-lines-between-describes * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExampleGroup == RSpec/EmptyLineAfterFinalLet |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.14 +| - |=== Checks if there is an empty line after the last let block. @@ -915,19 +1277,26 @@ === References +* https://rspec.rubystyle.guide/#empty-line-after-let * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterFinalLet == RSpec/EmptyLineAfterHook |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.27 +| 2.13 |=== Checks if there is an empty line after hook blocks. +`AllowConsecutiveOneLiners` configures whether adjacent +one-line definitions are considered an offense. + === Examples [source,ruby] @@ -945,11 +1314,27 @@ it { does_something } # good -before { do_something } +after { do_something } it { does_something } -# good +# fair - it's ok to have non-separated one-liners hooks +around { |test| test.run } +after { do_something } + +it { does_something } +---- + +==== with AllowConsecutiveOneLiners configuration + +[source,ruby] +---- +# rubocop.yml +# RSpec/EmptyLineAfterHook: +# AllowConsecutiveOneLiners: false + +# bad +around { |test| test.run } after { do_something } it { does_something } @@ -957,20 +1342,36 @@ # good around { |test| test.run } +after { do_something } + it { does_something } ---- +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| AllowConsecutiveOneLiners +| `true` +| Boolean +|=== + === References +* https://rspec.rubystyle.guide/#empty-line-after-let * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook == RSpec/EmptyLineAfterSubject |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.14 +| - |=== Checks if there is an empty line after subject block. @@ -991,23 +1392,31 @@ === References +* https://rspec.rubystyle.guide/#empty-line-after-let * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject == RSpec/ExampleLength |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.5 +| 2.3 |=== 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 +extracting out some behavior, e.g. with a `let` block, or a helper method. +You can set literals you want to fold with `CountAsOne`. +Available are: 'array', 'hash', and 'heredoc'. Each literal +will be counted as one line regardless of its actual size. + === Examples [source,ruby] @@ -1029,6 +1438,27 @@ end ---- +==== CountAsOne: ['array', 'heredoc'] + +[source,ruby] +---- +it do + array = [ # +1 + 1, + 2 + ] + + hash = { # +3 + key: 'value' + } + + msg = <<~HEREDOC # +1 + Heredoc + content. + HEREDOC +end # 5 points +---- + === Configurable attributes |=== @@ -1037,6 +1467,10 @@ | Max | `5` | Integer + +| CountAsOne +| `[]` +| Array |=== === References @@ -1046,10 +1480,13 @@ == RSpec/ExampleWithoutDescription |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.22 +| - |=== Checks for examples without a description. @@ -1065,7 +1502,7 @@ === Examples -==== `EnforcedStyle: always_allow` +==== `EnforcedStyle: always_allow` (default) [source,ruby] ---- @@ -1128,18 +1565,26 @@ == RSpec/ExampleWording |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.0 +| 2.13 |=== Checks for common mistakes in example descriptions. This cop will correct docstrings that begin with 'should' and 'it'. +This cop will also look for insufficient examples and call them out. The autocorrect is experimental - use with care! It can be configured -with CustomTransform (e.g. have \=> has) and IgnoredWords (e.g. only). +with CustomTransform (e.g. have => has) and IgnoredWords (e.g. only). + +Use the DisallowedExamples setting to prevent unclear or insufficient +descriptions. Please note that this config will not be treated as +case sensitive. === Examples @@ -1165,34 +1610,99 @@ end ---- +==== `DisallowedExamples: ['works']` (default) + +[source,ruby] +---- +# bad +it 'works' do +end + +# good +it 'marks the task as done' do +end +---- + === Configurable attributes |=== | Name | Default value | Configurable values | CustomTransform -| `+{"be"=>"is", "BE"=>"IS", "have"=>"has", "HAVE"=>"HAS"}+` -| +| `{"be"=>"is", "BE"=>"IS", "have"=>"has", "HAVE"=>"HAS"}` +| | IgnoredWords | `[]` | Array + +| DisallowedExamples +| `works` +| Array |=== === References +* https://rspec.rubystyle.guide/#should-in-example-docstrings * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording +== RSpec/ExcessiveDocstringSpacing + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.5 +| - +|=== + +Checks for excessive whitespace in example descriptions. + +=== Examples + +[source,ruby] +---- +# bad +it ' has excessive spacing ' do +end + +# good +it 'has excessive spacing' do +end +---- + +[source,ruby] +---- +# bad +context ' when a condition is met ' do +end + +# good +context 'when a condition is met' do +end +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExcessiveDocstringSpacing + == RSpec/ExpectActual |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.7 +| - |=== -Checks for `+expect(...)+` calls containing literal values. +Checks for `expect(...)` calls containing literal values. + +Autocorrection is performed when the expected is not a literal. === Examples @@ -1207,6 +1717,9 @@ expect(price).to eq(5) expect(pattern).to eq(/foo/) expect(name).to eq("John") + +# bad (not supported autocorrection) +expect(false).to eq(true) ---- === Configurable attributes @@ -1226,10 +1739,13 @@ == RSpec/ExpectChange |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes (Unsafe) +| 1.22 +| 2.5 |=== Checks for consistent style of change matcher. @@ -1241,31 +1757,31 @@ === Examples -==== `EnforcedStyle: block` +==== `EnforcedStyle: method_call` (default) [source,ruby] ---- # bad -expect { run }.to change(Foo, :bar) +expect { run }.to change { Foo.bar } +expect { run }.to change { foo.baz } # good -expect { run }.to change { Foo.bar } +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 } ---- -==== `EnforcedStyle: method_call` +==== `EnforcedStyle: block` [source,ruby] ---- # bad -expect { run }.to change { Foo.bar } -expect { run }.to change { foo.baz } +expect { run }.to change(Foo, :bar) # 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 } +expect { run }.to change { Foo.bar } ---- === Configurable attributes @@ -1285,10 +1801,13 @@ == RSpec/ExpectInHook |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.16 +| - |=== Do not use `expect` in hooks such as `before`. @@ -1320,13 +1839,16 @@ == RSpec/ExpectOutput |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.10 +| - |=== -Checks for opportunities to use `+expect { ... }.to output+`. +Checks for opportunities to use `expect { ... }.to output`. === Examples @@ -1349,10 +1871,13 @@ == RSpec/FilePath |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.2 +| 1.40 |=== Checks that spec file paths are consistent and well-formed. @@ -1366,7 +1891,7 @@ 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' ). +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 @@ -1425,9 +1950,13 @@ |=== | Name | Default value | Configurable values +| Include +| `+**/*_spec*rb*+`, `+**/spec/**/*+` +| Array + | CustomTransform -| `+{"RuboCop"=>"rubocop", "RSpec"=>"rspec"}+` -| +| `{"RuboCop"=>"rubocop", "RSpec"=>"rspec"}` +| | IgnoreMethods | `false` @@ -1445,14 +1974,19 @@ == RSpec/Focus |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled -| No +| Yes +| Yes +| 1.5 +| 2.1 |=== Checks if examples are focused. +This cop does not support autocorrection in some cases. + === Examples [source,ruby] @@ -1470,6 +2004,21 @@ # good describe MyClass do end + +# bad +fdescribe 'test' do; end + +# good +describe 'test' do; end + +# bad +fdescribe 'test' do; end + +# good +describe 'test' do; end + +# bad (does not support autocorrection) +focus 'test' do; end ---- === References @@ -1479,10 +2028,13 @@ == RSpec/HookArgument |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.7 +| - |=== Checks the arguments passed to `before`, `around`, and `after`. @@ -1494,7 +2046,7 @@ === Examples -==== when configuration is `EnforcedStyle: implicit` +==== `EnforcedStyle: implicit` (default) [source,ruby] ---- @@ -1514,7 +2066,7 @@ end ---- -==== when configuration is `EnforcedStyle: each` +==== `EnforcedStyle: each` [source,ruby] ---- @@ -1523,7 +2075,7 @@ # ... end -# good +# bad before do # ... end @@ -1534,7 +2086,7 @@ end ---- -==== when configuration is `EnforcedStyle: example` +==== `EnforcedStyle: example` [source,ruby] ---- @@ -1566,15 +2118,19 @@ === References +* https://rspec.rubystyle.guide/#redundant-beforeeach * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HookArgument == RSpec/HooksBeforeExamples |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.29 +| - |=== Checks for before/around/after hooks that come after an example. @@ -1583,8 +2139,7 @@ [source,ruby] ---- -# Bad - +# bad it 'checks what foo does' do expect(foo).to be end @@ -1592,7 +2147,7 @@ before { prepare } after { clean_up } -# Good +# good before { prepare } after { clean_up } @@ -1605,13 +2160,47 @@ * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples +== RSpec/IdenticalEqualityAssertion + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| No +| 2.4 +| - +|=== + +Checks for equality assertions with identical expressions on both sides. + +=== Examples + +[source,ruby] +---- +# bad +expect(foo.bar).to eq(foo.bar) +expect(foo.bar).to eql(foo.bar) + +# good +expect(foo.bar).to eq(2) +expect(foo.bar).to eql(2) +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IdenticalEqualityAssertion + == RSpec/ImplicitBlockExpectation |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.35 +| - |=== Check that implicit block expectation syntax is not used. @@ -1634,15 +2223,19 @@ === References +* https://rspec.rubystyle.guide/#implicit-block-expectations * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitBlockExpectation == RSpec/ImplicitExpect |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.8 +| - |=== Check that a consistent implicit expectation style is used. @@ -1652,7 +2245,7 @@ === Examples -==== `EnforcedStyle: is_expected` +==== `EnforcedStyle: is_expected` (default) [source,ruby] ---- @@ -1686,15 +2279,19 @@ === References +* https://rspec.rubystyle.guide/#use-expect * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitExpect == RSpec/ImplicitSubject |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.29 +| 2.13 |=== Checks for usage of implicit subject (`is_expected` / `should`). @@ -1703,7 +2300,7 @@ === Examples -==== `EnforcedStyle: single_line_only` +==== `EnforcedStyle: single_line_only` (default) [source,ruby] ---- @@ -1719,6 +2316,26 @@ end ---- +==== `EnforcedStyle: single_statement_only` + +[source,ruby] +---- +# bad +it do + foo = 1 + is_expected.to be_truthy +end + +# good +it do + foo = 1 + expect(subject).to be_truthy +end +it do + is_expected.to be_truthy +end +---- + ==== `EnforcedStyle: disallow` [source,ruby] @@ -1730,6 +2347,30 @@ it { expect(subject).to be_truthy } ---- +==== `EnforcedStyle: require_implicit` + +[source,ruby] +---- +# bad +it { expect(subject).to be_truthy } + +# good +it { is_expected.to be_truthy } + +# bad +it do + expect(subject).to be_truthy +end + +# good +it do + is_expected.to be_truthy +end + +# good +it { expect(named_subject).to be_truthy } +---- + === Configurable attributes |=== @@ -1737,7 +2378,7 @@ | EnforcedStyle | `single_line_only` -| `single_line_only`, `single_statement_only`, `disallow` +| `single_line_only`, `single_statement_only`, `disallow`, `require_implicit` |=== === References @@ -1747,10 +2388,13 @@ == RSpec/InstanceSpy |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.12 +| - |=== Checks for `instance_double` used with `have_received`. @@ -1779,10 +2423,13 @@ == RSpec/InstanceVariable |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.0 +| 1.7 |=== Checks for instance variable usage in specs. @@ -1847,51 +2494,26 @@ === References +* https://rspec.rubystyle.guide/#instance-variables * 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 by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.13 +| - |=== Checks that only one `it_behaves_like` style is used. === Examples -==== when configuration is `EnforcedStyle: it_behaves_like` +==== `EnforcedStyle: it_behaves_like` (default) [source,ruby] ---- @@ -1902,7 +2524,7 @@ it_behaves_like 'a foo' ---- -==== when configuration is `EnforcedStyle: it_should_behave_like` +==== `EnforcedStyle: it_should_behave_like` [source,ruby] ---- @@ -1930,10 +2552,13 @@ == RSpec/IteratedExpectation |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.14 +| - |=== Check that `all` matcher is used instead of iterating over an array. @@ -1960,10 +2585,13 @@ == RSpec/LeadingSubject |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.7 +| 1.14 |=== Enforce that subject is the first definition in the test. @@ -1973,41 +2601,45 @@ [source,ruby] ---- # bad - let(:params) { blah } - subject { described_class.new(params) } +let(:params) { blah } +subject { described_class.new(params) } - before { do_something } - 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 } +it { expect_something } +subject { described_class.new(params) } +it { expect_something_else } # good - subject { described_class.new(params) } - let(:params) { blah } +subject { described_class.new(params) } +let(:params) { blah } # good - subject { described_class.new(params) } - before { do_something } +subject { described_class.new(params) } +before { do_something } # good - subject { described_class.new(params) } - it { expect_something } - it { expect_something_else } +subject { described_class.new(params) } +it { expect_something } +it { expect_something_else } ---- === References +* https://rspec.rubystyle.guide/#leading-subject * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject == RSpec/LeakyConstantDeclaration |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.35 +| - |=== Checks that no class, module, or constant is declared. @@ -2017,7 +2649,7 @@ 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 +examples will be reopening it and modifying its behavior in unpredictable ways. Even worse when a class that exists in the codebase is reopened. @@ -2111,15 +2743,19 @@ === References +* https://rspec.rubystyle.guide/#declare-constants * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeakyConstantDeclaration == RSpec/LetBeforeExamples |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.16 +| 1.22 |=== Checks for `let` definitions that come after an example. @@ -2128,7 +2764,7 @@ [source,ruby] ---- -# Bad +# bad let(:foo) { bar } it 'checks what foo does' do @@ -2141,7 +2777,7 @@ expect(some).to be end -# Good +# good let(:foo) { bar } let(:some) { other } @@ -2161,10 +2797,13 @@ == RSpec/LetSetup |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.7 +| - |=== Checks unreferenced `let!` calls being used for test setup. @@ -2173,20 +2812,20 @@ [source,ruby] ---- -# Bad +# bad let!(:my_widget) { create(:widget) } it 'counts widgets' do expect(Widget.count).to eq(1) end -# Good +# good it 'counts widgets' do create(:widget) expect(Widget.count).to eq(1) end -# Good +# good before { create(:widget) } it 'counts widgets' do @@ -2201,10 +2840,13 @@ == RSpec/MessageChain |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.7 +| - |=== Check that chains of messages are not being stubbed. @@ -2216,7 +2858,7 @@ # bad allow(foo).to receive_message_chain(:bar, :baz).and_return(42) -# better +# good thing = Thing.new(baz: 42) allow(foo).to receive(:bar).and_return(thing) ---- @@ -2228,10 +2870,13 @@ == RSpec/MessageExpectation |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Disabled +| Yes | No +| 1.7 +| 1.8 |=== Checks for consistent message expectation style. @@ -2241,7 +2886,7 @@ === Examples -==== `EnforcedStyle: allow` +==== `EnforcedStyle: allow` (default) [source,ruby] ---- @@ -2280,10 +2925,13 @@ == RSpec/MessageSpies |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.9 +| - |=== Checks that message expectations are set using spies. @@ -2293,14 +2941,17 @@ === Examples -==== `EnforcedStyle: have_received` +==== `EnforcedStyle: have_received` (default) [source,ruby] ---- # bad expect(foo).to receive(:bar) +do_something # good +allow(foo).to receive(:bar) # or use instance_spy +do_something expect(foo).to have_received(:bar) ---- @@ -2309,10 +2960,13 @@ [source,ruby] ---- # bad +allow(foo).to receive(:bar) +do_something expect(foo).to have_received(:bar) # good expect(foo).to receive(:bar) +do_something ---- === Configurable attributes @@ -2332,10 +2986,13 @@ == RSpec/MissingExampleGroupArgument |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.28 +| - |=== Checks that the first argument to an example group is not empty. @@ -2366,13 +3023,16 @@ == RSpec/MultipleDescribes |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.0 +| - |=== -Checks for multiple top level describes. +Checks for multiple top-level example groups. Multiple descriptions for the same class or module should either be nested or separated into different test files. @@ -2403,10 +3063,13 @@ == RSpec/MultipleExpectations |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.7 +| 1.21 |=== Checks if examples contain too many `expect` calls. @@ -2438,16 +3101,42 @@ end ---- -==== configuration +==== `aggregate_failures: true` (default) [source,ruby] ---- -# .rubocop.yml -# RSpec/MultipleExpectations: -# Max: 2 +# good - the cop ignores when RSpec aggregates failures + describe UserCreator do + it 'builds a user', :aggregate_failures do + expect(user.name).to eq("John") + expect(user.age).to eq(22) + end + end +---- -# not flagged by rubocop -describe UserCreator do +==== `aggregate_failures: false` + +[source,ruby] +---- +# Detected as an offense + describe UserCreator do + it 'builds a user', aggregate_failures: false do + expect(user.name).to eq("John") + 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) @@ -2467,31 +3156,159 @@ === References +* https://rspec.rubystyle.guide/#expectation-per-example * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations +== RSpec/MultipleMemoizedHelpers + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| No +| 1.43 +| - +|=== + +Checks if example groups contain too many `let` and `subject` calls. + +This cop is configurable using the `Max` option and the `AllowSubject` +which will configure the cop to only register offenses on calls to +`let` and not calls to `subject`. + +=== Examples + +[source,ruby] +---- +# bad +describe MyClass do + let(:foo) { [] } + let(:bar) { [] } + let!(:baz) { [] } + let(:qux) { [] } + let(:quux) { [] } + let(:quuz) { {} } +end + +describe MyClass do + let(:foo) { [] } + let(:bar) { [] } + let!(:baz) { [] } + + context 'when stuff' do + let(:qux) { [] } + let(:quux) { [] } + let(:quuz) { {} } + end +end + +# good +describe MyClass do + let(:bar) { [] } + let!(:baz) { [] } + let(:qux) { [] } + let(:quux) { [] } + let(:quuz) { {} } +end + +describe MyClass do + context 'when stuff' do + let(:foo) { [] } + let(:bar) { [] } + let!(:booger) { [] } + end + + context 'when other stuff' do + let(:qux) { [] } + let(:quux) { [] } + let(:quuz) { {} } + end +end +---- + +==== when disabling AllowSubject configuration + +[source,ruby] +---- +# rubocop.yml +# RSpec/MultipleMemoizedHelpers: +# AllowSubject: false + +# bad - `subject` counts towards memoized helpers +describe MyClass do + subject { {} } + let(:foo) { [] } + let(:bar) { [] } + let!(:baz) { [] } + let(:qux) { [] } + let(:quux) { [] } +end +---- + +==== with Max configuration + +[source,ruby] +---- +# rubocop.yml +# RSpec/MultipleMemoizedHelpers: +# Max: 1 + +# bad +describe MyClass do + let(:foo) { [] } + let(:bar) { [] } +end +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| AllowSubject +| `true` +| Boolean + +| Max +| `5` +| Integer +|=== + +=== References + +* https://rspec.rubystyle.guide/#let-blocks +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers + == RSpec/MultipleSubjects |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.16 +| - |=== Checks if an example group defines `subject` multiple times. +This cop does not support autocorrection in some cases. 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 + - 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 @@ -2508,6 +3325,20 @@ let(:user) { User.new } subject(:post) { Post.new } end + +# bad (does not support autocorrection) +describe Foo do + subject!(:user) { User.new } + subject!(:post) { Post.new } +end + +# good +describe Foo do + before do + User.new + Post.new + end +end ---- === References @@ -2517,27 +3348,32 @@ == RSpec/NamedSubject |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.5.3 +| 2.15 |=== Checks for explicitly referenced test subjects. -RSpec lets you declare an "implicit subject" using `+subject { ... }+` +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 +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 +This cop can be configured in your configuration using `EnforcedStyle`, +and `IgnoreSharedExamples` which will not report offenses for implicit subjects in shared example groups. === Examples +==== `EnforcedStyle: always` (default) + [source,ruby] ---- # bad @@ -2550,7 +3386,7 @@ end # good -RSpec.describe Foo do +RSpec.describe User do subject(:user) { described_class.new } it 'is valid' do @@ -2559,18 +3395,61 @@ end # also good -RSpec.describe Foo do +RSpec.describe User do subject(:user) { described_class.new } it { is_expected.to be_valid } end ---- +==== `EnforcedStyle: named_only` + +[source,ruby] +---- +# bad +RSpec.describe User do + subject(:user) { described_class.new } + + it 'is valid' do + expect(subject.valid?).to be(true) + end +end + +# good +RSpec.describe User do + subject(:user) { described_class.new } + + it 'is valid' do + expect(user.valid?).to be(true) + end +end + +# also good +RSpec.describe User do + subject { described_class.new } + + it { is_expected.to be_valid } +end + +# acceptable +RSpec.describe User do + subject { described_class.new } + + it 'is valid' do + expect(subject.valid?).to be(true) + end +end +---- + === Configurable attributes |=== | Name | Default value | Configurable values +| EnforcedStyle +| `always` +| `always`, `named_only` + | IgnoreSharedExamples | `true` | Boolean @@ -2578,21 +3457,25 @@ === References +* https://rspec.rubystyle.guide/#use-subject * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject == RSpec/NestedGroups |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.7 +| 2.13 |=== Checks for nested example groups. This cop is configurable using the `Max` option -and supports `--auto-gen-config +and supports `--auto-gen-config`. === Examples @@ -2625,7 +3508,7 @@ end end -# better +# good context 'using some feature as an admin' do let(:some) { :various } let(:feature) { :setup } @@ -2643,36 +3526,55 @@ end ---- -==== configuration +==== `Max: 3` (default) [source,ruby] ---- -# .rubocop.yml -# RSpec/NestedGroups: -# Max: 2 +# bad +describe Foo do + context 'foo' do + context 'bar' do + context 'baz' do # flagged by rubocop + end + end + end +end +---- -context 'when using some feature' do - let(:some) { :various } - let(:feature) { :setup } +==== `Max: 2` - context 'when user is signed in' do - let(:user) do - UserCreate.call(user_attributes) +[source,ruby] +---- +# bad +describe Foo do + context 'foo' do + context 'bar' do # flagged by rubocop + context 'baz' do # flagged by rubocop + end end + end +end +---- - let(:user_attributes) do - { - name: 'John', - age: 22, - role: role - } +==== `AllowedGroups: [] (default)` + +[source,ruby] +---- +describe Foo do # <-- nested groups 1 + context 'foo' do # <-- nested groups 2 + context 'bar' do # <-- nested groups 3 end + end +end +---- - context 'when user is an admin' do # flagged by rubocop - let(:role) { 'admin' } +==== `AllowedGroups: [path]` - it 'blah blah' - it 'yada yada' +[source,ruby] +---- +describe Foo do # <-- nested groups 1 + path '/foo' do # <-- nested groups 1 (not counted) + context 'bar' do # <-- nested groups 2 end end end @@ -2686,25 +3588,121 @@ | Max | `3` | Integer + +| AllowedGroups +| `[]` +| Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups +== RSpec/NoExpectationExample + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| No +| No +| 2.13 +| 2.14 +|=== + +Checks if an example contains any expectation. + +All RSpec's example and expectation methods are covered by default. +If you are using your own custom methods, +add the following configuration: + + RSpec: + Language: + Examples: + Regular: + - custom_it + Expectations: + - custom_expect + +This cop can be customized with an allowed expectation methods pattern +with an `AllowedPatterns` option. ^expect_ and ^assert_ are allowed +by default. + +=== Examples + +[source,ruby] +---- +# bad +it do + a? +end + +# good +it do + expect(a?).to be(true) +end +---- + +==== `AllowedPatterns` configuration + +[source,ruby] +---- +# .rubocop.yml +# RSpec/NoExpectationExample: +# AllowedPatterns: +# - ^expect_ +# - ^assert_ +---- + +[source,ruby] +---- +# bad +it do + not_expect_something +end + +# good +it do + expect_something +end + +it do + assert_something +end +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| AllowedPatterns +| `^expect_`, `^assert_` +| Array +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NoExpectationExample + == RSpec/NotToNot |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.4 +| - |=== Checks for consistent method usage for negating expectations. === Examples +==== `EnforcedStyle: not_to` (default) + [source,ruby] ---- # bad @@ -2718,6 +3716,21 @@ end ---- +==== `EnforcedStyle: to_not` + +[source,ruby] +---- +# bad +it '...' do + expect(false).not_to be_true +end + +# good +it '...' do + expect(false).to_not be_true +end +---- + === Configurable attributes |=== @@ -2735,10 +3748,13 @@ == RSpec/OverwritingSetup |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.14 +| - |=== Checks if there is a let/subject that overwrites an existing one. @@ -2771,10 +3787,13 @@ == RSpec/Pending |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Disabled +| Yes | No +| 1.25 +| - |=== Checks for any pending or skipped examples. @@ -2806,21 +3825,98 @@ end # good -describe MyClass do +describe MyClass do +end +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending + +== RSpec/PendingWithoutReason + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| No +| 2.16 +| - +|=== + +Checks for pending or skipped examples without reason. + +=== Examples + +[source,ruby] +---- +# bad +pending 'does something' do +end + +# bad +it 'does something', :pending do +end + +# bad +it 'does something' do + pending +end + +# bad +xdescribe 'something' do +end + +# bad +skip 'does something' do +end + +# bad +it 'does something', :skip do +end + +# bad +it 'does something' do + skip +end + +# bad +it 'does something' + +# good +it 'does something' do + pending 'reason' +end + +# good +it 'does something' do + skip 'reason' +end + +# good +it 'does something', pending: 'reason' do +end + +# good +it 'does something', skip: 'reason' do end ---- === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PendingWithoutReason == RSpec/PredicateMatcher |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes (Unsafe) +| 1.16 +| - |=== Prefer using predicate matcher over using predicate method directly. @@ -2842,7 +3938,7 @@ expect(foo).to be_something # also good - It checks "true" strictly. -expect(foo).to be(true) +expect(foo.something?).to be(true) ---- ==== Strict: false, EnforcedStyle: inflected @@ -2851,7 +3947,7 @@ ---- # bad expect(foo.something?).to be_truthy -expect(foo).to be(true) +expect(foo.something?).to be(true) # good expect(foo).to be_something @@ -2899,15 +3995,19 @@ === References +* https://rspec.rubystyle.guide/#predicate-matchers * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher == RSpec/ReceiveCounts |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.26 +| - |=== Check for `once` and `twice` receive counts matchers usage. @@ -2940,13 +4040,16 @@ == RSpec/ReceiveNever |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.28 +| - |=== -Prefer `+not_to receive(...)+` over `+receive(...).never+`. +Prefer `not_to receive(...)` over `receive(...).never`. === Examples @@ -2966,10 +4069,13 @@ == RSpec/RepeatedDescription |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.9 +| - |=== Check for repeated description strings in example groups. @@ -3019,10 +4125,13 @@ == RSpec/RepeatedExample |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.10 +| - |=== Check for repeated examples within example groups. @@ -3047,10 +4156,13 @@ == RSpec/RepeatedExampleGroupBody |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.38 +| - |=== Check for repeated describe and context block body. @@ -3085,6 +4197,15 @@ context 'when case y' do it { cool_predicate } end + +# good +context Array do + it { is_expected.to respond_to :each } +end + +context Hash do + it { is_expected.to respond_to :each } +end ---- === References @@ -3094,10 +4215,13 @@ == RSpec/RepeatedExampleGroupDescription |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.38 +| - |=== Check for repeated example group descriptions. @@ -3147,13 +4271,78 @@ * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription +== RSpec/RepeatedIncludeExample + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| No +| 1.44 +| - +|=== + +Check for repeated include of shared examples. + +=== Examples + +[source,ruby] +---- +# bad +describe 'foo' do + include_examples 'cool stuff' + include_examples 'cool stuff' +end + +# bad +describe 'foo' do + it_behaves_like 'a cool', 'thing' + it_behaves_like 'a cool', 'thing' +end + +# bad +context 'foo' do + it_should_behave_like 'a duck' + it_should_behave_like 'a duck' +end + +# good +describe 'foo' do + include_examples 'cool stuff' +end + +describe 'bar' do + include_examples 'cool stuff' +end + +# good +describe 'foo' do + it_behaves_like 'a cool', 'thing' + it_behaves_like 'a cool', 'person' +end + +# good +context 'foo' do + it_should_behave_like 'a duck' + it_should_behave_like 'a goose' +end +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedIncludeExample + == RSpec/ReturnFromStub |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.16 +| 1.22 |=== Checks for consistent style of stub's return setting. @@ -3166,34 +4355,34 @@ === Examples -==== `EnforcedStyle: block` +==== `EnforcedStyle: and_return` (default) [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" } + +# 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).and_return(bar.baz) +allow(Foo).to receive(:bar) { bar.baz } ---- -==== `EnforcedStyle: and_return` +==== `EnforcedStyle: block` [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") + +# 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) { bar.baz } +allow(Foo).to receive(:bar).and_return(bar.baz) ---- === Configurable attributes @@ -3213,10 +4402,13 @@ == RSpec/ScatteredLet |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.14 +| 1.39 |=== Checks for let scattered across the example group. @@ -3246,16 +4438,6 @@ end ---- -=== Configurable attributes - -|=== -| Name | Default value | Configurable values - -| VersionChanged -| `1.39` -| String -|=== - === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet @@ -3263,10 +4445,13 @@ == RSpec/ScatteredSetup |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.10 +| - |=== Checks for setup scattered across multiple hooks in an example group. @@ -3299,10 +4484,13 @@ == RSpec/SharedContext |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.13 +| - |=== Checks for proper shared_context and shared_examples usage. @@ -3365,10 +4553,13 @@ == RSpec/SharedExamples |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.25 +| - |=== Enforces use of string to titleize shared examples. @@ -3399,10 +4590,13 @@ == RSpec/SingleArgumentMessageChain |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.9 +| 1.10 |=== Checks that chains of messages contain more than one element. @@ -3426,42 +4620,175 @@ * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain +== RSpec/SortMetadata + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.14 +| - +|=== + +Sort RSpec metadata alphabetically. + +=== Examples + +[source,ruby] +---- +# bad +describe 'Something', :b, :a +context 'Something', foo: 'bar', baz: true +it 'works', :b, :a, foo: 'bar', baz: true + +# good +describe 'Something', :a, :b +context 'Something', baz: true, foo: 'bar' +it 'works', :a, :b, baz: true, foo: 'bar' +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SortMetadata + +== RSpec/StubbedMock + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| No +| 1.44 +| - +|=== + +Checks that message expectations do not have a configured response. + +=== Examples + +[source,ruby] +---- +# bad +expect(foo).to receive(:bar).with(42).and_return("hello world") + +# good (without spies) +allow(foo).to receive(:bar).with(42).and_return("hello world") +expect(foo).to receive(:bar).with(42) +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StubbedMock + +== RSpec/SubjectDeclaration + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| No +| 2.5 +| - +|=== + +Ensure that subject is defined using subject helper. + +=== Examples + +[source,ruby] +---- +# bad +let(:subject) { foo } +let!(:subject) { foo } +subject(:subject) { foo } +subject!(:subject) { foo } + +# bad +block = -> {} +let(:subject, &block) + +# good +subject(:test_subject) { foo } +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectDeclaration + == RSpec/SubjectStub |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.7 +| 2.8 |=== Checks for stubbed test subjects. +Checks nested subject stubs for innermost subject definition +when subject is also defined in parent example groups. + === Examples [source,ruby] ---- # bad -describe Foo do - subject(:bar) { baz } +describe Article do + subject(:article) { Article.new } - before do - allow(bar).to receive(:qux?).and_return(true) + it 'indicates that the author is unknown' do + allow(article).to receive(:author).and_return(nil) + expect(article.description).to include('by an unknown author') + end +end + +# bad +describe Article do + subject(:foo) { Article.new } + + context 'nested subject' do + subject(:article) { Article.new } + + it 'indicates that the author is unknown' do + allow(article).to receive(:author).and_return(nil) + expect(article.description).to include('by an unknown author') + end + end +end + +# good +describe Article do + subject(:article) { Article.new(author: nil) } + + it 'indicates that the author is unknown' do + expect(article.description).to include('by an unknown author') end end ---- === References +* https://rspec.rubystyle.guide/#dont-stub-subject * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectStub == RSpec/UnspecifiedException |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.30 +| - |=== Checks for a specified error in checking raised errors. @@ -3502,10 +4829,13 @@ == RSpec/VariableDefinition |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled -| No +| Yes +| Yes +| 1.40 +| - |=== Checks that memoized helpers names are symbols or strings. @@ -3517,12 +4847,12 @@ [source,ruby] ---- # bad -let('user_name') { 'Adam' } subject('user') { create_user } +let('user_name') { 'Adam' } # good -let(:user_name) { 'Adam' } subject(:user) { create_user } +let(:user_name) { 'Adam' } ---- ==== EnforcedStyle: strings @@ -3530,12 +4860,12 @@ [source,ruby] ---- # bad -let(:user_name) { 'Adam' } subject(:user) { create_user } +let(:user_name) { 'Adam' } # good -let('user_name') { 'Adam' } subject('user') { create_user } +let('user_name') { 'Adam' } ---- === Configurable attributes @@ -3546,10 +4876,6 @@ | EnforcedStyle | `symbols` | `symbols`, `strings` - -| VersionAdded -| `1.40` -| String |=== === References @@ -3559,14 +4885,20 @@ == RSpec/VariableName |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.40 +| 2.13 |=== Checks that memoized helper names use the configured style. +Variables can be excluded from checking using the `AllowedPatterns` +option. + === Examples ==== EnforcedStyle: snake_case (default) @@ -3574,12 +4906,12 @@ [source,ruby] ---- # bad -let(:userName) { 'Adam' } -subject(:userName) { 'Adam' } +subject(:userName1) { 'Adam' } +let(:userName2) { 'Adam' } # good -let(:user_name) { 'Adam' } -subject(:user_name) { 'Adam' } +subject(:user_name_1) { 'Adam' } +let(:user_name_2) { 'Adam' } ---- ==== EnforcedStyle: camelCase @@ -3587,12 +4919,30 @@ [source,ruby] ---- # bad -let(:user_name) { 'Adam' } -subject(:user_name) { 'Adam' } +subject(:user_name_1) { 'Adam' } +let(:user_name_2) { 'Adam' } # good -let(:userName) { 'Adam' } -subject(:userName) { 'Adam' } +subject(:userName1) { 'Adam' } +let(:userName2) { 'Adam' } +---- + +==== AllowedPatterns configuration + +[source,ruby] +---- +# rubocop.yml +# RSpec/VariableName: +# EnforcedStyle: snake_case +# AllowedPatterns: +# - ^userFood +---- + +[source,ruby] +---- +# okay because it matches the `^userFood` regex in `AllowedPatterns` +subject(:userFood_1) { 'spaghetti' } +let(:userFood_2) { 'fettuccine' } ---- === Configurable attributes @@ -3604,22 +4954,100 @@ | `snake_case` | `snake_case`, `camelCase` -| VersionAdded -| `1.40` -| String +| AllowedPatterns +| `[]` +| Array |=== === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName +== RSpec/VerifiedDoubleReference + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes (Unsafe) +| 2.10.0 +| 2.12 +|=== + +Checks for consistent verified double reference style. + +Only investigates references that are one of the supported styles. + +This cop can be configured in your configuration using the +`EnforcedStyle` option and supports `--auto-gen-config`. + +=== Examples + +==== `EnforcedStyle: constant` (default) + +[source,ruby] +---- +# bad +let(:foo) do + instance_double('ClassName', method_name: 'returned_value') +end + +# good +let(:foo) do + instance_double(ClassName, method_name: 'returned_value') +end +---- + +==== `EnforcedStyle: string` + +[source,ruby] +---- +# bad +let(:foo) do + instance_double(ClassName, method_name: 'returned_value') +end + +# good +let(:foo) do + instance_double('ClassName', method_name: 'returned_value') +end +---- + +==== Reference is not in the supported style list. No enforcement + +[source,ruby] +---- +# good +let(:foo) do + instance_double(@klass, method_name: 'returned_value') +end +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| EnforcedStyle +| `constant` +| `constant`, `string` +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubleReference + == RSpec/VerifiedDoubles |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.2.1 +| 1.5 |=== Prefer using verifying doubles over normal doubles. @@ -3660,18 +5088,22 @@ === References +* https://rspec.rubystyle.guide/#doubles * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles == RSpec/VoidExpect |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled +| Yes | No +| 1.16 +| - |=== -This cop checks void `expect()`. +Checks void `expect()`. === Examples @@ -3691,13 +5123,16 @@ == RSpec/Yield |=== -| Enabled by default | Supports autocorrection +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed | Enabled | Yes +| Yes +| 1.32 +| - |=== -This cop checks for calling a block within a stub. +Checks for calling a block within a stub. === Examples @@ -3707,7 +5142,7 @@ allow(foo).to receive(:bar) { |&block| block.call(1) } # good -expect(foo).to be(:bar).and_yield(1) +expect(foo).to receive(:bar).and_yield(1) ---- === References diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec_capybara.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec_capybara.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec_capybara.adoc 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec_capybara.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,318 @@ += RSpec/Capybara + +== RSpec/Capybara/CurrentPathExpectation + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| Yes +| 1.18 +| 2.0 +|=== + +Checks that no expectations are set on Capybara's `current_path`. + +The +https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method[`have_current_path` matcher] +should be used on `page` to set expectations on Capybara's +current path, since it uses +https://github.com/teamcapybara/capybara/blob/master/README.md#asynchronous-javascript-ajax-and-friends[Capybara's waiting functionality] +which ensures that preceding actions (like `click_link`) have +completed. + +This cop does not support autocorrection in some cases. + +=== Examples + +[source,ruby] +---- +# bad +expect(current_path).to eq('/callback') + +# good +expect(page).to have_current_path('/callback') + +# bad (does not support autocorrection) +expect(page.current_path).to match(variable) + +# good +expect(page).to have_current_path('/callback') +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/CurrentPathExpectation + +== RSpec/Capybara/FeatureMethods + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| Yes +| 1.17 +| 2.0 +|=== + +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 + +== RSpec/Capybara/NegationMatcher + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.14 +| - +|=== + +Enforces use of `have_no_*` or `not_to` for negated expectations. + +=== Examples + +==== EnforcedStyle: not_to (default) + +[source,ruby] +---- +# bad +expect(page).to have_no_selector +expect(page).to have_no_css('a') + +# good +expect(page).not_to have_selector +expect(page).not_to have_css('a') +---- + +==== EnforcedStyle: have_no + +[source,ruby] +---- +# bad +expect(page).not_to have_selector +expect(page).not_to have_css('a') + +# good +expect(page).to have_no_selector +expect(page).to have_no_css('a') +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| EnforcedStyle +| `not_to` +| `have_no`, `not_to` +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/NegationMatcher + +== RSpec/Capybara/SpecificActions + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| No +| 2.14 +| - +|=== + +Checks for there is a more specific actions offered by Capybara. + +=== Examples + +[source,ruby] +---- +# bad +find('a').click +find('button.cls').click +find('a', exact_text: 'foo').click +find('div button').click + +# good +click_link +click_button(class: 'cls') +click_link(exact_text: 'foo') +find('div').click_button +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificActions + +== RSpec/Capybara/SpecificFinders + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.13 +| - +|=== + +Checks if there is a more specific finder offered by Capybara. + +=== Examples + +[source,ruby] +---- +# bad +find('#some-id') +find('[visible][id=some-id]') + +# good +find_by_id('some-id') +find_by_id('some-id', visible: true) +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificFinders + +== RSpec/Capybara/SpecificMatcher + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| No +| 2.12 +| - +|=== + +Checks for there is a more specific matcher offered by Capybara. + +=== Examples + +[source,ruby] +---- +# bad +expect(page).to have_selector('button') +expect(page).to have_no_selector('button.cls') +expect(page).to have_css('button') +expect(page).to have_no_css('a.cls', href: 'http://example.com') +expect(page).to have_css('table.cls') +expect(page).to have_css('select') +expect(page).to have_css('input', exact_text: 'foo') + +# good +expect(page).to have_button +expect(page).to have_no_button(class: 'cls') +expect(page).to have_button +expect(page).to have_no_link('foo', class: 'cls', href: 'http://example.com') +expect(page).to have_table(class: 'cls') +expect(page).to have_select +expect(page).to have_field('foo') +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificMatcher + +== RSpec/Capybara/VisibilityMatcher + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| No +| 1.39 +| 2.0 +|=== + +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`. +Read more in +https://www.rubydoc.info/gems/capybara/Capybara%2FNode%2FFinders:all[the documentation]. + +=== 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) +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/VisibilityMatcher diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec_factorybot.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec_factorybot.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec_factorybot.adoc 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec_factorybot.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,355 @@ += RSpec/FactoryBot + +== RSpec/FactoryBot/AttributeDefinedStatically + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| Yes +| 1.28 +| 2.0 +|=== + +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 } +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| Include +| `spec/factories.rb`, `+spec/factories/**/*.rb+`, `+features/support/factories/**/*.rb+` +| Array +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/AttributeDefinedStatically + +== RSpec/FactoryBot/ConsistentParenthesesStyle + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.14 +| - +|=== + +Use a consistent style for parentheses in factory bot calls. + +=== Examples + +[source,ruby] +---- +# bad +create :user +build(:user) +create(:login) +create :login +---- + +==== `EnforcedStyle: require_parentheses` (default) + +[source,ruby] +---- +# good +create(:user) +create(:user) +create(:login) +build(:login) +---- + +==== `EnforcedStyle: omit_parentheses` + +[source,ruby] +---- +# good +create :user +build :user +create :login +create :login + +# also good +# when method name and first argument are not on same line +create( + :user +) +build( + :user, + name: 'foo' +) +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| EnforcedStyle +| `require_parentheses` +| `require_parentheses`, `omit_parentheses` +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/ConsistentParenthesesStyle + +== RSpec/FactoryBot/CreateList + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| Yes +| 1.25 +| 2.0 +|=== + +Checks for create_list usage. + +This cop can be configured using the `EnforcedStyle` option + +=== Examples + +==== `EnforcedStyle: create_list` (default) + +[source,ruby] +---- +# bad +3.times { create :user } + +# good +create_list :user, 3 + +# bad +3.times { create :user, age: 18 } + +# good - index is used to alter the created models attributes +3.times { |n| create :user, age: n } + +# good - contains a method call, may return different values +3.times { create :user, age: rand } +---- + +==== `EnforcedStyle: n_times` + +[source,ruby] +---- +# bad +create_list :user, 3 + +# good +3.times { create :user } +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| Include +| `+**/*_spec.rb+`, `+**/spec/**/*+`, `spec/factories.rb`, `+spec/factories/**/*.rb+`, `+features/support/factories/**/*.rb+` +| Array + +| EnforcedStyle +| `create_list` +| `create_list`, `n_times` +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList + +== RSpec/FactoryBot/FactoryClassName + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| Yes +| 1.37 +| 2.0 +|=== + +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 +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| Include +| `spec/factories.rb`, `+spec/factories/**/*.rb+`, `+features/support/factories/**/*.rb+` +| Array +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName + +== RSpec/FactoryBot/FactoryNameStyle + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.16 +| - +|=== + +Checks for name style for argument of FactoryBot::Syntax::Methods. + +=== Examples + +==== EnforcedStyle: symbol (default) + +[source,ruby] +---- +# bad +create('user') +build "user", username: "NAME" + +# good +create(:user) +build :user, username: "NAME" +---- + +==== EnforcedStyle: string + +[source,ruby] +---- +# bad +create(:user) +build :user, username: "NAME" + +# good +create('user') +build "user", username: "NAME" +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| EnforcedStyle +| `symbol` +| `symbol`, `string` +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryNameStyle + +== RSpec/FactoryBot/SyntaxMethods + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes (Unsafe) +| 2.7 +| - +|=== + +Use shorthands from `FactoryBot::Syntax::Methods` in your specs. + +=== Safety + +The autocorrection is marked as unsafe because the cop +cannot verify whether you already include +`FactoryBot::Syntax::Methods` in your test suite. + +If you're using Rails, add the following configuration to +`spec/support/factory_bot.rb` and be sure to require that file in +`rails_helper.rb`: + +[source,ruby] +---- +RSpec.configure do |config| + config.include FactoryBot::Syntax::Methods +end +---- + +If you're not using Rails: + +[source,ruby] +---- +RSpec.configure do |config| + config.include FactoryBot::Syntax::Methods + + config.before(:suite) do + FactoryBot.find_definitions + end +end +---- + +=== Examples + +[source,ruby] +---- +# bad +FactoryBot.create(:bar) +FactoryBot.build(:bar) +FactoryBot.attributes_for(:bar) + +# good +create(:bar) +build(:bar) +attributes_for(:bar) +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/SyntaxMethods diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec_rails.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec_rails.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/cops_rspec_rails.adoc 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/cops_rspec_rails.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,206 @@ += RSpec/Rails + +== RSpec/Rails/AvoidSetupHook + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes +| 2.4 +| - +|=== + +Checks that tests use RSpec `before` hook over Rails `setup` method. + +=== Examples + +[source,ruby] +---- +# bad +setup do + allow(foo).to receive(:bar) +end + +# good +before do + allow(foo).to receive(:bar) +end +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/AvoidSetupHook + +== RSpec/Rails/HaveHttpStatus + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Yes (Unsafe) +| 2.12 +| - +|=== + +Checks that tests use `have_http_status` instead of equality matchers. + +=== Examples + +[source,ruby] +---- +# bad +expect(response.status).to be(200) + +# good +expect(response).to have_http_status(200) +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HaveHttpStatus + +== RSpec/Rails/HttpStatus + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Enabled +| Yes +| Yes +| 1.23 +| 2.0 +|=== + +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 + +== RSpec/Rails/InferredSpecType + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| No +| Yes (Unsafe) +| 2.14 +| - +|=== + +Identifies redundant spec type. + +After setting up rspec-rails, you will have enabled +`config.infer_spec_type_from_file_location!` by default in +spec/rails_helper.rb. This cop works in conjunction with this config. +If you disable this config, disable this cop as well. + +=== Safety + +This cop is marked as unsafe because +`config.infer_spec_type_from_file_location!` may not be enabled. + +=== Examples + +[source,ruby] +---- +# bad +# spec/models/user_spec.rb +RSpec.describe User, type: :model do +end + +# good +# spec/models/user_spec.rb +RSpec.describe User do +end + +# good +# spec/models/user_spec.rb +RSpec.describe User, type: :common do +end +---- + +==== `Inferences` configuration + +[source,ruby] +---- +# .rubocop.yml +# RSpec/Rails/InferredSpecType: +# Inferences: +# services: service + +# bad +# spec/services/user_spec.rb +RSpec.describe User, type: :service do +end + +# good +# spec/services/user_spec.rb +RSpec.describe User do +end + +# good +# spec/services/user_spec.rb +RSpec.describe User, type: :common do +end +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| Inferences +| `{"channels"=>"channel", "controllers"=>"controller", "features"=>"feature", "generator"=>"generator", "helpers"=>"helper", "jobs"=>"job", "mailboxes"=>"mailbox", "mailers"=>"mailer", "models"=>"model", "requests"=>"request", "integration"=>"request", "api"=>"request", "routing"=>"routing", "system"=>"system", "views"=>"view"}` +| +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/InferredSpecType diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/development.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/development.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/development.adoc 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/development.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,32 @@ += Development + +This page describes considerations when developing RSpec-specific cops. It is intended to be a complement to the general https://docs.rubocop.org/rubocop/development.html[RuboCop development documentation]. + +== Base class + +The `RuboCop::Cop::RSpec::Base` class includes convenient https://docs.rubocop.org/rubocop-ast/node_pattern.html[node pattern DSL] matchers that will automatically account for any xref:usage.adoc#rspec-dsl-configuration[custom RSpec DSL configuration]. + +For example, if the project defines https://github.com/test-prof/test-prof/blob/master/docs/recipes/let_it_be.md[`let_it_be`] as a `Helper`, then all cops will find `let_it_be` when using the `let?` matcher. + +== Writing specs + +When working on RSpec-specific cops, ensure that the https://github.com/rubocop/rubocop-rspec/blob/master/config/default.yml[default language config] is loaded for all RSpec specs. For example: + +[source,ruby] +---- +require 'rubocop/rspec/shared_contexts/default_rspec_language_config_context' + +RSpec.config do |config| + # Set metadata on all cop specs + config.define_derived_metadata(file_path: %r{/spec/rubocop/cop/}) do |meta| + meta[:type] = :cop_spec + end + + # Include RuboCop's config shared context for all cop specs + config.define_derived_metadata(type: :cop_spec) do |meta| + meta[:config] = true + end + + config.include_context 'with default RSpec/Language config', :config +end +---- diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/index.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/index.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/index.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/index.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -1,7 +1,13 @@ = RuboCop RSpec RSpec-specific analysis for your projects, as an extension to -https://github.com/rubocop-hq/rubocop[RuboCop]. +https://github.com/rubocop/rubocop[RuboCop]. + +RuboCop RSpec follows the https://docs.rubocop.org/rubocop/versioning.html[RuboCop versioning guide]. +In a nutshell, between major versions new cops are introduced in a special `pending` status. +That means that they won’t be run unless explicitly told otherwise. +RuboCop will warn on start that certain cops are neither explicitly enabled and disabled. +On a major version release, all `pending` cops are enabled. == Project Goals diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/third_party_rspec_syntax_extensions.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/third_party_rspec_syntax_extensions.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/third_party_rspec_syntax_extensions.adoc 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/third_party_rspec_syntax_extensions.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,28 @@ += RSpec syntax extensions in third-party gems + +Some gems, e.g. https://github.com/CanCanCommunity/cancancan[cancancan], https://github.com/palkan/action_policy[action_policy] and https://github.com/varvet/pundit[pundit] provide their own extensions and aliases to RSpec syntax. Also, RSpec extensions like https://github.com/palkan/test-prof[test-prof], https://github.com/rspec/rspec-its[rspec-its] and https://github.com/zverok/saharspec#its-addons[saharspec] do. + +By default, RuboCop RSpec is not aware of those syntax extensions, and does not intend to gather all of them in the default configuration file. +It is possible for the gems to provide configuration for RuboCop RSpec to allow proper detection of RSpec elements. +RuboCop https://docs.rubocop.org/rubocop/configuration.html#inheriting-configuration-from-a-dependency-gem[provides third-party gems with an ability to configure RuboCop]. + +== Packaging configuration for RuboCop RSpec + +NOTE: Due to https://github.com/rubocop/rubocop-rspec/issues/1126[a bug], this feature doesn't work properly for `rubocop-rspec` 2.5.0 and earlier versions. + +For a third-party gem, it's sufficient to follow three steps: + +1. Provide a configuration file (e.g. `.rubocop_rspec_alias_config.yml` or `config/rubocop-rspec.yml`). +Please check with the xref:usage.adoc#rspec-dsl-configuration[RSpec DSL configuration] how different elements of RSpec syntax can be configured. + +2. Add a section to their documentation how users can benefit from using RuboCop RSpec with full detection of their syntax extensions. + Example: + + ## Usage with RuboCop RSpec + Please add the following to your `.rubocop.yml` to make RuboCop RSpec aware of our cool syntax extensions: + inherit_gem: + third-party-gem: .rubocop_rspec_alias_config.yml + +3. Include the configuration file to their package by updating their `gemspec`’s `spec.files` to include the aforementioned configuration file. + +See pull requests: https://github.com/test-prof/test-prof/pull/199[test-prof], and https://github.com/palkan/action_policy/pull/138[action_policy] for a less trivial example. diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/upgrade_to_version_2.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/upgrade_to_version_2.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/upgrade_to_version_2.adoc 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/upgrade_to_version_2.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,273 @@ += Upgrade to Version 2.x +:doctype: book + +== Configuration File Update + +In version 2.x: + + - `RSpec/InvalidPredicateMatcher` cop is removed + - `CustomIncludeMethods` configuration option for `RSpec/EmptyExampleGroup` is removed + - cop departments are nested for cops with a department that doesn’t match the extension name (`Capybara`, `FactoryBot`, `Rails`) + - `AllCops/RSpec/Patterns`/`AllCops/FactoryBot/Patterns` options are removed + - Calling `super` from `#on_new_investigation` defined in a cop is mandatory now + - In specs, do not define `cop` + +[discrete] +=== Adjust the configuration of `RSpec/EmptyExampleGroup` + +[source,yaml] +---- +# .rubocop.yml + +# Before +RSpec/EmptyExampleGroup: + CustomIncludeMethods: + - include_tests + +# After +RSpec: + Language: + Includes: + Examples: + - include_tests +---- + +=== Add a top-level `RSpec` department + +RuboCop extensions had cops with clashing names and departments, e.g. both `rspec-rails` and `rubocop-rspec` had `Rails::HttpStatus` cops. +To avoid issues, e.g. inability to disable just one of the cops, each extension now has its own uber-department. +Expectedly, RuboCop RSpec’s uber-department name is `RSpec`. +Changes are only applied to cops that don’t already have the department set to `RSpec`, i.e. `Capybara`, `FactoryBot` and `Rails`. + +[source,yaml] +---- +# .rubocop.yml + +# Before +Capybara/CurrentPathExpectation: + Enabled: false + +FactoryBot/AttributeDefinedStatically: + Enabled: false + +# remains the same +RSpec/EmptyExampleGroup: + Enabled: false + +# After +RSpec/Capybara/CurrentPathExpectation: + Enabled: false + +RSpec/FactoryBot/AttributeDefinedStatically: + Enabled: false + +# remains the same +RSpec/EmptyExampleGroup: + Enabled: false +---- + +https://github.com/rubocop/rubocop/pull/8490[Learn more about this change]. + + +=== Use the RuboCop standard `Include` option to filter inspected files + +`Patterns` was a RuboCop RSpec-specific option, and RuboCop has a standard replacement. + +[source,yaml] +---- +# .rubocop.yml + +# Before +AllCops: + RSpec/FactoryBot: + Patterns: + - spec/factories/**/*.rb + - property/factories/**/*.rb + +# After +RSpec/FactoryBot: + Include: + - spec/factories/**/*.rb + - property/factories/**/*.rb +---- + +NOTE: Please keep in mind that merge mode for `Include` is set to override the default settings, so if you intend to add a path while keeping the default paths, you should include the default `Include` paths in your configuration. + +https://github.com/rubocop/rubocop-rspec/pull/1063[Learn more about this change]. + +== Custom Cop Update Guide + +Due to significant API changes, custom cops may break. +Here is the summary of the changes: + +1. The base class for cops is now `RuboCop::Cop::RSpec::Base` instead of `RuboCop::Cop::RSpec::Cop`. + +2. The module `RuboCop::Cop::RSpec::TopLevelDescribe` is replaced with a more generic `RuboCop::Cop::RSpec::TopLevelGroup`. + +3. `RuboCop::RSpec::Language` has been completely rewritten to support dynamic RSpec DSL aliases and negated matchers to fully support third-party libraries such as RSpec Rails, Pundit, Action Policy and many others. + +4. RuboCop RSpec updated the dependency of RuboCop to 1.0+. + +Below are the necessary steps to update custom cops to work with `rubocop-rspec` version 2.x. + + +=== Change the Parent Class + +Change the parent class of the custom cops from `RuboCop::Cop::RSpec::Cop` to `RuboCop::Cop::RSpec::Base`. + +[source,ruby] +---- +# Before +module RuboCop + module Cop + module RSpec + class FightPowerty < Cop + +# After +module RuboCop + module Cop + module RSpec + class FightPowerty < Base +---- + +https://github.com/rubocop/rubocop-rspec/pull/962[Example pull request]. + + +=== Replace `TopLevelDescribe` + +`TopLevelDescribe` was incomplete, had poor performance and did not distinguish between example groups and shared example groups. + +`TopLevelGroup` provides a similar interface, but instead of a single `on_top_level_describe` hook there are two, `on_top_level_example_group` and `on_top_level_group`. +There’s no need yet for `on_top_level_shared_group` for RuboCop core cops, but if your custom cop needs such a hook, please feel free to send a pull request. + +Additionally, `single_top_level_describe?` is removed with no direct replacement. +You may use `top_level_groups` query method instead, e.g. `top_level_groups.one?`. + +Example pull requests to replace `TopLevelDescribe` with `TopLevelGroup` [https://github.com/rubocop/rubocop-rspec/pull/978[1], https://github.com/rubocop/rubocop-rspec/pull/932[2], https://github.com/rubocop/rubocop-rspec/pull/977[3]]. + + +=== Change the `Language` Module Usages + +To allow for lazy initialization, and for loading of the language configuration after the class are loaded, a https://docs.rubocop.org/rubocop-ast/node_pattern.html#to-call-functions[function call feature of RuboCop AST] is used. + +The `RuboCop::RSpec::Language` is completely different now. + +`Hooks::ALL` and alike, and their accompanying helpers work differently. + +[source,ruby] +---- +# Before +def_node_matcher :shared_context, + SharedGroups::CONTEXT.block_pattern + +# After +def_node_matcher :shared_context, + block_pattern('#SharedGroups.context') +---- + +[source,ruby] +---- +# Before +def_node_search :examples?, + (Includes::EXAMPLES + Examples::ALL).send_pattern + +# After +def_node_search :examples?, + send_pattern('{#Includes.examples #Examples.all}') +---- + +[source,ruby] +---- +# Before +def_node_search :find_rspec_blocks, + ExampleGroups::ALL.block_pattern + +# After +def_node_search :find_rspec_blocks, + block_pattern('#ExampleGroups.all') +---- + +If you were calling Language elements directly, you have to make the same adjustments: + +[source,ruby] +---- +# Before +node&.sym_type? && Hooks::Scopes::ALL.include?(node.value) + +# After +node&.sym_type? && Language::HookScopes.all(node.value) +---- + +You may see a common pattern in the change. +There is a small exception, though: + +[source,ruby] +---- +# Before +ExampleGroups::GROUPS + +# After +ExampleGroups.regular + +# Before +Examples::EXAMPLES + +# After +Examples.regular +---- + +https://github.com/rubocop/rubocop-rspec/pull/956[Pull request with more examples]. + +=== Always call `super` from `on_new_investigation` in your cops + +`on_new_investigation` is now used for internal purposes, and not calling `super` from your cop involves a risk of configuration not being properly loaded, and dynamic RSpec DSL matchers won't work. + +NOTE: You don't have to define `on_new_investigation` in your cops unless you need to. + +[source,ruby] +---- +module RuboCop + module Cop + module RSpec + class MultipleMemoizedHelpers < Base + def on_new_investigation + super # Always call `super` + @example_group_memoized_helpers = {} + end + end + end + end +end +---- + +https://github.com/rubocop/rubocop-rspec/pull/956[Pull request with more examples]. + +=== Use `:config` RSpec metadata in cop specs + +`:config` metadata should be added to the top-level example group of your cop spec. +Doing otherwise will not pass configuration to the cop, and dynamic RSpec DSL matchers might not work. + +[source,ruby] +---- +# Before +RSpec.describe 'MyMightyCop' do + let(:cop) { described_class.new } + # ... +end + +# After +RSpec.describe 'MyMightyCop', :config do + # `cop` is defined for you by RuboCop's shared context that is included + # to example groups with :config metadata + + # ... +end +---- + +https://github.com/rubocop/rubocop/blob/51ff1d7e29c985732fe129082c98d66c531a2611/lib/rubocop/rspec/shared_contexts.rb#L56[RuboCop takes care of defining everything for your cop specs]. + +=== Conform with RuboCop API Changes + +The parent project, RuboCop, has API changes. +While they won’t result in cop breakages, it is recommended to update cops to use new API’s. +Follow the https://docs.rubocop.org/rubocop/v1_upgrade_notes[RuboCop v1 update guide] to adjust custom cops’ use of RuboCop’s auto-correction API. diff -Nru ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/usage.adoc ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/usage.adoc --- ruby-rubocop-rspec-1.42.0/docs/modules/ROOT/pages/usage.adoc 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/docs/modules/ROOT/pages/usage.adoc 2022-12-13 09:15:42.000000000 +0000 @@ -1,19 +1,79 @@ = Usage -You need to tell RuboCop to load the RSpec extension. There are three -ways to do this: +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`. +Put this into your `.rubocop.yml`: ---- require: rubocop-rspec ---- +or, if you are using several extensions: + +---- +require: + - rubocop-rspec + - rubocop-performance +---- + Now you can run `rubocop` and it will automatically load the RuboCop RSpec cops together with the standard cops. +=== RSpec DSL configuration + +In case you https://github.com/rspec/rspec-core/blob/b0d0843a285693c64cdbe0c85726db155b46047e/lib/rspec/core/configuration.rb#L1122[define aliases for RSpec DSL], i.e. examples, example groups, hooks, or include example statements, you need to configure it so those elements are properly detected by RuboCop RSpec. + +[source,ruby] +---- +# spec/spec_helper.rb +RSpec.configure do |c| + c.alias_example_group_to :detail, :detailed => true +end + +# spec/detail_spec.rb +RSpec.detail "a detail" do + it "can do some less important stuff" do + end +end +---- + +[source,yaml] +---- +# .rubocop.yml +RSpec: + Language: + ExampleGroups: + Regular: + - detail +---- + +Some libraries extensively define RSpec DSL aliases (e.g. Pundit, Action Policy) or augment existing elements providing the same semantics (e.g. `let_it_be` from `test-prof`). +Those libraries can provide necessary configuration, but won't necessarily do so. +If they do, their README will mention that you have to explicitly require their configuration from your `.rubocop.yml` file. + +[source,yaml] +---- +# .rubocop.yml + +require: + - rubocop-rspec + - test-prof + +# or + +RSpec: + Language: + Helpers: + - let_it_be +---- + +NOTE: the default merge mode is to inherit, so you won't remove any of the default settings. + +RuboCop RSpec's https://github.com/rubocop/rubocop-rspec/blob/a43424527c09fae2e6ddb133f4b2988f6c46bb2e/config/default.yml#L6[default configuration] is a good source of information on what can be configured. + == Command line [source,bash] @@ -36,23 +96,22 @@ == 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: +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 setting `Include`: [source,yaml] ---- -# Inspect all files -AllCops: - RSpec: - Patterns: - - '.+' +# Inspect files in `test/` directory +RSpec: + Include: + - '**/test/**/*' ---- - [source,yaml] ---- # Inspect only files ending with `_test.rb` -AllCops: - RSpec: - Patterns: - - '_test.rb$' +RSpec: + Include: + - '**/*_test.rb' ---- + +NOTE: Please keep in mind that merge mode for `Include` is set to override the default settings, so if you intend to add a path while keeping the default paths, you should include the default `Include` paths in your configuration. diff -Nru ruby-rubocop-rspec-1.42.0/Gemfile ruby-rubocop-rspec-2.16.0/Gemfile --- ruby-rubocop-rspec-1.42.0/Gemfile 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/Gemfile 2022-12-13 09:15:42.000000000 +0000 @@ -4,8 +4,13 @@ gemspec -local_gemfile = 'Gemfile.local' +gem 'bump' +gem 'rack' +gem 'rake' +gem 'rspec', '~> 3.11' +gem 'rubocop-performance', '~> 1.7' +gem 'rubocop-rake', '~> 0.6' +gem 'yard' -if File.exist?(local_gemfile) - eval(File.read(local_gemfile)) # rubocop:disable Security/Eval -end +local_gemfile = 'Gemfile.local' +eval_gemfile(local_gemfile) if File.exist?(local_gemfile) diff -Nru ruby-rubocop-rspec-1.42.0/.git-blame-ignore-revs ruby-rubocop-rspec-2.16.0/.git-blame-ignore-revs --- ruby-rubocop-rspec-1.42.0/.git-blame-ignore-revs 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.git-blame-ignore-revs 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,3 @@ +# .git-blame-ignore-revs +# Add mdformat to the workflow in GitHub Actions +4874a5a4a2a58e76d343aaa02279cd93b16f5a30 diff -Nru ruby-rubocop-rspec-1.42.0/.github/CONTRIBUTING.md ruby-rubocop-rspec-2.16.0/.github/CONTRIBUTING.md --- ruby-rubocop-rspec-1.42.0/.github/CONTRIBUTING.md 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.github/CONTRIBUTING.md 2022-12-13 09:15:42.000000000 +0000 @@ -1,34 +1,62 @@ # 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. +If you encounter problems or have ideas for improvements or new features, please report them to the [issue tracker](https://github.com/rubocop/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. +- 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. +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/rubocop-rspec/blob/master/CHANGELOG.md) entry. +6. Commit your changes. +7. Push to the branch. +8. Create new Pull Request. + +### Spell Checking + +We are running [codespell](https://github.com/codespell-project/codespell) with [GitHub Actions](https://github.com/rubocop/rubocop-rspec/blob/master/.github/workflows/codespell.yml) to check spelling and +[codespell](https://pypi.org/project/codespell/). +`codespell` is written in [Python](https://www.python.org/) and you can run it with: + +```console +$ codespell --ignore-words=.codespellignore +``` + +### Linting YAML files + +We are running [yamllint](https://github.com/adrienverge/yamllint) for linting YAML files. This is also run by [GitHub Actions](https://github.com/rubocop/rubocop-rspec/blob/master/.github/workflows/linting.yml). +`yamllint` is written in [Python](https://www.python.org/) and you can run it with: + +```console +$ yamllint . +``` + +### Formatting Markdown files + +We are running [mdformat](https://github.com/executablebooks/mdformat) for formatting Markdown files. This is also run by [GitHub Actions](https://github.com/rubocop/rubocop-rspec/blob/master/.github/workflows/linting.yml). +`mdformat` is written in [Python](https://www.python.org/) and you can run it with: + +```console +$ mdformat . --number +``` ## 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.). +- 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.). diff -Nru ruby-rubocop-rspec-1.42.0/.github/dependabot.yml ruby-rubocop-rspec-2.16.0/.github/dependabot.yml --- ruby-rubocop-rspec-1.42.0/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.github/dependabot.yml 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'weekly' diff -Nru ruby-rubocop-rspec-1.42.0/.github/PULL_REQUEST_TEMPLATE.md ruby-rubocop-rspec-2.16.0/.github/PULL_REQUEST_TEMPLATE.md --- ruby-rubocop-rspec-1.42.0/.github/PULL_REQUEST_TEMPLATE.md 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.github/PULL_REQUEST_TEMPLATE.md 2022-12-13 09:15:42.000000000 +0000 @@ -1,23 +1,25 @@ **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). +- [ ] 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. +- [ ] Added the new cop to `config/default.yml`. +- [ ] The cop is configured as `Enabled: pending` in `config/default.yml`. +- [ ] The cop is configured as `Enabled: true` in `.rubocop.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`. If you have modified an existing cop's configuration options: -* [ ] Set `VersionChanged` in `default/config.yml` to the next major version. +- [ ] Set `VersionChanged: "<>"` in `config/default.yml`. diff -Nru ruby-rubocop-rspec-1.42.0/.github/workflows/codespell.yml ruby-rubocop-rspec-2.16.0/.github/workflows/codespell.yml --- ruby-rubocop-rspec-1.42.0/.github/workflows/codespell.yml 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.github/workflows/codespell.yml 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,14 @@ +name: CodeSpell +on: + - pull_request +jobs: + codespell: + name: CodeSpell + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: CodeSpell + uses: codespell-project/actions-codespell@master + with: + check_filenames: true + ignore_words_file: .codespellignore diff -Nru ruby-rubocop-rspec-1.42.0/.github/workflows/linting.yml ruby-rubocop-rspec-2.16.0/.github/workflows/linting.yml --- ruby-rubocop-rspec-1.42.0/.github/workflows/linting.yml 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.github/workflows/linting.yml 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,26 @@ +name: Linting +on: + - pull_request +jobs: + yamllint: + name: Yamllint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Yamllint + uses: karancode/yamllint-github-action@master + with: + yamllint_comment: true + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + mdformat: + name: Mdformat + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Mdformat + uses: ydah/mdformat-action@main + with: + number: true + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff -Nru ruby-rubocop-rspec-1.42.0/.github/workflows/main.yml ruby-rubocop-rspec-2.16.0/.github/workflows/main.yml --- ruby-rubocop-rspec-1.42.0/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.github/workflows/main.yml 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,82 @@ +name: CI + +on: + pull_request: + push: + branches: + - master + +jobs: + confirm_config_and_documentation: + runs-on: ubuntu-latest + name: Confirm config and documentation + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.1" + bundler-cache: true + - run: bundle exec rake confirm_config documentation_syntax_check confirm_documentation + + main: + runs-on: ubuntu-latest + strategy: + matrix: + ruby: + - "2.6" + - "2.7" + - "3.0" + - "3.1" + - ruby-head + - jruby-9.3 + task: + - internal_investigation + - spec + name: "Ruby ${{ matrix.ruby }}: ${{ matrix.task }}" + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "${{ matrix.ruby }}" + bundler-cache: true + - run: bundle exec rake ${{ matrix.task }} + + edge-rubocop: + runs-on: ubuntu-latest + strategy: + matrix: + task: + - internal_investigation + - spec + name: "Edge RuboCop: ${{ matrix.task }}" + steps: + - uses: actions/checkout@v3 + - name: Use latest RuboCop from `master` + run: | + echo "gem 'rubocop', github: 'rubocop-hq/rubocop'" > Gemfile.local + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.1" + bundler-cache: true + - run: bundle exec rake ${{ matrix.task }} + + rspec4: + runs-on: ubuntu-latest + name: RSpec 4 + steps: + - uses: actions/checkout@v3 + - name: Use latest RSpec 4 from `4-0-dev` branch + run: | + sed -e '/rspec/d' -i Gemfile + cat << EOF > Gemfile.local + gem 'rspec', github: 'rspec/rspec', branch: '4-0-dev' + gem 'rspec-core', github: 'rspec/rspec-core', branch: '4-0-dev' + gem 'rspec-expectations', github: 'rspec/rspec-expectations', branch: '4-0-dev' + gem 'rspec-mocks', github: 'rspec/rspec-mocks', branch: '4-0-dev' + gem 'rspec-support', github: 'rspec/rspec-support', branch: '4-0-dev' + EOF + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.1" + bundler-cache: true + - run: bundle exec rake spec diff -Nru ruby-rubocop-rspec-1.42.0/.gitignore ruby-rubocop-rspec-2.16.0/.gitignore --- ruby-rubocop-rspec-1.42.0/.gitignore 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/.gitignore 2022-12-13 09:15:42.000000000 +0000 @@ -1,7 +1,3 @@ -# rcov generated -coverage -coverage.data - # rdoc generated rdoc diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/align_left_let_brace.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/align_left_let_brace.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/align_left_let_brace.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/align_left_let_brace.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,18 +6,17 @@ # Checks that left braces for adjacent single line lets are aligned. # # @example + # # bad + # let(:foobar) { blahblah } + # let(:baz) { bar } + # let(:a) { b } # - # # bad - # let(:foobar) { blahblah } - # let(:baz) { bar } - # let(:a) { b } + # # good + # let(:foobar) { blahblah } + # let(:baz) { bar } + # let(:a) { b } # - # # good - # let(:foobar) { blahblah } - # let(:baz) { bar } - # let(:a) { b } - # - class AlignLeftLetBrace < Cop + class AlignLeftLetBrace < Base extend AutoCorrector MSG = 'Align left let brace' @@ -27,11 +26,9 @@ end def on_new_investigation + super 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( @@ -40,6 +37,12 @@ end end end + + private + + def token_aligner + RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin) + end end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/align_right_let_brace.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/align_right_let_brace.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/align_right_let_brace.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/align_right_let_brace.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,18 +6,17 @@ # Checks that right braces for adjacent single line lets are aligned. # # @example + # # bad + # let(:foobar) { blahblah } + # let(:baz) { bar } + # let(:a) { b } # - # # bad - # let(:foobar) { blahblah } - # let(:baz) { bar } - # let(:a) { b } + # # good + # let(:foobar) { blahblah } + # let(:baz) { bar } + # let(:a) { b } # - # # good - # let(:foobar) { blahblah } - # let(:baz) { bar } - # let(:a) { b } - # - class AlignRightLetBrace < Cop + class AlignRightLetBrace < Base extend AutoCorrector MSG = 'Align right let brace' @@ -27,11 +26,9 @@ end def on_new_investigation + super 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( @@ -40,6 +37,12 @@ end end end + + private + + def token_aligner + RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end) + end end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/any_instance.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/any_instance.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/any_instance.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/any_instance.rb 2022-12-13 09:15:42.000000000 +0000 @@ -22,20 +22,17 @@ # allow(my_instance).to receive(:foo) # end # end - class AnyInstance < Cop + # + class AnyInstance < Base MSG = 'Avoid stubbing using `%s`.' - - def_node_matcher :disallowed_stub, <<-PATTERN - (send _ ${:any_instance :allow_any_instance_of :expect_any_instance_of} ...) - PATTERN + RESTRICT_ON_SEND = %i[ + any_instance + allow_any_instance_of + expect_any_instance_of + ].freeze def on_send(node) - disallowed_stub(node) do |method| - add_offense( - node, - message: format(MSG, method: method) - ) - end + add_offense(node, message: format(MSG, method: node.method_name)) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/around_block.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/around_block.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/around_block.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/around_block.rb 2022-12-13 09:15:42.000000000 +0000 @@ -25,21 +25,29 @@ # some_method # test.run # end - class AroundBlock < Cop + # + class AroundBlock < Base MSG_NO_ARG = 'Test object should be passed to around block.' - MSG_UNUSED_ARG = 'You should call `%s.call` '\ + 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 $...) ...) + # @!method hook_block(node) + def_node_matcher :hook_block, <<-PATTERN + (block (send nil? :around sym ?) (args $...) ...) PATTERN + # @!method hook_numblock(node) + def_node_matcher :hook_numblock, <<-PATTERN + (numblock (send nil? :around sym ?) ...) + PATTERN + + # @!method find_arg_usage(node) def_node_search :find_arg_usage, <<-PATTERN {(send $... {:call :run}) (send _ _ $...) (yield $...) (block-pass $...)} PATTERN def on_block(node) - hook(node) do |(example_proxy)| + hook_block(node) do |(example_proxy)| if example_proxy.nil? add_no_arg_offense(node) else @@ -48,6 +56,12 @@ end end + def on_numblock(node) + hook_numblock(node) do + check_for_numblock(node) + end + end + private def add_no_arg_offense(node) @@ -66,6 +80,17 @@ message: format(MSG_UNUSED_ARG, arg: name) ) end + + def check_for_numblock(block) + find_arg_usage(block) do |usage| + return if usage.include?(s(:lvar, :_1)) + end + + add_offense( + block.children.last, + message: format(MSG_UNUSED_ARG, arg: :_1) + ) + end end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/base.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/base.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/base.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/base.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # @abstract parent class to RSpec cops + class Base < ::RuboCop::Cop::Base + include RuboCop::RSpec::Language + extend RuboCop::RSpec::Language::NodePattern + + exclude_from_registry + + # Invoke the original inherited hook so our cops are recognized + def self.inherited(subclass) # rubocop:disable Lint/MissingSuper + RuboCop::Cop::Base.inherited(subclass) + end + + # Set the config for dynamic DSL configuration-aware helpers + # that have no other means of accessing the configuration. + def on_new_investigation + super + RuboCop::RSpec::Language.config = config['RSpec']['Language'] + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be_eql.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be_eql.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be_eql.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be_eql.rb 2022-12-13 09:15:42.000000000 +0000 @@ -10,8 +10,10 @@ # can be compared by identity and therefore the `be` matcher is # preferable as it is a more strict test. # - # @example + # @safety + # This cop is unsafe because it changes how values are compared. # + # @example # # bad # expect(foo).to eql(1) # expect(foo).to eql(1.0) @@ -35,13 +37,15 @@ # necessarily the same type as `b` since the `#==` operator can # coerce objects for comparison. # - class BeEql < Cop + class BeEql < Base extend AutoCorrector MSG = 'Prefer `be` over `eql`.' + RESTRICT_ON_SEND = %i[to].freeze + # @!method eql_type_with_identity(node) def_node_matcher :eql_type_with_identity, <<-PATTERN - (send _ :to $(send nil? :eql {true false int float sym nil_type?})) + (send _ :to $(send nil? :eql {true false int float sym nil})) PATTERN def on_send(node) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be_eq.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be_eq.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be_eq.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be_eq.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Check for expectations where `be(...)` can replace `eq(...)`. + # + # The `be` matcher compares by identity while the `eq` matcher compares + # using `==`. Booleans and nil can be compared by identity and therefore + # the `be` matcher is preferable as it is a more strict test. + # + # @safety + # This cop is unsafe because it changes how values are compared. + # + # @example + # # bad + # expect(foo).to eq(true) + # expect(foo).to eq(false) + # expect(foo).to eq(nil) + # + # # good + # expect(foo).to be(true) + # expect(foo).to be(false) + # expect(foo).to be(nil) + # + class BeEq < Base + extend AutoCorrector + + MSG = 'Prefer `be` over `eq`.' + RESTRICT_ON_SEND = %i[eq].freeze + + # @!method eq_type_with_identity?(node) + def_node_matcher :eq_type_with_identity?, <<-PATTERN + (send nil? :eq {true false nil}) + PATTERN + + def on_send(node) + return unless eq_type_with_identity?(node) + + add_offense(node.loc.selector) do |corrector| + corrector.replace(node.loc.selector, 'be') + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/before_after_all.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/before_after_all.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/before_after_all.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/before_after_all.rb 2022-12-13 09:15:42.000000000 +0000 @@ -23,12 +23,16 @@ # 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 '\ + # + class BeforeAfterAll < Base + 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.' + RESTRICT_ON_SEND = %i[before after].freeze + + # @!method before_or_after_all(node) def_node_matcher :before_or_after_all, <<-PATTERN $(send _ {:before :after} (sym {:all :context})) PATTERN diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be_nil.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be_nil.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be_nil.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be_nil.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Ensures a consistent style is used when matching `nil`. + # + # You can either use the more specific `be_nil` matcher, or the more + # generic `be` matcher with a `nil` argument. + # + # This cop can be configured using the `EnforcedStyle` option + # + # @example `EnforcedStyle: be_nil` (default) + # # bad + # expect(foo).to be(nil) + # + # # good + # expect(foo).to be_nil + # + # @example `EnforcedStyle: be` + # # bad + # expect(foo).to be_nil + # + # # good + # expect(foo).to be(nil) + # + class BeNil < Base + extend AutoCorrector + include ConfigurableEnforcedStyle + + BE_MSG = 'Prefer `be(nil)` over `be_nil`.' + BE_NIL_MSG = 'Prefer `be_nil` over `be(nil)`.' + RESTRICT_ON_SEND = %i[be be_nil].freeze + + # @!method be_nil_matcher?(node) + def_node_matcher :be_nil_matcher?, <<-PATTERN + (send nil? :be_nil) + PATTERN + + # @!method nil_value_expectation?(node) + def_node_matcher :nil_value_expectation?, <<-PATTERN + (send nil? :be nil) + PATTERN + + def on_send(node) + case style + when :be + check_be_style(node) + when :be_nil + check_be_nil_style(node) + end + end + + private + + def check_be_style(node) + return unless be_nil_matcher?(node) + + add_offense(node, message: BE_MSG) do |corrector| + corrector.replace(node.loc.expression, 'be(nil)') + end + end + + def check_be_nil_style(node) + return unless nil_value_expectation?(node) + + add_offense(node, message: BE_NIL_MSG) do |corrector| + corrector.replace(node.loc.expression, 'be_nil') + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/be.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/be.rb 2022-12-13 09:15:42.000000000 +0000 @@ -10,7 +10,6 @@ # cases it's better to specify what exactly is the expected value. # # @example - # # # bad # expect(foo).to be # @@ -19,11 +18,14 @@ # expect(foo).to be 1.0 # expect(foo).to be(true) # - class Be < Cop - MSG = 'Don\'t use `be` without an argument.' + class Be < Base + MSG = "Don't use `be` without an argument." + + RESTRICT_ON_SEND = Runners.all + # @!method be_without_args(node) def_node_matcher :be_without_args, <<-PATTERN - (send _ #{Runners::ALL.node_pattern_union} $(send nil? :be)) + (send _ #Runners.all $(send nil? :be)) PATTERN def on_send(node) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,47 +6,62 @@ 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. + # The + # https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method[`have_current_path` matcher] + # should be used on `page` to set expectations on Capybara's + # current path, since it uses + # https://github.com/teamcapybara/capybara/blob/master/README.md#asynchronous-javascript-ajax-and-friends[Capybara's waiting functionality] + # which ensures that preceding actions (like `click_link`) have + # completed. + # + # This cop does not support autocorrection in some cases. # # @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/) + # expect(page).to have_current_path('/callback') + # + # # bad (does not support autocorrection) + # expect(page.current_path).to match(variable) + # + # # good + # expect(page).to have_current_path('/callback') # - class CurrentPathExpectation < Cop + class CurrentPathExpectation < ::RuboCop::Cop::Base 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`' + RESTRICT_ON_SEND = %i[expect].freeze + + # @!method expectation_set_on_current_path(node) 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') + # @!method as_is_matcher(node) def_node_matcher :as_is_matcher, <<-PATTERN (send - #expectation_set_on_current_path $#{Runners::ALL.node_pattern_union} + #expectation_set_on_current_path ${:to :to_not :not_to} ${(send nil? :eq ...) (send nil? :match (regexp ...))}) PATTERN + # @!method regexp_str_matcher(node) def_node_matcher :regexp_str_matcher, <<-PATTERN (send - #expectation_set_on_current_path $#{Runners::ALL.node_pattern_union} + #expectation_set_on_current_path ${:to :to_not :not_to} $(send nil? :match (str $_))) PATTERN + def self.autocorrect_incompatible_with + [Style::TrailingCommaInArguments] + end + def on_send(node) expectation_set_on_current_path(node) do add_offense(node.loc.selector) do |corrector| diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/feature_methods.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/feature_methods.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/feature_methods.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/feature_methods.rb 2022-12-13 09:15:42.000000000 +0000 @@ -40,12 +40,14 @@ # # ... # end # end - class FeatureMethods < Cop + # + class FeatureMethods < Base extend AutoCorrector + include InsideExampleGroup MSG = 'Use `%s` instead of `%s`.' - # https://git.io/v7Kwr + # https://github.com/teamcapybara/capybara/blob/e283c1aeaa72441f5403963577e16333bf111a81/lib/capybara/rspec/features.rb#L31-L36 MAP = { background: :before, scenario: :it, @@ -55,20 +57,20 @@ feature: :describe }.freeze - def_node_matcher :spec?, <<-PATTERN - (block - (send #{RSPEC} {:describe :feature} ...) - ...) + # @!method capybara_speak(node) + def_node_matcher :capybara_speak, <<-PATTERN + {#{MAP.keys.map(&:inspect).join(' ')}} PATTERN + # @!method feature_method(node) def_node_matcher :feature_method, <<-PATTERN (block - $(send #{RSPEC} ${#{MAP.keys.map(&:inspect).join(' ')}} ...) + $(send #rspec? $#capybara_speak ...) ...) PATTERN - def on_block(node) - return unless inside_spec?(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler + return unless inside_example_group?(node) feature_method(node) do |send_node, match| next if enabled?(match) @@ -86,21 +88,6 @@ 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 diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/negation_matcher.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/negation_matcher.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/negation_matcher.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/negation_matcher.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,106 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module Capybara + # Enforces use of `have_no_*` or `not_to` for negated expectations. + # + # @example EnforcedStyle: not_to (default) + # # bad + # expect(page).to have_no_selector + # expect(page).to have_no_css('a') + # + # # good + # expect(page).not_to have_selector + # expect(page).not_to have_css('a') + # + # @example EnforcedStyle: have_no + # # bad + # expect(page).not_to have_selector + # expect(page).not_to have_css('a') + # + # # good + # expect(page).to have_no_selector + # expect(page).to have_no_css('a') + # + class NegationMatcher < ::RuboCop::Cop::Base + extend AutoCorrector + include ConfigurableEnforcedStyle + + MSG = 'Use `expect(...).%s %s`.' + CAPYBARA_MATCHERS = %w[ + selector css xpath text title current_path link button + field checked_field unchecked_field select table + sibling ancestor + ].freeze + POSITIVE_MATCHERS = + Set.new(CAPYBARA_MATCHERS) { |element| :"have_#{element}" }.freeze + NEGATIVE_MATCHERS = + Set.new(CAPYBARA_MATCHERS) { |element| :"have_no_#{element}" } + .freeze + RESTRICT_ON_SEND = (POSITIVE_MATCHERS + NEGATIVE_MATCHERS).freeze + + # @!method not_to?(node) + def_node_matcher :not_to?, <<~PATTERN + (send ... :not_to + (send nil? %POSITIVE_MATCHERS ...)) + PATTERN + + # @!method have_no?(node) + def_node_matcher :have_no?, <<~PATTERN + (send ... :to + (send nil? %NEGATIVE_MATCHERS ...)) + PATTERN + + def on_send(node) + return unless offense?(node.parent) + + matcher = node.method_name.to_s + add_offense(offense_range(node), + message: message(matcher)) do |corrector| + corrector.replace(node.parent.loc.selector, replaced_runner) + corrector.replace(node.loc.selector, + replaced_matcher(matcher)) + end + end + + private + + def offense?(node) + (style == :have_no && not_to?(node)) || + (style == :not_to && have_no?(node)) + end + + def offense_range(node) + node.parent.loc.selector.with(end_pos: node.loc.selector.end_pos) + end + + def message(matcher) + format(MSG, + runner: replaced_runner, + matcher: replaced_matcher(matcher)) + end + + def replaced_runner + case style + when :have_no + 'to' + when :not_to + 'not_to' + end + end + + def replaced_matcher(matcher) + case style + when :have_no + matcher.sub('have_', 'have_no_') + when :not_to + matcher.sub('have_no_', 'have_') + end + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/specific_actions.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/specific_actions.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/specific_actions.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/specific_actions.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module Capybara + # Checks for there is a more specific actions offered by Capybara. + # + # @example + # + # # bad + # find('a').click + # find('button.cls').click + # find('a', exact_text: 'foo').click + # find('div button').click + # + # # good + # click_link + # click_button(class: 'cls') + # click_link(exact_text: 'foo') + # find('div').click_button + # + class SpecificActions < ::RuboCop::Cop::Base + MSG = "Prefer `%s` over `find('%s').click`." + RESTRICT_ON_SEND = %i[click].freeze + SPECIFIC_ACTION = { + 'button' => 'button', + 'a' => 'link' + }.freeze + + # @!method click_on_selector(node) + def_node_matcher :click_on_selector, <<-PATTERN + (send _ :find (str $_) ...) + PATTERN + + def on_send(node) + click_on_selector(node.receiver) do |arg| + next unless supported_selector?(arg) + # Always check the last selector in the case of multiple selectors + # separated by whitespace. + # because the `.click` is executed on the element to + # which the last selector points. + next unless (selector = last_selector(arg)) + next unless (action = specific_action(selector)) + next unless CapybaraHelp.specific_option?(node.receiver, arg, + action) + next unless CapybaraHelp.specific_pseudo_classes?(arg) + + range = offense_range(node, node.receiver) + add_offense(range, message: message(action, selector)) + end + end + + private + + def specific_action(selector) + SPECIFIC_ACTION[last_selector(selector)] + end + + def supported_selector?(selector) + !selector.match?(/[>,+~]/) + end + + def last_selector(arg) + arg.split.last[/^\w+/, 0] + end + + def offense_range(node, receiver) + receiver.loc.selector.with(end_pos: node.loc.expression.end_pos) + end + + def message(action, selector) + format(MSG, + good_action: good_action(action), + selector: selector) + end + + def good_action(action) + "click_#{action}" + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/specific_finders.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/specific_finders.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/specific_finders.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/specific_finders.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module Capybara + # Checks if there is a more specific finder offered by Capybara. + # + # @example + # # bad + # find('#some-id') + # find('[visible][id=some-id]') + # + # # good + # find_by_id('some-id') + # find_by_id('some-id', visible: true) + # + class SpecificFinders < ::RuboCop::Cop::Base + extend AutoCorrector + + include RangeHelp + + MSG = 'Prefer `find_by` over `find`.' + RESTRICT_ON_SEND = %i[find].freeze + + # @!method find_argument(node) + def_node_matcher :find_argument, <<~PATTERN + (send _ :find (str $_) ...) + PATTERN + + def on_send(node) + find_argument(node) do |arg| + next if CssSelector.multiple_selectors?(arg) + + on_attr(node, arg) if attribute?(arg) + on_id(node, arg) if CssSelector.id?(arg) + end + end + + private + + def on_attr(node, arg) + return unless (id = CssSelector.attributes(arg)['id']) + + register_offense(node, replaced_arguments(arg, id)) + end + + def on_id(node, arg) + register_offense(node, "'#{arg.to_s.delete('#')}'") + end + + def attribute?(arg) + CssSelector.attribute?(arg) && + CssSelector.common_attributes?(arg) + end + + def register_offense(node, arg_replacement) + add_offense(offense_range(node)) do |corrector| + corrector.replace(node.loc.selector, 'find_by_id') + corrector.replace(node.first_argument.loc.expression, + arg_replacement) + end + end + + def replaced_arguments(arg, id) + options = to_options(CssSelector.attributes(arg)) + options.empty? ? id : "#{id}, #{options}" + end + + def to_options(attrs) + attrs.each.map do |key, value| + next if key == 'id' + + "#{key}: #{value}" + end.compact.join(', ') + end + + def offense_range(node) + range_between(node.loc.selector.begin_pos, end_pos(node)) + end + + def end_pos(node) + if node.loc.end + node.loc.end.end_pos + else + node.loc.expression.end_pos + end + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/specific_matcher.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/specific_matcher.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/specific_matcher.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/specific_matcher.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module Capybara + # Checks for there is a more specific matcher offered by Capybara. + # + # @example + # + # # bad + # expect(page).to have_selector('button') + # expect(page).to have_no_selector('button.cls') + # expect(page).to have_css('button') + # expect(page).to have_no_css('a.cls', href: 'http://example.com') + # expect(page).to have_css('table.cls') + # expect(page).to have_css('select') + # expect(page).to have_css('input', exact_text: 'foo') + # + # # good + # expect(page).to have_button + # expect(page).to have_no_button(class: 'cls') + # expect(page).to have_button + # expect(page).to have_no_link('foo', class: 'cls', href: 'http://example.com') + # expect(page).to have_table(class: 'cls') + # expect(page).to have_select + # expect(page).to have_field('foo') + # + class SpecificMatcher < ::RuboCop::Cop::Base + MSG = 'Prefer `%s` over `%s`.' + RESTRICT_ON_SEND = %i[have_selector have_no_selector have_css + have_no_css].freeze + SPECIFIC_MATCHER = { + 'button' => 'button', + 'a' => 'link', + 'table' => 'table', + 'select' => 'select', + 'input' => 'field' + }.freeze + + # @!method first_argument(node) + def_node_matcher :first_argument, <<-PATTERN + (send nil? _ (str $_) ... ) + PATTERN + + def on_send(node) + first_argument(node) do |arg| + next unless (matcher = specific_matcher(arg)) + next if CssSelector.multiple_selectors?(arg) + next unless CapybaraHelp.specific_option?(node, arg, matcher) + next unless CapybaraHelp.specific_pseudo_classes?(arg) + + add_offense(node, message: message(node, matcher)) + end + end + + private + + def specific_matcher(arg) + splitted_arg = arg[/^\w+/, 0] + SPECIFIC_MATCHER[splitted_arg] + end + + def message(node, matcher) + format(MSG, + good_matcher: good_matcher(node, matcher), + bad_matcher: node.method_name) + end + + def good_matcher(node, matcher) + node.method_name + .to_s + .gsub(/selector|css/, matcher.to_s) + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb 2022-12-13 09:15:42.000000000 +0000 @@ -4,7 +4,7 @@ module Cop module RSpec module Capybara - # Checks for boolean visibility in capybara finders. + # 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 @@ -12,10 +12,10 @@ # 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) + # Read more in + # https://www.rubydoc.info/gems/capybara/Capybara%2FNode%2FFinders:all[the documentation]. # # @example - # # # bad # expect(page).to have_selector('.foo', visible: false) # expect(page).to have_css('.foo', visible: true) @@ -26,28 +26,32 @@ # expect(page).to have_css('.foo', visible: :all) # expect(page).to have_link('my link', visible: :hidden) # - class VisibilityMatcher < Cop + class VisibilityMatcher < ::RuboCop::Cop::Base 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 + CAPYBARA_MATCHER_METHODS = %w[ + button + checked_field + css + field + link + select + selector + table + unchecked_field + xpath + ].flat_map do |element| + ["have_#{element}".to_sym, "have_no_#{element}".to_sym] + end + + RESTRICT_ON_SEND = CAPYBARA_MATCHER_METHODS + # @!method visible_true?(node) def_node_matcher :visible_true?, <<~PATTERN (send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) true) ...>)) PATTERN + # @!method visible_false?(node) def_node_matcher :visible_false?, <<~PATTERN (send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) false) ...>)) PATTERN diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/change_by_zero.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/change_by_zero.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/change_by_zero.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/change_by_zero.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,148 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Prefer negated matchers over `to change.by(0)`. + # + # In the case of composite expectations, cop suggest using the + # negation matchers of `RSpec::Matchers#change`. + # + # By default the cop does not support autocorrect of + # compound expectations, but if you set the + # negated matcher for `change`, e.g. `not_change` with + # the `NegatedMatcher` option, the cop will perform the autocorrection. + # + # @example NegatedMatcher: ~ (default) + # # bad + # expect { run }.to change(Foo, :bar).by(0) + # expect { run }.to change { Foo.bar }.by(0) + # + # # bad - compound expectations (does not support autocorrection) + # expect { run } + # .to change(Foo, :bar).by(0) + # .and change(Foo, :baz).by(0) + # expect { run } + # .to change { Foo.bar }.by(0) + # .and change { Foo.baz }.by(0) + # + # # good + # expect { run }.not_to change(Foo, :bar) + # expect { run }.not_to change { Foo.bar } + # + # # good - compound expectations + # define_negated_matcher :not_change, :change + # expect { run } + # .to not_change(Foo, :bar) + # .and not_change(Foo, :baz) + # expect { run } + # .to not_change { Foo.bar } + # .and not_change { Foo.baz } + # + # @example NegatedMatcher: not_change + # # bad (support autocorrection to good case) + # expect { run } + # .to change(Foo, :bar).by(0) + # .and change(Foo, :baz).by(0) + # expect { run } + # .to change { Foo.bar }.by(0) + # .and change { Foo.baz }.by(0) + # + # # good + # define_negated_matcher :not_change, :change + # expect { run } + # .to not_change(Foo, :bar) + # .and not_change(Foo, :baz) + # expect { run } + # .to not_change { Foo.bar } + # .and not_change { Foo.baz } + # + class ChangeByZero < Base + extend AutoCorrector + MSG = 'Prefer `not_to change` over `to change.by(0)`.' + MSG_COMPOUND = 'Prefer %s with compound expectations ' \ + 'over `change.by(0)`.' + RESTRICT_ON_SEND = %i[change].freeze + + # @!method expect_change_with_arguments(node) + def_node_matcher :expect_change_with_arguments, <<-PATTERN + (send + (send nil? :change ...) :by + (int 0)) + PATTERN + + # @!method expect_change_with_block(node) + def_node_matcher :expect_change_with_block, <<-PATTERN + (send + (block + (send nil? :change) + (args) + (send (...) $_)) :by + (int 0)) + PATTERN + + # @!method change_nodes(node) + def_node_search :change_nodes, <<-PATTERN + $(send nil? :change ...) + PATTERN + + def on_send(node) + expect_change_with_arguments(node.parent) do + check_offense(node.parent) + end + + expect_change_with_block(node.parent.parent) do + check_offense(node.parent.parent) + end + end + + private + + def check_offense(node) + expression = node.loc.expression + if compound_expectations?(node) + add_offense(expression, message: message_compound) do |corrector| + autocorrect_compound(corrector, node) + end + else + add_offense(expression) do |corrector| + autocorrect(corrector, node) + end + end + end + + def compound_expectations?(node) + %i[and or & |].include?(node.parent.method_name) + end + + def autocorrect(corrector, node) + corrector.replace(node.parent.loc.selector, 'not_to') + range = node.loc.dot.with(end_pos: node.loc.expression.end_pos) + corrector.remove(range) + end + + def autocorrect_compound(corrector, node) + return unless negated_matcher + + change_nodes(node) do |change_node| + corrector.replace(change_node.loc.selector, negated_matcher) + range = node.loc.dot.with(end_pos: node.loc.expression.end_pos) + corrector.remove(range) + end + end + + def negated_matcher + cop_config['NegatedMatcher'] + end + + def message_compound + format(MSG_COMPOUND, preferred: preferred_method) + end + + def preferred_method + negated_matcher ? "`#{negated_matcher}`" : 'negated matchers' + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/class_check.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/class_check.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/class_check.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/class_check.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Enforces consistent use of `be_a` or `be_kind_of`. + # + # @example EnforcedStyle: be_a (default) + # # bad + # expect(object).to be_kind_of(String) + # expect(object).to be_a_kind_of(String) + # + # # good + # expect(object).to be_a(String) + # expect(object).to be_an(String) + # + # @example EnforcedStyle: be_kind_of + # # bad + # expect(object).to be_a(String) + # expect(object).to be_an(String) + # + # # good + # expect(object).to be_kind_of(String) + # expect(object).to be_a_kind_of(String) + # + class ClassCheck < Base + extend AutoCorrector + include ConfigurableEnforcedStyle + + MSG = 'Prefer `%s` over `%s`.' + + METHOD_NAMES_FOR_BE_A = ::Set[ + :be_a, + :be_an + ].freeze + + METHOD_NAMES_FOR_KIND_OF = ::Set[ + :be_a_kind_of, + :be_kind_of + ].freeze + + PREFERRED_METHOD_NAME_BY_STYLE = { + be_a: :be_a, + be_kind_of: :be_kind_of + }.freeze + + RESTRICT_ON_SEND = %i[ + be_a + be_a_kind_of + be_an + be_kind_of + ].freeze + + def on_send(node) + return unless offending?(node) + + add_offense( + node.loc.selector, + message: format_message(node) + ) do |corrector| + autocorrect(corrector, node) + end + end + + private + + def autocorrect(corrector, node) + corrector.replace(node.loc.selector, preferred_method_name) + end + + def format_message(node) + format( + MSG, + current: node.method_name, + preferred: preferred_method_name + ) + end + + def offending?(node) + !node.receiver && !preferred_method_name?(node.method_name) + end + + def preferred_method_name?(method_name) + preferred_method_names.include?(method_name) + end + + def preferred_method_name + PREFERRED_METHOD_NAME_BY_STYLE[style] + end + + def preferred_method_names + if style == :be_a + METHOD_NAMES_FOR_BE_A + else + METHOD_NAMES_FOR_KIND_OF + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/context_method.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/context_method.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/context_method.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/context_method.rb 2022-12-13 09:15:42.000000000 +0000 @@ -23,16 +23,18 @@ # describe '.foo_bar' do # # ... # end - class ContextMethod < Cop + # + class ContextMethod < Base extend AutoCorrector MSG = 'Use `describe` for testing methods.' + # @!method context_method(node) def_node_matcher :context_method, <<-PATTERN - (block (send #{RSPEC} :context $(str #method_name?) ...) ...) + (block (send #rspec? :context $(str #method_name?) ...) ...) PATTERN - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler context_method(node) do |context| add_offense(context) do |corrector| corrector.replace(node.send_node.loc.selector, 'describe') diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/context_wording.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/context_wording.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/context_wording.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/context_wording.rb 2022-12-13 09:15:42.000000000 +0000 @@ -8,12 +8,12 @@ # 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`. + # They may consist of multiple words if desired. # # @see https://rspec.rubystyle.guide/#context-descriptions # @see http://www.betterspecs.org/#contexts # # @example `Prefixes` configuration - # # # .rubocop.yml # # RSpec/ContextWording: # # Prefixes: @@ -34,36 +34,75 @@ # context 'when the display name is not present' do # # ... # end - class ContextWording < Cop - MSG = 'Start context description with %s.' + # + # This cop can be customized allowed context description pattern + # with `AllowedPatterns`. By default, there are no checking by pattern. + # + # @example `AllowedPatterns` configuration + # + # # .rubocop.yml + # # RSpec/ContextWording: + # # AllowedPatterns: + # # - とき$ + # + # @example + # # bad + # context '条件を満たす' do + # # ... + # end + # + # # good + # context '条件を満たすとき' do + # # ... + # end + # + class ContextWording < Base + include AllowedPattern + + MSG = 'Context description should match %s.' + # @!method context_wording(node) def_node_matcher :context_wording, <<-PATTERN - (block (send #{RSPEC} { :context :shared_context } $(str #bad_prefix?) ...) ...) + (block (send #rspec? { :context :shared_context } $(str $_) ...) ...) PATTERN - def on_block(node) - context_wording(node) do |context| - add_offense(context, - message: format(MSG, prefixes: joined_prefixes)) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler + context_wording(node) do |context, description| + if bad_pattern?(description) + message = format(MSG, patterns: expect_patterns) + add_offense(context, message: message) + end end end private - def bad_prefix?(description) - !prefixes.include?(description.split.first) + def allowed_patterns + super + prefix_regexes end - def joined_prefixes - quoted = prefixes.map { |prefix| "'#{prefix}'" } - return quoted.first if quoted.size == 1 + def prefix_regexes + @prefix_regexes ||= prefixes.map { |pre| /^#{Regexp.escape(pre)}\b/ } + end + + def bad_pattern?(description) + return false if allowed_patterns.empty? + + !matches_allowed_pattern?(description) + end + + def expect_patterns + inspected = allowed_patterns.map do |pattern| + pattern.inspect.gsub(/\A"|"\z/, '/') + end + return inspected.first if inspected.size == 1 - quoted << "or #{quoted.pop}" - quoted.join(', ') + inspected << "or #{inspected.pop}" + inspected.join(', ') end def prefixes - cop_config['Prefixes'] || [] + Array(cop_config.fetch('Prefixes', [])) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/cop.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/cop.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/cop.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/cop.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -# 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 diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_class.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/describe_class.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_class.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/describe_class.rb 2022-12-13 09:15:42.000000000 +0000 @@ -3,7 +3,19 @@ module RuboCop module Cop module RSpec - # Check that the first argument to the top level describe is a constant. + # Check that the first argument to the top-level describe is a constant. + # + # It can be configured to ignore strings when certain metadata is passed. + # + # Ignores Rails and Aruba `type` metadata by default. + # + # @example `IgnoredMetadata` configuration + # # .rubocop.yml + # # RSpec/DescribeClass: + # # IgnoredMetadata: + # # type: + # # - request + # # - controller # # @example # # bad @@ -21,50 +33,51 @@ # # describe "A feature example", type: :feature do # end - class DescribeClass < Cop - include RuboCop::RSpec::TopLevelDescribe + # + class DescribeClass < Base + include TopLevelGroup - MSG = 'The first argument to describe should be '\ + 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) - } + # @!method example_group_with_ignored_metadata?(node) + def_node_matcher :example_group_with_ignored_metadata?, <<~PATTERN + (send #rspec? :describe ... (hash <#ignored_metadata? ...>)) PATTERN - def_node_matcher :describe_with_rails_metadata?, <<-PATTERN - (send #{RSPEC} :describe !const ... - (hash <#rails_metadata? ...>) - ) + # @!method not_a_const_described(node) + def_node_matcher :not_a_const_described, <<~PATTERN + (send #rspec? :describe $[!const !#string_constant?] ...) PATTERN - def_node_matcher :rails_metadata?, <<-PATTERN - (pair - (sym :type) - (sym { - :channel :controller :helper :job :mailer :model :request - :routing :view :feature :system :mailbox - } - ) - ) + # @!method sym_pair(node) + def_node_matcher :sym_pair, <<~PATTERN + (pair $sym $sym) 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) + def on_top_level_group(node) + return if example_group_with_ignored_metadata?(node.send_node) - add_offense(described_value) + not_a_const_described(node.send_node) do |described| + add_offense(described) + end end private - def string_constant_describe?(described_value) - described_value.str_type? && - described_value.value =~ /^((::)?[A-Z]\w*)+$/ + def ignored_metadata?(node) + sym_pair(node) do |key, value| + ignored_metadata[key.value.to_s].to_a.include?(value.value.to_s) + end + end + + def string_constant?(described) + described.str_type? && + described.value.match?(/^(?:(?:::)?[A-Z]\w*)+$/) + end + + def ignored_metadata + cop_config['IgnoredMetadata'] || {} end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/described_class_module_wrapping.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/described_class_module_wrapping.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/described_class_module_wrapping.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/described_class_module_wrapping.rb 2022-12-13 09:15:42.000000000 +0000 @@ -18,12 +18,12 @@ # # ... # end # - # @see https://github.com/rubocop-hq/rubocop-rspec/issues/735 - class DescribedClassModuleWrapping < Cop + # @see https://github.com/rubocop/rubocop-rspec/issues/735 + class DescribedClassModuleWrapping < Base MSG = 'Avoid opening modules and defining specs within them.' - def_node_search :find_rspec_blocks, - ExampleGroups::ALL.block_pattern + # @!method find_rspec_blocks(node) + def_node_search :find_rspec_blocks, block_pattern('#ExampleGroups.all') def on_module(node) find_rspec_blocks(node) do diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/described_class.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/described_class.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/described_class.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/described_class.rb 2022-12-13 09:15:42.000000000 +0000 @@ -11,7 +11,7 @@ # This cop can be configured using the `EnforcedStyle` and `SkipBlocks` # options. # - # @example `EnforcedStyle: described_class` + # @example `EnforcedStyle: described_class` (default) # # bad # describe MyClass do # subject { MyClass.do_something } @@ -54,31 +54,35 @@ # end # end # - class DescribedClass < Cop + class DescribedClass < Base extend AutoCorrector include ConfigurableEnforcedStyle + include Namespace DESCRIBED_CLASS = 'described_class' MSG = 'Use `%s` instead of `%s`.' + # @!method common_instance_exec_closure?(node) 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 + # @!method rspec_block?(node) + def_node_matcher :rspec_block?, block_pattern('#ALL.all') + # @!method scope_changing_syntax?(node) def_node_matcher :scope_changing_syntax?, '{def class module}' + # @!method described_constant(node) def_node_matcher :described_constant, <<-PATTERN (block (send _ :describe $(const ...) ...) (args) $_) PATTERN - def_node_search :contains_described_class?, <<-PATTERN - (send nil? :described_class) - PATTERN + # @!method contains_described_class?(node) + def_node_search :contains_described_class?, + '(send nil? :described_class)' - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler # In case the explicit style is used, we need to remember what's # being described. @described_class, body = described_constant(node) @@ -125,29 +129,26 @@ end def scope_change?(node) - scope_changing_syntax?(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'] + node.block_type? && !rspec_block?(node) && cop_config['SkipBlocks'] end def offensive?(node) if style == :described_class offensive_described_class?(node) else - node.send_type? && node.method_name == :described_class + node.send_type? && node.method?(: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) @@ -160,7 +161,8 @@ end def full_const_name(node) - collapse_namespace(namespace(node), const_name(node)) + symbolized_namespace = namespace(node).map(&:to_sym) + collapse_namespace(symbolized_namespace, const_name(node)) end # @param namespace [Array] @@ -168,14 +170,13 @@ # @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] + # 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? + return const if namespace.empty? || const.first.nil? start = [0, (namespace.length - const.length)].max max = namespace.length @@ -192,29 +193,15 @@ # 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 + namespace, name = *node # rubocop:disable InternalAffairs/NodeDestructuring if !namespace [name] elsif namespace.const_type? [*const_name(namespace), name] - elsif namespace.lvar_type? || namespace.cbase_type? + elsif %i[lvar cbase send].include?(namespace.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 diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_method.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/describe_method.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_method.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/describe_method.rb 2022-12-13 09:15:42.000000000 +0000 @@ -16,17 +16,27 @@ # # describe MyClass, '.my_class_method' do # end - class DescribeMethod < Cop - include RuboCop::RSpec::TopLevelDescribe + # + class DescribeMethod < Base + include TopLevelGroup - MSG = 'The second argument to describe should be the method '\ + MSG = 'The second argument to describe should be the method ' \ "being tested. '#instance' or '.class'." - def on_top_level_describe(_node, (_, second_arg)) - return unless second_arg&.str_type? - return if second_arg.str_content.start_with?('#', '.') + # @!method second_argument(node) + def_node_matcher :second_argument, <<~PATTERN + (block + (send #rspec? :describe _first_argument $(str _) ...) ... + ) + PATTERN + + def on_top_level_group(node) + second_argument = second_argument(node) + + return unless second_argument + return if second_argument.str_content.start_with?('#', '.') - add_offense(second_arg) + add_offense(second_argument) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_symbol.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/describe_symbol.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/describe_symbol.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/describe_symbol.rb 2022-12-13 09:15:42.000000000 +0000 @@ -17,11 +17,13 @@ # end # # @see https://github.com/rspec/rspec-core/issues/1610 - class DescribeSymbol < Cop + class DescribeSymbol < Base MSG = 'Avoid describing symbols.' + RESTRICT_ON_SEND = %i[describe].freeze + # @!method describe_symbol?(node) def_node_matcher :describe_symbol?, <<-PATTERN - (send #{RSPEC} :describe $sym ...) + (send #rspec? :describe $sym ...) PATTERN def on_send(node) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/dialect.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/dialect.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/dialect.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/dialect.rb 2022-12-13 09:15:42.000000000 +0000 @@ -3,7 +3,7 @@ module RuboCop module Cop module RSpec - # This cop enforces custom RSpec dialects. + # Enforces custom RSpec dialects. # # A dialect can be based on the following RSpec methods: # @@ -41,13 +41,15 @@ # describe 'display name presence' do # # ... # end - class Dialect < Cop + # + class Dialect < Base extend AutoCorrector include MethodPreference MSG = 'Prefer `%s` over `%s`.' - def_node_matcher :rspec_method?, ALL.send_pattern + # @!method rspec_method?(node) + def_node_matcher :rspec_method?, send_pattern('#ALL.all') def on_send(node) return unless rspec_method?(node) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/duplicated_metadata.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/duplicated_metadata.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/duplicated_metadata.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/duplicated_metadata.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Avoid duplicated metadata. + # + # @example + # # bad + # describe 'Something', :a, :a + # + # # good + # describe 'Something', :a + class DuplicatedMetadata < Base + extend AutoCorrector + + include Metadata + include RangeHelp + + MSG = 'Avoid duplicated metadata.' + + def on_metadata(symbols, _pairs) + symbols.each do |symbol| + on_metadata_symbol(symbol) + end + end + + private + + def on_metadata_symbol(node) + return unless duplicated?(node) + + add_offense(node) do |corrector| + autocorrect(corrector, node) + end + end + + def autocorrect(corrector, node) + corrector.remove( + range_with_surrounding_comma( + range_with_surrounding_space( + node.location.expression, + side: :left + ), + :left + ) + ) + end + + def duplicated?(node) + node.left_siblings.any? do |sibling| + sibling.eql?(node) + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_example_group.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_example_group.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_example_group.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_example_group.rb 2022-12-13 09:15:42.000000000 +0000 @@ -5,10 +5,7 @@ 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) } @@ -33,56 +30,153 @@ # 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 + # # good # 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 + # pending 'will add tests later' # end # - class EmptyExampleGroup < Cop + class EmptyExampleGroup < Base + extend AutoCorrector + + include RangeHelp + MSG = 'Empty example group detected.' - def_node_search :contains_example?, <<-PATTERN + # @!method example_group_body(node) + # Match example group blocks and yield their body + # + # @example source that matches + # describe 'example group' do + # it { is_expected.to be } + # end + # + # @param node [RuboCop::AST::Node] + # @yield [RuboCop::AST::Node] example group body + def_node_matcher :example_group_body, <<~PATTERN + (block #{send_pattern('#ExampleGroups.all')} args $_) + PATTERN + + # @!method example_or_group_or_include?(node) + # Match examples, example groups and includes + # + # @example source that matches + # it { is_expected.to fly } + # describe('non-empty example groups too') { } + # it_behaves_like 'an animal' + # it_behaves_like('a cat') { let(:food) { 'milk' } } + # it_has_root_access + # skip + # it 'will be implemented later' + # + # @param node [RuboCop::AST::Node] + # @return [Array] matching nodes + def_node_matcher :example_or_group_or_include?, <<~PATTERN { - #{(Examples::ALL + Includes::ALL).send_pattern} - (send _ #custom_include? ...) + #{block_pattern( + '{#Examples.all #ExampleGroups.all #Includes.all}' + )} + #{send_pattern('{#Examples.all #Includes.all}')} } PATTERN - def on_block(node) - return unless example_group?(node) && !contains_example?(node) + # @!method examples_inside_block?(node) + # Match examples defined inside a block which is not a hook + # + # @example source that matches + # %w(r g b).each do |color| + # it { is_expected.to have_color(color) } + # end + # + # @example source that does not match + # before do + # it { is_expected.to fall_into_oblivion } + # end + # + # @param node [RuboCop::AST::Node] + # @return [Array] matching nodes + def_node_matcher :examples_inside_block?, <<~PATTERN + (block !#{send_pattern('#Hooks.all')} _ #examples?) + PATTERN + + # @!method examples_directly_or_in_block?(node) + # Match examples or examples inside blocks + # + # @example source that matches + # it { expect(drink).to be_cold } + # context('when winter') { it { expect(drink).to be_hot } } + # (1..5).each { |divisor| it { is_expected.to divide_by(divisor) } } + # + # @param node [RuboCop::AST::Node] + # @return [Array] matching nodes + def_node_matcher :examples_directly_or_in_block?, <<~PATTERN + { + #example_or_group_or_include? + #examples_inside_block? + } + PATTERN - add_offense(node.send_node) + # @!method examples?(node) + # Matches examples defined in scopes where they could run + # + # @example source that matches + # it { expect(myself).to be_run } + # describe { it { i_run_as_well } } + # + # @example source that does not match + # before { it { whatever here won't run anyway } } + # + # @param node [RuboCop::AST::Node] + # @return [Array] matching nodes + def_node_matcher :examples?, <<~PATTERN + { + #examples_directly_or_in_block? + (begin <#examples_directly_or_in_block? ...>) + } + PATTERN + + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler + return if node.each_ancestor(:def, :defs).any? + return if node.each_ancestor(:block).any? { |block| example?(block) } + + example_group_body(node) do |body| + next unless offensive?(body) + + add_offense(node.send_node) do |corrector| + corrector.remove(removed_range(node)) + end + end end private - def custom_include?(method_name) - custom_include_methods.include?(method_name) + def offensive?(body) + return true unless body + return false if conditionals_with_examples?(body) + + if body.if_type? || body.case_type? + !examples_in_branches?(body) + else + !examples?(body) + end + end + + def conditionals_with_examples?(body) + return unless body.begin_type? || body.case_type? + + body.each_descendant(:if, :case).any? do |condition_node| + examples_in_branches?(condition_node) + end + end + + def examples_in_branches?(condition_node) + condition_node.branches.any? { |branch| examples?(branch) } end - def custom_include_methods - cop_config - .fetch('CustomIncludeMethods', []) - .map(&:to_sym) + def removed_range(node) + range_by_whole_lines( + node.location.expression, + include_final_newline: true + ) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_hook.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_hook.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_hook.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_hook.rb 2022-12-13 09:15:42.000000000 +0000 @@ -22,21 +22,24 @@ # create_feed # end # after(:all) { cleanup_feed } - class EmptyHook < Cop + # + class EmptyHook < Base extend AutoCorrector include RuboCop::Cop::RangeHelp MSG = 'Empty hook detected.' + # @!method empty_hook?(node) def_node_matcher :empty_hook?, <<~PATTERN - (block $#{Hooks::ALL.send_pattern} _ nil?) + (block $#{send_pattern('#Hooks.all')} _ nil?) PATTERN - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler empty_hook?(node) do |hook| add_offense(hook) do |corrector| - range = range_with_surrounding_space(range: node.loc.expression) - corrector.remove(range) + corrector.remove( + range_with_surrounding_space(node.loc.expression, side: :left) + ) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_example_group.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_example_group.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_example_group.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_example_group.rb 2022-12-13 09:15:42.000000000 +0000 @@ -23,21 +23,17 @@ # end # end # - class EmptyLineAfterExampleGroup < Cop + class EmptyLineAfterExampleGroup < Base extend AutoCorrector - include RuboCop::RSpec::BlankLineSeparation + include EmptyLineSeparation MSG = 'Add an empty line after `%s`.' - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler 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 + missing_separating_line_offense(node) do |method| + format(MSG, example_group: method) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_example.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_example.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_example.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_example.rb 2022-12-13 09:15:42.000000000 +0000 @@ -30,7 +30,6 @@ # end # # @example with AllowConsecutiveOneLiners configuration - # # # rubocop.yml # # RSpec/EmptyLineAfterExample: # # AllowConsecutiveOneLiners: false @@ -41,25 +40,23 @@ # it { two } # end # - class EmptyLineAfterExample < Cop + class EmptyLineAfterExample < Base extend AutoCorrector - include RuboCop::RSpec::BlankLineSeparation + include EmptyLineSeparation MSG = 'Add an empty line after `%s`.' - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler 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 + missing_separating_line_offense(node) do |method| + format(MSG, example: method) end end + private + def allowed_one_liner?(node) consecutive_one_liner?(node) && allow_consecutive_one_liners? end @@ -69,19 +66,15 @@ end def consecutive_one_liner?(node) - node.line_count == 1 && next_one_line_example?(node) + node.single_line? && next_one_line_example?(node) end def next_one_line_example?(node) - next_sibling = next_sibling(node) + next_sibling = node.right_sibling 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] + next_sibling.single_line? end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_final_let.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_final_let.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_final_let.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_final_let.rb 2022-12-13 09:15:42.000000000 +0000 @@ -16,24 +16,22 @@ # let(:something) { other } # # it { does_something } - class EmptyLineAfterFinalLet < Cop + # + class EmptyLineAfterFinalLet < Base extend AutoCorrector - include RuboCop::RSpec::BlankLineSeparation + include EmptyLineSeparation - MSG = 'Add an empty line after the last `let` block.' + MSG = 'Add an empty line after the last `%s`.' - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless example_group_with_body?(node) - latest_let = node.body.child_nodes.select { |child| let?(child) }.last + final_let = node.body.child_nodes.reverse.find { |child| let?(child) } - return if latest_let.nil? - return if last_child?(latest_let) + return if final_let.nil? - missing_separating_line(latest_let) do |location| - add_offense(location) do |corrector| - corrector.insert_after(location.end, "\n") - end + missing_separating_line_offense(final_let) do |method| + format(MSG, let: method) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_hook.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_hook.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_hook.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_hook.rb 2022-12-13 09:15:42.000000000 +0000 @@ -5,6 +5,9 @@ module RSpec # Checks if there is an empty line after hook blocks. # + # `AllowConsecutiveOneLiners` configures whether adjacent + # one-line definitions are considered an offense. + # # @example # # bad # before { do_something } @@ -19,11 +22,23 @@ # it { does_something } # # # good - # before { do_something } + # after { do_something } # # it { does_something } # - # # good + # # fair - it's ok to have non-separated one-liners hooks + # around { |test| test.run } + # after { do_something } + # + # it { does_something } + # + # @example with AllowConsecutiveOneLiners configuration + # # rubocop.yml + # # RSpec/EmptyLineAfterHook: + # # AllowConsecutiveOneLiners: false + # + # # bad + # around { |test| test.run } # after { do_something } # # it { does_something } @@ -31,25 +46,36 @@ # # good # around { |test| test.run } # + # after { do_something } + # # it { does_something } # - class EmptyLineAfterHook < Cop + class EmptyLineAfterHook < Base extend AutoCorrector - include RuboCop::RSpec::BlankLineSeparation + include ConfigurableEnforcedStyle + include EmptyLineSeparation MSG = 'Add an empty line after `%s`.' def on_block(node) return unless hook?(node) - return if last_child?(node) + return if cop_config['AllowConsecutiveOneLiners'] && + chained_single_line_hooks?(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 + missing_separating_line_offense(node) do |method| + format(MSG, hook: method) end end + + alias on_numblock on_block + + private + + def chained_single_line_hooks?(node) + next_node = node.right_sibling + + hook?(next_node) && node.single_line? && next_node.single_line? + end end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_subject.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_subject.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/empty_line_after_subject.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/empty_line_after_subject.rb 2022-12-13 09:15:42.000000000 +0000 @@ -14,28 +14,20 @@ # subject(:obj) { described_class } # # let(:foo) { bar } - class EmptyLineAfterSubject < Cop + # + class EmptyLineAfterSubject < Base 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) + include EmptyLineSeparation + include InsideExampleGroup - missing_separating_line(node) do |location| - add_offense(location) do |corrector| - corrector.insert_after(location.end, "\n") - end - end - end + MSG = 'Add an empty line after `%s`.' - private + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler + return unless subject?(node) + return unless inside_example_group?(node) - def in_spec_block?(node) - node.each_ancestor(:block).any? do |ancestor| - Examples::ALL.include?(ancestor.method_name) + missing_separating_line_offense(node) do |method| + format(MSG, subject: method) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_length.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/example_length.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_length.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/example_length.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,7 +6,7 @@ # 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 + # extracting out some behavior, e.g. with a `let` block, or a helper # method. # # @example @@ -25,29 +25,44 @@ # result = service.call # expect(result).to be(true) # end - class ExampleLength < Cop + # + # You can set literals you want to fold with `CountAsOne`. + # Available are: 'array', 'hash', and 'heredoc'. Each literal + # will be counted as one line regardless of its actual size. + # + # @example CountAsOne: ['array', 'heredoc'] + # + # it do + # array = [ # +1 + # 1, + # 2 + # ] + # + # hash = { # +3 + # key: 'value' + # } + # + # msg = <<~HEREDOC # +1 + # Heredoc + # content. + # HEREDOC + # end # 5 points + # + class ExampleLength < Base include CodeLength - MSG = 'Example has too many lines [%d/%d].' + LABEL = 'Example' - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless example?(node) - length = code_length(node) - - return unless length > max_length - - add_offense(node, message: message(length)) + check_code_length(node) 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) + def cop_label + LABEL end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_without_description.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/example_without_description.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_without_description.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/example_without_description.rb 2022-12-13 09:15:42.000000000 +0000 @@ -14,7 +14,7 @@ # # This cop can be configured using the `EnforcedStyle` option # - # @example `EnforcedStyle: always_allow` + # @example `EnforcedStyle: always_allow` (default) # # bad # it('') { is_expected.to be_good } # it '' do @@ -47,16 +47,18 @@ # result = service.call # expect(result).to be(true) # end - class ExampleWithoutDescription < Cop + # + class ExampleWithoutDescription < Base include ConfigurableEnforcedStyle MSG_DEFAULT_ARGUMENT = 'Omit the argument when you want to ' \ 'have auto-generated description.' MSG_ADD_DESCRIPTION = 'Add a description.' + # @!method example_description(node) def_node_matcher :example_description, '(send nil? _ $(str $_))' - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless example?(node) check_example_without_description(node.send_node) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_wording.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/example_wording.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/example_wording.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/example_wording.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,12 +6,17 @@ # Checks for common mistakes in example descriptions. # # This cop will correct docstrings that begin with 'should' and 'it'. + # This cop will also look for insufficient examples and call them out. # # @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). # + # Use the DisallowedExamples setting to prevent unclear or insufficient + # descriptions. Please note that this config will not be treated as + # case sensitive. + # # @example # # bad # it 'should find nothing' do @@ -29,15 +34,27 @@ # # good # it 'does things' do # end - class ExampleWording < Cop + # + # @example `DisallowedExamples: ['works']` (default) + # # bad + # it 'works' do + # end + # + # # good + # it 'marks the task as done' do + # end + class ExampleWording < Base extend AutoCorrector MSG_SHOULD = 'Do not use should when describing your tests.' MSG_IT = "Do not repeat 'it' when describing your tests." + MSG_INSUFFICIENT_DESCRIPTION = 'Your example description is ' \ + 'insufficient.' SHOULD_PREFIX = /\Ashould(?:n't)?\b/i.freeze IT_PREFIX = /\Ait /i.freeze + # @!method it_description(node) def_node_matcher :it_description, <<-PATTERN (block (send _ :it ${ (str $_) @@ -45,12 +62,15 @@ } ...) ...) PATTERN - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler it_description(node) do |description_node, message| - if message =~ SHOULD_PREFIX + if message.match?(SHOULD_PREFIX) add_wording_offense(description_node, MSG_SHOULD) - elsif message =~ IT_PREFIX + elsif message.match?(IT_PREFIX) add_wording_offense(description_node, MSG_IT) + elsif insufficient_docstring?(description_node) + add_offense(docstring(description_node), + message: MSG_INSUFFICIENT_DESCRIPTION) end end end @@ -59,7 +79,10 @@ def add_wording_offense(node, message) docstring = docstring(node) + add_offense(docstring, message: message) do |corrector| + next if node.heredoc? + corrector.replace(docstring, replacement_text(node)) end end @@ -77,7 +100,7 @@ def replacement_text(node) text = text(node) - if text =~ SHOULD_PREFIX + if text.match?(SHOULD_PREFIX) RuboCop::RSpec::Wording.new( text, ignore: ignored_words, @@ -108,6 +131,19 @@ def ignored_words cop_config.fetch('IgnoredWords', []) end + + def insufficient_docstring?(description_node) + insufficient_examples.include?(preprocess(text(description_node))) + end + + def insufficient_examples + examples = cop_config.fetch('DisallowedExamples', []) + examples.map! { |example| preprocess(example) } + end + + def preprocess(message) + message.strip.squeeze(' ').downcase + end end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Checks for excessive whitespace in example descriptions. + # + # @example + # # bad + # it ' has excessive spacing ' do + # end + # + # # good + # it 'has excessive spacing' do + # end + # + # @example + # # bad + # context ' when a condition is met ' do + # end + # + # # good + # context 'when a condition is met' do + # end + # + class ExcessiveDocstringSpacing < Base + extend AutoCorrector + + MSG = 'Excessive whitespace.' + + # @!method example_description(node) + def_node_matcher :example_description, <<-PATTERN + (send _ {#Examples.all #ExampleGroups.all} ${ + $str + $(dstr ({str dstr `sym} ...) ...) + } ...) + PATTERN + + def on_send(node) + example_description(node) do |description_node, message| + return if description_node.heredoc? + + text = text(message) + + return unless excessive_whitespace?(text) + + add_whitespace_offense(description_node, text) + end + end + + private + + # @param text [String] + def excessive_whitespace?(text) + return true if text.start_with?(' ') || text.end_with?(' ') + + text.match?(/[^\n ] +[^ ]/) + end + + # @param text [String] + def strip_excessive_whitespace(text) + text.strip.gsub(/ +/, ' ') + end + + # @param node [RuboCop::AST::Node] + # @param text [String] + def add_whitespace_offense(node, text) + docstring = docstring(node) + corrected = strip_excessive_whitespace(text) + + add_offense(docstring) do |corrector| + corrector.replace(docstring, corrected) + 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 + + # 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, :sym + node.value + when :begin + node.source + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_actual.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_actual.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_actual.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_actual.rb 2022-12-13 09:15:42.000000000 +0000 @@ -5,6 +5,8 @@ module RSpec # Checks for `expect(...)` calls containing literal values. # + # Autocorrection is performed when the expected is not a literal. + # # @example # # bad # expect(5).to eq(price) @@ -16,11 +18,16 @@ # expect(pattern).to eq(/foo/) # expect(name).to eq("John") # - class ExpectActual < Cop + # # bad (not supported autocorrection) + # expect(false).to eq(true) + # + class ExpectActual < Base extend AutoCorrector MSG = 'Provide the actual you are testing to `expect(...)`.' + RESTRICT_ON_SEND = Runners.all + SIMPLE_LITERALS = %i[ true false @@ -45,10 +52,11 @@ SUPPORTED_MATCHERS = %i[eq eql equal be].freeze + # @!method expect_literal(node) def_node_matcher :expect_literal, <<~PATTERN (send (send nil? :expect $#literal?) - #{Runners::ALL.node_pattern_union} + #Runners.all { (send (send nil? $:be) :== $_) (send nil? $_ $_ ...) @@ -60,6 +68,7 @@ expect_literal(node) do |actual, matcher, expected| add_offense(actual.source_range) do |corrector| next unless SUPPORTED_MATCHERS.include?(matcher) + next if literal?(expected) swap(corrector, actual, expected) end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_change.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_change.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_change.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_change.rb 2022-12-13 09:15:42.000000000 +0000 @@ -10,14 +10,7 @@ # # 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` + # @example `EnforcedStyle: method_call` (default) # # bad # expect { run }.to change { Foo.bar } # expect { run }.to change { foo.baz } @@ -29,22 +22,38 @@ # expect { run }.to change { Foo.bar(:count) } # expect { run }.to change { user.reload.name } # - class ExpectChange < Cop + # @example `EnforcedStyle: block` + # # bad + # expect { run }.to change(Foo, :bar) + # + # # good + # expect { run }.to change { Foo.bar } + # + class ExpectChange < Base extend AutoCorrector include ConfigurableEnforcedStyle MSG_BLOCK = 'Prefer `change(%s, :%s)`.' MSG_CALL = 'Prefer `change { %s.%s }`.' + RESTRICT_ON_SEND = %i[change].freeze + # @!method expect_change_with_arguments(node) def_node_matcher :expect_change_with_arguments, <<-PATTERN - (send nil? :change ({const send} nil? $_) (sym $_)) + (send nil? :change $_ ({sym str} $_)) PATTERN + # @!method expect_change_with_block(node) def_node_matcher :expect_change_with_block, <<-PATTERN (block (send nil? :change) (args) - (send ({const send} nil? $_) $_) + (send + ${ + (send nil? _) # change { user.name } + const # change { User.count } + } + $_ + ) ) PATTERN @@ -52,21 +61,21 @@ return unless style == :block expect_change_with_arguments(node) do |receiver, message| - msg = format(MSG_CALL, obj: receiver, attr: message) + msg = format(MSG_CALL, obj: receiver.source, attr: message) add_offense(node, message: msg) do |corrector| - replacement = "change { #{receiver}.#{message} }" + replacement = "change { #{receiver.source}.#{message} }" corrector.replace(node, replacement) end end end - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless style == :method_call expect_change_with_block(node) do |receiver, message| - msg = format(MSG_BLOCK, obj: receiver, attr: message) + msg = format(MSG_BLOCK, obj: receiver.source, attr: message) add_offense(node, message: msg) do |corrector| - replacement = "change(#{receiver}, :#{message})" + replacement = "change(#{receiver.source}, :#{message})" corrector.replace(node, replacement) end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_in_hook.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_in_hook.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_in_hook.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_in_hook.rb 2022-12-13 09:15:42.000000000 +0000 @@ -20,12 +20,14 @@ # it do # expect(something).to eq 'foo' # end - class ExpectInHook < Cop + # + class ExpectInHook < Base MSG = 'Do not use `%s` in `%s` hook' - def_node_search :expectation, Expectations::ALL.send_pattern + # @!method expectation(node) + def_node_search :expectation, send_pattern('#Expectations.all') - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless hook?(node) return if node.body.nil? @@ -35,6 +37,8 @@ end end + alias on_numblock on_block + private def message(expect, hook) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_output.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_output.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/expect_output.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/expect_output.rb 2022-12-13 09:15:42.000000000 +0000 @@ -14,8 +14,9 @@ # # # good # expect { my_app.print_report }.to output('Hello World').to_stdout - class ExpectOutput < Cop - MSG = 'Use `expect { ... }.to output(...).to_%s` '\ + # + class ExpectOutput < Base + MSG = 'Use `expect { ... }.to output(...).to_%s` ' \ 'instead of mutating $%s.' def on_gvasgn(node) @@ -24,7 +25,7 @@ # rubocop:disable InternalAffairs/NodeDestructuring variable_name, _rhs = *node # rubocop:enable InternalAffairs/NodeDestructuring - name = variable_name[1..-1] + name = variable_name[1..] return unless name.eql?('stdout') || name.eql?('stderr') add_offense(node.loc.name, message: format(MSG, name: name)) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb 2022-12-13 09:15:42.000000000 +0000 @@ -24,22 +24,25 @@ # # # good # count { 1 } - class AttributeDefinedStatically < Cop + # + class AttributeDefinedStatically < ::RuboCop::Cop::Base extend AutoCorrector MSG = 'Use a block to declare attribute values.' + # @!method value_matcher(node) def_node_matcher :value_matcher, <<-PATTERN (send _ !#reserved_method? $...) PATTERN + # @!method factory_attributes(node) def_node_matcher :factory_attributes, <<-PATTERN (block (send _ #attribute_defining_method? ...) _ { (begin $...) $(send ...) } ) PATTERN - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler attributes = factory_attributes(node) || [] - attributes = [attributes] unless attributes.is_a?(Array) + attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective attributes.each do |attribute| next unless offensive_receiver?(attribute.receiver, node) @@ -79,12 +82,13 @@ value_matcher(attribute).to_a.all?(&:block_pass_type?) end + # @!method association?(node) 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.begin, " #{left_braces}") corrector.replace(node.location.end, right_braces) end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,117 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module FactoryBot + # Use a consistent style for parentheses in factory bot calls. + # + # @example + # + # # bad + # create :user + # build(:user) + # create(:login) + # create :login + # + # @example `EnforcedStyle: require_parentheses` (default) + # + # # good + # create(:user) + # create(:user) + # create(:login) + # build(:login) + # + # @example `EnforcedStyle: omit_parentheses` + # + # # good + # create :user + # build :user + # create :login + # create :login + # + # # also good + # # when method name and first argument are not on same line + # create( + # :user + # ) + # build( + # :user, + # name: 'foo' + # ) + # + class ConsistentParenthesesStyle < ::RuboCop::Cop::Base + extend AutoCorrector + include ConfigurableEnforcedStyle + include RuboCop::RSpec::FactoryBot::Language + include RuboCop::Cop::Util + + def self.autocorrect_incompatible_with + [Style::MethodCallWithArgsParentheses] + end + + MSG_REQUIRE_PARENS = 'Prefer method call with parentheses' + MSG_OMIT_PARENS = 'Prefer method call without parentheses' + + FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS + + RESTRICT_ON_SEND = FACTORY_CALLS + + # @!method factory_call(node) + def_node_matcher :factory_call, <<-PATTERN + (send + {#factory_bot? nil?} %FACTORY_CALLS + {sym str send lvar} _* + ) + PATTERN + + def on_send(node) + return if ambiguous_without_parentheses?(node) + + factory_call(node) do + return if node.method?(:generate) && node.arguments.count > 1 + + if node.parenthesized? + process_with_parentheses(node) + else + process_without_parentheses(node) + end + end + end + + private + + def process_with_parentheses(node) + return unless style == :omit_parentheses + return unless same_line?(node, node.first_argument) + + add_offense(node.loc.selector, + message: MSG_OMIT_PARENS) do |corrector| + remove_parentheses(corrector, node) + end + end + + def process_without_parentheses(node) + return unless style == :require_parentheses + + add_offense(node.loc.selector, + message: MSG_REQUIRE_PARENS) do |corrector| + add_parentheses(node, corrector) + end + end + + def ambiguous_without_parentheses?(node) + node.parent&.send_type? || + node.parent&.pair_type? || + node.parent&.array_type? + end + + def remove_parentheses(corrector, node) + corrector.replace(node.location.begin, ' ') + corrector.remove(node.location.end) + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/create_list.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/create_list.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/create_list.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/create_list.rb 2022-12-13 09:15:42.000000000 +0000 @@ -8,15 +8,21 @@ # # This cop can be configured using the `EnforcedStyle` option # - # @example `EnforcedStyle: create_list` + # @example `EnforcedStyle: create_list` (default) # # bad # 3.times { create :user } # # # good # create_list :user, 3 # - # # good - # 3.times { |n| create :user, created_at: n.months.ago } + # # bad + # 3.times { create :user, age: 18 } + # + # # good - index is used to alter the created models attributes + # 3.times { |n| create :user, age: n } + # + # # good - contains a method call, may return different values + # 3.times { create :user, age: rand } # # @example `EnforcedStyle: n_times` # # bad @@ -24,32 +30,58 @@ # # # good # 3.times { create :user } - class CreateList < Cop + # + class CreateList < ::RuboCop::Cop::Base extend AutoCorrector include ConfigurableEnforcedStyle + include RuboCop::RSpec::FactoryBot::Language MSG_CREATE_LIST = 'Prefer create_list.' MSG_N_TIMES = 'Prefer %s.times.' + RESTRICT_ON_SEND = %i[create_list].freeze - def_node_matcher :n_times_block_without_arg?, <<-PATTERN + # @!method array_new_or_n_times_block?(node) + def_node_matcher :array_new_or_n_times_block?, <<-PATTERN (block - (send (int _) :times) - (args) + { + (send (const {nil? | cbase} :Array) :new (int _)) | + (send (int _) :times) + } ... ) PATTERN + # @!method block_with_arg_and_used?(node) + def_node_matcher :block_with_arg_and_used?, <<-PATTERN + (block + _ + (args (arg _value)) + `_value + ) + PATTERN + + # @!method arguments_include_method_call?(node) + def_node_matcher :arguments_include_method_call?, <<-PATTERN + (send ${nil? #factory_bot?} :create (sym $_) `$(send ...)) + PATTERN + + # @!method factory_call(node) def_node_matcher :factory_call, <<-PATTERN - (send ${(const nil? {:FactoryGirl :FactoryBot}) nil?} :create (sym $_) $...) + (send ${nil? #factory_bot?} :create (sym $_) $...) PATTERN + # @!method factory_list_call(node) def_node_matcher :factory_list_call, <<-PATTERN - (send ${(const nil? {:FactoryGirl :FactoryBot}) nil?} :create_list (sym $_) (int $_) $...) + (send {nil? #factory_bot?} :create_list (sym _) (int $_) ...) PATTERN - def on_block(node) + def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler return unless style == :create_list - return unless n_times_block_without_arg?(node) + + return unless array_new_or_n_times_block?(node) + return if block_with_arg_and_used?(node) + return unless node.body + return if arguments_include_method_call?(node.body) return unless contains_only_factory?(node.body) add_offense(node.send_node, message: MSG_CREATE_LIST) do |corrector| @@ -60,7 +92,7 @@ def on_send(node) return unless style == :n_times - factory_list_call(node) do |_receiver, _factory, count, _| + factory_list_call(node) do |count| message = format(MSG_N_TIMES, number: count) add_offense(node.loc.selector, message: message) do |corrector| TimesCorrector.new(node).call(corrector) @@ -79,7 +111,7 @@ end # :nodoc - class Corrector + module Corrector private def build_options_string(options) @@ -102,14 +134,16 @@ end # :nodoc - class TimesCorrector < Corrector + class TimesCorrector + include Corrector + def initialize(node) @node = node end def call(corrector) replacement = generate_n_times_block(node) - corrector.replace(node, replacement) + corrector.replace(node.block_node || node, replacement) end private @@ -125,12 +159,21 @@ replacement = format_receiver(node.receiver) replacement += format_method_call(node, 'create', arguments) + replacement += " #{factory_call_block_source}" if node.block_node "#{count.source}.times { #{replacement} }" end + + def factory_call_block_source + node.block_node.location.begin.with( + end_pos: node.block_node.location.end.end_pos + ).source + end end # :nodoc: - class CreateListCorrector < Corrector + class CreateListCorrector + include Corrector + def initialize(node) @node = node.parent end @@ -151,8 +194,8 @@ def call_with_block_replacement(node) block = node.body - arguments = build_arguments(block, node.receiver.source) - replacement = format_receiver(block.send_node.receiver) + arguments = build_arguments(block, count_from(node)) + replacement = format_receiver(block.receiver) replacement += format_method_call(block, 'create_list', arguments) replacement += format_block(block) replacement @@ -171,7 +214,7 @@ block = node.body factory, *options = *block.arguments - arguments = "#{factory.source}, #{node.receiver.source}" + arguments = "#{factory.source}, #{count_from(node)}" options = build_options_string(options) arguments += ", #{options}" unless options.empty? @@ -180,11 +223,21 @@ replacement end + def count_from(node) + count_node = + if node.receiver.int_type? + node.receiver + else + node.send_node.first_argument + end + count_node.source + end + def format_block(node) if node.body.begin_type? format_multiline_block(node) else - format_singeline_block(node) + format_singleline_block(node) end end @@ -192,11 +245,11 @@ indent = ' ' * node.body.loc.column indent_end = ' ' * node.parent.loc.column " do #{node.arguments.source}\n" \ - "#{indent}#{node.body.source}\n" \ - "#{indent_end}end" + "#{indent}#{node.body.source}\n" \ + "#{indent_end}end" end - def format_singeline_block(node) + def format_singleline_block(node) " { #{node.arguments.source} #{node.body.source} }" end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb 2022-12-13 09:15:42.000000000 +0000 @@ -19,13 +19,16 @@ # # good # factory :foo, class: 'Foo' do # end - class FactoryClassName < Cop + # + class FactoryClassName < ::RuboCop::Cop::Base extend AutoCorrector MSG = "Pass '%s' string instead of `%s` " \ 'constant.' ALLOWED_CONSTANTS = %w[Hash OpenStruct].freeze + RESTRICT_ON_SEND = %i[factory].freeze + # @!method class_name(node) def_node_matcher :class_name, <<~PATTERN (send _ :factory _ (hash <(pair (sym :class) $(const ...)) ...>)) PATTERN diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module FactoryBot + # Checks for name style for argument of FactoryBot::Syntax::Methods. + # + # @example EnforcedStyle: symbol (default) + # # bad + # create('user') + # build "user", username: "NAME" + # + # # good + # create(:user) + # build :user, username: "NAME" + # + # @example EnforcedStyle: string + # # bad + # create(:user) + # build :user, username: "NAME" + # + # # good + # create('user') + # build "user", username: "NAME" + # + class FactoryNameStyle < ::RuboCop::Cop::Base + extend AutoCorrector + include ConfigurableEnforcedStyle + include RuboCop::RSpec::FactoryBot::Language + + MSG = 'Use %s to refer to a factory.' + FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS + RESTRICT_ON_SEND = FACTORY_CALLS + + # @!method factory_call(node) + def_node_matcher :factory_call, <<-PATTERN + (send + {#factory_bot? nil?} %FACTORY_CALLS + ${str sym} ... + ) + PATTERN + + def on_send(node) + factory_call(node) do |name| + if offense_for_symbol_style?(name) + register_offense(name, name.value.to_sym.inspect) + elsif offense_for_string_style?(name) + register_offense(name, name.value.to_s.inspect) + end + end + end + + private + + def offense_for_symbol_style?(name) + name.str_type? && style == :symbol + end + + def offense_for_string_style?(name) + name.sym_type? && style == :string + end + + def register_offense(name, prefer) + add_offense(name, + message: format(MSG, prefer: style.to_s)) do |corrector| + corrector.replace(name, prefer) + end + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module FactoryBot + # Use shorthands from `FactoryBot::Syntax::Methods` in your specs. + # + # @safety + # The autocorrection is marked as unsafe because the cop + # cannot verify whether you already include + # `FactoryBot::Syntax::Methods` in your test suite. + # + # If you're using Rails, add the following configuration to + # `spec/support/factory_bot.rb` and be sure to require that file in + # `rails_helper.rb`: + # + # [source,ruby] + # ---- + # RSpec.configure do |config| + # config.include FactoryBot::Syntax::Methods + # end + # ---- + # + # If you're not using Rails: + # + # [source,ruby] + # ---- + # RSpec.configure do |config| + # config.include FactoryBot::Syntax::Methods + # + # config.before(:suite) do + # FactoryBot.find_definitions + # end + # end + # ---- + # + # @example + # # bad + # FactoryBot.create(:bar) + # FactoryBot.build(:bar) + # FactoryBot.attributes_for(:bar) + # + # # good + # create(:bar) + # build(:bar) + # attributes_for(:bar) + # + class SyntaxMethods < Base + extend AutoCorrector + include InsideExampleGroup + include RangeHelp + include RuboCop::RSpec::FactoryBot::Language + + MSG = 'Use `%s` from `FactoryBot::Syntax::Methods`.' + + RESTRICT_ON_SEND = RuboCop::RSpec::FactoryBot::Language::METHODS + + def on_send(node) + return unless factory_bot?(node.receiver) + return unless inside_example_group?(node) + + message = format(MSG, method: node.method_name) + + add_offense(crime_scene(node), message: message) do |corrector| + corrector.remove(offense(node)) + end + end + + private + + def crime_scene(node) + range_between( + node.loc.expression.begin_pos, + node.loc.selector.end_pos + ) + end + + def offense(node) + range_between( + node.loc.expression.begin_pos, + node.loc.selector.begin_pos + ) + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/file_path.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/file_path.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/file_path.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/file_path.rb 2022-12-13 09:15:42.000000000 +0000 @@ -56,53 +56,78 @@ # # good # my_class_spec.rb # describe MyClass, '#method' # - class FilePath < Cop - include RuboCop::RSpec::TopLevelDescribe + class FilePath < Base + include TopLevelGroup + include Namespace 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) + # @!method example_group(node) + def_node_matcher :example_group, <<~PATTERN + (block + $(send #rspec? _example_group $_ $...) ... + ) + PATTERN - glob = glob_for(args) + # @!method routing_metadata?(node) + def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))' - return if filename_ends_with?(glob) + def on_top_level_example_group(node) + return unless top_level_groups.one? - add_offense( - node, - message: format(MSG, suffix: glob) - ) + example_group(node) do |send_node, example_group, arguments| + ensure_correct_file_path(send_node, example_group, arguments) + end end private + def ensure_correct_file_path(send_node, example_group, arguments) + pattern = pattern_for(example_group, arguments) + return if filename_ends_with?(pattern) + + # For the suffix shown in the offense message, modify the regular + # expression pattern to resemble a glob pattern for clearer error + # messages. + offense_suffix = pattern.gsub('.*', '*').sub('[^/]', '') + .sub('\.', '.') + add_offense(send_node, message: format(MSG, suffix: offense_suffix)) + end + def routing_spec?(args) - args.any?(&method(:routing_metadata?)) + args.any?(&method(:routing_metadata?)) || routing_spec_path? end - def glob_for((described_class, method_name)) - return glob_for_spec_suffix_only? if spec_suffix_only? + def pattern_for(example_group, arguments) + method_name = arguments.first + if spec_suffix_only? || !example_group.const_type? || + routing_spec?(arguments) + return pattern_for_spec_suffix_only + end - "#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb" + [ + expected_path(example_group), + name_pattern(method_name), + '[^/]*_spec\.rb' + ].join end - def glob_for_spec_suffix_only? - '*_spec.rb' + def pattern_for_spec_suffix_only + '.*_spec\.rb' end - def name_glob(name) - return unless name&.str_type? + def name_pattern(method_name) + return unless method_name&.str_type? + return if ignore_methods? - "*#{name.str_content.gsub(/\W/, '')}" unless ignore_methods? + ".*#{method_name.str_content.gsub(/\s/, '_').gsub(/\W/, '')}" end def expected_path(constant) + constants = namespace(constant) + constant.const_name.split('::') + File.join( - constant.const_name.split('::').map do |name| + constants.map do |name| custom_transform.fetch(name) { camel_to_snake_case(name) } end ) @@ -123,11 +148,8 @@ cop_config['IgnoreMethods'] end - def filename_ends_with?(glob) - filename = - RuboCop::PathUtil.relative_path(processed_source.buffer.name) - .gsub('../', '') - File.fnmatch?("*#{glob}", filename) + def filename_ends_with?(pattern) + expanded_file_path.match?("#{pattern}$") end def relevant_rubocop_rspec_file?(_file) @@ -137,6 +159,14 @@ def spec_suffix_only? cop_config['SpecSuffixOnly'] end + + def routing_spec_path? + expanded_file_path.include?('spec/routing/') + end + + def expanded_file_path + File.expand_path(processed_source.buffer.name) + end end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/focus.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/focus.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/focus.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/focus.rb 2022-12-13 09:15:42.000000000 +0000 @@ -5,6 +5,8 @@ module RSpec # Checks if examples are focused. # + # This cop does not support autocorrection in some cases. + # # @example # # bad # describe MyClass, focus: true do @@ -19,30 +21,60 @@ # # good # describe MyClass do # end - class Focus < Cop - MSG = 'Focused spec found.' - - focusable = - ExampleGroups::GROUPS + - ExampleGroups::SKIPPED + - Examples::EXAMPLES + - Examples::SKIPPED + - Examples::PENDING + # + # # bad + # fdescribe 'test' do; end + # + # # good + # describe 'test' do; end + # + # # bad + # fdescribe 'test' do; end + # + # # good + # describe 'test' do; end + # + # # bad (does not support autocorrection) + # focus 'test' do; end + # + class Focus < Base + extend AutoCorrector + include RangeHelp - focused = ExampleGroups::FOCUSED + Examples::FOCUSED + MSG = 'Focused spec found.' - FOCUSABLE_SELECTORS = focusable.node_pattern_union + # @!method focusable_selector?(node) + def_node_matcher :focusable_selector?, <<-PATTERN + { + #ExampleGroups.regular + #ExampleGroups.skipped + #Examples.regular + #Examples.skipped + #Examples.pending + } + PATTERN + # @!method metadata(node) def_node_matcher :metadata, <<-PATTERN - {(send #{RSPEC} #{FOCUSABLE_SELECTORS} <$(sym :focus) ...>) - (send #{RSPEC} #{FOCUSABLE_SELECTORS} ... (hash <$(pair (sym :focus) true) ...>))} + {(send #rspec? #focusable_selector? <$(sym :focus) ...>) + (send #rspec? #focusable_selector? ... (hash <$(pair (sym :focus) true) ...>))} PATTERN - def_node_matcher :focused_block?, focused.send_pattern + # @!method focused_block?(node) + def_node_matcher :focused_block?, + send_pattern(<<~PATTERN) + {#ExampleGroups.focused #Examples.focused} + PATTERN def on_send(node) focus_metadata(node) do |focus| - add_offense(focus) + add_offense(focus) do |corrector| + if focus.pair_type? || focus.str_type? || focus.sym_type? + corrector.remove(with_surrounding(focus)) + elsif focus.send_type? + correct_send(corrector, focus) + end + end end end @@ -53,6 +85,24 @@ metadata(node, &block) end + + def with_surrounding(focus) + range_with_space = + range_with_surrounding_space(focus.loc.expression, side: :left) + + range_with_surrounding_comma(range_with_space, :left) + end + + def correct_send(corrector, focus) + range = focus.loc.selector + unfocused = focus.method_name.to_s.sub(/^f/, '') + unless Examples.regular(unfocused) || ExampleGroups.regular(unfocused) + return + end + + corrector.replace(range, + range.source.sub(focus.method_name.to_s, unfocused)) + end end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/hook_argument.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/hook_argument.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/hook_argument.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/hook_argument.rb 2022-12-13 09:15:42.000000000 +0000 @@ -10,7 +10,7 @@ # styles: "implicit", "each", and "example." All styles have # the same behavior. # - # @example when configuration is `EnforcedStyle: implicit` + # @example `EnforcedStyle: implicit` (default) # # bad # before(:each) do # # ... @@ -26,13 +26,13 @@ # # ... # end # - # @example when configuration is `EnforcedStyle: each` + # @example `EnforcedStyle: each` # # bad # before(:example) do # # ... # end # - # # good + # # bad # before do # # ... # end @@ -42,7 +42,7 @@ # # ... # end # - # @example when configuration is `EnforcedStyle: example` + # @example `EnforcedStyle: example` # # bad # before(:each) do # # ... @@ -57,21 +57,23 @@ # before(:example) do # # ... # end - class HookArgument < Cop + # + class HookArgument < Base extend AutoCorrector include ConfigurableEnforcedStyle - IMPLICIT_MSG = 'Omit the default `%p` ' \ - 'argument for RSpec hooks.' + IMPLICIT_MSG = 'Omit the default `%p` argument for RSpec hooks.' EXPLICIT_MSG = 'Use `%p` for RSpec hooks.' - HOOKS = Hooks::ALL.node_pattern_union.freeze - + # @!method scoped_hook(node) def_node_matcher :scoped_hook, <<-PATTERN - (block $(send _ #{HOOKS} (sym ${:each :example})) ...) + ({block numblock} $(send _ #Hooks.all (sym ${:each :example})) ...) PATTERN - def_node_matcher :unscoped_hook, "(block $(send _ #{HOOKS}) ...)" + # @!method unscoped_hook(node) + def_node_matcher :unscoped_hook, <<-PATTERN + ({block numblock} $(send _ #Hooks.all) ...) + PATTERN def on_block(node) hook(node) do |method_send, scope_name| @@ -87,6 +89,8 @@ end end + alias on_numblock on_block + private def check_implicit(method_send) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/hooks_before_examples.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/hooks_before_examples.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/hooks_before_examples.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/hooks_before_examples.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,8 +6,7 @@ # Checks for before/around/after hooks that come after an example. # # @example - # # Bad - # + # # bad # it 'checks what foo does' do # expect(foo).to be # end @@ -15,7 +14,7 @@ # before { prepare } # after { clean_up } # - # # Good + # # good # before { prepare } # after { clean_up } # @@ -23,15 +22,17 @@ # expect(foo).to be # end # - class HooksBeforeExamples < Cop + class HooksBeforeExamples < Base extend AutoCorrector MSG = 'Move `%s` above the examples in the group.' + # @!method example_or_group?(node) def_node_matcher :example_or_group?, <<-PATTERN { - #{(Examples::ALL + ExampleGroups::ALL).block_pattern} - #{Includes::EXAMPLES.send_pattern} + #{block_pattern('{#ExampleGroups.all #Examples.all}')} + #{numblock_pattern('{#ExampleGroups.all #Examples.all}')} + #{send_pattern('#Includes.examples')} } PATTERN @@ -41,6 +42,8 @@ check_hooks(node.body) if multiline_block?(node.body) end + alias on_numblock on_block + private def multiline_block?(block) @@ -51,13 +54,12 @@ 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) + first_example.right_siblings.each do |sibling| + next unless hook?(sibling) + + msg = format(MSG, hook: sibling.method_name) + add_offense(sibling, message: msg) do |corrector| + autocorrect(corrector, sibling, first_example) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/identical_equality_assertion.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/identical_equality_assertion.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/identical_equality_assertion.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/identical_equality_assertion.rb 2022-12-13 09:15:42.000000000 +0000 @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Checks for equality assertions with identical expressions on both sides. + # + # @example + # # bad + # expect(foo.bar).to eq(foo.bar) + # expect(foo.bar).to eql(foo.bar) + # + # # good + # expect(foo.bar).to eq(2) + # expect(foo.bar).to eql(2) + # + class IdenticalEqualityAssertion < Base + MSG = 'Identical expressions on both sides of the equality ' \ + 'may indicate a flawed test.' + RESTRICT_ON_SEND = %i[to].freeze + + # @!method equality_check?(node) + def_node_matcher :equality_check?, <<~PATTERN + (send (send nil? :expect $_) :to + {(send nil? {:eql :eq :be} $_) + (send (send nil? :be) :== $_)}) + PATTERN + + def on_send(node) + equality_check?(node) do |left, right| + add_offense(node) if left == right + end + end + end + end + end +end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_block_expectation.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/implicit_block_expectation.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_block_expectation.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/implicit_block_expectation.rb 2022-12-13 09:15:42.000000000 +0000 @@ -16,19 +16,23 @@ # it 'changes something to a new value' do # expect { do_something }.to change(something).to(new_value) # end - class ImplicitBlockExpectation < Cop + # + class ImplicitBlockExpectation < Base MSG = 'Avoid implicit block expectations.' + RESTRICT_ON_SEND = %i[is_expected should should_not].freeze + # @!method lambda?(node) def_node_matcher :lambda?, <<-PATTERN { (send (const nil? :Proc) :new) - (send nil? :proc) - (send nil? :lambda) + (send nil? {:proc :lambda}) } PATTERN + # @!method lambda_subject?(node) def_node_matcher :lambda_subject?, '(block #lambda? ...)' + # @!method implicit_expect(node) def_node_matcher :implicit_expect, <<-PATTERN $(send nil? {:is_expected :should :should_not} ...) PATTERN diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_expect.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/implicit_expect.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_expect.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/implicit_expect.rb 2022-12-13 09:15:42.000000000 +0000 @@ -8,8 +8,7 @@ # This cop can be configured using the `EnforcedStyle` option # and supports the `--auto-gen-config` flag. # - # @example `EnforcedStyle: is_expected` - # + # @example `EnforcedStyle: is_expected` (default) # # bad # it { should be_truthy } # @@ -17,23 +16,25 @@ # it { is_expected.to be_truthy } # # @example `EnforcedStyle: should` - # # # bad # it { is_expected.to be_truthy } # # # good # it { should be_truthy } # - class ImplicitExpect < Cop + class ImplicitExpect < Base extend AutoCorrector include ConfigurableEnforcedStyle MSG = 'Prefer `%s` over `%s`.' + RESTRICT_ON_SEND = Runners.all + %i[should should_not] + + # @!method implicit_expect(node) def_node_matcher :implicit_expect, <<-PATTERN { (send nil? ${:should :should_not} ...) - (send (send nil? $:is_expected) #{Runners::ALL.node_pattern_union} ...) + (send (send nil? $:is_expected) #Runners.all ...) } PATTERN diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_subject.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/implicit_subject.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/implicit_subject.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/implicit_subject.rb 2022-12-13 09:15:42.000000000 +0000 @@ -7,7 +7,7 @@ # # This cop can be configured using the `EnforcedStyle` option # - # @example `EnforcedStyle: single_line_only` + # @example `EnforcedStyle: single_line_only` (default) # # bad # it do # is_expected.to be_truthy @@ -19,6 +19,22 @@ # expect(subject).to be_truthy # end # + # @example `EnforcedStyle: single_statement_only` + # # bad + # it do + # foo = 1 + # is_expected.to be_truthy + # end + # + # # good + # it do + # foo = 1 + # expect(subject).to be_truthy + # end + # it do + # is_expected.to be_truthy + # end + # # @example `EnforcedStyle: disallow` # # bad # it { is_expected.to be_truthy } @@ -26,19 +42,53 @@ # # good # it { expect(subject).to be_truthy } # - class ImplicitSubject < Cop + # @example `EnforcedStyle: require_implicit` + # # bad + # it { expect(subject).to be_truthy } + # + # # good + # it { is_expected.to be_truthy } + # + # # bad + # it do + # expect(subject).to be_truthy + # end + # + # # good + # it do + # is_expected.to be_truthy + # end + # + # # good + # it { expect(named_subject).to be_truthy } + # + class ImplicitSubject < Base extend AutoCorrector include ConfigurableEnforcedStyle - MSG = "Don't use implicit subject." + MSG_REQUIRE_EXPLICIT = "Don't use implicit subject." + + MSG_REQUIRE_IMPLICIT = "Don't use explicit subject." + RESTRICT_ON_SEND = %i[ + expect + is_expected + should + should_not + ].freeze + + # @!method explicit_unnamed_subject?(node) + def_node_matcher :explicit_unnamed_subject?, <<-PATTERN + (send nil? :expect (send nil? :subject)) + PATTERN + + # @!method implicit_subject?(node) 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) + return unless invalid?(node) add_offense(node) do |corrector| autocorrect(corrector, node) @@ -48,30 +98,67 @@ private def autocorrect(corrector, node) - replacement = 'expect(subject)' - if node.method_name == :should - replacement += '.to' - elsif node.method_name == :should_not - replacement += '.not_to' + case node.method_name + when :expect + corrector.replace(node, 'is_expected') + when :is_expected + corrector.replace(node.location.selector, 'expect(subject)') + when :should + corrector.replace(node.location.selector, 'expect(subject).to') + when :should_not + corrector.replace(node.location.selector, 'expect(subject).not_to') end + end - corrector.replace(node.loc.selector, replacement) + def message(_node) + case style + when :require_implicit + MSG_REQUIRE_IMPLICIT + else + MSG_REQUIRE_EXPLICIT + end end - def valid_usage?(node) - example = node.ancestors.find { |parent| example?(parent) } - return false if example.nil? + def invalid?(node) + case style + when :require_implicit + explicit_unnamed_subject?(node) + when :disallow + implicit_subject_in_non_its?(node) + when :single_line_only + implicit_subject_in_non_its_and_non_single_line?(node) + when :single_statement_only + implicit_subject_in_non_its_and_non_single_statement?(node) + end + end - example.method_name == :its || allowed_by_style?(example) + def implicit_subject_in_non_its?(node) + implicit_subject?(node) && !its?(node) 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 + def implicit_subject_in_non_its_and_non_single_line?(node) + implicit_subject_in_non_its?(node) && !single_line?(node) + end + + def implicit_subject_in_non_its_and_non_single_statement?(node) + implicit_subject_in_non_its?(node) && !single_statement?(node) + end + + def its?(node) + example_of(node)&.method?(:its) + end + + def single_line?(node) + example_of(node)&.single_line? + end + + def single_statement?(node) + !example_of(node)&.body&.begin_type? + end + + def example_of(node) + node.each_ancestor.find do |ancestor| + example?(ancestor) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/instance_spy.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/instance_spy.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/instance_spy.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/instance_spy.rb 2022-12-13 09:15:42.000000000 +0000 @@ -18,12 +18,13 @@ # expect(foo).to have_received(:bar) # end # - class InstanceSpy < Cop + class InstanceSpy < Base extend AutoCorrector - MSG = 'Use `instance_spy` when you check your double '\ + MSG = 'Use `instance_spy` when you check your double ' \ 'with `have_received`.' + # @!method null_double(node) def_node_search :null_double, <<-PATTERN (lvasgn $_ (send @@ -31,6 +32,7 @@ ...) :as_null_object)) PATTERN + # @!method have_received_usage(node) def_node_search :have_received_usage, <<-PATTERN (send (send nil? :expect @@ -40,7 +42,7 @@ ...) PATTERN - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless example?(node) null_double(node) do |var, receiver| diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/instance_variable.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/instance_variable.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/instance_variable.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/instance_variable.rb 2022-12-13 09:15:42.000000000 +0000 @@ -24,7 +24,6 @@ # end # # @example with AssignmentOnly configuration - # # # rubocop.yml # # RSpec/InstanceVariable: # # AssignmentOnly: false @@ -46,16 +45,18 @@ # it { expect(foo).to be_empty } # end # - class InstanceVariable < Cop - include RuboCop::RSpec::TopLevelGroup + class InstanceVariable < Base + include TopLevelGroup MSG = 'Avoid instance variables – use let, ' \ 'a method call, or a local variable (if possible).' + # @!method dynamic_class?(node) def_node_matcher :dynamic_class?, <<-PATTERN (block (send (const nil? :Class) :new ...) ...) PATTERN + # @!method custom_matcher?(node) def_node_matcher :custom_matcher?, <<-PATTERN (block { (send nil? :matcher sym) @@ -63,8 +64,10 @@ } ...) PATTERN + # @!method ivar_usage(node) def_node_search :ivar_usage, '$(ivar $_)' + # @!method ivar_assigned?(node) def_node_search :ivar_assigned?, '(ivasgn % ...)' def on_top_level_group(node) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -# 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 diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/it_behaves_like.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/it_behaves_like.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/it_behaves_like.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/it_behaves_like.rb 2022-12-13 09:15:42.000000000 +0000 @@ -5,26 +5,29 @@ module RSpec # Checks that only one `it_behaves_like` style is used. # - # @example when configuration is `EnforcedStyle: it_behaves_like` + # @example `EnforcedStyle: it_behaves_like` (default) # # bad # it_should_behave_like 'a foo' # # # good # it_behaves_like 'a foo' # - # @example when configuration is `EnforcedStyle: it_should_behave_like` + # @example `EnforcedStyle: it_should_behave_like` # # bad # it_behaves_like 'a foo' # # # good # it_should_behave_like 'a foo' - class ItBehavesLike < Cop + # + class ItBehavesLike < Base extend AutoCorrector include ConfigurableEnforcedStyle - MSG = 'Prefer `%s` over `%s` when including '\ + MSG = 'Prefer `%s` over `%s` when including ' \ 'examples in a nested context.' + RESTRICT_ON_SEND = %i[it_behaves_like it_should_behave_like].freeze + # @!method example_inclusion_offense(node) def_node_matcher :example_inclusion_offense, '(send _ % ...)' def on_send(node) diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/iterated_expectation.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/iterated_expectation.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/iterated_expectation.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/iterated_expectation.rb 2022-12-13 09:15:42.000000000 +0000 @@ -15,10 +15,12 @@ # it 'validates users' do # expect([user1, user2, user3]).to all(be_valid) # end - class IteratedExpectation < Cop + # + class IteratedExpectation < Base MSG = 'Prefer using the `all` matcher instead ' \ - 'of iterating over an array.' + 'of iterating over an array.' + # @!method each?(node) def_node_matcher :each?, <<-PATTERN (block (send ... :each) @@ -27,6 +29,14 @@ ) PATTERN + # @!method each_numblock?(node) + def_node_matcher :each_numblock?, <<-PATTERN + (numblock + (send ... :each) _ $(...) + ) + PATTERN + + # @!method expectation?(node) def_node_matcher :expectation?, <<-PATTERN (send (send nil? :expect (lvar %)) :to ...) PATTERN @@ -39,6 +49,14 @@ end end + def on_numblock(node) + each_numblock?(node) do |body| + if single_expectation?(body, :_1) || only_expectations?(body, :_1) + add_offense(node.send_node) + end + end + end + private def single_expectation?(body, arg) @@ -46,6 +64,8 @@ end def only_expectations?(body, arg) + return false unless body.each_child_node.any? + body.each_child_node.all? { |child| expectation?(child, arg) } end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/leading_subject.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/leading_subject.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/leading_subject.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/leading_subject.rb 2022-12-13 09:15:42.000000000 +0000 @@ -7,75 +7,78 @@ # # @example # # bad - # let(:params) { blah } - # subject { described_class.new(params) } + # let(:params) { blah } + # subject { described_class.new(params) } # - # before { do_something } - # 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 } + # it { expect_something } + # subject { described_class.new(params) } + # it { expect_something_else } # # # # good - # subject { described_class.new(params) } - # let(:params) { blah } + # subject { described_class.new(params) } + # let(:params) { blah } # # # good - # subject { described_class.new(params) } - # before { do_something } + # subject { described_class.new(params) } + # before { do_something } # # # good - # subject { described_class.new(params) } - # it { expect_something } - # it { expect_something_else } + # subject { described_class.new(params) } + # it { expect_something } + # it { expect_something_else } # - class LeadingSubject < Cop + class LeadingSubject < Base extend AutoCorrector + include InsideExampleGroup MSG = 'Declare `subject` above any other `%s` declarations.' - def on_block(node) - return unless subject?(node) && !in_spec_block?(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler + return unless subject?(node) + return unless inside_example_group?(node) check_previous_nodes(node) end + private + 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 + offending_node(node) do |offender| + msg = format(MSG, offending: offender.method_name) + add_offense(node, message: msg) do |corrector| + autocorrect(corrector, node, offender) end - - break if offending?(sibling) || sibling.equal?(node) end end - private + def offending_node(node) + parent(node).each_child_node.find do |sibling| + break if sibling.equal?(node) - def autocorrect(corrector, node) - first_node = find_first_offending_node(node) - RuboCop::RSpec::Corrector::MoveNode.new( - node, corrector, processed_source - ).move_before(first_node) + yield sibling if offending?(sibling) + end end - def offending?(node) - let?(node) || hook?(node) || example?(node) + def parent(node) + node.each_ancestor(:block).first.body end - def find_first_offending_node(node) - node.parent.children.find { |sibling| offending?(sibling) } + def autocorrect(corrector, node, sibling) + RuboCop::RSpec::Corrector::MoveNode.new( + node, corrector, processed_source + ).move_before(sibling) end - def in_spec_block?(node) - node.each_ancestor(:block).any? do |ancestor| - example?(ancestor) - end + def offending?(node) + let?(node) || + hook?(node) || + example?(node) || + spec_group?(node) || + include?(node) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/leaky_constant_declaration.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/leaky_constant_declaration.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/leaky_constant_declaration.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/leaky_constant_declaration.rb 2022-12-13 09:15:42.000000000 +0000 @@ -10,7 +10,7 @@ # # 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 + # examples will be reopening it and modifying its behavior in # unpredictable ways. # Even worse when a class that exists in the codebase is reopened. # @@ -93,7 +93,7 @@ # stub_const('SomeModule::SomeClass', foo_class) # end # end - class LeakyConstantDeclaration < Cop + class LeakyConstantDeclaration < Base 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.' diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/let_before_examples.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/let_before_examples.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/let_before_examples.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/let_before_examples.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,7 +6,7 @@ # Checks for `let` definitions that come after an example. # # @example - # # Bad + # # bad # let(:foo) { bar } # # it 'checks what foo does' do @@ -19,7 +19,7 @@ # expect(some).to be # end # - # # Good + # # good # let(:foo) { bar } # let(:some) { other } # @@ -30,19 +30,28 @@ # it 'checks what some does' do # expect(some).to be # end - class LetBeforeExamples < Cop + class LetBeforeExamples < Base extend AutoCorrector MSG = 'Move `let` before the examples in the group.' + # @!method example_or_group?(node) def_node_matcher :example_or_group?, <<-PATTERN { - #{(Examples::ALL + ExampleGroups::ALL).block_pattern} - #{Includes::EXAMPLES.send_pattern} + #{block_pattern('{#ExampleGroups.all #Examples.all}')} + #{send_pattern('#Includes.examples')} } PATTERN - def on_block(node) + # @!method include_examples?(node) + def_node_matcher :include_examples?, <<~PATTERN + { + #{block_pattern(':include_examples')} + #{send_pattern(':include_examples')} + } + PATTERN + + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless example_group_with_body?(node) check_let_declarations(node.body) if multiline_block?(node.body) @@ -50,6 +59,10 @@ private + def example_group_with_include_examples?(body) + body.children.any? { |sibling| include_examples?(sibling) } + end + def multiline_block?(block) block.begin_type? end @@ -58,12 +71,13 @@ 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) + correct = !example_group_with_include_examples?(node) + + first_example.right_siblings.each do |sibling| + next unless let?(sibling) - add_offense(child) do |corrector| - autocorrect(corrector, child, first_example) + add_offense(sibling) do |corrector| + autocorrect(corrector, sibling, first_example) if correct end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/let_setup.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/let_setup.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/let_setup.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/let_setup.rb 2022-12-13 09:15:42.000000000 +0000 @@ -6,41 +6,50 @@ # Checks unreferenced `let!` calls being used for test setup. # # @example - # # Bad + # # bad # let!(:my_widget) { create(:widget) } # # it 'counts widgets' do # expect(Widget.count).to eq(1) # end # - # # Good + # # good # it 'counts widgets' do # create(:widget) # expect(Widget.count).to eq(1) # end # - # # Good + # # good # before { create(:widget) } # # it 'counts widgets' do # expect(Widget.count).to eq(1) # end - class LetSetup < Cop + class LetSetup < Base MSG = 'Do not use `let!` to setup objects not referenced in tests.' + # @!method example_or_shared_group_or_including?(node) def_node_matcher :example_or_shared_group_or_including?, - ( - ExampleGroups::ALL + SharedGroups::ALL + - Includes::ALL - ).block_pattern + block_pattern(<<~PATTERN) + { + #SharedGroups.all + #ExampleGroups.all + #Includes.all + } + PATTERN + # @!method let_bang(node) def_node_matcher :let_bang, <<-PATTERN - (block $(send nil? :let! (sym $_)) args ...) + { + (block $(send nil? :let! {(sym $_) (str $_)}) ...) + $(send nil? :let! {(sym $_) (str $_)} block_pass) + } PATTERN + # @!method method_called?(node) def_node_search :method_called?, '(send nil? %)' - def on_block(node) + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless example_or_shared_group_or_including?(node) unused_let_bang(node) do |let| @@ -52,7 +61,7 @@ def unused_let_bang(node) child_let_bang(node) do |method_send, method_name| - yield(method_send) unless method_called?(node, method_name) + yield(method_send) unless method_called?(node, method_name.to_sym) end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/message_chain.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/message_chain.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/message_chain.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/message_chain.rb 2022-12-13 09:15:42.000000000 +0000 @@ -9,24 +9,18 @@ # # bad # allow(foo).to receive_message_chain(:bar, :baz).and_return(42) # - # # better + # # good # thing = Thing.new(baz: 42) # allow(foo).to receive(:bar).and_return(thing) # - class MessageChain < Cop + class MessageChain < Base MSG = 'Avoid stubbing using `%s`.' - - def_node_matcher :message_chain, <<-PATTERN - (send _ {:receive_message_chain :stub_chain} ...) - PATTERN + RESTRICT_ON_SEND = %i[receive_message_chain stub_chain].freeze def on_send(node) - message_chain(node) do - add_offense( - node.loc.selector, - message: format(MSG, method: node.method_name) - ) - end + add_offense( + node.loc.selector, message: format(MSG, method: node.method_name) + ) end end end diff -Nru ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/message_expectation.rb ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/message_expectation.rb --- ruby-rubocop-rspec-1.42.0/lib/rubocop/cop/rspec/message_expectation.rb 2020-07-09 20:51:09.000000000 +0000 +++ ruby-rubocop-rspec-2.16.0/lib/rubocop/cop/rspec/message_expectation.rb 2022-12-13 09:15:42.000000000 +0000 @@ -8,7 +8,7 @@ # This cop can be configured in your configuration using the # `EnforcedStyle` option and supports `--auto-gen-config`. # - # @example `EnforcedStyle: allow` + # @example `EnforcedStyle: allow` (default) # # # bad # expect(foo).to receive(:bar) @@ -24,17 +24,20 @@ # # good # expect(foo).to receive(:bar) # - class MessageExpectation < Cop + class MessageExpectation < Base include ConfigurableEnforcedStyle MSG = 'Prefer `%