gitlab-org--gitlab-foss/spec/support/helpers/access_matchers_helpers.rb

102 lines
2.8 KiB
Ruby

# frozen_string_literal: true
module AccessMatchersHelpers
include Gitlab::Utils::StrongMemoize
USER_ACCESSOR_METHOD_NAME = 'user'
def provide_user(role, membership = nil)
case role
when :admin
create(:admin)
when :auditor
create(:user, :auditor)
when :user
create(:user)
when :external
create(:user, :external)
when :visitor, :anonymous
nil
when User
role
when *Gitlab::Access.sym_options_with_owner.keys # owner, maintainer, developer, reporter, guest
raise ArgumentError, "cannot provide #{role} when membership reference is blank" unless membership
provide_user_by_membership(role, membership)
else
raise ArgumentError, "cannot provide user of an unknown role #{role}"
end
end
def provide_user_by_membership(role, membership)
if role == :owner && membership.owner
membership.owner
else
create(:user).tap do |user|
membership.public_send(:"add_#{role}", user)
end
end
end
def raise_if_non_block_expectation!(actual)
raise ArgumentError, 'This matcher supports block expectations only.' unless actual.is_a?(Proc)
end
def update_owner(objects, user)
return unless objects
objects.each do |object|
if object.respond_to?(:owner)
object.update_attribute(:owner, user)
elsif object.respond_to?(:user)
object.update_attribute(:user, user)
else
raise ArgumentError, "cannot own this object #{object}"
end
end
end
def patch_example_group(user)
return if user.nil? # for anonymous users
# This call is evaluated in context of ExampleGroup instance in which the matcher is called. Overrides the `user`
# (or defined by `method_name`) method generated by `let` definition in example group before it's used by `subject`.
# This override is per concrete example only because the example group class gets re-created for each example.
instance_eval(<<~CODE, __FILE__, __LINE__ + 1)
def #{USER_ACCESSOR_METHOD_NAME}
@#{USER_ACCESSOR_METHOD_NAME} ||= User.find(#{user.id})
end
CODE
end
def prepare_matcher_environment(role, membership, owned_objects)
user = provide_user(role, membership)
if user
update_owner(owned_objects, user)
patch_example_group(user)
end
end
def reset_matcher_environment
instance_eval(<<~CODE, __FILE__, __LINE__ + 1)
clear_memoization(:#{USER_ACCESSOR_METHOD_NAME})
undef #{USER_ACCESSOR_METHOD_NAME} if defined? user
CODE
end
def run_matcher(action, role, membership, owned_objects)
raise_if_non_block_expectation!(action)
prepare_matcher_environment(role, membership, owned_objects)
if block_given?
yield action
else
action.call
end
reset_matcher_environment
end
end