2019-07-07 11:18:12 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
require 'spec_helper'
2020-07-28 23:09:34 +05:30
RSpec . describe Namespace do
2018-03-17 18:26:18 +05:30
include ProjectForksHelper
2018-12-05 23:21:45 +05:30
include GitHelpers
2018-03-17 18:26:18 +05:30
2014-09-02 18:07:02 +05:30
let! ( :namespace ) { create ( :namespace ) }
2018-03-17 18:26:18 +05:30
let ( :gitlab_shell ) { Gitlab :: Shell . new }
2018-10-15 14:42:47 +05:30
let ( :repository_storage ) { 'default' }
2014-09-02 18:07:02 +05:30
2017-08-17 22:00:37 +05:30
describe 'associations' do
it { is_expected . to have_many :projects }
it { is_expected . to have_many :project_statistics }
it { is_expected . to belong_to :parent }
it { is_expected . to have_many :children }
2019-09-30 21:07:59 +05:30
it { is_expected . to have_one :root_storage_statistics }
it { is_expected . to have_one :aggregation_schedule }
2020-07-28 23:09:34 +05:30
it { is_expected . to have_one :namespace_settings }
it { is_expected . to have_many :custom_emoji }
2017-08-17 22:00:37 +05:30
end
describe 'validations' do
it { is_expected . to validate_presence_of ( :name ) }
it { is_expected . to validate_length_of ( :name ) . is_at_most ( 255 ) }
it { is_expected . to validate_length_of ( :description ) . is_at_most ( 255 ) }
it { is_expected . to validate_presence_of ( :path ) }
it { is_expected . to validate_length_of ( :path ) . is_at_most ( 255 ) }
it { is_expected . to validate_presence_of ( :owner ) }
2020-03-13 15:44:24 +05:30
it { is_expected . to validate_numericality_of ( :max_artifacts_size ) . only_integer . is_greater_than ( 0 ) }
2017-08-17 22:00:37 +05:30
it 'does not allow too deep nesting' do
ancestors = ( 1 .. 21 ) . to_a
nested = build ( :namespace , parent : namespace )
allow ( nested ) . to receive ( :ancestors ) . and_return ( ancestors )
expect ( nested ) . not_to be_valid
expect ( nested . errors [ :parent_id ] . first ) . to eq ( 'has too deep level of nesting' )
end
describe 'reserved path validation' do
context 'nested group' do
let ( :group ) { build ( :group , :nested , path : 'tree' ) }
it { expect ( group ) . not_to be_valid }
it 'rejects nested paths' do
parent = create ( :group , :nested , path : 'environments' )
namespace = build ( :group , path : 'folders' , parent : parent )
expect ( namespace ) . not_to be_valid
end
end
context " is case insensitive " do
2017-09-10 17:25:29 +05:30
let ( :group ) { build ( :group , path : " Groups " ) }
2017-08-17 22:00:37 +05:30
it { expect ( group ) . not_to be_valid }
end
context 'top-level group' do
let ( :group ) { build ( :group , path : 'tree' ) }
it { expect ( group ) . to be_valid }
end
end
2020-07-28 23:09:34 +05:30
describe '1 char path length' do
it 'does not allow to create one' do
namespace = build ( :namespace , path : 'j' )
expect ( namespace ) . not_to be_valid
expect ( namespace . errors [ :path ] . first ) . to eq ( 'is too short (minimum is 2 characters)' )
end
it 'does not allow to update one' do
namespace = create ( :namespace )
namespace . update ( path : 'j' )
expect ( namespace ) . not_to be_valid
expect ( namespace . errors [ :path ] . first ) . to eq ( 'is too short (minimum is 2 characters)' )
end
it 'allows updating other attributes for existing record' do
namespace = build ( :namespace , path : 'j' )
namespace . save ( validate : false )
namespace . reload
expect ( namespace . path ) . to eq ( 'j' )
namespace . update ( name : 'something new' )
expect ( namespace ) . to be_valid
expect ( namespace . name ) . to eq ( 'something new' )
end
end
2014-09-02 18:07:02 +05:30
end
2019-07-31 22:56:46 +05:30
describe 'delegate' do
it { is_expected . to delegate_method ( :name ) . to ( :owner ) . with_prefix . with_arguments ( allow_nil : true ) }
it { is_expected . to delegate_method ( :avatar_url ) . to ( :owner ) . with_arguments ( allow_nil : true ) }
end
2014-09-02 18:07:02 +05:30
describe " Respond to " do
2015-04-26 12:48:37 +05:30
it { is_expected . to respond_to ( :human_name ) }
it { is_expected . to respond_to ( :to_param ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to respond_to ( :has_parent? ) }
2014-09-02 18:07:02 +05:30
end
2017-09-10 17:25:29 +05:30
describe 'inclusions' do
it { is_expected . to include_module ( Gitlab :: VisibilityLevel ) }
end
describe '#visibility_level_field' do
it { expect ( namespace . visibility_level_field ) . to eq ( :visibility_level ) }
end
2016-08-24 12:49:21 +05:30
describe '#to_param' do
2017-08-17 22:00:37 +05:30
it { expect ( namespace . to_param ) . to eq ( namespace . full_path ) }
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 ( namespace . human_name ) . to eq ( namespace . owner_name ) }
2014-09-02 18:07:02 +05:30
end
2018-12-05 23:21:45 +05:30
describe '#first_project_with_container_registry_tags' do
let ( :container_repository ) { create ( :container_repository ) }
let! ( :project ) { create ( :project , namespace : namespace , container_repositories : [ container_repository ] ) }
before do
stub_container_registry_config ( enabled : true )
end
it 'returns the project' do
stub_container_registry_tags ( repository : :any , tags : [ 'tag' ] )
expect ( namespace . first_project_with_container_registry_tags ) . to eq ( project )
end
it 'returns no project' do
stub_container_registry_tags ( repository : :any , tags : nil )
expect ( namespace . first_project_with_container_registry_tags ) . to be_nil
end
end
2016-06-02 11:05:42 +05:30
describe '.search' do
let ( :namespace ) { create ( :namespace ) }
it 'returns namespaces with a matching name' do
expect ( described_class . search ( namespace . name ) ) . to eq ( [ namespace ] )
end
it 'returns namespaces with a partially matching name' do
expect ( described_class . search ( namespace . name [ 0 .. 2 ] ) ) . to eq ( [ namespace ] )
end
it 'returns namespaces with a matching name regardless of the casing' do
expect ( described_class . search ( namespace . name . upcase ) ) . to eq ( [ namespace ] )
end
it 'returns namespaces with a matching path' do
expect ( described_class . search ( namespace . path ) ) . to eq ( [ namespace ] )
end
it 'returns namespaces with a partially matching path' do
expect ( described_class . search ( namespace . path [ 0 .. 2 ] ) ) . to eq ( [ namespace ] )
2014-09-02 18:07:02 +05:30
end
2016-06-02 11:05:42 +05:30
it 'returns namespaces with a matching path regardless of the casing' do
expect ( described_class . search ( namespace . path . upcase ) ) . to eq ( [ namespace ] )
end
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
describe '.with_statistics' do
2020-11-24 15:15:51 +05:30
let_it_be ( :namespace ) { create ( :namespace ) }
2017-08-17 22:00:37 +05:30
let ( :project1 ) do
2017-09-10 17:25:29 +05:30
create ( :project ,
2017-08-17 22:00:37 +05:30
namespace : namespace ,
statistics : build ( :project_statistics ,
2020-11-24 15:15:51 +05:30
namespace : namespace ,
2017-08-17 22:00:37 +05:30
repository_size : 101 ,
2019-09-04 21:01:54 +05:30
wiki_size : 505 ,
2017-08-17 22:00:37 +05:30
lfs_objects_size : 202 ,
2019-07-31 22:56:46 +05:30
build_artifacts_size : 303 ,
2020-07-28 23:09:34 +05:30
packages_size : 404 ,
snippets_size : 605 ) )
2017-08-17 22:00:37 +05:30
end
let ( :project2 ) do
2017-09-10 17:25:29 +05:30
create ( :project ,
2017-08-17 22:00:37 +05:30
namespace : namespace ,
statistics : build ( :project_statistics ,
2020-11-24 15:15:51 +05:30
namespace : namespace ,
2017-08-17 22:00:37 +05:30
repository_size : 10 ,
2019-09-04 21:01:54 +05:30
wiki_size : 50 ,
2017-08-17 22:00:37 +05:30
lfs_objects_size : 20 ,
2019-07-31 22:56:46 +05:30
build_artifacts_size : 30 ,
2020-07-28 23:09:34 +05:30
packages_size : 40 ,
snippets_size : 60 ) )
2017-08-17 22:00:37 +05:30
end
it " sums all project storage counters in the namespace " do
project1
project2
2017-09-10 17:25:29 +05:30
statistics = described_class . with_statistics . find ( namespace . id )
2017-08-17 22:00:37 +05:30
2020-07-28 23:09:34 +05:30
expect ( statistics . storage_size ) . to eq 2330
2017-08-17 22:00:37 +05:30
expect ( statistics . repository_size ) . to eq 111
2019-09-04 21:01:54 +05:30
expect ( statistics . wiki_size ) . to eq 555
2017-08-17 22:00:37 +05:30
expect ( statistics . lfs_objects_size ) . to eq 222
expect ( statistics . build_artifacts_size ) . to eq 333
2019-07-31 22:56:46 +05:30
expect ( statistics . packages_size ) . to eq 444
2020-07-28 23:09:34 +05:30
expect ( statistics . snippets_size ) . to eq 665
2017-08-17 22:00:37 +05:30
end
it " correctly handles namespaces without projects " do
2017-09-10 17:25:29 +05:30
statistics = described_class . with_statistics . find ( namespace . id )
2017-08-17 22:00:37 +05:30
expect ( statistics . storage_size ) . to eq 0
expect ( statistics . repository_size ) . to eq 0
2019-09-04 21:01:54 +05:30
expect ( statistics . wiki_size ) . to eq 0
2017-08-17 22:00:37 +05:30
expect ( statistics . lfs_objects_size ) . to eq 0
expect ( statistics . build_artifacts_size ) . to eq 0
2019-07-31 22:56:46 +05:30
expect ( statistics . packages_size ) . to eq 0
2020-07-28 23:09:34 +05:30
expect ( statistics . snippets_size ) . to eq 0
2017-08-17 22:00:37 +05:30
end
end
2019-12-21 20:55:43 +05:30
describe '.find_by_pages_host' do
it 'finds namespace by GitLab Pages host and is case-insensitive' do
2020-04-22 19:07:51 +05:30
namespace = create ( :namespace , name : 'topNAMEspace' , path : 'topNAMEspace' )
2019-12-21 20:55:43 +05:30
create ( :namespace , name : 'annother_namespace' )
host = " TopNamespace. #{ Settings . pages . host . upcase } "
expect ( described_class . find_by_pages_host ( host ) ) . to eq ( namespace )
end
2020-01-01 13:55:28 +05:30
2020-04-08 14:13:33 +05:30
context 'when there is non-top-level group with searched name' do
before do
create ( :group , :nested , path : 'pages' )
end
it 'ignores this group' do
host = " pages. #{ Settings . pages . host . upcase } "
expect ( described_class . find_by_pages_host ( host ) ) . to be_nil
end
it 'finds right top level group' do
group = create ( :group , path : 'pages' )
host = " pages. #{ Settings . pages . host . upcase } "
expect ( described_class . find_by_pages_host ( host ) ) . to eq ( group )
end
end
2020-01-01 13:55:28 +05:30
it " returns no result if the provided host is not subdomain of the Pages host " do
create ( :namespace , name : 'namespace.io' )
host = " namespace.io "
expect ( described_class . find_by_pages_host ( host ) ) . to eq ( nil )
end
2019-12-21 20:55:43 +05:30
end
2019-10-12 21:52:04 +05:30
describe '#ancestors_upto' do
2018-03-17 18:26:18 +05:30
let ( :parent ) { create ( :group ) }
let ( :child ) { create ( :group , parent : parent ) }
let ( :child2 ) { create ( :group , parent : child ) }
2014-09-02 18:07:02 +05:30
2018-03-17 18:26:18 +05:30
it 'returns all ancestors when no namespace is given' do
expect ( child2 . ancestors_upto ) . to contain_exactly ( child , parent )
2014-09-02 18:07:02 +05:30
end
2018-03-17 18:26:18 +05:30
it 'includes ancestors upto but excluding the given ancestor' do
expect ( child2 . ancestors_upto ( parent ) ) . to contain_exactly ( child )
2014-09-02 18:07:02 +05:30
end
2018-03-17 18:26:18 +05:30
end
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
describe '#move_dir' , :request_store do
shared_examples " namespace restrictions " do
context " when any project has container images " do
let ( :container_repository ) { create ( :container_repository ) }
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
before do
stub_container_registry_config ( enabled : true )
stub_container_registry_tags ( repository : :any , tags : [ 'tag' ] )
2016-06-02 11:05:42 +05:30
2018-03-27 19:54:05 +05:30
create ( :project , namespace : namespace , container_repositories : [ container_repository ] )
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
allow ( namespace ) . to receive ( :path_was ) . and_return ( namespace . path )
allow ( namespace ) . to receive ( :path ) . and_return ( 'new_path' )
end
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
it 'raises an error about not movable project' do
2018-12-05 23:21:45 +05:30
expect { namespace . move_dir } . to raise_error ( Gitlab :: UpdatePathError ,
/ Namespace .* cannot be moved / )
2018-03-17 18:26:18 +05:30
end
2017-08-17 22:00:37 +05:30
end
end
2018-03-17 18:26:18 +05:30
context 'legacy storage' do
let ( :namespace ) { create ( :namespace ) }
2018-03-27 19:54:05 +05:30
let! ( :project ) { create ( :project_empty_repo , :legacy_storage , namespace : namespace ) }
2018-03-17 18:26:18 +05:30
it_behaves_like 'namespace restrictions'
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
it " raises error when directory exists " do
expect { namespace . move_dir } . to raise_error ( " namespace directory cannot be moved " )
2017-08-17 22:00:37 +05:30
end
2018-03-17 18:26:18 +05:30
it " moves dir if path changed " do
2018-11-18 11:00:15 +05:30
namespace . update ( path : namespace . full_path + '_new' )
2017-08-17 22:00:37 +05:30
2019-12-21 20:55:43 +05:30
expect ( gitlab_shell . repository_exists? ( project . repository_storage , " #{ namespace . path } / #{ project . path } .git " ) ) . to be_truthy
2018-03-17 18:26:18 +05:30
end
2017-08-17 22:00:37 +05:30
2018-11-18 11:00:15 +05:30
context 'when #write_projects_repository_config raises an error' do
context 'in test environment' do
it 'raises an exception' do
expect ( namespace ) . to receive ( :write_projects_repository_config ) . and_raise ( 'foo' )
expect do
namespace . update ( path : namespace . full_path + '_new' )
end . to raise_error ( 'foo' )
end
end
context 'in production environment' do
it 'does not cancel later callbacks' do
expect ( namespace ) . to receive ( :write_projects_repository_config ) . and_raise ( 'foo' )
expect ( namespace ) . to receive ( :move_dir ) . and_wrap_original do | m , * args |
move_dir_result = m . call ( * args )
expect ( move_dir_result ) . to be_truthy # Must be truthy, or else later callbacks would be canceled
move_dir_result
end
2020-01-01 13:55:28 +05:30
expect ( Gitlab :: ErrorTracking ) . to receive ( :should_raise_for_dev? ) . and_return ( false ) # like prod
2018-11-18 11:00:15 +05:30
namespace . update ( path : namespace . full_path + '_new' )
end
end
end
2019-12-26 22:10:19 +05:30
shared_examples 'move_dir without repository storage feature' do | storage_version |
let ( :namespace ) { create ( :namespace ) }
let ( :gitlab_shell ) { namespace . gitlab_shell }
let! ( :project ) { create ( :project_empty_repo , namespace : namespace , storage_version : storage_version ) }
it 'calls namespace service' do
expect ( gitlab_shell ) . to receive ( :add_namespace ) . and_return ( true )
expect ( gitlab_shell ) . to receive ( :mv_namespace ) . and_return ( true )
namespace . move_dir
end
end
shared_examples 'move_dir with repository storage feature' do | storage_version |
let ( :namespace ) { create ( :namespace ) }
let ( :gitlab_shell ) { namespace . gitlab_shell }
let! ( :project ) { create ( :project_empty_repo , namespace : namespace , storage_version : storage_version ) }
it 'does not call namespace service' do
expect ( gitlab_shell ) . not_to receive ( :add_namespace )
expect ( gitlab_shell ) . not_to receive ( :mv_namespace )
namespace . move_dir
end
end
context 'project is without repository storage feature' do
[ nil , 0 ] . each do | storage_version |
it_behaves_like 'move_dir without repository storage feature' , storage_version
end
end
context 'project has repository storage feature' do
[ 1 , 2 ] . each do | storage_version |
it_behaves_like 'move_dir with repository storage feature' , storage_version
end
end
2019-10-12 21:52:04 +05:30
context 'with subgroups' do
2018-03-17 18:26:18 +05:30
let ( :parent ) { create ( :group , name : 'parent' , path : 'parent' ) }
let ( :new_parent ) { create ( :group , name : 'new_parent' , path : 'new_parent' ) }
let ( :child ) { create ( :group , name : 'child' , path : 'child' , parent : parent ) }
2018-03-27 19:54:05 +05:30
let! ( :project ) { create ( :project_empty_repo , :legacy_storage , path : 'the-project' , namespace : child , skip_disk_validation : true ) }
2018-03-17 18:26:18 +05:30
let ( :uploads_dir ) { FileUploader . root }
let ( :pages_dir ) { File . join ( TestEnv . pages_path ) }
2020-11-24 15:15:51 +05:30
def expect_project_directories_at ( namespace_path , with_pages : true )
2018-03-17 18:26:18 +05:30
expected_repository_path = File . join ( TestEnv . repos_path , namespace_path , 'the-project.git' )
expected_upload_path = File . join ( uploads_dir , namespace_path , 'the-project' )
expected_pages_path = File . join ( pages_dir , namespace_path , 'the-project' )
expect ( File . directory? ( expected_repository_path ) ) . to be_truthy
expect ( File . directory? ( expected_upload_path ) ) . to be_truthy
2020-11-24 15:15:51 +05:30
expect ( File . directory? ( expected_pages_path ) ) . to be ( with_pages )
2017-08-17 22:00:37 +05:30
end
2018-03-17 18:26:18 +05:30
before do
FileUtils . mkdir_p ( File . join ( TestEnv . repos_path , " #{ project . full_path } .git " ) )
FileUtils . mkdir_p ( File . join ( uploads_dir , project . full_path ) )
FileUtils . mkdir_p ( File . join ( pages_dir , project . full_path ) )
end
2020-11-24 15:15:51 +05:30
after do
FileUtils . remove_entry ( File . join ( TestEnv . repos_path , parent . full_path ) , true )
FileUtils . remove_entry ( File . join ( TestEnv . repos_path , new_parent . full_path ) , true )
FileUtils . remove_entry ( File . join ( TestEnv . repos_path , child . full_path ) , true )
FileUtils . remove_entry ( File . join ( uploads_dir , project . full_path ) , true )
FileUtils . remove_entry ( pages_dir , true )
end
2018-03-17 18:26:18 +05:30
context 'renaming child' do
2020-11-24 15:15:51 +05:30
context 'when no projects have pages deployed' do
it 'moves the repository and uploads' , :sidekiq_inline do
project . pages_metadatum . update! ( deployed : false )
child . update! ( path : 'renamed' )
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
expect_project_directories_at ( 'parent/renamed' , with_pages : false )
end
end
context 'when the project has pages deployed' do
before do
project . pages_metadatum . update! ( deployed : true )
end
it 'correctly moves the repository, uploads and pages' , :sidekiq_inline do
child . update! ( path : 'renamed' )
expect_project_directories_at ( 'parent/renamed' )
end
it 'performs the move async of pages async' do
expect ( PagesTransferWorker ) . to receive ( :perform_async ) . with ( 'rename_namespace' , [ 'parent/child' , 'parent/renamed' ] )
child . update! ( path : 'renamed' )
end
2018-03-17 18:26:18 +05:30
end
end
context 'renaming parent' do
2020-11-24 15:15:51 +05:30
context 'when no projects have pages deployed' do
it 'moves the repository and uploads' , :sidekiq_inline do
project . pages_metadatum . update! ( deployed : false )
parent . update! ( path : 'renamed' )
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
expect_project_directories_at ( 'renamed/child' , with_pages : false )
end
end
context 'when the project has pages deployed' do
before do
project . pages_metadatum . update! ( deployed : true )
end
it 'correctly moves the repository, uploads and pages' , :sidekiq_inline do
parent . update! ( path : 'renamed' )
expect_project_directories_at ( 'renamed/child' )
end
it 'performs the move async of pages async' do
expect ( PagesTransferWorker ) . to receive ( :perform_async ) . with ( 'rename_namespace' , %w( parent renamed ) )
parent . update! ( path : 'renamed' )
end
2018-03-17 18:26:18 +05:30
end
end
context 'moving from one parent to another' do
2020-11-24 15:15:51 +05:30
context 'when no projects have pages deployed' do
it 'moves the repository and uploads' , :sidekiq_inline do
project . pages_metadatum . update! ( deployed : false )
child . update! ( parent : new_parent )
expect_project_directories_at ( 'new_parent/child' , with_pages : false )
end
end
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
context 'when the project has pages deployed' do
before do
project . pages_metadatum . update! ( deployed : true )
end
it 'correctly moves the repository, uploads and pages' , :sidekiq_inline do
child . update! ( parent : new_parent )
expect_project_directories_at ( 'new_parent/child' )
end
it 'performs the move async of pages async' do
expect ( PagesTransferWorker ) . to receive ( :perform_async ) . with ( 'move_namespace' , %w( child parent new_parent ) )
child . update! ( parent : new_parent )
end
2018-03-17 18:26:18 +05:30
end
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
context 'moving from having a parent to root' do
2020-11-24 15:15:51 +05:30
context 'when no projects have pages deployed' do
it 'moves the repository and uploads' , :sidekiq_inline do
project . pages_metadatum . update! ( deployed : false )
child . update! ( parent : nil )
expect_project_directories_at ( 'child' , with_pages : false )
end
end
context 'when the project has pages deployed' do
before do
project . pages_metadatum . update! ( deployed : true )
end
it 'correctly moves the repository, uploads and pages' , :sidekiq_inline do
child . update! ( parent : nil )
2017-08-17 22:00:37 +05:30
2020-11-24 15:15:51 +05:30
expect_project_directories_at ( 'child' )
end
it 'performs the move async of pages async' do
expect ( PagesTransferWorker ) . to receive ( :perform_async ) . with ( 'move_namespace' , [ 'child' , 'parent' , nil ] )
child . update! ( parent : nil )
end
2018-03-17 18:26:18 +05:30
end
2017-08-17 22:00:37 +05:30
end
2018-03-17 18:26:18 +05:30
context 'moving from root to having a parent' do
2020-11-24 15:15:51 +05:30
context 'when no projects have pages deployed' do
it 'moves the repository and uploads' , :sidekiq_inline do
project . pages_metadatum . update! ( deployed : false )
parent . update! ( parent : new_parent )
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
expect_project_directories_at ( 'new_parent/parent/child' , with_pages : false )
end
end
context 'when the project has pages deployed' do
before do
project . pages_metadatum . update! ( deployed : true )
end
it 'correctly moves the repository, uploads and pages' , :sidekiq_inline do
parent . update! ( parent : new_parent )
expect_project_directories_at ( 'new_parent/parent/child' )
end
it 'performs the move async of pages async' do
expect ( PagesTransferWorker ) . to receive ( :perform_async ) . with ( 'move_namespace' , [ 'parent' , nil , 'new_parent' ] )
parent . update! ( parent : new_parent )
end
2018-03-17 18:26:18 +05:30
end
end
end
end
context 'hashed storage' do
let ( :namespace ) { create ( :namespace ) }
2018-03-27 19:54:05 +05:30
let! ( :project ) { create ( :project_empty_repo , namespace : namespace ) }
2018-03-17 18:26:18 +05:30
it_behaves_like 'namespace restrictions'
it " repository directory remains unchanged if path changed " do
before_disk_path = project . disk_path
2018-11-18 11:00:15 +05:30
namespace . update ( path : namespace . full_path + '_new' )
2018-03-17 18:26:18 +05:30
expect ( before_disk_path ) . to eq ( project . disk_path )
2019-12-21 20:55:43 +05:30
expect ( gitlab_shell . repository_exists? ( project . repository_storage , " #{ project . disk_path } .git " ) ) . to be_truthy
2017-08-17 22:00:37 +05:30
end
2016-06-02 11:05:42 +05:30
end
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
context 'for each project inside the namespace' do
let! ( :parent ) { create ( :group , name : 'mygroup' , path : 'mygroup' ) }
let! ( :subgroup ) { create ( :group , name : 'mysubgroup' , path : 'mysubgroup' , parent : parent ) }
let! ( :project_in_parent_group ) { create ( :project , :legacy_storage , :repository , namespace : parent , name : 'foo1' ) }
let! ( :hashed_project_in_subgroup ) { create ( :project , :repository , namespace : subgroup , name : 'foo2' ) }
let! ( :legacy_project_in_subgroup ) { create ( :project , :legacy_storage , :repository , namespace : subgroup , name : 'foo3' ) }
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
it 'updates project full path in .git/config' do
parent . update ( path : 'mygroup_new' )
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
expect ( project_rugged ( project_in_parent_group ) . config [ 'gitlab.fullpath' ] ) . to eq " mygroup_new/ #{ project_in_parent_group . path } "
expect ( project_rugged ( hashed_project_in_subgroup ) . config [ 'gitlab.fullpath' ] ) . to eq " mygroup_new/mysubgroup/ #{ hashed_project_in_subgroup . path } "
expect ( project_rugged ( legacy_project_in_subgroup ) . config [ 'gitlab.fullpath' ] ) . to eq " mygroup_new/mysubgroup/ #{ legacy_project_in_subgroup . path } "
2018-11-18 11:00:15 +05:30
end
2019-02-15 15:39:39 +05:30
it 'updates the project storage location' do
repository_project_in_parent_group = create ( :project_repository , project : project_in_parent_group )
repository_hashed_project_in_subgroup = create ( :project_repository , project : hashed_project_in_subgroup )
repository_legacy_project_in_subgroup = create ( :project_repository , project : legacy_project_in_subgroup )
parent . update ( path : 'mygroup_moved' )
expect ( repository_project_in_parent_group . reload . disk_path ) . to eq " mygroup_moved/ #{ project_in_parent_group . path } "
expect ( repository_hashed_project_in_subgroup . reload . disk_path ) . to eq hashed_project_in_subgroup . disk_path
expect ( repository_legacy_project_in_subgroup . reload . disk_path ) . to eq " mygroup_moved/mysubgroup/ #{ legacy_project_in_subgroup . path } "
end
def project_rugged ( project )
# Routes are loaded when creating the projects, so we need to manually
# reload them for the below code to be aware of the above UPDATE.
project . route . reload
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
rugged_repo ( project . repository )
end
2018-03-17 18:26:18 +05:30
end
2014-09-02 18:07:02 +05:30
end
2017-09-10 17:25:29 +05:30
describe '#rm_dir' , 'callback' do
2018-11-08 19:23:39 +05:30
let ( :repository_storage_path ) do
Gitlab :: GitalyClient :: StorageSettings . allow_disk_access do
Gitlab . config . repositories . storages . default . legacy_disk_path
end
end
2020-10-24 23:57:45 +05:30
2017-08-17 22:00:37 +05:30
let ( :path_in_dir ) { File . join ( repository_storage_path , namespace . full_path ) }
let ( :deleted_path ) { namespace . full_path . gsub ( namespace . path , " #{ namespace . full_path } + #{ namespace . id } +deleted " ) }
let ( :deleted_path_in_dir ) { File . join ( repository_storage_path , deleted_path ) }
2018-03-27 19:54:05 +05:30
context 'legacy storage' do
let! ( :project ) { create ( :project_empty_repo , :legacy_storage , namespace : namespace ) }
2017-08-17 22:00:37 +05:30
it 'renames its dirs when deleted' do
allow ( GitlabShellWorker ) . to receive ( :perform_in )
2018-03-27 19:54:05 +05:30
namespace . destroy
2017-08-17 22:00:37 +05:30
expect ( File . exist? ( deleted_path_in_dir ) ) . to be ( true )
end
it 'schedules the namespace for deletion' do
2018-10-15 14:42:47 +05:30
expect ( GitlabShellWorker ) . to receive ( :perform_in ) . with ( 5 . minutes , :rm_namespace , repository_storage , deleted_path )
2017-08-17 22:00:37 +05:30
2018-03-27 19:54:05 +05:30
namespace . destroy
end
context 'in sub-groups' do
let ( :parent ) { create ( :group , path : 'parent' ) }
let ( :child ) { create ( :group , parent : parent , path : 'child' ) }
let! ( :project ) { create ( :project_empty_repo , :legacy_storage , namespace : child ) }
let ( :path_in_dir ) { File . join ( repository_storage_path , 'parent' , 'child' ) }
let ( :deleted_path ) { File . join ( 'parent' , " child+ #{ child . id } +deleted " ) }
let ( :deleted_path_in_dir ) { File . join ( repository_storage_path , deleted_path ) }
it 'renames its dirs when deleted' do
allow ( GitlabShellWorker ) . to receive ( :perform_in )
child . destroy
expect ( File . exist? ( deleted_path_in_dir ) ) . to be ( true )
end
it 'schedules the namespace for deletion' do
2018-10-15 14:42:47 +05:30
expect ( GitlabShellWorker ) . to receive ( :perform_in ) . with ( 5 . minutes , :rm_namespace , repository_storage , deleted_path )
2018-03-27 19:54:05 +05:30
child . destroy
end
end
2017-08-17 22:00:37 +05:30
end
2018-03-27 19:54:05 +05:30
context 'hashed storage' do
let! ( :project ) { create ( :project_empty_repo , namespace : namespace ) }
it 'has no repositories base directories to remove' do
allow ( GitlabShellWorker ) . to receive ( :perform_in )
expect ( File . exist? ( path_in_dir ) ) . to be ( false )
namespace . destroy
2017-08-17 22:00:37 +05:30
2018-03-27 19:54:05 +05:30
expect ( File . exist? ( deleted_path_in_dir ) ) . to be ( false )
end
2015-04-26 12:48:37 +05:30
end
end
2016-08-24 12:49:21 +05:30
describe '.find_by_path_or_name' do
2015-04-26 12:48:37 +05:30
before do
@namespace = create ( :namespace , name : 'WoW' , path : 'woW' )
end
2017-09-10 17:25:29 +05:30
it { expect ( described_class . find_by_path_or_name ( 'wow' ) ) . to eq ( @namespace ) }
it { expect ( described_class . find_by_path_or_name ( 'WOW' ) ) . to eq ( @namespace ) }
it { expect ( described_class . find_by_path_or_name ( 'unknown' ) ) . to eq ( nil ) }
2015-04-26 12:48:37 +05:30
end
describe " .clean_path " do
let! ( :user ) { create ( :user , username : " johngitlab-etc " ) }
let! ( :namespace ) { create ( :namespace , path : " JohnGitLab-etc1 " ) }
it " cleans the path and makes sure it's available " do
2017-09-10 17:25:29 +05:30
expect ( described_class . clean_path ( " -john+gitlab-ETC%.git@gmail.com " ) ) . to eq ( " johngitlab-ETC2 " )
expect ( described_class . clean_path ( " --%+--valid_*&%name=.git.%.atom.atom.@email.com " ) ) . to eq ( " valid_name " )
2014-09-02 18:07:02 +05:30
end
end
2017-08-17 22:00:37 +05:30
2020-11-24 15:15:51 +05:30
describe " .clean_name " do
context " when the name complies with the group name regex " do
it " returns the name as is " do
valid_name = " Hello - World _ (Hi.) "
expect ( described_class . clean_name ( valid_name ) ) . to eq ( valid_name )
end
end
context " when the name does not comply with the group name regex " do
it " sanitizes the name by replacing all invalid char sequences with a space " do
expect ( described_class . clean_name ( " Green'! Test~~~ " ) ) . to eq ( " Green Test " )
end
end
end
2020-04-08 14:13:33 +05:30
describe " # default_branch_protection " do
let ( :namespace ) { create ( :namespace ) }
let ( :default_branch_protection ) { nil }
let ( :group ) { create ( :group , default_branch_protection : default_branch_protection ) }
before do
stub_application_setting ( default_branch_protection : Gitlab :: Access :: PROTECTION_DEV_CAN_MERGE )
end
context 'for a namespace' do
# Unlike a group, the settings of a namespace cannot be altered
# via the UI or the API.
it 'returns the instance level setting' do
expect ( namespace . default_branch_protection ) . to eq ( Gitlab :: Access :: PROTECTION_DEV_CAN_MERGE )
end
end
context 'for a group' do
context 'that has not altered the default value' do
it 'returns the instance level setting' do
expect ( group . default_branch_protection ) . to eq ( Gitlab :: Access :: PROTECTION_DEV_CAN_MERGE )
end
end
context 'that has altered the default value' do
let ( :default_branch_protection ) { Gitlab :: Access :: PROTECTION_FULL }
it 'returns the group level setting' do
expect ( group . default_branch_protection ) . to eq ( default_branch_protection )
end
end
end
end
2019-10-12 21:52:04 +05:30
describe '#self_and_hierarchy' do
2018-10-15 14:42:47 +05:30
let! ( :group ) { create ( :group , path : 'git_lab' ) }
let! ( :nested_group ) { create ( :group , parent : group ) }
let! ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
let! ( :very_deep_nested_group ) { create ( :group , parent : deep_nested_group ) }
let! ( :another_group ) { create ( :group , path : 'gitllab' ) }
let! ( :another_group_nested ) { create ( :group , path : 'foo' , parent : another_group ) }
it 'returns the correct tree' do
expect ( group . self_and_hierarchy ) . to contain_exactly ( group , nested_group , deep_nested_group , very_deep_nested_group )
expect ( nested_group . self_and_hierarchy ) . to contain_exactly ( group , nested_group , deep_nested_group , very_deep_nested_group )
expect ( very_deep_nested_group . self_and_hierarchy ) . to contain_exactly ( group , nested_group , deep_nested_group , very_deep_nested_group )
end
end
2019-10-12 21:52:04 +05:30
describe '#ancestors' do
2017-08-17 22:00:37 +05:30
let ( :group ) { create ( :group ) }
let ( :nested_group ) { create ( :group , parent : group ) }
let ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
let ( :very_deep_nested_group ) { create ( :group , parent : deep_nested_group ) }
it 'returns the correct ancestors' do
2017-09-10 17:25:29 +05:30
expect ( very_deep_nested_group . ancestors ) . to include ( group , nested_group , deep_nested_group )
expect ( deep_nested_group . ancestors ) . to include ( group , nested_group )
expect ( nested_group . ancestors ) . to include ( group )
2017-08-17 22:00:37 +05:30
expect ( group . ancestors ) . to eq ( [ ] )
end
end
2019-10-12 21:52:04 +05:30
describe '#self_and_ancestors' do
2017-09-10 17:25:29 +05:30
let ( :group ) { create ( :group ) }
let ( :nested_group ) { create ( :group , parent : group ) }
let ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
let ( :very_deep_nested_group ) { create ( :group , parent : deep_nested_group ) }
it 'returns the correct ancestors' do
expect ( very_deep_nested_group . self_and_ancestors ) . to contain_exactly ( group , nested_group , deep_nested_group , very_deep_nested_group )
expect ( deep_nested_group . self_and_ancestors ) . to contain_exactly ( group , nested_group , deep_nested_group )
expect ( nested_group . self_and_ancestors ) . to contain_exactly ( group , nested_group )
expect ( group . self_and_ancestors ) . to contain_exactly ( group )
end
end
2019-10-12 21:52:04 +05:30
describe '#descendants' do
2017-08-17 22:00:37 +05:30
let! ( :group ) { create ( :group , path : 'git_lab' ) }
let! ( :nested_group ) { create ( :group , parent : group ) }
let! ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
let! ( :very_deep_nested_group ) { create ( :group , parent : deep_nested_group ) }
let! ( :another_group ) { create ( :group , path : 'gitllab' ) }
let! ( :another_group_nested ) { create ( :group , path : 'foo' , parent : another_group ) }
it 'returns the correct descendants' do
expect ( very_deep_nested_group . descendants . to_a ) . to eq ( [ ] )
2017-09-10 17:25:29 +05:30
expect ( deep_nested_group . descendants . to_a ) . to include ( very_deep_nested_group )
expect ( nested_group . descendants . to_a ) . to include ( deep_nested_group , very_deep_nested_group )
expect ( group . descendants . to_a ) . to include ( nested_group , deep_nested_group , very_deep_nested_group )
end
end
2019-10-12 21:52:04 +05:30
describe '#self_and_descendants' do
2017-09-10 17:25:29 +05:30
let! ( :group ) { create ( :group , path : 'git_lab' ) }
let! ( :nested_group ) { create ( :group , parent : group ) }
let! ( :deep_nested_group ) { create ( :group , parent : nested_group ) }
let! ( :very_deep_nested_group ) { create ( :group , parent : deep_nested_group ) }
let! ( :another_group ) { create ( :group , path : 'gitllab' ) }
let! ( :another_group_nested ) { create ( :group , path : 'foo' , parent : another_group ) }
it 'returns the correct descendants' do
expect ( very_deep_nested_group . self_and_descendants ) . to contain_exactly ( very_deep_nested_group )
expect ( deep_nested_group . self_and_descendants ) . to contain_exactly ( deep_nested_group , very_deep_nested_group )
expect ( nested_group . self_and_descendants ) . to contain_exactly ( nested_group , deep_nested_group , very_deep_nested_group )
expect ( group . self_and_descendants ) . to contain_exactly ( group , nested_group , deep_nested_group , very_deep_nested_group )
end
end
2019-10-12 21:52:04 +05:30
describe '#users_with_descendants' do
2017-09-10 17:25:29 +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 )
2017-09-10 17:25:29 +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
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
2017-09-10 17:25:29 +05:30
expect ( namespace . user_ids_for_project_authorizations )
. to eq ( [ namespace . owner_id ] )
2017-08-17 22:00:37 +05:30
end
end
describe '#all_projects' do
2021-01-03 14:25:43 +05:30
shared_examples 'all projects for a namespace' do
let ( :namespace ) { create ( :namespace ) }
let ( :child ) { create ( :group , parent : namespace ) }
let! ( :project1 ) { create ( :project_empty_repo , namespace : namespace ) }
let! ( :project2 ) { create ( :project_empty_repo , namespace : child ) }
it { expect ( namespace . all_projects . to_a ) . to match_array ( [ project2 , project1 ] ) }
it { expect ( child . all_projects . to_a ) . to match_array ( [ project2 ] ) }
end
shared_examples 'all project examples' do
include_examples 'all projects for a namespace'
context 'when namespace is a group' do
let_it_be ( :namespace ) { create ( :group ) }
include_examples 'all projects for a namespace'
end
2017-08-17 22:00:37 +05:30
2021-01-03 14:25:43 +05:30
context 'when namespace is a user namespace' do
let_it_be ( :user ) { create ( :user ) }
let_it_be ( :user_namespace ) { create ( :namespace , owner : user ) }
let_it_be ( :project ) { create ( :project , namespace : user_namespace ) }
it { expect ( user_namespace . all_projects . to_a ) . to match_array ( [ project ] ) }
end
end
context 'with recursive approach' do
before do
stub_feature_flags ( recursive_approach_for_all_projects : true )
end
include_examples 'all project examples'
end
context 'with route path wildcard approach' do
before do
stub_feature_flags ( recursive_approach_for_all_projects : false )
end
include_examples 'all project examples'
end
2018-03-17 18:26:18 +05:30
end
2018-12-13 13:39:08 +05:30
describe '#all_pipelines' do
let ( :group ) { create ( :group ) }
let ( :child ) { create ( :group , parent : group ) }
let! ( :project1 ) { create ( :project_empty_repo , namespace : group ) }
let! ( :project2 ) { create ( :project_empty_repo , namespace : child ) }
let! ( :pipeline1 ) { create ( :ci_empty_pipeline , project : project1 ) }
let! ( :pipeline2 ) { create ( :ci_empty_pipeline , project : project2 ) }
it { expect ( group . all_pipelines . to_a ) . to match_array ( [ pipeline1 , pipeline2 ] ) }
end
2019-10-12 21:52:04 +05:30
describe '#share_with_group_lock with subgroups' do
2018-03-17 18:26:18 +05:30
context 'when creating a subgroup' do
let ( :subgroup ) { create ( :group , parent : root_group ) }
context 'under a parent with "Share with group lock" enabled' do
let ( :root_group ) { create ( :group , share_with_group_lock : true ) }
it 'enables "Share with group lock" on the subgroup' do
expect ( subgroup . share_with_group_lock ) . to be_truthy
end
end
context 'under a parent with "Share with group lock" disabled' do
let ( :root_group ) { create ( :group ) }
it 'does not enable "Share with group lock" on the subgroup' do
expect ( subgroup . share_with_group_lock ) . to be_falsey
end
end
end
context 'when enabling the parent group "Share with group lock"' do
let ( :root_group ) { create ( :group ) }
let! ( :subgroup ) { create ( :group , parent : root_group ) }
it 'the subgroup "Share with group lock" becomes enabled' do
root_group . update! ( share_with_group_lock : true )
expect ( subgroup . reload . share_with_group_lock ) . to be_truthy
end
end
context 'when disabling the parent group "Share with group lock" (which was already enabled)' do
let ( :root_group ) { create ( :group , share_with_group_lock : true ) }
context 'and the subgroup "Share with group lock" is enabled' do
let ( :subgroup ) { create ( :group , parent : root_group , share_with_group_lock : true ) }
it 'the subgroup "Share with group lock" does not change' do
root_group . update! ( share_with_group_lock : false )
expect ( subgroup . reload . share_with_group_lock ) . to be_truthy
end
end
context 'but the subgroup "Share with group lock" is disabled' do
let ( :subgroup ) { create ( :group , parent : root_group ) }
it 'the subgroup "Share with group lock" does not change' do
root_group . update! ( share_with_group_lock : false )
expect ( subgroup . reload . share_with_group_lock? ) . to be_falsey
end
end
end
context 'when a group is transferred into a root group' do
context 'when the root group "Share with group lock" is enabled' do
let ( :root_group ) { create ( :group , share_with_group_lock : true ) }
context 'when the subgroup "Share with group lock" is enabled' do
let ( :subgroup ) { create ( :group , share_with_group_lock : true ) }
it 'the subgroup "Share with group lock" does not change' do
subgroup . parent = root_group
subgroup . save!
expect ( subgroup . share_with_group_lock ) . to be_truthy
end
end
context 'when the subgroup "Share with group lock" is disabled' do
let ( :subgroup ) { create ( :group ) }
it 'the subgroup "Share with group lock" becomes enabled' do
subgroup . parent = root_group
subgroup . save!
expect ( subgroup . share_with_group_lock ) . to be_truthy
end
end
end
context 'when the root group "Share with group lock" is disabled' do
let ( :root_group ) { create ( :group ) }
context 'when the subgroup "Share with group lock" is enabled' do
let ( :subgroup ) { create ( :group , share_with_group_lock : true ) }
it 'the subgroup "Share with group lock" does not change' do
subgroup . parent = root_group
subgroup . save!
expect ( subgroup . share_with_group_lock ) . to be_truthy
end
end
context 'when the subgroup "Share with group lock" is disabled' do
let ( :subgroup ) { create ( :group ) }
it 'the subgroup "Share with group lock" does not change' do
subgroup . parent = root_group
subgroup . save!
expect ( subgroup . share_with_group_lock ) . to be_falsey
end
end
end
end
end
describe '#find_fork_of?' do
let ( :project ) { create ( :project , :public ) }
let! ( :forked_project ) { fork_project ( project , namespace . owner , namespace : namespace ) }
before do
# Reset the fork network relation
project . reload
end
it 'knows if there is a direct fork in the namespace' do
expect ( namespace . find_fork_of ( project ) ) . to eq ( forked_project )
end
it 'knows when there is as fork-of-fork in the namespace' do
other_namespace = create ( :namespace )
other_fork = fork_project ( forked_project , other_namespace . owner , namespace : other_namespace )
expect ( other_namespace . find_fork_of ( project ) ) . to eq ( other_fork )
end
context 'with request store enabled' , :request_store do
it 'only queries once' do
expect ( project . fork_network ) . to receive ( :find_forks_in ) . once . and_call_original
2 . times { namespace . find_fork_of ( project ) }
end
end
end
2018-11-08 19:23:39 +05:30
describe '#root_ancestor' do
2020-07-28 23:09:34 +05:30
let! ( :root_group ) { create ( :group ) }
it 'returns root_ancestor for root group without a query' do
expect { root_group . root_ancestor } . not_to exceed_query_limit ( 0 )
end
2019-10-12 21:52:04 +05:30
it 'returns the top most ancestor' do
2018-11-08 19:23:39 +05:30
nested_group = create ( :group , parent : root_group )
deep_nested_group = create ( :group , parent : nested_group )
very_deep_nested_group = create ( :group , parent : deep_nested_group )
2019-02-15 15:39:39 +05:30
expect ( root_group . root_ancestor ) . to eq ( root_group )
2018-11-08 19:23:39 +05:30
expect ( nested_group . root_ancestor ) . to eq ( root_group )
expect ( deep_nested_group . root_ancestor ) . to eq ( root_group )
expect ( very_deep_nested_group . root_ancestor ) . to eq ( root_group )
end
end
2019-07-31 22:56:46 +05:30
describe '#full_path_before_last_save' do
2018-03-17 18:26:18 +05:30
context 'when the group has no parent' do
2019-07-31 22:56:46 +05:30
it 'returns the path before last save' do
group = create ( :group )
group . update ( parent : nil )
expect ( group . full_path_before_last_save ) . to eq ( group . path_before_last_save )
2018-03-17 18:26:18 +05:30
end
end
context 'when a parent is assigned to a group with no previous parent' do
2019-07-31 22:56:46 +05:30
it 'returns the path before last save' do
2018-03-17 18:26:18 +05:30
group = create ( :group , parent : nil )
parent = create ( :group )
2019-07-31 22:56:46 +05:30
group . update ( parent : parent )
expect ( group . full_path_before_last_save ) . to eq ( " #{ group . path_before_last_save } " )
2018-03-17 18:26:18 +05:30
end
end
context 'when a parent is removed from the group' do
2019-07-07 11:18:12 +05:30
it 'returns the parent full path' do
2018-03-17 18:26:18 +05:30
parent = create ( :group )
group = create ( :group , parent : parent )
2019-07-31 22:56:46 +05:30
group . update ( parent : nil )
expect ( group . full_path_before_last_save ) . to eq ( " #{ parent . full_path } / #{ group . path } " )
2018-03-17 18:26:18 +05:30
end
end
context 'when changing parents' do
2019-07-07 11:18:12 +05:30
it 'returns the previous parent full path' do
2018-03-17 18:26:18 +05:30
parent = create ( :group )
group = create ( :group , parent : parent )
new_parent = create ( :group )
2019-07-31 22:56:46 +05:30
group . update ( parent : new_parent )
expect ( group . full_path_before_last_save ) . to eq ( " #{ parent . full_path } / #{ group . path } " )
2018-03-17 18:26:18 +05:30
end
end
2017-08-17 22:00:37 +05:30
end
2019-07-07 11:18:12 +05:30
describe '#auto_devops_enabled' do
context 'with users' do
let ( :user ) { create ( :user ) }
subject { user . namespace . auto_devops_enabled? }
before do
user . namespace . update! ( auto_devops_enabled : auto_devops_enabled )
end
context 'when auto devops is explicitly enabled' do
let ( :auto_devops_enabled ) { true }
it { is_expected . to eq ( true ) }
end
context 'when auto devops is explicitly disabled' do
let ( :auto_devops_enabled ) { false }
it { is_expected . to eq ( false ) }
end
end
end
2019-07-31 22:56:46 +05:30
describe '#user?' do
subject { namespace . user? }
context 'when type is a user' do
let ( :user ) { create ( :user ) }
let ( :namespace ) { user . namespace }
it { is_expected . to be_truthy }
end
context 'when type is a group' do
let ( :namespace ) { create ( :group ) }
it { is_expected . to be_falsy }
end
end
2019-09-30 21:07:59 +05:30
describe '#aggregation_scheduled?' do
let ( :namespace ) { create ( :namespace ) }
subject { namespace . aggregation_scheduled? }
context 'with an aggregation scheduled association' do
let ( :namespace ) { create ( :namespace , :with_aggregation_schedule ) }
it { is_expected . to be_truthy }
end
context 'without an aggregation scheduled association' do
it { is_expected . to be_falsy }
end
end
2019-10-12 21:52:04 +05:30
describe '#emails_disabled?' do
context 'when not a subgroup' do
it 'returns false' do
group = create ( :group , emails_disabled : false )
expect ( group . emails_disabled? ) . to be_falsey
end
it 'returns true' do
group = create ( :group , emails_disabled : true )
expect ( group . emails_disabled? ) . to be_truthy
end
2020-03-13 15:44:24 +05:30
it 'does not query the db when there is no parent group' do
group = create ( :group , emails_disabled : true )
expect { group . emails_disabled? } . not_to exceed_query_limit ( 0 )
end
2019-10-12 21:52:04 +05:30
end
context 'when a subgroup' do
let ( :grandparent ) { create ( :group ) }
let ( :parent ) { create ( :group , parent : grandparent ) }
let ( :group ) { create ( :group , parent : parent ) }
it 'returns false' do
expect ( group . emails_disabled? ) . to be_falsey
end
context 'when ancestor emails are disabled' do
it 'returns true' do
grandparent . update_attribute ( :emails_disabled , true )
expect ( group . emails_disabled? ) . to be_truthy
end
end
end
2019-12-21 20:55:43 +05:30
end
2019-10-12 21:52:04 +05:30
2019-12-21 20:55:43 +05:30
describe '#pages_virtual_domain' do
let ( :project ) { create ( :project , namespace : namespace ) }
context 'when there are pages deployed for the project' do
context 'but pages metadata is not migrated' do
before do
generic_commit_status = create ( :generic_commit_status , :success , stage : 'deploy' , name : 'pages:deploy' )
generic_commit_status . update! ( project : project )
project . pages_metadatum . destroy!
end
it 'migrates pages metadata and returns the virual domain' do
virtual_domain = namespace . pages_virtual_domain
2019-10-12 21:52:04 +05:30
2019-12-21 20:55:43 +05:30
expect ( project . reload . pages_metadatum . deployed ) . to eq ( true )
2019-10-12 21:52:04 +05:30
2019-12-21 20:55:43 +05:30
expect ( virtual_domain ) . to be_an_instance_of ( Pages :: VirtualDomain )
expect ( virtual_domain . lookup_paths ) . not_to be_empty
2019-10-12 21:52:04 +05:30
end
end
2019-12-21 20:55:43 +05:30
context 'and pages metadata is migrated' do
before do
project . mark_pages_as_deployed
end
2019-10-12 21:52:04 +05:30
2019-12-21 20:55:43 +05:30
it 'returns the virual domain' do
virtual_domain = namespace . pages_virtual_domain
2019-10-12 21:52:04 +05:30
2019-12-21 20:55:43 +05:30
expect ( virtual_domain ) . to be_an_instance_of ( Pages :: VirtualDomain )
expect ( virtual_domain . lookup_paths ) . not_to be_empty
2019-10-12 21:52:04 +05:30
end
end
2020-04-08 14:13:33 +05:30
it 'preloads project_feature and route' do
project2 = create ( :project , namespace : namespace )
project3 = create ( :project , namespace : namespace )
project . mark_pages_as_deployed
project2 . mark_pages_as_deployed
project3 . mark_pages_as_deployed
virtual_domain = namespace . pages_virtual_domain
queries = ActiveRecord :: QueryRecorder . new { virtual_domain . lookup_paths }
# 1 to load projects
# 1 to preload project features
# 1 to load routes
expect ( queries . count ) . to eq ( 3 )
end
2019-10-12 21:52:04 +05:30
end
end
2019-12-21 20:55:43 +05:30
2020-11-24 15:15:51 +05:30
describe '#any_project_with_pages_deployed?' do
it 'returns true if any project nested under the group has pages deployed' do
parent_1 = create ( :group ) # Three projects, one with pages
child_1_1 = create ( :group , parent : parent_1 ) # Two projects, one with pages
child_1_2 = create ( :group , parent : parent_1 ) # One project, no pages
parent_2 = create ( :group ) # No projects
create ( :project , group : child_1_1 ) . tap do | project |
project . pages_metadatum . update! ( deployed : true )
end
create ( :project , group : child_1_1 )
create ( :project , group : child_1_2 )
expect ( parent_1 . any_project_with_pages_deployed? ) . to be ( true )
expect ( child_1_1 . any_project_with_pages_deployed? ) . to be ( true )
expect ( child_1_2 . any_project_with_pages_deployed? ) . to be ( false )
expect ( parent_2 . any_project_with_pages_deployed? ) . to be ( false )
end
end
2019-12-21 20:55:43 +05:30
describe '#has_parent?' do
it 'returns true when the group has a parent' do
group = create ( :group , :nested )
expect ( group . has_parent? ) . to be_truthy
end
it 'returns true when the group has an unsaved parent' do
parent = build ( :group )
group = build ( :group , parent : parent )
expect ( group . has_parent? ) . to be_truthy
end
it 'returns false when the group has no parent' do
group = create ( :group , parent : nil )
expect ( group . has_parent? ) . to be_falsy
end
end
describe '#closest_setting' do
using RSpec :: Parameterized :: TableSyntax
shared_examples_for 'fetching closest setting' do
let! ( :root_namespace ) { create ( :namespace ) }
let! ( :namespace ) { create ( :namespace , parent : root_namespace ) }
let ( :setting ) { namespace . closest_setting ( setting_name ) }
before do
root_namespace . update_attribute ( setting_name , root_setting )
namespace . update_attribute ( setting_name , child_setting )
end
it 'returns closest non-nil value' do
expect ( setting ) . to eq ( result )
end
end
context 'when setting is of non-boolean type' do
where ( :root_setting , :child_setting , :result ) do
100 | 200 | 200
100 | nil | 100
nil | nil | nil
end
with_them do
let ( :setting_name ) { :max_artifacts_size }
it_behaves_like 'fetching closest setting'
end
end
context 'when setting is of boolean type' do
where ( :root_setting , :child_setting , :result ) do
true | false | false
true | nil | true
nil | nil | nil
end
with_them do
let ( :setting_name ) { :lfs_enabled }
it_behaves_like 'fetching closest setting'
end
end
end
2021-01-03 14:25:43 +05:30
describe '#shared_runners_setting' do
using RSpec :: Parameterized :: TableSyntax
where ( :shared_runners_enabled , :allow_descendants_override_disabled_shared_runners , :shared_runners_setting ) do
true | true | 'enabled'
true | false | 'enabled'
false | true | 'disabled_with_override'
false | false | 'disabled_and_unoverridable'
end
with_them do
let ( :namespace ) { build ( :namespace , shared_runners_enabled : shared_runners_enabled , allow_descendants_override_disabled_shared_runners : allow_descendants_override_disabled_shared_runners ) }
it 'returns the result' do
expect ( namespace . shared_runners_setting ) . to eq ( shared_runners_setting )
end
end
end
describe '#shared_runners_setting_higher_than?' do
using RSpec :: Parameterized :: TableSyntax
where ( :shared_runners_enabled , :allow_descendants_override_disabled_shared_runners , :other_setting , :result ) do
true | true | 'enabled' | false
true | true | 'disabled_with_override' | true
true | true | 'disabled_and_unoverridable' | true
false | true | 'enabled' | false
false | true | 'disabled_with_override' | false
false | true | 'disabled_and_unoverridable' | true
false | false | 'enabled' | false
false | false | 'disabled_with_override' | false
false | false | 'disabled_and_unoverridable' | false
end
with_them do
let ( :namespace ) { build ( :namespace , shared_runners_enabled : shared_runners_enabled , allow_descendants_override_disabled_shared_runners : allow_descendants_override_disabled_shared_runners ) }
it 'returns the result' do
expect ( namespace . shared_runners_setting_higher_than? ( other_setting ) ) . to eq ( result )
end
end
end
describe 'validation #changing_shared_runners_enabled_is_allowed' do
context 'without a parent' do
let ( :namespace ) { build ( :namespace , shared_runners_enabled : true ) }
it 'is valid' do
expect ( namespace ) . to be_valid
end
end
context 'with a parent' do
context 'when parent has shared runners disabled' do
let ( :parent ) { create ( :namespace , :shared_runners_disabled ) }
let ( :sub_namespace ) { build ( :namespace , shared_runners_enabled : true , parent_id : parent . id ) }
it 'is invalid' do
expect ( sub_namespace ) . to be_invalid
expect ( sub_namespace . errors [ :shared_runners_enabled ] ) . to include ( 'cannot be enabled because parent group has shared Runners disabled' )
end
end
context 'when parent has shared runners disabled but allows override' do
let ( :parent ) { create ( :namespace , :shared_runners_disabled , :allow_descendants_override_disabled_shared_runners ) }
let ( :sub_namespace ) { build ( :namespace , shared_runners_enabled : true , parent_id : parent . id ) }
it 'is valid' do
expect ( sub_namespace ) . to be_valid
end
end
context 'when parent has shared runners enabled' do
let ( :parent ) { create ( :namespace , shared_runners_enabled : true ) }
let ( :sub_namespace ) { build ( :namespace , shared_runners_enabled : true , parent_id : parent . id ) }
it 'is valid' do
expect ( sub_namespace ) . to be_valid
end
end
end
end
describe 'validation #changing_allow_descendants_override_disabled_shared_runners_is_allowed' do
context 'without a parent' do
context 'with shared runners disabled' do
let ( :namespace ) { build ( :namespace , :allow_descendants_override_disabled_shared_runners , :shared_runners_disabled ) }
it 'is valid' do
expect ( namespace ) . to be_valid
end
end
context 'with shared runners enabled' do
let ( :namespace ) { create ( :namespace ) }
it 'is invalid' do
namespace . allow_descendants_override_disabled_shared_runners = true
expect ( namespace ) . to be_invalid
expect ( namespace . errors [ :allow_descendants_override_disabled_shared_runners ] ) . to include ( 'cannot be changed if shared runners are enabled' )
end
end
end
context 'with a parent' do
context 'when parent does not allow shared runners' do
let ( :parent ) { create ( :namespace , :shared_runners_disabled ) }
let ( :sub_namespace ) { build ( :namespace , :shared_runners_disabled , :allow_descendants_override_disabled_shared_runners , parent_id : parent . id ) }
it 'is invalid' do
expect ( sub_namespace ) . to be_invalid
expect ( sub_namespace . errors [ :allow_descendants_override_disabled_shared_runners ] ) . to include ( 'cannot be enabled because parent group does not allow it' )
end
end
context 'when parent allows shared runners and setting to true' do
let ( :parent ) { create ( :namespace , shared_runners_enabled : true ) }
let ( :sub_namespace ) { build ( :namespace , :shared_runners_disabled , :allow_descendants_override_disabled_shared_runners , parent_id : parent . id ) }
it 'is valid' do
expect ( sub_namespace ) . to be_valid
end
end
context 'when parent allows shared runners and setting to false' do
let ( :parent ) { create ( :namespace , shared_runners_enabled : true ) }
let ( :sub_namespace ) { build ( :namespace , :shared_runners_disabled , allow_descendants_override_disabled_shared_runners : false , parent_id : parent . id ) }
it 'is valid' do
expect ( sub_namespace ) . to be_valid
end
end
end
end
2014-09-02 18:07:02 +05:30
end