2019-07-07 11:18:12 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
require 'spec_helper'
2017-09-10 17:25:29 +05:30
describe Group do
2017-08-17 22:00:37 +05:30
let! ( :group ) { create ( :group , :access_requestable ) }
2014-09-02 18:07:02 +05:30
2015-09-11 14:41:01 +05:30
describe 'associations' do
2015-04-26 12:48:37 +05:30
it { is_expected . to have_many :projects }
2016-06-16 23:09:34 +05:30
it { is_expected . to have_many ( :group_members ) . dependent ( :destroy ) }
it { is_expected . to have_many ( :users ) . through ( :group_members ) }
2016-08-24 12:49:21 +05:30
it { is_expected . to have_many ( :owners ) . through ( :group_members ) }
it { is_expected . to have_many ( :requesters ) . dependent ( :destroy ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :members_and_requesters ) }
2016-06-16 23:09:34 +05:30
it { is_expected . to have_many ( :project_group_links ) . dependent ( :destroy ) }
it { is_expected . to have_many ( :shared_projects ) . through ( :project_group_links ) }
it { is_expected . to have_many ( :notification_settings ) . dependent ( :destroy ) }
2016-11-03 12:29:30 +05:30
it { is_expected . to have_many ( :labels ) . class_name ( 'GroupLabel' ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :variables ) . class_name ( 'Ci::GroupVariable' ) }
2018-11-08 19:23:39 +05:30
it { is_expected . to have_many ( :uploads ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to have_one ( :chat_team ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :custom_attributes ) . class_name ( 'GroupCustomAttribute' ) }
2018-03-27 19:54:05 +05:30
it { is_expected . to have_many ( :badges ) . class_name ( 'GroupBadge' ) }
2018-12-13 13:39:08 +05:30
it { is_expected . to have_many ( :cluster_groups ) . class_name ( 'Clusters::Group' ) }
it { is_expected . to have_many ( :clusters ) . class_name ( 'Clusters::Cluster' ) }
2019-10-12 21:52:04 +05:30
it { is_expected . to have_many ( :container_repositories ) }
2016-08-24 12:49:21 +05:30
describe '#members & #requesters' do
let ( :requester ) { create ( :user ) }
let ( :developer ) { create ( :user ) }
before do
group . request_access ( requester )
group . add_developer ( developer )
end
2018-03-17 18:26:18 +05:30
it_behaves_like 'members and requesters associations' do
let ( :namespace ) { group }
2016-08-24 12:49:21 +05:30
end
end
2014-09-02 18:07:02 +05:30
end
2015-09-11 14:41:01 +05:30
describe 'modules' do
subject { described_class }
it { is_expected . to include_module ( Referable ) }
end
describe 'validations' do
it { is_expected . to validate_presence_of :name }
it { is_expected . to validate_presence_of :path }
it { is_expected . not_to validate_presence_of :owner }
2017-08-17 22:00:37 +05:30
it { is_expected . to validate_presence_of :two_factor_grace_period }
it { is_expected . to validate_numericality_of ( :two_factor_grace_period ) . is_greater_than_or_equal_to ( 0 ) }
describe 'path validation' do
it 'rejects paths reserved on the root namespace when the group has no parent' do
group = build ( :group , path : 'api' )
expect ( group ) . not_to be_valid
end
it 'allows root paths when the group has a parent' do
group = build ( :group , path : 'api' , parent : create ( :group ) )
expect ( group ) . to be_valid
end
it 'rejects any wildcard paths when not a top level group' do
group = build ( :group , path : 'tree' , parent : create ( :group ) )
expect ( group ) . not_to be_valid
end
2018-03-17 18:26:18 +05:30
end
2017-08-17 22:00:37 +05:30
2019-10-12 21:52:04 +05:30
describe '#notification_settings' do
2018-11-08 19:23:39 +05:30
let ( :user ) { create ( :user ) }
let ( :group ) { create ( :group ) }
let ( :sub_group ) { create ( :group , parent_id : group . id ) }
before do
group . add_developer ( user )
2019-02-15 15:39:39 +05:30
sub_group . add_maintainer ( user )
2018-11-08 19:23:39 +05:30
end
it 'also gets notification settings from parent groups' do
expect ( sub_group . notification_settings . size ) . to eq ( 2 )
expect ( sub_group . notification_settings ) . to include ( group . notification_settings . first )
end
context 'when sub group is deleted' do
it 'does not delete parent notification settings' do
expect do
sub_group . destroy
end . to change { NotificationSetting . count } . by ( - 1 )
end
end
end
2019-10-12 21:52:04 +05:30
describe '#notification_email_for' do
let ( :user ) { create ( :user ) }
let ( :group ) { create ( :group ) }
let ( :subgroup ) { create ( :group , parent : group ) }
let ( :group_notification_email ) { 'user+group@example.com' }
let ( :subgroup_notification_email ) { 'user+subgroup@example.com' }
subject { subgroup . notification_email_for ( user ) }
context 'when both group notification emails are set' do
it 'returns subgroup notification email' do
create ( :notification_setting , user : user , source : group , notification_email : group_notification_email )
create ( :notification_setting , user : user , source : subgroup , notification_email : subgroup_notification_email )
is_expected . to eq ( subgroup_notification_email )
end
end
context 'when subgroup notification email is blank' do
it 'returns parent group notification email' do
create ( :notification_setting , user : user , source : group , notification_email : group_notification_email )
create ( :notification_setting , user : user , source : subgroup , notification_email : '' )
is_expected . to eq ( group_notification_email )
end
end
context 'when only the parent group notification email is set' do
it 'returns parent group notification email' do
create ( :notification_setting , user : user , source : group , notification_email : group_notification_email )
is_expected . to eq ( group_notification_email )
end
end
end
2018-03-17 18:26:18 +05:30
describe '#visibility_level_allowed_by_parent' do
let ( :parent ) { create ( :group , :internal ) }
let ( :sub_group ) { build ( :group , parent_id : parent . id ) }
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
context 'without a parent' do
it 'is valid' do
sub_group . parent_id = nil
expect ( sub_group ) . to be_valid
end
end
context 'with a parent' do
context 'when visibility of sub group is greater than the parent' do
it 'is invalid' do
sub_group . visibility_level = Gitlab :: VisibilityLevel :: PUBLIC
expect ( sub_group ) . to be_invalid
end
end
context 'when visibility of sub group is lower or equal to the parent' do
[ Gitlab :: VisibilityLevel :: INTERNAL , Gitlab :: VisibilityLevel :: PRIVATE ] . each do | level |
it 'is valid' do
sub_group . visibility_level = level
expect ( sub_group ) . to be_valid
end
end
end
end
end
describe '#visibility_level_allowed_by_projects' do
let! ( :internal_group ) { create ( :group , :internal ) }
let! ( :internal_project ) { create ( :project , :internal , group : internal_group ) }
context 'when group has a lower visibility' do
it 'is invalid' do
internal_group . visibility_level = Gitlab :: VisibilityLevel :: PRIVATE
expect ( internal_group ) . to be_invalid
expect ( internal_group . errors [ :visibility_level ] ) . to include ( 'private is not allowed since this group contains projects with higher visibility.' )
end
end
context 'when group has a higher visibility' do
it 'is valid' do
internal_group . visibility_level = Gitlab :: VisibilityLevel :: PUBLIC
expect ( internal_group ) . to be_valid
end
end
end
describe '#visibility_level_allowed_by_sub_groups' do
let! ( :internal_group ) { create ( :group , :internal ) }
let! ( :internal_sub_group ) { create ( :group , :internal , parent : internal_group ) }
context 'when parent group has a lower visibility' do
it 'is invalid' do
internal_group . visibility_level = Gitlab :: VisibilityLevel :: PRIVATE
expect ( internal_group ) . to be_invalid
expect ( internal_group . errors [ :visibility_level ] ) . to include ( 'private is not allowed since there are sub-groups with higher visibility.' )
end
end
context 'when parent group has a higher visibility' do
it 'is valid' do
internal_group . visibility_level = Gitlab :: VisibilityLevel :: PUBLIC
expect ( internal_group ) . to be_valid
end
2017-08-17 22:00:37 +05:30
end
end
2015-09-11 14:41:01 +05:30
end
2018-11-08 19:23:39 +05:30
describe '.public_or_visible_to_user' do
let! ( :private_group ) { create ( :group , :private ) }
let! ( :internal_group ) { create ( :group , :internal ) }
2015-11-26 14:37:03 +05:30
2018-11-08 19:23:39 +05:30
subject { described_class . public_or_visible_to_user ( user ) }
2015-11-26 14:37:03 +05:30
2018-11-08 19:23:39 +05:30
context 'when user is nil' do
let! ( :user ) { nil }
2015-11-26 14:37:03 +05:30
2018-11-08 19:23:39 +05:30
it { is_expected . to match_array ( [ group ] ) }
2015-11-26 14:37:03 +05:30
end
2018-11-08 19:23:39 +05:30
context 'when user' do
let! ( :user ) { create ( :user ) }
context 'when user does not have access to any private group' do
it { is_expected . to match_array ( [ internal_group , group ] ) }
end
context 'when user is a member of private group' do
before do
private_group . add_user ( user , Gitlab :: Access :: DEVELOPER )
end
it { is_expected . to match_array ( [ private_group , internal_group , group ] ) }
end
2019-10-12 21:52:04 +05:30
context 'when user is a member of private subgroup' do
2018-11-08 19:23:39 +05:30
let! ( :private_subgroup ) { create ( :group , :private , parent : private_group ) }
before do
private_subgroup . add_user ( user , Gitlab :: Access :: DEVELOPER )
end
it { is_expected . to match_array ( [ private_subgroup , internal_group , group ] ) }
end
2015-11-26 14:37:03 +05:30
end
end
2016-06-02 11:05:42 +05:30
describe 'scopes' do
let! ( :private_group ) { create ( :group , :private ) }
let! ( :internal_group ) { create ( :group , :internal ) }
describe 'public_only' do
subject { described_class . public_only . to_a }
2017-08-17 22:00:37 +05:30
it { is_expected . to eq ( [ group ] ) }
2016-06-02 11:05:42 +05:30
end
describe 'public_and_internal_only' do
subject { described_class . public_and_internal_only . to_a }
2017-08-17 22:00:37 +05:30
it { is_expected . to match_array ( [ group , internal_group ] ) }
end
describe 'non_public_only' do
subject { described_class . non_public_only . to_a }
it { is_expected . to match_array ( [ private_group , internal_group ] ) }
2016-06-02 11:05:42 +05:30
end
end
2015-09-11 14:41:01 +05:30
describe '#to_reference' do
it 'returns a String reference to the object' do
expect ( group . to_reference ) . to eq " @ #{ group . name } "
end
end
2014-09-02 18:07:02 +05:30
2016-08-24 12:49:21 +05:30
describe '#users' do
2015-04-26 12:48:37 +05:30
it { expect ( group . users ) . to eq ( group . owners ) }
2014-09-02 18:07:02 +05:30
end
2016-08-24 12:49:21 +05:30
describe '#human_name' do
2015-04-26 12:48:37 +05:30
it { expect ( group . human_name ) . to eq ( group . name ) }
2014-09-02 18:07:02 +05:30
end
2016-08-24 12:49:21 +05:30
describe '#add_user' do
2014-09-02 18:07:02 +05:30
let ( :user ) { create ( :user ) }
2017-09-10 17:25:29 +05:30
before do
2018-11-18 11:00:15 +05:30
group . add_user ( user , GroupMember :: MAINTAINER )
2017-09-10 17:25:29 +05:30
end
2014-09-02 18:07:02 +05:30
2018-11-18 11:00:15 +05:30
it { expect ( group . group_members . maintainers . map ( & :user ) ) . to include ( user ) }
2014-09-02 18:07:02 +05:30
end
2016-08-24 12:49:21 +05:30
describe '#add_users' do
2014-09-02 18:07:02 +05:30
let ( :user ) { create ( :user ) }
2017-09-10 17:25:29 +05:30
before do
group . add_users ( [ user . id ] , GroupMember :: GUEST )
end
2014-09-02 18:07:02 +05:30
2016-09-13 17:45:13 +05:30
it " updates the group permission " do
2015-04-26 12:48:37 +05:30
expect ( group . group_members . guests . map ( & :user ) ) . to include ( user )
group . add_users ( [ user . id ] , GroupMember :: DEVELOPER )
expect ( group . group_members . developers . map ( & :user ) ) . to include ( user )
expect ( group . group_members . guests . map ( & :user ) ) . not_to include ( user )
2014-09-02 18:07:02 +05:30
end
end
2016-08-24 12:49:21 +05:30
describe '#avatar_type' do
2014-09-02 18:07:02 +05:30
let ( :user ) { create ( :user ) }
2017-09-10 17:25:29 +05:30
before do
2018-11-18 11:00:15 +05:30
group . add_user ( user , GroupMember :: MAINTAINER )
2017-09-10 17:25:29 +05:30
end
2014-09-02 18:07:02 +05:30
2016-09-13 17:45:13 +05:30
it " is true if avatar is image " do
2014-09-02 18:07:02 +05:30
group . update_attribute ( :avatar , 'uploads/avatar.png' )
2015-04-26 12:48:37 +05:30
expect ( group . avatar_type ) . to be_truthy
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " is false if avatar is html page " do
2014-09-02 18:07:02 +05:30
group . update_attribute ( :avatar , 'uploads/avatar.html' )
2018-11-08 19:23:39 +05:30
expect ( group . avatar_type ) . to eq ( [ " file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico " ] )
2014-09-02 18:07:02 +05:30
end
end
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
describe '#avatar_url' do
let! ( :group ) { create ( :group , :access_requestable , :with_avatar ) }
let ( :user ) { create ( :user ) }
context 'when avatar file is uploaded' do
before do
2018-11-18 11:00:15 +05:30
group . add_maintainer ( user )
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
it 'shows correct avatar url' do
2018-03-17 18:26:18 +05:30
expect ( group . avatar_url ) . to eq ( group . avatar . url )
expect ( group . avatar_url ( only_path : false ) ) . to eq ( [ Gitlab . config . gitlab . url , group . avatar . url ] . join )
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
end
end
2016-06-02 11:05:42 +05:30
describe '.search' do
it 'returns groups with a matching name' do
expect ( described_class . search ( group . name ) ) . to eq ( [ group ] )
end
it 'returns groups with a partially matching name' do
expect ( described_class . search ( group . name [ 0 .. 2 ] ) ) . to eq ( [ group ] )
end
it 'returns groups with a matching name regardless of the casing' do
expect ( described_class . search ( group . name . upcase ) ) . to eq ( [ group ] )
end
it 'returns groups with a matching path' do
expect ( described_class . search ( group . path ) ) . to eq ( [ group ] )
end
it 'returns groups with a partially matching path' do
expect ( described_class . search ( group . path [ 0 .. 2 ] ) ) . to eq ( [ group ] )
end
it 'returns groups with a matching path regardless of the casing' do
expect ( described_class . search ( group . path . upcase ) ) . to eq ( [ group ] )
end
end
2016-06-16 23:09:34 +05:30
describe '#has_owner?' do
2017-09-10 17:25:29 +05:30
before do
@members = setup_group_members ( group )
create ( :group_member , :invited , :owner , group : group )
end
2016-06-16 23:09:34 +05:30
it { expect ( group . has_owner? ( @members [ :owner ] ) ) . to be_truthy }
2018-11-18 11:00:15 +05:30
it { expect ( group . has_owner? ( @members [ :maintainer ] ) ) . to be_falsey }
2016-06-16 23:09:34 +05:30
it { expect ( group . has_owner? ( @members [ :developer ] ) ) . to be_falsey }
it { expect ( group . has_owner? ( @members [ :reporter ] ) ) . to be_falsey }
it { expect ( group . has_owner? ( @members [ :guest ] ) ) . to be_falsey }
it { expect ( group . has_owner? ( @members [ :requester ] ) ) . to be_falsey }
2017-09-10 17:25:29 +05:30
it { expect ( group . has_owner? ( nil ) ) . to be_falsey }
2016-06-16 23:09:34 +05:30
end
2018-11-18 11:00:15 +05:30
describe '#has_maintainer?' do
2017-09-10 17:25:29 +05:30
before do
@members = setup_group_members ( group )
2018-11-18 11:00:15 +05:30
create ( :group_member , :invited , :maintainer , group : group )
2017-09-10 17:25:29 +05:30
end
2016-06-16 23:09:34 +05:30
2018-11-18 11:00:15 +05:30
it { expect ( group . has_maintainer? ( @members [ :owner ] ) ) . to be_falsey }
it { expect ( group . has_maintainer? ( @members [ :maintainer ] ) ) . to be_truthy }
it { expect ( group . has_maintainer? ( @members [ :developer ] ) ) . to be_falsey }
it { expect ( group . has_maintainer? ( @members [ :reporter ] ) ) . to be_falsey }
it { expect ( group . has_maintainer? ( @members [ :guest ] ) ) . to be_falsey }
it { expect ( group . has_maintainer? ( @members [ :requester ] ) ) . to be_falsey }
it { expect ( group . has_maintainer? ( nil ) ) . to be_falsey }
2016-06-16 23:09:34 +05:30
end
2019-07-07 11:18:12 +05:30
describe '#last_owner?' do
before do
@members = setup_group_members ( group )
end
it { expect ( group . last_owner? ( @members [ :owner ] ) ) . to be_truthy }
context 'with two owners' do
before do
create ( :group_member , :owner , group : group )
end
it { expect ( group . last_owner? ( @members [ :owner ] ) ) . to be_falsy }
end
2019-10-12 21:52:04 +05:30
context 'with owners from a parent' do
2019-07-07 11:18:12 +05:30
before do
parent_group = create ( :group )
create ( :group_member , :owner , group : parent_group )
group . update ( parent : parent_group )
end
it { expect ( group . last_owner? ( @members [ :owner ] ) ) . to be_falsy }
end
end
2016-09-29 09:46:39 +05:30
describe '#lfs_enabled?' do
context 'LFS enabled globally' do
before do
allow ( Gitlab . config . lfs ) . to receive ( :enabled ) . and_return ( true )
end
it 'returns true when nothing is set' do
expect ( group . lfs_enabled? ) . to be_truthy
end
it 'returns false when set to false' do
group . update_attribute ( :lfs_enabled , false )
expect ( group . lfs_enabled? ) . to be_falsey
end
it 'returns true when set to true' do
group . update_attribute ( :lfs_enabled , true )
expect ( group . lfs_enabled? ) . to be_truthy
end
end
context 'LFS disabled globally' do
before do
allow ( Gitlab . config . lfs ) . to receive ( :enabled ) . and_return ( false )
end
it 'returns false when nothing is set' do
expect ( group . lfs_enabled? ) . to be_falsey
end
it 'returns false when set to false' do
group . update_attribute ( :lfs_enabled , false )
expect ( group . lfs_enabled? ) . to be_falsey
end
it 'returns false when set to true' do
group . update_attribute ( :lfs_enabled , true )
expect ( group . lfs_enabled? ) . to be_falsey
end
end
end
2016-06-22 15:30:34 +05:30
describe '#owners' do
let ( :owner ) { create ( :user ) }
let ( :developer ) { create ( :user ) }
it 'returns the owners of a Group' do
group . add_owner ( owner )
group . add_developer ( developer )
expect ( group . owners ) . to eq ( [ owner ] )
end
end
2016-06-16 23:09:34 +05:30
def setup_group_members ( group )
members = {
owner : create ( :user ) ,
2018-11-18 11:00:15 +05:30
maintainer : create ( :user ) ,
2016-06-16 23:09:34 +05:30
developer : create ( :user ) ,
reporter : create ( :user ) ,
guest : create ( :user ) ,
requester : create ( :user )
}
group . add_user ( members [ :owner ] , GroupMember :: OWNER )
2018-11-18 11:00:15 +05:30
group . add_user ( members [ :maintainer ] , GroupMember :: MAINTAINER )
2016-06-16 23:09:34 +05:30
group . add_user ( members [ :developer ] , GroupMember :: DEVELOPER )
group . add_user ( members [ :reporter ] , GroupMember :: REPORTER )
group . add_user ( members [ :guest ] , GroupMember :: GUEST )
group . request_access ( members [ :requester ] )
members
end
2016-11-03 12:29:30 +05:30
describe '#web_url' do
it 'returns the canonical URL' do
expect ( group . web_url ) . to include ( " groups/ #{ group . name } " )
end
2017-08-17 22:00:37 +05:30
context 'nested group' do
let ( :nested_group ) { create ( :group , :nested ) }
it { expect ( nested_group . web_url ) . to include ( " groups/ #{ nested_group . full_path } " ) }
end
end
describe 'nested group' do
subject { build ( :group , :nested ) }
it { is_expected . to be_valid }
2017-09-10 17:25:29 +05:30
it { expect ( subject . parent ) . to be_kind_of ( described_class ) }
2017-08-17 22:00:37 +05:30
end
2019-10-12 21:52:04 +05:30
describe '#members_with_parents' do
2017-08-17 22:00:37 +05:30
let! ( :group ) { create ( :group , :nested ) }
2018-11-18 11:00:15 +05:30
let! ( :maintainer ) { group . parent . add_user ( create ( :user ) , GroupMember :: MAINTAINER ) }
2017-08-17 22:00:37 +05:30
let! ( :developer ) { group . add_user ( create ( :user ) , GroupMember :: DEVELOPER ) }
it 'returns parents members' do
expect ( group . members_with_parents ) . to include ( developer )
2018-11-18 11:00:15 +05:30
expect ( group . members_with_parents ) . to include ( maintainer )
2017-08-17 22:00:37 +05:30
end
end
2019-10-12 21:52:04 +05:30
describe '#direct_and_indirect_members' do
2018-10-15 14:42:47 +05:30
let! ( :group ) { create ( :group , :nested ) }
let! ( :sub_group ) { create ( :group , parent : group ) }
2018-11-18 11:00:15 +05:30
let! ( :maintainer ) { group . parent . add_user ( create ( :user ) , GroupMember :: MAINTAINER ) }
2018-10-15 14:42:47 +05:30
let! ( :developer ) { group . add_user ( create ( :user ) , GroupMember :: DEVELOPER ) }
let! ( :other_developer ) { group . add_user ( create ( :user ) , GroupMember :: DEVELOPER ) }
it 'returns parents members' do
expect ( group . direct_and_indirect_members ) . to include ( developer )
2018-11-18 11:00:15 +05:30
expect ( group . direct_and_indirect_members ) . to include ( maintainer )
2018-10-15 14:42:47 +05:30
end
it 'returns descendant members' do
expect ( group . direct_and_indirect_members ) . to include ( other_developer )
end
end
2019-10-12 21:52:04 +05:30
describe '#users_with_descendants' do
2018-10-15 14:42:47 +05:30
let ( :user_a ) { create ( :user ) }
let ( :user_b ) { create ( :user ) }
let ( :group ) { create ( :group ) }
let ( :nested_group ) { create ( :group , parent : group ) }
let ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
it 'returns member users on every nest level without duplication' do
group . add_developer ( user_a )
nested_group . add_developer ( user_b )
2019-02-15 15:39:39 +05:30
deep_nested_group . add_maintainer ( user_a )
2018-10-15 14:42:47 +05:30
expect ( group . users_with_descendants ) . to contain_exactly ( user_a , user_b )
expect ( nested_group . users_with_descendants ) . to contain_exactly ( user_a , user_b )
expect ( deep_nested_group . users_with_descendants ) . to contain_exactly ( user_a )
end
end
2019-10-12 21:52:04 +05:30
describe '#direct_and_indirect_users' do
2018-10-15 14:42:47 +05:30
let ( :user_a ) { create ( :user ) }
let ( :user_b ) { create ( :user ) }
let ( :user_c ) { create ( :user ) }
let ( :user_d ) { create ( :user ) }
let ( :group ) { create ( :group ) }
let ( :nested_group ) { create ( :group , parent : group ) }
let ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
let ( :project ) { create ( :project , namespace : group ) }
before do
group . add_developer ( user_a )
group . add_developer ( user_c )
nested_group . add_developer ( user_b )
deep_nested_group . add_developer ( user_a )
project . add_developer ( user_d )
end
it 'returns member users on every nest level without duplication' do
expect ( group . direct_and_indirect_users ) . to contain_exactly ( user_a , user_b , user_c , user_d )
expect ( nested_group . direct_and_indirect_users ) . to contain_exactly ( user_a , user_b , user_c )
expect ( deep_nested_group . direct_and_indirect_users ) . to contain_exactly ( user_a , user_b , user_c )
end
it 'does not return members of projects belonging to ancestor groups' do
expect ( nested_group . direct_and_indirect_users ) . not_to include ( user_d )
end
end
2019-10-12 21:52:04 +05:30
describe '#project_users_with_descendants' do
2018-10-15 14:42:47 +05:30
let ( :user_a ) { create ( :user ) }
let ( :user_b ) { create ( :user ) }
let ( :user_c ) { create ( :user ) }
let ( :group ) { create ( :group ) }
let ( :nested_group ) { create ( :group , parent : group ) }
let ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
let ( :project_a ) { create ( :project , namespace : group ) }
let ( :project_b ) { create ( :project , namespace : nested_group ) }
let ( :project_c ) { create ( :project , namespace : deep_nested_group ) }
it 'returns members of all projects in group and subgroups' do
project_a . add_developer ( user_a )
project_b . add_developer ( user_b )
project_c . add_developer ( user_c )
expect ( group . project_users_with_descendants ) . to contain_exactly ( user_a , user_b , user_c )
expect ( nested_group . project_users_with_descendants ) . to contain_exactly ( user_b , user_c )
expect ( deep_nested_group . project_users_with_descendants ) . to contain_exactly ( user_c )
end
end
2017-08-17 22:00:37 +05:30
describe '#user_ids_for_project_authorizations' do
it 'returns the user IDs for which to refresh authorizations' do
2018-11-18 11:00:15 +05:30
maintainer = create ( :user )
2017-08-17 22:00:37 +05:30
developer = create ( :user )
2018-11-18 11:00:15 +05:30
group . add_user ( maintainer , GroupMember :: MAINTAINER )
2017-08-17 22:00:37 +05:30
group . add_user ( developer , GroupMember :: DEVELOPER )
2017-09-10 17:25:29 +05:30
expect ( group . user_ids_for_project_authorizations )
2018-11-18 11:00:15 +05:30
. to include ( maintainer . id , developer . id )
2017-08-17 22:00:37 +05:30
end
end
describe '#update_two_factor_requirement' do
let ( :user ) { create ( :user ) }
2019-09-04 21:01:54 +05:30
context 'group membership' do
before do
group . add_user ( user , GroupMember :: OWNER )
end
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
it 'is called when require_two_factor_authentication is changed' do
expect_any_instance_of ( User ) . to receive ( :update_two_factor_requirement )
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
group . update! ( require_two_factor_authentication : true )
end
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
it 'is called when two_factor_grace_period is changed' do
expect_any_instance_of ( User ) . to receive ( :update_two_factor_requirement )
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
group . update! ( two_factor_grace_period : 23 )
end
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
it 'is not called when other attributes are changed' do
expect_any_instance_of ( User ) . not_to receive ( :update_two_factor_requirement )
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
group . update! ( description : 'foobar' )
end
it 'calls #update_two_factor_requirement on each group member' do
other_user = create ( :user )
group . add_user ( other_user , GroupMember :: OWNER )
calls = 0
allow_any_instance_of ( User ) . to receive ( :update_two_factor_requirement ) do
calls += 1
end
group . update! ( require_two_factor_authentication : true , two_factor_grace_period : 23 )
expect ( calls ) . to eq 2
end
2017-08-17 22:00:37 +05:30
end
2019-10-12 21:52:04 +05:30
context 'sub groups and projects' do
2019-09-04 21:01:54 +05:30
it 'enables two_factor_requirement for group member' do
group . add_user ( user , GroupMember :: OWNER )
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
group . update! ( require_two_factor_authentication : true )
expect ( user . reload . require_two_factor_authentication_from_group ) . to be_truthy
2017-08-17 22:00:37 +05:30
end
2019-10-12 21:52:04 +05:30
context 'expanded group members' do
2019-09-04 21:01:54 +05:30
let ( :indirect_user ) { create ( :user ) }
it 'enables two_factor_requirement for subgroup member' do
subgroup = create ( :group , :nested , parent : group )
subgroup . add_user ( indirect_user , GroupMember :: OWNER )
2017-08-17 22:00:37 +05:30
2019-09-04 21:01:54 +05:30
group . update! ( require_two_factor_authentication : true )
expect ( indirect_user . reload . require_two_factor_authentication_from_group ) . to be_truthy
end
it 'does not enable two_factor_requirement for ancestor group member' do
ancestor_group = create ( :group )
ancestor_group . add_user ( indirect_user , GroupMember :: OWNER )
group . update! ( parent : ancestor_group )
group . update! ( require_two_factor_authentication : true )
expect ( indirect_user . reload . require_two_factor_authentication_from_group ) . to be_falsey
end
end
context 'project members' do
it 'does not enable two_factor_requirement for child project member' do
project = create ( :project , group : group )
project . add_maintainer ( user )
group . update! ( require_two_factor_authentication : true )
expect ( user . reload . require_two_factor_authentication_from_group ) . to be_falsey
end
2019-10-12 21:52:04 +05:30
it 'does not enable two_factor_requirement for subgroup child project member' do
2019-09-04 21:01:54 +05:30
subgroup = create ( :group , :nested , parent : group )
project = create ( :project , group : subgroup )
project . add_maintainer ( user )
group . update! ( require_two_factor_authentication : true )
expect ( user . reload . require_two_factor_authentication_from_group ) . to be_falsey
end
end
2017-08-17 22:00:37 +05:30
end
2016-11-03 12:29:30 +05:30
end
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
describe '#path_changed_hook' do
let ( :system_hook_service ) { SystemHooksService . new }
context 'for a new group' do
let ( :group ) { build ( :group ) }
before do
expect ( group ) . to receive ( :system_hook_service ) . and_return ( system_hook_service )
end
it 'does not trigger system hook' do
expect ( system_hook_service ) . to receive ( :execute_hooks_for ) . with ( group , :create )
group . save!
end
end
context 'for an existing group' do
let ( :group ) { create ( :group , path : 'old-path' ) }
context 'when the path is changed' do
let ( :new_path ) { 'very-new-path' }
it 'triggers the rename system hook' do
expect ( group ) . to receive ( :system_hook_service ) . and_return ( system_hook_service )
expect ( system_hook_service ) . to receive ( :execute_hooks_for ) . with ( group , :rename )
2018-11-18 11:00:15 +05:30
group . update! ( path : new_path )
2018-03-17 18:26:18 +05:30
end
end
context 'when the path is not changed' do
it 'does not trigger system hook' do
expect ( group ) . not_to receive ( :system_hook_service )
2018-11-18 11:00:15 +05:30
group . update! ( name : 'new name' )
2018-03-17 18:26:18 +05:30
end
end
end
end
2018-12-13 13:39:08 +05:30
describe '#ci_variables_for' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , group : group ) }
2018-12-13 13:39:08 +05:30
let! ( :ci_variable ) do
2017-09-10 17:25:29 +05:30
create ( :ci_group_variable , value : 'secret' , group : group )
end
let! ( :protected_variable ) do
create ( :ci_group_variable , :protected , value : 'protected' , group : group )
end
2018-12-13 13:39:08 +05:30
subject { group . ci_variables_for ( 'ref' , project ) }
2017-09-10 17:25:29 +05:30
shared_examples 'ref is protected' do
it 'contains all the variables' do
2018-12-13 13:39:08 +05:30
is_expected . to contain_exactly ( ci_variable , protected_variable )
2017-09-10 17:25:29 +05:30
end
end
context 'when the ref is not protected' do
before do
stub_application_setting (
default_branch_protection : Gitlab :: Access :: PROTECTION_NONE )
end
2018-12-13 13:39:08 +05:30
it 'contains only the CI variables' do
is_expected . to contain_exactly ( ci_variable )
2017-09-10 17:25:29 +05:30
end
end
context 'when the ref is a protected branch' do
before do
2018-03-17 18:26:18 +05:30
allow ( project ) . to receive ( :protected_for? ) . with ( 'ref' ) . and_return ( true )
2017-09-10 17:25:29 +05:30
end
it_behaves_like 'ref is protected'
end
context 'when the ref is a protected tag' do
before do
2018-03-17 18:26:18 +05:30
allow ( project ) . to receive ( :protected_for? ) . with ( 'ref' ) . and_return ( true )
2017-09-10 17:25:29 +05:30
end
it_behaves_like 'ref is protected'
end
2019-10-12 21:52:04 +05:30
context 'when group has children' do
2017-09-10 17:25:29 +05:30
let ( :group_child ) { create ( :group , parent : group ) }
let ( :group_child_2 ) { create ( :group , parent : group_child ) }
let ( :group_child_3 ) { create ( :group , parent : group_child_2 ) }
let ( :variable_child ) { create ( :ci_group_variable , group : group_child ) }
let ( :variable_child_2 ) { create ( :ci_group_variable , group : group_child_2 ) }
let ( :variable_child_3 ) { create ( :ci_group_variable , group : group_child_3 ) }
2018-03-17 18:26:18 +05:30
before do
allow ( project ) . to receive ( :protected_for? ) . with ( 'ref' ) . and_return ( true )
end
2017-09-10 17:25:29 +05:30
it 'returns all variables belong to the group and parent groups' do
2018-12-13 13:39:08 +05:30
expected_array1 = [ protected_variable , ci_variable ]
2017-09-10 17:25:29 +05:30
expected_array2 = [ variable_child , variable_child_2 , variable_child_3 ]
2018-12-13 13:39:08 +05:30
got_array = group_child_3 . ci_variables_for ( 'ref' , project ) . to_a
2017-09-10 17:25:29 +05:30
expect ( got_array . shift ( 2 ) ) . to contain_exactly ( * expected_array1 )
expect ( got_array ) . to eq ( expected_array2 )
end
end
end
2018-03-17 18:26:18 +05:30
2019-10-12 21:52:04 +05:30
describe '#highest_group_member' do
2019-03-02 22:35:43 +05:30
let ( :nested_group ) { create ( :group , parent : group ) }
let ( :nested_group_2 ) { create ( :group , parent : nested_group ) }
let ( :user ) { create ( :user ) }
subject ( :highest_group_member ) { nested_group_2 . highest_group_member ( user ) }
context 'when the user is not a member of any group in the hierarchy' do
it 'returns nil' do
expect ( highest_group_member ) . to be_nil
end
end
context 'when the user is only a member of one group in the hierarchy' do
before do
nested_group . add_developer ( user )
end
it 'returns that group member' do
expect ( highest_group_member . access_level ) . to eq ( Gitlab :: Access :: DEVELOPER )
end
end
context 'when the user is a member of several groups in the hierarchy' do
before do
group . add_owner ( user )
nested_group . add_developer ( user )
nested_group_2 . add_maintainer ( user )
end
it 'returns the group member with the highest access level' do
expect ( highest_group_member . access_level ) . to eq ( Gitlab :: Access :: OWNER )
end
end
end
2018-03-17 18:26:18 +05:30
describe '#has_parent?' do
context 'when the group has a parent' do
2019-07-07 11:18:12 +05:30
it 'is truthy' do
2018-03-17 18:26:18 +05:30
group = create ( :group , :nested )
expect ( group . has_parent? ) . to be_truthy
end
end
context 'when the group has no parent' do
2019-07-07 11:18:12 +05:30
it 'is falsy' do
2018-03-17 18:26:18 +05:30
group = create ( :group , parent : nil )
expect ( group . has_parent? ) . to be_falsy
end
end
end
2018-11-08 19:23:39 +05:30
context 'with uploads' do
2019-02-15 15:39:39 +05:30
it_behaves_like 'model with uploads' , true do
2018-11-08 19:23:39 +05:30
let ( :model_object ) { create ( :group , :with_avatar ) }
let ( :upload_attribute ) { :avatar }
let ( :uploader_class ) { AttachmentUploader }
end
end
2019-02-15 15:39:39 +05:30
2019-07-07 11:18:12 +05:30
describe '#first_auto_devops_config' do
using RSpec :: Parameterized :: TableSyntax
let ( :group ) { create ( :group ) }
subject { group . first_auto_devops_config }
where ( :instance_value , :group_value , :config ) do
# Instance level enabled
true | nil | { status : true , scope : :instance }
true | true | { status : true , scope : :group }
true | false | { status : false , scope : :group }
# Instance level disabled
false | nil | { status : false , scope : :instance }
false | true | { status : true , scope : :group }
false | false | { status : false , scope : :group }
end
with_them do
before do
stub_application_setting ( auto_devops_enabled : instance_value )
group . update_attribute ( :auto_devops_enabled , group_value )
end
it { is_expected . to eq ( config ) }
end
2019-10-12 21:52:04 +05:30
context 'with parent groups' do
2019-07-07 11:18:12 +05:30
where ( :instance_value , :parent_value , :group_value , :config ) do
# Instance level enabled
true | nil | nil | { status : true , scope : :instance }
true | nil | true | { status : true , scope : :group }
true | nil | false | { status : false , scope : :group }
true | true | nil | { status : true , scope : :group }
true | true | true | { status : true , scope : :group }
true | true | false | { status : false , scope : :group }
true | false | nil | { status : false , scope : :group }
true | false | true | { status : true , scope : :group }
true | false | false | { status : false , scope : :group }
# Instance level disable
false | nil | nil | { status : false , scope : :instance }
false | nil | true | { status : true , scope : :group }
false | nil | false | { status : false , scope : :group }
false | true | nil | { status : true , scope : :group }
false | true | true | { status : true , scope : :group }
false | true | false | { status : false , scope : :group }
false | false | nil | { status : false , scope : :group }
false | false | true | { status : true , scope : :group }
false | false | false | { status : false , scope : :group }
end
with_them do
before do
stub_application_setting ( auto_devops_enabled : instance_value )
parent = create ( :group , auto_devops_enabled : parent_value )
group . update! (
auto_devops_enabled : group_value ,
parent : parent
)
end
it { is_expected . to eq ( config ) }
end
end
end
describe '#auto_devops_enabled?' do
subject { group . auto_devops_enabled? }
context 'when auto devops is explicitly enabled on group' do
let ( :group ) { create ( :group , :auto_devops_enabled ) }
it { is_expected . to be_truthy }
end
context 'when auto devops is explicitly disabled on group' do
let ( :group ) { create ( :group , :auto_devops_disabled ) }
it { is_expected . to be_falsy }
end
context 'when auto devops is implicitly enabled or disabled' do
before do
stub_application_setting ( auto_devops_enabled : false )
group . update! ( parent : parent_group )
end
context 'when auto devops is enabled on root group' do
let ( :root_group ) { create ( :group , :auto_devops_enabled ) }
let ( :subgroup ) { create ( :group , parent : root_group ) }
let ( :parent_group ) { create ( :group , parent : subgroup ) }
it { is_expected . to be_truthy }
end
context 'when auto devops is disabled on root group' do
let ( :root_group ) { create ( :group , :auto_devops_disabled ) }
let ( :subgroup ) { create ( :group , parent : root_group ) }
let ( :parent_group ) { create ( :group , parent : subgroup ) }
it { is_expected . to be_falsy }
end
context 'when auto devops is disabled on parent group and enabled on root group' do
let ( :root_group ) { create ( :group , :auto_devops_enabled ) }
let ( :parent_group ) { create ( :group , :auto_devops_disabled , parent : root_group ) }
it { is_expected . to be_falsy }
end
end
end
describe 'project_creation_level' do
it 'outputs the default one if it is nil' do
group = create ( :group , project_creation_level : nil )
expect ( group . project_creation_level ) . to eq ( Gitlab :: CurrentSettings . default_project_creation )
end
end
2019-10-12 21:52:04 +05:30
describe 'subgroup_creation_level' do
it 'defaults to maintainers' do
expect ( group . subgroup_creation_level )
. to eq ( Gitlab :: Access :: MAINTAINER_SUBGROUP_ACCESS )
end
end
2014-09-02 18:07:02 +05:30
end