From 368aecb101ab4d063ce2d68d2c7978ae04db1cd2 Mon Sep 17 00:00:00 2001 From: Stephann <3025661+stephannv@users.noreply.github.com> Date: Tue, 13 Apr 2021 10:08:26 -0300 Subject: [PATCH] Add CountAsOne config option to ExampleLength --- CHANGELOG.md | 3 ++ config/default.yml | 2 + docs/modules/ROOT/pages/cops_rspec.adoc | 31 ++++++++++++++- lib/rubocop/cop/rspec/example_length.rb | 38 +++++++++++++------ spec/rubocop/cop/rspec/example_length_spec.rb | 26 ++++++++++++- 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 361815fed..30ce30b0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * Allow `RSpec/ContextWording` to accept multi-word prefixes. ([@hosamaly][]) * Drop support for ruby 2.4. ([@bquorning][]) +* Add `CountAsOne` configuration option to `RSpec/ExampleLength`. ([@stephannv][]) + ## 2.2.0 (2021-02-02) * Fix `HooksBeforeExamples`, `LeadingSubject`, `LetBeforeExamples` and `ScatteredLet` autocorrection to take into account inline comments and comments immediately before the moved node. ([@Darhazer][]) @@ -607,3 +609,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. [@ahukkanen]: https://github.com/ahukkanen [@dvandersluis]: https://github.com/dvandersluis [@hosamaly]: https://github.com/hosamaly +[@stephannv]: https://github.com/stephannv diff --git a/config/default.yml b/config/default.yml index 4f13fdde4..1b3b7d3f4 100644 --- a/config/default.yml +++ b/config/default.yml @@ -253,7 +253,9 @@ RSpec/ExampleLength: Description: Checks for long examples. Enabled: true Max: 5 + CountAsOne: [] VersionAdded: '1.5' + VersionChanged: '2.3' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength RSpec/ExampleWithoutDescription: diff --git a/docs/modules/ROOT/pages/cops_rspec.adoc b/docs/modules/ROOT/pages/cops_rspec.adoc index 98268d455..6bd0f07ed 100644 --- a/docs/modules/ROOT/pages/cops_rspec.adoc +++ b/docs/modules/ROOT/pages/cops_rspec.adoc @@ -1051,7 +1051,7 @@ let(:foo) { bar } | Yes | No | 1.5 -| - +| 2.3 |=== Checks for long examples. @@ -1060,6 +1060,10 @@ A long example is usually more difficult to understand. Consider extracting out some behaviour, e.g. with a `let` block, or a helper method. +You can set literals you want to fold with `CountAsOne`. +Available are: 'array', 'hash', and 'heredoc'. Each literal +will be counted as one line regardless of its actual size. + === Examples [source,ruby] @@ -1081,6 +1085,27 @@ it do end ---- +==== CountAsOne: ['array', 'heredoc'] + +[source,ruby] +---- +it do + array = [ # +1 + 1, + 2 + ] + + hash = { # +3 + key: 'value' + } + + msg = <<~HEREDOC # +1 + Heredoc + content. + HEREDOC +end # 5 points +---- + === Configurable attributes |=== @@ -1089,6 +1114,10 @@ end | Max | `5` | Integer + +| CountAsOne +| `[]` +| Array |=== === References diff --git a/lib/rubocop/cop/rspec/example_length.rb b/lib/rubocop/cop/rspec/example_length.rb index 35a7142d7..c39ec6153 100644 --- a/lib/rubocop/cop/rspec/example_length.rb +++ b/lib/rubocop/cop/rspec/example_length.rb @@ -25,29 +25,43 @@ module RSpec # result = service.call # expect(result).to be(true) # end + # + # You can set literals you want to fold with `CountAsOne`. + # Available are: 'array', 'hash', and 'heredoc'. Each literal + # will be counted as one line regardless of its actual size. + # + # @example CountAsOne: ['array', 'heredoc'] + # + # it do + # array = [ # +1 + # 1, + # 2 + # ] + # + # hash = { # +3 + # key: 'value' + # } + # + # msg = <<~HEREDOC # +1 + # Heredoc + # content. + # HEREDOC + # end # 5 points class ExampleLength < Base include CodeLength - MSG = 'Example has too many lines [%d/%d].' + LABEL = 'Example' def on_block(node) return unless example?(node) - length = code_length(node) - - return unless length > max_length - - add_offense(node, message: message(length)) + check_code_length(node) end private - def code_length(node) - node.source.lines[1..-2].count { |line| !irrelevant_line(line) } - end - - def message(length) - format(MSG, total: length, max: max_length) + def cop_label + LABEL end end end diff --git a/spec/rubocop/cop/rspec/example_length_spec.rb b/spec/rubocop/cop/rspec/example_length_spec.rb index eeb4d9418..5a1346277 100644 --- a/spec/rubocop/cop/rspec/example_length_spec.rb +++ b/spec/rubocop/cop/rspec/example_length_spec.rb @@ -46,7 +46,7 @@ it 'flags the example' do expect_offense(<<-RUBY) it do - ^^^^^ Example has too many lines [4/3]. + ^^^^^ Example has too many lines. [4/3] line 1 line 2 line 3 @@ -64,7 +64,7 @@ it 'flags the example' do expect_offense(<<-RUBY) it do - ^^^^^ Example has too many lines [4/3]. + ^^^^^ Example has too many lines. [4/3] line 1 line 2 # comment @@ -73,4 +73,26 @@ RUBY end end + + context 'when `CountAsOne` is not empty' do + before { cop_config['CountAsOne'] = ['array'] } + + it 'folds array into one line' do + expect_no_offenses(<<~RUBY) + it do + a = 1 + a = [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + end + RUBY + end + end end