summaryrefslogtreecommitdiff
path: root/spec/support/helpers/access_matchers_helpers.rb
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-14 12:06:30 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-14 12:06:30 +0000
commitd8c06be498acbfc2024c01b6b6b02d120dc499f2 (patch)
tree9e2e0852c45332d6222898676a2f6f096e600084 /spec/support/helpers/access_matchers_helpers.rb
parent2fa7d2ddf6a7004f89616e43b8279229af831e25 (diff)
downloadgitlab-ce-d8c06be498acbfc2024c01b6b6b02d120dc499f2.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/support/helpers/access_matchers_helpers.rb')
-rw-r--r--spec/support/helpers/access_matchers_helpers.rb95
1 files changed, 95 insertions, 0 deletions
diff --git a/spec/support/helpers/access_matchers_helpers.rb b/spec/support/helpers/access_matchers_helpers.rb
new file mode 100644
index 00000000000..9100f245d36
--- /dev/null
+++ b/spec/support/helpers/access_matchers_helpers.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module AccessMatchersHelpers
+ 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)
+ if instance_variable_get(:@__#{USER_ACCESSOR_METHOD_NAME}_patched)
+ raise ArgumentError, 'An access matcher be_allowed_for/be_denied_for can be used only once per example (`it` block)'
+ end
+ instance_variable_set(:@__#{USER_ACCESSOR_METHOD_NAME}_patched, true)
+
+ 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 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
+ end
+end