Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rubocop/cop/rspec/before_all_role_assignment.rb')
-rw-r--r--rubocop/cop/rspec/before_all_role_assignment.rb77
1 files changed, 77 insertions, 0 deletions
diff --git a/rubocop/cop/rspec/before_all_role_assignment.rb b/rubocop/cop/rspec/before_all_role_assignment.rb
new file mode 100644
index 00000000000..fc7fdf4208a
--- /dev/null
+++ b/rubocop/cop/rspec/before_all_role_assignment.rb
@@ -0,0 +1,77 @@
+# 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