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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/namespace_spec.rb')
-rw-r--r--spec/models/namespace_spec.rb246
1 files changed, 172 insertions, 74 deletions
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 647e279bf83..65d787d334b 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Namespace do
include ProjectForksHelper
include GitHelpers
- let!(:namespace) { create(:namespace) }
+ let!(:namespace) { create(:namespace, :with_namespace_settings) }
let(:gitlab_shell) { Gitlab::Shell.new }
let(:repository_storage) { 'default' }
@@ -32,14 +32,68 @@ RSpec.describe Namespace do
it { is_expected.to validate_presence_of(:owner) }
it { is_expected.to validate_numericality_of(:max_artifacts_size).only_integer.is_greater_than(0) }
+ context 'validating the parent of a namespace' do
+ context 'when the namespace has no parent' do
+ it 'allows a namespace to have no parent associated with it' do
+ namespace = build(:namespace)
+
+ expect(namespace).to be_valid
+ end
+ end
+
+ context 'when the namespace has a parent' do
+ it 'does not allow a namespace to have a group as its parent' do
+ namespace = build(:namespace, parent: build(:group))
+
+ expect(namespace).not_to be_valid
+ expect(namespace.errors[:parent_id].first).to eq('a user namespace cannot have a parent')
+ end
+
+ it 'does not allow a namespace to have another namespace as its parent' do
+ namespace = build(:namespace, parent: build(:namespace))
+
+ expect(namespace).not_to be_valid
+ expect(namespace.errors[:parent_id].first).to eq('a user namespace cannot have a parent')
+ end
+ end
+
+ context 'when the feature flag `validate_namespace_parent_type` is disabled' do
+ before do
+ stub_feature_flags(validate_namespace_parent_type: false)
+ end
+
+ context 'when the namespace has no parent' do
+ it 'allows a namespace to have no parent associated with it' do
+ namespace = build(:namespace)
+
+ expect(namespace).to be_valid
+ end
+ end
+
+ context 'when the namespace has a parent' do
+ it 'allows a namespace to have a group as its parent' do
+ namespace = build(:namespace, parent: build(:group))
+
+ expect(namespace).to be_valid
+ end
+
+ it 'allows a namespace to have another namespace as its parent' do
+ namespace = build(:namespace, parent: build(:namespace))
+
+ expect(namespace).to be_valid
+ end
+ end
+ end
+ end
+
it 'does not allow too deep nesting' do
ancestors = (1..21).to_a
- nested = build(:namespace, parent: namespace)
+ group = build(:group)
- allow(nested).to receive(:ancestors).and_return(ancestors)
+ allow(group).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')
+ expect(group).not_to be_valid
+ expect(group.errors[:parent_id].first).to eq('has too deep level of nesting')
end
describe 'reserved path validation' do
@@ -116,6 +170,28 @@ RSpec.describe Namespace do
it { is_expected.to include_module(Namespaces::Traversal::Recursive) }
end
+ describe 'callbacks' do
+ describe 'before_save :ensure_delayed_project_removal_assigned_to_namespace_settings' do
+ it 'sets the matching value in namespace_settings' do
+ expect { namespace.update!(delayed_project_removal: true) }.to change {
+ namespace.namespace_settings.delayed_project_removal
+ }.from(false).to(true)
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(migrate_delayed_project_removal: false)
+ end
+
+ it 'does not set the matching value in namespace_settings' do
+ expect { namespace.update!(delayed_project_removal: true) }.not_to change {
+ namespace.namespace_settings.delayed_project_removal
+ }
+ end
+ end
+ end
+ end
+
describe '#visibility_level_field' do
it { expect(namespace.visibility_level_field).to eq(:visibility_level) }
end
@@ -150,45 +226,45 @@ RSpec.describe Namespace do
end
describe '.search' do
- let_it_be(:first_namespace) { build(:namespace, name: 'my first namespace', path: 'old-path').tap(&:save!) }
- let_it_be(:parent_namespace) { build(:namespace, name: 'my parent namespace', path: 'parent-path').tap(&:save!) }
- let_it_be(:second_namespace) { build(:namespace, name: 'my second namespace', path: 'new-path', parent: parent_namespace).tap(&:save!) }
- let_it_be(:project_with_same_path) { create(:project, id: second_namespace.id, path: first_namespace.path) }
+ let_it_be(:first_group) { build(:group, name: 'my first namespace', path: 'old-path').tap(&:save!) }
+ let_it_be(:parent_group) { build(:group, name: 'my parent namespace', path: 'parent-path').tap(&:save!) }
+ let_it_be(:second_group) { build(:group, name: 'my second namespace', path: 'new-path', parent: parent_group).tap(&:save!) }
+ let_it_be(:project_with_same_path) { create(:project, id: second_group.id, path: first_group.path) }
it 'returns namespaces with a matching name' do
- expect(described_class.search('my first namespace')).to eq([first_namespace])
+ expect(described_class.search('my first namespace')).to eq([first_group])
end
it 'returns namespaces with a partially matching name' do
- expect(described_class.search('first')).to eq([first_namespace])
+ expect(described_class.search('first')).to eq([first_group])
end
it 'returns namespaces with a matching name regardless of the casing' do
- expect(described_class.search('MY FIRST NAMESPACE')).to eq([first_namespace])
+ expect(described_class.search('MY FIRST NAMESPACE')).to eq([first_group])
end
it 'returns namespaces with a matching path' do
- expect(described_class.search('old-path')).to eq([first_namespace])
+ expect(described_class.search('old-path')).to eq([first_group])
end
it 'returns namespaces with a partially matching path' do
- expect(described_class.search('old')).to eq([first_namespace])
+ expect(described_class.search('old')).to eq([first_group])
end
it 'returns namespaces with a matching path regardless of the casing' do
- expect(described_class.search('OLD-PATH')).to eq([first_namespace])
+ expect(described_class.search('OLD-PATH')).to eq([first_group])
end
it 'returns namespaces with a matching route path' do
- expect(described_class.search('parent-path/new-path', include_parents: true)).to eq([second_namespace])
+ expect(described_class.search('parent-path/new-path', include_parents: true)).to eq([second_group])
end
it 'returns namespaces with a partially matching route path' do
- expect(described_class.search('parent-path/new', include_parents: true)).to eq([second_namespace])
+ expect(described_class.search('parent-path/new', include_parents: true)).to eq([second_group])
end
it 'returns namespaces with a matching route path regardless of the casing' do
- expect(described_class.search('PARENT-PATH/NEW-PATH', include_parents: true)).to eq([second_namespace])
+ expect(described_class.search('PARENT-PATH/NEW-PATH', include_parents: true)).to eq([second_group])
end
end
@@ -285,6 +361,18 @@ RSpec.describe Namespace do
end
end
+ describe '.top_most' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+
+ subject { described_class.top_most.ids }
+
+ it 'only contains root namespaces' do
+ is_expected.to contain_exactly(group.id, namespace.id)
+ end
+ end
+
describe '#ancestors_upto' do
let(:parent) { create(:group) }
let(:child) { create(:group, parent: parent) }
@@ -800,7 +888,7 @@ RSpec.describe Namespace do
end
describe '#all_projects' do
- shared_examples 'all projects for a group' do
+ context 'when namespace is a group' do
let(:namespace) { create(:group) }
let(:child) { create(:group, parent: namespace) }
let!(:project1) { create(:project_empty_repo, namespace: namespace) }
@@ -808,49 +896,39 @@ RSpec.describe Namespace do
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 projects for personal 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
-
- context 'with recursive approach' do
- context 'when namespace is a group' do
- include_examples 'all projects for a group'
+ context 'when recursive_namespace_lookup_as_inner_join feature flag is on' do
+ before do
+ stub_feature_flags(recursive_namespace_lookup_as_inner_join: true)
+ end
it 'queries for the namespace and its descendants' do
- expect(Project).to receive(:where).with(namespace: [namespace, child])
-
- namespace.all_projects
+ expect(namespace.all_projects).to match_array([project1, project2])
end
end
- context 'when namespace is a user namespace' do
- include_examples 'all projects for personal namespace'
-
- it 'only queries for the namespace itself' do
- expect(Project).to receive(:where).with(namespace: user_namespace)
+ context 'when recursive_namespace_lookup_as_inner_join feature flag is off' do
+ before do
+ stub_feature_flags(recursive_namespace_lookup_as_inner_join: false)
+ end
- user_namespace.all_projects
+ it 'queries for the namespace and its descendants' do
+ expect(namespace.all_projects).to match_array([project1, project2])
end
end
end
- context 'with route path wildcard approach' do
- before do
- stub_feature_flags(recursive_approach_for_all_projects: false)
- end
+ 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) }
- context 'when namespace is a group' do
- include_examples 'all projects for a group'
- end
+ it { expect(user_namespace.all_projects.to_a).to match_array([project]) }
+
+ it 'only queries for the namespace itself' do
+ expect(Project).to receive(:where).with(namespace: user_namespace)
- context 'when namespace is a user namespace' do
- include_examples 'all projects for personal namespace'
+ user_namespace.all_projects
end
end
end
@@ -1250,14 +1328,14 @@ RSpec.describe Namespace 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!(:parent) { create(:group) }
+ let!(:group) { create(:group, parent: parent) }
- let(:setting) { namespace.closest_setting(setting_name) }
+ let(:setting) { group.closest_setting(setting_name) }
before do
- root_namespace.update_attribute(setting_name, root_setting)
- namespace.update_attribute(setting_name, child_setting)
+ parent.update_attribute(setting_name, root_setting)
+ group.update_attribute(setting_name, child_setting)
end
it 'returns closest non-nil value' do
@@ -1348,30 +1426,30 @@ RSpec.describe Namespace do
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) }
+ let(:parent) { create(:group, :shared_runners_disabled) }
+ let(:group) { build(:group, 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')
+ expect(group).to be_invalid
+ expect(group.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) }
+ let(:parent) { create(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners) }
+ let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
it 'is valid' do
- expect(sub_namespace).to be_valid
+ expect(group).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) }
+ let(:parent) { create(:group, shared_runners_enabled: true) }
+ let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
it 'is valid' do
- expect(sub_namespace).to be_valid
+ expect(group).to be_valid
end
end
end
@@ -1401,30 +1479,30 @@ RSpec.describe Namespace do
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) }
+ let(:parent) { create(:group, :shared_runners_disabled) }
+ let(:group) { build(:group, :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')
+ expect(group).to be_invalid
+ expect(group.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) }
+ let(:parent) { create(:group, shared_runners_enabled: true) }
+ let(:group) { build(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners, parent_id: parent.id) }
it 'is valid' do
- expect(sub_namespace).to be_valid
+ expect(group).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) }
+ let(:parent) { create(:group, shared_runners_enabled: true) }
+ let(:group) { build(:group, :shared_runners_disabled, allow_descendants_override_disabled_shared_runners: false, parent_id: parent.id) }
it 'is valid' do
- expect(sub_namespace).to be_valid
+ expect(group).to be_valid
end
end
end
@@ -1449,4 +1527,24 @@ RSpec.describe Namespace do
end
end
end
+
+ describe '#recent?' do
+ subject { namespace.recent? }
+
+ context 'when created more than 90 days ago' do
+ before do
+ namespace.update_attribute(:created_at, 91.days.ago)
+ end
+
+ it { is_expected.to be(false) }
+ end
+
+ context 'when created less than 90 days ago' do
+ before do
+ namespace.update_attribute(:created_at, 89.days.ago)
+ end
+
+ it { is_expected.to be(true) }
+ end
+ end
end