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
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-28 18:09:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-28 18:09:19 +0300
commit24623a974348595d33cc9be6881b285a026ff13b (patch)
tree20a28aa9b423a65c52ea5ca54c6fcb91dd9ddfd6 /spec
parent72ba138510cad0a8c4819ef0512153dd4dbced7f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/projects/activity/user_sees_activity_spec.rb14
-rw-r--r--spec/features/projects/badges/coverage_spec.rb11
-rw-r--r--spec/features/projects/branches/download_buttons_spec.rb24
-rw-r--r--spec/features/projects/branches_spec.rb15
-rw-r--r--spec/features/projects/commit/builds_spec.rb4
-rw-r--r--spec/features/projects/commit/mini_pipeline_graph_spec.rb12
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb10
-rw-r--r--spec/features/projects/environments/environment_spec.rb24
-rw-r--r--spec/features/projects/environments/environments_spec.rb66
-rw-r--r--spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb3
-rw-r--r--spec/features/projects/files/download_buttons_spec.rb11
-rw-r--r--spec/features/projects/files/editing_a_file_spec.rb9
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb2
-rw-r--r--spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb23
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb16
-rw-r--r--spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb2
-rw-r--r--spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb2
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb8
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb190
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb52
-rw-r--r--spec/features/projects/releases/user_views_release_spec.rb10
-rw-r--r--spec/features/snippets/search_snippets_spec.rb2
-rw-r--r--spec/frontend/fixtures/groups.rb33
-rw-r--r--spec/frontend/groups/components/app_spec.js8
-rw-r--r--spec/frontend/groups/components/overview_tabs_spec.js67
-rw-r--r--spec/frontend/groups/service/archived_projects_service_spec.js90
-rw-r--r--spec/frontend/groups/service/groups_service_spec.js19
-rw-r--r--spec/frontend/search/mock_data.js19
-rw-r--r--spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js6
-rw-r--r--spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js4
-rw-r--r--spec/helpers/groups_helper_spec.rb1
-rw-r--r--spec/helpers/search_helper_spec.rb4
-rw-r--r--spec/lib/expand_variables_spec.rb102
-rw-r--r--spec/lib/gitlab/auth_spec.rb31
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb56
-rw-r--r--spec/lib/gitlab/legacy_github_import/client_spec.rb18
-rw-r--r--spec/requests/api/user_runners_spec.rb243
-rw-r--r--spec/requests/api/users_spec.rb165
-rw-r--r--spec/requests/openid_connect_spec.rb11
-rw-r--r--spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb28
-rw-r--r--spec/services/packages/nuget/extract_metadata_content_service_spec.rb64
-rw-r--r--spec/services/packages/nuget/extract_metadata_file_service_spec.rb100
-rw-r--r--spec/services/packages/nuget/metadata_extraction_service_spec.rb138
-rw-r--r--spec/services/packages/nuget/update_package_from_metadata_service_spec.rb2
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb32
-rw-r--r--spec/workers/packages/nuget/extraction_worker_spec.rb2
47 files changed, 1118 insertions, 637 deletions
diff --git a/spec/features/projects/activity/user_sees_activity_spec.rb b/spec/features/projects/activity/user_sees_activity_spec.rb
index 5335b9d0e95..7940ded41a9 100644
--- a/spec/features/projects/activity/user_sees_activity_spec.rb
+++ b/spec/features/projects/activity/user_sees_activity_spec.rb
@@ -10,12 +10,14 @@ RSpec.describe 'Projects > Activity > User sees activity', feature_category: :gr
before do
create(:event, :created, project: project, target: issue, author: user)
event = create(:push_event, project: project, author: user)
- create(:push_event_payload,
- event: event,
- action: :created,
- commit_to: '6d394385cf567f80a8fd85055db1ab4c5295806f',
- ref: 'fix',
- commit_count: 1)
+ create(
+ :push_event_payload,
+ event: event,
+ action: :created,
+ commit_to: '6d394385cf567f80a8fd85055db1ab4c5295806f',
+ ref: 'fix',
+ commit_count: 1
+ )
end
it 'shows the last push in the activity page', :js do
diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb
index 38a7bdf65c3..c4f20ff74b2 100644
--- a/spec/features/projects/badges/coverage_spec.rb
+++ b/spec/features/projects/badges/coverage_spec.rb
@@ -190,8 +190,15 @@ RSpec.describe 'test coverage badge', feature_category: :code_testing do
end
def show_test_coverage_badge(job: nil, min_good: nil, min_acceptable: nil, min_medium: nil)
- visit coverage_project_badges_path(project, ref: :master, job: job, min_good: min_good,
- min_acceptable: min_acceptable, min_medium: min_medium, format: :svg)
+ visit coverage_project_badges_path(
+ project,
+ ref: :master,
+ job: job,
+ min_good: min_good,
+ min_acceptable: min_acceptable,
+ min_medium: min_medium,
+ format: :svg
+ )
end
def expect_coverage_badge(coverage)
diff --git a/spec/features/projects/branches/download_buttons_spec.rb b/spec/features/projects/branches/download_buttons_spec.rb
index 2092af537e8..a888b5b977d 100644
--- a/spec/features/projects/branches/download_buttons_spec.rb
+++ b/spec/features/projects/branches/download_buttons_spec.rb
@@ -9,18 +9,24 @@ RSpec.describe 'Download buttons in branches page', feature_category: :groups_an
let(:project) { create(:project, :repository) }
let(:pipeline) do
- create(:ci_pipeline,
- project: project,
- sha: project.commit('binary-encoding').sha,
- ref: 'binary-encoding', # make sure the branch is in the 1st page!
- status: status)
+ create(
+ :ci_pipeline,
+ project: project,
+ sha: project.commit('binary-encoding').sha,
+ ref: 'binary-encoding', # make sure the branch is in the 1st page!
+ status: status
+ )
end
let!(:build) do
- create(:ci_build, :success, :artifacts,
- pipeline: pipeline,
- status: pipeline.status,
- name: 'build')
+ create(
+ :ci_build,
+ :success,
+ :artifacts,
+ pipeline: pipeline,
+ status: pipeline.status,
+ name: 'build'
+ )
end
before do
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 841a9cf78c5..50df7bb7ca5 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -95,15 +95,22 @@ RSpec.describe 'Branches', feature_category: :groups_and_projects do
it 'shows only default_per_page active branches sorted by last updated' do
visit project_branches_filtered_path(project, state: 'active')
- expect(page).to have_content(sorted_branches(repository, count: Kaminari.config.default_per_page,
- sort_by: :updated_desc, state: 'active'))
+ expect(page).to have_content(sorted_branches(
+ repository,
+ count: Kaminari.config.default_per_page,
+ sort_by: :updated_desc,
+ state: 'active'
+ ))
end
it 'shows only default_per_page branches sorted by last updated on All branches' do
visit project_branches_filtered_path(project, state: 'all')
- expect(page).to have_content(sorted_branches(repository, count: Kaminari.config.default_per_page,
- sort_by: :updated_desc))
+ expect(page).to have_content(sorted_branches(
+ repository,
+ count: Kaminari.config.default_per_page,
+ sort_by: :updated_desc
+ ))
end
end
end
diff --git a/spec/features/projects/commit/builds_spec.rb b/spec/features/projects/commit/builds_spec.rb
index dfd58a99953..54a189692ce 100644
--- a/spec/features/projects/commit/builds_spec.rb
+++ b/spec/features/projects/commit/builds_spec.rb
@@ -6,9 +6,7 @@ RSpec.describe 'project commit pipelines', :js, feature_category: :continuous_in
let(:project) { create(:project, :repository) }
before do
- create(:ci_pipeline, project: project,
- sha: project.commit.sha,
- ref: 'master')
+ create(:ci_pipeline, project: project, sha: project.commit.sha, ref: 'master')
user = create(:user)
project.add_maintainer(user)
diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
index 3611efd1477..d2104799e79 100644
--- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb
+++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
@@ -7,11 +7,13 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js, feature_category: :sou
context 'when commit has pipelines' do
let(:pipeline) do
- create(:ci_pipeline,
- status: :running,
- project: project,
- ref: project.default_branch,
- sha: project.commit.sha)
+ create(
+ :ci_pipeline,
+ status: :running,
+ project: project,
+ ref: project.default_branch,
+ sha: project.commit.sha
+ )
end
let(:build) { create(:ci_build, pipeline: pipeline, status: :running) }
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 791f626b8d9..3513e249b63 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -175,9 +175,13 @@ RSpec.describe 'User browses commits', feature_category: :source_code_management
let(:confidential_issue) { create(:issue, confidential: true, title: 'Secret issue!', project: project) }
before do
- project.repository.create_file(user, 'dummy-file', 'dummy content',
- branch_name: 'feature',
- message: "Linking #{confidential_issue.to_reference}")
+ project.repository.create_file(
+ user,
+ 'dummy-file',
+ 'dummy content',
+ branch_name: 'feature',
+ message: "Linking #{confidential_issue.to_reference}"
+ )
end
context 'when the user cannot see confidential issues but was cached with a link', :use_clean_rails_memory_store_fragment_caching do
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 0f903901984..11ea72b87a2 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -300,14 +300,12 @@ RSpec.describe 'Environment', feature_category: :groups_and_projects do
context 'with manual action' do
let(:action) do
- create(:ci_build, :manual, pipeline: pipeline,
- name: 'deploy to production', environment: environment.name)
+ create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production', environment: environment.name)
end
context 'when user has ability to trigger deployment' do
let(:permissions) do
- create(:protected_branch, :developers_can_merge,
- name: action.ref, project: project)
+ create(:protected_branch, :developers_can_merge, name: action.ref, project: project)
end
it 'does show a play button' do
@@ -331,8 +329,7 @@ RSpec.describe 'Environment', feature_category: :groups_and_projects do
context 'when user has no ability to trigger a deployment' do
let(:permissions) do
- create(:protected_branch, :no_one_can_merge,
- name: action.ref, project: project)
+ create(:protected_branch, :no_one_can_merge, name: action.ref, project: project)
end
it 'does not show a play button' do
@@ -391,10 +388,7 @@ RSpec.describe 'Environment', feature_category: :groups_and_projects do
end
let(:deployment) do
- create(:deployment, :success,
- environment: environment,
- deployable: build,
- on_stop: 'close_app')
+ create(:deployment, :success, environment: environment, deployable: build, on_stop: 'close_app')
end
context 'when user has ability to stop environment' do
@@ -411,8 +405,7 @@ RSpec.describe 'Environment', feature_category: :groups_and_projects do
context 'when user has no ability to stop environment' do
let(:permissions) do
- create(:protected_branch, :no_one_can_merge,
- name: action.ref, project: project)
+ create(:protected_branch, :no_one_can_merge, name: action.ref, project: project)
end
it 'does not allow to stop environment', :js do
@@ -445,9 +438,7 @@ RSpec.describe 'Environment', feature_category: :groups_and_projects do
describe 'environment folders', :js do
context 'when folder name contains special charaters' do
before do
- create(:environment, project: project,
- name: 'staging-1.0/review',
- state: :available)
+ create(:environment, project: project, name: 'staging-1.0/review', state: :available)
end
it 'renders a correct environment folder' do
@@ -465,8 +456,7 @@ RSpec.describe 'Environment', feature_category: :groups_and_projects do
let(:project) { create(:project, :repository) }
let!(:environment) do
- create(:environment, :with_review_app, project: project,
- ref: 'feature')
+ create(:environment, :with_review_app, project: project, ref: 'feature')
end
it 'user visits environment page', :js do
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 9f1f7d04339..3a2c7f0ac7b 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -159,9 +159,7 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
let(:project) { create(:project, :repository) }
let!(:deployment) do
- create(:deployment, :success,
- environment: environment,
- sha: project.commit.id)
+ create(:deployment, :success, environment: environment, sha: project.commit.id)
end
it 'shows deployment SHA and internal ID' do
@@ -182,10 +180,7 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
end
let!(:deployment) do
- create(:deployment, :success,
- environment: environment,
- deployable: build,
- sha: project.commit.id)
+ create(:deployment, :success, environment: environment, deployable: build, sha: project.commit.id)
end
before do
@@ -241,10 +236,7 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
end
let(:deployment) do
- create(:deployment, :success,
- environment: environment,
- deployable: build,
- on_stop: 'close_app')
+ create(:deployment, :success, environment: environment, deployable: build, on_stop: 'close_app')
end
it 'shows a stop button and dialog' do
@@ -296,18 +288,11 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
let!(:build) { create(:ci_build, pipeline: pipeline) }
let!(:delayed_job) do
- create(:ci_build, :scheduled,
- pipeline: pipeline,
- name: 'delayed job',
- stage: 'test')
+ create(:ci_build, :scheduled, pipeline: pipeline, name: 'delayed job', stage: 'test')
end
let!(:deployment) do
- create(:deployment,
- :success,
- environment: environment,
- deployable: build,
- sha: project.commit.id)
+ create(:deployment, :success, environment: environment, deployable: build, sha: project.commit.id)
end
before do
@@ -327,10 +312,7 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
context 'when delayed job is expired already' do
let!(:delayed_job) do
- create(:ci_build, :expired_scheduled,
- pipeline: pipeline,
- name: 'delayed job',
- stage: 'test')
+ create(:ci_build, :expired_scheduled, pipeline: pipeline, name: 'delayed job', stage: 'test')
end
it "shows 00:00:00 as the remaining time" do
@@ -365,9 +347,7 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
let(:project) { create(:project, :repository) }
let!(:deployment) do
- create(:deployment, :failed,
- environment: environment,
- sha: project.commit.id)
+ create(:deployment, :failed, environment: environment, sha: project.commit.id)
end
it 'does not show deployments', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/409990' do
@@ -382,9 +362,7 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
let_it_be(:project) { create(:project, :repository) }
let!(:deployment) do
- create(:deployment, :running,
- environment: environment,
- sha: project.commit.id)
+ create(:deployment, :running, environment: environment, sha: project.commit.id)
end
it "renders the upcoming deployment", :aggregate_failures do
@@ -443,14 +421,8 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
describe 'environments folders' do
describe 'available environments' do
before do
- create(:environment, :will_auto_stop,
- project: project,
- name: 'staging/review-1',
- state: :available)
- create(:environment, :will_auto_stop,
- project: project,
- name: 'staging/review-2',
- state: :available)
+ create(:environment, :will_auto_stop, project: project, name: 'staging/review-1', state: :available)
+ create(:environment, :will_auto_stop, project: project, name: 'staging/review-2', state: :available)
end
it 'users unfurls an environment folder' do
@@ -470,14 +442,8 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
describe 'stopped environments' do
before do
- create(:environment, :will_auto_stop,
- project: project,
- name: 'staging/review-1',
- state: :stopped)
- create(:environment, :will_auto_stop,
- project: project,
- name: 'staging/review-2',
- state: :stopped)
+ create(:environment, :will_auto_stop, project: project, name: 'staging/review-1', state: :stopped)
+ create(:environment, :will_auto_stop, project: project, name: 'staging/review-2', state: :stopped)
end
it 'users unfurls an environment folder' do
@@ -497,12 +463,8 @@ RSpec.describe 'Environments page', :js, feature_category: :continuous_delivery
describe 'environments folders view' do
before do
- create(:environment, project: project,
- name: 'staging.review/review-1',
- state: :available)
- create(:environment, project: project,
- name: 'staging.review/review-2',
- state: :available)
+ create(:environment, project: project, name: 'staging.review/review-1', state: :available)
+ create(:environment, project: project, name: 'staging.review/review-2', state: :available)
end
it 'user opens folder view' do
diff --git a/spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb b/spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb
index 852d7bca96a..2c8d7275fbf 100644
--- a/spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb
+++ b/spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb
@@ -9,8 +9,7 @@ RSpec.describe 'User deletes feature flag', :js, feature_category: :feature_flag
let(:project) { create(:project, namespace: user.namespace) }
let!(:feature_flag) do
- create_flag(project, 'ci_live_trace', false,
- description: 'For live trace feature')
+ create_flag(project, 'ci_live_trace', false, description: 'For live trace feature')
end
before do
diff --git a/spec/features/projects/files/download_buttons_spec.rb b/spec/features/projects/files/download_buttons_spec.rb
index 9b3d19cfea3..81bd0523c70 100644
--- a/spec/features/projects/files/download_buttons_spec.rb
+++ b/spec/features/projects/files/download_buttons_spec.rb
@@ -7,18 +7,11 @@ RSpec.describe 'Projects > Files > Download buttons in files tree', feature_cate
let(:user) { project.creator }
let(:pipeline) do
- create(:ci_pipeline,
- project: project,
- sha: project.commit.sha,
- ref: project.default_branch,
- status: 'success')
+ create(:ci_pipeline, project: project, sha: project.commit.sha, ref: project.default_branch, status: 'success')
end
let!(:build) do
- create(:ci_build, :success, :artifacts,
- pipeline: pipeline,
- status: pipeline.status,
- name: 'build')
+ create(:ci_build, :success, :artifacts, pipeline: pipeline, status: pipeline.status, name: 'build')
end
before do
diff --git a/spec/features/projects/files/editing_a_file_spec.rb b/spec/features/projects/files/editing_a_file_spec.rb
index b4edd5c2729..6efe1eb1ad1 100644
--- a/spec/features/projects/files/editing_a_file_spec.rb
+++ b/spec/features/projects/files/editing_a_file_spec.rb
@@ -13,16 +13,14 @@ RSpec.describe 'Projects > Files > User wants to edit a file', feature_category:
commit_message: "Committing First Update",
file_path: ".gitignore",
file_content: "First Update",
- last_commit_sha: Gitlab::Git::Commit.last_for_path(project.repository, project.default_branch,
- ".gitignore").sha
+ last_commit_sha: Gitlab::Git::Commit.last_for_path(project.repository, project.default_branch, ".gitignore").sha
}
end
context 'when the user has write access' do
before do
sign_in user
- visit project_edit_blob_path(project,
- File.join(project.default_branch, '.gitignore'))
+ visit project_edit_blob_path(project, File.join(project.default_branch, '.gitignore'))
end
it 'file has been updated since the user opened the edit page' do
@@ -43,8 +41,7 @@ RSpec.describe 'Projects > Files > User wants to edit a file', feature_category:
before do
forked_project
sign_in user
- visit project_edit_blob_path(project,
- File.join(project.default_branch, '.gitignore'))
+ visit project_edit_blob_path(project, File.join(project.default_branch, '.gitignore'))
end
context 'and the forked project is ahead of the upstream project' do
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index bfe1fd073c5..c8543764d15 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > Project owner sees a link to create a license file in empty project', :js,
-feature_category: :groups_and_projects do
+ feature_category: :groups_and_projects do
include Features::WebIdeSpecHelpers
let(:project) { create(:project_empty_repo) }
diff --git a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb
index 645bfeb14e3..37b718061c6 100644
--- a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb
+++ b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
# This is a regression test for https://gitlab.com/gitlab-org/gitlab-foss/issues/37569
RSpec.describe 'Projects > Files > User browses a tree with a folder containing only a folder', :js,
-feature_category: :groups_and_projects do
+ feature_category: :groups_and_projects do
let(:project) { create(:project, :empty_repo) }
let(:user) { project.first_owner }
diff --git a/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb b/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb
index 3d40bae8544..bf1b2f7e5cd 100644
--- a/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb
+++ b/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb
@@ -8,26 +8,19 @@ RSpec.describe 'viewing an issue with cross project references' do
let(:user) { create(:user) }
let(:other_project) do
- create(:project, :public,
- external_authorization_classification_label: 'other_label')
+ create(:project, :public, external_authorization_classification_label: 'other_label')
end
let(:other_issue) do
- create(:issue, :closed,
- title: 'I am in another project',
- project: other_project)
+ create(:issue, :closed, title: 'I am in another project', project: other_project)
end
let(:other_confidential_issue) do
- create(:issue, :confidential, :closed,
- title: 'I am in another project and confidential',
- project: other_project)
+ create(:issue, :confidential, :closed, title: 'I am in another project and confidential', project: other_project)
end
let(:other_merge_request) do
- create(:merge_request, :closed,
- title: 'I am a merge request in another project',
- source_project: other_project)
+ create(:merge_request, :closed, title: 'I am a merge request in another project', source_project: other_project)
end
let(:description_referencing_other_issue) do
@@ -39,15 +32,11 @@ RSpec.describe 'viewing an issue with cross project references' do
let(:project) { create(:project) }
let(:issue) do
- create(:issue,
- project: project,
- description: description_referencing_other_issue)
+ create(:issue, project: project, description: description_referencing_other_issue)
end
let(:confidential_issue) do
- create(:issue, :confidential, :closed,
- title: "I am in the same project and confidential",
- project: project)
+ create(:issue, :confidential, :closed, title: "I am in the same project and confidential", project: project)
end
before do
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index aeba53c22b6..77f95827d88 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -79,8 +79,7 @@ RSpec.describe 'User browses jobs', feature_category: :groups_and_projects do
context 'when a job can be retried' do
let!(:job) do
- create(:ci_build, pipeline: pipeline,
- stage: 'test')
+ create(:ci_build, pipeline: pipeline, stage: 'test')
end
before do
@@ -148,10 +147,7 @@ RSpec.describe 'User browses jobs', feature_category: :groups_and_projects do
context 'with downloadable artifacts' do
let!(:with_artifacts) do
- build = create(:ci_build, :success,
- pipeline: pipeline,
- name: 'rspec tests',
- stage: 'test')
+ build = create(:ci_build, :success, pipeline: pipeline, name: 'rspec tests', stage: 'test')
create(:ci_job_artifact, :archive, job: build)
end
@@ -167,10 +163,7 @@ RSpec.describe 'User browses jobs', feature_category: :groups_and_projects do
context 'with artifacts expired' do
let!(:with_artifacts_expired) do
- create(:ci_build, :expired, :success,
- pipeline: pipeline,
- name: 'rspec',
- stage: 'test')
+ create(:ci_build, :expired, :success, pipeline: pipeline, name: 'rspec', stage: 'test')
end
before do
@@ -188,8 +181,7 @@ RSpec.describe 'User browses jobs', feature_category: :groups_and_projects do
context 'column links' do
let!(:job) do
- create(:ci_build, pipeline: pipeline,
- stage: 'test')
+ create(:ci_build, pipeline: pipeline, stage: 'test')
end
before do
diff --git a/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb b/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb
index 6656ca3ef18..2780326cd35 100644
--- a/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb
+++ b/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > Group member cannot request access to their group project',
-feature_category: :groups_and_projects do
+ feature_category: :groups_and_projects do
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:project) { create(:project, namespace: group) }
diff --git a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb
index 9db34cee5d6..47cd0d612b5 100644
--- a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb
+++ b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > Group requester cannot request access to project', :js,
-feature_category: :groups_and_projects do
+ feature_category: :groups_and_projects do
let(:user) { create(:user) }
let(:owner) { create(:user) }
let(:group) { create(:group, :public) }
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index 6f76424e377..9af36b4b2a9 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -38,9 +38,11 @@ RSpec.describe 'Projects > Members > User requests access', :js, feature_categor
context 'code access is restricted' do
it 'user can request access' do
- project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE,
- builds_access_level: ProjectFeature::PRIVATE,
- merge_requests_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(
+ repository_access_level: ProjectFeature::PRIVATE,
+ builds_access_level: ProjectFeature::PRIVATE,
+ merge_requests_access_level: ProjectFeature::PRIVATE
+ )
visit project_path(project)
expect(page).to have_content 'Request Access'
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 1f60996fac8..aeb01603872 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -21,42 +21,39 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
let!(:external_stage) { create(:ci_stage, name: 'external', pipeline: pipeline) }
let!(:build_passed) do
- create(:ci_build, :success,
- pipeline: pipeline, stage: 'build', stage_idx: 0, name: 'build')
+ create(:ci_build, :success, pipeline: pipeline, stage: 'build', stage_idx: 0, name: 'build')
end
let!(:build_failed) do
- create(:ci_build, :failed,
- pipeline: pipeline, stage: 'test', stage_idx: 1, name: 'test')
+ create(:ci_build, :failed, pipeline: pipeline, stage: 'test', stage_idx: 1, name: 'test')
end
let!(:build_preparing) do
- create(:ci_build, :preparing,
- pipeline: pipeline, stage: 'deploy', stage_idx: 2, name: 'prepare')
+ create(:ci_build, :preparing, pipeline: pipeline, stage: 'deploy', stage_idx: 2, name: 'prepare')
end
let!(:build_running) do
- create(:ci_build, :running,
- pipeline: pipeline, stage: 'deploy', stage_idx: 3, name: 'deploy')
+ create(:ci_build, :running, pipeline: pipeline, stage: 'deploy', stage_idx: 3, name: 'deploy')
end
let!(:build_manual) do
- create(:ci_build, :manual,
- pipeline: pipeline, stage: 'deploy', stage_idx: 3, name: 'manual-build')
+ create(:ci_build, :manual, pipeline: pipeline, stage: 'deploy', stage_idx: 3, name: 'manual-build')
end
let!(:build_scheduled) do
- create(:ci_build, :scheduled,
- pipeline: pipeline, stage: 'deploy', stage_idx: 3, name: 'delayed-job')
+ create(:ci_build, :scheduled, pipeline: pipeline, stage: 'deploy', stage_idx: 3, name: 'delayed-job')
end
let!(:build_external) do
- create(:generic_commit_status, status: 'success',
- pipeline: pipeline,
- name: 'jenkins',
- ci_stage: external_stage,
- ref: 'master',
- target_url: 'http://gitlab.com/status')
+ create(
+ :generic_commit_status,
+ status: 'success',
+ pipeline: pipeline,
+ name: 'jenkins',
+ ci_stage: external_stage,
+ ref: 'master',
+ target_url: 'http://gitlab.com/status'
+ )
end
end
@@ -127,13 +124,16 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
describe 'pipeline stats text' do
let(:finished_pipeline) do
- create(:ci_pipeline, :success, project: project,
- ref: 'master', sha: project.commit.id, user: user)
+ create(:ci_pipeline, :success, project: project, ref: 'master', sha: project.commit.id, user: user)
end
before do
- finished_pipeline.update!(started_at: "2023-01-01 01:01:05", created_at: "2023-01-01 01:01:01",
- finished_at: "2023-01-01 01:01:10", duration: 9)
+ finished_pipeline.update!(
+ started_at: "2023-01-01 01:01:05",
+ created_at: "2023-01-01 01:01:01",
+ finished_at: "2023-01-01 01:01:10",
+ duration: 9
+ )
end
context 'pipeline has finished' do
@@ -332,13 +332,15 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
context 'when pipeline has a downstream pipeline' do
let(:downstream_project) { create(:project, :repository, group: group) }
let(:downstream_pipeline) do
- create(:ci_pipeline,
- status,
- user: user,
- project: downstream_project,
- ref: 'master',
- sha: downstream_project.commit.id,
- child_of: pipeline)
+ create(
+ :ci_pipeline,
+ status,
+ user: user,
+ project: downstream_project,
+ ref: 'master',
+ sha: downstream_project.commit.id,
+ child_of: pipeline
+ )
end
let!(:build) { create(:ci_build, status, pipeline: downstream_pipeline, user: user) }
@@ -585,10 +587,13 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
context 'when pipeline ref does not exist in repository anymore' do
let(:pipeline) do
- create(:ci_empty_pipeline, project: project,
- ref: 'non-existent',
- sha: project.commit.id,
- user: user)
+ create(
+ :ci_empty_pipeline,
+ project: project,
+ ref: 'non-existent',
+ sha: project.commit.id,
+ user: user
+ )
end
before do
@@ -612,10 +617,12 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
let(:target_project) { project }
let(:merge_request) do
- create(:merge_request,
+ create(
+ :merge_request,
:with_detached_merge_request_pipeline,
source_project: source_project,
- target_project: target_project)
+ target_project: target_project
+ )
end
let(:pipeline) do
@@ -788,17 +795,23 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
let(:downstream) { create(:project, :repository) }
let(:pipeline) do
- create(:ci_pipeline, project: project,
- ref: 'master',
- sha: project.commit.id,
- user: user)
+ create(
+ :ci_pipeline,
+ project: project,
+ ref: 'master',
+ sha: project.commit.id,
+ user: user
+ )
end
let!(:bridge) do
- create(:ci_bridge, pipeline: pipeline,
- name: 'cross-build',
- user: user,
- downstream: downstream)
+ create(
+ :ci_bridge,
+ pipeline: pipeline,
+ name: 'cross-build',
+ user: user,
+ downstream: downstream
+ )
end
describe 'GET /:project/-/pipelines/:id' do
@@ -866,13 +879,20 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
let(:resource_group) { create(:ci_resource_group, project: project) }
let!(:test_job) do
- create(:ci_build, :pending, stage: 'test', name: 'test',
- stage_idx: 1, pipeline: pipeline, project: project)
+ create(:ci_build, :pending, stage: 'test', name: 'test', stage_idx: 1, pipeline: pipeline, project: project)
end
let!(:deploy_job) do
- create(:ci_build, :created, stage: 'deploy', name: 'deploy',
- stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group)
+ create(
+ :ci_build,
+ :created,
+ stage: 'deploy',
+ name: 'deploy',
+ stage_idx: 2,
+ pipeline: pipeline,
+ project: project,
+ resource_group: resource_group
+ )
end
describe 'GET /:project/-/pipelines/:id' do
@@ -1131,8 +1151,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
context 'when user does have permission to retry build' do
before do
- create(:protected_branch, :developers_can_merge,
- name: pipeline.ref, project: project)
+ create(:protected_branch, :developers_can_merge, name: pipeline.ref, project: project)
end
it 'shows retry button for failed build' do
@@ -1239,11 +1258,13 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
include_context 'pipeline builds'
let(:pipeline) do
- create(:ci_pipeline,
- project: project,
- ref: 'master',
- sha: project.commit.id,
- user: user)
+ create(
+ :ci_pipeline,
+ project: project,
+ ref: 'master',
+ sha: project.commit.id,
+ user: user
+ )
end
before do
@@ -1259,12 +1280,14 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
context 'when pipeline has configuration errors' do
let(:pipeline) do
- create(:ci_pipeline,
- :invalid,
- project: project,
- ref: 'master',
- sha: project.commit.id,
- user: user)
+ create(
+ :ci_pipeline,
+ :invalid,
+ project: project,
+ ref: 'master',
+ sha: project.commit.id,
+ user: user
+ )
end
before do
@@ -1302,10 +1325,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
context 'when pipeline is stuck' do
let(:pipeline) do
- create(:ci_pipeline,
- project: project,
- status: :created,
- user: user)
+ create(:ci_pipeline, project: project, status: :created, user: user)
end
before do
@@ -1325,12 +1345,14 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
let(:project) { create(:project, :repository, auto_devops_attributes: { enabled: true }) }
let(:pipeline) do
- create(:ci_pipeline,
- :auto_devops_source,
- project: project,
- ref: 'master',
- sha: project.commit.id,
- user: user)
+ create(
+ :ci_pipeline,
+ :auto_devops_source,
+ project: project,
+ ref: 'master',
+ sha: project.commit.id,
+ user: user
+ )
end
before do
@@ -1348,21 +1370,25 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
include_context 'pipeline builds'
let(:pipeline) do
- create(:ci_pipeline,
- source: :merge_request_event,
- project: merge_request.source_project,
- ref: 'feature',
- sha: merge_request.diff_head_sha,
- user: user,
- merge_request: merge_request)
+ create(
+ :ci_pipeline,
+ source: :merge_request_event,
+ project: merge_request.source_project,
+ ref: 'feature',
+ sha: merge_request.diff_head_sha,
+ user: user,
+ merge_request: merge_request
+ )
end
let(:merge_request) do
- create(:merge_request,
- source_project: project,
- source_branch: 'feature',
- target_project: project,
- target_branch: 'master')
+ create(
+ :merge_request,
+ source_project: project,
+ source_branch: 'feature',
+ target_project: project,
+ target_branch: 'master'
+ )
end
before do
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index c47c9c75f91..25eddf64f99 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -105,8 +105,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
context 'when pipeline is cancelable' do
let!(:build) do
- create(:ci_build, pipeline: pipeline,
- stage: 'test')
+ create(:ci_build, pipeline: pipeline, stage: 'test')
end
before do
@@ -135,8 +134,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
context 'when pipeline is retryable', :sidekiq_might_not_need_inline do
let!(:build) do
- create(:ci_build, pipeline: pipeline,
- stage: 'test')
+ create(:ci_build, pipeline: pipeline, stage: 'test')
end
before do
@@ -164,10 +162,12 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
context 'when pipeline is detached merge request pipeline' do
let(:merge_request) do
- create(:merge_request,
- :with_detached_merge_request_pipeline,
- source_project: source_project,
- target_project: target_project)
+ create(
+ :merge_request,
+ :with_detached_merge_request_pipeline,
+ source_project: source_project,
+ target_project: target_project
+ )
end
let!(:pipeline) { merge_request.all_pipelines.first }
@@ -183,8 +183,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
within '.pipeline-tags' do
expect(page).to have_content(expected_detached_mr_tag)
- expect(page).to have_link(merge_request.iid,
- href: project_merge_request_path(project, merge_request))
+ expect(page).to have_link(merge_request.iid, href: project_merge_request_path(project, merge_request))
expect(page).not_to have_link(pipeline.ref)
end
@@ -202,11 +201,13 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
context 'when pipeline is merge request pipeline' do
let(:merge_request) do
- create(:merge_request,
- :with_merge_request_pipeline,
- source_project: source_project,
- target_project: target_project,
- merge_sha: target_project.commit.sha)
+ create(
+ :merge_request,
+ :with_merge_request_pipeline,
+ source_project: source_project,
+ target_project: target_project,
+ merge_sha: target_project.commit.sha
+ )
end
let!(:pipeline) { merge_request.all_pipelines.first }
@@ -222,8 +223,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
within '.pipeline-tags' do
expect(page).not_to have_content(expected_detached_mr_tag)
- expect(page).to have_link(merge_request.iid,
- href: project_merge_request_path(project, merge_request))
+ expect(page).to have_link(merge_request.iid, href: project_merge_request_path(project, merge_request))
expect(page).not_to have_link(pipeline.ref)
end
@@ -520,9 +520,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
context 'mini pipeline graph' do
let!(:build) do
- create(:ci_build, :pending, pipeline: pipeline,
- stage: 'build',
- name: 'build')
+ create(:ci_build, :pending, pipeline: pipeline, stage: 'build', name: 'build')
end
dropdown_selector = '[data-testid="mini-pipeline-graph-dropdown"]'
@@ -554,9 +552,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
context 'for a failed pipeline' do
let!(:build) do
- create(:ci_build, :failed, pipeline: pipeline,
- stage: 'build',
- name: 'build')
+ create(:ci_build, :failed, pipeline: pipeline, stage: 'build', name: 'build')
end
it 'displays the failure reason' do
@@ -624,10 +620,12 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
let(:project) { create(:project, :repository) }
let(:pipeline) do
- create(:ci_empty_pipeline,
- project: project,
- sha: project.commit.id,
- user: user)
+ create(
+ :ci_empty_pipeline,
+ project: project,
+ sha: project.commit.id,
+ user: user
+ )
end
let(:external_stage) { create(:ci_stage, name: 'external', pipeline: pipeline) }
diff --git a/spec/features/projects/releases/user_views_release_spec.rb b/spec/features/projects/releases/user_views_release_spec.rb
index efa0ebd761d..282b8958814 100644
--- a/spec/features/projects/releases/user_views_release_spec.rb
+++ b/spec/features/projects/releases/user_views_release_spec.rb
@@ -7,10 +7,12 @@ RSpec.describe 'User views Release', :js, feature_category: :continuous_delivery
let(:user) { create(:user) }
let(:release) do
- create(:release,
- project: project,
- name: 'The first release',
- description: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)')
+ create(
+ :release,
+ project: project,
+ name: 'The first release',
+ description: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)'
+ )
end
before do
diff --git a/spec/features/snippets/search_snippets_spec.rb b/spec/features/snippets/search_snippets_spec.rb
index 98842f54015..66c4041241c 100644
--- a/spec/features/snippets/search_snippets_spec.rb
+++ b/spec/features/snippets/search_snippets_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Search Snippets', :js, feature_category: :source_code_management
visit dashboard_snippets_path
submit_search('Middle')
- select_search_scope('Titles and Descriptions')
+ select_search_scope(_("Snippets"))
expect(page).to have_link(public_snippet.title)
expect(page).to have_link(private_snippet.title)
diff --git a/spec/frontend/fixtures/groups.rb b/spec/frontend/fixtures/groups.rb
index 9c22ff176ff..e69287c879b 100644
--- a/spec/frontend/fixtures/groups.rb
+++ b/spec/frontend/fixtures/groups.rb
@@ -2,24 +2,39 @@
require 'spec_helper'
-RSpec.describe 'Groups (JavaScript fixtures)', type: :controller do
+RSpec.describe 'Groups (JavaScript fixtures)', feature_category: :groups_and_projects do
+ include ApiHelpers
include JavaScriptFixturesHelpers
- let(:user) { create(:user) }
- let(:group) { create(:group, name: 'frontend-fixtures-group', runners_token: 'runnerstoken:intabulasreferre') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, name: 'frontend-fixtures-group', runners_token: 'runnerstoken:intabulasreferre') }
+ let_it_be(:projects) { create_list(:project, 2, namespace: group) }
- before do
- group.add_owner(user)
- sign_in(user)
- end
+ describe GroupsController, '(JavaScript fixtures)', type: :controller do
+ render_views
- render_views
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
- describe GroupsController, '(JavaScript fixtures)', type: :controller do
it 'groups/edit.html' do
get :edit, params: { id: group }
expect(response).to be_successful
end
end
+
+ describe API::Groups, '(JavaScript fixtures)', type: :request do
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'api/groups/projects/get.json' do
+ get api("/groups/#{group.id}/projects", user)
+
+ expect(response).to be_successful
+ end
+ end
end
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index b474745790e..e32c50db8bf 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -93,10 +93,9 @@ describe('AppComponent', () => {
page: 2,
filterGroupsBy: 'git',
sortBy: 'created_desc',
- archived: true,
})
.then(() => {
- expect(getGroupsSpy).toHaveBeenCalledWith(1, 2, 'git', 'created_desc', true);
+ expect(getGroupsSpy).toHaveBeenCalledWith(1, 2, 'git', 'created_desc');
});
});
@@ -154,7 +153,6 @@ describe('AppComponent', () => {
filterGroupsBy: 'foobar',
sortBy: null,
updatePagination: true,
- archived: null,
});
return fetchPromise.then(() => {
expect(vm.updateGroups).toHaveBeenCalledWith(mockSearchedGroups, true);
@@ -177,7 +175,6 @@ describe('AppComponent', () => {
page: 2,
filterGroupsBy: null,
sortBy: null,
- archived: true,
});
expect(vm.isLoading).toBe(true);
@@ -186,7 +183,6 @@ describe('AppComponent', () => {
filterGroupsBy: null,
sortBy: null,
updatePagination: true,
- archived: true,
});
return fetchPagePromise.then(() => {
@@ -471,7 +467,7 @@ describe('AppComponent', () => {
it('calls API with expected params', () => {
emitFetchFilteredAndSortedGroups();
- expect(getGroupsSpy).toHaveBeenCalledWith(undefined, undefined, search, sort, undefined);
+ expect(getGroupsSpy).toHaveBeenCalledWith(undefined, undefined, search, sort);
});
it('updates pagination', () => {
diff --git a/spec/frontend/groups/components/overview_tabs_spec.js b/spec/frontend/groups/components/overview_tabs_spec.js
index ca852f398d0..8db69295ac4 100644
--- a/spec/frontend/groups/components/overview_tabs_spec.js
+++ b/spec/frontend/groups/components/overview_tabs_spec.js
@@ -10,26 +10,29 @@ import SharedProjectsEmptyState from '~/groups/components/empty_states/shared_pr
import ArchivedProjectsEmptyState from '~/groups/components/empty_states/archived_projects_empty_state.vue';
import GroupsStore from '~/groups/store/groups_store';
import GroupsService from '~/groups/service/groups_service';
+import ArchivedProjectsService from '~/groups/service/archived_projects_service';
import { createRouter } from '~/groups/init_overview_tabs';
import eventHub from '~/groups/event_hub';
import {
ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
ACTIVE_TAB_SHARED,
ACTIVE_TAB_ARCHIVED,
- OVERVIEW_TABS_SORTING_ITEMS,
+ SORTING_ITEM_NAME,
+ SORTING_ITEM_UPDATED,
+ SORTING_ITEM_STARS,
} from '~/groups/constants';
import axios from '~/lib/utils/axios_utils';
import waitForPromises from 'helpers/wait_for_promises';
Vue.component('GroupFolder', GroupFolderComponent);
const router = createRouter();
-const [SORTING_ITEM_NAME, , SORTING_ITEM_UPDATED] = OVERVIEW_TABS_SORTING_ITEMS;
describe('OverviewTabs', () => {
let wrapper;
let axiosMock;
const defaultProvide = {
+ groupId: '1',
endpoints: {
subgroups_and_projects: '/groups/foobar/-/children.json',
shared: '/groups/foobar/-/shared_projects.json',
@@ -92,7 +95,10 @@ describe('OverviewTabs', () => {
expect(tabPanel.findComponent(GroupsApp).props()).toMatchObject({
action: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
store: new GroupsStore({ showSchemaMarkup: true }),
- service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
+ service: new GroupsService(
+ defaultProvide.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS],
+ defaultProvide.initialSort,
+ ),
});
await waitForPromises();
@@ -115,7 +121,10 @@ describe('OverviewTabs', () => {
expect(tabPanel.findComponent(GroupsApp).props()).toMatchObject({
action: ACTIVE_TAB_SHARED,
store: new GroupsStore(),
- service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SHARED]),
+ service: new GroupsService(
+ defaultProvide.endpoints[ACTIVE_TAB_SHARED],
+ defaultProvide.initialSort,
+ ),
});
expect(tabPanel.vm.$attrs.lazy).toBe(false);
@@ -140,7 +149,7 @@ describe('OverviewTabs', () => {
expect(tabPanel.findComponent(GroupsApp).props()).toMatchObject({
action: ACTIVE_TAB_ARCHIVED,
store: new GroupsStore(),
- service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_ARCHIVED]),
+ service: new ArchivedProjectsService(defaultProvide.groupId, defaultProvide.initialSort),
});
expect(tabPanel.vm.$attrs.lazy).toBe(false);
@@ -219,7 +228,7 @@ describe('OverviewTabs', () => {
it(`pushes expected route when ${tabToClick} tab is clicked`, async () => {
await findTab(tabToClick).trigger('click');
- expect(routerMock.push).toHaveBeenCalledWith(expectedRoute);
+ expect(routerMock.push).toHaveBeenCalledWith(expect.objectContaining(expectedRoute));
});
});
@@ -304,6 +313,52 @@ describe('OverviewTabs', () => {
sharedAssertions({ search: '', sort: SORTING_ITEM_UPDATED.asc });
});
+ describe('when tab is changed', () => {
+ describe('when selected sort is supported', () => {
+ beforeEach(async () => {
+ await createComponent({
+ route: {
+ name: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
+ params: { group: 'foo/bar/baz' },
+ query: { sort: SORTING_ITEM_NAME.asc },
+ },
+ });
+ });
+
+ it('adds sort query string', async () => {
+ await findTab(OverviewTabs.i18n[ACTIVE_TAB_ARCHIVED]).trigger('click');
+
+ expect(routerMock.push).toHaveBeenCalledWith(
+ expect.objectContaining({
+ query: { sort: SORTING_ITEM_NAME.asc },
+ }),
+ );
+ });
+ });
+
+ describe('when selected sort is not supported', () => {
+ beforeEach(async () => {
+ await createComponent({
+ route: {
+ name: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
+ params: { group: 'foo/bar/baz' },
+ query: { sort: SORTING_ITEM_STARS.asc },
+ },
+ });
+ });
+
+ it('defaults to sorting by name', async () => {
+ await findTab(OverviewTabs.i18n[ACTIVE_TAB_ARCHIVED]).trigger('click');
+
+ expect(routerMock.push).toHaveBeenCalledWith(
+ expect.objectContaining({
+ query: { sort: SORTING_ITEM_NAME.asc },
+ }),
+ );
+ });
+ });
+ });
+
describe('when sort direction is changed', () => {
beforeEach(async () => {
await setup();
diff --git a/spec/frontend/groups/service/archived_projects_service_spec.js b/spec/frontend/groups/service/archived_projects_service_spec.js
new file mode 100644
index 00000000000..3aec9d57ee1
--- /dev/null
+++ b/spec/frontend/groups/service/archived_projects_service_spec.js
@@ -0,0 +1,90 @@
+import projects from 'test_fixtures/api/groups/projects/get.json';
+import ArchivedProjectsService from '~/groups/service/archived_projects_service';
+import Api from '~/api';
+
+jest.mock('~/api');
+
+describe('ArchivedProjectsService', () => {
+ const groupId = 1;
+ let service;
+
+ beforeEach(() => {
+ service = new ArchivedProjectsService(groupId, 'name_asc');
+ });
+
+ describe('getGroups', () => {
+ const headers = { 'x-next-page': '2', 'x-page': '1', 'x-per-page': '20' };
+ const page = 2;
+ const query = 'git';
+ const sort = 'created_asc';
+
+ beforeEach(() => {
+ Api.groupProjects.mockResolvedValueOnce({ data: projects, headers });
+ });
+
+ it('returns promise the resolves with formatted project', async () => {
+ await expect(service.getGroups(undefined, page, query, sort)).resolves.toEqual({
+ data: projects.map((project) => {
+ return {
+ id: project.id,
+ name: project.name,
+ full_name: project.name_with_namespace,
+ markdown_description: project.description_html,
+ visibility: project.visibility,
+ avatar_url: project.avatar_url,
+ relative_path: `/${project.path_with_namespace}`,
+ edit_path: null,
+ leave_path: null,
+ can_edit: false,
+ can_leave: false,
+ can_remove: false,
+ type: 'project',
+ permission: null,
+ children: [],
+ parent_id: project.namespace.id,
+ project_count: 0,
+ subgroup_count: 0,
+ number_users_with_delimiter: 0,
+ star_count: project.star_count,
+ updated_at: project.updated_at,
+ marked_for_deletion: project.marked_for_deletion_at !== null,
+ last_activity_at: project.last_activity_at,
+ };
+ }),
+ headers,
+ });
+
+ expect(Api.groupProjects).toHaveBeenCalledWith(groupId, query, {
+ archived: true,
+ page,
+ order_by: 'created_at',
+ sort: 'asc',
+ });
+ });
+
+ describe.each`
+ sortArgument | expectedOrderByParameter | expectedSortParameter
+ ${'name_asc'} | ${'name'} | ${'asc'}
+ ${'name_desc'} | ${'name'} | ${'desc'}
+ ${'created_asc'} | ${'created_at'} | ${'asc'}
+ ${'created_desc'} | ${'created_at'} | ${'desc'}
+ ${'latest_activity_asc'} | ${'last_activity_at'} | ${'asc'}
+ ${'latest_activity_desc'} | ${'last_activity_at'} | ${'desc'}
+ ${undefined} | ${'name'} | ${'asc'}
+ `(
+ 'when the sort argument is $sortArgument',
+ ({ sortArgument, expectedSortParameter, expectedOrderByParameter }) => {
+ it(`calls the API with sort parameter set to ${expectedSortParameter} and order_by parameter set to ${expectedOrderByParameter}`, () => {
+ service.getGroups(undefined, page, query, sortArgument);
+
+ expect(Api.groupProjects).toHaveBeenCalledWith(groupId, query, {
+ archived: true,
+ page,
+ order_by: expectedOrderByParameter,
+ sort: expectedSortParameter,
+ });
+ });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/groups/service/groups_service_spec.js b/spec/frontend/groups/service/groups_service_spec.js
index e037a6df1e2..ef0a7fde70a 100644
--- a/spec/frontend/groups/service/groups_service_spec.js
+++ b/spec/frontend/groups/service/groups_service_spec.js
@@ -7,7 +7,7 @@ describe('GroupsService', () => {
let service;
beforeEach(() => {
- service = new GroupsService(mockEndpoint);
+ service = new GroupsService(mockEndpoint, 'created_asc');
});
describe('getGroups', () => {
@@ -17,17 +17,28 @@ describe('GroupsService', () => {
page: 2,
filter: 'git',
sort: 'created_asc',
- archived: true,
};
- service.getGroups(55, 2, 'git', 'created_asc', true);
+ service.getGroups(55, 2, 'git', 'created_asc');
expect(axios.get).toHaveBeenCalledWith(mockEndpoint, { params: { parent_id: 55 } });
- service.getGroups(null, 2, 'git', 'created_asc', true);
+ service.getGroups(null, 2, 'git', 'created_asc');
expect(axios.get).toHaveBeenCalledWith(mockEndpoint, { params });
});
+
+ describe('when sort argument is undefined', () => {
+ it('calls API with `initialSort` argument', () => {
+ jest.spyOn(axios, 'get').mockResolvedValue();
+
+ service.getGroups(undefined, 2, 'git', undefined);
+
+ expect(axios.get).toHaveBeenCalledWith(mockEndpoint, {
+ params: { sort: 'created_asc', filter: 'git', page: 2 },
+ });
+ });
+ });
});
describe('leaveGroup', () => {
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js
index 7cf8633d749..eb57deb46b1 100644
--- a/spec/frontend/search/mock_data.js
+++ b/spec/frontend/search/mock_data.js
@@ -132,6 +132,13 @@ export const MOCK_NAVIGATION = {
active: true,
count: '2,430',
},
+ epics: {
+ label: 'Epics',
+ scope: 'epics',
+ link: '/search?scope=epics&search=et',
+ active: true,
+ count: '0',
+ },
merge_requests: {
label: 'Merge requests',
scope: 'merge_requests',
@@ -496,6 +503,14 @@ export const MOCK_NAVIGATION_ITEMS = [
items: [],
},
{
+ title: 'Epics',
+ icon: 'epic',
+ link: '/search?scope=epics&search=et',
+ is_active: true,
+ pill_count: '0',
+ items: [],
+ },
+ {
title: 'Merge requests',
icon: 'merge-request',
link: '/search?scope=merge_requests&search=et',
@@ -505,7 +520,7 @@ export const MOCK_NAVIGATION_ITEMS = [
},
{
title: 'Wiki',
- icon: 'overview',
+ icon: 'book',
link: '/search?scope=wiki_blobs&search=et',
is_active: false,
pill_count: '0',
@@ -529,7 +544,7 @@ export const MOCK_NAVIGATION_ITEMS = [
},
{
title: 'Milestones',
- icon: 'tag',
+ icon: 'clock',
link: '/search?scope=milestones&search=et',
is_active: false,
pill_count: '0',
diff --git a/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js b/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js
index 6a94da31a1b..786ad806ea6 100644
--- a/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js
+++ b/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js
@@ -7,6 +7,8 @@ import ScopeLegacyNavigation from '~/search/sidebar/components/scope_legacy_navi
Vue.use(Vuex);
+const MOCK_NAVIGATION_ENTRIES = Object.entries(MOCK_NAVIGATION);
+
describe('ScopeLegacyNavigation', () => {
let wrapper;
@@ -55,12 +57,12 @@ describe('ScopeLegacyNavigation', () => {
});
it('renders all nav item components', () => {
- expect(findGlNavItems()).toHaveLength(9);
+ expect(findGlNavItems()).toHaveLength(MOCK_NAVIGATION_ENTRIES.length);
});
it('has all proper links', () => {
const linkAtPosition = 3;
- const { link } = MOCK_NAVIGATION[Object.keys(MOCK_NAVIGATION)[linkAtPosition]];
+ const { link } = MOCK_NAVIGATION_ENTRIES[linkAtPosition][1];
expect(findGlNavItems().at(linkAtPosition).attributes('href')).toBe(link);
});
diff --git a/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js b/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js
index 4b71ff0bedc..86939bdc5d6 100644
--- a/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js
+++ b/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js
@@ -7,6 +7,8 @@ import { MOCK_QUERY, MOCK_NAVIGATION, MOCK_NAVIGATION_ITEMS } from '../../mock_d
Vue.use(Vuex);
+const MOCK_NAVIGATION_ENTRIES = Object.entries(MOCK_NAVIGATION);
+
describe('ScopeSidebarNavigation', () => {
let wrapper;
@@ -59,7 +61,7 @@ describe('ScopeSidebarNavigation', () => {
});
it('renders all nav item components', () => {
- expect(findNavItems()).toHaveLength(9);
+ expect(findNavItems()).toHaveLength(MOCK_NAVIGATION_ENTRIES.length);
});
it('has all proper links', () => {
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 9df044c8a66..1b5f23a5e8e 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -503,6 +503,7 @@ RSpec.describe GroupsHelper do
it 'returns expected hash' do
expect(helper.group_overview_tabs_app_data(group)).to match(
{
+ group_id: group.id,
subgroups_and_projects_endpoint: including("/groups/#{group.path}/-/children.json"),
shared_projects_endpoint: including("/groups/#{group.path}/-/shared_projects.json"),
archived_projects_endpoint: including("/groups/#{group.path}/-/children.json?archived=only"),
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 5c55c1d604a..6634e7dbf27 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -1396,9 +1396,9 @@ RSpec.describe SearchHelper, feature_category: :global_search do
context 'data' do
where(:scope, :label, :data, :search, :active_scope) do
"projects" | "Projects" | { qa_selector: 'projects_tab' } | nil | "projects"
- "snippet_titles" | "Titles and Descriptions" | nil | { snippets: "test" } | "code"
+ "snippet_titles" | "Snippets" | nil | { snippets: "test" } | "code"
"projects" | "Projects" | { qa_selector: 'projects_tab' } | nil | "issue"
- "snippet_titles" | "Titles and Descriptions" | nil | { snippets: "test" } | "snippet_titles"
+ "snippet_titles" | "Snippets" | nil | { snippets: "test" } | "snippet_titles"
end
with_them do
diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb
index 0c5d587d8e8..ad73665326a 100644
--- a/spec/lib/expand_variables_spec.rb
+++ b/spec/lib/expand_variables_spec.rb
@@ -3,7 +3,7 @@
require 'fast_spec_helper'
require 'rspec-parameterized'
-RSpec.describe ExpandVariables do
+RSpec.describe ExpandVariables, feature_category: :secrets_management do
shared_examples 'common variable expansion' do |expander|
using RSpec::Parameterized::TableSyntax
@@ -35,7 +35,14 @@ RSpec.describe ExpandVariables do
{ key: 'variable', value: 'value' }
]
},
- "simple expansions": {
+ "expansion using %": {
+ value: 'key%variable%',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "multiple simple expansions": {
value: 'key$variable$variable2',
result: 'keyvalueresult',
variables: [
@@ -43,7 +50,7 @@ RSpec.describe ExpandVariables do
{ key: 'variable2', value: 'result' }
]
},
- "complex expansions": {
+ "multiple complex expansions": {
value: 'key${variable}${variable2}',
result: 'keyvalueresult',
variables: [
@@ -51,6 +58,15 @@ RSpec.describe ExpandVariables do
{ key: 'variable2', value: 'result' }
]
},
+ "nested expansion is not expanded": {
+ value: 'key$variable$variable2',
+ result: 'keyvalue$variable3',
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'result' }
+ ]
+ },
"out-of-order expansion": {
value: 'key$variable2$variable',
result: 'keyresultvalue',
@@ -99,10 +115,86 @@ RSpec.describe ExpandVariables do
end
end
+ shared_examples 'file variable expansion with expand_file_refs true' do |expander|
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "simple with a file variable": {
+ value: 'key$variable',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value', file: true }
+ ]
+ },
+ "complex expansion with a file variable": {
+ value: 'key${variable}',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value', file: true }
+ ]
+ },
+ "expansion using % with a file variable": {
+ value: 'key%variable%',
+ result: 'keyvalue',
+ variables: [
+ { key: 'variable', value: 'value', file: true }
+ ]
+ }
+ }
+ end
+
+ with_them do
+ subject { expander.call(value, variables, expand_file_refs: true) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+
+ shared_examples 'file variable expansion with expand_file_refs false' do |expander|
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "simple with a file variable": {
+ value: 'key$variable',
+ result: 'key$variable',
+ variables: [
+ { key: 'variable', value: 'value', file: true }
+ ]
+ },
+ "complex expansion with a file variable": {
+ value: 'key${variable}',
+ result: 'key${variable}',
+ variables: [
+ { key: 'variable', value: 'value', file: true }
+ ]
+ },
+ "expansion using % with a file variable": {
+ value: 'key%variable%',
+ result: 'key%variable%',
+ variables: [
+ { key: 'variable', value: 'value', file: true }
+ ]
+ }
+ }
+ end
+
+ with_them do
+ subject { expander.call(value, variables, expand_file_refs: false) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+
describe '#expand' do
context 'table tests' do
it_behaves_like 'common variable expansion', described_class.method(:expand)
+ it_behaves_like 'file variable expansion with expand_file_refs true', described_class.method(:expand)
+
+ it_behaves_like 'file variable expansion with expand_file_refs false', described_class.method(:expand)
+
context 'with missing variables' do
using RSpec::Parameterized::TableSyntax
@@ -169,6 +261,10 @@ RSpec.describe ExpandVariables do
context 'table tests' do
it_behaves_like 'common variable expansion', described_class.method(:expand_existing)
+ it_behaves_like 'file variable expansion with expand_file_refs true', described_class.method(:expand_existing)
+
+ it_behaves_like 'file variable expansion with expand_file_refs false', described_class.method(:expand_existing)
+
context 'with missing variables' do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index b864dba58de..603609e5e62 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
describe 'constants' do
it 'API_SCOPES contains all scopes for API access' do
- expect(subject::API_SCOPES).to match_array %i[api read_user read_api]
+ expect(subject::API_SCOPES).to match_array %i[api read_user read_api create_runner]
end
it 'ADMIN_SCOPES contains all scopes for ADMIN access' do
@@ -40,29 +40,29 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
end
it 'contains all non-default scopes' do
- expect(subject.all_available_scopes).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode read_observability write_observability]
+ expect(subject.all_available_scopes).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode read_observability write_observability create_runner]
end
it 'contains for non-admin user all non-default scopes without ADMIN access and without observability scopes' do
user = build_stubbed(:user, admin: false)
- expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry]
+ expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry create_runner]
end
it 'contains for admin user all non-default scopes with ADMIN access and without observability scopes' do
user = build_stubbed(:user, admin: true)
- expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode]
+ expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode create_runner]
end
it 'contains for project all resource bot scopes without observability scopes' do
- expect(subject.available_scopes_for(project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry]
+ expect(subject.available_scopes_for(project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner]
end
it 'contains for group all resource bot scopes' do
group = build_stubbed(:group)
- expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability]
+ expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability create_runner]
end
it 'contains for unsupported type no scopes' do
@@ -70,7 +70,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
end
it 'optional_scopes contains all non-default scopes' do
- expect(subject.optional_scopes).to match_array %i[read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode openid profile email read_observability write_observability]
+ expect(subject.optional_scopes).to match_array %i[read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode openid profile email read_observability write_observability create_runner]
end
context 'with observability_group_tab feature flag' do
@@ -82,7 +82,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
it 'contains for group all resource bot scopes without observability scopes' do
group = build_stubbed(:group)
- expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry]
+ expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner]
end
end
@@ -94,23 +94,23 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
end
it 'contains for other group all resource bot scopes including observability scopes' do
- expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability]
+ expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability create_runner]
end
it 'contains for admin user all non-default scopes with ADMIN access and without observability scopes' do
user = build_stubbed(:user, admin: true)
- expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode]
+ expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo admin_mode create_runner]
end
it 'contains for project all resource bot scopes without observability scopes' do
- expect(subject.available_scopes_for(project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry]
+ expect(subject.available_scopes_for(project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner]
end
it 'contains for other group all resource bot scopes without observability scopes' do
other_group = build_stubbed(:group)
- expect(subject.available_scopes_for(other_group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry]
+ expect(subject.available_scopes_for(other_group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner]
end
end
end
@@ -351,6 +351,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
'read_api' | described_class.read_only_authentication_abilities
'read_repository' | [:download_code]
'write_repository' | [:download_code, :push_code]
+ 'create_runner' | [:create_instance_runner, :create_runner]
'read_user' | []
'sudo' | []
'openid' | []
@@ -412,6 +413,12 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect_results_with_abilities(personal_access_token, [:download_code, :push_code])
end
+ it 'succeeds for personal access tokens with the `create_runner` scope' do
+ personal_access_token = create(:personal_access_token, scopes: ['create_runner'])
+
+ expect_results_with_abilities(personal_access_token, [:create_instance_runner, :create_runner])
+ end
+
context 'when registry is enabled' do
before do
stub_container_registry_config(enabled: true)
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 181e37de9b9..006f7c2ebe6 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -3,6 +3,62 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Variables::Collection, feature_category: :secrets_management do
+ describe '.fabricate' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "given an array of variables": {
+ input: [
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' }
+ ]
+ },
+ "given a hash of variables": {
+ input: { 'VAR1' => 'value1', 'VAR2' => 'value2' }
+ },
+ "given a proc that evaluates to an array": {
+ input: -> do
+ [
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' }
+ ]
+ end
+ },
+ "given a proc that evaluates to a hash": {
+ input: -> do
+ { 'VAR1' => 'value1', 'VAR2' => 'value2' }
+ end
+ },
+ "given a collection": {
+ input: Gitlab::Ci::Variables::Collection.new(
+ [
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' }
+ ]
+ )
+ }
+ }
+ end
+
+ with_them do
+ subject(:collection) { Gitlab::Ci::Variables::Collection.fabricate(input) }
+
+ it 'returns a collection' do
+ expect(collection).to be_a(Gitlab::Ci::Variables::Collection)
+ expect(collection.size).to eq(2)
+ expect(collection.map(&:key)).to contain_exactly('VAR1', 'VAR2')
+ expect(collection.map(&:value)).to contain_exactly('value1', 'value2')
+ end
+ end
+
+ context 'when given an unrecognized type' do
+ it 'raises error' do
+ expect { Gitlab::Ci::Variables::Collection.fabricate(1) }.to raise_error(ArgumentError)
+ end
+ end
+ end
+
describe '.new' do
it 'can be initialized with an array' do
variable = { key: 'VAR', value: 'value', public: true, masked: false }
diff --git a/spec/lib/gitlab/legacy_github_import/client_spec.rb b/spec/lib/gitlab/legacy_github_import/client_spec.rb
index 757bdd8dd6c..4aea7308e37 100644
--- a/spec/lib/gitlab/legacy_github_import/client_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/client_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::Client, feature_category: :importers do
let(:token) { '123456' }
- let(:github_provider) { GitlabSettings::Options.build('app_id' => 'asd123', 'app_secret' => 'asd123', 'name' => 'github', 'args' => { 'client_options' => {} }) }
+ let(:github_provider) { GitlabSettings::Options.build('app_id' => 'asd123', 'app_secret' => 'asd123', 'name' => 'github', 'args' => { 'client_options' => client_options }) }
+ let(:client_options) { {} }
let(:wait_for_rate_limit_reset) { true }
subject(:client) { described_class.new(token, wait_for_rate_limit_reset: wait_for_rate_limit_reset) }
@@ -13,8 +14,19 @@ RSpec.describe Gitlab::LegacyGithubImport::Client, feature_category: :importers
allow(Gitlab.config.omniauth).to receive(:providers).and_return([github_provider])
end
- it 'convert OAuth2 client options to symbols' do
- expect(client.client.options.keys).to all(be_kind_of(Symbol))
+ context 'with client options' do
+ let(:client_options) do
+ {
+ 'authorize_url' => 'https://github.com/login/oauth/authorize',
+ 'token_url' => 'https://github.com/login/oauth/access_token'
+ }
+ end
+
+ it 'convert OAuth2 client options to symbols' do
+ expect(client.client.options.keys).to all(be_kind_of(Symbol))
+ expect(client.client.options[:authorize_url]).to eq(client_options['authorize_url'])
+ expect(client.client.options[:token_url]).to eq(client_options['token_url'])
+ end
end
it 'does not crash (e.g. GitlabSettings::MissingSetting) when verify_ssl config is not present' do
diff --git a/spec/requests/api/user_runners_spec.rb b/spec/requests/api/user_runners_spec.rb
new file mode 100644
index 00000000000..0e40dcade19
--- /dev/null
+++ b/spec/requests/api/user_runners_spec.rb
@@ -0,0 +1,243 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::UserRunners, :aggregate_failures, feature_category: :runner_fleet do
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:user, reload: true) { create(:user, username: 'user.withdot') }
+
+ describe 'POST /user/runners' do
+ subject(:request) { post api(path, current_user, **post_args), params: runner_attrs }
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
+ let_it_be(:group_owner) { create(:user).tap { |user| group.add_owner(user) } }
+ let_it_be(:group_maintainer) { create(:user).tap { |user| group.add_maintainer(user) } }
+ let_it_be(:project_developer) { create(:user).tap { |user| project.add_developer(user) } }
+
+ let(:post_args) { { admin_mode: true } }
+ let(:runner_attrs) { { runner_type: 'instance_type' } }
+ let(:path) { '/user/runners' }
+
+ shared_examples 'when runner creation fails due to authorization' do
+ it 'does not create a runner' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ shared_context 'when user does not have sufficient permissions returns forbidden' do
+ context 'when user is admin and admin mode is disabled' do
+ let(:current_user) { admin }
+ let(:post_args) { { admin_mode: false } }
+
+ it_behaves_like 'when runner creation fails due to authorization'
+ end
+
+ context 'when user is not an admin or a member of the namespace' do
+ let(:current_user) { user }
+
+ it_behaves_like 'when runner creation fails due to authorization'
+ end
+ end
+
+ shared_examples 'creates a runner' do
+ it 'creates a runner' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:created)
+ end.to change { Ci::Runner.count }.by(1)
+ end
+ end
+
+ shared_examples 'fails to create runner with expected_status_code' do
+ let(:expected_message) { nil }
+ let(:expected_error) { nil }
+
+ it 'does not create runner' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(expected_status_code)
+ expect(json_response['message']).to include(expected_message) if expected_message
+ expect(json_response['error']).to include(expected_error) if expected_error
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ shared_context 'with request authorized with access token' do
+ let(:current_user) { nil }
+ let(:pat) { create(:personal_access_token, user: token_user, scopes: [scope]) }
+ let(:path) { "/user/runners?private_token=#{pat.token}" }
+
+ %i[create_runner api].each do |scope|
+ context "with #{scope} scope" do
+ let(:scope) { scope }
+
+ it_behaves_like 'creates a runner'
+ end
+ end
+
+ context 'with read_api scope' do
+ let(:scope) { :read_api }
+
+ it_behaves_like 'fails to create runner with expected_status_code' do
+ let(:expected_status_code) { :forbidden }
+ let(:expected_error) { 'insufficient_scope' }
+ end
+ end
+ end
+
+ context 'when runner_type is :instance_type' do
+ let(:runner_attrs) { { runner_type: 'instance_type' } }
+
+ context 'when user has sufficient permissions' do
+ let(:current_user) { admin }
+
+ it_behaves_like 'creates a runner'
+ end
+
+ context 'with admin mode enabled', :enable_admin_mode do
+ let(:token_user) { admin }
+
+ it_behaves_like 'with request authorized with access token'
+ end
+
+ it_behaves_like 'when user does not have sufficient permissions returns forbidden'
+
+ context 'when user is not an admin' do
+ let(:current_user) { user }
+
+ it_behaves_like 'when runner creation fails due to authorization'
+ end
+
+ context 'when model validation fails' do
+ let(:runner_attrs) { { runner_type: 'instance_type', run_untagged: false, tag_list: [] } }
+ let(:current_user) { admin }
+
+ it_behaves_like 'fails to create runner with expected_status_code' do
+ let(:expected_status_code) { :bad_request }
+ let(:expected_message) { 'Tags list can not be empty' }
+ end
+ end
+ end
+
+ context 'when runner_type is :group_type' do
+ let(:post_args) { {} }
+
+ context 'when group_id is specified' do
+ let(:runner_attrs) { { runner_type: 'group_type', group_id: group.id } }
+
+ context 'when user has sufficient permissions' do
+ let(:current_user) { group_owner }
+
+ it_behaves_like 'creates a runner'
+ end
+
+ it_behaves_like 'with request authorized with access token' do
+ let(:token_user) { group_owner }
+ end
+
+ it_behaves_like 'when user does not have sufficient permissions returns forbidden'
+
+ context 'when user is a maintainer' do
+ let(:current_user) { group_maintainer }
+
+ it_behaves_like 'when runner creation fails due to authorization'
+ end
+ end
+
+ context 'when group_id is not specified' do
+ let(:runner_attrs) { { runner_type: 'group_type' } }
+ let(:current_user) { group_owner }
+
+ it 'fails to create runner with :bad_request' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to include('group_id is missing')
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+ end
+
+ context 'when runner_type is :project_type' do
+ let(:post_args) { {} }
+
+ context 'when project_id is specified' do
+ let(:runner_attrs) { { runner_type: 'project_type', project_id: project.id } }
+
+ context 'when user has sufficient permissions' do
+ let(:current_user) { group_owner }
+
+ it_behaves_like 'creates a runner'
+ end
+
+ it_behaves_like 'with request authorized with access token' do
+ let(:token_user) { group_owner }
+ end
+
+ it_behaves_like 'when user does not have sufficient permissions returns forbidden'
+
+ context 'when user is a developer' do
+ let(:current_user) { project_developer }
+
+ it_behaves_like 'when runner creation fails due to authorization'
+ end
+ end
+
+ context 'when project_id is not specified' do
+ let(:runner_attrs) { { runner_type: 'project_type' } }
+ let(:current_user) { group_owner }
+
+ it 'fails to create runner with :bad_request' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to include('project_id is missing')
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+ end
+
+ context 'with missing runner_type' do
+ let(:runner_attrs) { {} }
+ let(:current_user) { admin }
+
+ it 'fails to create runner with :bad_request' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('runner_type is missing, runner_type does not have a valid value')
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ context 'with unknown runner_type' do
+ let(:runner_attrs) { { runner_type: 'unknown' } }
+ let(:current_user) { admin }
+
+ it 'fails to create runner with :bad_request' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('runner_type does not have a valid value')
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ it 'returns a 401 error if unauthorized' do
+ post api(path), params: runner_attrs
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 3737c91adbc..2bbcf6b3f38 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -4851,169 +4851,4 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
let(:attributable) { user }
let(:other_attributable) { admin }
end
-
- describe 'POST /user/runners', feature_category: :runner_fleet do
- subject(:request) { post api(path, current_user, **post_args), params: runner_attrs }
-
- let_it_be(:group_owner) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, namespace: group) }
-
- let(:post_args) { { admin_mode: true } }
- let(:runner_attrs) { { runner_type: 'instance_type' } }
- let(:path) { '/user/runners' }
-
- before do
- group.add_owner(group_owner)
- end
-
- shared_context 'returns forbidden when user does not have sufficient permissions' do
- let(:current_user) { admin }
- let(:post_args) { { admin_mode: false } }
-
- it 'does not create a runner' do
- expect do
- request
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end.not_to change { Ci::Runner.count }
- end
- end
-
- shared_examples 'creates a runner' do
- it 'creates a runner' do
- expect do
- request
-
- expect(response).to have_gitlab_http_status(:created)
- end.to change { Ci::Runner.count }.by(1)
- end
- end
-
- shared_examples 'fails to create runner with :bad_request' do
- it 'does not create runner' do
- expect do
- request
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to include(expected_error)
- end.not_to change { Ci::Runner.count }
- end
- end
-
- context 'when runner_type is :instance_type' do
- let(:runner_attrs) { { runner_type: 'instance_type' } }
-
- context 'when user has sufficient permissions' do
- let(:current_user) { admin }
-
- it_behaves_like 'creates a runner'
- end
-
- it_behaves_like 'returns forbidden when user does not have sufficient permissions'
-
- context 'when model validation fails' do
- let(:runner_attrs) { { runner_type: 'instance_type', run_untagged: false, tag_list: [] } }
- let(:current_user) { admin }
-
- it_behaves_like 'fails to create runner with :bad_request' do
- let(:expected_error) { 'Tags list can not be empty' }
- end
- end
- end
-
- context 'when runner_type is :group_type' do
- let(:post_args) { {} }
-
- context 'when group_id is specified' do
- let(:runner_attrs) { { runner_type: 'group_type', group_id: group.id } }
-
- context 'when user has sufficient permissions' do
- let(:current_user) { group_owner }
-
- it_behaves_like 'creates a runner'
- end
-
- it_behaves_like 'returns forbidden when user does not have sufficient permissions'
- end
-
- context 'when group_id is not specified' do
- let(:runner_attrs) { { runner_type: 'group_type' } }
- let(:current_user) { group_owner }
-
- it 'fails to create runner with :bad_request' do
- expect do
- request
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to include('group_id is missing')
- end.not_to change { Ci::Runner.count }
- end
- end
- end
-
- context 'when runner_type is :project_type' do
- let(:post_args) { {} }
-
- context 'when project_id is specified' do
- let(:runner_attrs) { { runner_type: 'project_type', project_id: project.id } }
-
- context 'when user has sufficient permissions' do
- let(:current_user) { group_owner }
-
- it_behaves_like 'creates a runner'
- end
-
- it_behaves_like 'returns forbidden when user does not have sufficient permissions'
- end
-
- context 'when project_id is not specified' do
- let(:runner_attrs) { { runner_type: 'project_type' } }
- let(:current_user) { group_owner }
-
- it 'fails to create runner with :bad_request' do
- expect do
- request
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to include('project_id is missing')
- end.not_to change { Ci::Runner.count }
- end
- end
- end
-
- context 'with missing runner_type' do
- let(:runner_attrs) { {} }
- let(:current_user) { admin }
-
- it 'fails to create runner with :bad_request' do
- expect do
- request
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq('runner_type is missing, runner_type does not have a valid value')
- end.not_to change { Ci::Runner.count }
- end
- end
-
- context 'with unknown runner_type' do
- let(:runner_attrs) { { runner_type: 'unknown' } }
- let(:current_user) { admin }
-
- it 'fails to create runner with :bad_request' do
- expect do
- request
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq('runner_type does not have a valid value')
- end.not_to change { Ci::Runner.count }
- end
- end
-
- it 'returns a 401 error if unauthorized' do
- post api(path), params: runner_attrs
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
end
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index 82f972e7f94..217241200ff 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -270,13 +270,20 @@ RSpec.describe 'OpenID Connect requests', feature_category: :system_access do
end
context 'OpenID configuration information' do
+ let(:expected_scopes) do
+ %w[
+ admin_mode api read_user read_api read_repository write_repository sudo openid profile email
+ read_observability write_observability create_runner
+ ]
+ end
+
it 'correctly returns the configuration' do
get '/.well-known/openid-configuration'
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['issuer']).to eq('http://localhost')
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
- expect(json_response['scopes_supported']).to match_array %w[admin_mode api read_user read_api read_repository write_repository sudo openid profile email read_observability write_observability]
+ expect(json_response['scopes_supported']).to match_array expected_scopes
end
context 'with a cross-origin request' do
@@ -286,7 +293,7 @@ RSpec.describe 'OpenID Connect requests', feature_category: :system_access do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['issuer']).to eq('http://localhost')
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
- expect(json_response['scopes_supported']).to match_array %w[admin_mode api read_user read_api read_repository write_repository sudo openid profile email read_observability write_observability]
+ expect(json_response['scopes_supported']).to match_array expected_scopes
end
it_behaves_like 'cross-origin GET request'
diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
index c43f1e5264e..15f2cc0990c 100644
--- a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
+++ b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
@@ -1094,34 +1094,6 @@ RSpec.describe Ci::PipelineProcessing::AtomicProcessingService, feature_category
process_pipeline
end
end
-
- context 'when FF `ci_reset_skipped_jobs_in_atomic_processing` is disabled' do
- before do
- stub_feature_flags(ci_reset_skipped_jobs_in_atomic_processing: false)
-
- process_pipeline # First pipeline processing
-
- # Change the manual jobs from stopped to alive status
- manual1.enqueue!
- manual2.enqueue!
-
- mock_play_jobs_during_processing([manual1, manual2])
- end
-
- it 'does not run ResetSkippedJobsService' do
- expect(Ci::ResetSkippedJobsService).not_to receive(:new)
-
- process_pipeline
-
- expect(all_builds_names_and_statuses).to eq(statuses_2)
- end
-
- it 'does not log event' do
- expect(Gitlab::AppJsonLogger).not_to receive(:info)
-
- process_pipeline
- end
- end
end
context 'when a bridge job has parallel:matrix config', :sidekiq_inline do
diff --git a/spec/services/packages/nuget/extract_metadata_content_service_spec.rb b/spec/services/packages/nuget/extract_metadata_content_service_spec.rb
new file mode 100644
index 00000000000..ff1b26e8b28
--- /dev/null
+++ b/spec/services/packages/nuget/extract_metadata_content_service_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Nuget::ExtractMetadataContentService, feature_category: :package_registry do
+ let(:nuspec_file_content) { fixture_file(nuspec_filepath) }
+
+ let(:service) { described_class.new(nuspec_file_content) }
+
+ describe '#execute' do
+ subject { service.execute.payload }
+
+ context 'with nuspec file content' do
+ context 'with dependencies' do
+ let(:nuspec_filepath) { 'packages/nuget/with_dependencies.nuspec' }
+
+ it { is_expected.to have_key(:package_dependencies) }
+
+ it 'extracts dependencies' do
+ dependencies = subject[:package_dependencies]
+
+ expect(dependencies).to include(name: 'Moqi', version: '2.5.6')
+ expect(dependencies).to include(name: 'Castle.Core')
+ expect(dependencies).to include(name: 'Test.Dependency', version: '2.3.7',
+ target_framework: '.NETStandard2.0')
+ expect(dependencies).to include(name: 'Newtonsoft.Json', version: '12.0.3',
+ target_framework: '.NETStandard2.0')
+ end
+ end
+
+ context 'with package types' do
+ let(:nuspec_filepath) { 'packages/nuget/with_package_types.nuspec' }
+
+ it { is_expected.to have_key(:package_types) }
+
+ it 'extracts package types' do
+ expect(subject[:package_types]).to include('SymbolsPackage')
+ end
+ end
+
+ context 'with a nuspec file with metadata' do
+ let(:nuspec_filepath) { 'packages/nuget/with_metadata.nuspec' }
+
+ it { expect(subject[:package_tags].sort).to eq(%w[foo bar test tag1 tag2 tag3 tag4 tag5].sort) }
+ end
+ end
+
+ context 'with a nuspec file content with metadata' do
+ let_it_be(:nuspec_filepath) { 'packages/nuget/with_metadata.nuspec' }
+
+ it 'returns the correct metadata' do
+ expected_metadata = {
+ authors: 'Author Test',
+ description: 'Description Test',
+ license_url: 'https://opensource.org/licenses/MIT',
+ project_url: 'https://gitlab.com/gitlab-org/gitlab',
+ icon_url: 'https://opensource.org/files/osi_keyhole_300X300_90ppi_0.png'
+ }
+
+ expect(subject.slice(*expected_metadata.keys)).to eq(expected_metadata)
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/nuget/extract_metadata_file_service_spec.rb b/spec/services/packages/nuget/extract_metadata_file_service_spec.rb
new file mode 100644
index 00000000000..412c22fe8de
--- /dev/null
+++ b/spec/services/packages/nuget/extract_metadata_file_service_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Nuget::ExtractMetadataFileService, feature_category: :package_registry do
+ let_it_be(:package_file) { create(:nuget_package).package_files.first }
+
+ let(:service) { described_class.new(package_file.id) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ shared_examples 'raises an error' do |error_message|
+ it { expect { subject }.to raise_error(described_class::ExtractionError, error_message) }
+ end
+
+ context 'with valid package file id' do
+ expected_metadata = <<~XML.squish
+ <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
+ <metadata>
+ <id>DummyProject.DummyPackage</id>
+ <version>1.0.0</version>
+ <title>Dummy package</title>
+ <authors>Test</authors>
+ <owners>Test</owners>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>This is a dummy project</description>
+ <dependencies>
+ <group targetFramework=".NETCoreApp3.0">
+ <dependency id="Newtonsoft.Json" version="12.0.3" exclude="Build,Analyzers" />
+ </group>
+ </dependencies>
+ </metadata>
+ </package>
+ XML
+
+ it 'returns the nuspec file content' do
+ expect(subject.payload.squish).to include(expected_metadata)
+ end
+ end
+
+ context 'with invalid package file id' do
+ let(:package_file) { instance_double('Packages::PackageFile', id: 555) }
+
+ it_behaves_like 'raises an error', 'invalid package file'
+ end
+
+ context 'when linked to a non nuget package' do
+ before do
+ package_file.package.maven!
+ end
+
+ it_behaves_like 'raises an error', 'invalid package file'
+ end
+
+ context 'with a 0 byte package file id' do
+ before do
+ allow_next_instance_of(Packages::PackageFileUploader) do |instance|
+ allow(instance).to receive(:size).and_return(0)
+ end
+ end
+
+ it_behaves_like 'raises an error', 'invalid package file'
+ end
+
+ context 'without the nuspec file' do
+ before do
+ allow_next_instance_of(Zip::File) do |instance|
+ allow(instance).to receive(:glob).and_return([])
+ end
+ end
+
+ it_behaves_like 'raises an error', 'nuspec file not found'
+ end
+
+ context 'with a too big nuspec file' do
+ before do
+ allow_next_instance_of(Zip::File) do |instance|
+ allow(instance).to receive(:glob).and_return([instance_double('File', size: 6.megabytes)])
+ end
+ end
+
+ it_behaves_like 'raises an error', 'nuspec file too big'
+ end
+
+ context 'with a corrupted nupkg file with a wrong entry size' do
+ let(:nupkg_fixture_path) { expand_fixture_path('packages/nuget/corrupted_package.nupkg') }
+
+ before do
+ allow(Zip::File).to receive(:new).and_return(Zip::File.new(nupkg_fixture_path, false, false))
+ end
+
+ it_behaves_like 'raises an error',
+ <<~ERROR.squish
+ nuspec file has the wrong entry size: entry 'DummyProject.DummyPackage.nuspec' should be 255B,
+ but is larger when inflated.
+ ERROR
+ end
+ end
+end
diff --git a/spec/services/packages/nuget/metadata_extraction_service_spec.rb b/spec/services/packages/nuget/metadata_extraction_service_spec.rb
index 8954b89971e..c8c06414830 100644
--- a/spec/services/packages/nuget/metadata_extraction_service_spec.rb
+++ b/spec/services/packages/nuget/metadata_extraction_service_spec.rb
@@ -5,17 +5,33 @@ require 'spec_helper'
RSpec.describe Packages::Nuget::MetadataExtractionService, feature_category: :package_registry do
let_it_be(:package_file) { create(:nuget_package).package_files.first }
- let(:service) { described_class.new(package_file.id) }
+ subject { described_class.new(package_file.id) }
describe '#execute' do
- subject { service.execute }
-
- shared_examples 'raises an error' do |error_message|
- it { expect { subject }.to raise_error(described_class::ExtractionError, error_message) }
+ let(:nuspec_file_content) do
+ <<~XML.squish
+ <?xml version="1.0" encoding="utf-8"?>
+ <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
+ <metadata>
+ <id>DummyProject.DummyPackage</id>
+ <version>1.0.0</version>
+ <title>Dummy package</title>
+ <authors>Test</authors>
+ <owners>Test</owners>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>This is a dummy project</description>
+ <dependencies>
+ <group targetFramework=".NETCoreApp3.0">
+ <dependency id="Newtonsoft.Json" version="12.0.3" exclude="Build,Analyzers" />
+ </group>
+ </dependencies>
+ </metadata>
+ </package>
+ XML
end
- context 'with valid package file id' do
- expected_metadata = {
+ let(:expected_metadata) do
+ {
package_name: 'DummyProject.DummyPackage',
package_version: '1.0.0',
authors: 'Test',
@@ -30,113 +46,21 @@ RSpec.describe Packages::Nuget::MetadataExtractionService, feature_category: :pa
package_tags: [],
package_types: []
}
-
- it { is_expected.to eq(expected_metadata) }
end
- context 'with nuspec file' do
- before do
- allow(service).to receive(:nuspec_file_content).and_return(fixture_file(nuspec_filepath))
- end
-
- context 'with dependencies' do
- let(:nuspec_filepath) { 'packages/nuget/with_dependencies.nuspec' }
-
- it { is_expected.to have_key(:package_dependencies) }
-
- it 'extracts dependencies' do
- dependencies = subject[:package_dependencies]
-
- expect(dependencies).to include(name: 'Moqi', version: '2.5.6')
- expect(dependencies).to include(name: 'Castle.Core')
- expect(dependencies).to include(name: 'Test.Dependency', version: '2.3.7', target_framework: '.NETStandard2.0')
- expect(dependencies).to include(name: 'Newtonsoft.Json', version: '12.0.3', target_framework: '.NETStandard2.0')
- end
- end
-
- context 'with package types' do
- let(:nuspec_filepath) { 'packages/nuget/with_package_types.nuspec' }
-
- it { is_expected.to have_key(:package_types) }
-
- it 'extracts package types' do
- expect(subject[:package_types]).to include('SymbolsPackage')
+ it 'calls the necessary services and executes the metadata extraction' do
+ expect(::Packages::Nuget::ExtractMetadataFileService).to receive(:new).with(package_file.id) do
+ double.tap do |service|
+ expect(service).to receive(:execute).and_return(double(payload: nuspec_file_content))
end
end
- context 'with a nuspec file with metadata' do
- let(:nuspec_filepath) { 'packages/nuget/with_metadata.nuspec' }
-
- it { expect(subject[:package_tags].sort).to eq(%w(foo bar test tag1 tag2 tag3 tag4 tag5).sort) }
- end
- end
-
- context 'with a nuspec file with metadata' do
- let_it_be(:nuspec_filepath) { 'packages/nuget/with_metadata.nuspec' }
-
- before do
- allow(service).to receive(:nuspec_file_content).and_return(fixture_file(nuspec_filepath))
- end
-
- it 'returns the correct metadata' do
- expected_metadata = {
- authors: 'Author Test',
- description: 'Description Test',
- license_url: 'https://opensource.org/licenses/MIT',
- project_url: 'https://gitlab.com/gitlab-org/gitlab',
- icon_url: 'https://opensource.org/files/osi_keyhole_300X300_90ppi_0.png'
- }
-
- expect(subject.slice(*expected_metadata.keys)).to eq(expected_metadata)
- end
- end
+ expect(::Packages::Nuget::ExtractMetadataContentService).to receive_message_chain(:new, :execute)
+ .with(nuspec_file_content).with(no_args).and_return(double(payload: expected_metadata))
- context 'with invalid package file id' do
- let(:package_file) { double('file', id: 555) }
-
- it_behaves_like 'raises an error', 'invalid package file'
- end
-
- context 'linked to a non nuget package' do
- before do
- package_file.package.maven!
- end
-
- it_behaves_like 'raises an error', 'invalid package file'
- end
-
- context 'with a 0 byte package file id' do
- before do
- allow_any_instance_of(Packages::PackageFileUploader).to receive(:size).and_return(0)
- end
-
- it_behaves_like 'raises an error', 'invalid package file'
- end
-
- context 'without the nuspec file' do
- before do
- allow_any_instance_of(Zip::File).to receive(:glob).and_return([])
- end
-
- it_behaves_like 'raises an error', 'nuspec file not found'
- end
-
- context 'with a too big nuspec file' do
- before do
- allow_any_instance_of(Zip::File).to receive(:glob).and_return([double('file', size: 6.megabytes)])
- end
-
- it_behaves_like 'raises an error', 'nuspec file too big'
- end
-
- context 'with a corrupted nupkg file with a wrong entry size' do
- let(:nupkg_fixture_path) { expand_fixture_path('packages/nuget/corrupted_package.nupkg') }
-
- before do
- allow(Zip::File).to receive(:new).and_return(Zip::File.new(nupkg_fixture_path, false, false))
- end
+ metadata = subject.execute.payload
- it_behaves_like 'raises an error', "nuspec file has the wrong entry size: entry 'DummyProject.DummyPackage.nuspec' should be 255B, but is larger when inflated."
+ expect(metadata).to eq(expected_metadata)
end
end
end
diff --git a/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb b/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
index fa7d994c13c..caa4e42d002 100644
--- a/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
+++ b/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
@@ -228,7 +228,7 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
end
end
- it_behaves_like 'raising an', ::Packages::Nuget::MetadataExtractionService::ExtractionError, with_message: 'nuspec file not found'
+ it_behaves_like 'raising an', ::Packages::Nuget::ExtractMetadataFileService::ExtractionError, with_message: 'nuspec file not found'
end
context 'with a symbol package' do
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index ffe1034bcad..2298f2e086f 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -122,11 +122,9 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'AdminEmailsWorker' => 3,
'Analytics::CodeReviewMetricsWorker' => 3,
'Analytics::DevopsAdoption::CreateSnapshotWorker' => 3,
- 'Analytics::InstanceStatistics::CounterJobWorker' => 3,
'Analytics::UsageTrends::CounterJobWorker' => 3,
'ApprovalRules::ExternalApprovalRulePayloadWorker' => 3,
'ApproveBlockedPendingApprovalUsersWorker' => 3,
- 'ArchiveTraceWorker' => 3,
'AuthorizedKeysWorker' => 3,
'AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker' => 3,
'AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker' => 3,
@@ -136,7 +134,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'AutoMergeProcessWorker' => 3,
'BackgroundMigrationWorker' => 3,
'BackgroundMigration::CiDatabaseWorker' => 3,
- 'BuildFinishedWorker' => 3,
'BuildHooksWorker' => 3,
'BuildQueueWorker' => 3,
'BuildSuccessWorker' => 3,
@@ -187,7 +184,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'Clusters::Applications::DeactivateIntegrationWorker' => 3,
'Clusters::Applications::UninstallWorker' => 3,
'Clusters::Applications::WaitForUninstallAppWorker' => 3,
- 'Clusters::Cleanup::AppWorker' => 3,
'Clusters::Cleanup::ProjectNamespaceWorker' => 3,
'Clusters::Cleanup::ServiceAccountWorker' => 3,
'ContainerExpirationPolicies::CleanupContainerRepositoryWorker' => 0,
@@ -207,10 +203,7 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'DependencyProxy::CleanupBlobWorker' => 3,
'DependencyProxy::CleanupManifestWorker' => 3,
'Deployments::AutoRollbackWorker' => 3,
- 'Deployments::FinishedWorker' => 3,
- 'Deployments::ForwardDeploymentWorker' => 3,
'Deployments::LinkMergeRequestWorker' => 3,
- 'Deployments::SuccessWorker' => 3,
'Deployments::UpdateEnvironmentWorker' => 3,
'Deployments::ApprovalWorker' => 3,
'DesignManagement::CopyDesignCollectionWorker' => 3,
@@ -260,7 +253,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'Geo::VerificationTimeoutWorker' => false,
'Geo::VerificationWorker' => 3,
'GeoRepositoryDestroyWorker' => 3,
- 'GitGarbageCollectWorker' => false,
'Gitlab::BitbucketServerImport::AdvanceStageWorker' => 3,
'Gitlab::BitbucketServerImport::Stage::FinishImportWorker' => 3,
'Gitlab::BitbucketServerImport::Stage::ImportLfsObjectsWorker' => 3,
@@ -356,7 +348,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'MergeRequestCleanupRefsWorker' => 3,
'MergeRequestMergeabilityCheckWorker' => 3,
'MergeRequestResetApprovalsWorker' => 3,
- 'MergeRequests::AssigneesChangeWorker' => 3,
'MergeRequests::CaptureSuggestedReviewersAcceptedWorker' => 3,
'MergeRequests::CreatePipelineWorker' => 3,
'MergeRequests::DeleteSourceBranchWorker' => 3,
@@ -373,7 +364,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'Onboarding::ProgressWorker' => 3,
'Onboarding::UserAddedWorker' => 3,
'Namespaces::FreeUserCap::OverLimitNotificationWorker' => false,
- 'Namespaces::RefreshRootStatisticsWorker' => 3,
'Namespaces::RootStatisticsWorker' => 3,
'Namespaces::ScheduleAggregationWorker' => 3,
'Namespaces::FreeUserCap::NotificationClearingWorker' => false,
@@ -411,9 +401,7 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'ProjectDestroyWorker' => 3,
'ProjectExportWorker' => false,
'ProjectImportScheduleWorker' => 1,
- 'ProjectScheduleBulkRepositoryShardMovesWorker' => 3,
'ProjectTemplateExportWorker' => false,
- 'ProjectUpdateRepositoryStorageWorker' => 3,
'Projects::DeregisterSuggestedReviewersProjectWorker' => 3,
'Projects::DisableLegacyOpenSourceLicenseForInactiveProjectsWorker' => 3,
'Projects::GitGarbageCollectWorker' => false,
@@ -451,8 +439,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'Security::TrackSecureScansWorker' => 1,
'ServiceDeskEmailReceiverWorker' => 3,
'SetUserStatusBasedOnUserCapSettingWorker' => 3,
- 'SnippetScheduleBulkRepositoryShardMovesWorker' => 3,
- 'SnippetUpdateRepositoryStorageWorker' => 3,
'Snippets::ScheduleBulkRepositoryShardMovesWorker' => 3,
'Snippets::UpdateRepositoryStorageWorker' => 3,
'StageUpdateWorker' => 3,
@@ -480,7 +466,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'VulnerabilityExports::ExportWorker' => 3,
'WaitForClusterCreationWorker' => 3,
'WebHookWorker' => 4,
- 'WebHooks::DestroyWorker' => 3,
'WebHooks::LogExecutionWorker' => 3,
'Wikis::GitGarbageCollectWorker' => false,
'WorkItems::ImportWorkItemsCsvWorker' => 3,
@@ -490,6 +475,23 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
}.merge(extra_retry_exceptions)
end
+ it 'defines `retry_exceptions` only for existing workers', if: Gitlab.ee? do
+ removed_workers = retry_exceptions.keys - retry_exception_workers.map { |worker| worker.klass.to_s }
+ message = -> do
+ list = removed_workers.map { |name| "- #{name}" }
+
+ <<~MESSAGE
+ The following workers no longer exist but are defined in `retry_exceptions`:
+
+ #{list.join("\n")}
+
+ Make sure to remove them from `retry_exceptions` because their definition is unnecessary.
+ MESSAGE
+ end
+
+ expect(removed_workers).to be_empty, message
+ end
+
it 'uses the default number of retries for new jobs' do
expect(workers_without_defaults - cronjobs - retry_exception_workers).to all(have_attributes(retries: true))
end
diff --git a/spec/workers/packages/nuget/extraction_worker_spec.rb b/spec/workers/packages/nuget/extraction_worker_spec.rb
index c1d42d556c2..11eaa1b5dde 100644
--- a/spec/workers/packages/nuget/extraction_worker_spec.rb
+++ b/spec/workers/packages/nuget/extraction_worker_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe Packages::Nuget::ExtractionWorker, type: :worker, feature_categor
allow_any_instance_of(Zip::File).to receive(:glob).and_return([])
end
- it_behaves_like 'handling the metadata error', exception_class: ::Packages::Nuget::MetadataExtractionService::ExtractionError
+ it_behaves_like 'handling the metadata error', exception_class: ::Packages::Nuget::ExtractMetadataFileService::ExtractionError
end
context 'with package with an invalid package name' do