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/services/projects')
-rw-r--r--spec/services/projects/apple_target_platform_detector_service_spec.rb61
-rw-r--r--spec/services/projects/container_repository/cleanup_tags_service_spec.rb2
-rw-r--r--spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb14
-rw-r--r--spec/services/projects/create_service_spec.rb28
-rw-r--r--spec/services/projects/operations/update_service_spec.rb31
-rw-r--r--spec/services/projects/record_target_platforms_service_spec.rb66
-rw-r--r--spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb13
-rw-r--r--spec/services/projects/transfer_service_spec.rb72
8 files changed, 252 insertions, 35 deletions
diff --git a/spec/services/projects/apple_target_platform_detector_service_spec.rb b/spec/services/projects/apple_target_platform_detector_service_spec.rb
new file mode 100644
index 00000000000..6391161824c
--- /dev/null
+++ b/spec/services/projects/apple_target_platform_detector_service_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::AppleTargetPlatformDetectorService do
+ let_it_be(:project) { build(:project) }
+
+ subject { described_class.new(project).execute }
+
+ context 'when project is not an xcode project' do
+ before do
+ allow(Gitlab::FileFinder).to receive(:new) { instance_double(Gitlab::FileFinder, find: []) }
+ end
+
+ it 'returns an empty array' do
+ is_expected.to match_array []
+ end
+ end
+
+ context 'when project is an xcode project' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:finder) { instance_double(Gitlab::FileFinder) }
+
+ before do
+ allow(Gitlab::FileFinder).to receive(:new) { finder }
+ end
+
+ def search_query(sdk, filename)
+ "SDKROOT = #{sdk} filename:#{filename}"
+ end
+
+ context 'when setting string is found' do
+ where(:sdk, :filename, :result) do
+ 'iphoneos' | 'project.pbxproj' | [:ios]
+ 'iphoneos' | '*.xcconfig' | [:ios]
+ end
+
+ with_them do
+ before do
+ allow(finder).to receive(:find).with(anything) { [] }
+ allow(finder).to receive(:find).with(search_query(sdk, filename)) { [instance_double(Gitlab::Search::FoundBlob)] }
+ end
+
+ it 'returns an array of unique detected targets' do
+ is_expected.to match_array result
+ end
+ end
+ end
+
+ context 'when setting string is not found' do
+ before do
+ allow(finder).to receive(:find).with(anything) { [] }
+ end
+
+ it 'returns an empty array' do
+ is_expected.to match_array []
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
index 38a3e00c8e7..86c0ba4222c 100644
--- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService, :clean_gitlab_
let(:tags) { %w[latest A Ba Bb C D E] }
before do
- project.add_maintainer(user)
+ project.add_maintainer(user) if user
stub_container_registry_config(enabled: true)
diff --git a/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb b/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb
index 7fc963949eb..22cada7816b 100644
--- a/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb
@@ -58,7 +58,19 @@ RSpec.describe Projects::ContainerRepository::ThirdParty::DeleteTagsService do
stub_put_manifest_request('Ba', 500, {})
end
- it { is_expected.to eq(status: :error, message: 'could not delete tags') }
+ it { is_expected.to eq(status: :error, message: "could not delete tags: #{tags.join(', ')}")}
+
+ context 'when a large list of tag updates fails' do
+ let(:tags) { Array.new(1000) { |i| "tag_#{i}" } }
+
+ before do
+ expect(service).to receive(:replace_tag_manifests).and_return({})
+ end
+
+ it 'truncates the log message' do
+ expect(subject).to eq(status: :error, message: "could not delete tags: #{tags.join(', ')}".truncate(1000))
+ end
+ end
end
context 'a single tag update fails' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 96a50b26871..c5c5af3cb01 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -135,10 +135,22 @@ RSpec.describe Projects::CreateService, '#execute' do
create_project(user, opts)
end
- it 'builds associated project settings' do
+ it 'creates associated project settings' do
project = create_project(user, opts)
- expect(project.project_setting).to be_new_record
+ expect(project.project_setting).to be_persisted
+ end
+
+ context 'create_project_settings feature flag is disabled' do
+ before do
+ stub_feature_flags(create_project_settings: false)
+ end
+
+ it 'builds associated project settings' do
+ project = create_project(user, opts)
+
+ expect(project.project_setting).to be_new_record
+ end
end
it_behaves_like 'storing arguments in the application context' do
@@ -376,6 +388,18 @@ RSpec.describe Projects::CreateService, '#execute' do
imported_project
end
+
+ describe 'import scheduling' do
+ context 'when project import type is gitlab project migration' do
+ it 'does not schedule project import' do
+ opts[:import_type] = 'gitlab_project_migration'
+
+ project = create_project(user, opts)
+
+ expect(project.import_state.status).to eq('none')
+ end
+ end
+ end
end
context 'builds_enabled global setting' do
diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb
index b64f2d1e7d6..3ee867ba6f2 100644
--- a/spec/services/projects/operations/update_service_spec.rb
+++ b/spec/services/projects/operations/update_service_spec.rb
@@ -407,10 +407,11 @@ RSpec.describe Projects::Operations::UpdateService do
context 'prometheus integration' do
context 'prometheus params were passed into service' do
- let(:prometheus_integration) do
- build_stubbed(:prometheus_integration, project: project, properties: {
+ let!(:prometheus_integration) do
+ create(:prometheus_integration, :instance, properties: {
api_url: "http://example.prometheus.com",
- manual_configuration: "0"
+ manual_configuration: "0",
+ google_iap_audience_client_id: 123
})
end
@@ -424,21 +425,23 @@ RSpec.describe Projects::Operations::UpdateService do
end
it 'uses Project#find_or_initialize_integration to include instance defined defaults and pass them to Projects::UpdateService', :aggregate_failures do
- project_update_service = double(Projects::UpdateService)
-
- expect(project)
- .to receive(:find_or_initialize_integration)
- .with('prometheus')
- .and_return(prometheus_integration)
expect(Projects::UpdateService).to receive(:new) do |project_arg, user_arg, update_params_hash|
+ prometheus_attrs = update_params_hash[:prometheus_integration_attributes]
+
expect(project_arg).to eq project
expect(user_arg).to eq user
- expect(update_params_hash[:prometheus_integration_attributes]).to include('properties' => { 'api_url' => 'http://new.prometheus.com', 'manual_configuration' => '1' })
- expect(update_params_hash[:prometheus_integration_attributes]).not_to include(*%w(id project_id created_at updated_at))
- end.and_return(project_update_service)
- expect(project_update_service).to receive(:execute)
+ expect(prometheus_attrs).to have_key('encrypted_properties')
+ expect(prometheus_attrs.keys).not_to include(*%w(id project_id created_at updated_at properties))
+ expect(prometheus_attrs['encrypted_properties']).not_to eq(prometheus_integration.encrypted_properties)
+ end.and_call_original
- subject.execute
+ expect { subject.execute }.to change(Integrations::Prometheus, :count).by(1)
+
+ expect(Integrations::Prometheus.last).to have_attributes(
+ api_url: 'http://new.prometheus.com',
+ manual_configuration: true,
+ google_iap_audience_client_id: 123
+ )
end
end
diff --git a/spec/services/projects/record_target_platforms_service_spec.rb b/spec/services/projects/record_target_platforms_service_spec.rb
new file mode 100644
index 00000000000..85311f36428
--- /dev/null
+++ b/spec/services/projects/record_target_platforms_service_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::RecordTargetPlatformsService, '#execute' do
+ let_it_be(:project) { create(:project) }
+
+ subject(:execute) { described_class.new(project).execute }
+
+ context 'when project is an XCode project' do
+ before do
+ double = instance_double(Projects::AppleTargetPlatformDetectorService, execute: [:ios, :osx])
+ allow(Projects::AppleTargetPlatformDetectorService).to receive(:new) { double }
+ end
+
+ it 'creates a new setting record for the project', :aggregate_failures do
+ expect { execute }.to change { ProjectSetting.count }.from(0).to(1)
+ expect(ProjectSetting.last.target_platforms).to match_array(%w(ios osx))
+ end
+
+ it 'returns array of detected target platforms' do
+ expect(execute).to match_array %w(ios osx)
+ end
+
+ context 'when a project has an existing setting record' do
+ before do
+ create(:project_setting, project: project, target_platforms: saved_target_platforms)
+ end
+
+ def project_setting
+ ProjectSetting.find_by_project_id(project.id)
+ end
+
+ context 'when target platforms changed' do
+ let(:saved_target_platforms) { %w(tvos) }
+
+ it 'updates' do
+ expect { execute }.to change { project_setting.target_platforms }.from(%w(tvos)).to(%w(ios osx))
+ end
+
+ it { is_expected.to match_array %w(ios osx) }
+ end
+
+ context 'when target platforms are the same' do
+ let(:saved_target_platforms) { %w(osx ios) }
+
+ it 'does not update' do
+ expect { execute }.not_to change { project_setting.updated_at }
+ end
+ end
+ end
+ end
+
+ context 'when project is not an XCode project' do
+ before do
+ double = instance_double(Projects::AppleTargetPlatformDetectorService, execute: [])
+ allow(Projects::AppleTargetPlatformDetectorService).to receive(:new).with(project) { double }
+ end
+
+ it 'does nothing' do
+ expect { execute }.not_to change { ProjectSetting.count }
+ end
+
+ it { is_expected.to be_nil }
+ end
+end
diff --git a/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb b/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb
index 41de8c6bdbb..41487e9ea48 100644
--- a/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb
+++ b/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb
@@ -10,7 +10,8 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitl
let_it_be(:artifact_1) { create(:ci_job_artifact, project: project, size: 1, created_at: 14.days.ago) }
let_it_be(:artifact_2) { create(:ci_job_artifact, project: project, size: 2, created_at: 13.days.ago) }
- let_it_be(:artifact_3) { create(:ci_job_artifact, project: project, size: 5, created_at: 12.days.ago) }
+ let_it_be(:artifact_3) { create(:ci_job_artifact, project: project, size: nil, created_at: 13.days.ago) }
+ let_it_be(:artifact_4) { create(:ci_job_artifact, project: project, size: 5, created_at: 12.days.ago) }
# This should not be included in the recalculation as it is created later than the refresh start time
let_it_be(:future_artifact) { create(:ci_job_artifact, project: project, size: 8, created_at: 2.days.from_now) }
@@ -33,7 +34,7 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitl
end
before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
+ stub_const("#{described_class}::BATCH_SIZE", 3)
stats = create(:project_statistics, project: project, build_artifacts_size: 120)
stats.increment_counter(:build_artifacts_size, 30)
@@ -48,7 +49,7 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitl
end
it 'updates the last_job_artifact_id to the ID of the last artifact from the batch' do
- expect { service.execute }.to change { refresh.reload.last_job_artifact_id.to_i }.to(artifact_2.id)
+ expect { service.execute }.to change { refresh.reload.last_job_artifact_id.to_i }.to(artifact_3.id)
end
it 'requeues the refresh job' do
@@ -62,7 +63,7 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitl
:project_build_artifacts_size_refresh,
:pending,
project: project,
- last_job_artifact_id: artifact_2.id
+ last_job_artifact_id: artifact_3.id
)
end
@@ -73,7 +74,7 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitl
end
it 'keeps the last_job_artifact_id unchanged' do
- expect(refresh.reload.last_job_artifact_id).to eq(artifact_2.id)
+ expect(refresh.reload.last_job_artifact_id).to eq(artifact_3.id)
end
it 'keeps the state of the refresh record at running' do
@@ -89,7 +90,7 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitl
project: project,
updated_at: 2.days.ago,
refresh_started_at: now,
- last_job_artifact_id: artifact_3.id
+ last_job_artifact_id: artifact_4.id
)
end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index fb94e94fd18..e547ace1d9f 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -11,8 +11,9 @@ RSpec.describe Projects::TransferService do
let(:project) { create(:project, :repository, :legacy_storage, namespace: user.namespace) }
let(:target) { group }
+ let(:executor) { user }
- subject(:execute_transfer) { described_class.new(project, user).execute(target).tap { project.reload } }
+ subject(:execute_transfer) { described_class.new(project, executor).execute(target).tap { project.reload } }
context 'with npm packages' do
before do
@@ -92,6 +93,55 @@ RSpec.describe Projects::TransferService do
end
end
+ context 'project in a group -> a personal namespace', :enable_admin_mode do
+ let(:project) { create(:project, :repository, :legacy_storage, group: group) }
+ let(:target) { user.namespace }
+ # We need to use an admin user as the executor because
+ # only an admin user has required permissions to transfer projects
+ # under _all_ the different circumstances specified below.
+ let(:executor) { create(:user, :admin) }
+
+ it 'executes the transfer to personal namespace successfully' do
+ execute_transfer
+
+ expect(project.namespace).to eq(user.namespace)
+ end
+
+ context 'the owner of the namespace does not have a direct membership in the project residing in the group' do
+ it 'creates a project membership record for the owner of the namespace, with OWNER access level, after the transfer' do
+ execute_transfer
+
+ expect(project.members.owners.find_by(user_id: user.id)).to be_present
+ end
+ end
+
+ context 'the owner of the namespace has a direct membership in the project residing in the group' do
+ context 'that membership has an access level of OWNER' do
+ before do
+ project.add_owner(user)
+ end
+
+ it 'retains the project membership record for the owner of the namespace, with OWNER access level, after the transfer' do
+ execute_transfer
+
+ expect(project.members.owners.find_by(user_id: user.id)).to be_present
+ end
+ end
+
+ context 'that membership has an access level that is not OWNER' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'updates the project membership record for the owner of the namespace, to OWNER access level, after the transfer' do
+ execute_transfer
+
+ expect(project.members.owners.find_by(user_id: user.id)).to be_present
+ end
+ end
+ end
+ end
+
context 'when transfer succeeds' do
before do
group.add_owner(user)
@@ -148,23 +198,23 @@ RSpec.describe Projects::TransferService do
context 'with a project integration' do
let_it_be_with_reload(:project) { create(:project, namespace: user.namespace) }
- let_it_be(:instance_integration) { create(:integrations_slack, :instance, webhook: 'http://project.slack.com') }
+ let_it_be(:instance_integration) { create(:integrations_slack, :instance) }
+ let_it_be(:project_integration) { create(:integrations_slack, project: project) }
- context 'with an inherited integration' do
- let_it_be(:project_integration) { create(:integrations_slack, project: project, webhook: 'http://project.slack.com', inherit_from_id: instance_integration.id) }
+ context 'when it inherits from instance_integration' do
+ before do
+ project_integration.update!(inherit_from_id: instance_integration.id, webhook: instance_integration.webhook)
+ end
it 'replaces inherited integrations', :aggregate_failures do
- execute_transfer
-
- expect(project.slack_integration.webhook).to eq(group_integration.webhook)
- expect(Integration.count).to eq(3)
+ expect { execute_transfer }
+ .to change(Integration, :count).by(0)
+ .and change { project.slack_integration.webhook }.to eq(group_integration.webhook)
end
end
context 'with a custom integration' do
- let_it_be(:project_integration) { create(:integrations_slack, project: project, webhook: 'http://project.slack.com') }
-
- it 'does not updates the integrations' do
+ it 'does not update the integrations' do
expect { execute_transfer }.not_to change { project.slack_integration.webhook }
end
end