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/project_spec.rb')
-rw-r--r--spec/models/project_spec.rb244
1 files changed, 193 insertions, 51 deletions
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 538f6b363e9..5d622b8eccd 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
describe 'associations' do
it { is_expected.to belong_to(:group) }
it { is_expected.to belong_to(:namespace) }
- it { is_expected.to belong_to(:project_namespace).class_name('Namespaces::ProjectNamespace').with_foreign_key('project_namespace_id') }
+ it { is_expected.to belong_to(:project_namespace).class_name('Namespaces::ProjectNamespace').with_foreign_key('project_namespace_id').inverse_of(:project) }
it { is_expected.to belong_to(:creator).class_name('User') }
it { is_expected.to belong_to(:pool_repository) }
it { is_expected.to have_many(:users) }
@@ -46,6 +46,8 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
it { is_expected.to have_one(:design_management_repository).class_name('DesignManagement::Repository').inverse_of(:project) }
it { is_expected.to have_one(:slack_integration) }
it { is_expected.to have_one(:catalog_resource) }
+ it { is_expected.to have_many(:ci_components).class_name('Ci::Catalog::Resources::Component') }
+ it { is_expected.to have_many(:catalog_resource_versions).class_name('Ci::Catalog::Resources::Version') }
it { is_expected.to have_one(:microsoft_teams_integration) }
it { is_expected.to have_one(:mattermost_integration) }
it { is_expected.to have_one(:hangouts_chat_integration) }
@@ -633,8 +635,8 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
it 'validates the visibility' do
- expect_any_instance_of(described_class).to receive(:visibility_level_allowed_as_fork).and_call_original
- expect_any_instance_of(described_class).to receive(:visibility_level_allowed_by_group).and_call_original
+ expect_any_instance_of(described_class).to receive(:visibility_level_allowed_as_fork).twice.and_call_original
+ expect_any_instance_of(described_class).to receive(:visibility_level_allowed_by_group).twice.and_call_original
create(:project)
end
@@ -1121,6 +1123,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
'group_runners_enabled' => '',
'default_git_depth' => 'ci_',
'forward_deployment_enabled' => 'ci_',
+ 'forward_deployment_rollback_allowed' => 'ci_',
'keep_latest_artifact' => '',
'restrict_user_defined_variables' => '',
'runner_token_expiration_interval' => '',
@@ -1147,6 +1150,12 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
+ describe '#ci_forward_deployment_rollback_allowed?' do
+ it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_' do
+ let(:delegated_method) { :forward_deployment_rollback_allowed? }
+ end
+ end
+
describe '#ci_allow_fork_pipelines_to_run_in_parent_project?' do
it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_' do
let(:delegated_method) { :allow_fork_pipelines_to_run_in_parent_project? }
@@ -3037,6 +3046,34 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
shard_name: 'foo'
)
end
+
+ it 'refreshes a memoized repository value' do
+ previous_repository = project.repository
+
+ allow(project).to receive(:disk_path).and_return('fancy/new/path')
+ allow(project).to receive(:repository_storage).and_return('foo')
+
+ project.track_project_repository
+
+ expect(project.repository).not_to eq(previous_repository)
+ end
+
+ context 'when "replicate_object_pool_on_move" FF is disabled' do
+ before do
+ stub_feature_flags(replicate_object_pool_on_move: false)
+ end
+
+ it 'does not update a memoized repository value' do
+ previous_repository = project.repository
+
+ allow(project).to receive(:disk_path).and_return('fancy/new/path')
+ allow(project).to receive(:repository_storage).and_return('foo')
+
+ project.track_project_repository
+
+ expect(project.repository).to eq(previous_repository)
+ end
+ end
end
end
@@ -3982,51 +4019,10 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
describe '#emails_disabled?' do
- let_it_be(:namespace) { create(:namespace) }
-
- let(:project) { build(:project, namespace: namespace, emails_disabled: false) }
-
- context 'emails disabled in group' do
- it 'returns true' do
- allow(project.namespace).to receive(:emails_disabled?) { true }
-
- expect(project.emails_disabled?).to be_truthy
- end
- end
-
- context 'emails enabled in group' do
- before do
- allow(project.namespace).to receive(:emails_disabled?) { false }
- end
-
- it 'returns false' do
- expect(project.emails_disabled?).to be_falsey
- end
-
- it 'returns true' do
- project.update_attribute(:emails_disabled, true)
-
- expect(project.emails_disabled?).to be_truthy
- end
- end
- end
-
- describe '#emails_enabled?' do
- context 'without a persisted project_setting object' do
- let(:project) { build(:project, emails_disabled: false) }
-
- it "is the opposite of emails_disabled" do
- expect(project.emails_enabled?).to be_truthy
- end
- end
-
- context 'with a persisted project_setting object' do
- let(:project_settings) { create(:project_setting, emails_enabled: true) }
- let(:project) { build(:project, emails_disabled: false, project_setting: project_settings) }
+ let(:project) { build(:project, emails_enabled: true) }
- it "is the opposite of emails_disabled" do
- expect(project.emails_enabled?).to be_truthy
- end
+ it "is the opposite of emails_disabled" do
+ expect(project.emails_disabled?).to be_falsey
end
end
@@ -6984,6 +6980,73 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
+ describe '#swap_pool_repository!' do
+ subject(:swap_pool_repository!) { project.swap_pool_repository! }
+
+ let_it_be_with_reload(:project) { create(:project, :empty_repo) }
+ let_it_be(:shard_to) { create(:shard, name: 'test_second_storage') }
+
+ let!(:pool1) { create(:pool_repository, source_project: project) }
+ let!(:pool2) { create(:pool_repository, shard: shard_to, source_project: project) }
+ let(:project_pool) { pool1 }
+ let(:repository_storage) { shard_to.name }
+
+ before do
+ stub_storage_settings(
+ 'test_second_storage' => {
+ 'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address,
+ 'path' => TestEnv::SECOND_STORAGE_PATH
+ }
+ )
+
+ project.update!(pool_repository: project_pool, repository_storage: repository_storage)
+ end
+
+ shared_examples 'no pool repository swap' do
+ it 'does not change pool repository for the project' do
+ expect { swap_pool_repository! }.not_to change { project.reload.pool_repository }
+ end
+ end
+
+ it 'moves project to the new pool repository' do
+ expect { swap_pool_repository! }.to change { project.reload.pool_repository }.from(pool1).to(pool2)
+ end
+
+ context 'when feature flag replicate_object_pool_on_move is disabled' do
+ before do
+ stub_feature_flags(replicate_object_pool_on_move: false)
+ end
+
+ it_behaves_like 'no pool repository swap'
+ end
+
+ context 'when repository does not exist' do
+ let(:project) { build(:project) }
+
+ it_behaves_like 'no pool repository swap'
+ end
+
+ context 'when project does not have a pool repository' do
+ let(:project_pool) { nil }
+
+ it_behaves_like 'no pool repository swap'
+ end
+
+ context 'when project pool is on the same shard as repository' do
+ let(:project_pool) { pool2 }
+
+ it_behaves_like 'no pool repository swap'
+ end
+
+ context 'when pool repository for shard is missing' do
+ let(:pool2) { nil }
+
+ it 'raises record not found error' do
+ expect { swap_pool_repository! }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+
describe '#leave_pool_repository' do
let(:pool) { create(:pool_repository) }
let(:project) { create(:project, :repository, pool_repository: pool) }
@@ -7011,6 +7074,53 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
+ describe '#link_pool_repository' do
+ let(:pool) { create(:pool_repository) }
+ let(:project) { build(:project, :empty_repo, pool_repository: pool) }
+
+ subject { project.link_pool_repository }
+
+ it 'links pool repository to project repository' do
+ expect(pool).to receive(:link_repository).with(project.repository)
+
+ subject
+ end
+
+ context 'when pool repository is missing' do
+ let(:pool) { nil }
+
+ it 'does not link anything' do
+ allow_next_instance_of(PoolRepository) do |pool_repository|
+ expect(pool_repository).not_to receive(:link_repository)
+ end
+
+ subject
+ end
+ end
+
+ context 'when pool repository is on the different shard as project repository' do
+ let(:pool) { create(:pool_repository, shard: create(:shard, name: 'new')) }
+
+ it 'does not link anything' do
+ expect(pool).not_to receive(:link_repository)
+
+ subject
+ end
+
+ context 'when feature flag replicate_object_pool_on_move is disabled' do
+ before do
+ stub_feature_flags(replicate_object_pool_on_move: false)
+ end
+
+ it 'links pool repository to project repository' do
+ expect(pool).to receive(:link_repository).with(project.repository)
+
+ subject
+ end
+ end
+ end
+ end
+
describe '#check_personal_projects_limit' do
context 'when creating a project for a group' do
it 'does nothing' do
@@ -7084,10 +7194,10 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
where(:shared_runners_setting, :project_shared_runners_enabled, :valid_record) do
:shared_runners_enabled | true | true
:shared_runners_enabled | false | true
- :disabled_and_overridable | true | true
- :disabled_and_overridable | false | true
- :disabled_and_unoverridable | true | false
- :disabled_and_unoverridable | false | true
+ :shared_runners_disabled_and_overridable | true | true
+ :shared_runners_disabled_and_overridable | false | true
+ :shared_runners_disabled_and_unoverridable | true | false
+ :shared_runners_disabled_and_unoverridable | false | true
end
with_them do
@@ -7333,6 +7443,32 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
+ describe '#pages_variables' do
+ let(:group) { build(:group, path: 'group') }
+ let(:project) { build(:project, path: 'project', namespace: group) }
+
+ it 'returns the pages variables' do
+ expect(project.pages_variables.to_hash).to eq({
+ 'CI_PAGES_DOMAIN' => 'example.com',
+ 'CI_PAGES_URL' => 'http://group.example.com/project'
+ })
+ end
+
+ it 'returns the pages variables' do
+ build(
+ :project_setting,
+ project: project,
+ pages_unique_domain_enabled: true,
+ pages_unique_domain: 'unique-domain'
+ )
+
+ expect(project.pages_variables.to_hash).to eq({
+ 'CI_PAGES_DOMAIN' => 'example.com',
+ 'CI_PAGES_URL' => 'http://unique-domain.example.com'
+ })
+ end
+ end
+
describe '#closest_setting' do
shared_examples_for 'fetching closest setting' do
let!(:namespace) { create(:namespace) }
@@ -8992,6 +9128,12 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
it { is_expected.to eq false }
end
+
+ context 'when there is no creator' do
+ let_it_be(:project) { build_stubbed(:project, creator: nil) }
+
+ it { is_expected.to eq false }
+ end
end
it_behaves_like 'something that has web-hooks' do