diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..e356c939e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,48 @@ +--- +name: Bug Report +about: Report an issue with RuboCop RSpec you've discovered. +--- + +*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.* + +*Use the template below when reporting bugs. Please, make sure that +you're running the latest stable RuboCop RSpec and that the problem you're reporting +hasn't been reported (and potentially fixed) already.* + +*Before filing the ticket you should replace all text above the horizontal +rule with your own words.* + +*In the case of false positive or false negative, please add the +corresponding cop name.* + +______________________________________________________________________ + +## Expected behavior + +Describe here how you expected RuboCop RSpec to behave in this particular situation. + +## Actual behavior + +Describe here what actually happened. +Please use `rubocop --debug` when pasting rubocop output as it contains additional information. + +## Steps to reproduce the problem + +This is extremely important! Providing us with a reliable way to reproduce +a problem will expedite its solution. + +## RuboCop RSpec version + +Include the output of `rubocop -V` or `bundle exec rubocop -V` if using Bundler. +If you see extension cop versions (e.g. `rubocop-performance`, `rubocop-rake`, and others) +output by `rubocop -V`, include them as well. Here's an example: + +```shell +$ [bundle exec] rubocop -V +1.67.0 (using Parser 3.3.5.0, rubocop-ast 1.32.3, analyzing as Ruby 2.7, running on ruby 3.4.0) [arm64-darwin23] + - rubocop-performance 1.22.1 + - rubocop-rake 0.6.0 + - rubocop-rspec 3.1.0 +``` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..5c8eefd93 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature Request +about: Suggest new RuboCop RSpec features or improvements to existing features. +--- + +## Is your feature request related to a problem? Please describe. + +A clear and concise description of what the problem is. Ex. I'm always frustrated when \[...\] + +## Describe the solution you'd like + +A clear and concise description of what you want to happen. + +## Describe alternatives you've considered + +A clear and concise description of any alternative solutions or features you've considered. + +## Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.rubocop.yml b/.rubocop.yml index 4795eec03..6fb427aef 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -101,34 +101,34 @@ RSpec: - expect_no_offenses - expect_offense +RSpec/DescribeClass: + Exclude: + - spec/project/**/*.rb + RSpec/ExampleLength: CountAsOne: - heredoc Max: 11 -RSpec/DescribeClass: - Exclude: - - spec/project/**/*.rb - RSpec/MultipleExpectations: Max: 2 +RSpec/SpecFilePathFormat: + Exclude: + - spec/rubocop/cop/rspec/mixin/**/*.rb + # `expect_offense` does not use Kernel#format or String#% Style/FormatStringToken: Exclude: - spec/rubocop/**/*.rb -Style/RequireOrder: - Enabled: true - -RSpec/SpecFilePathFormat: - Exclude: - - spec/rubocop/cop/rspec/mixin/**/*.rb - Style/NumberedParameters: Enabled: true EnforcedStyle: disallow +Style/RequireOrder: + Enabled: true + # Enable RuboCop's pending cops up to v1.63 Gemspec/DeprecatedAttributeAssignment: {Enabled: true} @@ -253,4 +253,5 @@ Style/YAMLFileRead: {Enabled: true} # Enable our own pending cops. # -# No pending cops yet. +RSpec/StringAsInstanceDoubleConstant: + Enabled: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 1996901a9..73cb05892 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,38 @@ ## Master (Unreleased) +## 3.2.0 (2024-10-26) + +- Fix `RSpec/VoidExpect` to only operate inside an example block. ([@corsonknowles]) +- Change `RSpec/ContextWording` cop to always report an offense when both `Prefixes` and `AllowedPatterns` are empty. ([@ydah]) +- Add support for `and` and `or` compound matchers to `RSpec/ChangeByZero` cop. ([@ydah]) + +## 3.1.0 (2024-10-01) + +- Add `RSpec/StringAsInstanceDoubleConstant` to check for and correct strings used as instance_doubles. ([@corsonknowles]) +- Fix false-positive for `RSpec/UnspecifiedException` when a method is literally named `raise_exception`. ([@aarestad]) +- Fix false-positive for `RSpec/UnspecifiedException` when `not_to raise_error` is used within a block. ([@aarestad], [@G-Rath]) + +## 3.0.5 (2024-09-07) + +- Fix false-negative and error for `RSpec/MetadataStyle` when non-literal args are used in metadata in `EnforceStyle: hash`. ([@cbliard]) +- Improve offense message for `RSpec/IndexedLet`. ([@earlopain]) + +## 3.0.4 (2024-08-05) + +- Fix false-negative for `UnspecifiedException` when matcher is chained. ([@r7kamura]) + +## 3.0.3 (2024-07-12) + +- Add support for Unicode RIGHT SINGLE QUOTATION MARK in `RSpec/ExampleWording`. ([@jdufresne]) +- Suppress deprecation warning for `RSpec/MultipleExpectations`, `RSpec/MultipleMemoizedHelpers`, and `RSpec/NestedGroups` cops. ([@koic]) + +## 3.0.2 (2024-07-02) + +- Fix wrong autocorrect for `RSpec/ScatteredSetup` when hook contains heredoc. ([@earlopain]) +- Fix false negative for `RSpec/PredicateMatcher` when expectation contains custom failure message. ([@earlopain]) +- Facilitate the 3.0 upgrade flow with proper extracted cop messages. ([@jeppester]) + ## 3.0.1 (2024-06-11) - Bump RuboCop requirement to +1.61. ([@ydah]) @@ -879,6 +911,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. +[@aarestad]: https://github.com/aarestad [@abrom]: https://github.com/abrom [@ahukkanen]: https://github.com/ahukkanen [@akiomik]: https://github.com/akiomik @@ -896,9 +929,11 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. [@bquorning]: https://github.com/bquorning [@brentwheeldon]: https://github.com/BrentWheeldon [@brianhawley]: https://github.com/BrianHawley +[@cbliard]: https://github.com/cbliard [@cfabianski]: https://github.com/cfabianski [@clupprich]: https://github.com/clupprich [@composerinteralia]: https://github.com/composerinteralia +[@corsonknowles]: https://github.com/corsonknowles [@corydiamand]: https://github.com/corydiamand [@darhazer]: https://github.com/Darhazer [@daveworth]: https://github.com/daveworth @@ -933,6 +968,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. [@jaredmoody]: https://github.com/jaredmoody [@jdufresne]: https://github.com/jdufresne [@jeffreyc]: https://github.com/jeffreyc +[@jeppester]: https://github.com/jeppester [@jessieay]: https://github.com/jessieay [@jfragoulis]: https://github.com/jfragoulis [@johnny-miyake]: https://github.com/johnny-miyake diff --git a/README.md b/README.md index 2f8b38ec8..61b5ff355 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,15 @@ [RSpec](https://rspec.info/)-specific analysis for your projects, as an extension to [RuboCop](https://github.com/rubocop/rubocop). +- [Installation](#installation) + - [Upgrading to RuboCop RSpec v3.x](#upgrading-to-rubocop-rspec-v3x) + - [Upgrading to RuboCop RSpec v2.x](#upgrading-to-rubocop-rspec-v2x) +- [Usage](#usage) +- [Documentation](#documentation) +- [The Cops](#the-cops) +- [Contributing](#contributing) +- [License](#license) + ## Installation Just install the `rubocop-rspec` gem @@ -21,6 +30,10 @@ or if you use bundler put this in your `Gemfile` gem 'rubocop-rspec', require: false ``` +### Upgrading to RuboCop RSpec v3.x + +Read all the details in our [Upgrade to Version 3.x](https://docs.rubocop.org/rubocop-rspec/3.0/upgrade_to_version_3.html) document. + ### 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. diff --git a/Rakefile b/Rakefile index a91382b68..23d584ed0 100644 --- a/Rakefile +++ b/Rakefile @@ -72,12 +72,15 @@ end desc 'Confirm documentation is up to date' task confirm_documentation: :generate_cops_documentation do - _, _, _, process = - Open3.popen3('git diff --exit-code docs/') - - unless process.value.success? - raise 'Please run `rake generate_cops_documentation` ' \ - 'and add docs/ to the commit.' + stdout, _stderr, status = + Open3.capture3('git diff --exit-code docs/') + + unless status.success? + warn 'Documentation is out of sync:' + warn stdout + warn 'Please run `rake generate_cops_documentation` ' \ + 'and add docs/ to the commit.' + exit 1 end end diff --git a/config/default.yml b/config/default.yml index 62135b81d..6c09b7d72 100644 --- a/config/default.yml +++ b/config/default.yml @@ -403,6 +403,7 @@ RSpec/ExampleWithoutDescription: - single_line_only - disallow VersionAdded: '1.22' + StyleGuide: https://rspec.rubystyle.guide/#it-and-specify Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription RSpec/ExampleWording: @@ -929,6 +930,13 @@ RSpec/SpecFilePathSuffix: - "**/spec/**/*" Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathSuffix +RSpec/StringAsInstanceDoubleConstant: + Description: Do not use a string as `instance_double` constant. + Enabled: pending + Safe: false + VersionAdded: '3.1' + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StringAsInstanceDoubleConstant + RSpec/StubbedMock: Description: Checks that message expectations do not have a configured response. Enabled: true diff --git a/config/obsoletion.yml b/config/obsoletion.yml index 5669cc85b..530bd0ed4 100644 --- a/config/obsoletion.yml +++ b/config/obsoletion.yml @@ -13,28 +13,6 @@ changed_parameters: alternative: AllowedPatterns severity: warning -renamed: - RSpec/Capybara/CurrentPathExpectation: Capybara/CurrentPathExpectation - RSpec/Capybara/MatchStyle: Capybara/MatchStyle - RSpec/Capybara/NegationMatcher: Capybara/NegationMatcher - RSpec/Capybara/SpecificActions: Capybara/SpecificActions - RSpec/Capybara/SpecificFinders: Capybara/SpecificFinders - RSpec/Capybara/SpecificMatcher: Capybara/SpecificMatcher - RSpec/Capybara/VisibilityMatcher: Capybara/VisibilityMatcher - RSpec/FactoryBot/AttributeDefinedStatically: FactoryBot/AttributeDefinedStatically - RSpec/FactoryBot/ConsistentParenthesesStyle: FactoryBot/ConsistentParenthesesStyle - RSpec/FactoryBot/CreateList: FactoryBot/CreateList - RSpec/FactoryBot/FactoryClassName: FactoryBot/FactoryClassName - RSpec/FactoryBot/FactoryNameStyle: FactoryBot/FactoryNameStyle - RSpec/FactoryBot/SyntaxMethods: FactoryBot/SyntaxMethods - RSpec/Rails/AvoidSetupHook: RSpecRails/AvoidSetupHook - RSpec/Rails/HaveHttpStatus: RSpecRails/HaveHttpStatus - RSpec/Rails/HttpStatus: RSpecRails/HttpStatus - RSpec/Rails/InferredSpecType: RSpecRails/InferredSpecType - RSpec/Rails/MinitestAssertions: RSpecRails/MinitestAssertions - RSpec/Rails/NegationBeValid: RSpecRails/NegationBeValid - RSpec/Rails/TravelAround: RSpecRails/TravelAround - split: RSpec/FilePath: alternatives: @@ -45,3 +23,8 @@ removed: RSpec/Capybara/FeatureMethods: reason: > this cop has migrated to `RSpec/Dialect`. Please use `RSpec/Dialect` instead + +extracted: + RSpec/Rails/*: rubocop-rspec_rails + RSpec/FactoryBot/*: rubocop-factory_bot + RSpec/Capybara/*: rubocop-capybara diff --git a/docs/antora.yml b/docs/antora.yml index 51a533a15..7cca04801 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,5 +1,5 @@ name: rubocop-rspec title: RuboCop RSpec -version: ~ +version: '3.2' nav: - modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index 16ddf0fd6..116d2a714 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -101,6 +101,7 @@ * xref:cops_rspec.adoc#rspecsortmetadata[RSpec/SortMetadata] * xref:cops_rspec.adoc#rspecspecfilepathformat[RSpec/SpecFilePathFormat] * xref:cops_rspec.adoc#rspecspecfilepathsuffix[RSpec/SpecFilePathSuffix] +* xref:cops_rspec.adoc#rspecstringasinstancedoubleconstant[RSpec/StringAsInstanceDoubleConstant] * xref:cops_rspec.adoc#rspecstubbedmock[RSpec/StubbedMock] * xref:cops_rspec.adoc#rspecsubjectdeclaration[RSpec/SubjectDeclaration] * xref:cops_rspec.adoc#rspecsubjectstub[RSpec/SubjectStub] diff --git a/docs/modules/ROOT/pages/cops_rspec.adoc b/docs/modules/ROOT/pages/cops_rspec.adoc index 143791aa5..20015bc0a 100644 --- a/docs/modules/ROOT/pages/cops_rspec.adoc +++ b/docs/modules/ROOT/pages/cops_rspec.adoc @@ -6,6 +6,7 @@ = RSpec +[#rspecalignleftletbrace] == RSpec/AlignLeftLetBrace |=== @@ -20,6 +21,7 @@ Checks that left braces for adjacent single line lets are aligned. +[#examples-rspecalignleftletbrace] === Examples [source,ruby] @@ -35,10 +37,12 @@ let(:baz) { bar } let(:a) { b } ---- +[#references-rspecalignleftletbrace] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignLeftLetBrace +[#rspecalignrightletbrace] == RSpec/AlignRightLetBrace |=== @@ -53,6 +57,7 @@ let(:a) { b } Checks that right braces for adjacent single line lets are aligned. +[#examples-rspecalignrightletbrace] === Examples [source,ruby] @@ -68,10 +73,12 @@ let(:baz) { bar } let(:a) { b } ---- +[#references-rspecalignrightletbrace] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignRightLetBrace +[#rspecanyinstance] == RSpec/AnyInstance |=== @@ -88,6 +95,7 @@ Check that instances are not being stubbed globally. Prefer instance doubles over stubbing any instance of a class +[#examples-rspecanyinstance] === Examples [source,ruby] @@ -108,11 +116,13 @@ describe MyClass do end ---- +[#references-rspecanyinstance] === References * https://rspec.rubystyle.guide/#any_instance_of * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance +[#rspecaroundblock] == RSpec/AroundBlock |=== @@ -127,6 +137,7 @@ end Checks that around blocks actually run the test. +[#examples-rspecaroundblock] === Examples [source,ruby] @@ -152,10 +163,12 @@ around do |test| end ---- +[#references-rspecaroundblock] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AroundBlock +[#rspecbe] == RSpec/Be |=== @@ -174,6 +187,7 @@ The `be` matcher is too generic, as it pass on everything that is not nil or false. If that is the exact intend, use `be_truthy`. In all other cases it's better to specify what exactly is the expected value. +[#examples-rspecbe] === Examples [source,ruby] @@ -187,11 +201,13 @@ expect(foo).to be 1.0 expect(foo).to be(true) ---- +[#references-rspecbe] === References * https://rspec.rubystyle.guide/#be-matcher * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be +[#rspecbeempty] == RSpec/BeEmpty |=== @@ -206,6 +222,7 @@ expect(foo).to be(true) Prefer using `be_empty` when checking for an empty array. +[#examples-rspecbeempty] === Examples [source,ruby] @@ -218,10 +235,12 @@ expect(array).to match_array([]) expect(array).to be_empty ---- +[#references-rspecbeempty] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEmpty +[#rspecbeeq] == RSpec/BeEq |=== @@ -240,10 +259,12 @@ The `be` matcher compares by identity while the `eq` matcher compares using `==`. Booleans and nil can be compared by identity and therefore the `be` matcher is preferable as it is a more strict test. +[#safety-rspecbeeq] === Safety This cop is unsafe because it changes how values are compared. +[#examples-rspecbeeq] === Examples [source,ruby] @@ -259,10 +280,12 @@ expect(foo).to be(false) expect(foo).to be(nil) ---- +[#references-rspecbeeq] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEq +[#rspecbeeql] == RSpec/BeEql |=== @@ -289,10 +312,12 @@ than `!equal?`. We also do not try to flag `eq` because if necessarily the same type as `b` since the `#==` operator can coerce objects for comparison. +[#safety-rspecbeeql] === Safety This cop is unsafe because it changes how values are compared. +[#examples-rspecbeeql] === Examples [source,ruby] @@ -314,10 +339,12 @@ expect(foo).to be(:bar) expect(foo).to be(nil) ---- +[#references-rspecbeeql] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql +[#rspecbenil] == RSpec/BeNil |=== @@ -337,8 +364,10 @@ generic `be` matcher with a `nil` argument. This cop can be configured using the `EnforcedStyle` option +[#examples-rspecbenil] === Examples +[#_enforcedstyle_-be_nil_-_default_-rspecbenil] ==== `EnforcedStyle: be_nil` (default) [source,ruby] @@ -350,6 +379,7 @@ expect(foo).to be(nil) expect(foo).to be_nil ---- +[#_enforcedstyle_-be_-rspecbenil] ==== `EnforcedStyle: be` [source,ruby] @@ -361,6 +391,7 @@ expect(foo).to be_nil expect(foo).to be(nil) ---- +[#configurable-attributes-rspecbenil] === Configurable attributes |=== @@ -371,10 +402,12 @@ expect(foo).to be(nil) | `be`, `be_nil` |=== +[#references-rspecbenil] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeNil +[#rspecbeforeafterall] == RSpec/BeforeAfterAll |=== @@ -389,6 +422,7 @@ expect(foo).to be(nil) Check that before/after(:all/:context) isn't being used. +[#examples-rspecbeforeafterall] === Examples [source,ruby] @@ -406,6 +440,7 @@ describe MyClass do end ---- +[#configurable-attributes-rspecbeforeafterall] === Configurable attributes |=== @@ -416,11 +451,13 @@ end | Array |=== +[#references-rspecbeforeafterall] === References * https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll +[#rspecchangebyzero] == RSpec/ChangeByZero |=== @@ -443,8 +480,10 @@ compound expectations, but if you set the negated matcher for `change`, e.g. `not_change` with the `NegatedMatcher` option, the cop will perform the autocorrection. +[#examples-rspecchangebyzero] === Examples +[#negatedmatcher_-_-_default_-rspecchangebyzero] ==== NegatedMatcher: ~ (default) [source,ruby] @@ -475,6 +514,7 @@ expect { run } .and not_change { Foo.baz } ---- +[#negatedmatcher_-not_change-rspecchangebyzero] ==== NegatedMatcher: not_change [source,ruby] @@ -497,6 +537,7 @@ expect { run } .and not_change { Foo.baz } ---- +[#configurable-attributes-rspecchangebyzero] === Configurable attributes |=== @@ -507,10 +548,12 @@ expect { run } | |=== +[#references-rspecchangebyzero] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ChangeByZero +[#rspecclasscheck] == RSpec/ClassCheck |=== @@ -525,8 +568,10 @@ expect { run } Enforces consistent use of `be_a` or `be_kind_of`. +[#examples-rspecclasscheck] === Examples +[#enforcedstyle_-be_a-_default_-rspecclasscheck] ==== EnforcedStyle: be_a (default) [source,ruby] @@ -540,6 +585,7 @@ expect(object).to be_a(String) expect(object).to be_an(String) ---- +[#enforcedstyle_-be_kind_of-rspecclasscheck] ==== EnforcedStyle: be_kind_of [source,ruby] @@ -553,6 +599,7 @@ expect(object).to be_kind_of(String) expect(object).to be_a_kind_of(String) ---- +[#configurable-attributes-rspecclasscheck] === Configurable attributes |=== @@ -563,11 +610,13 @@ expect(object).to be_a_kind_of(String) | `be_a`, `be_kind_of` |=== +[#references-rspecclasscheck] === References * https://rubystyle.guide#is-a-vs-kind-of * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ClassCheck +[#rspeccontainexactly] == RSpec/ContainExactly |=== @@ -586,6 +635,7 @@ This cop checks for the following: - Prefer `match_array` when matching array values. - Prefer `be_empty` when using `contain_exactly` with no arguments. +[#examples-rspeccontainexactly] === Examples [source,ruby] @@ -600,10 +650,12 @@ it { is_expected.to match_array(array1 + array2) } it { is_expected.to contain_exactly(content, *array) } ---- +[#references-rspeccontainexactly] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContainExactly +[#rspeccontextmethod] == RSpec/ContextMethod |=== @@ -618,6 +670,7 @@ it { is_expected.to contain_exactly(content, *array) } `context` should not be used for specifying methods. +[#examples-rspeccontextmethod] === Examples [source,ruby] @@ -641,11 +694,13 @@ describe '.foo_bar' do end ---- +[#references-rspeccontextmethod] === References * https://rspec.rubystyle.guide/#example-group-naming * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod +[#rspeccontextwording] == RSpec/ContextWording |=== @@ -665,11 +720,16 @@ the configuration to meet project needs. Other acceptable prefixes may include `if`, `unless`, `for`, `before`, `after`, or `during`. They may consist of multiple words if desired. +If both `Prefixes` and `AllowedPatterns` are empty, this cop will always +report an offense. So you need to set at least one of them. + This cop can be customized allowed context description pattern with `AllowedPatterns`. By default, there are no checking by pattern. +[#examples-rspeccontextwording] === Examples +[#_prefixes_-configuration-rspeccontextwording] ==== `Prefixes` configuration [source,ruby] @@ -698,6 +758,7 @@ context 'when the display name is not present' do end ---- +[#_allowedpatterns_-configuration-rspeccontextwording] ==== `AllowedPatterns` configuration [source,ruby] @@ -721,6 +782,7 @@ context '条件を満たすとき' do end ---- +[#configurable-attributes-rspeccontextwording] === Configurable attributes |=== @@ -735,12 +797,14 @@ end | Array |=== +[#references-rspeccontextwording] === References * https://rspec.rubystyle.guide/#context-descriptions * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording * http://www.betterspecs.org/#contexts +[#rspecdescribeclass] == RSpec/DescribeClass |=== @@ -759,8 +823,10 @@ It can be configured to ignore strings when certain metadata is passed. Ignores Rails and Aruba `type` metadata by default. +[#examples-rspecdescribeclass] === Examples +[#_ignoredmetadata_-configuration-rspecdescribeclass] ==== `IgnoredMetadata` configuration [source,ruby] @@ -792,6 +858,7 @@ describe "A feature example", type: :feature do end ---- +[#configurable-attributes-rspecdescribeclass] === Configurable attributes |=== @@ -806,10 +873,12 @@ end | |=== +[#references-rspecdescribeclass] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass +[#rspecdescribemethod] == RSpec/DescribeMethod |=== @@ -824,6 +893,7 @@ end Checks that the second argument to `describe` specifies a method. +[#examples-rspecdescribemethod] === Examples [source,ruby] @@ -840,10 +910,12 @@ describe MyClass, '.my_class_method' do end ---- +[#references-rspecdescribemethod] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeMethod +[#rspecdescribesymbol] == RSpec/DescribeSymbol |=== @@ -858,6 +930,7 @@ end Avoid describing symbols. +[#examples-rspecdescribesymbol] === Examples [source,ruby] @@ -873,11 +946,13 @@ describe '#my_method' do end ---- +[#references-rspecdescribesymbol] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol * https://github.com/rspec/rspec-core/issues/1610 +[#rspecdescribedclass] == RSpec/DescribedClass |=== @@ -909,8 +984,10 @@ To narrow down this setting to only a specific directory, it is possible to use an overriding configuration file local to that directory. +[#examples-rspecdescribedclass] === Examples +[#_enforcedstyle_-described_class_-_default_-rspecdescribedclass] ==== `EnforcedStyle: described_class` (default) [source,ruby] @@ -926,6 +1003,7 @@ describe MyClass do end ---- +[#_onlystaticconstants_-true_-_default_-rspecdescribedclass] ==== `OnlyStaticConstants: true` (default) [source,ruby] @@ -936,6 +1014,7 @@ describe MyClass do end ---- +[#_onlystaticconstants_-false_-rspecdescribedclass] ==== `OnlyStaticConstants: false` [source,ruby] @@ -946,6 +1025,7 @@ describe MyClass do end ---- +[#_enforcedstyle_-explicit_-rspecdescribedclass] ==== `EnforcedStyle: explicit` [source,ruby] @@ -961,6 +1041,7 @@ describe MyClass do end ---- +[#_skipblocks_-true_-rspecdescribedclass] ==== `SkipBlocks: true` [source,ruby] @@ -977,6 +1058,7 @@ describe MyConcern do end ---- +[#configurable-attributes-rspecdescribedclass] === Configurable attributes |=== @@ -995,10 +1077,12 @@ end | Boolean |=== +[#references-rspecdescribedclass] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass +[#rspecdescribedclassmodulewrapping] == RSpec/DescribedClassModuleWrapping |=== @@ -1013,6 +1097,7 @@ end Avoid opening modules and defining specs within them. +[#examples-rspecdescribedclassmodulewrapping] === Examples [source,ruby] @@ -1030,11 +1115,13 @@ RSpec.describe MyModule::MyClass do end ---- +[#references-rspecdescribedclassmodulewrapping] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping * https://github.com/rubocop/rubocop-rspec/issues/735 +[#rspecdialect] == RSpec/Dialect |=== @@ -1088,6 +1175,7 @@ native RSpec method (e.g. are just aliases), use the following config: You can expect the following behavior: +[#examples-rspecdialect] === Examples [source,ruby] @@ -1103,6 +1191,7 @@ describe 'display name presence' do end ---- +[#configurable-attributes-rspecdialect] === Configurable attributes |=== @@ -1113,10 +1202,12 @@ end | |=== +[#references-rspecdialect] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect +[#rspecduplicatedmetadata] == RSpec/DuplicatedMetadata |=== @@ -1131,6 +1222,7 @@ end Avoid duplicated metadata. +[#examples-rspecduplicatedmetadata] === Examples [source,ruby] @@ -1142,10 +1234,12 @@ describe 'Something', :a, :a describe 'Something', :a ---- +[#references-rspecduplicatedmetadata] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DuplicatedMetadata +[#rspecemptyexamplegroup] == RSpec/EmptyExampleGroup |=== @@ -1160,8 +1254,10 @@ describe 'Something', :a Checks if an example group does not include any tests. +[#examples-rspecemptyexamplegroup] === Examples +[#usage-rspecemptyexamplegroup] ==== usage [source,ruby] @@ -1196,10 +1292,12 @@ describe Bacon do end ---- +[#references-rspecemptyexamplegroup] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup +[#rspecemptyhook] == RSpec/EmptyHook |=== @@ -1214,6 +1312,7 @@ end Checks for empty before and after hooks. +[#examples-rspecemptyhook] === Examples [source,ruby] @@ -1236,10 +1335,12 @@ end after(:all) { cleanup_feed } ---- +[#references-rspecemptyhook] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook +[#rspecemptylineafterexample] == RSpec/EmptyLineAfterExample |=== @@ -1254,6 +1355,7 @@ after(:all) { cleanup_feed } Checks if there is an empty line after example blocks. +[#examples-rspecemptylineafterexample] === Examples [source,ruby] @@ -1282,6 +1384,7 @@ RSpec.describe Foo do end ---- +[#with-allowconsecutiveoneliners-configuration-rspecemptylineafterexample] ==== with AllowConsecutiveOneLiners configuration [source,ruby] @@ -1297,6 +1400,7 @@ RSpec.describe Foo do end ---- +[#configurable-attributes-rspecemptylineafterexample] === Configurable attributes |=== @@ -1307,11 +1411,13 @@ end | Boolean |=== +[#references-rspecemptylineafterexample] === References * https://rspec.rubystyle.guide/#empty-lines-around-examples * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample +[#rspecemptylineafterexamplegroup] == RSpec/EmptyLineAfterExampleGroup |=== @@ -1326,6 +1432,7 @@ end Checks if there is an empty line after example group blocks. +[#examples-rspecemptylineafterexamplegroup] === Examples [source,ruby] @@ -1348,11 +1455,13 @@ RSpec.describe Foo do end ---- +[#references-rspecemptylineafterexamplegroup] === References * https://rspec.rubystyle.guide/#empty-lines-between-describes * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExampleGroup +[#rspecemptylineafterfinallet] == RSpec/EmptyLineAfterFinalLet |=== @@ -1367,6 +1476,7 @@ end Checks if there is an empty line after the last let block. +[#examples-rspecemptylineafterfinallet] === Examples [source,ruby] @@ -1383,11 +1493,13 @@ let(:something) { other } it { does_something } ---- +[#references-rspecemptylineafterfinallet] === References * https://rspec.rubystyle.guide/#empty-line-after-let * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterFinalLet +[#rspecemptylineafterhook] == RSpec/EmptyLineAfterHook |=== @@ -1405,6 +1517,7 @@ Checks if there is an empty line after hook blocks. `AllowConsecutiveOneLiners` configures whether adjacent one-line definitions are considered an offense. +[#examples-rspecemptylineafterhook] === Examples [source,ruby] @@ -1433,6 +1546,7 @@ after { do_something } it { does_something } ---- +[#with-allowconsecutiveoneliners-configuration-rspecemptylineafterhook] ==== with AllowConsecutiveOneLiners configuration [source,ruby] @@ -1455,6 +1569,7 @@ after { do_something } it { does_something } ---- +[#configurable-attributes-rspecemptylineafterhook] === Configurable attributes |=== @@ -1465,11 +1580,13 @@ it { does_something } | Boolean |=== +[#references-rspecemptylineafterhook] === References * https://rspec.rubystyle.guide/#empty-line-after-let * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook +[#rspecemptylineaftersubject] == RSpec/EmptyLineAfterSubject |=== @@ -1484,6 +1601,7 @@ it { does_something } Checks if there is an empty line after subject block. +[#examples-rspecemptylineaftersubject] === Examples [source,ruby] @@ -1498,11 +1616,13 @@ subject(:obj) { described_class } let(:foo) { bar } ---- +[#references-rspecemptylineaftersubject] === References * https://rspec.rubystyle.guide/#empty-line-after-let * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject +[#rspecemptymetadata] == RSpec/EmptyMetadata |=== @@ -1517,8 +1637,10 @@ let(:foo) { bar } Avoid empty metadata hash. +[#examples-rspecemptymetadata] === Examples +[#enforcedstyle_-symbol-_default_-rspecemptymetadata] ==== EnforcedStyle: symbol (default) [source,ruby] @@ -1530,10 +1652,12 @@ describe 'Something', {} describe 'Something' ---- +[#references-rspecemptymetadata] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyMetadata +[#rspecemptyoutput] == RSpec/EmptyOutput |=== @@ -1548,6 +1672,7 @@ describe 'Something' Check that the `output` matcher is not called with an empty string. +[#examples-rspecemptyoutput] === Examples [source,ruby] @@ -1561,10 +1686,12 @@ expect { foo }.not_to output.to_stdout expect { bar }.to output.to_stderr ---- +[#references-rspecemptyoutput] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyOutput +[#rspeceq] == RSpec/Eq |=== @@ -1579,6 +1706,7 @@ expect { bar }.to output.to_stderr Use `eq` instead of `be ==` to compare objects. +[#examples-rspeceq] === Examples [source,ruby] @@ -1590,10 +1718,12 @@ expect(foo).to be == 42 expect(foo).to eq 42 ---- +[#references-rspeceq] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Eq +[#rspecexamplelength] == RSpec/ExampleLength |=== @@ -1617,6 +1747,7 @@ Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct will be counted as one line regardless of its actual size. +[#examples-rspecexamplelength] === Examples [source,ruby] @@ -1638,6 +1769,7 @@ it do end ---- +[#countasone_-__array__-_heredoc__-_method_call__-rspecexamplelength] ==== CountAsOne: ['array', 'heredoc', 'method_call'] [source,ruby] @@ -1664,6 +1796,7 @@ it do end # 6 points ---- +[#configurable-attributes-rspecexamplelength] === Configurable attributes |=== @@ -1678,10 +1811,12 @@ end # 6 points | Array |=== +[#references-rspecexamplelength] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength +[#rspecexamplewithoutdescription] == RSpec/ExampleWithoutDescription |=== @@ -1706,6 +1841,7 @@ on the configured style. This cop can be configured using the `EnforcedStyle` option +[#examples-rspecexamplewithoutdescription] === Examples [source,ruby] @@ -1717,6 +1853,7 @@ specify do end ---- +[#_enforcedstyle_-always_allow_-_default_-rspecexamplewithoutdescription] ==== `EnforcedStyle: always_allow` (default) [source,ruby] @@ -1736,6 +1873,7 @@ specify do end ---- +[#_enforcedstyle_-single_line_only_-rspecexamplewithoutdescription] ==== `EnforcedStyle: single_line_only` [source,ruby] @@ -1751,6 +1889,7 @@ end it { is_expected.to be_good } ---- +[#_enforcedstyle_-disallow_-rspecexamplewithoutdescription] ==== `EnforcedStyle: disallow` [source,ruby] @@ -1763,6 +1902,7 @@ it do end ---- +[#configurable-attributes-rspecexamplewithoutdescription] === Configurable attributes |=== @@ -1773,10 +1913,13 @@ end | `always_allow`, `single_line_only`, `disallow` |=== +[#references-rspecexamplewithoutdescription] === References +* https://rspec.rubystyle.guide/#it-and-specify * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription +[#rspecexamplewording] == RSpec/ExampleWording |=== @@ -1801,6 +1944,7 @@ Use the DisallowedExamples setting to prevent unclear or insufficient descriptions. Please note that this config will not be treated as case sensitive. +[#examples-rspecexamplewording] === Examples [source,ruby] @@ -1828,6 +1972,7 @@ it 'does things' do end ---- +[#_disallowedexamples_-__works___-_default_-rspecexamplewording] ==== `DisallowedExamples: ['works']` (default) [source,ruby] @@ -1841,6 +1986,7 @@ it 'marks the task as done' do end ---- +[#configurable-attributes-rspecexamplewording] === Configurable attributes |=== @@ -1859,12 +2005,14 @@ end | Array |=== +[#references-rspecexamplewording] === References * https://rspec.rubystyle.guide/#should-in-example-docstrings * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording * http://betterspecs.org/#should +[#rspecexcessivedocstringspacing] == RSpec/ExcessiveDocstringSpacing |=== @@ -1879,6 +2027,7 @@ end Checks for excessive whitespace in example descriptions. +[#examples-rspecexcessivedocstringspacing] === Examples [source,ruby] @@ -1903,10 +2052,12 @@ context 'when a condition is met' do end ---- +[#references-rspecexcessivedocstringspacing] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExcessiveDocstringSpacing +[#rspecexpectactual] == RSpec/ExpectActual |=== @@ -1923,6 +2074,7 @@ Checks for `expect(...)` calls containing literal values. Autocorrection is performed when the expected is not a literal. +[#examples-rspecexpectactual] === Examples [source,ruby] @@ -1941,6 +2093,7 @@ expect(name).to eq("John") expect(false).to eq(true) ---- +[#configurable-attributes-rspecexpectactual] === Configurable attributes |=== @@ -1951,10 +2104,12 @@ expect(false).to eq(true) | Array |=== +[#references-rspecexpectactual] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectActual +[#rspecexpectchange] == RSpec/ExpectChange |=== @@ -1974,8 +2129,10 @@ or passing a block that reads the attribute value. This cop can be configured using the `EnforcedStyle` option. +[#examples-rspecexpectchange] === Examples +[#_enforcedstyle_-method_call_-_default_-rspecexpectchange] ==== `EnforcedStyle: method_call` (default) [source,ruby] @@ -1992,6 +2149,7 @@ expect { run }.to change { Foo.bar(:count) } expect { run }.to change { user.reload.name } ---- +[#_enforcedstyle_-block_-rspecexpectchange] ==== `EnforcedStyle: block` [source,ruby] @@ -2003,6 +2161,7 @@ expect { run }.to change(Foo, :bar) expect { run }.to change { Foo.bar } ---- +[#configurable-attributes-rspecexpectchange] === Configurable attributes |=== @@ -2013,10 +2172,12 @@ expect { run }.to change { Foo.bar } | `method_call`, `block` |=== +[#references-rspecexpectchange] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectChange +[#rspecexpectinhook] == RSpec/ExpectInHook |=== @@ -2031,6 +2192,7 @@ expect { run }.to change { Foo.bar } Do not use `expect` in hooks such as `before`. +[#examples-rspecexpectinhook] === Examples [source,ruby] @@ -2051,10 +2213,12 @@ it do end ---- +[#references-rspecexpectinhook] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectInHook +[#rspecexpectinlet] == RSpec/ExpectInLet |=== @@ -2069,6 +2233,7 @@ end Do not use `expect` in let. +[#examples-rspecexpectinlet] === Examples [source,ruby] @@ -2084,10 +2249,12 @@ it do end ---- +[#references-rspecexpectinlet] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectInLet +[#rspecexpectoutput] == RSpec/ExpectOutput |=== @@ -2102,6 +2269,7 @@ end Checks for opportunities to use `expect { ... }.to output`. +[#examples-rspecexpectoutput] === Examples [source,ruby] @@ -2116,10 +2284,12 @@ expect($stdout.string).to eq('Hello World') expect { my_app.print_report }.to output('Hello World').to_stdout ---- +[#references-rspecexpectoutput] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectOutput +[#rspecfocus] == RSpec/Focus |=== @@ -2136,6 +2306,7 @@ Checks if examples are focused. This cop does not support autocorrection in some cases. +[#examples-rspecfocus] === Examples [source,ruby] @@ -2182,10 +2353,12 @@ shared_context 'test' do; end focus 'test' do; end ---- +[#references-rspecfocus] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Focus +[#rspechookargument] == RSpec/HookArgument |=== @@ -2205,8 +2378,10 @@ hooks which run for each example. There are three supported styles: "implicit", "each", and "example." All styles have the same behavior. +[#examples-rspechookargument] === Examples +[#_enforcedstyle_-implicit_-_default_-rspechookargument] ==== `EnforcedStyle: implicit` (default) [source,ruby] @@ -2227,6 +2402,7 @@ before do end ---- +[#_enforcedstyle_-each_-rspechookargument] ==== `EnforcedStyle: each` [source,ruby] @@ -2247,6 +2423,7 @@ before(:each) do end ---- +[#_enforcedstyle_-example_-rspechookargument] ==== `EnforcedStyle: example` [source,ruby] @@ -2267,6 +2444,7 @@ before(:example) do end ---- +[#configurable-attributes-rspechookargument] === Configurable attributes |=== @@ -2277,11 +2455,13 @@ end | `implicit`, `each`, `example` |=== +[#references-rspechookargument] === References * https://rspec.rubystyle.guide/#redundant-beforeeach * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HookArgument +[#rspechooksbeforeexamples] == RSpec/HooksBeforeExamples |=== @@ -2296,6 +2476,7 @@ end Checks for before/around/after hooks that come after an example. +[#examples-rspechooksbeforeexamples] === Examples [source,ruby] @@ -2317,10 +2498,12 @@ it 'checks what foo does' do end ---- +[#references-rspechooksbeforeexamples] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples +[#rspecidenticalequalityassertion] == RSpec/IdenticalEqualityAssertion |=== @@ -2335,6 +2518,7 @@ end Checks for equality assertions with identical expressions on both sides. +[#examples-rspecidenticalequalityassertion] === Examples [source,ruby] @@ -2348,10 +2532,12 @@ expect(foo.bar).to eq(2) expect(foo.bar).to eql(2) ---- +[#references-rspecidenticalequalityassertion] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IdenticalEqualityAssertion +[#rspecimplicitblockexpectation] == RSpec/ImplicitBlockExpectation |=== @@ -2368,6 +2554,7 @@ Check that implicit block expectation syntax is not used. Prefer using explicit block expectations. +[#examples-rspecimplicitblockexpectation] === Examples [source,ruby] @@ -2382,11 +2569,13 @@ it 'changes something to a new value' do end ---- +[#references-rspecimplicitblockexpectation] === References * https://rspec.rubystyle.guide/#implicit-block-expectations * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitBlockExpectation +[#rspecimplicitexpect] == RSpec/ImplicitExpect |=== @@ -2404,8 +2593,10 @@ Check that a consistent implicit expectation style is used. This cop can be configured using the `EnforcedStyle` option and supports the `--auto-gen-config` flag. +[#examples-rspecimplicitexpect] === Examples +[#_enforcedstyle_-is_expected_-_default_-rspecimplicitexpect] ==== `EnforcedStyle: is_expected` (default) [source,ruby] @@ -2417,6 +2608,7 @@ it { should be_truthy } it { is_expected.to be_truthy } ---- +[#_enforcedstyle_-should_-rspecimplicitexpect] ==== `EnforcedStyle: should` [source,ruby] @@ -2428,6 +2620,7 @@ it { is_expected.to be_truthy } it { should be_truthy } ---- +[#configurable-attributes-rspecimplicitexpect] === Configurable attributes |=== @@ -2438,11 +2631,13 @@ it { should be_truthy } | `is_expected`, `should` |=== +[#references-rspecimplicitexpect] === References * https://rspec.rubystyle.guide/#use-expect * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitExpect +[#rspecimplicitsubject] == RSpec/ImplicitSubject |=== @@ -2459,8 +2654,10 @@ Checks for usage of implicit subject (`is_expected` / `should`). This cop can be configured using the `EnforcedStyle` option +[#examples-rspecimplicitsubject] === Examples +[#_enforcedstyle_-single_line_only_-_default_-rspecimplicitsubject] ==== `EnforcedStyle: single_line_only` (default) [source,ruby] @@ -2477,6 +2674,7 @@ it do end ---- +[#_enforcedstyle_-single_statement_only_-rspecimplicitsubject] ==== `EnforcedStyle: single_statement_only` [source,ruby] @@ -2497,6 +2695,7 @@ it do end ---- +[#_enforcedstyle_-disallow_-rspecimplicitsubject] ==== `EnforcedStyle: disallow` [source,ruby] @@ -2508,6 +2707,7 @@ it { is_expected.to be_truthy } it { expect(subject).to be_truthy } ---- +[#_enforcedstyle_-require_implicit_-rspecimplicitsubject] ==== `EnforcedStyle: require_implicit` [source,ruby] @@ -2532,6 +2732,7 @@ end it { expect(named_subject).to be_truthy } ---- +[#configurable-attributes-rspecimplicitsubject] === Configurable attributes |=== @@ -2542,10 +2743,12 @@ it { expect(named_subject).to be_truthy } | `single_line_only`, `single_statement_only`, `disallow`, `require_implicit` |=== +[#references-rspecimplicitsubject] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject +[#rspecindexedlet] == RSpec/IndexedLet |=== @@ -2566,8 +2769,10 @@ is tested by this particular example. The configurable options `AllowedIdentifiers` and `AllowedPatterns` will also read those set in `Naming/VariableNumber`. +[#examples-rspecindexedlet] === Examples +[#_max_-1-_default__-rspecindexedlet] ==== `Max: 1 (default)` [source,ruby] @@ -2585,6 +2790,7 @@ let(:visible_item) { create(:item, visible: true) } let(:invisible_item) { create(:item, visible: false) } ---- +[#_max_-2_-rspecindexedlet] ==== `Max: 2` [source,ruby] @@ -2599,6 +2805,7 @@ let(:item_1) { create(:item) } let(:item_2) { create(:item) } ---- +[#_allowedidentifiers_-__item_1__-_item_2___-rspecindexedlet] ==== `AllowedIdentifiers: ['item_1', 'item_2']` [source,ruby] @@ -2608,6 +2815,7 @@ let(:item_1) { create(:item) } let(:item_2) { create(:item) } ---- +[#_allowedpatterns_-__item___-rspecindexedlet] ==== `AllowedPatterns: ['item']` [source,ruby] @@ -2617,6 +2825,7 @@ let(:item_1) { create(:item) } let(:item_2) { create(:item) } ---- +[#configurable-attributes-rspecindexedlet] === Configurable attributes |=== @@ -2635,10 +2844,12 @@ let(:item_2) { create(:item) } | Array |=== +[#references-rspecindexedlet] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IndexedLet +[#rspecinstancespy] == RSpec/InstanceSpy |=== @@ -2653,6 +2864,7 @@ let(:item_2) { create(:item) } Checks for `instance_double` used with `have_received`. +[#examples-rspecinstancespy] === Examples [source,ruby] @@ -2670,10 +2882,12 @@ it do end ---- +[#references-rspecinstancespy] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceSpy +[#rspecinstancevariable] == RSpec/InstanceVariable |=== @@ -2693,6 +2907,7 @@ will configure the cop to only register offenses on instance variable usage if the instance variable is also assigned within the spec +[#examples-rspecinstancevariable] === Examples [source,ruby] @@ -2710,6 +2925,7 @@ describe MyClass do end ---- +[#with-assignmentonly-configuration-rspecinstancevariable] ==== with AssignmentOnly configuration [source,ruby] @@ -2736,6 +2952,7 @@ describe MyClass do end ---- +[#configurable-attributes-rspecinstancevariable] === Configurable attributes |=== @@ -2746,11 +2963,13 @@ end | Boolean |=== +[#references-rspecinstancevariable] === References * https://rspec.rubystyle.guide/#instance-variables * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceVariable +[#rspecisexpectedspecify] == RSpec/IsExpectedSpecify |=== @@ -2765,6 +2984,7 @@ end Check for `specify` with `is_expected` and one-liner expectations. +[#examples-rspecisexpectedspecify] === Examples [source,ruby] @@ -2782,11 +3002,13 @@ end specify { expect(sqrt(4)).to eq(2) } ---- +[#references-rspecisexpectedspecify] === References * https://rspec.rubystyle.guide/#it-and-specify * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IsExpectedSpecify +[#rspecitbehaveslike] == RSpec/ItBehavesLike |=== @@ -2801,8 +3023,10 @@ specify { expect(sqrt(4)).to eq(2) } Checks that only one `it_behaves_like` style is used. +[#examples-rspecitbehaveslike] === Examples +[#_enforcedstyle_-it_behaves_like_-_default_-rspecitbehaveslike] ==== `EnforcedStyle: it_behaves_like` (default) [source,ruby] @@ -2814,6 +3038,7 @@ it_should_behave_like 'a foo' it_behaves_like 'a foo' ---- +[#_enforcedstyle_-it_should_behave_like_-rspecitbehaveslike] ==== `EnforcedStyle: it_should_behave_like` [source,ruby] @@ -2825,6 +3050,7 @@ it_behaves_like 'a foo' it_should_behave_like 'a foo' ---- +[#configurable-attributes-rspecitbehaveslike] === Configurable attributes |=== @@ -2835,10 +3061,12 @@ it_should_behave_like 'a foo' | `it_behaves_like`, `it_should_behave_like` |=== +[#references-rspecitbehaveslike] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike +[#rspeciteratedexpectation] == RSpec/IteratedExpectation |=== @@ -2853,6 +3081,7 @@ it_should_behave_like 'a foo' Check that `all` matcher is used instead of iterating over an array. +[#examples-rspeciteratedexpectation] === Examples [source,ruby] @@ -2868,10 +3097,12 @@ it 'validates users' do end ---- +[#references-rspeciteratedexpectation] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IteratedExpectation +[#rspecleadingsubject] == RSpec/LeadingSubject |=== @@ -2886,6 +3117,7 @@ end Enforce that subject is the first definition in the test. +[#examples-rspecleadingsubject] === Examples [source,ruby] @@ -2915,11 +3147,13 @@ it { expect_something } it { expect_something_else } ---- +[#references-rspecleadingsubject] === References * https://rspec.rubystyle.guide/#leading-subject * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject +[#rspecleakyconstantdeclaration] == RSpec/LeakyConstantDeclaration |=== @@ -2946,8 +3180,10 @@ Even worse when a class that exists in the codebase is reopened. Anonymous classes are fine, since they don't result in global namespace name clashes. +[#examples-rspecleakyconstantdeclaration] === Examples +[#constants-leak-between-examples-rspecleakyconstantdeclaration] ==== Constants leak between examples [source,ruby] @@ -3031,12 +3267,14 @@ describe SomeClass do end ---- +[#references-rspecleakyconstantdeclaration] === References * https://rspec.rubystyle.guide/#declare-constants * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeakyConstantDeclaration * https://rspec.info/features/3-12/rspec-mocks/mutating-constants +[#rspecletbeforeexamples] == RSpec/LetBeforeExamples |=== @@ -3051,6 +3289,7 @@ end Checks for `let` definitions that come after an example. +[#examples-rspecletbeforeexamples] === Examples [source,ruby] @@ -3081,10 +3320,12 @@ it 'checks what some does' do end ---- +[#references-rspecletbeforeexamples] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetBeforeExamples +[#rspecletsetup] == RSpec/LetSetup |=== @@ -3099,6 +3340,7 @@ end Checks unreferenced `let!` calls being used for test setup. +[#examples-rspecletsetup] === Examples [source,ruby] @@ -3124,10 +3366,12 @@ it 'counts widgets' do end ---- +[#references-rspecletsetup] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup +[#rspecmatcharray] == RSpec/MatchArray |=== @@ -3146,6 +3390,7 @@ This cop checks for the following: - Prefer `contain_exactly` when matching an array with values. - Prefer `eq` when using `match_array` with an empty array literal. +[#examples-rspecmatcharray] === Examples [source,ruby] @@ -3163,10 +3408,12 @@ it { is_expected.to match_array([content] + array) } it { is_expected.to match_array(%w(tremble in fear foolish mortals)) } ---- +[#references-rspecmatcharray] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MatchArray +[#rspecmessagechain] == RSpec/MessageChain |=== @@ -3181,6 +3428,7 @@ it { is_expected.to match_array(%w(tremble in fear foolish mortals)) } Check that chains of messages are not being stubbed. +[#examples-rspecmessagechain] === Examples [source,ruby] @@ -3193,10 +3441,12 @@ thing = Thing.new(baz: 42) allow(foo).to receive(:bar).and_return(thing) ---- +[#references-rspecmessagechain] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageChain +[#rspecmessageexpectation] == RSpec/MessageExpectation |=== @@ -3214,8 +3464,10 @@ Checks for consistent message expectation style. This cop can be configured in your configuration using the `EnforcedStyle` option and supports `--auto-gen-config`. +[#examples-rspecmessageexpectation] === Examples +[#_enforcedstyle_-allow_-_default_-rspecmessageexpectation] ==== `EnforcedStyle: allow` (default) [source,ruby] @@ -3227,6 +3479,7 @@ expect(foo).to receive(:bar) allow(foo).to receive(:bar) ---- +[#_enforcedstyle_-expect_-rspecmessageexpectation] ==== `EnforcedStyle: expect` [source,ruby] @@ -3238,6 +3491,7 @@ allow(foo).to receive(:bar) expect(foo).to receive(:bar) ---- +[#configurable-attributes-rspecmessageexpectation] === Configurable attributes |=== @@ -3248,10 +3502,12 @@ expect(foo).to receive(:bar) | `allow`, `expect` |=== +[#references-rspecmessageexpectation] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageExpectation +[#rspecmessagespies] == RSpec/MessageSpies |=== @@ -3269,8 +3525,10 @@ Checks that message expectations are set using spies. This cop can be configured in your configuration using the `EnforcedStyle` option and supports `--auto-gen-config`. +[#examples-rspecmessagespies] === Examples +[#_enforcedstyle_-have_received_-_default_-rspecmessagespies] ==== `EnforcedStyle: have_received` (default) [source,ruby] @@ -3285,6 +3543,7 @@ do_something expect(foo).to have_received(:bar) ---- +[#_enforcedstyle_-receive_-rspecmessagespies] ==== `EnforcedStyle: receive` [source,ruby] @@ -3299,6 +3558,7 @@ expect(foo).to receive(:bar) do_something ---- +[#configurable-attributes-rspecmessagespies] === Configurable attributes |=== @@ -3309,10 +3569,12 @@ do_something | `have_received`, `receive` |=== +[#references-rspecmessagespies] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageSpies +[#rspecmetadatastyle] == RSpec/MetadataStyle |=== @@ -3331,8 +3593,10 @@ This cop does not support autocorrection in the case of `EnforcedStyle: hash` where the trailing metadata type is ambiguous. (e.g. `describe 'Something', :a, b`) +[#examples-rspecmetadatastyle] === Examples +[#enforcedstyle_-symbol-_default_-rspecmetadatastyle] ==== EnforcedStyle: symbol (default) [source,ruby] @@ -3344,6 +3608,7 @@ describe 'Something', a: true describe 'Something', :a ---- +[#enforcedstyle_-hash-rspecmetadatastyle] ==== EnforcedStyle: hash [source,ruby] @@ -3355,6 +3620,7 @@ describe 'Something', :a describe 'Something', a: true ---- +[#configurable-attributes-rspecmetadatastyle] === Configurable attributes |=== @@ -3365,10 +3631,12 @@ describe 'Something', a: true | `hash`, `symbol` |=== +[#references-rspecmetadatastyle] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MetadataStyle +[#rspecmissingexamplegroupargument] == RSpec/MissingExampleGroupArgument |=== @@ -3383,6 +3651,7 @@ describe 'Something', a: true Checks that the first argument to an example group is not empty. +[#examples-rspecmissingexamplegroupargument] === Examples [source,ruby] @@ -3402,10 +3671,12 @@ describe "A feature example" do end ---- +[#references-rspecmissingexamplegroupargument] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument +[#rspecmissingexpectationtargetmethod] == RSpec/MissingExpectationTargetMethod |=== @@ -3423,6 +3694,7 @@ Checks if `.to`, `not_to` or `to_not` are used. The RSpec::Expectations::ExpectationTarget must use `to`, `not_to` or `to_not` to run. Therefore, this cop checks if other methods are used. +[#examples-rspecmissingexpectationtargetmethod] === Examples [source,ruby] @@ -3438,10 +3710,12 @@ is_expected.to eq 42 expect{something}.to raise_error BarError ---- +[#references-rspecmissingexpectationtargetmethod] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExpectationTargetMethod +[#rspecmultipledescribes] == RSpec/MultipleDescribes |=== @@ -3459,6 +3733,7 @@ Checks for multiple top-level example groups. Multiple descriptions for the same class or module should either be nested or separated into different test files. +[#examples-rspecmultipledescribes] === Examples [source,ruby] @@ -3478,10 +3753,12 @@ describe MyClass do end ---- +[#references-rspecmultipledescribes] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes +[#rspecmultipleexpectations] == RSpec/MultipleExpectations |=== @@ -3499,6 +3776,7 @@ Checks if examples contain too many `expect` calls. This cop is configurable using the `Max` option and works with `--auto-gen-config`. +[#examples-rspecmultipleexpectations] === Examples [source,ruby] @@ -3523,6 +3801,7 @@ describe UserCreator do end ---- +[#_aggregate_failures_-true_-_default_-rspecmultipleexpectations] ==== `aggregate_failures: true` (default) [source,ruby] @@ -3536,6 +3815,7 @@ describe UserCreator do end ---- +[#_aggregate_failures_-false_-rspecmultipleexpectations] ==== `aggregate_failures: false` [source,ruby] @@ -3549,6 +3829,7 @@ describe UserCreator do end ---- +[#_max_-1_-_default_-rspecmultipleexpectations] ==== `Max: 1` (default) [source,ruby] @@ -3562,6 +3843,7 @@ describe UserCreator do end ---- +[#_max_-2_-rspecmultipleexpectations] ==== `Max: 2` [source,ruby] @@ -3575,6 +3857,7 @@ describe UserCreator do end ---- +[#configurable-attributes-rspecmultipleexpectations] === Configurable attributes |=== @@ -3585,12 +3868,14 @@ end | Integer |=== +[#references-rspecmultipleexpectations] === References * https://rspec.rubystyle.guide/#expectation-per-example * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations * http://betterspecs.org/#single +[#rspecmultiplememoizedhelpers] == RSpec/MultipleMemoizedHelpers |=== @@ -3609,6 +3894,7 @@ This cop is configurable using the `Max` option and the `AllowSubject` which will configure the cop to only register offenses on calls to `let` and not calls to `subject`. +[#examples-rspecmultiplememoizedhelpers] === Examples [source,ruby] @@ -3659,6 +3945,7 @@ describe MyClass do end ---- +[#when-disabling-allowsubject-configuration-rspecmultiplememoizedhelpers] ==== when disabling AllowSubject configuration [source,ruby] @@ -3678,6 +3965,7 @@ describe MyClass do end ---- +[#with-max-configuration-rspecmultiplememoizedhelpers] ==== with Max configuration [source,ruby] @@ -3693,6 +3981,7 @@ describe MyClass do end ---- +[#configurable-attributes-rspecmultiplememoizedhelpers] === Configurable attributes |=== @@ -3707,11 +3996,13 @@ end | Integer |=== +[#references-rspecmultiplememoizedhelpers] === References * https://rspec.rubystyle.guide/#let-blocks * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers +[#rspecmultiplesubjects] == RSpec/MultipleSubjects |=== @@ -3742,6 +4033,7 @@ duplication: This is enough of an edge case that people can just move this to a `before` hook on their own +[#examples-rspecmultiplesubjects] === Examples [source,ruby] @@ -3773,10 +4065,12 @@ describe Foo do end ---- +[#references-rspecmultiplesubjects] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleSubjects +[#rspecnamedsubject] == RSpec/NamedSubject |=== @@ -3802,8 +4096,10 @@ This cop can be configured in your configuration using `EnforcedStyle`, and `IgnoreSharedExamples` which will not report offenses for implicit subjects in shared example groups. +[#examples-rspecnamedsubject] === Examples +[#_enforcedstyle_-always_-_default_-rspecnamedsubject] ==== `EnforcedStyle: always` (default) [source,ruby] @@ -3834,6 +4130,7 @@ RSpec.describe User do end ---- +[#_enforcedstyle_-named_only_-rspecnamedsubject] ==== `EnforcedStyle: named_only` [source,ruby] @@ -3873,6 +4170,7 @@ RSpec.describe User do end ---- +[#configurable-attributes-rspecnamedsubject] === Configurable attributes |=== @@ -3887,11 +4185,13 @@ end | Boolean |=== +[#references-rspecnamedsubject] === References * https://rspec.rubystyle.guide/#use-subject * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject +[#rspecnestedgroups] == RSpec/NestedGroups |=== @@ -3909,6 +4209,7 @@ Checks for nested example groups. This cop is configurable using the `Max` option and supports `--auto-gen-config`. +[#examples-rspecnestedgroups] === Examples [source,ruby] @@ -3958,6 +4259,7 @@ context 'using some feature as an admin' do end ---- +[#_max_-3_-_default_-rspecnestedgroups] ==== `Max: 3` (default) [source,ruby] @@ -3973,6 +4275,7 @@ describe Foo do end ---- +[#_max_-2_-rspecnestedgroups] ==== `Max: 2` [source,ruby] @@ -3988,6 +4291,7 @@ describe Foo do end ---- +[#_allowedgroups_-__-_default__-rspecnestedgroups] ==== `AllowedGroups: [] (default)` [source,ruby] @@ -4000,6 +4304,7 @@ describe Foo do # <-- nested groups 1 end ---- +[#_allowedgroups_-_path__-rspecnestedgroups] ==== `AllowedGroups: [path]` [source,ruby] @@ -4012,6 +4317,7 @@ describe Foo do # <-- nested groups 1 end ---- +[#configurable-attributes-rspecnestedgroups] === Configurable attributes |=== @@ -4026,10 +4332,12 @@ end | Array |=== +[#references-rspecnestedgroups] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups +[#rspecnoexpectationexample] == RSpec/NoExpectationExample |=== @@ -4060,6 +4368,7 @@ This cop can be customized with an allowed expectation methods pattern with an `AllowedPatterns` option. ^expect_ and ^assert_ are allowed by default. +[#examples-rspecnoexpectationexample] === Examples [source,ruby] @@ -4075,6 +4384,7 @@ it do end ---- +[#_allowedpatterns_-configuration-rspecnoexpectationexample] ==== `AllowedPatterns` configuration [source,ruby] @@ -4103,6 +4413,7 @@ it do end ---- +[#configurable-attributes-rspecnoexpectationexample] === Configurable attributes |=== @@ -4113,10 +4424,12 @@ end | Array |=== +[#references-rspecnoexpectationexample] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NoExpectationExample +[#rspecnottonot] == RSpec/NotToNot |=== @@ -4131,8 +4444,10 @@ end Checks for consistent method usage for negating expectations. +[#examples-rspecnottonot] === Examples +[#_enforcedstyle_-not_to_-_default_-rspecnottonot] ==== `EnforcedStyle: not_to` (default) [source,ruby] @@ -4148,6 +4463,7 @@ it '...' do end ---- +[#_enforcedstyle_-to_not_-rspecnottonot] ==== `EnforcedStyle: to_not` [source,ruby] @@ -4163,6 +4479,7 @@ it '...' do end ---- +[#configurable-attributes-rspecnottonot] === Configurable attributes |=== @@ -4173,10 +4490,12 @@ end | `not_to`, `to_not` |=== +[#references-rspecnottonot] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NotToNot +[#rspecoverwritingsetup] == RSpec/OverwritingSetup |=== @@ -4191,6 +4510,7 @@ end Checks if there is a let/subject that overwrites an existing one. +[#examples-rspecoverwritingsetup] === Examples [source,ruby] @@ -4212,10 +4532,12 @@ let(:baz) { baz } let!(:other) { other } ---- +[#references-rspecoverwritingsetup] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/OverwritingSetup +[#rspecpending] == RSpec/Pending |=== @@ -4230,6 +4552,7 @@ let!(:other) { other } Checks for any pending or skipped examples. +[#examples-rspecpending] === Examples [source,ruby] @@ -4261,10 +4584,12 @@ describe MyClass do end ---- +[#references-rspecpending] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending +[#rspecpendingwithoutreason] == RSpec/PendingWithoutReason |=== @@ -4279,6 +4604,7 @@ end Checks for pending or skipped examples without reason. +[#examples-rspecpendingwithoutreason] === Examples [source,ruby] @@ -4335,10 +4661,12 @@ it 'does something', skip: 'reason' do end ---- +[#references-rspecpendingwithoutreason] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PendingWithoutReason +[#rspecpredicatematcher] == RSpec/PredicateMatcher |=== @@ -4357,8 +4685,10 @@ RSpec defines magic matchers for predicate methods. This cop recommends to use the predicate matcher instead of using predicate method directly. +[#examples-rspecpredicatematcher] === Examples +[#strict_-true_-enforcedstyle_-inflected-_default_-rspecpredicatematcher] ==== Strict: true, EnforcedStyle: inflected (default) [source,ruby] @@ -4373,6 +4703,7 @@ expect(foo).to be_something expect(foo.something?).to be(true) ---- +[#strict_-false_-enforcedstyle_-inflected-rspecpredicatematcher] ==== Strict: false, EnforcedStyle: inflected [source,ruby] @@ -4385,6 +4716,7 @@ expect(foo.something?).to be(true) expect(foo).to be_something ---- +[#strict_-true_-enforcedstyle_-explicit-rspecpredicatematcher] ==== Strict: true, EnforcedStyle: explicit [source,ruby] @@ -4407,6 +4739,7 @@ expect(foo.something?(<<~TEXT)).to be(true) TEXT ---- +[#strict_-false_-enforcedstyle_-explicit-rspecpredicatematcher] ==== Strict: false, EnforcedStyle: explicit [source,ruby] @@ -4418,6 +4751,7 @@ expect(foo).to be_something expect(foo.something?).to be_truthy ---- +[#configurable-attributes-rspecpredicatematcher] === Configurable attributes |=== @@ -4436,11 +4770,13 @@ expect(foo.something?).to be_truthy | Array |=== +[#references-rspecpredicatematcher] === References * https://rspec.rubystyle.guide/#predicate-matchers * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher +[#rspecreceivecounts] == RSpec/ReceiveCounts |=== @@ -4455,6 +4791,7 @@ expect(foo.something?).to be_truthy Check for `once` and `twice` receive counts matchers usage. +[#examples-rspecreceivecounts] === Examples [source,ruby] @@ -4476,10 +4813,12 @@ expect(foo).to receive(:bar).at_most(:once) expect(foo).to receive(:bar).at_most(:twice).times ---- +[#references-rspecreceivecounts] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts +[#rspecreceivemessages] == RSpec/ReceiveMessages |=== @@ -4494,12 +4833,14 @@ expect(foo).to receive(:bar).at_most(:twice).times Checks for multiple messages stubbed on the same object. +[#safety-rspecreceivemessages] === Safety The autocorrection is marked as unsafe, because it may change the order of stubs. This in turn may cause e.g. variables to be called before they are defined. +[#examples-rspecreceivemessages] === Examples [source,ruby] @@ -4522,10 +4863,12 @@ before do end ---- +[#references-rspecreceivemessages] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveMessages +[#rspecreceivenever] == RSpec/ReceiveNever |=== @@ -4540,6 +4883,7 @@ end Prefer `not_to receive(...)` over `receive(...).never`. +[#examples-rspecreceivenever] === Examples [source,ruby] @@ -4551,10 +4895,12 @@ expect(foo).to receive(:bar).never expect(foo).not_to receive(:bar) ---- +[#references-rspecreceivenever] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever +[#rspecredundantaround] == RSpec/RedundantAround |=== @@ -4569,6 +4915,7 @@ expect(foo).not_to receive(:bar) Remove redundant `around` hook. +[#examples-rspecredundantaround] === Examples [source,ruby] @@ -4581,10 +4928,12 @@ end # good ---- +[#references-rspecredundantaround] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantAround +[#rspecredundantpredicatematcher] == RSpec/RedundantPredicateMatcher |=== @@ -4599,6 +4948,7 @@ end Checks for redundant predicate matcher. +[#examples-rspecredundantpredicatematcher] === Examples [source,ruby] @@ -4614,10 +4964,12 @@ expect(foo).not_to include(bar) expect(foo).to all be(bar) ---- +[#references-rspecredundantpredicatematcher] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantPredicateMatcher +[#rspecremoveconst] == RSpec/RemoveConst |=== @@ -4632,6 +4984,7 @@ expect(foo).to all be(bar) Checks that `remove_const` is not used in specs. +[#examples-rspecremoveconst] === Examples [source,ruby] @@ -4646,10 +4999,12 @@ before do end ---- +[#references-rspecremoveconst] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RemoveConst +[#rspecrepeateddescription] == RSpec/RepeatedDescription |=== @@ -4664,6 +5019,7 @@ end Check for repeated description strings in example groups. +[#examples-rspecrepeateddescription] === Examples [source,ruby] @@ -4702,10 +5058,12 @@ RSpec.describe User do end ---- +[#references-rspecrepeateddescription] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedDescription +[#rspecrepeatedexample] == RSpec/RepeatedExample |=== @@ -4720,6 +5078,7 @@ end Check for repeated examples within example groups. +[#examples-rspecrepeatedexample] === Examples [source,ruby] @@ -4733,10 +5092,12 @@ it 'validates the user' do end ---- +[#references-rspecrepeatedexample] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExample +[#rspecrepeatedexamplegroupbody] == RSpec/RepeatedExampleGroupBody |=== @@ -4751,6 +5112,7 @@ end Check for repeated describe and context block body. +[#examples-rspecrepeatedexamplegroupbody] === Examples [source,ruby] @@ -4792,10 +5154,12 @@ context Hash do end ---- +[#references-rspecrepeatedexamplegroupbody] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupBody +[#rspecrepeatedexamplegroupdescription] == RSpec/RepeatedExampleGroupDescription |=== @@ -4810,6 +5174,7 @@ end Check for repeated example group descriptions. +[#examples-rspecrepeatedexamplegroupdescription] === Examples [source,ruby] @@ -4851,10 +5216,12 @@ context 'when another case' do end ---- +[#references-rspecrepeatedexamplegroupdescription] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription +[#rspecrepeatedincludeexample] == RSpec/RepeatedIncludeExample |=== @@ -4869,6 +5236,7 @@ end Check for repeated include of shared examples. +[#examples-rspecrepeatedincludeexample] === Examples [source,ruby] @@ -4913,10 +5281,12 @@ context 'foo' do end ---- +[#references-rspecrepeatedincludeexample] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedIncludeExample +[#rspecrepeatedsubjectcall] == RSpec/RepeatedSubjectCall |=== @@ -4931,6 +5301,7 @@ end Checks for repeated calls to subject missing that it is memoized. +[#examples-rspecrepeatedsubjectcall] === Examples [source,ruby] @@ -4959,10 +5330,12 @@ it do end ---- +[#references-rspecrepeatedsubjectcall] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedSubjectCall +[#rspecreturnfromstub] == RSpec/ReturnFromStub |=== @@ -4983,8 +5356,10 @@ are the result would be different This cop can be configured using the `EnforcedStyle` option +[#examples-rspecreturnfromstub] === Examples +[#_enforcedstyle_-and_return_-_default_-rspecreturnfromstub] ==== `EnforcedStyle: and_return` (default) [source,ruby] @@ -5000,6 +5375,7 @@ expect(Foo).to receive(:bar).and_return("baz") allow(Foo).to receive(:bar) { bar.baz } ---- +[#_enforcedstyle_-block_-rspecreturnfromstub] ==== `EnforcedStyle: block` [source,ruby] @@ -5015,6 +5391,7 @@ expect(Foo).to receive(:bar) { "baz" } allow(Foo).to receive(:bar).and_return(bar.baz) ---- +[#configurable-attributes-rspecreturnfromstub] === Configurable attributes |=== @@ -5025,10 +5402,12 @@ allow(Foo).to receive(:bar).and_return(bar.baz) | `and_return`, `block` |=== +[#references-rspecreturnfromstub] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReturnFromStub +[#rspecscatteredlet] == RSpec/ScatteredLet |=== @@ -5045,6 +5424,7 @@ Checks for let scattered across the example group. Group lets together +[#examples-rspecscatteredlet] === Examples [source,ruby] @@ -5068,10 +5448,12 @@ describe Foo do end ---- +[#references-rspecscatteredlet] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet +[#rspecscatteredsetup] == RSpec/ScatteredSetup |=== @@ -5088,6 +5470,7 @@ Checks for setup scattered across multiple hooks in an example group. Unify `before`, `after`, and `around` hooks when possible. +[#examples-rspecscatteredsetup] === Examples [source,ruby] @@ -5107,10 +5490,12 @@ describe Foo do end ---- +[#references-rspecscatteredsetup] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredSetup +[#rspecsharedcontext] == RSpec/SharedContext |=== @@ -5128,6 +5513,7 @@ Checks for proper shared_context and shared_examples usage. If there are no examples defined, use shared_context. If there is no setup defined, use shared_examples. +[#examples-rspecsharedcontext] === Examples [source,ruby] @@ -5176,10 +5562,12 @@ RSpec.shared_context 'only setup here' do end ---- +[#references-rspecsharedcontext] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedContext +[#rspecsharedexamples] == RSpec/SharedExamples |=== @@ -5198,8 +5586,10 @@ Enforces either `string` or `symbol` for shared example names. This cop can be configured using the `EnforcedStyle` option +[#examples-rspecsharedexamples] === Examples +[#_enforcedstyle_-string_-_default_-rspecsharedexamples] ==== `EnforcedStyle: string` (default) [source,ruby] @@ -5219,6 +5609,7 @@ shared_examples_for 'foo bar baz' include_examples 'foo bar baz' ---- +[#_enforcedstyle_-symbol_-rspecsharedexamples] ==== `EnforcedStyle: symbol` [source,ruby] @@ -5238,6 +5629,7 @@ shared_examples_for :foo_bar_baz include_examples :foo_bar_baz ---- +[#configurable-attributes-rspecsharedexamples] === Configurable attributes |=== @@ -5248,10 +5640,12 @@ include_examples :foo_bar_baz | `string`, `symbol` |=== +[#references-rspecsharedexamples] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedExamples +[#rspecsingleargumentmessagechain] == RSpec/SingleArgumentMessageChain |=== @@ -5266,6 +5660,7 @@ include_examples :foo_bar_baz Checks that chains of messages contain more than one element. +[#examples-rspecsingleargumentmessagechain] === Examples [source,ruby] @@ -5281,10 +5676,12 @@ allow(foo).to receive(:bar, :baz) allow(foo).to receive("bar.baz") ---- +[#references-rspecsingleargumentmessagechain] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain +[#rspecskipblockinsideexample] == RSpec/SkipBlockInsideExample |=== @@ -5299,6 +5696,7 @@ allow(foo).to receive("bar.baz") Checks for passing a block to `skip` within examples. +[#examples-rspecskipblockinsideexample] === Examples [source,ruby] @@ -5321,10 +5719,12 @@ skip 'not yet implemented' do end ---- +[#references-rspecskipblockinsideexample] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SkipBlockInsideExample +[#rspecsortmetadata] == RSpec/SortMetadata |=== @@ -5339,6 +5739,7 @@ end Sort RSpec metadata alphabetically. +[#examples-rspecsortmetadata] === Examples [source,ruby] @@ -5354,10 +5755,12 @@ context 'Something', baz: true, foo: 'bar' it 'works', :a, :b, baz: true, foo: 'bar' ---- +[#references-rspecsortmetadata] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SortMetadata +[#rspecspecfilepathformat] == RSpec/SpecFilePathFormat |=== @@ -5372,6 +5775,7 @@ it 'works', :a, :b, baz: true, foo: 'bar' Checks that spec file paths are consistent and well-formed. +[#examples-rspecspecfilepathformat] === Examples [source,ruby] @@ -5386,6 +5790,7 @@ my_class_method_spec.rb # describe MyClass, '#method' my_class/method_spec.rb # describe MyClass, '#method' ---- +[#_customtransform_-_rubocop__rubocop_-rspec__rspec__-_default_-rspecspecfilepathformat] ==== `CustomTransform: {RuboCop=>rubocop, RSpec=>rspec}` (default) [source,ruby] @@ -5395,6 +5800,7 @@ rubocop_spec.rb # describe RuboCop rspec_spec.rb # describe RSpec ---- +[#_ignoremethods_-false_-_default_-rspecspecfilepathformat] ==== `IgnoreMethods: false` (default) [source,ruby] @@ -5403,6 +5809,7 @@ rspec_spec.rb # describe RSpec my_class_spec.rb # describe MyClass, '#method' ---- +[#_ignoremethods_-true_-rspecspecfilepathformat] ==== `IgnoreMethods: true` [source,ruby] @@ -5411,6 +5818,7 @@ my_class_spec.rb # describe MyClass, '#method' my_class_spec.rb # describe MyClass, '#method' ---- +[#_ignoremetadata_-_type__routing__-_default_-rspecspecfilepathformat] ==== `IgnoreMetadata: {type=>routing}` (default) [source,ruby] @@ -5419,6 +5827,7 @@ my_class_spec.rb # describe MyClass, '#method' whatever_spec.rb # describe MyClass, type: :routing do; end ---- +[#configurable-attributes-rspecspecfilepathformat] === Configurable attributes |=== @@ -5445,10 +5854,12 @@ whatever_spec.rb # describe MyClass, type: :routing do; end | |=== +[#references-rspecspecfilepathformat] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathFormat +[#rspecspecfilepathsuffix] == RSpec/SpecFilePathSuffix |=== @@ -5463,6 +5874,7 @@ whatever_spec.rb # describe MyClass, type: :routing do; end Checks that spec file paths suffix are consistent and well-formed. +[#examples-rspecspecfilepathsuffix] === Examples [source,ruby] @@ -5479,6 +5891,7 @@ my_class_spec.rb # describe MyClass spec/models/user.rb # shared_examples_for 'foo' ---- +[#configurable-attributes-rspecspecfilepathsuffix] === Configurable attributes |=== @@ -5489,10 +5902,51 @@ spec/models/user.rb # shared_examples_for 'foo' | Array |=== +[#references-rspecspecfilepathsuffix] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathSuffix +[#rspecstringasinstancedoubleconstant] +== RSpec/StringAsInstanceDoubleConstant + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| No +| Always (Unsafe) +| 3.1 +| - +|=== + +Do not use a string as `instance_double` constant. + +[#safety-rspecstringasinstancedoubleconstant] +=== Safety + +This cop is unsafe because the correction requires loading the class. +Loading before stubbing causes RSpec to only allow instance methods +to be stubbed. + +[#examples-rspecstringasinstancedoubleconstant] +=== Examples + +[source,ruby] +---- +# bad +instance_double('User', name: 'John') + +# good +instance_double(User, name: 'John') +---- + +[#references-rspecstringasinstancedoubleconstant] +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StringAsInstanceDoubleConstant + +[#rspecstubbedmock] == RSpec/StubbedMock |=== @@ -5507,6 +5961,7 @@ spec/models/user.rb # shared_examples_for 'foo' Checks that message expectations do not have a configured response. +[#examples-rspecstubbedmock] === Examples [source,ruby] @@ -5519,10 +5974,12 @@ allow(foo).to receive(:bar).with(42).and_return("hello world") expect(foo).to receive(:bar).with(42) ---- +[#references-rspecstubbedmock] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StubbedMock +[#rspecsubjectdeclaration] == RSpec/SubjectDeclaration |=== @@ -5537,6 +5994,7 @@ expect(foo).to receive(:bar).with(42) Ensure that subject is defined using subject helper. +[#examples-rspecsubjectdeclaration] === Examples [source,ruby] @@ -5555,10 +6013,12 @@ let(:subject, &block) subject(:test_subject) { foo } ---- +[#references-rspecsubjectdeclaration] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectDeclaration +[#rspecsubjectstub] == RSpec/SubjectStub |=== @@ -5576,6 +6036,7 @@ Checks for stubbed test subjects. Checks nested subject stubs for innermost subject definition when subject is also defined in parent example groups. +[#examples-rspecsubjectstub] === Examples [source,ruby] @@ -5614,6 +6075,7 @@ describe Article do end ---- +[#references-rspecsubjectstub] === References * https://rspec.rubystyle.guide/#dont-stub-subject @@ -5621,6 +6083,7 @@ end * https://robots.thoughtbot.com/don-t-stub-the-system-under-test * https://penelope.zone/2015/12/27/introducing-rspec-smells-and-where-to-find-them.html#smell-1-stubjec +[#rspecundescriptiveliteralsdescription] == RSpec/UndescriptiveLiteralsDescription |=== @@ -5638,6 +6101,7 @@ Description should be descriptive. If example group or example contains only `execute string`, numbers and regular expressions, the description is not clear. +[#examples-rspecundescriptiveliteralsdescription] === Examples [source,ruby] @@ -5678,10 +6142,12 @@ it 'does something' do end ---- +[#references-rspecundescriptiveliteralsdescription] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UndescriptiveLiteralsDescription +[#rspecunspecifiedexception] == RSpec/UnspecifiedException |=== @@ -5700,6 +6166,7 @@ Enforces one of an Exception type, a string, or a regular expression to match against the exception message as a parameter to `raise_error` +[#examples-rspecunspecifiedexception] === Examples [source,ruby] @@ -5725,10 +6192,12 @@ expect { expect { do_something }.not_to raise_error ---- +[#references-rspecunspecifiedexception] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UnspecifiedException +[#rspecvariabledefinition] == RSpec/VariableDefinition |=== @@ -5743,8 +6212,10 @@ expect { do_something }.not_to raise_error Checks that memoized helpers names are symbols or strings. +[#examples-rspecvariabledefinition] === Examples +[#enforcedstyle_-symbols-_default_-rspecvariabledefinition] ==== EnforcedStyle: symbols (default) [source,ruby] @@ -5758,6 +6229,7 @@ subject(:user) { create_user } let(:user_name) { 'Adam' } ---- +[#enforcedstyle_-strings-rspecvariabledefinition] ==== EnforcedStyle: strings [source,ruby] @@ -5771,6 +6243,7 @@ subject('user') { create_user } let('user_name') { 'Adam' } ---- +[#configurable-attributes-rspecvariabledefinition] === Configurable attributes |=== @@ -5781,10 +6254,12 @@ let('user_name') { 'Adam' } | `symbols`, `strings` |=== +[#references-rspecvariabledefinition] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableDefinition +[#rspecvariablename] == RSpec/VariableName |=== @@ -5802,8 +6277,10 @@ Checks that memoized helper names use the configured style. Variables can be excluded from checking using the `AllowedPatterns` option. +[#examples-rspecvariablename] === Examples +[#enforcedstyle_-snake_case-_default_-rspecvariablename] ==== EnforcedStyle: snake_case (default) [source,ruby] @@ -5817,6 +6294,7 @@ subject(:user_name_1) { 'Adam' } let(:user_name_2) { 'Adam' } ---- +[#enforcedstyle_-camelcase-rspecvariablename] ==== EnforcedStyle: camelCase [source,ruby] @@ -5830,6 +6308,7 @@ subject(:userName1) { 'Adam' } let(:userName2) { 'Adam' } ---- +[#allowedpatterns-configuration-rspecvariablename] ==== AllowedPatterns configuration [source,ruby] @@ -5848,6 +6327,7 @@ subject(:userFood_1) { 'spaghetti' } let(:userFood_2) { 'fettuccine' } ---- +[#configurable-attributes-rspecvariablename] === Configurable attributes |=== @@ -5862,10 +6342,12 @@ let(:userFood_2) { 'fettuccine' } | Array |=== +[#references-rspecvariablename] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName +[#rspecverifieddoublereference] == RSpec/VerifiedDoubleReference |=== @@ -5885,8 +6367,10 @@ Only investigates references that are one of the supported styles. This cop can be configured in your configuration using the `EnforcedStyle` option and supports `--auto-gen-config`. +[#examples-rspecverifieddoublereference] === Examples +[#_enforcedstyle_-constant_-_default_-rspecverifieddoublereference] ==== `EnforcedStyle: constant` (default) [source,ruby] @@ -5902,6 +6386,7 @@ let(:foo) do end ---- +[#_enforcedstyle_-string_-rspecverifieddoublereference] ==== `EnforcedStyle: string` [source,ruby] @@ -5917,6 +6402,7 @@ let(:foo) do end ---- +[#reference-is-not-in-the-supported-style-list_-no-enforcement-rspecverifieddoublereference] ==== Reference is not in the supported style list. No enforcement [source,ruby] @@ -5927,6 +6413,7 @@ let(:foo) do end ---- +[#configurable-attributes-rspecverifieddoublereference] === Configurable attributes |=== @@ -5937,11 +6424,13 @@ end | `constant`, `string` |=== +[#references-rspecverifieddoublereference] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubleReference * https://rspec.info/features/3-12/rspec-mocks/verifying-doubles +[#rspecverifieddoubles] == RSpec/VerifiedDoubles |=== @@ -5956,6 +6445,7 @@ end Prefer using verifying doubles over normal doubles. +[#examples-rspecverifieddoubles] === Examples [source,ruby] @@ -5976,6 +6466,7 @@ let(:foo) do end ---- +[#configurable-attributes-rspecverifieddoubles] === Configurable attributes |=== @@ -5990,12 +6481,14 @@ end | Boolean |=== +[#references-rspecverifieddoubles] === References * https://rspec.rubystyle.guide/#doubles * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles * https://rspec.info/features/3-12/rspec-mocks/verifying-doubles +[#rspecvoidexpect] == RSpec/VoidExpect |=== @@ -6010,6 +6503,7 @@ end Checks void `expect()`. +[#examples-rspecvoidexpect] === Examples [source,ruby] @@ -6021,10 +6515,12 @@ expect(something) expect(something).to be(1) ---- +[#references-rspecvoidexpect] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect +[#rspecyield] == RSpec/Yield |=== @@ -6039,6 +6535,7 @@ expect(something).to be(1) Checks for calling a block within a stub. +[#examples-rspecyield] === Examples [source,ruby] @@ -6050,6 +6547,7 @@ allow(foo).to receive(:bar) { |&block| block.call(1) } expect(foo).to receive(:bar).and_yield(1) ---- +[#references-rspecyield] === References * https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield diff --git a/docs/modules/ROOT/pages/upgrade_to_version_3.adoc b/docs/modules/ROOT/pages/upgrade_to_version_3.adoc index d0ad8adfd..29de466d4 100644 --- a/docs/modules/ROOT/pages/upgrade_to_version_3.adoc +++ b/docs/modules/ROOT/pages/upgrade_to_version_3.adoc @@ -10,7 +10,11 @@ In version 3.x: [discrete] === Extraction of cop departments. (`Capybara`, `FactoryBot`, `Rails`) -If you are using the RSpec/Capybara, RSpec/FactoryBot, or RSpec/Rails departments, you need to install the corresponding gem and add it to your `.rubocop.yml` file. +If you are using the RSpec/Capybara, RSpec/FactoryBot, or RSpec/Rails departments -- or have one in a `require` list in your rubocop.yml -- you need to install the corresponding gem and add it to your `.rubocop.yml` file: + +* Capybara: `rubocop-capybara` +* FactoryBot: `rubocop-factory_bot` +* Rails: `rubocop-rspec_rails` For example, if you are using the RSpec/Capybara department, you need to install the `rubocop-capybara` gem and add it to your `.rubocop.yml` file: @@ -25,8 +29,9 @@ end [source,yaml] ---- -Capybara: - Enabled: true +require: + - rubocop-rspec + - rubocop-capybara ---- And you need to remove the old department in your `.rubocop.yml` file: @@ -49,3 +54,7 @@ RSpec/FactoryBot: RSpec/Rails: Enabled: false ---- + +== Troubleshooting + +If you're seeing `cannot load such file` when running rubocop, even after installing the gems, restart the server with `rubocop --restart-server`. diff --git a/lib/rubocop/cop/rspec/change_by_zero.rb b/lib/rubocop/cop/rspec/change_by_zero.rb index d37ddd4dd..82da74193 100644 --- a/lib/rubocop/cop/rspec/change_by_zero.rb +++ b/lib/rubocop/cop/rspec/change_by_zero.rb @@ -104,12 +104,12 @@ def on_send(node) # rubocop:disable Metrics/MethodLength def register_offense(node, change_node) if compound_expectations?(node) - add_offense(node.source_range, + add_offense(node, message: message_compound(change_node)) do |corrector| autocorrect_compound(corrector, node) end else - add_offense(node.source_range, + add_offense(node, message: message(change_node)) do |corrector| autocorrect(corrector, node, change_node) end @@ -118,7 +118,8 @@ def register_offense(node, change_node) # rubocop:enable Metrics/MethodLength def compound_expectations?(node) - %i[and or & |].include?(node.parent.method_name) + node.parent.send_type? && + %i[and or & |].include?(node.parent.method_name) end def message(change_node) diff --git a/lib/rubocop/cop/rspec/context_wording.rb b/lib/rubocop/cop/rspec/context_wording.rb index 693c5c185..3fdba92f6 100644 --- a/lib/rubocop/cop/rspec/context_wording.rb +++ b/lib/rubocop/cop/rspec/context_wording.rb @@ -12,6 +12,9 @@ module RSpec # # @see http://www.betterspecs.org/#contexts # + # If both `Prefixes` and `AllowedPatterns` are empty, this cop will always + # report an offense. So you need to set at least one of them. + # # @example `Prefixes` configuration # # .rubocop.yml # # RSpec/ContextWording: @@ -58,7 +61,9 @@ module RSpec class ContextWording < Base include AllowedPattern - MSG = 'Context description should match %s.' + MSG_MATCH = 'Context description should match %s.' + MSG_ALWAYS = 'Current settings will always report an offense. Please ' \ + 'add allowed words to `Prefixes` or `AllowedPatterns`.' # @!method context_wording(node) def_node_matcher :context_wording, <<~PATTERN @@ -67,8 +72,7 @@ class ContextWording < Base def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler context_wording(node) do |context| - if bad_pattern?(context) - message = format(MSG, patterns: expect_patterns) + unless matches_allowed_pattern?(description(context)) add_offense(context, message: message) end end @@ -84,12 +88,6 @@ def prefix_regexes @prefix_regexes ||= prefixes.map { |pre| /^#{Regexp.escape(pre)}\b/ } end - def bad_pattern?(node) - return false if allowed_patterns.empty? - - !matches_allowed_pattern?(description(node)) - end - def description(context) if context.xstr_type? context.value.value @@ -98,6 +96,14 @@ def description(context) end end + def message + if allowed_patterns.empty? + MSG_ALWAYS + else + format(MSG_MATCH, patterns: expect_patterns) + end + end + def expect_patterns inspected = allowed_patterns.map do |pattern| pattern.inspect.gsub(/\A"|"\z/, '/') diff --git a/lib/rubocop/cop/rspec/example_wording.rb b/lib/rubocop/cop/rspec/example_wording.rb index a650183f2..a07e6abfa 100644 --- a/lib/rubocop/cop/rspec/example_wording.rb +++ b/lib/rubocop/cop/rspec/example_wording.rb @@ -55,8 +55,8 @@ class ExampleWording < Base MSG_INSUFFICIENT_DESCRIPTION = 'Your example description is ' \ 'insufficient.' - SHOULD_PREFIX = /\Ashould(?:n't)?\b/i.freeze - WILL_PREFIX = /\A(?:will|won't)\b/i.freeze + SHOULD_PREFIX = /\Ashould(?:n't|n’t)?\b/i.freeze + WILL_PREFIX = /\A(?:will|won't|won’t)\b/i.freeze IT_PREFIX = /\Ait /i.freeze # @!method it_description(node) diff --git a/lib/rubocop/cop/rspec/expect_actual.rb b/lib/rubocop/cop/rspec/expect_actual.rb index 7a15aa25d..7aeb0fa81 100644 --- a/lib/rubocop/cop/rspec/expect_actual.rb +++ b/lib/rubocop/cop/rspec/expect_actual.rb @@ -69,7 +69,7 @@ def on_send(node) # rubocop:disable Metrics/MethodLength expect_literal(node) do |actual, send_node, matcher, expected| next if SKIPPED_MATCHERS.include?(matcher) - add_offense(actual.source_range) do |corrector| + add_offense(actual) do |corrector| next unless CORRECTABLE_MATCHERS.include?(matcher) next if literal?(expected) diff --git a/lib/rubocop/cop/rspec/indexed_let.rb b/lib/rubocop/cop/rspec/indexed_let.rb index 546d56d3e..dab5d0e97 100644 --- a/lib/rubocop/cop/rspec/indexed_let.rb +++ b/lib/rubocop/cop/rspec/indexed_let.rb @@ -48,8 +48,8 @@ class IndexedLet < Base include AllowedIdentifiers include AllowedPattern - MSG = 'This `let` statement uses index in its name. Please give it ' \ - 'a meaningful name.' + MSG = 'This `let` statement uses `%s` in its name. ' \ + 'Please give it a meaningful name.' # @!method let_name(node) def_node_matcher :let_name, <<~PATTERN @@ -66,7 +66,8 @@ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless children filter_indexed_lets(children).each do |let_node| - add_offense(let_node) + index = let_name(let_node)[INDEX_REGEX] + add_offense(let_node, message: format(MSG, index: index)) end end diff --git a/lib/rubocop/cop/rspec/metadata_style.rb b/lib/rubocop/cop/rspec/metadata_style.rb index bb9d4c628..23b2b91dd 100644 --- a/lib/rubocop/cop/rspec/metadata_style.rb +++ b/lib/rubocop/cop/rspec/metadata_style.rb @@ -45,13 +45,8 @@ class MetadataStyle < Base # rubocop:disable Metrics/ClassLength PATTERN def on_metadata(symbols, hash) - # RSpec example groups accept two string arguments. In such a case, - # the rspec_metadata matcher will interpret the second string - # argument as a metadata symbol. - symbols.shift if symbols.first&.str_type? - symbols.each do |symbol| - on_metadata_symbol(symbol) + on_metadata_symbol(symbol) if symbol.sym_type? end return unless hash diff --git a/lib/rubocop/cop/rspec/multiple_expectations.rb b/lib/rubocop/cop/rspec/multiple_expectations.rb index 2d51f218d..bb1a32297 100644 --- a/lib/rubocop/cop/rspec/multiple_expectations.rb +++ b/lib/rubocop/cop/rspec/multiple_expectations.rb @@ -67,13 +67,13 @@ module RSpec # end # class MultipleExpectations < Base - include ConfigurableMax - MSG = 'Example has too many expectations [%d/%d].' ANYTHING = ->(_node) { true } TRUE_NODE = lambda(&:true_type?) + exclude_limit 'Max' + # @!method aggregate_failures?(node) def_node_matcher :aggregate_failures?, <<~PATTERN (block { diff --git a/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb b/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb index e386c5c68..b15dba208 100644 --- a/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +++ b/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb @@ -82,11 +82,12 @@ module RSpec # end # class MultipleMemoizedHelpers < Base - include ConfigurableMax include Variable MSG = 'Example group has too many memoized helpers [%d/%d]' + exclude_limit 'Max' + def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless spec_group?(node) diff --git a/lib/rubocop/cop/rspec/nested_groups.rb b/lib/rubocop/cop/rspec/nested_groups.rb index 2529621ac..40e5aa2d8 100644 --- a/lib/rubocop/cop/rspec/nested_groups.rb +++ b/lib/rubocop/cop/rspec/nested_groups.rb @@ -92,7 +92,6 @@ module RSpec # end # class NestedGroups < Base - include ConfigurableMax include TopLevelGroup MSG = 'Maximum example group nesting exceeded [%d/%d].' @@ -103,6 +102,8 @@ class NestedGroups < Base "Configuration key `#{DEPRECATED_MAX_KEY}` for #{cop_name} is " \ 'deprecated in favor of `Max`. Please use that instead.' + exclude_limit 'Max' + def on_top_level_group(node) find_nested_example_groups(node) do |example_group, nesting| self.max = nesting diff --git a/lib/rubocop/cop/rspec/predicate_matcher.rb b/lib/rubocop/cop/rspec/predicate_matcher.rb index 560b00600..a9b51e262 100644 --- a/lib/rubocop/cop/rspec/predicate_matcher.rb +++ b/lib/rubocop/cop/rspec/predicate_matcher.rb @@ -32,7 +32,7 @@ def check_inflected(node) (block $(send !nil? #predicate? ...) ...) $(send !nil? #predicate? ...)}) $#Runners.all - $#boolean_matcher?) + $#boolean_matcher? ...) PATTERN # @!method be_bool?(node) @@ -183,8 +183,12 @@ def heredoc_argument?(matcher) (send (send nil? :expect $!nil?) #Runners.all - {$(send nil? #predicate_matcher_name? ...) - (block $(send nil? #predicate_matcher_name? ...) ...)}) + { + $(send nil? #predicate_matcher_name? ...) + (block $(send nil? #predicate_matcher_name? ...) ...) + } + ... + ) PATTERN # @!method predicate_matcher_block?(node) diff --git a/lib/rubocop/cop/rspec/scattered_setup.rb b/lib/rubocop/cop/rspec/scattered_setup.rb index cd23e02d3..56a0444ff 100644 --- a/lib/rubocop/cop/rspec/scattered_setup.rb +++ b/lib/rubocop/cop/rspec/scattered_setup.rb @@ -23,6 +23,7 @@ module RSpec # end # class ScatteredSetup < Base + include FinalEndLocation include RangeHelp extend AutoCorrector @@ -75,8 +76,13 @@ def message(occurrences, occurrence) def autocorrect(corrector, first_occurrence, occurrence) return if first_occurrence == occurrence || !first_occurrence.body + # Take heredocs into account + body = occurrence.body&.source_range&.with( + end_pos: final_end_location(occurrence).begin_pos + ) + corrector.insert_after(first_occurrence.body, - "\n#{occurrence.body&.source}") + "\n#{body&.source}") corrector.remove(range_by_whole_lines(occurrence.source_range, include_final_newline: true)) end diff --git a/lib/rubocop/cop/rspec/string_as_instance_double_constant.rb b/lib/rubocop/cop/rspec/string_as_instance_double_constant.rb new file mode 100644 index 000000000..c7a346821 --- /dev/null +++ b/lib/rubocop/cop/rspec/string_as_instance_double_constant.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Do not use a string as `instance_double` constant. + # + # @safety + # This cop is unsafe because the correction requires loading the class. + # Loading before stubbing causes RSpec to only allow instance methods + # to be stubbed. + # + # @example + # # bad + # instance_double('User', name: 'John') + # + # # good + # instance_double(User, name: 'John') + # + class StringAsInstanceDoubleConstant < Base + extend AutoCorrector + + MSG = 'Do not use a string as `instance_double` constant.' + RESTRICT_ON_SEND = %i[instance_double].freeze + + # @!method stringified_instance_double_const?(node) + def_node_matcher :stringified_instance_double_const?, <<~PATTERN + (send nil? :instance_double $str ...) + PATTERN + + def on_send(node) + stringified_instance_double_const?(node) do |args_node| + add_offense(args_node) do |corrector| + autocorrect(corrector, args_node) + end + end + end + + def autocorrect(corrector, node) + corrector.replace(node, node.value) + end + end + end + end +end diff --git a/lib/rubocop/cop/rspec/unspecified_exception.rb b/lib/rubocop/cop/rspec/unspecified_exception.rb index c8bcf6bc9..30d4c49af 100644 --- a/lib/rubocop/cop/rspec/unspecified_exception.rb +++ b/lib/rubocop/cop/rspec/unspecified_exception.rb @@ -32,34 +32,42 @@ module RSpec # class UnspecifiedException < Base MSG = 'Specify the exception being captured' - RESTRICT_ON_SEND = %i[to].freeze - # @!method empty_raise_error_or_exception(node) - def_node_matcher :empty_raise_error_or_exception, <<~PATTERN - (send - (block - (send nil? :expect) ...) - :to - (send nil? {:raise_error :raise_exception}) - ) + RESTRICT_ON_SEND = %i[ + raise_exception + raise_error + ].freeze + + # @!method expect_to?(node) + def_node_matcher :expect_to?, <<~PATTERN + (send (block (send nil? :expect) ...) :to ...) PATTERN def on_send(node) return unless empty_exception_matcher?(node) - add_offense(node.children.last) + add_offense(node) end private def empty_exception_matcher?(node) - empty_raise_error_or_exception(node) && !block_with_args?(node.parent) + return false if node.arguments? || node.block_literal? + + expect_to = find_expect_to(node) + return false unless expect_to + return false if expect_to.block_node&.arguments? + + true end - def block_with_args?(node) - return false unless node&.block_type? + def find_expect_to(node) + node.each_ancestor.find do |ancestor| + break if ancestor.block_type? + next unless ancestor.send_type? - node.arguments? + expect_to?(ancestor) + end end end end diff --git a/lib/rubocop/cop/rspec/void_expect.rb b/lib/rubocop/cop/rspec/void_expect.rb index 8db6a496c..52f32147c 100644 --- a/lib/rubocop/cop/rspec/void_expect.rb +++ b/lib/rubocop/cop/rspec/void_expect.rb @@ -29,12 +29,14 @@ class VoidExpect < Base def on_send(node) return unless expect?(node) + return unless inside_example?(node) check_expect(node) end def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless expect_block?(node) + return unless inside_example?(node) check_expect(node) end @@ -49,11 +51,14 @@ def check_expect(node) def void?(expect) parent = expect.parent - return true unless parent return true if parent.begin_type? parent.block_type? && parent.body == expect end + + def inside_example?(node) + node.each_ancestor(:block).any? { |ancestor| example?(ancestor) } + end end end end diff --git a/lib/rubocop/cop/rspec_cops.rb b/lib/rubocop/cop/rspec_cops.rb index 5eed7e860..85c177e8e 100644 --- a/lib/rubocop/cop/rspec_cops.rb +++ b/lib/rubocop/cop/rspec_cops.rb @@ -99,6 +99,7 @@ require_relative 'rspec/sort_metadata' require_relative 'rspec/spec_file_path_format' require_relative 'rspec/spec_file_path_suffix' +require_relative 'rspec/string_as_instance_double_constant' require_relative 'rspec/stubbed_mock' require_relative 'rspec/subject_declaration' require_relative 'rspec/subject_stub' diff --git a/lib/rubocop/rspec/version.rb b/lib/rubocop/rspec/version.rb index 79d587230..e511c3f04 100644 --- a/lib/rubocop/rspec/version.rb +++ b/lib/rubocop/rspec/version.rb @@ -4,7 +4,7 @@ module RuboCop module RSpec # Version information for the RSpec RuboCop plugin. module Version - STRING = '3.0.1' + STRING = '3.2.0' end end end diff --git a/lib/rubocop/rspec/wording.rb b/lib/rubocop/rspec/wording.rb index baee2818a..57929c3e3 100644 --- a/lib/rubocop/rspec/wording.rb +++ b/lib/rubocop/rspec/wording.rb @@ -4,10 +4,10 @@ module RuboCop module RSpec # RSpec example wording rewriter class Wording - SHOULDNT_PREFIX = /\Ashould(?:n't| not)\b/i.freeze + SHOULDNT_PREFIX = /\Ashould(?:n't|n’t| not)\b/i.freeze SHOULDNT_BE_PREFIX = /#{SHOULDNT_PREFIX} be\b/i.freeze WILL_NOT_PREFIX = /\Awill not\b/i.freeze - WONT_PREFIX = /\Awon't\b/i.freeze + WONT_PREFIX = /\Awo(?:n't|n’t)\b/i.freeze ES_SUFFIX_PATTERN = /(?:o|s|x|ch|sh|z)\z/i.freeze IES_SUFFIX_PATTERN = /[^aeou]y\z/i.freeze diff --git a/spec/rubocop/cli/run_spec.rb b/spec/rubocop/cli/run_spec.rb index b8ae33670..4b0f6ba7b 100644 --- a/spec/rubocop/cli/run_spec.rb +++ b/spec/rubocop/cli/run_spec.rb @@ -39,9 +39,9 @@ == spec/example.rb == C: 2: 7: Naming/VariableNumber: Use normalcase for symbol numbers. C: 3: 7: Naming/VariableNumber: Use normalcase for symbol numbers. - C: 6: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name. + C: 6: 3: RSpec/IndexedLet: This let statement uses 1 in its name. Please give it a meaningful name. C: 6: 7: Naming/VariableNumber: Use normalcase for symbol numbers. - C: 7: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name. + C: 7: 3: RSpec/IndexedLet: This let statement uses 2 in its name. Please give it a meaningful name. C: 7: 7: Naming/VariableNumber: Use normalcase for symbol numbers. 1 file inspected, 6 offenses detected @@ -82,9 +82,9 @@ == spec/example.rb == C: 2: 7: Naming/VariableNumber: Use normalcase for symbol numbers. C: 3: 7: Naming/VariableNumber: Use normalcase for symbol numbers. - C: 6: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name. + C: 6: 3: RSpec/IndexedLet: This let statement uses 1 in its name. Please give it a meaningful name. C: 6: 7: Naming/VariableNumber: Use normalcase for symbol numbers. - C: 7: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name. + C: 7: 3: RSpec/IndexedLet: This let statement uses 2 in its name. Please give it a meaningful name. C: 7: 7: Naming/VariableNumber: Use normalcase for symbol numbers. 1 file inspected, 6 offenses detected diff --git a/spec/rubocop/cop/rspec/change_by_zero_spec.rb b/spec/rubocop/cop/rspec/change_by_zero_spec.rb index 5f313895b..4e9604768 100644 --- a/spec/rubocop/cop/rspec/change_by_zero_spec.rb +++ b/spec/rubocop/cop/rspec/change_by_zero_spec.rb @@ -68,6 +68,10 @@ expect { foo }.to change { Foo.bar }.by(0).and change { Foo.baz }.by(0) ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change(Foo, :bar).by(0).and change(Foo, :baz) + ^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change { Foo.bar }.and change { Foo.baz }.by(0) + ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. end RUBY @@ -84,6 +88,10 @@ expect { foo }.to change { Foo.bar }.by(0) & change { Foo.baz }.by(0) ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change(Foo, :bar).by(0) & change(Foo, :baz) + ^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change { Foo.bar } & change { Foo.baz }.by(0) + ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. end RUBY @@ -100,6 +108,10 @@ expect { foo }.to change { Foo.bar }.by(0).or change { Foo.baz }.by(0) ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change(Foo, :bar).by(0).or change(Foo, :baz) + ^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change { Foo.bar }.or change { Foo.baz }.by(0) + ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. end RUBY @@ -116,6 +128,10 @@ expect { foo }.to change { Foo.bar }.by(0) | change { Foo.baz }.by(0) ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change(Foo, :bar) | change(Foo, :baz).by(0) + ^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. + expect { foo }.to change { Foo.bar }.by(0) | change { Foo.baz } + ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer negated matchers with compound expectations over `change.by(0)`. end RUBY @@ -244,6 +260,14 @@ ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `not_change` with compound expectations over `change.by(0)`. .and change { Foo.baz }.by(0) ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `not_change` with compound expectations over `change.by(0)`. + expect { foo } + .to change(Foo, :bar) + .and change(Foo, :baz).by(0) + ^^^^^^^^^^^^^^^^^^^^^^^ Prefer `not_change` with compound expectations over `change.by(0)`. + expect { foo } + .to change { Foo.bar } + .and change { Foo.baz }.by(0) + ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `not_change` with compound expectations over `change.by(0)`. end RUBY @@ -255,6 +279,12 @@ expect { foo } .to not_change { Foo.bar } .and not_change { Foo.baz } + expect { foo } + .to change(Foo, :bar) + .and not_change(Foo, :baz) + expect { foo } + .to change { Foo.bar } + .and not_change { Foo.baz } end RUBY end diff --git a/spec/rubocop/cop/rspec/context_wording_spec.rb b/spec/rubocop/cop/rspec/context_wording_spec.rb index 5896110af..de3394b53 100644 --- a/spec/rubocop/cop/rspec/context_wording_spec.rb +++ b/spec/rubocop/cop/rspec/context_wording_spec.rb @@ -214,4 +214,18 @@ end end end + + context 'when `AllowedPatterns:` and `Prefixes:` are both empty' do + let(:cop_config) do + { 'Prefixes' => [], 'AllowedPatterns' => [] } + end + + it 'always registers an offense' do + expect_offense(<<~RUBY) + context 'this is an incorrect context' do + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Current settings will always report an offense. Please add allowed words to `Prefixes` or `AllowedPatterns`. + end + RUBY + end + end end diff --git a/spec/rubocop/cop/rspec/example_without_description_spec.rb b/spec/rubocop/cop/rspec/example_without_description_spec.rb index c3dad2ac1..1759505a6 100644 --- a/spec/rubocop/cop/rspec/example_without_description_spec.rb +++ b/spec/rubocop/cop/rspec/example_without_description_spec.rb @@ -84,7 +84,7 @@ RUBY end - it 'ignores `specify` missing decripton in multi-line examples' do + it 'ignores `specify` missing description in multi-line examples' do expect_no_offenses(<<~RUBY) specify do expect(subject).to be_good diff --git a/spec/rubocop/cop/rspec/example_wording_spec.rb b/spec/rubocop/cop/rspec/example_wording_spec.rb index 100ae719d..40645886b 100644 --- a/spec/rubocop/cop/rspec/example_wording_spec.rb +++ b/spec/rubocop/cop/rspec/example_wording_spec.rb @@ -148,6 +148,19 @@ RUBY end + it 'finds description with `won’t` at the beginning' do + expect_offense(<<~RUBY) + it "won’t do something" do + ^^^^^^^^^^^^^^^^^^ Do not use the future tense when describing your tests. + end + RUBY + + expect_correction(<<~RUBY) + it "does not do something" do + end + RUBY + end + it "finds description with `WON'T` at the beginning" do expect_offense(<<~RUBY) it "WON'T do something" do @@ -161,6 +174,19 @@ RUBY end + it 'finds description with `WON’T` at the beginning' do + expect_offense(<<~RUBY) + it "WON’T do something" do + ^^^^^^^^^^^^^^^^^^ Do not use the future tense when describing your tests. + end + RUBY + + expect_correction(<<~RUBY) + it "DOES NOT do something" do + end + RUBY + end + it 'flags a lone will' do expect_offense(<<~RUBY) it 'will' do @@ -200,6 +226,19 @@ RUBY end + it 'flags a lone won’t' do + expect_offense(<<~RUBY) + it "won’t" do + ^^^^^ Do not use the future tense when describing your tests. + end + RUBY + + expect_correction(<<~RUBY) + it "does not" do + end + RUBY + end + it 'finds leading its' do expect_offense(<<~RUBY) it "it does something" do diff --git a/spec/rubocop/cop/rspec/indexed_let_spec.rb b/spec/rubocop/cop/rspec/indexed_let_spec.rb index deff26c93..9f6cdbf4f 100644 --- a/spec/rubocop/cop/rspec/indexed_let_spec.rb +++ b/spec/rubocop/cop/rspec/indexed_let_spec.rb @@ -16,9 +16,9 @@ expect_offense(<<~RUBY) describe SomeService do let(:item_1) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `1` in its name. Please give it a meaningful name. let(:item_2) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `2` in its name. Please give it a meaningful name. end RUBY end @@ -27,9 +27,9 @@ expect_offense(<<~RUBY) describe SomeService do let("item_1") { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `1` in its name. Please give it a meaningful name. let("item_2") { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `2` in its name. Please give it a meaningful name. end RUBY end @@ -38,9 +38,9 @@ expect_offense(<<~RUBY) describe SomeService do let(:item1) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `1` in its name. Please give it a meaningful name. let(:item2) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `2` in its name. Please give it a meaningful name. end RUBY end @@ -49,9 +49,9 @@ expect_offense(<<~RUBY) describe SomeService do let(:item_1, &block) - ^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `1` in its name. Please give it a meaningful name. let(:item_2, &block) - ^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `2` in its name. Please give it a meaningful name. end RUBY end @@ -72,11 +72,11 @@ expect_offense(<<~RUBY) context SomeService do let(:user_1_item_1) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `1` in its name. Please give it a meaningful name. let(:user_1_item_2) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `1` in its name. Please give it a meaningful name. let(:user_2_item_1) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `2` in its name. Please give it a meaningful name. end RUBY end @@ -112,9 +112,9 @@ expect_offense(<<~RUBY) describe SomeService do let(:item_1) { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `1` in its name. Please give it a meaningful name. let("item_2") { create(:item) } - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses index in its name. Please give it a meaningful name. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `let` statement uses `2` in its name. Please give it a meaningful name. end RUBY end diff --git a/spec/rubocop/cop/rspec/metadata_style_spec.rb b/spec/rubocop/cop/rspec/metadata_style_spec.rb index 58e4a852a..810e3816a 100644 --- a/spec/rubocop/cop/rspec/metadata_style_spec.rb +++ b/spec/rubocop/cop/rspec/metadata_style_spec.rb @@ -94,6 +94,15 @@ end end + context 'with non-literal metadata and symbol metadata' do + it 'registers no offense' do + expect_no_offenses(<<~RUBY) + describe 'Something', a, :b do + end + RUBY + end + end + context 'with boolean keyword arguments metadata and symbol metadata' do it 'registers offense' do expect_offense(<<~RUBY) @@ -243,6 +252,15 @@ end end + context 'with 2 non-literal metadata' do + it 'registers no offense' do + expect_no_offenses(<<~RUBY) + describe 'Something', a, b do + end + RUBY + end + end + context 'with symbol metadata after 2 string arguments' do it 'registers offense' do expect_offense(<<~RUBY) @@ -258,6 +276,21 @@ end end + context 'with symbol metadata after non-literal metadata' do + it 'registers offense' do + expect_offense(<<~RUBY) + describe 'Something', a, :b do + ^^ Use hash style for metadata. + end + RUBY + + expect_correction(<<~RUBY) + describe 'Something', a, b: true do + end + RUBY + end + end + context 'with symbol metadata with parentheses' do it 'registers offense' do expect_offense(<<~RUBY) diff --git a/spec/rubocop/cop/rspec/mixin/metadata_spec.rb b/spec/rubocop/cop/rspec/mixin/metadata_spec.rb new file mode 100644 index 000000000..df51b1c80 --- /dev/null +++ b/spec/rubocop/cop/rspec/mixin/metadata_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::Cop::RSpec::Metadata do + describe '#on_metadata' do + subject(:on_metadata) do + stub_class.new.on_metadata(:symbol, {}) + end + + let(:stub_class) do + Class.new do + include RuboCop::Cop::RSpec::Metadata + end + end + + it { expect { on_metadata }.to raise_error(NotImplementedError) } + end +end diff --git a/spec/rubocop/cop/rspec/predicate_matcher_spec.rb b/spec/rubocop/cop/rspec/predicate_matcher_spec.rb index c37b2c7fe..bd1f4c1fb 100644 --- a/spec/rubocop/cop/rspec/predicate_matcher_spec.rb +++ b/spec/rubocop/cop/rspec/predicate_matcher_spec.rb @@ -16,6 +16,8 @@ expect_offense(<<~RUBY) expect(foo.empty?).to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_empty` matcher over `empty?`. + expect(foo.empty?).to be_truthy, 'fail' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_empty` matcher over `empty?`. expect(foo.empty?).not_to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_empty` matcher over `empty?`. expect(foo.empty?).to_not be_truthy @@ -30,6 +32,7 @@ expect_correction(<<~RUBY) expect(foo).to be_empty + expect(foo).to be_empty, 'fail' expect(foo).not_to be_empty expect(foo).not_to be_empty expect(foo).not_to be_empty @@ -42,6 +45,8 @@ expect_offense(<<~RUBY) expect(foo.exist?).to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `exist` matcher over `exist?`. + expect(foo.exist?).to be_truthy, 'fail' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `exist` matcher over `exist?`. expect(foo.exists?).to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `exist` matcher over `exists?`. expect(foo.has_something?).to be_truthy @@ -58,6 +63,7 @@ expect_correction(<<~RUBY) expect(foo).to exist + expect(foo).to exist, 'fail' expect(foo).to exist expect(foo).to have_something expect(foo).not_to have_something @@ -71,6 +77,8 @@ expect_offense(<<~RUBY) expect(foo.something?('foo')).to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_something` matcher over `something?`. + expect(foo.something?('foo')).to be_truthy, 'fail' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_something` matcher over `something?`. expect(foo.something?('foo', 'bar')).to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_something` matcher over `something?`. expect(foo.something? 1, 2).to be_truthy @@ -85,6 +93,7 @@ expect_correction(<<~RUBY) expect(foo).to be_something('foo') + expect(foo).to be_something('foo'), 'fail' expect(foo).to be_something('foo', 'bar') expect(foo).to be_something 1, 2 expect(foo).to have_key('foo') @@ -112,6 +121,8 @@ expect_offense(<<~RUBY) expect(foo.all?(&:present?)).to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_all` matcher over `all?`. + expect(foo.all?(&:present?)).to be_truthy, 'fail' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_all` matcher over `all?`. expect(foo.all? { |x| x.present? }).to be_truthy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_all` matcher over `all?`. expect(foo.all?(n) { |x| x.present? }).to be_truthy @@ -134,6 +145,7 @@ expect_correction(<<~RUBY) expect(foo).to be_all(&:present?) + expect(foo).to be_all(&:present?), 'fail' expect(foo).to be_all { |x| x.present? } expect(foo).to be_all(n) { |x| x.present? } expect(foo).to be_all { present } @@ -151,6 +163,7 @@ it 'accepts a predicate method that is not checked true/false' do expect_no_offenses(<<~RUBY) expect(foo.something?).to eq "something" + expect(foo.something?).to eq "something", "fail" expect(foo.has_something?).to eq "something" RUBY end @@ -158,6 +171,7 @@ it 'accepts non-predicate method' do expect_no_offenses(<<~RUBY) expect(foo.something).to be(true) + expect(foo.something).to be(true), 'fail' expect(foo.has_something).to be(true) RUBY end @@ -171,6 +185,7 @@ it 'accepts strict checking boolean matcher' do expect_no_offenses(<<~RUBY) expect(foo.empty?).to eq(true) + expect(foo.empty?).to eq(true), 'fail' expect(foo.empty?).to be(true) expect(foo.empty?).to be(false) expect(foo.empty?).not_to be true @@ -188,6 +203,8 @@ expect_offense(<<~RUBY) expect(foo.empty?).to eq(true) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_empty` matcher over `empty?`. + expect(foo.empty?).to eq(true), 'fail' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_empty` matcher over `empty?`. expect(foo.empty?).not_to be(true) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `be_empty` matcher over `empty?`. expect(foo.empty?).to be(true) @@ -202,6 +219,7 @@ expect_correction(<<~RUBY) expect(foo).to be_empty + expect(foo).to be_empty, 'fail' expect(foo).not_to be_empty expect(foo).to be_empty expect(foo).not_to be_empty @@ -220,6 +238,8 @@ expect_offense(<<~RUBY) expect(foo).to be_empty ^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `empty?` over `be_empty` matcher. + expect(foo).to be_empty, 'fail' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `empty?` over `be_empty` matcher. expect(foo).not_to be_empty ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `empty?` over `be_empty` matcher. expect(foo).to have_something @@ -252,6 +272,7 @@ it 'accepts built in matchers' do expect_no_offenses(<<~RUBY) expect(foo).to be_truthy + expect(foo).to be_truthy, 'fail' expect(foo).to be_falsey expect(foo).to be_falsy expect(foo).to have_attributes(name: 'foo') @@ -275,6 +296,7 @@ it 'accepts non-predicate matcher' do expect_no_offenses(<<~RUBY) expect(foo).to be(true) + expect(foo).to be(true), 'fail' RUBY end @@ -282,6 +304,8 @@ expect_offense(<<~RUBY) expect(foo).to be_something ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `something?` over `be_something` matcher. + expect(foo).to be_something, 'fail' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `something?` over `be_something` matcher. expect(foo).not_to be_something ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `something?` over `be_something` matcher. expect(foo).to have_something @@ -300,6 +324,7 @@ expect_correction(<<~RUBY) expect(foo.something?).to #{matcher_true} + expect(foo.something?).to #{matcher_true}, 'fail' expect(foo.something?).to #{matcher_false} expect(foo.has_something?).to #{matcher_true} expect(foo.is_a?(Array)).to #{matcher_true} @@ -403,6 +428,7 @@ 'with no argument' do expect_no_offenses(<<~RUBY) expect(foo).to include + expect(foo).to include, 'fail' RUBY end diff --git a/spec/rubocop/cop/rspec/scattered_setup_spec.rb b/spec/rubocop/cop/rspec/scattered_setup_spec.rb index 09a297465..7e9afea79 100644 --- a/spec/rubocop/cop/rspec/scattered_setup_spec.rb +++ b/spec/rubocop/cop/rspec/scattered_setup_spec.rb @@ -14,7 +14,7 @@ expect_correction(<<~RUBY) describe Foo do before { bar - baz } + baz } end RUBY end @@ -34,8 +34,8 @@ expect_correction(<<~RUBY) describe Foo do after { bar - baz - baz } + baz#{' '} + baz } end RUBY end @@ -53,7 +53,7 @@ expect_correction(<<~RUBY) describe Foo do before(:all) { bar - baz } + baz } end RUBY end @@ -143,9 +143,9 @@ expect_correction(<<~RUBY) describe Foo do before(:each, :special_case) { foo - bar - bar - bar } + bar#{' '} + bar#{' '} + bar } before(:example, special_case: false) { bar } end RUBY @@ -168,4 +168,29 @@ end RUBY end + + it 'flags hooks that contain heredoc arguments and autocorrects correctly' do + expect_offense(<<~RUBY) + describe Foo do + before { foo } + ^^^^^^^^^^^^^^ Do not define multiple `before` hooks in the same example group (also defined on line 3). + before do + ^^^^^^^^^ Do not define multiple `before` hooks in the same example group (also defined on line 2). + bar(<<~'TEXT') + Hello World! + TEXT + end + end + RUBY + + expect_correction(<<~RUBY) + describe Foo do + before { foo + bar(<<~'TEXT') + Hello World! + TEXT + } + end + RUBY + end end diff --git a/spec/rubocop/cop/rspec/string_as_instance_double_constant_spec.rb b/spec/rubocop/cop/rspec/string_as_instance_double_constant_spec.rb new file mode 100644 index 000000000..8f19ada94 --- /dev/null +++ b/spec/rubocop/cop/rspec/string_as_instance_double_constant_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::Cop::RSpec::StringAsInstanceDoubleConstant, + :config do + context 'when using a class for instance_double' do + it 'does not register an offense' do + expect_no_offenses(<<~RUBY) + instance_double(Shape, area: 12) + RUBY + end + end + + context 'when passing a variable to initialize instance_double' do + it 'does not register an offense' do + expect_no_offenses(<<~RUBY) + instance_double(type_undetectable_in_static_analysis) + RUBY + end + end + + context 'when using a string for instance_double' do + it 'replaces the string with the class' do + expect_offense <<~RUBY + instance_double('Shape', area: 12) + ^^^^^^^ Do not use a string as `instance_double` constant. + RUBY + + expect_correction <<~RUBY + instance_double(Shape, area: 12) + RUBY + end + end +end diff --git a/spec/rubocop/cop/rspec/unspecified_exception_spec.rb b/spec/rubocop/cop/rspec/unspecified_exception_spec.rb index c4e1a6037..8c41e6b30 100644 --- a/spec/rubocop/cop/rspec/unspecified_exception_spec.rb +++ b/spec/rubocop/cop/rspec/unspecified_exception_spec.rb @@ -85,6 +85,30 @@ }.to raise_error(my_exception) RUBY end + + it 'allows a subject function to be named raise_error' do + expect_no_offenses(<<~RUBY) + def raise_exception + raise StandardError + end + + expect { + raise_error + }.to raise_error(StandardError) + RUBY + end + + it 'allows a subject function to be named raise_exception' do + expect_no_offenses(<<~RUBY) + def raise_exception + raise StandardError + end + + expect { + raise_exception + }.to raise_error(StandardError) + RUBY + end end context 'with raise_exception matcher' do @@ -171,5 +195,64 @@ }.to raise_exception(my_exception) RUBY end + + it 'detects chained offenses' do + expect_offense(<<~RUBY) + expect { + foo + }.to raise_exception.and change { bar } + ^^^^^^^^^^^^^^^ Specify the exception being captured + RUBY + end + + it 'detects more chained offenses' do + expect_offense(<<~RUBY) + expect { + foo + }.to raise_exception.and change { bar }.and change { baz } + ^^^^^^^^^^^^^^^ Specify the exception being captured + RUBY + end + + it 'detects more complex chained offenses' do + expect_offense(<<~RUBY) + expect { + foo + }.to change { bar }.and raise_exception.and change { baz } + ^^^^^^^^^^^^^^^ Specify the exception being captured + RUBY + end + + it 'does not confuse blocks with chains' do + expect_no_offenses(<<~RUBY) + expect do + expect { foo }.not_to raise_error + end.to change(Foo, :count).by(3) + RUBY + end + + it 'allows a subject function to be named raise_exception' do + expect_no_offenses(<<~RUBY) + def raise_error + raise StandardError + end + + expect { + raise_exception + }.to raise_exception(StandardError) + RUBY + end + + it 'allows a subject function to be named raise_error' do + expect_no_offenses(<<~RUBY) + def raise_error + raise StandardError + end + + expect { + raise_error + }.to raise_exception(StandardError) + RUBY + end end end diff --git a/spec/rubocop/cop/rspec/void_expect_spec.rb b/spec/rubocop/cop/rspec/void_expect_spec.rb index 5791d7161..1ccf3ae74 100644 --- a/spec/rubocop/cop/rspec/void_expect_spec.rb +++ b/spec/rubocop/cop/rspec/void_expect_spec.rb @@ -44,4 +44,26 @@ end RUBY end + + it 'ignores unrelated method named expect in an example block' do + expect_no_offenses(<<~RUBY) + it 'something' do + MyObject.expect(:foo) + end + RUBY + end + + context 'when expect has no parent node' do + it 'does not register an offense' do + expect_no_offenses(<<~RUBY) + expect(something) + RUBY + end + + it 'does not register an offense for unrelated expect with block' do + expect_no_offenses(<<~RUBY) + expect { block_contents } + RUBY + end + end end diff --git a/spec/rubocop/rspec/hook_spec.rb b/spec/rubocop/rspec/hook_spec.rb index dffb7d63d..ad9493527 100644 --- a/spec/rubocop/rspec/hook_spec.rb +++ b/spec/rubocop/rspec/hook_spec.rb @@ -74,24 +74,32 @@ def metadata(source) hook(source).metadata.to_s end + if RUBY_VERSION >= '3.4' + let(:expected_special) { 's(:sym, :special) => true' } + let(:expected_symbol) { 's(:sym, :symbol) => true' } + else + let(:expected_special) { 's(:sym, :special)=>true' } + let(:expected_symbol) { 's(:sym, :symbol)=>true' } + end + it 'extracts symbol metadata' do expect(metadata('before(:example, :special) { foo }')) - .to eq('{s(:sym, :special)=>true}') + .to eq("{#{expected_special}}") end it 'extracts hash metadata' do expect(metadata('before(:example, special: true) { foo }')) - .to eq('{s(:sym, :special)=>true}') + .to eq("{#{expected_special}}") end it 'combines symbol and hash metadata' do expect(metadata('before(:example, :symbol, special: true) { foo }')) - .to eq('{s(:sym, :symbol)=>true, s(:sym, :special)=>true}') + .to eq("{#{expected_symbol}, #{expected_special}}") end it 'extracts hash metadata with no scope given' do expect(metadata('before(special: true) { foo }')) - .to eq('{s(:sym, :special)=>true}') + .to eq("{#{expected_special}}") end it 'withstands no arguments' do diff --git a/spec/rubocop/rspec/wording_spec.rb b/spec/rubocop/rspec/wording_spec.rb index 80f7c8a43..7248f0dda 100644 --- a/spec/rubocop/rspec/wording_spec.rb +++ b/spec/rubocop/rspec/wording_spec.rb @@ -24,15 +24,20 @@ 'should wish me luck' => 'wishes me luck', 'should really only return one item' => 'really only returns one item', "shouldn't return something" => 'does not return something', + 'shouldn’t return something' => 'does not return something', 'SHOULD RETAIN UPPERCASE' => 'RETAINS UPPERCASE', "shouldn't be true" => 'is not true', + 'shouldn’t be true' => 'is not true', "SHOULDN'T BE true" => 'IS NOT true', + 'SHOULDN’T BE true' => 'IS NOT true', "SHOULDN'T NOT RETAIN UPPERCASE" => 'DOES NOT NOT RETAIN UPPERCASE', + 'SHOULDN’T NOT RETAIN UPPERCASE' => 'DOES NOT NOT RETAIN UPPERCASE', 'should WORRY' => 'WORRIES', 'should WISH me luck' => 'WISHES me luck', '' => '', 'should' => '', "shouldn't" => 'does not', + 'shouldn’t' => 'does not', 'should not' => 'does not', 'should fizz' => 'fizzes' } diff --git a/tasks/cut_release.rake b/tasks/cut_release.rake index 130b67768..1ffa53035 100644 --- a/tasks/cut_release.rake +++ b/tasks/cut_release.rake @@ -38,7 +38,7 @@ namespace :cut_release do def add_header_to_changelog(version) update_file('CHANGELOG.md') do |changelog| changelog.sub("## Master (Unreleased)\n\n", - '\0' "## #{version} (#{Time.now.strftime('%F')})\n\n") + "\\0## #{version} (#{Time.now.strftime('%F')})\n\n") end end