rubocop-rspec 1.26.0 → 1.27.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25c78adb48d8a15bb6229d1d8140abcd3f2e455c846288276ad01cedba024b4a
4
- data.tar.gz: 0e2fbf154570fca1aaf0a32cf7866902424bab10da2854038f5674c8664a2d11
3
+ metadata.gz: 2cb62faf05dbb3d997032a8fbac1d3d1897542d7a98b1540c54afebc10a6a294
4
+ data.tar.gz: 6b1fae2d79e473c5e8295fe6ccb5e843e8801b2ec6ea3c54625e8ba16e7c522d
5
5
  SHA512:
6
- metadata.gz: 7cc9ec95f341241d6c02083673e09ebd861929d846baae085c927a185998da95f573a18f0e7f3b9e7cdaba7f62812d7b80338534742fb2bde205df2fe29e0f3b
7
- data.tar.gz: 891e9714f685e8a3b1bee0ef80395cc11fe87eccb3226cd1bef201a90379e4424cbc5bd937cc632ba11efb7463f0654d756450e4ba44556e93dde7ef0838ab1a
6
+ metadata.gz: 2136057006988a3e05ab8be06f16125e76c520d1e46d656dd8aee9d7ae0c841fbc55d07e247e332120ab32b1f0a41e5b24827012104c8c3b75ac7e15de7e9395
7
+ data.tar.gz: 6a55cfcf03e4c2b15157e3292a89e161b3a25dc10ee45325912e9bf0fd4a13705b7d9b1e7c5f309c9a5ea9fc608a333af144a36844e95d6f20658cde5d290fd5
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 1.27.0 (2018-06-14)
6
+
7
+ * `RSpec/LeadingSubject` now enforces subject to be before any examples, hooks or let declarations. ([@Darhazer][])
8
+ * Fix `RSpec/NotToNot` to highlight only the selector (`not_to` or `to_not`), so it works also on `expect { ... }` blocks. ([@bquorning][])
9
+ * Add `RSpec/EmptyLineAfterHook` cop. ([@bquorning][])
10
+ * Add `RSpec/EmptyLineAfterExampleGroup` cop to check that there is an empty line after example group blocks. ([@bquorning][])
11
+ * Fix `RSpec/DescribeClass` crashing on `RSpec.describe` without arguments. ([@Darhazer][])
12
+ * Bump RuboCop requirement to v0.56.0. ([@bquorning][])
13
+ * Fix `RSpec/OverwritingSetup` crashing if a variable is used as an argument for `let`. ([@Darhazer][])
14
+
5
15
  ## 1.26.0 (2018-06-06)
6
16
 
7
17
  * Fix false positive in `RSpec/EmptyExampleGroup` cop when methods named like a RSpec method are used. ([@Darhazer][])
data/Gemfile CHANGED
@@ -2,10 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- group :test do
6
- gem 'simplecov', require: false
7
- end
8
-
9
5
  local_gemfile = 'Gemfile.local'
10
6
 
11
7
  if File.exist?(local_gemfile)
data/Rakefile CHANGED
@@ -51,7 +51,8 @@ task confirm_documentation: :generate_cops_documentation do
51
51
  Open3.popen3('git diff --exit-code manual/')
52
52
 
53
53
  unless process.value.success?
54
- raise 'manual is out of sync, please add manual/ to the commit'
54
+ raise 'Please run `rake generate_cops_documentation` ' \
55
+ 'and add manual/ to the commit.'
55
56
  end
56
57
  end
57
58
 
@@ -70,7 +71,10 @@ task :new_cop, [:cop] do |_task, args|
70
71
  exit!
71
72
  end
72
73
 
73
- generator = RuboCop::Cop::Generator.new(cop_name)
74
+ github_user = `git config github.user`.chop
75
+ github_user = 'your_id' if github_user.empty?
76
+
77
+ generator = RuboCop::Cop::Generator.new(cop_name, github_user)
74
78
 
75
79
  generator.write_source
76
80
  generator.write_spec
@@ -93,11 +93,21 @@ RSpec/EmptyExampleGroup:
93
93
  CustomIncludeMethods: []
94
94
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup
95
95
 
96
+ RSpec/EmptyLineAfterExampleGroup:
97
+ Description: Checks if there is an empty line after example group blocks.
98
+ Enabled: true
99
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExampleGroup
100
+
96
101
  RSpec/EmptyLineAfterFinalLet:
97
102
  Description: Checks if there is an empty line after the last let block.
98
103
  Enabled: true
99
104
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterFinalLet
100
105
 
106
+ RSpec/EmptyLineAfterHook:
107
+ Description: Checks if there is an empty line after hook blocks.
108
+ Enabled: true
109
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook
110
+
101
111
  RSpec/EmptyLineAfterSubject:
102
112
  Description: Checks if there is an empty line after subject block.
103
113
  Enabled: true
@@ -215,7 +225,7 @@ RSpec/ItBehavesLike:
215
225
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike
216
226
 
217
227
  RSpec/LeadingSubject:
218
- Description: Checks for `subject` definitions that come after `let` definitions.
228
+ Description: Enforce that subject is the first definition in the test.
219
229
  Enabled: true
220
230
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject
221
231
 
@@ -20,6 +20,8 @@ require_relative 'rubocop/cop/rspec/cop'
20
20
  require_relative 'rubocop/rspec/align_let_brace'
21
21
  require_relative 'rubocop/rspec/capybara'
22
22
  require_relative 'rubocop/rspec/factory_bot'
23
+ require_relative 'rubocop/rspec/final_end_location'
24
+ require_relative 'rubocop/rspec/blank_line_separation'
23
25
 
24
26
  RuboCop::RSpec::Inject.defaults!
25
27
 
@@ -23,7 +23,10 @@ module RuboCop
23
23
  'the class or module being tested.'.freeze
24
24
 
25
25
  def_node_matcher :valid_describe?, <<-PATTERN
26
- {(send {(const nil? :RSpec) nil?} :describe const ...) (send nil? :describe)}
26
+ {
27
+ (send {(const nil? :RSpec) nil?} :describe const ...)
28
+ (send {(const nil? :RSpec) nil?} :describe)
29
+ }
27
30
  PATTERN
28
31
 
29
32
  def_node_matcher :describe_with_metadata, <<-PATTERN
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks if there is an empty line after example group blocks.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # RSpec.describe Foo do
11
+ # describe '#bar' do
12
+ # end
13
+ # describe '#baz' do
14
+ # end
15
+ # end
16
+ #
17
+ # # good
18
+ # RSpec.describe Foo do
19
+ # describe '#bar' do
20
+ # end
21
+ #
22
+ # describe '#baz' do
23
+ # end
24
+ # end
25
+ #
26
+ class EmptyLineAfterExampleGroup < Cop
27
+ include RuboCop::RSpec::BlankLineSeparation
28
+
29
+ MSG = 'Add an empty line after `%<example_group>s`.'.freeze
30
+
31
+ def_node_matcher :example_group, ExampleGroups::ALL.block_pattern
32
+
33
+ def on_block(node)
34
+ return unless example_group(node)
35
+ return if node.parent && node.equal?(node.parent.children.last)
36
+
37
+ missing_separating_line(node) do |location|
38
+ add_offense(
39
+ node,
40
+ location: location,
41
+ message: format(MSG, example_group: node.method_name)
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -17,7 +17,7 @@ module RuboCop
17
17
  #
18
18
  # it { does_something }
19
19
  class EmptyLineAfterFinalLet < Cop
20
- include RangeHelp
20
+ include RuboCop::RSpec::BlankLineSeparation
21
21
 
22
22
  MSG = 'Add an empty line after the last `let` block.'.freeze
23
23
 
@@ -31,54 +31,10 @@ module RuboCop
31
31
  return if latest_let.nil?
32
32
  return if latest_let.equal?(node.body.children.last)
33
33
 
34
- no_new_line_after(latest_let) do |location|
34
+ missing_separating_line(latest_let) do |location|
35
35
  add_offense(latest_let, location: location)
36
36
  end
37
37
  end
38
-
39
- def autocorrect(node)
40
- lambda do |corrector|
41
- no_new_line_after(node) do |location|
42
- corrector.insert_after(location.end, "\n")
43
- end
44
- end
45
- end
46
-
47
- private
48
-
49
- def no_new_line_after(node)
50
- loc = last_node_loc(node)
51
- line = loc.line
52
- line += 1 while comment_line?(processed_source[line])
53
-
54
- return if processed_source[line].blank?
55
- yield offending_loc(node, line)
56
- end
57
-
58
- def last_node_loc(node)
59
- last_line = node.loc.end.line
60
- heredoc_line(node) do |loc|
61
- return loc if loc.line > last_line
62
- end
63
- node.loc.end
64
- end
65
-
66
- def heredoc_line(node, &block)
67
- yield node.loc.heredoc_end if node.loc.respond_to?(:heredoc_end)
68
-
69
- node.each_child_node { |child| heredoc_line(child, &block) }
70
- end
71
-
72
- def offending_loc(node, last_line)
73
- offending_line = processed_source[last_line - 1]
74
- if comment_line?(offending_line)
75
- start = offending_line.index('#')
76
- length = offending_line.length - start
77
- source_range(processed_source.buffer, last_line, start, length)
78
- else
79
- node.loc.expression
80
- end
81
- end
82
38
  end
83
39
  end
84
40
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks if there is an empty line after hook blocks.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # before { do_something }
11
+ # it { does_something }
12
+ #
13
+ # # bad
14
+ # after { do_something }
15
+ # it { does_something }
16
+ #
17
+ # # bad
18
+ # around { |test| test.run }
19
+ # it { does_something }
20
+ #
21
+ # # good
22
+ # before { do_something }
23
+ #
24
+ # it { does_something }
25
+ #
26
+ # # good
27
+ # after { do_something }
28
+ #
29
+ # it { does_something }
30
+ #
31
+ # # good
32
+ # around { |test| test.run }
33
+ #
34
+ # it { does_something }
35
+ #
36
+ class EmptyLineAfterHook < Cop
37
+ include RuboCop::RSpec::BlankLineSeparation
38
+
39
+ MSG = 'Add an empty line after `%<hook>s`.'.freeze
40
+
41
+ def_node_matcher :hook?, Hooks::ALL.block_pattern
42
+
43
+ def on_block(node)
44
+ return unless hook?(node)
45
+ return if node.equal?(node.parent.children.last)
46
+
47
+ missing_separating_line(node) do |location|
48
+ add_offense(
49
+ node,
50
+ location: location,
51
+ message: format(MSG, hook: node.method_name)
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -15,6 +15,8 @@ module RuboCop
15
15
  #
16
16
  # let(:foo) { bar }
17
17
  class EmptyLineAfterSubject < Cop
18
+ include RuboCop::RSpec::BlankLineSeparation
19
+
18
20
  MSG = 'Add empty line after `subject`.'.freeze
19
21
 
20
22
  def_node_matcher :subject?, Subject::ALL.block_pattern
@@ -23,15 +25,9 @@ module RuboCop
23
25
  return unless subject?(node) && !in_spec_block?(node)
24
26
  return if node.equal?(node.parent.children.last)
25
27
 
26
- send_line = node.loc.end.line
27
- next_line = processed_source[send_line]
28
- return if next_line.blank?
29
-
30
- add_offense(node, location: :expression, message: MSG)
31
- end
32
-
33
- def autocorrect(node)
34
- ->(corrector) { corrector.insert_after(node.loc.end, "\n") }
28
+ missing_separating_line(node) do |location|
29
+ add_offense(node, location: location, message: MSG)
30
+ end
35
31
  end
36
32
 
37
33
  private
@@ -3,64 +3,83 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # Checks for `subject` definitions that come after `let` definitions.
6
+ # Enforce that subject is the first definition in the test.
7
7
  #
8
8
  # @example
9
9
  # # bad
10
- # RSpec.describe User do
11
10
  # let(:params) { blah }
12
11
  # subject { described_class.new(params) }
13
12
  #
14
- # it 'is valid' do
15
- # expect(subject.valid?).to be(true)
16
- # end
17
- # end
13
+ # before { do_something }
14
+ # subject { described_class.new(params) }
18
15
  #
19
- # # good
20
- # RSpec.describe User do
16
+ # it { expect_something }
21
17
  # subject { described_class.new(params) }
18
+ # it { expect_something_else }
22
19
  #
20
+ #
21
+ # # good
22
+ # subject { described_class.new(params) }
23
23
  # let(:params) { blah }
24
24
  #
25
- # it 'is valid' do
26
- # expect(subject.valid?).to be(true)
27
- # end
28
- # end
25
+ # # good
26
+ # subject { described_class.new(params) }
27
+ # before { do_something }
28
+ #
29
+ # # good
30
+ # subject { described_class.new(params) }
31
+ # it { expect_something }
32
+ # it { expect_something_else }
33
+ #
29
34
  class LeadingSubject < Cop
30
35
  include RangeHelp
31
36
 
32
- MSG = 'Declare `subject` above any other `let` declarations.'.freeze
37
+ MSG = 'Declare `subject` above any other `%<offending>s` ' \
38
+ 'declarations.'.freeze
33
39
 
34
40
  def_node_matcher :subject?, Subject::ALL.block_pattern
41
+ def_node_matcher :let?, Helpers::ALL.block_pattern
42
+ def_node_matcher :hook?, Hooks::ALL.block_pattern
43
+ def_node_matcher :example?, Examples::ALL.block_pattern
35
44
 
36
45
  def on_block(node)
37
46
  return unless subject?(node) && !in_spec_block?(node)
38
47
 
48
+ check_previous_nodes(node)
49
+ end
50
+
51
+ def check_previous_nodes(node)
39
52
  node.parent.each_child_node do |sibling|
40
- break if sibling.equal?(node)
53
+ if offending?(sibling)
54
+ add_offense(
55
+ node,
56
+ location: :expression,
57
+ message: format(MSG, offending: sibling.method_name)
58
+ )
59
+ end
41
60
 
42
- break add_offense(node, location: :expression) if let?(sibling)
61
+ break if offending?(sibling) || sibling.equal?(node)
43
62
  end
44
63
  end
45
64
 
46
65
  def autocorrect(node)
47
66
  lambda do |corrector|
48
- first_let = find_first_let(node)
49
- first_let_position = first_let.loc.expression
50
- indent = "\n" + ' ' * first_let.loc.column
51
- corrector.insert_before(first_let_position, node.source + indent)
67
+ first_node = find_first_offending_node(node)
68
+ first_node_position = first_node.loc.expression
69
+ indent = "\n" + ' ' * first_node.loc.column
70
+ corrector.insert_before(first_node_position, node.source + indent)
52
71
  corrector.remove(node_range(node))
53
72
  end
54
73
  end
55
74
 
56
75
  private
57
76
 
58
- def let?(node)
59
- %i[let let!].include?(node.method_name)
77
+ def offending?(node)
78
+ let?(node) || hook?(node) || example?(node)
60
79
  end
61
80
 
62
- def find_first_let(node)
63
- node.parent.children.find { |sibling| let?(sibling) }
81
+ def find_first_offending_node(node)
82
+ node.parent.children.find { |sibling| offending?(sibling) }
64
83
  end
65
84
 
66
85
  def node_range(node)
@@ -32,6 +32,7 @@ module RuboCop
32
32
  # end
33
33
  class LetBeforeExamples < Cop
34
34
  include RangeHelp
35
+ include RuboCop::RSpec::FinalEndLocation
35
36
 
36
37
  MSG = 'Move `let` before the examples in the group.'.freeze
37
38
 
@@ -91,21 +92,10 @@ module RuboCop
91
92
  end
92
93
 
93
94
  def node_range(node)
94
- range_between(node.loc.expression.begin_pos, last_node_loc(node))
95
- end
96
-
97
- def last_node_loc(node)
98
- heredoc = heredoc_lines(node).last
99
-
100
- if heredoc
101
- heredoc.loc.heredoc_end.end_pos
102
- else
103
- node.loc.end.end_pos
104
- end
105
- end
106
-
107
- def heredoc_lines(node)
108
- node.body.child_nodes.select { |n| n.loc.respond_to?(:heredoc_end) }
95
+ range_between(
96
+ node.loc.expression.begin_pos,
97
+ final_end_location(node).end_pos
98
+ )
109
99
  end
110
100
  end
111
101
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
 
23
23
  def on_send(node)
24
24
  not_to_not_offense(node, alternative_style) do
25
- add_offense(node, location: :expression)
25
+ add_offense(node, location: :selector)
26
26
  end
27
27
  end
28
28
 
@@ -22,11 +22,10 @@ module RuboCop
22
22
  # let(:baz) { baz }
23
23
  # let!(:other) { other }
24
24
  class OverwritingSetup < Cop
25
- include RuboCop::RSpec::Util
26
-
27
25
  MSG = '`%<name>s` is already defined.'.freeze
28
26
 
29
27
  def_node_matcher :setup?, (Helpers::ALL + Subject::ALL).block_pattern
28
+ def_node_matcher :first_argument_name, '(send _ _ ({str sym} $_))'
30
29
 
31
30
  def on_block(node)
32
31
  return unless example_group_with_body?(node)
@@ -44,11 +43,11 @@ module RuboCop
44
43
 
45
44
  def find_duplicates(node)
46
45
  setup_expressions = Set.new
47
- node.each_child_node do |child|
48
- next unless setup?(child)
46
+ node.each_child_node(:block) do |child|
47
+ next unless common_setup?(child)
49
48
 
50
49
  name = if child.send_node.arguments?
51
- child.send_node.first_argument.value
50
+ first_argument_name(child.send_node).to_sym
52
51
  else
53
52
  :subject
54
53
  end
@@ -56,6 +55,13 @@ module RuboCop
56
55
  yield child, name unless setup_expressions.add?(name)
57
56
  end
58
57
  end
58
+
59
+ def common_setup?(node)
60
+ return false unless setup?(node)
61
+ # Search only for setup with basic_literal arguments (e.g. :sym, :str)
62
+ # or no arguments at all.
63
+ node.send_node.arguments.all?(&:basic_literal?)
64
+ end
59
65
  end
60
66
  end
61
67
  end
@@ -76,7 +76,7 @@ module RuboCop
76
76
 
77
77
  def range(node, offending_node)
78
78
  range_between(
79
- offending_node.loc.selector.begin_pos - 1, # match the dot as well
79
+ offending_node.loc.dot.begin_pos,
80
80
  node.loc.expression.end_pos
81
81
  )
82
82
  end
@@ -24,7 +24,9 @@ require_relative 'rspec/described_class'
24
24
  require_relative 'rspec/describe_method'
25
25
  require_relative 'rspec/describe_symbol'
26
26
  require_relative 'rspec/empty_example_group'
27
+ require_relative 'rspec/empty_line_after_example_group'
27
28
  require_relative 'rspec/empty_line_after_final_let'
29
+ require_relative 'rspec/empty_line_after_hook'
28
30
  require_relative 'rspec/empty_line_after_subject'
29
31
  require_relative 'rspec/example_length'
30
32
  require_relative 'rspec/example_without_description'
@@ -0,0 +1,37 @@
1
+ module RuboCop
2
+ module RSpec
3
+ # Helps determine the offending location if there is not a blank line
4
+ # following the node. Allows comments to follow directly after.
5
+ module BlankLineSeparation
6
+ include FinalEndLocation
7
+ include RuboCop::Cop::RangeHelp
8
+
9
+ def missing_separating_line(node)
10
+ line = final_end_location(node).line
11
+
12
+ line += 1 while comment_line?(processed_source[line])
13
+
14
+ return if processed_source[line].blank?
15
+
16
+ yield offending_loc(line)
17
+ end
18
+
19
+ def offending_loc(last_line)
20
+ offending_line = processed_source[last_line - 1]
21
+
22
+ content_length = offending_line.lstrip.length
23
+ start = offending_line.length - content_length
24
+
25
+ source_range(processed_source.buffer, last_line, start, content_length)
26
+ end
27
+
28
+ def autocorrect(node)
29
+ lambda do |corrector|
30
+ missing_separating_line(node) do |location|
31
+ corrector.insert_after(location.end, "\n")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ module RuboCop
2
+ module RSpec
3
+ # Helps find the true end location of nodes which might contain heredocs.
4
+ module FinalEndLocation
5
+ def final_end_location(start_node)
6
+ heredoc_endings =
7
+ start_node.each_node(:str, :dstr, :xstr)
8
+ .select(&:heredoc?)
9
+ .map { |node| node.loc.heredoc_end }
10
+
11
+ [start_node.loc.end, *heredoc_endings].max_by(&:line)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '1.26.0'.freeze
7
+ STRING = '1.27.0'.freeze
8
8
  end
9
9
  end
10
10
  end
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
37
37
  'documentation_uri' => 'https://rubocop-rspec.readthedocs.io/'
38
38
  }
39
39
 
40
- spec.add_runtime_dependency 'rubocop', '>= 0.53.0'
40
+ spec.add_runtime_dependency 'rubocop', '>= 0.56.0'
41
41
 
42
42
  spec.add_development_dependency 'rack'
43
43
  spec.add_development_dependency 'rake'
@@ -95,6 +95,9 @@ RSpec.describe RuboCop::Cop::RSpec::DescribeClass do
95
95
 
96
96
  it 'ignores an empty describe' do
97
97
  expect_no_offenses(<<-RUBY)
98
+ RSpec.describe do
99
+ end
100
+
98
101
  describe do
99
102
  end
100
103
  RUBY
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterExampleGroup do
4
+ subject(:cop) { described_class.new }
5
+
6
+ it 'checks for empty line after describe' do
7
+ expect_offense(<<-RUBY)
8
+ RSpec.describe Foo do
9
+ describe '#bar' do
10
+ end
11
+ ^^^ Add an empty line after `describe`.
12
+ describe '#baz' do
13
+ end
14
+ end
15
+ RUBY
16
+ end
17
+
18
+ it 'highlights single line formulations correctly' do
19
+ expect_offense(<<-RUBY)
20
+ RSpec.describe Foo do
21
+ describe('#bar') { }
22
+ ^^^^^^^^^^^^^^^^^^^^ Add an empty line after `describe`.
23
+ describe '#baz' do
24
+ end
25
+ end
26
+ RUBY
27
+ end
28
+
29
+ it 'checks for empty line after context' do
30
+ expect_offense(<<-RUBY)
31
+ RSpec.context 'foo' do
32
+ context 'bar' do
33
+ end
34
+ ^^^ Add an empty line after `context`.
35
+ context 'baz' do
36
+ end
37
+ end
38
+ RUBY
39
+ end
40
+
41
+ it 'approves empty line after describe' do
42
+ expect_no_offenses(<<-RUBY)
43
+ RSpec.describe Foo do
44
+ describe '#bar' do
45
+ end
46
+
47
+ describe '#baz' do
48
+ end
49
+ end
50
+ RUBY
51
+ end
52
+
53
+ it 'approves empty line after context' do
54
+ expect_no_offenses(<<-RUBY)
55
+ RSpec.context 'foo' do
56
+ context 'bar' do
57
+ end
58
+
59
+ context 'baz' do
60
+ end
61
+ end
62
+ RUBY
63
+ end
64
+
65
+ bad_example = <<-RUBY
66
+ RSpec.describe Foo do
67
+ describe '#bar' do
68
+ end
69
+ describe '#baz' do
70
+ end
71
+ end
72
+ RUBY
73
+
74
+ good_example = <<-RUBY
75
+ RSpec.describe Foo do
76
+ describe '#bar' do
77
+ end
78
+
79
+ describe '#baz' do
80
+ end
81
+ end
82
+ RUBY
83
+
84
+ include_examples 'autocorrect',
85
+ bad_example,
86
+ good_example
87
+ end
@@ -19,9 +19,9 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterFinalLet do
19
19
  RSpec.describe User do
20
20
  let(:a) { a }
21
21
  let!(:b) do
22
- ^^^^^^^^^^^ Add an empty line after the last `let` block.
23
22
  b
24
23
  end
24
+ ^^^ Add an empty line after the last `let` block.
25
25
  it { expect(a).to eq(b) }
26
26
  end
27
27
  RUBY
@@ -143,6 +143,21 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterFinalLet do
143
143
  RUBY
144
144
  end
145
145
 
146
+ it 'handles silly HEREDOC offense' do
147
+ expect_offense(<<-RUBY)
148
+ RSpec.describe 'silly heredoc syntax' do
149
+ let(:foo) { <<-BAR }
150
+ hello
151
+ world
152
+ BAR
153
+ ^^^ Add an empty line after the last `let` block.
154
+ it 'has tricky syntax' do
155
+ expect(foo).to eql(" hello\n world\n")
156
+ end
157
+ end
158
+ RUBY
159
+ end
160
+
146
161
  bad_example = <<-RUBY
147
162
  RSpec.describe User do
148
163
  let(:params) { foo }
@@ -185,6 +200,31 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterFinalLet do
185
200
  end
186
201
  RUBY
187
202
 
203
+ include_examples 'autocorrect',
204
+ bad_example,
205
+ good_example
206
+
207
+ bad_example = <<-RUBY
208
+ RSpec.describe User do
209
+ let(:params) { <<-DOC }
210
+ I'm super annoying!
211
+ DOC
212
+ it 'has a new line' do
213
+ end
214
+ end
215
+ RUBY
216
+
217
+ good_example = <<-RUBY
218
+ RSpec.describe User do
219
+ let(:params) { <<-DOC }
220
+ I'm super annoying!
221
+ DOC
222
+
223
+ it 'has a new line' do
224
+ end
225
+ end
226
+ RUBY
227
+
188
228
  include_examples 'autocorrect',
189
229
  bad_example,
190
230
  good_example
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterHook do
4
+ subject(:cop) { described_class.new }
5
+
6
+ it 'checks for empty line after `before` hook' do
7
+ expect_offense(<<-RUBY)
8
+ RSpec.describe User do
9
+ before { do_something }
10
+ ^^^^^^^^^^^^^^^^^^^^^^^ Add an empty line after `before`.
11
+ it { does_something }
12
+ end
13
+ RUBY
14
+ end
15
+
16
+ it 'checks for empty line after `after` hook' do
17
+ expect_offense(<<-RUBY)
18
+ RSpec.describe User do
19
+ after { do_something }
20
+ ^^^^^^^^^^^^^^^^^^^^^^ Add an empty line after `after`.
21
+ it { does_something }
22
+ end
23
+ RUBY
24
+ end
25
+
26
+ it 'checks for empty line after `around` hook' do
27
+ expect_offense(<<-RUBY)
28
+ RSpec.describe User do
29
+ around { |test| test.run }
30
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^ Add an empty line after `around`.
31
+ it { does_something }
32
+ end
33
+ RUBY
34
+ end
35
+
36
+ it 'approves empty line after `before` hook' do
37
+ expect_no_offenses(<<-RUBY)
38
+ RSpec.describe User do
39
+ before { do_something }
40
+
41
+ it { does_something }
42
+ end
43
+ RUBY
44
+ end
45
+
46
+ it 'approves empty line after `after` hook' do
47
+ expect_no_offenses(<<-RUBY)
48
+ RSpec.describe User do
49
+ after { do_something }
50
+
51
+ it { does_something }
52
+ end
53
+ RUBY
54
+ end
55
+
56
+ it 'approves empty line after `around` hook' do
57
+ expect_no_offenses(<<-RUBY)
58
+ RSpec.describe User do
59
+ around { |test| test.run }
60
+
61
+ it { does_something }
62
+ end
63
+ RUBY
64
+ end
65
+
66
+ it 'handles multiline `before` block' do
67
+ expect_no_offenses(<<-RUBY)
68
+ RSpec.describe User do
69
+ before do
70
+ do_something
71
+ end
72
+
73
+ it { does_something }
74
+ end
75
+ RUBY
76
+ end
77
+
78
+ it 'handles multiline `after` block' do
79
+ expect_no_offenses(<<-RUBY)
80
+ RSpec.describe User do
81
+ after do
82
+ do_something
83
+ end
84
+
85
+ it { does_something }
86
+ end
87
+ RUBY
88
+ end
89
+
90
+ it 'handles multiline `around` block' do
91
+ expect_no_offenses(<<-RUBY)
92
+ RSpec.describe User do
93
+ around do |test|
94
+ test.run
95
+ end
96
+
97
+ it { does_something }
98
+ end
99
+ RUBY
100
+ end
101
+
102
+ it 'handles `before` being the latest node' do
103
+ expect_no_offenses(<<-RUBY)
104
+ RSpec.describe User do
105
+ before { do_something }
106
+ end
107
+ RUBY
108
+ end
109
+
110
+ bad_example = <<-RUBY
111
+ RSpec.describe User do
112
+ before { do_something }
113
+ it { does_something }
114
+ end
115
+ RUBY
116
+
117
+ good_example = <<-RUBY
118
+ RSpec.describe User do
119
+ before { do_something }
120
+
121
+ it { does_something }
122
+ end
123
+ RUBY
124
+
125
+ include_examples 'autocorrect',
126
+ bad_example,
127
+ good_example
128
+ end
@@ -20,7 +20,7 @@ RSpec.describe RuboCop::Cop::RSpec::LeadingSubject do
20
20
  let!(:params) { foo }
21
21
 
22
22
  subject { described_class.new }
23
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `let` declarations.
23
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `let!` declarations.
24
24
  end
25
25
  RUBY
26
26
  end
@@ -63,8 +63,31 @@ RSpec.describe RuboCop::Cop::RSpec::LeadingSubject do
63
63
  RUBY
64
64
  end
65
65
 
66
+ it 'checks subject below hook' do
67
+ expect_offense(<<-RUBY)
68
+ RSpec.describe User do
69
+ before { allow(Foo).to receive(:bar) }
70
+
71
+ subject { described_class.new }
72
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `before` declarations.
73
+ end
74
+ RUBY
75
+ end
76
+
77
+ it 'checks subject below example' do
78
+ expect_offense(<<-RUBY)
79
+ RSpec.describe User do
80
+ it { is_expected.to be_present }
81
+
82
+ subject { described_class.new }
83
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `it` declarations.
84
+ end
85
+ RUBY
86
+ end
87
+
66
88
  bad_code = <<-RUBY
67
89
  RSpec.describe User do
90
+ before { allow(Foo).to receive(:bar) }
68
91
  let(:params) { foo }
69
92
  let(:bar) { baz }
70
93
 
@@ -76,6 +99,7 @@ RSpec.describe RuboCop::Cop::RSpec::LeadingSubject do
76
99
  good_code = <<-RUBY
77
100
  RSpec.describe User do
78
101
  subject { described_class.new }
102
+ before { allow(Foo).to receive(:bar) }
79
103
  let(:params) { foo }
80
104
  let(:bar) { baz }
81
105
 
@@ -7,7 +7,16 @@ RSpec.describe RuboCop::Cop::RSpec::NotToNot, :config do
7
7
  it 'detects the `to_not` offense' do
8
8
  expect_offense(<<-RUBY)
9
9
  it { expect(false).to_not be_true }
10
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `not_to` over `to_not`.
10
+ ^^^^^^ Prefer `not_to` over `to_not`.
11
+ RUBY
12
+ end
13
+
14
+ it 'detects the `to_not` offense on an expect block' do
15
+ expect_offense(<<-RUBY)
16
+ expect {
17
+ 2 + 2
18
+ }.to_not raise_error
19
+ ^^^^^^ Prefer `not_to` over `to_not`.
11
20
  RUBY
12
21
  end
13
22
 
@@ -20,6 +29,18 @@ RSpec.describe RuboCop::Cop::RSpec::NotToNot, :config do
20
29
  include_examples 'autocorrect',
21
30
  'it { expect(0).to_not equal 1 }',
22
31
  'it { expect(0).not_to equal 1 }'
32
+
33
+ original = <<-RUBY
34
+ expect {
35
+ 2 + 2
36
+ }.to_not raise_error
37
+ RUBY
38
+ corrected = <<-RUBY
39
+ expect {
40
+ 2 + 2
41
+ }.not_to raise_error
42
+ RUBY
43
+ include_examples 'autocorrect', original, corrected
23
44
  end
24
45
 
25
46
  context 'when AcceptedMethod is `to_not`' do
@@ -28,7 +49,16 @@ RSpec.describe RuboCop::Cop::RSpec::NotToNot, :config do
28
49
  it 'detects the `not_to` offense' do
29
50
  expect_offense(<<-RUBY)
30
51
  it { expect(false).not_to be_true }
31
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `to_not` over `not_to`.
52
+ ^^^^^^ Prefer `to_not` over `not_to`.
53
+ RUBY
54
+ end
55
+
56
+ it 'detects the `not_to` offense on an expect block' do
57
+ expect_offense(<<-RUBY)
58
+ expect {
59
+ 2 + 2
60
+ }.not_to raise_error
61
+ ^^^^^^ Prefer `to_not` over `not_to`.
32
62
  RUBY
33
63
  end
34
64
 
@@ -41,5 +71,17 @@ RSpec.describe RuboCop::Cop::RSpec::NotToNot, :config do
41
71
  include_examples 'autocorrect',
42
72
  'it { expect(0).not_to equal 1 }',
43
73
  'it { expect(0).to_not equal 1 }'
74
+
75
+ original = <<-RUBY
76
+ expect {
77
+ 2 + 2
78
+ }.not_to raise_error
79
+ RUBY
80
+ corrected = <<-RUBY
81
+ expect {
82
+ 2 + 2
83
+ }.to_not raise_error
84
+ RUBY
85
+ include_examples 'autocorrect', original, corrected
44
86
  end
45
87
  end
@@ -66,6 +66,27 @@ RSpec.describe RuboCop::Cop::RSpec::OverwritingSetup do
66
66
  RUBY
67
67
  end
68
68
 
69
+ it 'handles dynamic names for `let`' do
70
+ expect_no_offenses(<<-RUBY)
71
+ RSpec.describe User do
72
+ subject(:name) { a }
73
+
74
+ let(name) { b }
75
+ end
76
+ RUBY
77
+ end
78
+
79
+ it 'handles string arguments' do
80
+ expect_offense(<<-RUBY)
81
+ RSpec.describe User do
82
+ subject(:name) { a }
83
+
84
+ let("name") { b }
85
+ ^^^^^^^^^^^^^^^^^ `name` is already defined.
86
+ end
87
+ RUBY
88
+ end
89
+
69
90
  it 'does not encounter an error when handling an empty describe' do
70
91
  expect { inspect_source('RSpec.describe(User) do end', 'a_spec.rb') }
71
92
  .not_to raise_error
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.26.0
4
+ version: 1.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Backus
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-06-06 00:00:00.000000000 Z
13
+ date: 2018-06-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 0.53.0
21
+ version: 0.56.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: 0.53.0
28
+ version: 0.56.0
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: rack
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -132,7 +132,9 @@ files:
132
132
  - lib/rubocop/cop/rspec/describe_symbol.rb
133
133
  - lib/rubocop/cop/rspec/described_class.rb
134
134
  - lib/rubocop/cop/rspec/empty_example_group.rb
135
+ - lib/rubocop/cop/rspec/empty_line_after_example_group.rb
135
136
  - lib/rubocop/cop/rspec/empty_line_after_final_let.rb
137
+ - lib/rubocop/cop/rspec/empty_line_after_hook.rb
136
138
  - lib/rubocop/cop/rspec/empty_line_after_subject.rb
137
139
  - lib/rubocop/cop/rspec/example_length.rb
138
140
  - lib/rubocop/cop/rspec/example_without_description.rb
@@ -184,6 +186,7 @@ files:
184
186
  - lib/rubocop/cop/rspec_cops.rb
185
187
  - lib/rubocop/rspec.rb
186
188
  - lib/rubocop/rspec/align_let_brace.rb
189
+ - lib/rubocop/rspec/blank_line_separation.rb
187
190
  - lib/rubocop/rspec/capybara.rb
188
191
  - lib/rubocop/rspec/concept.rb
189
192
  - lib/rubocop/rspec/config_formatter.rb
@@ -191,6 +194,7 @@ files:
191
194
  - lib/rubocop/rspec/example.rb
192
195
  - lib/rubocop/rspec/example_group.rb
193
196
  - lib/rubocop/rspec/factory_bot.rb
197
+ - lib/rubocop/rspec/final_end_location.rb
194
198
  - lib/rubocop/rspec/hook.rb
195
199
  - lib/rubocop/rspec/inject.rb
196
200
  - lib/rubocop/rspec/language.rb
@@ -220,7 +224,9 @@ files:
220
224
  - spec/rubocop/cop/rspec/describe_symbol_spec.rb
221
225
  - spec/rubocop/cop/rspec/described_class_spec.rb
222
226
  - spec/rubocop/cop/rspec/empty_example_group_spec.rb
227
+ - spec/rubocop/cop/rspec/empty_line_after_example_group_spec.rb
223
228
  - spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb
229
+ - spec/rubocop/cop/rspec/empty_line_after_hook_spec.rb
224
230
  - spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb
225
231
  - spec/rubocop/cop/rspec/example_length_spec.rb
226
232
  - spec/rubocop/cop/rspec/example_without_description_spec.rb
@@ -327,7 +333,9 @@ test_files:
327
333
  - spec/rubocop/cop/rspec/describe_symbol_spec.rb
328
334
  - spec/rubocop/cop/rspec/described_class_spec.rb
329
335
  - spec/rubocop/cop/rspec/empty_example_group_spec.rb
336
+ - spec/rubocop/cop/rspec/empty_line_after_example_group_spec.rb
330
337
  - spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb
338
+ - spec/rubocop/cop/rspec/empty_line_after_hook_spec.rb
331
339
  - spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb
332
340
  - spec/rubocop/cop/rspec/example_length_spec.rb
333
341
  - spec/rubocop/cop/rspec/example_without_description_spec.rb