78 lines
2.2 KiB
Ruby
78 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rubocop-rspec'
|
|
|
|
module RuboCop
|
|
module Cop
|
|
module RSpec
|
|
# Checks for let_it_be with before instead of before_all when using `add_*` methods
|
|
#
|
|
# @example
|
|
#
|
|
# # bad
|
|
# let_it_be(:project) { create(:project) }
|
|
# let_it_be(:guest) { create(:user) }
|
|
#
|
|
# before do
|
|
# project.add_guest(guest)
|
|
# end
|
|
#
|
|
# # good
|
|
# let_it_be(:project) { create(:project) }
|
|
# let_it_be(:guest) { create(:user) }
|
|
#
|
|
# before_all do
|
|
# project.add_guest(guest)
|
|
# end
|
|
class BeforeAllRoleAssignment < RuboCop::Cop::RSpec::Base
|
|
MSG = "Use `before_all` when used with `%{let_it_be}`."
|
|
|
|
ROLE_METHODS = %i[add_guest add_reporter add_developer add_maintainer add_owner add_role].to_set.freeze
|
|
|
|
RESTRICT_ON_SEND = ROLE_METHODS
|
|
|
|
# @!method matching_let_it_be(node)
|
|
def_node_matcher :matching_let_it_be, <<~PATTERN
|
|
(block (send nil? $/^let_it_be/ (sym %name)) ...)
|
|
PATTERN
|
|
|
|
# @!method before_block?(node)
|
|
def_node_matcher :before_block?, <<~PATTERN
|
|
(block (send nil? :before ...) ...)
|
|
PATTERN
|
|
|
|
def_node_matcher :object_calling_add_role_method, <<~PATTERN
|
|
(send (send nil? $_) %ROLE_METHODS ...)
|
|
PATTERN
|
|
|
|
def on_send(node)
|
|
object_calling_add_role = object_calling_add_role_method(node)
|
|
return unless object_calling_add_role
|
|
|
|
before_block = before_block_ancestor(node)
|
|
return unless before_block
|
|
|
|
each_block_node_in_ancestor(node) do |child_node|
|
|
matching_let_it_be(child_node, name: object_calling_add_role) do |let_it_be|
|
|
message = format(MSG, let_it_be: let_it_be)
|
|
add_offense(node, message: message)
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def before_block_ancestor(node)
|
|
node.each_ancestor(:block).find { |block_node| before_block?(block_node) }
|
|
end
|
|
|
|
def each_block_node_in_ancestor(node, &block)
|
|
node.each_ancestor do |parent_node|
|
|
parent_node.each_child_node(:block, &block)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|