diff --git a/lib/rubocop/cop/rspec/let_setup.rb b/lib/rubocop/cop/rspec/let_setup.rb index b98a67551..eee06dbe4 100644 --- a/lib/rubocop/cop/rspec/let_setup.rb +++ b/lib/rubocop/cop/rspec/let_setup.rb @@ -28,14 +28,20 @@ module RSpec class LetSetup < Cop MSG = 'Do not use `let!` to setup objects not referenced in tests.' - def_node_search :let_bang, <<-PATTERN + def_node_matcher :example_or_shared_group_or_including?, + ( + ExampleGroups::ALL + SharedGroups::ALL + + Includes::ALL + ).block_pattern + + def_node_matcher :let_bang, <<-PATTERN (block $(send nil? :let! (sym $_)) args ...) PATTERN def_node_search :method_called?, '(send nil? %)' def on_block(node) - return unless example_group?(node) + return unless example_or_shared_group_or_including?(node) unused_let_bang(node) do |let| add_offense(let) @@ -45,10 +51,16 @@ def on_block(node) private def unused_let_bang(node) - let_bang(node) do |method_send, method_name| + child_let_bang(node) do |method_send, method_name| yield(method_send) unless method_called?(node, method_name) end end + + def child_let_bang(node, &block) + RuboCop::RSpec::ExampleGroup.new(node).lets.each do |let| + let_bang(let, &block) + end + end end end end diff --git a/spec/rubocop/cop/rspec/let_setup_spec.rb b/spec/rubocop/cop/rspec/let_setup_spec.rb index 7d42305cc..152a661a0 100644 --- a/spec/rubocop/cop/rspec/let_setup_spec.rb +++ b/spec/rubocop/cop/rspec/let_setup_spec.rb @@ -63,4 +63,53 @@ end RUBY end + + it 'complains when let! is used and not referenced in shared example group' do + expect_offense(<<-RUBY) + shared_context 'foo' do + let!(:bar) { baz } + ^^^^^^^^^^ Do not use `let!` to setup objects not referenced in tests. + + it 'does not use bar' do + expect(baz).to eq(qux) + end + end + RUBY + end + + it 'complains when let! used in shared example including' do + expect_offense(<<-RUBY) + describe Foo do + it_behaves_like 'bar' do + let!(:baz) { foobar } + ^^^^^^^^^^ Do not use `let!` to setup objects not referenced in tests. + let(:a) { b } + end + end + RUBY + end + + it 'complains when there is only one nested node into example group' do + expect_offense(<<-RUBY) + describe Foo do + let!(:bar) { baz } + ^^^^^^^^^^ Do not use `let!` to setup objects not referenced in tests. + end + RUBY + end + + it 'complains when there is a custom nesting level' do + expect_offense(<<-RUBY) + describe Foo do + [].each do |i| + let!(:bar) { i } + ^^^^^^^^^^ Do not use `let!` to setup objects not referenced in tests. + + it 'does not use bar' do + expect(baz).to eq(qux) + end + end + end + RUBY + end end