diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 56d2705..1a76643 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,15 +1,15 @@ # Contributing -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. +If you encounter problems or have ideas for improvements or new features, please report them to the [issue tracker](https://github.com/rubocop/rubocop-capybara/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. +- Check if the issue is a non-goal of RuboCop Capybara. - 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`. +- Report the versions of `rubocop-capybara`, as well as the output of `rubocop -V`. - Include any relevant code to the issue summary. ## Pull requests @@ -18,14 +18,14 @@ If you encounter problems or have ideas for improvements or new features, please 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. +5. Add a [changelog](https://github.com/rubocop/rubocop-capybara/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 +We are running [codespell](https://github.com/codespell-project/codespell) with [GitHub Actions](https://github.com/rubocop/rubocop-capybara/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: @@ -35,7 +35,7 @@ $ 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). +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-capybara/blob/master/.github/workflows/linting.yml). `yamllint` is written in [Python](https://www.python.org/) and you can run it with: ```console @@ -44,7 +44,7 @@ $ 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). +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-capybara/blob/master/.github/workflows/linting.yml). `mdformat` is written in [Python](https://www.python.org/) and you can run it with: ```console diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8695fed..fcfeb9e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,7 +15,6 @@ If you have created a new cop: - [ ] 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`. diff --git a/.rubocop.yml b/.rubocop.yml index 9223aa0..b699c10 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -14,7 +14,6 @@ AllCops: - 'vendor/**/*' - 'spec/fixtures/**/*' - 'tmp/**/*' - - 'spec/smoke_tests/**/*.rb' Layout/HashAlignment: EnforcedHashRocketStyle: @@ -49,13 +48,12 @@ Lint/RedundantCopDisableDirective: Metrics/BlockLength: Exclude: - - rubocop-rspec.gemspec - Rakefile - '**/*.rake' Naming/FileName: Exclude: - - lib/rubocop-rspec.rb + - lib/rubocop-capybara.rb Naming/InclusiveLanguage: Enabled: true @@ -112,7 +110,7 @@ Layout/LineEndStringConcatenationIndentation: Style/EmptyHeredoc: Enabled: true -# Enable our own pending cops. +# Enable pending rubocop-rspec cops. RSpec/BeEq: Enabled: true diff --git a/CHANGELOG.md b/CHANGELOG.md index a7234f3..bd15a25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,810 +2,48 @@ ## Master (Unreleased) -- Fix a false positive for `RSpec/PendingWithoutReason` when pending/skip is argument of methods. ([@ydah]) -- Add new `RSpec/Capybara/MatchStyle` cop. ([@ydah]) -- Add new `RSpec/Rails/MinitestAssertions` cop. ([@ydah]) -- Fix a false positive for `RSpec/PendingWithoutReason` when not inside example. ([@ydah]) - -## 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]) +## 2.17.0 (TBD) + +- Extracted from `rubocop-rspec` into a separate repository for easier use with Minitest/Cucumber. ([@pirj]) + +## Previously (see rubocop-rspec's changelist for details) + +- Fix a false positive for `Capybara/SpecificMatcher` when `have_css("a")` without attribute. ([@ydah]) +- Add new `Capybara/NegationMatcher` cop. ([@ydah]) +- Add new `Capybara/SpecificActions` cop. ([@ydah]) +- Fix an error for `Capybara/SpecificFinders` with no parentheses. ([@ydah]) +- Exclude `have_text` and `have_content` that raise `ArgumentError` with `Capybara/VisibilityMatcher` where `:visible` is an invalid option. ([@ydah]) +- Fix a false negative for `Capybara/VisibilityMatcher` with negative matchers. ([@ydah]) +- Fix a false positive for `Capybara/SpecificMatcher`. ([@ydah]) +- Fix a false negative for `Capybara/SpecificMatcher` for `have_field`. ([@ydah]) +- Fix a false positive for `Capybara/SpecificMatcher` when may not have a `href` by `have_link`. ([@ydah]) +- Add new `Capybara/SpecificFinders` cop. ([@ydah]) +- Fix a false positive for `Capybara/SpecificMatcher` when pseudo-classes. ([@ydah]) +- Fix a false positive for `Capybara/SpecificMatcher`. ([@ydah]) +- Add new `Capybara/SpecificMatcher` cop. ([@ydah]) - 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]) +- Fix `FactoryBot/SyntaxMethods` and `Capybara/FeatureMethods` to inspect shared groups. ([@pirj]) - 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]) - -## 1.41.0 (2020-07-03) - -- Extend the list of Rails spec types for `RSpec/DescribeClass`. ([@pirj]) -- Fix `FactoryBot/AttributeDefinedStatically` to allow `#traits_for_enum` without a block. ([@harrylewis]) -- Improve the performance of `FactoryBot/AttributeDefinedStatically`, `RSpec/InstanceVariable`, `RSpec/LetSetup`, `RSpec/NestedGroups` and `RSpec/ReturnFromStub`. ([@andrykonchin]) - -## 1.40.0 (2020-06-11) - -- Add new `RSpec/VariableName` cop. ([@tejasbubane]) -- Add new `RSpec/VariableDefinition` cop. ([@tejasbubane]) - Expand `Capybara/VisibilityMatcher` to support more than just `have_selector`. ([@twalpole]) -- Add new `SpecSuffixOnly` option to `RSpec/FilePath` cop. ([@zdennis]) -- Allow `RSpec/RepeatedExampleGroupBody` to differ only by described_class. ([@robotdana]) -- Fix `RSpec/FilePath` detection across sibling directories. ([@rolfschmidt]) -- Improve the performance of `RSpec/SubjectStub` by an order of magnitude. ([@andrykonchin]) - -## 1.39.0 (2020-05-01) - -- Fix `RSpec/FilePath` detection when absolute path includes test subject. ([@eitoball]) - Add new `Capybara/VisibilityMatcher` cop. ([@aried3r]) -- Ignore String constants by `RSpec/Describe`. ([@AlexWayfer]) -- Drop support for ruby 2.3. ([@bquorning]) -- Fix multiple cops to detect `let` with proc argument. ([@tejasbubane]) -- Add autocorrect support for `RSpec/ScatteredLet`. ([@Darhazer]) -- Add new `RSpec/EmptyHook` cop. ([@tejasbubane]) - -## 1.38.1 (2020-02-15) - -- Fix `RSpec/RepeatedDescription` to detect descriptions with interpolation and methods. ([@lazycoder9]) - -## 1.38.0 (2020-02-11) - -- Fix `RSpec/InstanceVariable` detection inside custom matchers. ([@pirj]) -- Fix `RSpec/ScatteredSetup` to distinguish hooks with different metadata. ([@pirj]) -- Add autocorrect support for `RSpec/ExpectActual` cop. ([@dduugg], [@pirj]) -- Add `RSpec/RepeatedExampleGroupBody` cop. ([@lazycoder9]) -- Add `RSpec/RepeatedExampleGroupDescription` cop. ([@lazycoder9]) -- Add block name and other lines to `RSpec/ScatteredSetup` message. ([@elebow]) -- Fix `RSpec/RepeatedDescription` to take into account example metadata. ([@lazycoder9]) - -## 1.37.1 (2019-12-16) - -- Improve message and description of `FactoryBot/FactoryClassName`. ([@ybiquitous]) -- Fix `FactoryBot/FactoryClassName` to ignore `Hash` and `OpenStruct`. ([@jfragoulis]) - -## 1.37.0 (2019-11-25) - -- Implement `RSpec/DescribedClassModuleWrapping` to disallow RSpec statements within a module. ([@kellysutton]) -- Fix documentation rake task to support Rubocop 0.75. ([@nickcampbell18]) -- Fix `RSpec/SubjectStub` to detect implicit subjects stubbed. ([@QQism]) -- Fix `RSpec/Pending` not flagging `skip` with string values. ([@pirj]) -- Add `AllowedExplicitMatchers` config option for `RSpec/PredicateMatcher`. ([@mkrawc]) -- Add `FactoryBot/FactoryClassName` cop. ([@jfragoulis]) - -## 1.36.0 (2019-09-27) - -- Fix `RSpec/DescribedClass`'s error when `described_class` is used as part of a constant. ([@pirj]) -- Fix `RSpec/ExampleWording` autocorrect of multi-line docstrings. ([@pirj]) -- Add `RSpec/ContextMethod` cop, to detect method names in `context`. ([@geniou]) -- Update RuboCop dependency to 0.68.1 with support for children matching node pattern syntax. ([@pirj]) -- Add `RSpec/EmptyLineAfterExample` cop to check that there is an empty line after example blocks. ([@pirj]) - Fix `Capybara/CurrentPathExpectation` auto-corrector, to include option `ignore_query: true`. ([@onumis]) -- Fix `RSpec/Focus` detecting mixed array/hash metadata. ([@dgollahon]) -- Fix `RSpec/Focus` to also detect `pending` examples. ([@dgollahon]) - -## 1.35.0 (2019-08-02) - -- Add `RSpec/ImplicitBlockExpectation` cop. ([@pirj]) - -## 1.34.1 (2019-07-31) - -- Fix `RSpec/DescribedClass`'s error when a local variable is part of the namespace. ([@pirj]) - -## 1.34.0 (2019-07-23) - -- Remove `AggregateFailuresByDefault` config option of `RSpec/MultipleExpectations`. ([@pirj]) -- Add `RSpec/LeakyConstantDeclaration` cop. ([@jonatas], [@pirj]) -- Improve `aggregate_failures` metadata detection of `RSpec/MultipleExpectations`. ([@pirj]) -- Improve `RSpec/SubjectStub` detection and message. ([@pirj]) -- Change message of `RSpec/LetSetup` cop to be more descriptive. ([@foton]) -- Improve `RSpec/ExampleWording` to handle interpolated example messages. ([@nc-holodakg]) -- Improve detection by allowing the use of `RSpec` as a top-level constant. ([@pirj]) -- Fix `RSpec/DescribedClass`'s incorrect detection. ([@pirj]) -- Improve `RSpec/DescribedClass`'s ability to detect inside modules and classes. ([@pirj]) - -## 1.33.0 (2019-05-13) - -- Let `RSpec/DescribedClass` pass `Struct` instantiation closures. ([@schmijos]) -- Fixed `RSpec/ContextWording` missing `context`s with metadata. ([@pirj]) -- Fix `FactoryBot/AttributeDefinedStatically` not working with an explicit receiver. ([@composerinteralia]) -- Add `RSpec/Dialect` enforces custom RSpec dialects. ([@gsamokovarov]) -- Fix redundant blank lines in `RSpec/MultipleSubjects`'s autocorrect. ([@pirj]) -- Drop support for ruby `2.2`. ([@bquorning]) - -## 1.32.0 (2019-01-27) - -- Add `RSpec/Yield` cop, suggesting using the `and_yield` method when stubbing a method, accepting a block. ([@Darhazer]) -- Fix `FactoryBot/CreateList` autocorrect crashing when the factory is called with a block=. ([@Darhazer]) -- Fixed `RSpec/Focus` not flagging some cases of `RSpec.describe` with `focus: true`. ([@Darhazer]) -- Fixed `RSpec/Pending` not flagging some cases of `RSpec.describe` with `:skip`. ([@Darhazer]) -- Fix false positive in `RSpec/ReceiveCounts` when method name `exactly`, `at_least` or `at_most` is used along with `times`, without being an RSpec API. ([@Darhazer]) - -## 1.31.0 (2019-01-02) - -- Add `IgnoreSharedExamples` option for `RSpec/NamedSubject`. ([@RST-J]) - Add autocorrect support for `Capybara/CurrentPathExpectation` cop. ([@ypresto]) -- Add support for built-in `exists` matcher for `RSpec/PredicateMatcher` cop. ([@mkenyon]) -- `SingleArgumentMessageChain` no longer reports an array as it's only argument as an offense. ([@Darhazer]) - -## 1.30.1 (2018-11-01) - -- `FactoryBot/CreateList` now ignores `times` blocks with an argument. ([@Darhazer]) - -## 1.30.0 (2018-10-08) - -- Add config to `RSpec/VerifiedDoubles` to enforcement of verification on unnamed doubles. ([@BrentWheeldon]) -- Fix `FactoryBot/AttributeDefinedStatically` not working when there is a non-symbol key. ([@vzvu3k6k]) -- Fix false positive in `RSpec/ImplicitSubject` when `is_expected` is used inside `its()` block. ([@Darhazer]) -- Add `single_statement_only` style to `RSpec/ImplicitSubject` as a more relaxed alternative to `single_line_only`. ([@Darhazer]) -- Add `RSpec/UnspecifiedException` as a default cop to encourage more-specific `expect{}.to raise_error(ExceptionType)`, or `raise_exception` style handling of exceptions. ([@daveworth]) - -## 1.29.1 (2018-09-01) - -- Fix false negative in `FactoryBot/AttributeDefinedStatically` when attribute is defined on `self`. ([@Darhazer]) -- `RSpec/FactoryBot` cops will now also inspect the `spec/factories.rb` path by default. ([@bquorning]) - -## 1.29.0 (2018-08-25) - -- `RSpec/InstanceVariable` - Recommend local variables in addition to `let`. ([@jaredbeck]) -- Add `RSpec/ImplicitSubject` cop. ([@Darhazer]) -- Add `RSpec/HooksBeforeExamples` cop. ([@Darhazer]) - -## 1.28.0 (2018-08-14) - -- Add `RSpec/ReceiveNever` cop enforcing usage of `not_to receive` instead of `never` matcher. ([@Darhazer]) -- Fix false positive in `RSpec/EmptyLineAfterExampleGroup` cop when example is inside `if`. ([@Darhazer]) -- Add `RSpec/MissingExampleGroupArgument` to enforce first argument for an example group. ([@geniou]) -- Drop support for ruby `2.1`. ([@bquorning]) -- Add `FactoryBot/AttributeDefinedStatically` cop to help FactoryBot users with the deprecation of static attributes. ([@composerinteralia], [@seanpdoyle]) -- Remove `FactoryBot/DynamicAttributeDefinedStatically` and `FactoryBot/StaticAttributeDefinedDynamically` cops. ([@composerinteralia]) - -## 1.27.0 (2018-06-14) - -- `RSpec/LeadingSubject` now enforces subject to be before any examples, hooks or let declarations. ([@Darhazer]) -- Fix `RSpec/NotToNot` to highlight only the selector (`not_to` or `to_not`), so it works also on `expect { ... }` blocks. ([@bquorning]) -- Add `RSpec/EmptyLineAfterHook` cop. ([@bquorning]) -- Add `RSpec/EmptyLineAfterExampleGroup` cop to check that there is an empty line after example group blocks. ([@bquorning]) -- Fix `RSpec/DescribeClass` crashing on `RSpec.describe` without arguments. ([@Darhazer]) -- Bump RuboCop requirement to v0.56.0. ([@bquorning]) -- Fix `RSpec/OverwritingSetup` crashing if a variable is used as an argument for `let`. ([@Darhazer]) - -## 1.26.0 (2018-06-06) - -- Fix false positive in `RSpec/EmptyExampleGroup` cop when methods named like a RSpec method are used. ([@Darhazer]) - Fix `Capybara/FeatureMethods` not working when there is require before the spec. ([@Darhazer]) -- Fix `RSpec/EmptyLineAfterFinalLet`: allow a comment to be placed after latest let, requiring empty line after the comment. ([@Darhazer]) -- Add `RSpec/ReceiveCounts` cop to enforce usage of :once and :twice matchers. ([@Darhazer]) - -## 1.25.1 (2018-04-10) - -- Fix false positive in `RSpec/Pending` cop when pending is used as a method name. ([@Darhazer]) -- Fix `FactoryBot/DynamicAttributeDefinedStatically` false positive when using symbol proc argument for a sequence. ([@tdeo]) - -## 1.25.0 (2018-04-07) - -- Add `RSpec/SharedExamples` cop to enforce consistent usage of string to titleize shared examples. ([@anthony-robin]) -- Add `RSpec/Be` cop to enforce passing argument to the generic `be` matcher. ([@Darhazer]) -- Fix false positives in `StaticAttributeDefinedDynamically` and `ReturnFromStub` when a const is used in an array or hash. ([@Darhazer]) -- Add `RSpec/Pending` cop to enforce no existing pending or skipped examples. This is disabled by default. ([@patrickomatic]) -- Fix `RSpec/NestedGroups` cop support --auto-gen-config. ([@walf443]) - Fix false positives in `Capybara/FeatureMethods` when feature methods are used as property names in a factory. ([@Darhazer]) - Allow configuring enabled methods in `Capybara/FeatureMethods`. ([@Darhazer]) -- Add `FactoryBot/CreateList` cop. ([@Darhazer]) - -## 1.24.0 (2018-03-06) - -- Compatibility with RuboCop v0.53.0. ([@bquorning]) -- The `Rails/HttpStatus` cop is unavailable if the `rack` gem cannot be loaded. ([@bquorning]) -- Fix `Rails/HttpStatus` not working with custom HTTP status codes. ([@bquorning]) -- Fix `FactoryBot/StaticAttributeDefinedDynamically` to handle empty block. ([@abrom]) -- Fix false positive in `FactoryBot/DynamicAttributeDefinedStatically` when a before/after callback has a symbol proc argument. ([@abrom]) - -## 1.23.0 (2018-02-23) - -- Add `RSpec/Rails/HttpStatus` cop to enforce consistent usage of the status format (numeric or symbolic). ([@anthony-robin], [@jojos003]) -- Fix false negative in `RSpec/ReturnFromStub` when a constant is being returned by the stub. ([@Darhazer]) -- Fix `FactoryBot/DynamicAttributeDefinedStatically` to handle dynamic attributes inside arrays/hashes. ([@abrom]) -- Add `FactoryBot/StaticAttributeDefinedDynamically` (based on dynamic attribute cop). ([@abrom]) - -## 1.22.2 (2018-02-01) - -- Fix error in `RSpec/DescribedClass` when working on an empty `describe` block. ([@bquorning]) - -## 1.22.1 (2018-01-17) - -- Fix false positives in `RSpec/ReturnFromStub`. ([@Darhazer]) - -## 1.22.0 (2018-01-10) - -- Updates `describe_class` to account for RSpecs `:system` wrapper of rails system tests. ([@EliseFitz15]) -- Add `RSpec/ExpectChange` cop to enforce consistent usage of the change matcher. ([@Darhazer]) -- Add autocorrect support to `RSpec/LetBeforeExamples`. ([@Darhazer]) -- Fix `RSpec/InstanceVariable` flagging instance variables inside dynamically defined class. ([@Darhazer]) -- Add autocorrect support for `RSpec/ReturnFromStub` cop. ([@bquorning]) -- Add `RSpec/ExampleWithoutDescription` cop. ([@Darhazer]) - -## 1.21.0 (2017-12-13) - -- Compatibility with RuboCop v0.52.0. ([@bquorning]) -- Improve performance when user does not override default RSpec Pattern config. ([@walf443]) -- Add `AggregateFailuresByDefault` configuration for `RSpec/MultipleExpectations` cop. ([@onk]) - -## 1.20.1 (2017-11-15) - -- Add "without" to list of default allowed prefixes for `RSpec/ContextWording`. ([@bquorning]) - -## 1.20.0 (2017-11-09) - -- Rename namespace `FactoryGirl` to `FactoryBot` following original library update. ([@walf443]) -- Fix exception in `RSpec/ReturnFromStub` on empty block. ([@yevhene]) -- Add `RSpec/ContextWording` cop. ([@pirj], [@telmofcosta]) -- Fix `RSpec/SubjectStub` cop matches receive message inside all matcher. ([@walf443]) - -## 1.19.0 (2017-10-18) - -Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. - -## 1.18.0 (2017-09-29) - - Fix false positive in `Capybara/FeatureMethods`. ([@Darhazer]) -- Add `RSpec/Capybara/CurrentPathExpectation` cop for feature specs, disallowing setting expectations on `current_path`. ([@timrogers]) -- Fix false positive in `RSpec/LetBeforeExamples` cop when example group contains single let. ([@Darhazer]) - -## 1.17.1 (2017-09-20) - -- Improved `RSpec/ReturnFromStub` to handle string interpolation, hashes and do..end blocks. ([@Darhazer]) -- Fixed compatibility with JRuby. ([@zverok]) - -## 1.17.0 (2017-09-14) - +- Add `Capybara/CurrentPathExpectation` cop for feature specs, disallowing setting expectations on `current_path`. ([@timrogers]) - Add `RSpec/Capybara` namespace including the first cop for feature specs: `Capybara/FeatureMethods`. ([@rspeicher]) -- Update to RuboCop 0.50.0. ([@bquorning]) - -## 1.16.0 (2017-09-06) - -- Add `RSpec/FactoryGirl` namespace including the first cop for factories: `FactoryGirl/DynamicAttributeDefinedStatically`. ([@jonatas]) -- Add disabled by default `RSpec/AlignLeftLetBrace`. ([@backus]) -- Add disabled by default `RSpec/AlignRightLetBrace`. ([@backus]) -- Add `RSpec/LetBeforeExamples` cop. ([@Darhazer]) -- Add `RSpec/MultipleSubjects` cop. ([@backus]) -- Add `RSpec/ReturnFromStub` cop. ([@Darhazer]) -- Add `RSpec/VoidExpect` cop. ([@pocke]) -- Add `RSpec/InvalidPredicateMatcher` cop. ([@pocke]) -- Change HookArgument cop to detect when hook has a receiver. ([@pocke]) -- Add `RSpec/PredicateMatcher` cop. ([@pocke]) -- Add `RSpec/ExpectInHook` cop. ([@pocke]) -- `RSpec/MultipleExpectations` now detects usage of expect_any_instance_of. ([@Darhazer]) -- `RSpec/MultipleExpectations` now detects usage of is_expected. ([@bmorrall]) - -## 1.15.1 (2017-04-30) - -- Fix the handling of various edge cases in the `RSpec/ExampleWording` cop, including one that would cause autocorrect to crash. ([@dgollahon]) -- Fix `RSpec/IteratedExpectation` crashing when there is an assignment in the iteration. ([@Darhazer]) -- Fix false positive in `RSpec/SingleArgumentMessageChain` cop when the single argument is a hash. ([@Darhazer]) - -## 1.15.0 (2017-03-24) - -- Add `RSpec/DescribeSymbol` cop. ([@rspeicher]) -- Fix error when `RSpec/OverwritingSetup` and `RSpec/ScatteredLet` analyzed empty example groups. ([@backus]) - -## 1.14.0 (2017-03-24) - -- Add `RSpec/OverwritingSetup` cop. ([@Darhazer]) -- Add autocorrect support for `RSpec/LeadingSubject` cop. ([@Darhazer]) -- Add `RSpec/ScatteredLet` cop. ([@Darhazer]) -- Add `RSpec/IteratedExpectation` cop. ([@Darhazer]) -- Add `RSpec/EmptyLineAfterSubject` cop. ([@Darhazer]) -- Add `RSpec/EmptyLineAfterFinalLet` cop. ([@Darhazer]) - -## 1.13.0 (2017-03-07) - -- Add repeated 'it' detection to `RSpec/ExampleWording` cop. ([@dgollahon]) -- Add \[observed_nesting/max_nesting\] info to `RSpec/NestedGroups` messages. ([@dgollahon]) -- Add `RSpec/ItBehavesLike` cop. ([@dgollahon]) -- Add `RSpec/SharedContext` cop. ([@Darhazer]) -- `RSpec/MultipleExpectations`: Count aggregate_failures block as single expectation. ([@Darhazer]) -- Fix `ExpectActual` cop flagging `rspec-rails` routing specs. ([@backus]) -- Fix `FilePath` cop not registering offenses for files like `spec/blog/user.rb` when it should be `spec/blog/user_spec.rb`. ([@backus]) - -## 1.12.0 (2017-02-21) - -- Add `RSpec/InstanceSpy` cop. ([@Darhazer]) -- Add `RSpec/BeforeAfterAll` for avoiding leaky global test setup. ([@cfabianski]) - -## 1.11.0 (2017-02-16) - -- Add `AroundBlock` cop. ([@Darhazer]) -- Add `EnforcedStyle` configuration for `RSpec/DescribedClass` cop. ([@Darhazer]) -- Fix false positive for `RSpec/RepeatedExample` cop. ([@redross]) - -## 1.10.0 (2017-01-15) - -- Fix false negative for `RSpec/MessageSpies` cop. ([@onk]) -- Fix internal dependencies on RuboCop to be compatible with 0.47 release. ([@backus]) -- Add autocorrect support for `SingleArgumentMessageChain` cop. ([@bquorning]) -- Rename `NestedGroups`' configuration key from `MaxNesting` to `Max` in order to be consistent with other cop configuration. ([@backus]) -- Add `RepeatedExample` cop for detecting repeated examples within example groups. ([@backus]) -- Add `ScatteredSetup` cop for enforcing that only one `before`, `around`, and `after` hook are used per example group scope. ([@backus]) -- Add `ExpectOutput` cop for recommending `expect { ... }.to output(...).to_stdout`. ([@backus]) - -## 1.9.1 (2017-01-02) - -- Fix unintentional regression change in `NestedGroups` reported in #270. ([@backus]) -- Change `MaxNesting` for `NestedGroups` from 2 to 3. ([@backus]) - -## 1.9.0 (2016-12-29) - -- Add `MessageSpies` cop for enforcing consistent style of either `expect(...).to have_received` or `expect(...).to receive`, intended as a replacement for the `MessageExpectation` cop. ([@bquorning]) -- Fix `DescribeClass` to not flag `describe` at the top of a block of shared examples. ([@clupprich]) -- Add `SingleArgumentMessageChain` cop for recommending use of `receive` instead of `receive_message_chain` where possible. ([@bquorning]) -- Add `RepeatedDescription` cop for detecting repeated example descriptions within example groups. ([@backus]) - -## 1.8.0 (2016-10-27) - -- Optionally ignore method names in the `describe` argument when running the `FilePath` cop. ([@bquorning]) -- Fix regression in how `FilePath` converts alphanumeric class names into paths. ([@bquorning]) -- Add `ImplicitExpect` cop for enforcing `should` vs. `is_expected.to`. ([@backus]) -- Disable `MessageExpectation` cop in the default configuration. ([@bquorning]) - -## 1.7.0 (2016-08-24) - -- Add support for checking all example groups with `ExampleLength`. ([@backus]) -- Add support for checking shared example groups for `DescribedClass`. ([@backus]) -- Add support for checking `its` from [rspec-its](https://github.com/rspec/rspec-its). ([@backus]) -- Add `EmptyExampleGroup` cop for detecting `describe`s and `context`s without any tests inside. ([@backus]) -- Add `CustomIncludeMethods` configuration option for `EmptyExampleGroup`. ([@backus]) -- Add `NestedGroups` cop for detecting excessive example group nesting. ([@backus]) -- Add `MaxNesting` configuration option for `NestedGroups` cop. ([@backus]) -- Add `ExpectActual` cop for detecting literal values within `expect(...)`. ([@backus]) -- Add `MultipleExpectations` cop for detecting multiple `expect(...)` calls within one example. ([@backus]) -- Add `Max` configuration option for `MultipleExpectations`. ([@backus]) -- Add `SubjectStub` cop for testing stubbed test subjects. ([@backus]) -- Add `LetSetup` cop for detecting cases where `let!` is used for test setup. ([@backus]) -- Change all cops to only inspect files with names following rspec convention (`*/spec/*` and/or `_spec.rb`). ([@backus]) -- Add `AllCops/RSpec` configuration option for specifying custom spec file patterns. ([@backus]) -- Add `AssignmentOnly` configuration option for `RSpec/InstanceVariable` cop. ([@backus]) -- Add `BeEql` cop which looks for expectations that can use `be(...)` instead of `eql(...)`. ([@backus]) -- Add autocorrect support for `BeEql` cop. ([@backus]) -- Add `MessageExpectation` cop for enforcing consistent style of either `expect(...).to receive` or `allow(...).to receive`. ([@backus]) -- Add `MessageChain` cop. ([@bquorning]) - -## 1.6.0 (2016-08-03) - -- Add `SkipBlocks` option for `DescribedClass` cop. ([@backus]) - -## 1.5.3 (2016-08-02) - -- Add `RSpec/NamedSubject` cop. ([@backus]) - -## 1.5.2 (2016-08-01) - -- Drop support for ruby `2.0.0` and `2.1.0`. ([@backus]) -- Internal refactorings and improved test coverage. ([@backus]) - -## 1.5.1 (2016-07-20) - -- Fix `unrecognized parameter RSpec/VerifiedDoubles:IgnoreSymbolicNames` warning. ([@jeffreyc]) -- Update to rubocop 0.41.2. ([@backus]) - -## 1.5.0 (2016-05-17) - -- Expand `VerifiedDoubles` cop to check for `spy` as well as `double`. ([@andyw8]) -- Enable `VerifiedDoubles` cop by default. ([@andyw8]) -- Add `IgnoreSymbolicNames` option for `VerifiedDoubles` cop. ([@andyw8]) -- Add `RSpec::ExampleLength` cop. ([@andyw8]) -- Handle alphanumeric class names in `FilePath` cop. ([@andyw8]) -- Skip `DescribeClass` cop for view specs. ([@andyw8]) -- Skip `FilePath` cop for Rails routing specs. ([@andyw8]) -- Add cop to check for focused specs. ([@renanborgescampos], [@jaredmoody]) -- Clean-up `RSpec::NotToNot` to use same configuration semantics as other Rubocop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal]) -- Update to rubocop 0.40.0. ([@nijikon]) - -## 1.4.1 (2016-04-03) - -- Ignore routing specs for DescribeClass cop. ([@nijikon]) -- Move rubocop dependency to runtime. ([@nijikon]) -- Update to rubocop 0.39.0. ([@nijikon]) - -## 1.4.0 (2016-02-15) - -- Update to rubocop 0.37.2. ([@nijikon]) -- Update ruby versions we test against. ([@nijikon]) -- Add `RSpec::NotToNot` cop. ([@miguelfteixeira]) -- Add `RSpec/AnyInstance` cop. ([@mlarraz]) - -## 1.3.1 - -- Fix auto correction issue - syntax had changed in RuboCop v0.31. ([@bquorning]) -- Add RuboCop clone to vendor folder - see #39 for details. ([@bquorning]) - -## 1.3.0 - -- Ignore non string arguments for FilePathCop - thanks to @deivid-rodriguez. ([@geniou]) -- Skip DescribeMethod cop for tagged specs. ([@deivid-rodriguez]) -- Skip DescribeClass cop for feature/request specs. ([@deivid-rodriguez]) - -## 1.2.2 - -- Make `RSpec::ExampleWording` case insensitive. ([@geniou]) - -## 1.2.1 - -- Add `RSpec::VerifiedDoubles` cop. ([@andyw8]) - -## 1.2.0 - -- Drop support of ruby `1.9.2`. ([@geniou]) -- Update to RuboCop `~> 0.24`. ([@geniou]) -- Add `autocorrect` to `RSpec::ExampleWording`. This experimental - use with care and check the changes. ([@geniou]) -- Fix config loader debug output. ([@geniou]) -- Rename `FileName` cop to `FilePath` as a workaround - see [#19](https://github.com/nevir/rubocop-rspec/issues/19). ([@geniou]) - -## 1.1.0 - -- Add `autocorrect` to `RSpec::DescribedClass` cop. ([@geniou]) - -## 1.0.1 - -- Add `config` folder to gemspec. ([@pstengel]) - -## 1.0.rc3 - -- Update to RuboCop `>= 0.23`. ([@geniou]) -- Add configuration option for `CustomTransformation` to `FileName` cop. ([@geniou]) - -## 1.0.rc2 - -- Gem is no longer 20MB (sorry!). ([@nevir]) -- `RspecFileName` cop allows for method specs to organized into directories by class and type. ([@nevir]) - -## 1.0.rc1 - -- Update code to work with rubocop `>= 0.19`. ([@geniou]) -- Split `UnitSpecNaming` cop into `RSpecDescribeClass`, `RSpecDescribeMethod` and `RSpecFileName` and enabled them all by default. ([@geniou]) -- Add `RSpecExampleWording` cop to prevent to use of should at the beginning of the spec description. ([@geniou]) -- Fix `RSpecFileName` cop for non-class specs. ([@geniou]) -- Adapt `RSpecFileName` cop to 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 -[@jaredmoody]: https://github.com/jaredmoody -[@jeffreyc]: https://github.com/jeffreyc -[@jfragoulis]: https://github.com/jfragoulis -[@johnny-miyake]: https://github.com/johnny-miyake -[@jojos003]: https://github.com/jojos003 -[@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 -[@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 -[@nevir]: https://github.com/nevir -[@ngouy]: https://github.com/ngouy -[@nickcampbell18]: https://github.com/nickcampbell18 -[@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 -[@zverok]: https://github.com/zverok diff --git a/Gemfile b/Gemfile index fa7613d..57ac1b7 100644 --- a/Gemfile +++ b/Gemfile @@ -10,6 +10,7 @@ gem 'rake' gem 'rspec', '~> 3.11' gem 'rubocop-performance', '~> 1.7' gem 'rubocop-rake', '~> 0.6' +gem 'rubocop-rspec', '~> 2.16.0' gem 'yard' local_gemfile = 'Gemfile.local' diff --git a/README.md b/README.md index 3c12c55..0cd7b92 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,29 @@ -# RuboCop RSpec +# RuboCop Capybara [![Join the chat at https://gitter.im/rubocop-rspec/Lobby](https://badges.gitter.im/rubocop-rspec/Lobby.svg)](https://gitter.im/rubocop-rspec/Lobby) -[![Gem Version](https://badge.fury.io/rb/rubocop-rspec.svg)](https://rubygems.org/gems/rubocop-rspec) -![CI](https://github.com/rubocop/rubocop-rspec/workflows/CI/badge.svg) +[![Gem Version](https://badge.fury.io/rb/rubocop-capybara.svg)](https://rubygems.org/gems/rubocop-capybara) +![CI](https://github.com/rubocop/rubocop-capybara/workflows/CI/badge.svg) -RSpec-specific analysis for your projects, as an extension to +Capybara-specific analysis for your projects, as an extension to [RuboCop](https://github.com/rubocop/rubocop). ## Installation -Just install the `rubocop-rspec` gem +Just install the `rubocop-capybara` gem ```bash -gem install rubocop-rspec +gem install rubocop-capybara ``` or if you use bundler put this in your `Gemfile` ``` -gem 'rubocop-rspec', require: false +gem 'rubocop-capybara', require: false ``` -### Upgrading to RuboCop RSpec v2.x - -Read all the details in our [Upgrade to Version 2.x](https://docs.rubocop.org/rubocop-rspec/2.0/upgrade_to_version_2.html) document. - ## Usage -You need to tell RuboCop to load the RSpec extension. There are three +You need to tell RuboCop to load the Capybara extension. There are three ways to do this: ### RuboCop configuration file @@ -35,7 +31,7 @@ ways to do this: Put this into your `.rubocop.yml`. ```yaml -require: rubocop-rspec +require: rubocop-capybara ``` Alternatively, use the following array notation when specifying multiple extensions. @@ -43,47 +39,43 @@ Alternatively, use the following array notation when specifying multiple extensi ```yaml require: - rubocop-other-extension - - rubocop-rspec + - rubocop-capybara ``` -Now you can run `rubocop` and it will automatically load the RuboCop RSpec +Now you can run `rubocop` and it will automatically load the RuboCop Capybara cops together with the standard cops. ### Command line ```bash -rubocop --require rubocop-rspec +rubocop --require rubocop-capybara ``` ### Rake task ```ruby RuboCop::RakeTask.new do |task| - task.requires << 'rubocop-rspec' + task.requires << 'rubocop-capybara' end ``` -### Code Climate - -rubocop-rspec is available on Code Climate as part of the rubocop engine. [Learn More](https://marketing.codeclimate.com/changelog/55a433bbe30ba00852000fac/). - ## Documentation -You can read more about RuboCop RSpec in its [official manual](https://docs.rubocop.org/rubocop-rspec). +You can read more about RuboCop Capybara in its [official manual](https://docs.rubocop.org/rubocop-capybara). ## The Cops All cops are located under -[`lib/rubocop/cop/rspec`](lib/rubocop/cop/rspec), and contain +[`lib/rubocop/cop/capybara`](lib/rubocop/cop/capybara), and contain examples/documentation. -In your `.rubocop.yml`, you may treat the RSpec cops just like any other +In your `.rubocop.yml`, you may treat the Capybara cops just like any other cop. For example: ```yaml -RSpec/FilePath: +Capybara/SpecificMatcher: Exclude: - - spec/my_poorly_named_spec_file.rb + - spec/my_spec.rb ``` ## Contributing @@ -92,5 +84,5 @@ Checkout the [contribution guidelines](.github/CONTRIBUTING.md). ## License -`rubocop-rspec` is MIT licensed. [See the accompanying file](MIT-LICENSE.md) for +`rubocop-capybara` is MIT licensed. [See the accompanying file](MIT-LICENSE.md) for the full text. diff --git a/Rakefile b/Rakefile index fc44097..547a648 100644 --- a/Rakefile +++ b/Rakefile @@ -29,23 +29,16 @@ desc 'Build config/default.yml' task :build_config do require 'yard' - require 'rubocop-rspec' - 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::Base. - # Otherwise, cop's parent class for cops loaded before our base cop class - # 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', 'base.rb') + require 'rubocop-capybara' + require 'rubocop/capybara/config_formatter' + require 'rubocop/capybara/description_extractor' + + glob = File.join('lib', 'rubocop', 'cop', 'capybara', '*.rb') YARD::Tags::Library.define_tag('Cop Safety Information', :safety) - YARD.parse(Dir[glob].prepend(rspec_cop_path), []) + YARD.parse(Dir[glob], []) descriptions = - RuboCop::RSpec::DescriptionExtractor.new(YARD::Registry.all(:class)).to_h + RuboCop::Capybara::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 @@ -54,7 +47,7 @@ task :build_config do File.write( 'config/default.yml', - RuboCop::RSpec::ConfigFormatter.new(current_config, descriptions).dump + RuboCop::Capybara::ConfigFormatter.new(current_config, descriptions).dump ) end @@ -100,7 +93,7 @@ task :new_cop, [:cop] do |_task, args| generator = RuboCop::Cop::Generator.new(cop_name) generator.write_source generator.write_spec - generator.inject_require(root_file_path: 'lib/rubocop/cop/rspec_cops.rb') + generator.inject_require(root_file_path: 'lib/rubocop/cop/capybara_cops.rb') generator.inject_config puts generator.todo diff --git a/config/default.yml b/config/default.yml index 1b4a4fe..bbd2756 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1,899 +1,26 @@ --- -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' - 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' - 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://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' - 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://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' - 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 - VersionAdded: '1.12' - 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://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 - AllowedPatterns: [] - VersionAdded: '1.20' - 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. - 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' - 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' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeMethod - -RSpec/DescribeSymbol: - Description: Avoid describing symbols. - Enabled: true - VersionAdded: '1.15' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol - -RSpec/DescribedClass: - Description: Checks that tests use `described_class`. - Enabled: true - SkipBlocks: false - EnforcedStyle: described_class - SupportedStyles: - - described_class - - explicit - SafeAutoCorrect: false - VersionAdded: '1.0' - VersionChanged: '1.11' - 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' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping - -RSpec/Dialect: - Description: Enforces custom RSpec dialects. - Enabled: false - PreferredMethods: {} - VersionAdded: '1.33' - 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 - SafeAutoCorrect: false - VersionAdded: '1.7' - 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' - 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://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://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://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' - 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://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' - 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 - VersionAdded: '1.22' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription - -RSpec/ExampleWording: - Description: Checks for common mistakes in example descriptions. - Enabled: true - CustomTransform: - be: is - BE: IS - have: has - HAVE: HAS - IgnoredWords: [] - DisallowedExamples: - - works - VersionAdded: '1.0' - 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/**/* - VersionAdded: '1.7' - 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 - SafeAutoCorrect: false - VersionAdded: '1.22' - 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' - 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' - 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. +Capybara: Enabled: true + DocumentationBaseURL: https://docs.rubocop.org/rubocop-capybara Include: - - "**/*_spec*rb*" + - "**/*_spec.rb" - "**/spec/**/*" - CustomTransform: - RuboCop: rubocop - RSpec: rspec - IgnoreMethods: false - SpecSuffixOnly: false - VersionAdded: '1.2' - VersionChanged: '1.40' - 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' - 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 - VersionAdded: '1.7' - 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' - 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://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 - VersionAdded: '1.8' - 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 - - require_implicit - VersionAdded: '1.29' - 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' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceSpy - -RSpec/InstanceVariable: - Description: Checks for instance variable usage in specs. - Enabled: true - AssignmentOnly: false - VersionAdded: '1.0' - VersionChanged: '1.7' - StyleGuide: https://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 - VersionAdded: '1.13' - 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' - 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://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://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' - 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' - 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' - 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 - VersionAdded: '1.7' - VersionChanged: '1.8' - 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 - VersionAdded: '1.9' - 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' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument - -RSpec/MultipleDescribes: - Description: Checks for multiple top-level example groups. - Enabled: true - VersionAdded: '1.0' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes - -RSpec/MultipleExpectations: - Description: Checks if examples contain too many `expect` calls. - Enabled: true - Max: 1 - VersionAdded: '1.7' - VersionChanged: '1.21' - StyleGuide: https://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' - 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 - 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: '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 - VersionAdded: '1.4' - 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' - 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' - 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. - Enabled: true - Strict: true - EnforcedStyle: inflected - AllowedExplicitMatchers: [] - SupportedStyles: - - inflected - - explicit - SafeAutoCorrect: false - VersionAdded: '1.16' - 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' - 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' - 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' - 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' - 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' - 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' - 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 - VersionAdded: '1.16' - VersionChanged: '1.22' - 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' - 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' - 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' - 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' - 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' - 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' - 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' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UnspecifiedException + - "**/test/**/*" -RSpec/VariableDefinition: - Description: Checks that memoized helpers names are symbols or strings. - Enabled: true - EnforcedStyle: symbols - SupportedStyles: - - symbols - - strings - VersionAdded: '1.40' - 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 - AllowedPatterns: [] - VersionAdded: '1.40' - 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. - Enabled: true - IgnoreNameless: true - IgnoreSymbolicNames: false - VersionAdded: 1.2.1 - VersionChanged: '1.5' - StyleGuide: https://rspec.rubystyle.guide/#doubles - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles - -RSpec/VoidExpect: - Description: Checks void `expect()`. - Enabled: true - VersionAdded: '1.16' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect - -RSpec/Yield: - Description: Checks for calling a block within a stub. - Enabled: true - VersionAdded: '1.32' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield - -RSpec/Capybara: - Enabled: true - Include: *1 - Language: *2 - -RSpec/Capybara/CurrentPathExpectation: +Capybara/CurrentPathExpectation: Description: Checks that no expectations are set on Capybara's `current_path`. Enabled: true VersionAdded: '1.18' VersionChanged: '2.0' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/CurrentPathExpectation - -RSpec/Capybara/FeatureMethods: - Description: Checks for consistent method usage in feature specs. - Enabled: true - EnabledMethods: [] - VersionAdded: '1.17' - VersionChanged: '2.0' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/FeatureMethods + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/CurrentPathExpectation -RSpec/Capybara/MatchStyle: +Capybara/MatchStyle: Description: Checks for usage of deprecated style methods. Enabled: pending VersionAdded: "<>" - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/MatchStyle + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/MatchStyle -RSpec/Capybara/NegationMatcher: +Capybara/NegationMatcher: Description: Enforces use of `have_no_*` or `not_to` for negated expectations. Enabled: pending VersionAdded: '2.14' @@ -901,158 +28,29 @@ RSpec/Capybara/NegationMatcher: SupportedStyles: - have_no - not_to - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/NegationMatcher + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/NegationMatcher -RSpec/Capybara/SpecificActions: +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 + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/SpecificActions -RSpec/Capybara/SpecificFinders: +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 + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/SpecificFinders -RSpec/Capybara/SpecificMatcher: +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 + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/SpecificMatcher -RSpec/Capybara/VisibilityMatcher: +Capybara/VisibilityMatcher: Description: Checks for boolean visibility in Capybara finders. Enabled: true VersionAdded: '1.39' VersionChanged: '2.0' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/VisibilityMatcher - -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' - 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 - -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 - VersionAdded: '1.25' - VersionChanged: '2.0' - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList - -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' - 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 - -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 - VersionAdded: '1.23' - 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 - -RSpec/Rails/MinitestAssertions: - Description: Check if using Minitest matchers. - Enabled: pending - VersionAdded: "<>" - Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/VisibilityMatcher diff --git a/docs/antora.yml b/docs/antora.yml index 51a533a..8ec1220 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,5 +1,5 @@ -name: rubocop-rspec -title: RuboCop RSpec +name: rubocop-capybara +title: RuboCop Capybara version: ~ nav: - modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 0487d48..d357cb9 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -2,11 +2,6 @@ * 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_rspec_capybara.adoc[Capybara] -** xref:cops_rspec_factorybot.adoc[FactoryBot] -** xref:cops_rspec_rails.adoc[Rails] -** xref:cops_rspec.adoc[RSpec] +** xref:cops_capybara.adoc[Capybara] diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index ce14e6e..180007a 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -1,125 +1,13 @@ // START_COP_LIST -=== Department xref:cops_rspec.adoc[RSpec] - -* 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/matchstyle[RSpec/Capybara/MatchStyle] -* 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] -* xref:cops_rspec_rails.adoc#rspecrails/minitestassertions[RSpec/Rails/MinitestAssertions] +=== Department xref:cops_capybara.adoc[Capybara] + +* xref:cops_capybara.adoc#capybaracurrentpathexpectation[Capybara/CurrentPathExpectation] +* xref:cops_capybara.adoc#capybaramatchstyle[Capybara/MatchStyle] +* xref:cops_capybara.adoc#capybaranegationmatcher[Capybara/NegationMatcher] +* xref:cops_capybara.adoc#capybaraspecificactions[Capybara/SpecificActions] +* xref:cops_capybara.adoc#capybaraspecificfinders[Capybara/SpecificFinders] +* xref:cops_capybara.adoc#capybaraspecificmatcher[Capybara/SpecificMatcher] +* xref:cops_capybara.adoc#capybaravisibilitymatcher[Capybara/VisibilityMatcher] // END_COP_LIST diff --git a/docs/modules/ROOT/pages/cops_capybara.adoc b/docs/modules/ROOT/pages/cops_capybara.adoc index 93c24b9..73f5902 100644 --- a/docs/modules/ROOT/pages/cops_capybara.adoc +++ b/docs/modules/ROOT/pages/cops_capybara.adoc @@ -1,6 +1,6 @@ -= RSpec/Capybara += Capybara -== RSpec/Capybara/CurrentPathExpectation +== Capybara/CurrentPathExpectation |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed @@ -43,76 +43,9 @@ expect(page).to have_current_path('/callback') === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/CurrentPathExpectation +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/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/MatchStyle +== Capybara/MatchStyle |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed @@ -165,9 +98,9 @@ expect(page).to match_style(display: 'block') === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/MatchStyle +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/MatchStyle -== RSpec/Capybara/NegationMatcher +== Capybara/NegationMatcher |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed @@ -221,9 +154,9 @@ expect(page).to have_no_css('a') === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/NegationMatcher +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/NegationMatcher -== RSpec/Capybara/SpecificActions +== Capybara/SpecificActions |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed @@ -256,9 +189,9 @@ find('div').click_button === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificActions +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/SpecificActions -== RSpec/Capybara/SpecificFinders +== Capybara/SpecificFinders |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed @@ -287,9 +220,9 @@ find_by_id('some-id', visible: true) === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificFinders +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/SpecificFinders -== RSpec/Capybara/SpecificMatcher +== Capybara/SpecificMatcher |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed @@ -328,9 +261,9 @@ expect(page).to have_field('foo') === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/SpecificMatcher +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/SpecificMatcher -== RSpec/Capybara/VisibilityMatcher +== Capybara/VisibilityMatcher |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed @@ -370,4 +303,4 @@ expect(page).to have_link('my link', visible: :hidden) === References -* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/VisibilityMatcher +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/VisibilityMatcher diff --git a/docs/modules/ROOT/pages/development.adoc b/docs/modules/ROOT/pages/development.adoc index f10522d..01ebb88 100644 --- a/docs/modules/ROOT/pages/development.adoc +++ b/docs/modules/ROOT/pages/development.adoc @@ -1,32 +1,3 @@ = 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 ----- +This page describes considerations when developing Capybara-specific cops. It is intended to be a complement to the general https://docs.rubocop.org/rubocop/development.html[RuboCop development documentation]. diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index e7a3b37..ffed773 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -1,9 +1,9 @@ -= RuboCop RSpec += RuboCop Capybara -RSpec-specific analysis for your projects, as an extension to +Capybara-specific analysis for your projects, as an extension to https://github.com/rubocop/rubocop[RuboCop]. -RuboCop RSpec follows the https://docs.rubocop.org/rubocop/versioning.html[RuboCop versioning guide]. +RuboCop Capybara 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. @@ -11,49 +11,4 @@ On a major version release, all `pending` cops are enabled. == Project Goals -* Enforce the guidelines and best practices outlined in the community https://rspec.rubystyle.guide[RSpec style guide] -* Simplify the process of adopting new RSpec functionality - -== Non-goals of RuboCop RSpec - -=== Enforcing `should` vs. `expect` syntax - -Enforcing - -[source,ruby] ----- -expect(calculator.compute(line_item)).to eq(5) ----- - -over - -[source,ruby] ----- -calculator.compute(line_item).should == 5 ----- - -is a feature of RSpec itself – you can read about it in the https://relishapp.com/rspec/rspec-expectations/docs/syntax-configuration#disable-should-syntax[RSpec Documentation]. - -=== Enforcing an explicit RSpec receiver for top-level methods (disabling monkey patching) - -Enforcing - -[source,ruby] ----- -RSpec.describe MyClass do - ... -end ----- - -over - -[source,ruby] ----- -describe MyClass do - ... -end ----- - -can be achieved using RSpec's `disable_monkey_patching!` method, which you can read more about in the https://relishapp.com/rspec/rspec-core/v/3-7/docs/configuration/zero-monkey-patching-mode#monkey-patched-methods-are-undefined-with-%60disable-monkey-patching!%60[RSpec Documentation]. This will also prevent `should` from being defined on every object in your system. - -Before disabling `should` you will need all your specs to use the `expect` syntax. You can use http://yujinakayama.me/transpec/[Transpec], which will do the conversion for you. +* Simplify the process of adopting new Capybara functionality diff --git a/docs/modules/ROOT/pages/installation.adoc b/docs/modules/ROOT/pages/installation.adoc index dda8f54..f4f2094 100644 --- a/docs/modules/ROOT/pages/installation.adoc +++ b/docs/modules/ROOT/pages/installation.adoc @@ -1,15 +1,15 @@ = Installation -Just install the `rubocop-rspec` gem +Just install the `rubocop-capybara` gem [source,bash] ---- -gem install rubocop-rspec +gem install rubocop-capybara ---- or if you use bundler put this in your `Gemfile` [source,ruby] ---- -gem 'rubocop-rspec' +gem 'rubocop-capybara' ---- diff --git a/docs/modules/ROOT/pages/usage.adoc b/docs/modules/ROOT/pages/usage.adoc index dd381a6..362c0e0 100644 --- a/docs/modules/ROOT/pages/usage.adoc +++ b/docs/modules/ROOT/pages/usage.adoc @@ -1,6 +1,6 @@ = Usage -You need to tell RuboCop to load the RSpec extension. +You need to tell RuboCop to load the Capybara extension. There are three ways to do this: == RuboCop configuration file @@ -8,77 +8,25 @@ There are three ways to do this: Put this into your `.rubocop.yml`: ---- -require: rubocop-rspec +require: rubocop-capybara ---- or, if you are using several extensions: ---- require: - - rubocop-rspec + - rubocop-capybara - rubocop-performance ---- -Now you can run `rubocop` and it will automatically load the RuboCop RSpec +Now you can run `rubocop` and it will automatically load the RuboCop Capybara 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] ---- -$ rubocop --require rubocop-rspec +$ rubocop --require rubocop-capybara ---- == Rake task @@ -86,22 +34,18 @@ $ rubocop --require rubocop-rspec [source,ruby] ---- RuboCop::RakeTask.new do |task| - task.requires << 'rubocop-rspec' + task.requires << 'rubocop-capybara' end ---- -== Code Climate - -`rubocop-rspec` is available on Code Climate as part of the rubocop engine. https://codeclimate.com/changelog/55a433bbe30ba00852000fac[Learn More]. - == Inspecting files that don't end with `_spec.rb` -By default, `rubocop-rspec` only inspects code within paths ending in `_spec.rb` or including `spec/`. You can override this setting in your config file by setting `Include`: +By default, `rubocop-capybara` 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 files in `test/` directory -RSpec: +Capybara: Include: - '**/test/**/*' ---- @@ -109,7 +53,7 @@ RSpec: [source,yaml] ---- # Inspect only files ending with `_test.rb` -RSpec: +Capybara: Include: - '**/*_test.rb' ---- diff --git a/lib/rubocop-capybara.rb b/lib/rubocop-capybara.rb index 0f7e534..48a638f 100644 --- a/lib/rubocop-capybara.rb +++ b/lib/rubocop-capybara.rb @@ -5,63 +5,20 @@ require 'rubocop' -require_relative 'rubocop/rspec' -require_relative 'rubocop/rspec/inject' -require_relative 'rubocop/rspec/language/node_pattern' -require_relative 'rubocop/rspec/node' -require_relative 'rubocop/rspec/version' -require_relative 'rubocop/rspec/wording' +require_relative 'rubocop/cop/capybara/mixin/capybara_help' +require_relative 'rubocop/cop/capybara/mixin/css_selector' -# Dependent on `RuboCop::RSpec::Language::NodePattern`. -require_relative 'rubocop/rspec/language' +require_relative 'rubocop/cop/capybara_cops' -require_relative 'rubocop/rspec/factory_bot/language' - -require_relative 'rubocop/cop/rspec/mixin/capybara_help' -require_relative 'rubocop/cop/rspec/mixin/css_selector' -require_relative 'rubocop/cop/rspec/mixin/final_end_location' -require_relative 'rubocop/cop/rspec/mixin/inside_example_group' -require_relative 'rubocop/cop/rspec/mixin/metadata' -require_relative 'rubocop/cop/rspec/mixin/namespace' -require_relative 'rubocop/cop/rspec/mixin/skip_or_pending' -require_relative 'rubocop/cop/rspec/mixin/top_level_group' -require_relative 'rubocop/cop/rspec/mixin/variable' - -# Dependent on `RuboCop::Cop::RSpec::FinalEndLocation`. -require_relative 'rubocop/cop/rspec/mixin/comments_help' -require_relative 'rubocop/cop/rspec/mixin/empty_line_separation' - -require_relative 'rubocop/cop/rspec/base' -require_relative 'rubocop/rspec/align_let_brace' -require_relative 'rubocop/rspec/concept' -require_relative 'rubocop/rspec/corrector/move_node' -require_relative 'rubocop/rspec/example' -require_relative 'rubocop/rspec/example_group' -require_relative 'rubocop/rspec/factory_bot' -require_relative 'rubocop/rspec/hook' - -RuboCop::RSpec::Inject.defaults! - -require_relative 'rubocop/cop/rspec_cops' - -# We have to register our autocorrect incompatibilities in RuboCop's cops -# as well so we do not hit infinite loops - -RuboCop::Cop::Layout::ExtraSpacing.singleton_class.prepend( - Module.new do - def autocorrect_incompatible_with - super.push(RuboCop::Cop::RSpec::AlignLeftLetBrace) - .push(RuboCop::Cop::RSpec::AlignRightLetBrace) - end - end -) +project_root = File.join(__dir__, '..') +RuboCop::ConfigLoader.inject_defaults!(project_root) +obsoletion = File.join(project_root, 'config', 'obsoletion.yml') +RuboCop::ConfigObsoletion.files << obsoletion if File.exist?(obsoletion) RuboCop::Cop::Style::TrailingCommaInArguments.singleton_class.prepend( Module.new do def autocorrect_incompatible_with - super.push(RuboCop::Cop::RSpec::Capybara::CurrentPathExpectation) + super.push(RuboCop::Cop::Capybara::CurrentPathExpectation) end end ) - -RuboCop::AST::Node.include(RuboCop::RSpec::Node) diff --git a/lib/rubocop/capybara/config_formatter.rb b/lib/rubocop/capybara/config_formatter.rb index 443daca..5a0848a 100644 --- a/lib/rubocop/capybara/config_formatter.rb +++ b/lib/rubocop/capybara/config_formatter.rb @@ -3,13 +3,13 @@ require 'yaml' module RuboCop - module RSpec + module Capybara # Builds a YAML config file from two config hashes class ConfigFormatter - EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze - SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails) - AMENDMENTS = %(Metrics/BlockLength) - COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/' + EXTENSION_ROOT_DEPARTMENT = %r{^(Capybara/)}.freeze + SUBDEPARTMENTS = [].freeze + AMENDMENTS = [].freeze + COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/' def initialize(config, descriptions) @config = config @@ -19,9 +19,9 @@ def initialize(config, descriptions) def dump YAML.dump(unified_config) .gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1") - .gsub(*AMENDMENTS, "\n\\0") .gsub(/^(\s+)- /, '\1 - ') .gsub('"~"', '~') + # .gsub(*AMENDMENTS, "\n\\0") end private diff --git a/lib/rubocop/capybara/description_extractor.rb b/lib/rubocop/capybara/description_extractor.rb index f63cbc3..3e9e51b 100644 --- a/lib/rubocop/capybara/description_extractor.rb +++ b/lib/rubocop/capybara/description_extractor.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module RuboCop - module RSpec + module Capybara # Extracts cop descriptions from YARD docstrings class DescriptionExtractor def initialize(yardocs) @@ -10,7 +10,7 @@ def initialize(yardocs) def to_h code_objects - .select(&:rspec_cop?) + .select(&:cop?) .map(&:configuration) .reduce(:merge) end @@ -19,21 +19,19 @@ def to_h attr_reader :code_objects - # Decorator of a YARD code object for working with documented rspec cops + # Decorator of a YARD code object for working with documented cops class CodeObject - RSPEC_COP_CLASS_NAME = 'RuboCop::Cop::RSpec::Base' RUBOCOP_COP_CLASS_NAME = 'RuboCop::Cop::Base' - RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec' def initialize(yardoc) @yardoc = yardoc end - # Test if the YARD code object documents a concrete rspec cop class + # Test if the YARD code object documents a concrete cop class # # @return [Boolean] - def rspec_cop? - cop_subclass? && !abstract? && rspec_cop_namespace? + def cop? + cop_subclass? && !abstract? end # Configuration for the documented cop that would live in default.yml @@ -53,17 +51,12 @@ def description yardoc.docstring.split("\n\n").first.to_s end - def rspec_cop_namespace? - documented_constant.start_with?(RSPEC_NAMESPACE) - end - def documented_constant yardoc.to_s end def cop_subclass? - yardoc.superclass.path == RSPEC_COP_CLASS_NAME || - yardoc.superclass.path == RUBOCOP_COP_CLASS_NAME + yardoc.superclass.path == RUBOCOP_COP_CLASS_NAME end def abstract? diff --git a/lib/rubocop/capybara/version.rb b/lib/rubocop/capybara/version.rb index 97448c1..8528cca 100644 --- a/lib/rubocop/capybara/version.rb +++ b/lib/rubocop/capybara/version.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true module RuboCop - module RSpec - # Version information for the RSpec RuboCop plugin. + module Capybara + # Version information for the Capybara RuboCop plugin. module Version - STRING = '2.16.0' + STRING = '2.17.0' end end end diff --git a/lib/rubocop/cop/capybara/current_path_expectation.rb b/lib/rubocop/cop/capybara/current_path_expectation.rb index 6b9b023..121fa11 100644 --- a/lib/rubocop/cop/capybara/current_path_expectation.rb +++ b/lib/rubocop/cop/capybara/current_path_expectation.rb @@ -2,122 +2,120 @@ module RuboCop module Cop - module RSpec - module Capybara - # 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. - # - # @example - # # 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') - # - 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 ${: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 ${:to :to_not :not_to} - $(send nil? :match (str $_))) - PATTERN - - def self.autocorrect_incompatible_with - [Style::TrailingCommaInArguments] - end + module Capybara + # 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. + # + # @example + # # 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') + # + 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 ${: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 ${: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| - next unless node.chained? + def on_send(node) + expectation_set_on_current_path(node) do + add_offense(node.loc.selector) do |corrector| + next unless node.chained? - autocorrect(corrector, node) - end + autocorrect(corrector, node) end end + end - private - - def autocorrect(corrector, node) - as_is_matcher(node.parent) do |to_sym, matcher_node| - rewrite_expectation(corrector, node, to_sym, matcher_node) - end + private - regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp| - rewrite_expectation(corrector, node, to_sym, matcher_node) - convert_regexp_str_to_literal(corrector, matcher_node, regexp) - end + def autocorrect(corrector, node) + as_is_matcher(node.parent) do |to_sym, matcher_node| + rewrite_expectation(corrector, node, to_sym, matcher_node) end - def rewrite_expectation(corrector, node, to_symbol, matcher_node) - current_path_node = node.first_argument - corrector.replace(current_path_node, 'page') - corrector.replace(node.parent.loc.selector, 'to') - matcher_method = if to_symbol == :to - 'have_current_path' - else - 'have_no_current_path' - end - corrector.replace(matcher_node.loc.selector, matcher_method) - add_ignore_query_options(corrector, node) + regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp| + rewrite_expectation(corrector, node, to_sym, matcher_node) + convert_regexp_str_to_literal(corrector, matcher_node, regexp) end + end - def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str) - str_node = matcher_node.first_argument - regexp_expr = Regexp.new(regexp_str).inspect - corrector.replace(str_node, regexp_expr) - end + def rewrite_expectation(corrector, node, to_symbol, matcher_node) + current_path_node = node.first_argument + corrector.replace(current_path_node, 'page') + corrector.replace(node.parent.loc.selector, 'to') + matcher_method = if to_symbol == :to + 'have_current_path' + else + 'have_no_current_path' + end + corrector.replace(matcher_node.loc.selector, matcher_method) + add_ignore_query_options(corrector, node) + end - # `have_current_path` with no options will include the querystring - # while `page.current_path` does not. - # This ensures the option `ignore_query: true` is added - # except when the expectation is a regexp or string - def add_ignore_query_options(corrector, node) - expectation_node = node.parent.last_argument - expectation_last_child = expectation_node.children.last - return if %i[regexp str].include?(expectation_last_child.type) - - corrector.insert_after( - expectation_last_child, - ', ignore_query: true' - ) - end + def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str) + str_node = matcher_node.first_argument + regexp_expr = Regexp.new(regexp_str).inspect + corrector.replace(str_node, regexp_expr) + end + + # `have_current_path` with no options will include the querystring + # while `page.current_path` does not. + # This ensures the option `ignore_query: true` is added + # except when the expectation is a regexp or string + def add_ignore_query_options(corrector, node) + expectation_node = node.parent.last_argument + expectation_last_child = expectation_node.children.last + return if %i[regexp str].include?(expectation_last_child.type) + + corrector.insert_after( + expectation_last_child, + ', ignore_query: true' + ) end end end diff --git a/lib/rubocop/cop/capybara/match_style.rb b/lib/rubocop/cop/capybara/match_style.rb index 13b2891..1b0e8e1 100644 --- a/lib/rubocop/cop/capybara/match_style.rb +++ b/lib/rubocop/cop/capybara/match_style.rb @@ -2,57 +2,55 @@ module RuboCop module Cop - module RSpec - module Capybara - # Checks for usage of deprecated style methods. - # - # @example when using `assert_style` - # # bad - # page.find(:css, '#first').assert_style(display: 'block') - # - # # good - # page.find(:css, '#first').assert_matches_style(display: 'block') - # - # @example when using `has_style?` - # # bad - # expect(page.find(:css, 'first') - # .has_style?(display: 'block')).to be true - # - # # good - # expect(page.find(:css, 'first') - # .matches_style?(display: 'block')).to be true - # - # @example when using `have_style` - # # bad - # expect(page).to have_style(display: 'block') - # - # # good - # expect(page).to match_style(display: 'block') - # - class MatchStyle < Base - extend AutoCorrector + module Capybara + # Checks for usage of deprecated style methods. + # + # @example when using `assert_style` + # # bad + # page.find(:css, '#first').assert_style(display: 'block') + # + # # good + # page.find(:css, '#first').assert_matches_style(display: 'block') + # + # @example when using `has_style?` + # # bad + # expect(page.find(:css, 'first') + # .has_style?(display: 'block')).to be true + # + # # good + # expect(page.find(:css, 'first') + # .matches_style?(display: 'block')).to be true + # + # @example when using `have_style` + # # bad + # expect(page).to have_style(display: 'block') + # + # # good + # expect(page).to match_style(display: 'block') + # + class MatchStyle < ::RuboCop::Cop::Base + extend AutoCorrector - MSG = 'Use `%s` instead of `%s`.' - RESTRICT_ON_SEND = %i[assert_style has_style? have_style].freeze - PREFERRED_METHOD = { - 'assert_style' => 'assert_matches_style', - 'has_style?' => 'matches_style?', - 'have_style' => 'match_style' - }.freeze + MSG = 'Use `%s` instead of `%s`.' + RESTRICT_ON_SEND = %i[assert_style has_style? have_style].freeze + PREFERRED_METHOD = { + 'assert_style' => 'assert_matches_style', + 'has_style?' => 'matches_style?', + 'have_style' => 'match_style' + }.freeze - def on_send(node) - method_node = node.loc.selector - add_offense(method_node) do |corrector| - corrector.replace(method_node, - PREFERRED_METHOD[method_node.source]) - end + def on_send(node) + method_node = node.loc.selector + add_offense(method_node) do |corrector| + corrector.replace(method_node, + PREFERRED_METHOD[method_node.source]) end + end - private + private - def message(node) - format(MSG, good: PREFERRED_METHOD[node.source], bad: node.source) - end + def message(node) + format(MSG, good: PREFERRED_METHOD[node.source], bad: node.source) end end end diff --git a/lib/rubocop/cop/capybara/mixin/capybara_help.rb b/lib/rubocop/cop/capybara/mixin/capybara_help.rb index 95a0acb..02ac720 100644 --- a/lib/rubocop/cop/capybara/mixin/capybara_help.rb +++ b/lib/rubocop/cop/capybara/mixin/capybara_help.rb @@ -2,78 +2,76 @@ module RuboCop module Cop - module RSpec - # Help methods for capybara. - module CapybaraHelp - module_function + # Help methods for capybara. + module CapybaraHelp + module_function - # @param node [RuboCop::AST::SendNode] - # @param locator [String] - # @param element [String] - # @return [Boolean] - def specific_option?(node, locator, element) - attrs = CssSelector.attributes(locator).keys - return false unless replaceable_element?(node, element, attrs) + # @param node [RuboCop::AST::SendNode] + # @param locator [String] + # @param element [String] + # @return [Boolean] + def specific_option?(node, locator, element) + attrs = CssSelector.attributes(locator).keys + return false unless replaceable_element?(node, element, attrs) - attrs.all? do |attr| - CssSelector.specific_options?(element, attr) - end + attrs.all? do |attr| + CssSelector.specific_options?(element, attr) end + end - # @param locator [String] - # @return [Boolean] - def specific_pseudo_classes?(locator) - CssSelector.pseudo_classes(locator).all? do |pseudo_class| - replaceable_pseudo_class?(pseudo_class, locator) - end + # @param locator [String] + # @return [Boolean] + def specific_pseudo_classes?(locator) + CssSelector.pseudo_classes(locator).all? do |pseudo_class| + replaceable_pseudo_class?(pseudo_class, locator) end + end - # @param pseudo_class [String] - # @param locator [String] - # @return [Boolean] - def replaceable_pseudo_class?(pseudo_class, locator) - return false unless CssSelector.specific_pesudo_classes?(pseudo_class) + # @param pseudo_class [String] + # @param locator [String] + # @return [Boolean] + def replaceable_pseudo_class?(pseudo_class, locator) + return false unless CssSelector.specific_pesudo_classes?(pseudo_class) - case pseudo_class - when 'not()' then replaceable_pseudo_class_not?(locator) - else true - end + case pseudo_class + when 'not()' then replaceable_pseudo_class_not?(locator) + else true end + end - # @param locator [String] - # @return [Boolean] - def replaceable_pseudo_class_not?(locator) - locator.scan(/not\(.*?\)/).all? do |negation| - CssSelector.attributes(negation).values.all? do |v| - v.is_a?(TrueClass) || v.is_a?(FalseClass) - end + # @param locator [String] + # @return [Boolean] + def replaceable_pseudo_class_not?(locator) + locator.scan(/not\(.*?\)/).all? do |negation| + CssSelector.attributes(negation).values.all? do |v| + v.is_a?(TrueClass) || v.is_a?(FalseClass) end end + end - # @param node [RuboCop::AST::SendNode] - # @param element [String] - # @param attrs [Array] - # @return [Boolean] - def replaceable_element?(node, element, attrs) - case element - when 'link' then replaceable_to_link?(node, attrs) - else true - end + # @param node [RuboCop::AST::SendNode] + # @param element [String] + # @param attrs [Array] + # @return [Boolean] + def replaceable_element?(node, element, attrs) + case element + when 'link' then replaceable_to_link?(node, attrs) + else true end + end - # @param node [RuboCop::AST::SendNode] - # @param attrs [Array] - # @return [Boolean] - def replaceable_to_link?(node, attrs) - include_option?(node, :href) || attrs.include?('href') - end + # @param node [RuboCop::AST::SendNode] + # @param attrs [Array] + # @return [Boolean] + def replaceable_to_link?(node, attrs) + include_option?(node, :href) || attrs.include?('href') + end - # @param node [RuboCop::AST::SendNode] - # @param option [Symbol] - # @return [Boolean] - def include_option?(node, option) - node.each_descendant(:sym).find { |opt| opt.value == option } - end + # @param node [RuboCop::AST::SendNode] + # @param option [Symbol] + # @return [Boolean] + def include_option?(node, option) + node.each_descendant(:sym).find { |opt| opt.value == option } end end end diff --git a/lib/rubocop/cop/capybara/mixin/css_selector.rb b/lib/rubocop/cop/capybara/mixin/css_selector.rb index 3fc2603..8e7fe8a 100644 --- a/lib/rubocop/cop/capybara/mixin/css_selector.rb +++ b/lib/rubocop/cop/capybara/mixin/css_selector.rb @@ -2,143 +2,141 @@ module RuboCop module Cop - module RSpec - # Helps parsing css selector. - module CssSelector - COMMON_OPTIONS = %w[ - above below left_of right_of near count minimum maximum between text - id class style visible obscured exact exact_text normalize_ws match - wait filter_set focused - ].freeze - SPECIFIC_OPTIONS = { - 'button' => ( - COMMON_OPTIONS + %w[disabled name value title type] - ).freeze, - 'link' => ( - COMMON_OPTIONS + %w[href alt title download] - ).freeze, - 'table' => ( - COMMON_OPTIONS + %w[ - caption with_cols cols with_rows rows - ] - ).freeze, - 'select' => ( - COMMON_OPTIONS + %w[ - disabled name placeholder options enabled_options - disabled_options selected with_selected multiple with_options - ] - ).freeze, - 'field' => ( - COMMON_OPTIONS + %w[ - checked unchecked disabled valid name placeholder - validation_message readonly with type multiple - ] - ).freeze - }.freeze - SPECIFIC_PSEUDO_CLASSES = %w[ - not() disabled enabled checked unchecked - ].freeze + # Helps parsing css selector. + module CssSelector + COMMON_OPTIONS = %w[ + above below left_of right_of near count minimum maximum between text + id class style visible obscured exact exact_text normalize_ws match + wait filter_set focused + ].freeze + SPECIFIC_OPTIONS = { + 'button' => ( + COMMON_OPTIONS + %w[disabled name value title type] + ).freeze, + 'link' => ( + COMMON_OPTIONS + %w[href alt title download] + ).freeze, + 'table' => ( + COMMON_OPTIONS + %w[ + caption with_cols cols with_rows rows + ] + ).freeze, + 'select' => ( + COMMON_OPTIONS + %w[ + disabled name placeholder options enabled_options + disabled_options selected with_selected multiple with_options + ] + ).freeze, + 'field' => ( + COMMON_OPTIONS + %w[ + checked unchecked disabled valid name placeholder + validation_message readonly with type multiple + ] + ).freeze + }.freeze + SPECIFIC_PSEUDO_CLASSES = %w[ + not() disabled enabled checked unchecked + ].freeze - module_function + module_function - # @param element [String] - # @param attribute [String] - # @return [Boolean] - # @example - # specific_pesudo_classes?('button', 'name') # => true - # specific_pesudo_classes?('link', 'invalid') # => false - def specific_options?(element, attribute) - SPECIFIC_OPTIONS.fetch(element, []).include?(attribute) - end + # @param element [String] + # @param attribute [String] + # @return [Boolean] + # @example + # specific_pesudo_classes?('button', 'name') # => true + # specific_pesudo_classes?('link', 'invalid') # => false + def specific_options?(element, attribute) + SPECIFIC_OPTIONS.fetch(element, []).include?(attribute) + end - # @param pseudo_class [String] - # @return [Boolean] - # @example - # specific_pesudo_classes?('disabled') # => true - # specific_pesudo_classes?('first-of-type') # => false - def specific_pesudo_classes?(pseudo_class) - SPECIFIC_PSEUDO_CLASSES.include?(pseudo_class) - end + # @param pseudo_class [String] + # @return [Boolean] + # @example + # specific_pesudo_classes?('disabled') # => true + # specific_pesudo_classes?('first-of-type') # => false + def specific_pesudo_classes?(pseudo_class) + SPECIFIC_PSEUDO_CLASSES.include?(pseudo_class) + end - # @param selector [String] - # @return [Boolean] - # @example - # id?('#some-id') # => true - # id?('.some-class') # => false - def id?(selector) - selector.start_with?('#') - end + # @param selector [String] + # @return [Boolean] + # @example + # id?('#some-id') # => true + # id?('.some-class') # => false + def id?(selector) + selector.start_with?('#') + end - # @param selector [String] - # @return [Boolean] - # @example - # attribute?('[attribute]') # => true - # attribute?('attribute') # => false - def attribute?(selector) - selector.start_with?('[') - end + # @param selector [String] + # @return [Boolean] + # @example + # attribute?('[attribute]') # => true + # attribute?('attribute') # => false + def attribute?(selector) + selector.start_with?('[') + end - # @param selector [String] - # @return [Array] - # @example - # attributes('a[foo-bar_baz]') # => {"foo-bar_baz=>true} - # attributes('button[foo][bar]') # => {"foo"=>true, "bar"=>true} - # attributes('table[foo=bar]') # => {"foo"=>"'bar'"} - def attributes(selector) - selector.scan(/\[(.*?)\]/).flatten.to_h do |attr| - key, value = attr.split('=') - [key, normalize_value(value)] - end + # @param selector [String] + # @return [Array] + # @example + # attributes('a[foo-bar_baz]') # => {"foo-bar_baz=>true} + # attributes('button[foo][bar]') # => {"foo"=>true, "bar"=>true} + # attributes('table[foo=bar]') # => {"foo"=>"'bar'"} + def attributes(selector) + selector.scan(/\[(.*?)\]/).flatten.to_h do |attr| + key, value = attr.split('=') + [key, normalize_value(value)] end + end - # @param selector [String] - # @return [Boolean] - # @example - # common_attributes?('a[focused]') # => true - # common_attributes?('button[focused][visible]') # => true - # common_attributes?('table[id=some-id]') # => true - # common_attributes?('h1[invalid]') # => false - def common_attributes?(selector) - attributes(selector).keys.difference(COMMON_OPTIONS).none? - end + # @param selector [String] + # @return [Boolean] + # @example + # common_attributes?('a[focused]') # => true + # common_attributes?('button[focused][visible]') # => true + # common_attributes?('table[id=some-id]') # => true + # common_attributes?('h1[invalid]') # => false + def common_attributes?(selector) + attributes(selector).keys.difference(COMMON_OPTIONS).none? + end - # @param selector [String] - # @return [Array] - # @example - # pseudo_classes('button:not([disabled])') # => ['not()'] - # pseudo_classes('a:enabled:not([valid])') # => ['enabled', 'not()'] - def pseudo_classes(selector) - # Attributes must be excluded or else the colon in the `href`s URL - # will also be picked up as pseudo classes. - # "a:not([href='http://example.com']):enabled" => "a:not():enabled" - ignored_attribute = selector.gsub(/\[.*?\]/, '') - # "a:not():enabled" => ["not()", "enabled"] - ignored_attribute.scan(/:([^:]*)/).flatten - end + # @param selector [String] + # @return [Array] + # @example + # pseudo_classes('button:not([disabled])') # => ['not()'] + # pseudo_classes('a:enabled:not([valid])') # => ['enabled', 'not()'] + def pseudo_classes(selector) + # Attributes must be excluded or else the colon in the `href`s URL + # will also be picked up as pseudo classes. + # "a:not([href='http://example.com']):enabled" => "a:not():enabled" + ignored_attribute = selector.gsub(/\[.*?\]/, '') + # "a:not():enabled" => ["not()", "enabled"] + ignored_attribute.scan(/:([^:]*)/).flatten + end - # @param selector [String] - # @return [Boolean] - # @example - # multiple_selectors?('a.cls b#id') # => true - # multiple_selectors?('a.cls') # => false - def multiple_selectors?(selector) - selector.match?(/[ >,+~]/) - end + # @param selector [String] + # @return [Boolean] + # @example + # multiple_selectors?('a.cls b#id') # => true + # multiple_selectors?('a.cls') # => false + def multiple_selectors?(selector) + selector.match?(/[ >,+~]/) + end - # @param value [String] - # @return [Boolean, String] - # @example - # normalize_value('true') # => true - # normalize_value('false') # => false - # normalize_value(nil) # => false - # normalize_value("foo") # => "'foo'" - def normalize_value(value) - case value - when 'true' then true - when 'false' then false - when nil then true - else "'#{value}'" - end + # @param value [String] + # @return [Boolean, String] + # @example + # normalize_value('true') # => true + # normalize_value('false') # => false + # normalize_value(nil) # => false + # normalize_value("foo") # => "'foo'" + def normalize_value(value) + case value + when 'true' then true + when 'false' then false + when nil then true + else "'#{value}'" end end end diff --git a/lib/rubocop/cop/capybara/negation_matcher.rb b/lib/rubocop/cop/capybara/negation_matcher.rb index 57e3c75..1adcce4 100644 --- a/lib/rubocop/cop/capybara/negation_matcher.rb +++ b/lib/rubocop/cop/capybara/negation_matcher.rb @@ -2,102 +2,100 @@ 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 + 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 + 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 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 + # @!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) + 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 + 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 + private - def offense?(node) - (style == :have_no && not_to?(node)) || - (style == :not_to && have_no?(node)) - end + 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 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 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 + 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 + 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 diff --git a/lib/rubocop/cop/capybara/specific_actions.rb b/lib/rubocop/cop/capybara/specific_actions.rb index a25a4eb..a15f8fa 100644 --- a/lib/rubocop/cop/capybara/specific_actions.rb +++ b/lib/rubocop/cop/capybara/specific_actions.rb @@ -2,82 +2,80 @@ 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 + 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 + # @!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) + 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 + range = offense_range(node, node.receiver) + add_offense(range, message: message(action, selector)) end + end - private + private - def specific_action(selector) - SPECIFIC_ACTION[last_selector(selector)] - end + def specific_action(selector) + SPECIFIC_ACTION[last_selector(selector)] + end - def supported_selector?(selector) - !selector.match?(/[>,+~]/) - end + def supported_selector?(selector) + !selector.match?(/[>,+~]/) + end - def last_selector(arg) - arg.split.last[/^\w+/, 0] - 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 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 message(action, selector) + format(MSG, + good_action: good_action(action), + selector: selector) + end - def good_action(action) - "click_#{action}" - end + def good_action(action) + "click_#{action}" end end end diff --git a/lib/rubocop/cop/capybara/specific_finders.rb b/lib/rubocop/cop/capybara/specific_finders.rb index 805e827..8bc5190 100644 --- a/lib/rubocop/cop/capybara/specific_finders.rb +++ b/lib/rubocop/cop/capybara/specific_finders.rb @@ -2,89 +2,87 @@ 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 + 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 + private - def on_attr(node, arg) - return unless (id = CssSelector.attributes(arg)['id']) + def on_attr(node, arg) + return unless (id = CssSelector.attributes(arg)['id']) - register_offense(node, replaced_arguments(arg, id)) - end + register_offense(node, replaced_arguments(arg, id)) + end - def on_id(node, arg) - register_offense(node, "'#{arg.to_s.delete('#')}'") - 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 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 + 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 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' + def to_options(attrs) + attrs.each.map do |key, value| + next if key == 'id' - "#{key}: #{value}" - end.compact.join(', ') - end + "#{key}: #{value}" + end.compact.join(', ') + end - def offense_range(node) - range_between(node.loc.selector.begin_pos, end_pos(node)) - 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 + def end_pos(node) + if node.loc.end + node.loc.end.end_pos + else + node.loc.expression.end_pos end end end diff --git a/lib/rubocop/cop/capybara/specific_matcher.rb b/lib/rubocop/cop/capybara/specific_matcher.rb index e9ef2c0..1f8a8ed 100644 --- a/lib/rubocop/cop/capybara/specific_matcher.rb +++ b/lib/rubocop/cop/capybara/specific_matcher.rb @@ -2,76 +2,74 @@ 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 + 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 + # @!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) + 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 + add_offense(node, message: message(node, matcher)) end + end - private + private - def specific_matcher(arg) - splitted_arg = arg[/^\w+/, 0] - SPECIFIC_MATCHER[splitted_arg] - end + 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 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 + def good_matcher(node, matcher) + node.method_name + .to_s + .gsub(/selector|css/, matcher.to_s) end end end diff --git a/lib/rubocop/cop/capybara/visibility_matcher.rb b/lib/rubocop/cop/capybara/visibility_matcher.rb index 99f3a66..c06e38a 100644 --- a/lib/rubocop/cop/capybara/visibility_matcher.rb +++ b/lib/rubocop/cop/capybara/visibility_matcher.rb @@ -2,70 +2,68 @@ module RuboCop module Cop - module RSpec - module Capybara - # Checks for boolean visibility in Capybara finders. - # - # Capybara lets you find elements that match a certain visibility using - # the `:visible` option. `:visible` accepts both boolean and symbols as - # values, however using booleans can have unwanted effects. `visible: - # false` does not find just invisible elements, but both visible and - # invisible elements. For expressiveness and clarity, use one of the - # symbol values, `:all`, `:hidden` or `:visible`. - # 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) - # expect(page).to have_link('my link', visible: false) - # - # # good - # expect(page).to have_selector('.foo', visible: :visible) - # expect(page).to have_css('.foo', visible: :all) - # expect(page).to have_link('my link', visible: :hidden) - # - class VisibilityMatcher < ::RuboCop::Cop::Base - MSG_FALSE = 'Use `:all` or `:hidden` instead of `false`.' - MSG_TRUE = 'Use `:visible` instead of `true`.' - 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 + module Capybara + # Checks for boolean visibility in Capybara finders. + # + # Capybara lets you find elements that match a certain visibility using + # the `:visible` option. `:visible` accepts both boolean and symbols as + # values, however using booleans can have unwanted effects. `visible: + # false` does not find just invisible elements, but both visible and + # invisible elements. For expressiveness and clarity, use one of the + # symbol values, `:all`, `:hidden` or `:visible`. + # 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) + # expect(page).to have_link('my link', visible: false) + # + # # good + # expect(page).to have_selector('.foo', visible: :visible) + # expect(page).to have_css('.foo', visible: :all) + # expect(page).to have_link('my link', visible: :hidden) + # + class VisibilityMatcher < ::RuboCop::Cop::Base + MSG_FALSE = 'Use `:all` or `:hidden` instead of `false`.' + MSG_TRUE = 'Use `:visible` instead of `true`.' + 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 + 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_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 + # @!method visible_false?(node) + def_node_matcher :visible_false?, <<~PATTERN + (send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) false) ...>)) + PATTERN - def on_send(node) - visible_false?(node) { |arg| add_offense(arg, message: MSG_FALSE) } - visible_true?(node) { |arg| add_offense(arg, message: MSG_TRUE) } - end + def on_send(node) + visible_false?(node) { |arg| add_offense(arg, message: MSG_FALSE) } + visible_true?(node) { |arg| add_offense(arg, message: MSG_TRUE) } + end - private + private - def capybara_matcher?(method_name) - CAPYBARA_MATCHER_METHODS.include? method_name - end + def capybara_matcher?(method_name) + CAPYBARA_MATCHER_METHODS.include? method_name end end end diff --git a/lib/rubocop/cop/capybara_cops.rb b/lib/rubocop/cop/capybara_cops.rb index 619ada0..5166e6e 100644 --- a/lib/rubocop/cop/capybara_cops.rb +++ b/lib/rubocop/cop/capybara_cops.rb @@ -1,119 +1,9 @@ # frozen_string_literal: true -require_relative 'rspec/capybara/current_path_expectation' -require_relative 'rspec/capybara/feature_methods' -require_relative 'rspec/capybara/match_style' -require_relative 'rspec/capybara/negation_matcher' -require_relative 'rspec/capybara/specific_actions' -require_relative 'rspec/capybara/specific_finders' -require_relative 'rspec/capybara/specific_matcher' -require_relative 'rspec/capybara/visibility_matcher' - -require_relative 'rspec/factory_bot/attribute_defined_statically' -require_relative 'rspec/factory_bot/consistent_parentheses_style' -require_relative 'rspec/factory_bot/create_list' -require_relative 'rspec/factory_bot/factory_class_name' -require_relative 'rspec/factory_bot/factory_name_style' -require_relative 'rspec/factory_bot/syntax_methods' - -require_relative 'rspec/rails/avoid_setup_hook' -require_relative 'rspec/rails/have_http_status' -begin - require_relative 'rspec/rails/http_status' -rescue LoadError - # Rails/HttpStatus cannot be loaded if rack/utils is unavailable. -end -require_relative 'rspec/rails/inferred_spec_type' -require_relative 'rspec/rails/minitest_assertions' - -require_relative 'rspec/align_left_let_brace' -require_relative 'rspec/align_right_let_brace' -require_relative 'rspec/any_instance' -require_relative 'rspec/around_block' -require_relative 'rspec/be' -require_relative 'rspec/be_eq' -require_relative 'rspec/be_eql' -require_relative 'rspec/be_nil' -require_relative 'rspec/before_after_all' -require_relative 'rspec/change_by_zero' -require_relative 'rspec/class_check' -require_relative 'rspec/context_method' -require_relative 'rspec/context_wording' -require_relative 'rspec/describe_class' -require_relative 'rspec/describe_method' -require_relative 'rspec/describe_symbol' -require_relative 'rspec/described_class' -require_relative 'rspec/described_class_module_wrapping' -require_relative 'rspec/dialect' -require_relative 'rspec/duplicated_metadata' -require_relative 'rspec/empty_example_group' -require_relative 'rspec/empty_hook' -require_relative 'rspec/empty_line_after_example' -require_relative 'rspec/empty_line_after_example_group' -require_relative 'rspec/empty_line_after_final_let' -require_relative 'rspec/empty_line_after_hook' -require_relative 'rspec/empty_line_after_subject' -require_relative 'rspec/example_length' -require_relative 'rspec/example_without_description' -require_relative 'rspec/example_wording' -require_relative 'rspec/excessive_docstring_spacing' -require_relative 'rspec/expect_actual' -require_relative 'rspec/expect_change' -require_relative 'rspec/expect_in_hook' -require_relative 'rspec/expect_output' -require_relative 'rspec/file_path' -require_relative 'rspec/focus' -require_relative 'rspec/hook_argument' -require_relative 'rspec/hooks_before_examples' -require_relative 'rspec/identical_equality_assertion' -require_relative 'rspec/implicit_block_expectation' -require_relative 'rspec/implicit_expect' -require_relative 'rspec/implicit_subject' -require_relative 'rspec/instance_spy' -require_relative 'rspec/instance_variable' -require_relative 'rspec/it_behaves_like' -require_relative 'rspec/iterated_expectation' -require_relative 'rspec/leading_subject' -require_relative 'rspec/leaky_constant_declaration' -require_relative 'rspec/let_before_examples' -require_relative 'rspec/let_setup' -require_relative 'rspec/message_chain' -require_relative 'rspec/message_expectation' -require_relative 'rspec/message_spies' -require_relative 'rspec/missing_example_group_argument' -require_relative 'rspec/multiple_describes' -require_relative 'rspec/multiple_expectations' -require_relative 'rspec/multiple_memoized_helpers' -require_relative 'rspec/multiple_subjects' -require_relative 'rspec/named_subject' -require_relative 'rspec/nested_groups' -require_relative 'rspec/no_expectation_example' -require_relative 'rspec/not_to_not' -require_relative 'rspec/overwriting_setup' -require_relative 'rspec/pending' -require_relative 'rspec/pending_without_reason' -require_relative 'rspec/predicate_matcher' -require_relative 'rspec/receive_counts' -require_relative 'rspec/receive_never' -require_relative 'rspec/repeated_description' -require_relative 'rspec/repeated_example' -require_relative 'rspec/repeated_example_group_body' -require_relative 'rspec/repeated_example_group_description' -require_relative 'rspec/repeated_include_example' -require_relative 'rspec/return_from_stub' -require_relative 'rspec/scattered_let' -require_relative 'rspec/scattered_setup' -require_relative 'rspec/shared_context' -require_relative 'rspec/shared_examples' -require_relative 'rspec/single_argument_message_chain' -require_relative 'rspec/sort_metadata' -require_relative 'rspec/stubbed_mock' -require_relative 'rspec/subject_declaration' -require_relative 'rspec/subject_stub' -require_relative 'rspec/unspecified_exception' -require_relative 'rspec/variable_definition' -require_relative 'rspec/variable_name' -require_relative 'rspec/verified_double_reference' -require_relative 'rspec/verified_doubles' -require_relative 'rspec/void_expect' -require_relative 'rspec/yield' +require_relative 'capybara/current_path_expectation' +require_relative 'capybara/match_style' +require_relative 'capybara/negation_matcher' +require_relative 'capybara/specific_actions' +require_relative 'capybara/specific_finders' +require_relative 'capybara/specific_matcher' +require_relative 'capybara/visibility_matcher' diff --git a/rubocop-capybara.gemspec b/rubocop-capybara.gemspec index b96c366..20d9be2 100644 --- a/rubocop-capybara.gemspec +++ b/rubocop-capybara.gemspec @@ -1,25 +1,20 @@ # frozen_string_literal: true $LOAD_PATH.unshift File.expand_path('lib', __dir__) -require 'rubocop/rspec/version' +require 'rubocop/capybara/version' Gem::Specification.new do |spec| - spec.name = 'rubocop-rspec' - spec.summary = 'Code style checking for RSpec files' + spec.name = 'rubocop-capybara' + spec.summary = 'Code style checking for Capybara test files' spec.description = <<-DESCRIPTION - Code style checking for RSpec files. + Code style checking for Capybara test files (RSpec, Cucumber, Minitest). A plugin for the RuboCop code style enforcing & linting tool. DESCRIPTION - spec.homepage = 'https://github.com/rubocop/rubocop-rspec' - spec.authors = ['John Backus', 'Ian MacLeod', 'Nils Gemeinhardt'] - spec.email = [ - 'johncbackus@gmail.com', - 'ian@nevir.net', - 'git@nilsgemeinhardt.de' - ] + spec.homepage = 'https://github.com/rubocop/rubocop-capybara' + spec.authors = ['Yudai Takada'] spec.licenses = ['MIT'] - spec.version = RuboCop::RSpec::Version::STRING + spec.version = RuboCop::Capybara::Version::STRING spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.6.0' @@ -32,10 +27,10 @@ Gem::Specification.new do |spec| spec.extra_rdoc_files = ['MIT-LICENSE.md', 'README.md'] spec.metadata = { - 'changelog_uri' => 'https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md', - 'documentation_uri' => 'https://docs.rubocop.org/rubocop-rspec/', + 'changelog_uri' => 'https://github.com/rubocop/rubocop-capybara/blob/master/CHANGELOG.md', + 'documentation_uri' => 'https://docs.rubocop.org/rubocop-capybara/', 'rubygems_mfa_required' => 'true' } - spec.add_runtime_dependency 'rubocop', '~> 1.33' + spec.add_runtime_dependency 'rubocop', '~> 1.41' end diff --git a/spec/project/default_config_spec.rb b/spec/project/default_config_spec.rb index 1adbbdb..48e458a 100644 --- a/spec/project/default_config_spec.rb +++ b/spec/project/default_config_spec.rb @@ -7,25 +7,18 @@ let(:namespaces) do { - 'rspec' => 'RSpec', - 'capybara' => 'RSpec/Capybara', - 'factory_bot' => 'RSpec/FactoryBot', - 'rails' => 'RSpec/Rails' + 'capybara' => 'Capybara' } end let(:cop_names) do - glob = SpecHelper::ROOT.join('lib', 'rubocop', 'cop', 'rspec', - '{,capybara,factory_bot,rails}', '*.rb') - cop_names = - Pathname.glob(glob).map do |file| - file_name = file.basename('.rb').to_s - cop_name = file_name.gsub(/(^|_)(.)/) { Regexp.last_match(2).upcase } - namespace = namespaces[file.dirname.basename.to_s] - "#{namespace}/#{cop_name}" - end - - cop_names - %w[RSpec/Base] + glob = SpecHelper::ROOT.join('lib', 'rubocop', 'cop', 'capybara', '*.rb') + Pathname.glob(glob).map do |file| + file_name = file.basename('.rb').to_s + cop_name = file_name.gsub(/(^|_)(.)/) { Regexp.last_match(2).upcase } + namespace = namespaces[file.dirname.basename.to_s] + "#{namespace}/#{cop_name}" + end end let(:config_keys) do @@ -42,23 +35,23 @@ def cop_configuration(config_key) end end - it 'has configuration for all cops and amendments' do + it 'has configuration for all cops' do expect(default_config.keys) - .to match_array([*config_keys, 'Metrics/BlockLength']) + .to match_array(config_keys) end it 'sorts configuration keys alphabetically with nested namespaces last' do - rspec_keys = default_config.keys.select { |key| key.start_with?('RSpec') } - namespaced_rspec_keys = rspec_keys.select do |key| - key.start_with?(*(namespaces.values - ['RSpec'])) + keys = default_config.keys.select { |key| key.start_with?('Capybara') } + namespaced_keys = keys.select do |key| + key.start_with?(*(namespaces.values - ['Capybara'])) end - expected = rspec_keys.sort_by do |key| - namespaced = namespaced_rspec_keys.include?(key) ? 1 : 0 + expected = keys.sort_by do |key| + namespaced = namespaced_keys.include?(key) ? 1 : 0 "#{namespaced} #{key}" end - rspec_keys.each_with_index do |key, idx| + keys.each_with_index do |key, idx| expect(key).to eq expected[idx] end end diff --git a/spec/rubocop/capybara/config_formatter_spec.rb b/spec/rubocop/capybara/config_formatter_spec.rb index 262aeb2..af8e11b 100644 --- a/spec/rubocop/capybara/config_formatter_spec.rb +++ b/spec/rubocop/capybara/config_formatter_spec.rb @@ -1,22 +1,22 @@ # frozen_string_literal: true -require 'rubocop/rspec/config_formatter' +require 'rubocop/capybara/config_formatter' -RSpec.describe RuboCop::RSpec::ConfigFormatter do +RSpec.describe RuboCop::Capybara::ConfigFormatter do let(:config) do { 'AllCops' => { 'Setting' => 'forty two' }, - 'RSpec/Foo' => { + 'Capybara/Foo' => { 'Config' => 2, 'Enabled' => true }, - 'RSpec/Bar' => { + 'Capybara/Bar' => { 'Enabled' => true, 'Nullable' => nil }, - 'RSpec/Baz' => { + 'Capybara/Baz' => { 'Enabled' => true, 'StyleGuide' => '#buzz' } @@ -25,13 +25,13 @@ let(:descriptions) do { - 'RSpec/Foo' => { + 'Capybara/Foo' => { 'Description' => 'Blah' }, - 'RSpec/Bar' => { + 'Capybara/Bar' => { 'Description' => 'Wow' }, - 'RSpec/Baz' => { + 'Capybara/Baz' => { 'Description' => 'Woof' } } @@ -45,23 +45,23 @@ |AllCops: | Setting: forty two | - |RSpec/Foo: + |Capybara/Foo: | Config: 2 | Enabled: true | Description: Blah - | Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Foo + | Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/Foo | - |RSpec/Bar: + |Capybara/Bar: | Enabled: true | Nullable: ~ | Description: Wow - | Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Bar + | Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/Bar | - |RSpec/Baz: + |Capybara/Baz: | Enabled: true | StyleGuide: "#buzz" | Description: Woof - | Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Baz + | Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/Baz YAML end end diff --git a/spec/rubocop/capybara/description_extractor_spec.rb b/spec/rubocop/capybara/description_extractor_spec.rb index 6e2134e..ea24335 100644 --- a/spec/rubocop/capybara/description_extractor_spec.rb +++ b/spec/rubocop/capybara/description_extractor_spec.rb @@ -2,9 +2,9 @@ require 'yard' -require 'rubocop/rspec/description_extractor' +require 'rubocop/capybara/description_extractor' -RSpec.describe RuboCop::RSpec::DescriptionExtractor do +RSpec.describe RuboCop::Capybara::DescriptionExtractor do let(:yardocs) do YARD.parse_string(<<-RUBY) # This is not a cop @@ -14,7 +14,7 @@ class RuboCop::Cop::Mixin::Sneaky # This is not a concrete cop # # @abstract - class RuboCop::Cop::RSpec::Base + class RuboCop::Cop::Capybara::Base end # Checks foo @@ -22,7 +22,7 @@ class RuboCop::Cop::RSpec::Base # Some description # # @note only works with foo - class RuboCop::Cop::RSpec::Foo < RuboCop::Cop::RSpec::Base + class RuboCop::Cop::Capybara::Foo < RuboCop::Cop::Base # Hello def bar end @@ -32,7 +32,7 @@ class HelperClassForFoo end end - class RuboCop::Cop::RSpec::Undocumented < RuboCop::Cop::RSpec::Base + class RuboCop::Cop::Capybara::Undocumented < RuboCop::Cop::Base # Hello def bar end @@ -54,7 +54,7 @@ def inherited(*) end # rubocop:disable Lint/MissingSuper end def stub_cop_const(name) - stub_const("RuboCop::Cop::RSpec::#{name}", Class.new(temp_class)) + stub_const("RuboCop::Cop::Capybara::#{name}", Class.new(temp_class)) end before do @@ -64,8 +64,8 @@ def stub_cop_const(name) it 'builds a hash of descriptions' do expect(described_class.new(yardocs).to_h).to eql( - 'RSpec/Foo' => { 'Description' => 'Checks foo' }, - 'RSpec/Undocumented' => { 'Description' => '' } + 'Capybara/Foo' => { 'Description' => 'Checks foo' }, + 'Capybara/Undocumented' => { 'Description' => '' } ) end end diff --git a/spec/rubocop/cop/capybara/current_path_expectation_spec.rb b/spec/rubocop/cop/capybara/current_path_expectation_spec.rb index 5fbed50..6da1662 100644 --- a/spec/rubocop/cop/capybara/current_path_expectation_spec.rb +++ b/spec/rubocop/cop/capybara/current_path_expectation_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::RSpec::Capybara::CurrentPathExpectation do +RSpec.describe RuboCop::Cop::Capybara::CurrentPathExpectation do it 'flags violations for `expect(current_path)`' do expect_offense(<<~RUBY) expect(current_path).to eq "/callback" diff --git a/spec/rubocop/cop/capybara/match_style_spec.rb b/spec/rubocop/cop/capybara/match_style_spec.rb index 12600a3..d64eef2 100644 --- a/spec/rubocop/cop/capybara/match_style_spec.rb +++ b/spec/rubocop/cop/capybara/match_style_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::RSpec::Capybara::MatchStyle, :config do +RSpec.describe RuboCop::Cop::Capybara::MatchStyle, :config do it 'registers an offense when using `assert_style`' do expect_offense(<<~RUBY) page.find(:css, '#first').assert_style(display: 'block') diff --git a/spec/rubocop/cop/capybara/negation_matcher_spec.rb b/spec/rubocop/cop/capybara/negation_matcher_spec.rb index f84702c..f4ccfa6 100644 --- a/spec/rubocop/cop/capybara/negation_matcher_spec.rb +++ b/spec/rubocop/cop/capybara/negation_matcher_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::RSpec::Capybara::NegationMatcher, :config do +RSpec.describe RuboCop::Cop::Capybara::NegationMatcher, :config do let(:cop_config) { { 'EnforcedStyle' => enforced_style } } context 'with EnforcedStyle `have_no`' do diff --git a/spec/rubocop/cop/capybara/specific_actions_spec.rb b/spec/rubocop/cop/capybara/specific_actions_spec.rb index 84ee67d..985549e 100644 --- a/spec/rubocop/cop/capybara/specific_actions_spec.rb +++ b/spec/rubocop/cop/capybara/specific_actions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::RSpec::Capybara::SpecificActions, :config do +RSpec.describe RuboCop::Cop::Capybara::SpecificActions, :config do it 'does not register an offense for find and click action when ' \ 'first argument is link' do expect_no_offenses(<<~RUBY) diff --git a/spec/rubocop/cop/capybara/specific_finders_spec.rb b/spec/rubocop/cop/capybara/specific_finders_spec.rb index fc2bda6..24b0795 100644 --- a/spec/rubocop/cop/capybara/specific_finders_spec.rb +++ b/spec/rubocop/cop/capybara/specific_finders_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::RSpec::Capybara::SpecificFinders, :config do +RSpec.describe RuboCop::Cop::Capybara::SpecificFinders, :config do it 'registers an offense when using `find`' do expect_offense(<<~RUBY) find('#some-id') diff --git a/spec/rubocop/cop/capybara/specific_matcher_spec.rb b/spec/rubocop/cop/capybara/specific_matcher_spec.rb index 0a605cd..0b2d68d 100644 --- a/spec/rubocop/cop/capybara/specific_matcher_spec.rb +++ b/spec/rubocop/cop/capybara/specific_matcher_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::RSpec::Capybara::SpecificMatcher do +RSpec.describe RuboCop::Cop::Capybara::SpecificMatcher do it 'does not register an offense for abstract matcher when ' \ 'first argument is not a replaceable element' do expect_no_offenses(<<-RUBY) diff --git a/spec/rubocop/cop/capybara/visibility_matcher_spec.rb b/spec/rubocop/cop/capybara/visibility_matcher_spec.rb index c6c4936..68a1f95 100644 --- a/spec/rubocop/cop/capybara/visibility_matcher_spec.rb +++ b/spec/rubocop/cop/capybara/visibility_matcher_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::RSpec::Capybara::VisibilityMatcher do +RSpec.describe RuboCop::Cop::Capybara::VisibilityMatcher do it 'registers an offense when using `visible: true`' do expect_offense(<<-RUBY) expect(page).to have_selector('.my_element', visible: true) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index cf19e9f..df6abe6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,13 +1,14 @@ # frozen_string_literal: true require 'rubocop' -require 'rubocop/rspec/support' +require 'rubocop/rspec/support' # `expect_offense` etc module SpecHelper ROOT = Pathname.new(__dir__).parent.freeze end -spec_helper_glob = '{support,shared,../lib/rubocop/rspec/shared_contexts}/*.rb' +spec_helper_glob = + '{support,shared,../lib/rubocop/capybara/shared_contexts}/*.rb' Dir .glob(File.expand_path(spec_helper_glob, __dir__)) .sort @@ -36,12 +37,9 @@ module SpecHelper # We should take their advice! config.raise_on_warning = true - config.include(ExpectOffense) - - config.include_context 'with default RSpec/Language config', :config - config.include_context 'smoke test', type: :cop_spec + config.include RuboCop::RSpec::ExpectOffense end $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -require 'rubocop-rspec' +require 'rubocop-capybara' diff --git a/tasks/cops_documentation.rake b/tasks/cops_documentation.rake index 897ad7a..0d46ce1 100644 --- a/tasks/cops_documentation.rake +++ b/tasks/cops_documentation.rake @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'rubocop' -require 'rubocop-rspec' +require 'rubocop-capybara' require 'rubocop/cops_documentation_generator' require 'yard' @@ -13,7 +13,7 @@ end desc 'Generate docs of all cops departments' task generate_cops_documentation: :yard_for_generate_documentation do generator = CopsDocumentationGenerator.new( - departments: %w[RSpec/Capybara RSpec/FactoryBot RSpec/Rails RSpec] + departments: %w[Capybara] ) generator.call end