summaryrefslogtreecommitdiff
path: root/spec/requests
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-19 22:11:55 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-19 22:11:55 +0000
commit5a8431feceba47fd8e1804d9aa1b1730606b71d5 (patch)
treee5df8e0ceee60f4af8093f5c4c2f934b8abced05 /spec/requests
parent4d477238500c347c6553d335d920bedfc5a46869 (diff)
downloadgitlab-ce-5a8431feceba47fd8e1804d9aa1b1730606b71d5.tar.gz
Add latest changes from gitlab-org/gitlab@12-5-stable-ee
Diffstat (limited to 'spec/requests')
-rw-r--r--spec/requests/api/access_requests_spec.rb2
-rw-r--r--spec/requests/api/applications_spec.rb2
-rw-r--r--spec/requests/api/avatar_spec.rb2
-rw-r--r--spec/requests/api/award_emoji_spec.rb2
-rw-r--r--spec/requests/api/badges_spec.rb2
-rw-r--r--spec/requests/api/boards_spec.rb2
-rw-r--r--spec/requests/api/branches_spec.rb23
-rw-r--r--spec/requests/api/broadcast_messages_spec.rb2
-rw-r--r--spec/requests/api/commit_statuses_spec.rb6
-rw-r--r--spec/requests/api/commits_spec.rb45
-rw-r--r--spec/requests/api/deploy_keys_spec.rb2
-rw-r--r--spec/requests/api/deployments_spec.rb91
-rw-r--r--spec/requests/api/discussions_spec.rb2
-rw-r--r--spec/requests/api/doorkeeper_access_spec.rb2
-rw-r--r--spec/requests/api/environments_spec.rb2
-rw-r--r--spec/requests/api/events_spec.rb2
-rw-r--r--spec/requests/api/features_spec.rb17
-rw-r--r--spec/requests/api/files_spec.rb2
-rw-r--r--spec/requests/api/graphql/current_user/todos_query_spec.rb48
-rw-r--r--spec/requests/api/graphql/current_user_query_spec.rb33
-rw-r--r--spec/requests/api/graphql/gitlab_schema_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb134
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb108
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb79
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb66
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb63
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/todos/mark_done_spec.rb97
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb141
-rw-r--r--spec/requests/api/graphql/project/merge_request_spec.rb2
-rw-r--r--spec/requests/api/graphql/project_query_spec.rb2
-rw-r--r--spec/requests/api/group_boards_spec.rb2
-rw-r--r--spec/requests/api/group_clusters_spec.rb21
-rw-r--r--spec/requests/api/group_container_repositories_spec.rb10
-rw-r--r--spec/requests/api/group_export_spec.rb94
-rw-r--r--spec/requests/api/group_milestones_spec.rb2
-rw-r--r--spec/requests/api/group_variables_spec.rb2
-rw-r--r--spec/requests/api/groups_spec.rb2
-rw-r--r--spec/requests/api/helpers_spec.rb2
-rw-r--r--spec/requests/api/import_github_spec.rb2
-rw-r--r--spec/requests/api/internal/base_spec.rb12
-rw-r--r--spec/requests/api/jobs_spec.rb10
-rw-r--r--spec/requests/api/keys_spec.rb2
-rw-r--r--spec/requests/api/labels_spec.rb2
-rw-r--r--spec/requests/api/lint_spec.rb2
-rw-r--r--spec/requests/api/markdown_spec.rb2
-rw-r--r--spec/requests/api/members_spec.rb16
-rw-r--r--spec/requests/api/merge_request_diffs_spec.rb2
-rw-r--r--spec/requests/api/merge_requests_spec.rb75
-rw-r--r--spec/requests/api/namespaces_spec.rb2
-rw-r--r--spec/requests/api/notes_spec.rb2
-rw-r--r--spec/requests/api/notification_settings_spec.rb2
-rw-r--r--spec/requests/api/oauth_tokens_spec.rb2
-rw-r--r--spec/requests/api/pages/internal_access_spec.rb2
-rw-r--r--spec/requests/api/pages/private_access_spec.rb2
-rw-r--r--spec/requests/api/pages/public_access_spec.rb2
-rw-r--r--spec/requests/api/pages_domains_spec.rb96
-rw-r--r--spec/requests/api/pipeline_schedules_spec.rb2
-rw-r--r--spec/requests/api/pipelines_spec.rb2
-rw-r--r--spec/requests/api/project_clusters_spec.rb21
-rw-r--r--spec/requests/api/project_container_repositories_spec.rb9
-rw-r--r--spec/requests/api/project_events_spec.rb2
-rw-r--r--spec/requests/api/project_export_spec.rb4
-rw-r--r--spec/requests/api/project_hooks_spec.rb2
-rw-r--r--spec/requests/api/project_import_spec.rb4
-rw-r--r--spec/requests/api/project_milestones_spec.rb2
-rw-r--r--spec/requests/api/project_snapshots_spec.rb2
-rw-r--r--spec/requests/api/project_snippets_spec.rb2
-rw-r--r--spec/requests/api/project_templates_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb119
-rw-r--r--spec/requests/api/protected_branches_spec.rb2
-rw-r--r--spec/requests/api/protected_tags_spec.rb2
-rw-r--r--spec/requests/api/releases_spec.rb2
-rw-r--r--spec/requests/api/repositories_spec.rb2
-rw-r--r--spec/requests/api/runner_spec.rb6
-rw-r--r--spec/requests/api/runners_spec.rb2
-rw-r--r--spec/requests/api/search_spec.rb3
-rw-r--r--spec/requests/api/services_spec.rb6
-rw-r--r--spec/requests/api/settings_spec.rb82
-rw-r--r--spec/requests/api/sidekiq_metrics_spec.rb6
-rw-r--r--spec/requests/api/snippets_spec.rb2
-rw-r--r--spec/requests/api/system_hooks_spec.rb2
-rw-r--r--spec/requests/api/tags_spec.rb2
-rw-r--r--spec/requests/api/templates_spec.rb2
-rw-r--r--spec/requests/api/todos_spec.rb2
-rw-r--r--spec/requests/api/triggers_spec.rb2
-rw-r--r--spec/requests/api/users_spec.rb34
-rw-r--r--spec/requests/api/variables_spec.rb2
-rw-r--r--spec/requests/api/version_spec.rb2
-rw-r--r--spec/requests/api/wikis_spec.rb2
-rw-r--r--spec/requests/git_http_spec.rb36
-rw-r--r--spec/requests/groups/milestones_controller_spec.rb2
-rw-r--r--spec/requests/groups/registry/repositories_controller_spec.rb36
-rw-r--r--spec/requests/health_controller_spec.rb227
-rw-r--r--spec/requests/jwt_controller_spec.rb2
-rw-r--r--spec/requests/lfs_locks_api_spec.rb2
-rw-r--r--spec/requests/oauth_tokens_spec.rb2
-rw-r--r--spec/requests/openid_connect_spec.rb2
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb10
-rw-r--r--spec/requests/rack_attack_global_spec.rb64
-rw-r--r--spec/requests/request_profiler_spec.rb2
101 files changed, 1918 insertions, 160 deletions
diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb
index 100f3d33c7b..3bfca00776f 100644
--- a/spec/requests/api/access_requests_spec.rb
+++ b/spec/requests/api/access_requests_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::AccessRequests do
diff --git a/spec/requests/api/applications_spec.rb b/spec/requests/api/applications_spec.rb
index 53fc3096751..438d5dbf018 100644
--- a/spec/requests/api/applications_spec.rb
+++ b/spec/requests/api/applications_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Applications, :api do
diff --git a/spec/requests/api/avatar_spec.rb b/spec/requests/api/avatar_spec.rb
index 9bc49bd5982..c8bc7f8a4a2 100644
--- a/spec/requests/api/avatar_spec.rb
+++ b/spec/requests/api/avatar_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Avatar do
diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb
index 342fcfa1041..80040cddd4d 100644
--- a/spec/requests/api/award_emoji_spec.rb
+++ b/spec/requests/api/award_emoji_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::AwardEmoji do
diff --git a/spec/requests/api/badges_spec.rb b/spec/requests/api/badges_spec.rb
index 771a78a2d91..ea0a7d4c9b7 100644
--- a/spec/requests/api/badges_spec.rb
+++ b/spec/requests/api/badges_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Badges do
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index 0b9c0c2ebe9..8a67e956165 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Boards do
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index f9c8b42afa8..675b06b057c 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Branches do
@@ -117,6 +119,25 @@ describe API::Branches do
it_behaves_like 'repository branches'
end
+
+ it 'does not submit N+1 DB queries', :request_store do
+ create(:protected_branch, name: 'master', project: project)
+
+ # Make sure no setup step query is recorded.
+ get api(route, current_user), params: { per_page: 100 }
+
+ control = ActiveRecord::QueryRecorder.new do
+ get api(route, current_user), params: { per_page: 100 }
+ end
+
+ new_branch_name = 'protected-branch'
+ CreateBranchService.new(project, current_user).execute(new_branch_name, 'master')
+ create(:protected_branch, name: new_branch_name, project: project)
+
+ expect do
+ get api(route, current_user), params: { per_page: 100 }
+ end.not_to exceed_query_limit(control)
+ end
end
context 'when authenticated', 'as a guest' do
@@ -602,7 +623,7 @@ describe API::Branches do
post api(route, user), params: { branch: 'new_design3', ref: 'foo' }
expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Invalid reference name')
+ expect(json_response['message']).to eq('Invalid reference name: new_design3')
end
end
diff --git a/spec/requests/api/broadcast_messages_spec.rb b/spec/requests/api/broadcast_messages_spec.rb
index 0b48b79219c..541acb29857 100644
--- a/spec/requests/api/broadcast_messages_spec.rb
+++ b/spec/requests/api/broadcast_messages_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::BroadcastMessages do
diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb
index 6cb02ba2f6b..639b8e96343 100644
--- a/spec/requests/api/commit_statuses_spec.rb
+++ b/spec/requests/api/commit_statuses_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::CommitStatuses do
@@ -278,7 +280,7 @@ describe API::CommitStatuses do
}
end
- it 'update the correct pipeline' do
+ it 'update the correct pipeline', :sidekiq_might_not_need_inline do
subject
expect(first_pipeline.reload.status).to eq('created')
@@ -302,7 +304,7 @@ describe API::CommitStatuses do
expect(json_response['status']).to eq('success')
end
- it 'retries a commit status' do
+ it 'retries a commit status', :sidekiq_might_not_need_inline do
expect(CommitStatus.count).to eq 2
expect(CommitStatus.first).to be_retried
expect(CommitStatus.last.pipeline).to be_success
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 90ff1d12bf1..d8da1c001b0 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'mime/types'
@@ -369,7 +371,7 @@ describe API::Commits do
valid_c_params[:start_project] = public_project.id
end
- it 'adds a new commit to forked_project and returns a 201' do
+ it 'adds a new commit to forked_project and returns a 201', :sidekiq_might_not_need_inline do
expect_request_with_status(201) { post api(url, guest), params: valid_c_params }
.to change { last_commit_id(forked_project, valid_c_params[:branch]) }
.and not_change { last_commit_id(public_project, valid_c_params[:start_branch]) }
@@ -381,14 +383,14 @@ describe API::Commits do
valid_c_params[:start_project] = public_project.full_path
end
- it 'adds a new commit to forked_project and returns a 201' do
+ it 'adds a new commit to forked_project and returns a 201', :sidekiq_might_not_need_inline do
expect_request_with_status(201) { post api(url, guest), params: valid_c_params }
.to change { last_commit_id(forked_project, valid_c_params[:branch]) }
.and not_change { last_commit_id(public_project, valid_c_params[:start_branch]) }
end
end
- context 'when branch already exists' do
+ context 'when branch already exists', :sidekiq_might_not_need_inline do
before do
valid_c_params.delete(:start_branch)
valid_c_params[:branch] = 'master'
@@ -835,7 +837,7 @@ describe API::Commits do
}
end
- it 'allows pushing to the source branch of the merge request' do
+ it 'allows pushing to the source branch of the merge request', :sidekiq_might_not_need_inline do
post api(url, user), params: push_params('feature')
expect(response).to have_gitlab_http_status(:created)
@@ -1087,6 +1089,20 @@ describe API::Commits do
expect(json_response.first.keys).to include 'diff'
end
+ context 'when hard limits are lower than the number of files' do
+ before do
+ allow(Commit).to receive(:max_diff_options).and_return(max_files: 1)
+ end
+
+ it 'respects the limit' do
+ get api(route, current_user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response.size).to be <= 1
+ end
+ end
+
context 'when ref does not exist' do
let(:commit_id) { 'unknown' }
@@ -1360,6 +1376,12 @@ describe API::Commits do
it_behaves_like '400 response' do
let(:request) { post api(route, current_user), params: { branch: 'markdown' } }
end
+
+ it 'includes an error_code in the response' do
+ post api(route, current_user), params: { branch: 'markdown' }
+
+ expect(json_response['error_code']).to eq 'empty'
+ end
end
context 'when ref contains a dot' do
@@ -1417,7 +1439,7 @@ describe API::Commits do
let(:project_id) { forked_project.id }
- it 'allows access from a maintainer that to the source branch' do
+ it 'allows access from a maintainer that to the source branch', :sidekiq_might_not_need_inline do
post api(route, user), params: { branch: 'feature' }
expect(response).to have_gitlab_http_status(:created)
@@ -1519,6 +1541,19 @@ describe API::Commits do
let(:request) { post api(route, current_user) }
end
end
+
+ context 'when commit is already reverted in the target branch' do
+ it 'includes an error_code in the response' do
+ # First one actually reverts
+ post api(route, current_user), params: { branch: 'markdown' }
+
+ # Second one is redundant and should be empty
+ post api(route, current_user), params: { branch: 'markdown' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error_code']).to eq 'empty'
+ end
+ end
end
context 'when authenticated', 'as a developer' do
diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb
index e0cc18abcca..4579ccfad80 100644
--- a/spec/requests/api/deploy_keys_spec.rb
+++ b/spec/requests/api/deploy_keys_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::DeployKeys do
diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb
index ad7be531979..26849c0991d 100644
--- a/spec/requests/api/deployments_spec.rb
+++ b/spec/requests/api/deployments_spec.rb
@@ -12,9 +12,9 @@ describe API::Deployments do
describe 'GET /projects/:id/deployments' do
let(:project) { create(:project) }
- let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: Time.now) }
- let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago) }
- let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'patch', created_at: 2.days.ago) }
+ let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: Time.now, updated_at: Time.now) }
+ let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago, updated_at: 2.hours.ago) }
+ let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'patch', created_at: 2.days.ago, updated_at: 1.hour.ago) }
context 'as member of the project' do
it 'returns projects deployments sorted by id asc' do
@@ -57,6 +57,8 @@ describe API::Deployments do
'iid' | 'desc' | [:deployment_2, :deployment_1, :deployment_3]
'ref' | 'asc' | [:deployment_2, :deployment_1, :deployment_3]
'ref' | 'desc' | [:deployment_3, :deployment_1, :deployment_2]
+ 'updated_at' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
+ 'updated_at' | 'desc' | [:deployment_1, :deployment_3, :deployment_2]
end
with_them do
@@ -137,14 +139,42 @@ describe API::Deployments do
expect(response).to have_gitlab_http_status(500)
end
+
+ it 'links any merged merge requests to the deployment' do
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ source_project: project,
+ target_branch: 'master',
+ source_branch: 'foo'
+ )
+
+ post(
+ api("/projects/#{project.id}/deployments", user),
+ params: {
+ environment: 'production',
+ sha: sha,
+ ref: 'master',
+ tag: false,
+ status: 'success'
+ }
+ )
+
+ deploy = project.deployments.last
+
+ expect(deploy.merge_requests).to eq([mr])
+ end
end
context 'as a developer' do
- it 'creates a new deployment' do
- developer = create(:user)
+ let(:developer) { create(:user) }
+ before do
project.add_developer(developer)
+ end
+ it 'creates a new deployment' do
post(
api("/projects/#{project.id}/deployments", developer),
params: {
@@ -161,6 +191,32 @@ describe API::Deployments do
expect(json_response['sha']).to eq(sha)
expect(json_response['ref']).to eq('master')
end
+
+ it 'links any merged merge requests to the deployment' do
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ source_project: project,
+ target_branch: 'master',
+ source_branch: 'foo'
+ )
+
+ post(
+ api("/projects/#{project.id}/deployments", developer),
+ params: {
+ environment: 'production',
+ sha: sha,
+ ref: 'master',
+ tag: false,
+ status: 'success'
+ }
+ )
+
+ deploy = project.deployments.last
+
+ expect(deploy.merge_requests).to eq([mr])
+ end
end
context 'as non member' do
@@ -182,7 +238,7 @@ describe API::Deployments do
end
describe 'PUT /projects/:id/deployments/:deployment_id' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:build) { create(:ci_build, :failed, project: project) }
let(:environment) { create(:environment, project: project) }
let(:deploy) do
@@ -191,7 +247,8 @@ describe API::Deployments do
:failed,
project: project,
environment: environment,
- deployable: nil
+ deployable: nil,
+ sha: project.commit.sha
)
end
@@ -216,6 +273,26 @@ describe API::Deployments do
expect(response).to have_gitlab_http_status(200)
expect(json_response['status']).to eq('success')
end
+
+ it 'links merge requests when the deployment status changes to success', :sidekiq_inline do
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ source_project: project,
+ target_branch: 'master',
+ source_branch: 'foo'
+ )
+
+ put(
+ api("/projects/#{project.id}/deployments/#{deploy.id}", user),
+ params: { status: 'success' }
+ )
+
+ deploy = project.deployments.last
+
+ expect(deploy.merge_requests).to eq([mr])
+ end
end
context 'as a developer' do
diff --git a/spec/requests/api/discussions_spec.rb b/spec/requests/api/discussions_spec.rb
index 0420201efe3..68f7d407b54 100644
--- a/spec/requests/api/discussions_spec.rb
+++ b/spec/requests/api/discussions_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Discussions do
diff --git a/spec/requests/api/doorkeeper_access_spec.rb b/spec/requests/api/doorkeeper_access_spec.rb
index cfee3f6c0f8..2a34e623a7e 100644
--- a/spec/requests/api/doorkeeper_access_spec.rb
+++ b/spec/requests/api/doorkeeper_access_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'doorkeeper access' do
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index 745f3c55ac8..aa273e97209 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Environments do
diff --git a/spec/requests/api/events_spec.rb b/spec/requests/api/events_spec.rb
index 992fd5e9c66..9f8d254a00c 100644
--- a/spec/requests/api/events_spec.rb
+++ b/spec/requests/api/events_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Events do
diff --git a/spec/requests/api/features_spec.rb b/spec/requests/api/features_spec.rb
index 57a57e69a00..dfd14f89dbf 100644
--- a/spec/requests/api/features_spec.rb
+++ b/spec/requests/api/features_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Features do
@@ -118,14 +120,13 @@ describe API::Features do
post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username, feature_group: 'perf_team' }
expect(response).to have_gitlab_http_status(201)
- expect(json_response).to eq(
- 'name' => 'my_feature',
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'groups', 'value' => ['perf_team'] },
- { 'key' => 'actors', 'value' => ["User:#{user.id}"] }
- ])
+ expect(json_response['name']).to eq('my_feature')
+ expect(json_response['state']).to eq('conditional')
+ expect(json_response['gates']).to contain_exactly(
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'groups', 'value' => ['perf_team'] },
+ { 'key' => 'actors', 'value' => ["User:#{user.id}"] }
+ )
end
end
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index 21b67357543..ec18156f49f 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Files do
diff --git a/spec/requests/api/graphql/current_user/todos_query_spec.rb b/spec/requests/api/graphql/current_user/todos_query_spec.rb
new file mode 100644
index 00000000000..82deba0d92c
--- /dev/null
+++ b/spec/requests/api/graphql/current_user/todos_query_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Query current user todos' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:commit_todo) { create(:on_commit_todo, user: current_user, project: create(:project, :repository)) }
+ let_it_be(:issue_todo) { create(:todo, user: current_user, target: create(:issue)) }
+ let_it_be(:merge_request_todo) { create(:todo, user: current_user, target: create(:merge_request)) }
+
+ let(:fields) do
+ <<~QUERY
+ nodes {
+ #{all_graphql_fields_for('todos'.classify)}
+ }
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for('currentUser', {}, query_graphql_field('todos', {}, fields))
+ end
+
+ subject { graphql_data.dig('currentUser', 'todos', 'nodes') }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'contains the expected ids' do
+ is_expected.to include(
+ a_hash_including('id' => commit_todo.to_global_id.to_s),
+ a_hash_including('id' => issue_todo.to_global_id.to_s),
+ a_hash_including('id' => merge_request_todo.to_global_id.to_s)
+ )
+ end
+
+ it 'returns Todos for all target types' do
+ is_expected.to include(
+ a_hash_including('targetType' => 'COMMIT'),
+ a_hash_including('targetType' => 'ISSUE'),
+ a_hash_including('targetType' => 'MERGEREQUEST')
+ )
+ end
+end
diff --git a/spec/requests/api/graphql/current_user_query_spec.rb b/spec/requests/api/graphql/current_user_query_spec.rb
new file mode 100644
index 00000000000..9db638ea59e
--- /dev/null
+++ b/spec/requests/api/graphql/current_user_query_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'getting project information' do
+ include GraphqlHelpers
+
+ let(:query) do
+ graphql_query_for('currentUser', {}, 'name')
+ end
+
+ subject { graphql_data['currentUser'] }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ context 'when there is a current_user' do
+ set(:current_user) { create(:user) }
+
+ it_behaves_like 'a working graphql query'
+
+ it { is_expected.to include('name' => current_user.name) }
+ end
+
+ context 'when there is no current_user' do
+ let(:current_user) { nil }
+
+ it_behaves_like 'a working graphql query'
+
+ it { is_expected.to be_nil }
+ end
+end
diff --git a/spec/requests/api/graphql/gitlab_schema_spec.rb b/spec/requests/api/graphql/gitlab_schema_spec.rb
index 1e799a0a42a..2aeb75a10b4 100644
--- a/spec/requests/api/graphql/gitlab_schema_spec.rb
+++ b/spec/requests/api/graphql/gitlab_schema_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'GitlabSchema configurations' do
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb
new file mode 100644
index 00000000000..8f908b7bf88
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Setting assignees of a merge request' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:assignee) { create(:user) }
+ let(:assignee2) { create(:user) }
+ let(:input) { { assignee_usernames: [assignee.username] } }
+ let(:expected_result) do
+ [{ 'username' => assignee.username }]
+ end
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_set_assignees, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ mergeRequest {
+ id
+ assignees {
+ nodes {
+ username
+ }
+ }
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_set_assignees)
+ end
+
+ def mutation_assignee_nodes
+ mutation_response['mergeRequest']['assignees']['nodes']
+ end
+
+ before do
+ project.add_developer(current_user)
+ project.add_developer(assignee)
+ project.add_developer(assignee2)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'does not allow members without the right permission to add assignees' do
+ user = create(:user)
+ project.add_guest(user)
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ context 'with assignees already assigned' do
+ before do
+ merge_request.assignees = [assignee2]
+ merge_request.save!
+ end
+
+ it 'replaces the assignee' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_assignee_nodes).to match_array(expected_result)
+ end
+ end
+
+ context 'when passing an empty list of assignees' do
+ let(:input) { { assignee_usernames: [] } }
+
+ before do
+ merge_request.assignees = [assignee2]
+ merge_request.save!
+ end
+
+ it 'removes assignee' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_assignee_nodes).to eq([])
+ end
+ end
+
+ context 'when passing append as true' do
+ let(:input) { { assignee_usernames: [assignee2.username], operation_mode: Types::MutationOperationModeEnum.enum[:append] } }
+
+ before do
+ # In CE, APPEND is a NOOP as you can't have multiple assignees
+ # We test multiple assignment in EE specs
+ stub_licensed_features(multiple_merge_request_assignees: false)
+
+ merge_request.assignees = [assignee]
+ merge_request.save!
+ end
+
+ it 'does not replace the assignee in CE' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_assignee_nodes).to match_array(expected_result)
+ end
+ end
+
+ context 'when passing remove as true' do
+ let(:input) { { assignee_usernames: [assignee.username], operation_mode: Types::MutationOperationModeEnum.enum[:remove] } }
+ let(:expected_result) { [] }
+
+ before do
+ merge_request.assignees = [assignee]
+ merge_request.save!
+ end
+
+ it 'removes the users in the list, while adding none' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_assignee_nodes).to match_array(expected_result)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb
new file mode 100644
index 00000000000..2112ff0dc74
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Setting labels of a merge request' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:label) { create(:label, project: project) }
+ let(:label2) { create(:label, project: project) }
+ let(:input) { { label_ids: [GitlabSchema.id_from_object(label).to_s] } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_set_labels, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ mergeRequest {
+ id
+ labels {
+ nodes {
+ id
+ }
+ }
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_set_labels)
+ end
+
+ def mutation_label_nodes
+ mutation_response['mergeRequest']['labels']['nodes']
+ end
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'sets the merge request labels, removing existing ones' do
+ merge_request.update(labels: [label2])
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_label_nodes.count).to eq(1)
+ expect(mutation_label_nodes[0]['id']).to eq(label.to_global_id.to_s)
+ end
+
+ context 'when passing label_ids empty array as input' do
+ let(:input) { { label_ids: [] } }
+
+ it 'removes the merge request labels' do
+ merge_request.update!(labels: [label])
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_label_nodes.count).to eq(0)
+ end
+ end
+
+ context 'when passing operation_mode as APPEND' do
+ let(:input) { { operation_mode: Types::MutationOperationModeEnum.enum[:append], label_ids: [GitlabSchema.id_from_object(label).to_s] } }
+
+ before do
+ merge_request.update!(labels: [label2])
+ end
+
+ it 'sets the labels, without removing others' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_label_nodes.count).to eq(2)
+ expect(mutation_label_nodes).to contain_exactly({ 'id' => label.to_global_id.to_s }, { 'id' => label2.to_global_id.to_s })
+ end
+ end
+
+ context 'when passing operation_mode as REMOVE' do
+ let(:input) { { operation_mode: Types::MutationOperationModeEnum.enum[:remove], label_ids: [GitlabSchema.id_from_object(label).to_s] } }
+
+ before do
+ merge_request.update!(labels: [label, label2])
+ end
+
+ it 'removes the labels, without removing others' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_label_nodes.count).to eq(1)
+ expect(mutation_label_nodes[0]['id']).to eq(label2.to_global_id.to_s)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb
new file mode 100644
index 00000000000..c45da613591
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Setting locked status of a merge request' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:input) { { locked: true } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_set_locked, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ mergeRequest {
+ id
+ discussionLocked
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_set_locked)['mergeRequest']['discussionLocked']
+ end
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'marks the merge request as WIP' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response).to eq(true)
+ end
+
+ it 'does not do anything if the merge request was already locked' do
+ merge_request.update!(discussion_locked: true)
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response).to eq(true)
+ end
+
+ context 'when passing locked false as input' do
+ let(:input) { { locked: false } }
+
+ it 'does not do anything if the merge request was not marked locked' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response).to eq(false)
+ end
+
+ it 'unmarks the merge request as locked' do
+ merge_request.update!(discussion_locked: true)
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response).to eq(false)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb
new file mode 100644
index 00000000000..bd558edf9c5
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Setting milestone of a merge request' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:milestone) { create(:milestone, project: project) }
+ let(:input) { { milestone_id: GitlabSchema.id_from_object(milestone).to_s } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_set_milestone, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ mergeRequest {
+ id
+ milestone {
+ id
+ }
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_set_milestone)
+ end
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'sets the merge request milestone' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['mergeRequest']['milestone']['id']).to eq(milestone.to_global_id.to_s)
+ end
+
+ context 'when passing milestone_id nil as input' do
+ let(:input) { { milestone_id: nil } }
+
+ it 'removes the merge request milestone' do
+ merge_request.update!(milestone: milestone)
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['mergeRequest']['milestone']).to be_nil
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb
new file mode 100644
index 00000000000..975735bf246
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Setting subscribed status of a merge request' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:input) { { subscribed_state: true } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_set_subscription, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ mergeRequest {
+ id
+ subscribed
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_set_subscription)['mergeRequest']['subscribed']
+ end
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'marks the merge request as WIP' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response).to eq(true)
+ end
+
+ context 'when passing subscribe false as input' do
+ let(:input) { { subscribed_state: false } }
+
+ it 'unmarks the merge request as subscribed' do
+ merge_request.subscribe(current_user, project)
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response).to eq(false)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
index bbc477ba485..4492c51dbd7 100644
--- a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Setting WIP status of a merge request' do
diff --git a/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb
new file mode 100644
index 00000000000..fabbb3aeb49
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Marking todos done' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
+
+ let_it_be(:todo1) { create(:todo, user: current_user, author: author, state: :pending) }
+ let_it_be(:todo2) { create(:todo, user: current_user, author: author, state: :done) }
+
+ let_it_be(:other_user_todo) { create(:todo, user: other_user, author: author, state: :pending) }
+
+ let(:input) { { id: todo1.to_global_id.to_s } }
+
+ let(:mutation) do
+ graphql_mutation(:todo_mark_done, input,
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ todo {
+ id
+ state
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:todo_mark_done)
+ end
+
+ it 'marks a single todo as done' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(todo1.reload.state).to eq('done')
+ expect(todo2.reload.state).to eq('done')
+ expect(other_user_todo.reload.state).to eq('pending')
+
+ todo = mutation_response['todo']
+ expect(todo['id']).to eq(todo1.to_global_id.to_s)
+ expect(todo['state']).to eq('done')
+ end
+
+ context 'when todo is already marked done' do
+ let(:input) { { id: todo2.to_global_id.to_s } }
+
+ it 'has the expected response' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(todo1.reload.state).to eq('pending')
+ expect(todo2.reload.state).to eq('done')
+ expect(other_user_todo.reload.state).to eq('pending')
+
+ todo = mutation_response['todo']
+ expect(todo['id']).to eq(todo2.to_global_id.to_s)
+ expect(todo['state']).to eq('done')
+ end
+ end
+
+ context 'when todo does not belong to requesting user' do
+ let(:input) { { id: other_user_todo.to_global_id.to_s } }
+ let(:access_error) { 'The resource that you are attempting to access does not exist or you don\'t have permission to perform this action' }
+
+ it 'contains the expected error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ errors = json_response['errors']
+ expect(errors).not_to be_blank
+ expect(errors.first['message']).to eq(access_error)
+
+ expect(todo1.reload.state).to eq('pending')
+ expect(todo2.reload.state).to eq('done')
+ expect(other_user_todo.reload.state).to eq('pending')
+ end
+ end
+
+ context 'when using an invalid gid' do
+ let(:input) { { id: 'invalid_gid' } }
+ let(:invalid_gid_error) { 'invalid_gid is not a valid GitLab id.' }
+
+ it 'contains the expected error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ errors = json_response['errors']
+ expect(errors).not_to be_blank
+ expect(errors.first['message']).to eq(invalid_gid_error)
+
+ expect(todo1.reload.state).to eq('pending')
+ expect(todo2.reload.state).to eq('done')
+ expect(other_user_todo.reload.state).to eq('pending')
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 4f9f916f22e..4ce7a3912a3 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'getting an issue list for a project' do
@@ -62,7 +64,7 @@ describe 'getting an issue list for a project' do
end
end
- it "is expected to check permissions on the first issue only" do
+ it 'is expected to check permissions on the first issue only' do
allow(Ability).to receive(:allowed?).and_call_original
# Newest first, we only want to see the newest checked
expect(Ability).not_to receive(:allowed?).with(current_user, :read_issue, issues.first)
@@ -114,4 +116,141 @@ describe 'getting an issue list for a project' do
end
end
end
+
+ describe 'sorting and pagination' do
+ let(:start_cursor) { graphql_data['project']['issues']['pageInfo']['startCursor'] }
+ let(:end_cursor) { graphql_data['project']['issues']['pageInfo']['endCursor'] }
+
+ context 'when sorting by due date' do
+ let(:sort_project) { create(:project, :public) }
+
+ let!(:due_issue1) { create(:issue, project: sort_project, due_date: 3.days.from_now) }
+ let!(:due_issue2) { create(:issue, project: sort_project, due_date: nil) }
+ let!(:due_issue3) { create(:issue, project: sort_project, due_date: 2.days.ago) }
+ let!(:due_issue4) { create(:issue, project: sort_project, due_date: nil) }
+ let!(:due_issue5) { create(:issue, project: sort_project, due_date: 1.day.ago) }
+
+ let(:params) { 'sort: DUE_DATE_ASC' }
+
+ def query(issue_params = params)
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => sort_project.full_path },
+ <<~ISSUES
+ issues(#{issue_params}) {
+ pageInfo {
+ endCursor
+ }
+ edges {
+ node {
+ iid
+ dueDate
+ }
+ }
+ }
+ ISSUES
+ )
+ end
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ context 'when ascending' do
+ it 'sorts issues' do
+ expect(grab_iids).to eq [due_issue3.iid, due_issue5.iid, due_issue1.iid, due_issue4.iid, due_issue2.iid]
+ end
+
+ context 'when paginating' do
+ let(:params) { 'sort: DUE_DATE_ASC, first: 2' }
+
+ it 'sorts issues' do
+ expect(grab_iids).to eq [due_issue3.iid, due_issue5.iid]
+
+ cursored_query = query("sort: DUE_DATE_ASC, after: \"#{end_cursor}\"")
+ post_graphql(cursored_query, current_user: current_user)
+ response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+
+ expect(grab_iids(response_data)).to eq [due_issue1.iid, due_issue4.iid, due_issue2.iid]
+ end
+ end
+ end
+
+ context 'when descending' do
+ let(:params) { 'sort: DUE_DATE_DESC' }
+
+ it 'sorts issues' do
+ expect(grab_iids).to eq [due_issue1.iid, due_issue5.iid, due_issue3.iid, due_issue4.iid, due_issue2.iid]
+ end
+
+ context 'when paginating' do
+ let(:params) { 'sort: DUE_DATE_DESC, first: 2' }
+
+ it 'sorts issues' do
+ expect(grab_iids).to eq [due_issue1.iid, due_issue5.iid]
+
+ cursored_query = query("sort: DUE_DATE_DESC, after: \"#{end_cursor}\"")
+ post_graphql(cursored_query, current_user: current_user)
+ response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+
+ expect(grab_iids(response_data)).to eq [due_issue3.iid, due_issue4.iid, due_issue2.iid]
+ end
+ end
+ end
+ end
+
+ context 'when sorting by relative position' do
+ let(:sort_project) { create(:project, :public) }
+
+ let!(:relative_issue1) { create(:issue, project: sort_project, relative_position: 2000) }
+ let!(:relative_issue2) { create(:issue, project: sort_project, relative_position: nil) }
+ let!(:relative_issue3) { create(:issue, project: sort_project, relative_position: 1000) }
+ let!(:relative_issue4) { create(:issue, project: sort_project, relative_position: nil) }
+ let!(:relative_issue5) { create(:issue, project: sort_project, relative_position: 500) }
+
+ let(:params) { 'sort: RELATIVE_POSITION_ASC' }
+
+ def query(issue_params = params)
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => sort_project.full_path },
+ "issues(#{issue_params}) { pageInfo { endCursor} edges { node { iid dueDate } } }"
+ )
+ end
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ context 'when ascending' do
+ it 'sorts issues' do
+ expect(grab_iids).to eq [relative_issue5.iid, relative_issue3.iid, relative_issue1.iid, relative_issue4.iid, relative_issue2.iid]
+ end
+
+ context 'when paginating' do
+ let(:params) { 'sort: RELATIVE_POSITION_ASC, first: 2' }
+
+ it 'sorts issues' do
+ expect(grab_iids).to eq [relative_issue5.iid, relative_issue3.iid]
+
+ cursored_query = query("sort: RELATIVE_POSITION_ASC, after: \"#{end_cursor}\"")
+ post_graphql(cursored_query, current_user: current_user)
+ response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+
+ expect(grab_iids(response_data)).to eq [relative_issue1.iid, relative_issue4.iid, relative_issue2.iid]
+ end
+ end
+ end
+ end
+ end
+
+ def grab_iids(data = issues_data)
+ data.map do |issue|
+ issue.dig('node', 'iid').to_i
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb
index 74820d39102..70c21666799 100644
--- a/spec/requests/api/graphql/project/merge_request_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'getting merge request information nested in a project' do
diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb
index 0727ada4691..fbb22958d51 100644
--- a/spec/requests/api/graphql/project_query_spec.rb
+++ b/spec/requests/api/graphql/project_query_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'getting project information' do
diff --git a/spec/requests/api/group_boards_spec.rb b/spec/requests/api/group_boards_spec.rb
index b400a7f55ef..232ec9aca32 100644
--- a/spec/requests/api/group_boards_spec.rb
+++ b/spec/requests/api/group_boards_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::GroupBoards do
diff --git a/spec/requests/api/group_clusters_spec.rb b/spec/requests/api/group_clusters_spec.rb
index 46e3dd650cc..97465647a87 100644
--- a/spec/requests/api/group_clusters_spec.rb
+++ b/spec/requests/api/group_clusters_spec.rb
@@ -286,12 +286,15 @@ describe API::GroupClusters do
let(:update_params) do
{
domain: domain,
- platform_kubernetes_attributes: platform_kubernetes_attributes
+ platform_kubernetes_attributes: platform_kubernetes_attributes,
+ management_project_id: management_project_id
}
end
let(:domain) { 'new-domain.com' }
let(:platform_kubernetes_attributes) { {} }
+ let(:management_project) { create(:project, group: group) }
+ let(:management_project_id) { management_project.id }
let(:cluster) do
create(:cluster, :group, :provided_by_gcp,
@@ -308,6 +311,8 @@ describe API::GroupClusters do
context 'authorized user' do
before do
+ management_project.add_maintainer(current_user)
+
put api("/groups/#{group.id}/clusters/#{cluster.id}", current_user), params: update_params
cluster.reload
@@ -320,6 +325,7 @@ describe API::GroupClusters do
it 'updates cluster attributes' do
expect(cluster.domain).to eq('new-domain.com')
+ expect(cluster.management_project).to eq(management_project)
end
end
@@ -332,6 +338,7 @@ describe API::GroupClusters do
it 'does not update cluster attributes' do
expect(cluster.domain).to eq('old-domain.com')
+ expect(cluster.management_project).to be_nil
end
it 'returns validation errors' do
@@ -339,6 +346,18 @@ describe API::GroupClusters do
end
end
+ context 'current user does not have access to management_project_id' do
+ let(:management_project_id) { create(:project).id }
+
+ it 'responds with 400' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns validation errors' do
+ expect(json_response['message']['management_project_id'].first).to match('don\'t have permission')
+ end
+ end
+
context 'with a GCP cluster' do
context 'when user tries to change GCP specific fields' do
let(:platform_kubernetes_attributes) do
diff --git a/spec/requests/api/group_container_repositories_spec.rb b/spec/requests/api/group_container_repositories_spec.rb
index 0a41e455d01..785006253d8 100644
--- a/spec/requests/api/group_container_repositories_spec.rb
+++ b/spec/requests/api/group_container_repositories_spec.rb
@@ -3,10 +3,10 @@
require 'spec_helper'
describe API::GroupContainerRepositories do
- set(:group) { create(:group, :private) }
- set(:project) { create(:project, :private, group: group) }
- let(:reporter) { create(:user) }
- let(:guest) { create(:user) }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:project) { create(:project, :private, group: group) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:guest) { create(:user) }
let(:root_repository) { create(:container_repository, :root, project: project) }
let(:test_repository) { create(:container_repository, project: project) }
@@ -44,6 +44,8 @@ describe API::GroupContainerRepositories do
let(:object) { group }
end
+ it_behaves_like 'a gitlab tracking event', described_class.name, 'list_repositories'
+
context 'with invalid group id' do
let(:url) { '/groups/123412341234/registry/repositories' }
diff --git a/spec/requests/api/group_export_spec.rb b/spec/requests/api/group_export_spec.rb
new file mode 100644
index 00000000000..ac4853e5388
--- /dev/null
+++ b/spec/requests/api/group_export_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::GroupExport do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+
+ let(:path) { "/groups/#{group.id}/export" }
+ let(:download_path) { "/groups/#{group.id}/export/download" }
+
+ let(:export_path) { "#{Dir.tmpdir}/group_export_spec" }
+
+ before do
+ allow_next_instance_of(Gitlab::ImportExport) do |import_export|
+ expect(import_export).to receive(:storage_path).and_return(export_path)
+ end
+ end
+
+ after do
+ FileUtils.rm_rf(export_path, secure: true)
+ end
+
+ describe 'GET /groups/:group_id/export/download' do
+ let(:upload) { ImportExportUpload.new(group: group) }
+
+ before do
+ stub_uploads_object_storage(ImportExportUploader)
+
+ group.add_owner(user)
+ end
+
+ context 'when export file exists' do
+ before do
+ upload.export_file = fixture_file_upload('spec/fixtures/group_export.tar.gz', "`/tar.gz")
+ upload.save!
+ end
+
+ it 'downloads exported group archive' do
+ get api(download_path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+
+ context 'when export_file.file does not exist' do
+ before do
+ expect_next_instance_of(ImportExportUploader) do |uploader|
+ expect(uploader).to receive(:file).and_return(nil)
+ end
+ end
+
+ it 'returns 404' do
+ get api(download_path, user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
+ context 'when export file does not exist' do
+ it 'returns 404' do
+ get api(download_path, user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
+ describe 'POST /groups/:group_id/export' do
+ context 'when user is a group owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'accepts download' do
+ post api(path, user)
+
+ expect(response).to have_gitlab_http_status(202)
+ end
+ end
+
+ context 'when user is not a group owner' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'forbids the request' do
+ post api(path, user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/group_milestones_spec.rb b/spec/requests/api/group_milestones_spec.rb
index 6980eb7f55d..3e9b6246434 100644
--- a/spec/requests/api/group_milestones_spec.rb
+++ b/spec/requests/api/group_milestones_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::GroupMilestones do
diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb
index d50bae3dc47..abdc3a40360 100644
--- a/spec/requests/api/group_variables_spec.rb
+++ b/spec/requests/api/group_variables_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::GroupVariables do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 902a5ec2a86..cb97398805a 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Groups do
diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb
index a1a007811fe..bbfe40041a1 100644
--- a/spec/requests/api/helpers_spec.rb
+++ b/spec/requests/api/helpers_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'raven/transports/dummy'
require_relative '../../../config/initializers/sentry'
diff --git a/spec/requests/api/import_github_spec.rb b/spec/requests/api/import_github_spec.rb
index 68df02d4d8d..3ff7102479c 100644
--- a/spec/requests/api/import_github_spec.rb
+++ b/spec/requests/api/import_github_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ImportGithub do
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 01a2e33c0d9..fcff2cde730 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Internal::Base do
@@ -316,6 +318,7 @@ describe API::Internal::Base do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
+ expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-get-all-lfs-pointers-go' => 'true', 'gitaly-feature-inforef-uploadpack-cache' => 'true')
expect(user.reload.last_activity_on).to eql(Date.today)
end
end
@@ -335,6 +338,7 @@ describe API::Internal::Base do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
+ expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-get-all-lfs-pointers-go' => 'true', 'gitaly-feature-inforef-uploadpack-cache' => 'true')
expect(user.reload.last_activity_on).to be_nil
end
end
@@ -407,7 +411,6 @@ describe API::Internal::Base do
context "custom action" do
let(:access_checker) { double(Gitlab::GitAccess) }
- let(:message) { 'CustomActionError message' }
let(:payload) do
{
'action' => 'geo_proxy_to_primary',
@@ -418,8 +421,8 @@ describe API::Internal::Base do
}
}
end
-
- let(:custom_action_result) { Gitlab::GitAccessResult::CustomAction.new(payload, message) }
+ let(:console_messages) { ['informational message'] }
+ let(:custom_action_result) { Gitlab::GitAccessResult::CustomAction.new(payload, console_messages) }
before do
project.add_guest(user)
@@ -446,8 +449,8 @@ describe API::Internal::Base do
expect(response).to have_gitlab_http_status(300)
expect(json_response['status']).to be_truthy
- expect(json_response['message']).to eql(message)
expect(json_response['payload']).to eql(payload)
+ expect(json_response['gl_console_messages']).to eql(console_messages)
expect(user.reload.last_activity_on).to be_nil
end
end
@@ -577,6 +580,7 @@ describe API::Internal::Base do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
+ expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-get-all-lfs-pointers-go' => 'true', 'gitaly-feature-inforef-uploadpack-cache' => 'true')
end
end
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 89ee6f896f9..020e7659a4c 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Jobs do
@@ -595,7 +597,7 @@ describe API::Jobs do
context 'find proper job' do
shared_examples 'a valid file' do
- context 'when artifacts are stored locally' do
+ context 'when artifacts are stored locally', :sidekiq_might_not_need_inline do
let(:download_headers) do
{ 'Content-Transfer-Encoding' => 'binary',
'Content-Disposition' =>
@@ -674,7 +676,7 @@ describe API::Jobs do
let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
let(:public_builds) { true }
- it 'allows to access artifacts' do
+ it 'allows to access artifacts', :sidekiq_might_not_need_inline do
expect(response).to have_gitlab_http_status(200)
expect(response.headers.to_h)
.to include('Content-Type' => 'application/json',
@@ -711,7 +713,7 @@ describe API::Jobs do
let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
let(:public_builds) { true }
- it 'returns a specific artifact file for a valid path' do
+ it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do
expect(Gitlab::Workhorse)
.to receive(:send_artifacts_entry)
.and_call_original
@@ -732,7 +734,7 @@ describe API::Jobs do
sha: project.commit('improve/awesome').sha)
end
- it 'returns a specific artifact file for a valid path' do
+ it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do
get_artifact_file(artifact, 'improve/awesome')
expect(response).to have_gitlab_http_status(200)
diff --git a/spec/requests/api/keys_spec.rb b/spec/requests/api/keys_spec.rb
index f37d84fddef..6802a0cfdab 100644
--- a/spec/requests/api/keys_spec.rb
+++ b/spec/requests/api/keys_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Keys do
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 7089da3d351..d027738c8db 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Labels do
diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb
index f52cdf1c459..46d23bd16b9 100644
--- a/spec/requests/api/lint_spec.rb
+++ b/spec/requests/api/lint_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Lint do
diff --git a/spec/requests/api/markdown_spec.rb b/spec/requests/api/markdown_spec.rb
index 0cf5c5677b9..99263f2fc1e 100644
--- a/spec/requests/api/markdown_spec.rb
+++ b/spec/requests/api/markdown_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe API::Markdown do
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index eb55d747179..f2942020e16 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Members do
@@ -24,7 +26,7 @@ describe API::Members do
shared_examples 'GET /:source_type/:id/members/(all)' do |source_type, all|
let(:members_url) do
- "/#{source_type.pluralize}/#{source.id}/members".tap do |url|
+ (+"/#{source_type.pluralize}/#{source.id}/members").tap do |url|
url << "/all" if all
end
end
@@ -149,9 +151,15 @@ describe API::Members do
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.map { |u| u['id'] }).to eq [developer.id, maintainer.id, nested_user.id, project_user.id, linked_group_user.id]
- expect(json_response.map { |u| u['access_level'] }).to eq [Gitlab::Access::DEVELOPER, Gitlab::Access::OWNER, Gitlab::Access::DEVELOPER,
- Gitlab::Access::DEVELOPER, Gitlab::Access::DEVELOPER]
+
+ expected_users_and_access_levels = [
+ [developer.id, Gitlab::Access::DEVELOPER],
+ [maintainer.id, Gitlab::Access::OWNER],
+ [nested_user.id, Gitlab::Access::DEVELOPER],
+ [project_user.id, Gitlab::Access::DEVELOPER],
+ [linked_group_user.id, Gitlab::Access::DEVELOPER]
+ ]
+ expect(json_response.map { |u| [u['id'], u['access_level']] }).to match_array(expected_users_and_access_levels)
end
it 'finds all group members including inherited members' do
diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb
index 8a67d98fc4c..9de76c2fe50 100644
--- a/spec/requests/api/merge_request_diffs_spec.rb
+++ b/spec/requests/api/merge_request_diffs_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe API::MergeRequestDiffs, 'MergeRequestDiffs' do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 05160a33e61..c96c80b6998 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe API::MergeRequests do
@@ -10,7 +12,7 @@ describe API::MergeRequests do
let(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let(:milestone1) { create(:milestone, title: '0.9', project: project) }
- let!(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Test", created_at: base_time) }
+ let!(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
let!(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignees: [user], source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
let!(:merge_request_locked) { create(:merge_request, state: "locked", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Locked test", created_at: base_time + 1.second) }
@@ -699,16 +701,20 @@ describe API::MergeRequests do
expect(json_response.first['id']).to eq merge_request_closed.id
end
- it 'avoids N+1 queries' do
- control = ActiveRecord::QueryRecorder.new do
- get api("/projects/#{project.id}/merge_requests", user)
- end.count
+ context 'a project which enforces all discussions to be resolved' do
+ let!(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: true) }
- create(:merge_request, author: user, assignees: [user], source_project: project, target_project: project, created_at: base_time)
+ it 'avoids N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new do
+ get api("/projects/#{project.id}/merge_requests", user)
+ end.count
- expect do
- get api("/projects/#{project.id}/merge_requests", user)
- end.not_to exceed_query_limit(control)
+ create(:merge_request, author: user, assignees: [user], source_project: project, target_project: project, created_at: base_time)
+
+ expect do
+ get api("/projects/#{project.id}/merge_requests", user)
+ end.not_to exceed_query_limit(control)
+ end
end
end
@@ -775,6 +781,8 @@ describe API::MergeRequests do
expect(json_response['merge_error']).to eq(merge_request.merge_error)
expect(json_response['user']['can_merge']).to be_truthy
expect(json_response).not_to include('rebase_in_progress')
+ expect(json_response['has_conflicts']).to be_falsy
+ expect(json_response['blocking_discussions_resolved']).to be_truthy
end
it 'exposes description and title html when render_html is true' do
@@ -921,7 +929,7 @@ describe API::MergeRequests do
allow_collaboration: true)
end
- it 'includes the `allow_collaboration` field' do
+ it 'includes the `allow_collaboration` field', :sidekiq_might_not_need_inline do
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user)
expect(json_response['allow_collaboration']).to be_truthy
@@ -1035,14 +1043,12 @@ describe API::MergeRequests do
describe 'POST /projects/:id/merge_requests/:merge_request_iid/pipelines' do
before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:ci_yaml_file)
- .and_return(YAML.dump({
- rspec: {
- script: 'ls',
- only: ['merge_requests']
- }
- }))
+ stub_ci_pipeline_yaml_file(YAML.dump({
+ rspec: {
+ script: 'ls',
+ only: ['merge_requests']
+ }
+ }))
end
let(:project) do
@@ -1326,7 +1332,7 @@ describe API::MergeRequests do
context 'accepts remove_source_branch parameter' do
let(:params) do
{ title: 'Test merge_request',
- source_branch: 'markdown',
+ source_branch: 'feature_conflict',
target_branch: 'master',
author: user }
end
@@ -1406,7 +1412,7 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(400)
end
- it 'allows setting `allow_collaboration`' do
+ it 'allows setting `allow_collaboration`', :sidekiq_might_not_need_inline do
post api("/projects/#{forked_project.id}/merge_requests", user2),
params: { title: 'Test merge_request', source_branch: "feature_conflict", target_branch: "master", author: user2, target_project_id: project.id, allow_collaboration: true }
expect(response).to have_gitlab_http_status(201)
@@ -1438,7 +1444,7 @@ describe API::MergeRequests do
end
end
- it "returns 201 when target_branch is specified and for the same project" do
+ it "returns 201 when target_branch is specified and for the same project", :sidekiq_might_not_need_inline do
post api("/projects/#{forked_project.id}/merge_requests", user2),
params: { title: 'Test merge_request', target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: forked_project.id }
expect(response).to have_gitlab_http_status(201)
@@ -1486,7 +1492,7 @@ describe API::MergeRequests do
end
describe "PUT /projects/:id/merge_requests/:merge_request_iid/merge" do
- let(:pipeline) { create(:ci_pipeline_without_jobs) }
+ let(:pipeline) { create(:ci_pipeline) }
it "returns merge_request in case of success" do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
@@ -1633,6 +1639,21 @@ describe API::MergeRequests do
expect(source_repository.branch_exists?(source_branch)).to be_falsy
end
end
+
+ context "performing a ff-merge with squash" do
+ let(:merge_request) { create(:merge_request, :rebased, source_project: project, squash: true) }
+
+ before do
+ project.update(merge_requests_ff_only_enabled: true)
+ end
+
+ it "records the squash commit SHA and returns it in the response" do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['squash_commit_sha'].length).to eq(40)
+ end
+ end
end
describe "GET /projects/:id/merge_requests/:merge_request_iid/merge_ref", :clean_gitlab_redis_shared_state do
@@ -2152,6 +2173,16 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(409)
end
+
+ it "returns 409 if rebase can't lock the row" do
+ allow_any_instance_of(MergeRequest).to receive(:with_lock).and_raise(ActiveRecord::LockWaitTimeout)
+ expect(RebaseWorker).not_to receive(:perform_async)
+
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", user)
+
+ expect(response).to have_gitlab_http_status(409)
+ expect(json_response['message']).to eq(MergeRequest::REBASE_LOCK_MESSAGE)
+ end
end
describe 'Time tracking' do
diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb
index 2e376109b42..e0bf1509be3 100644
--- a/spec/requests/api/namespaces_spec.rb
+++ b/spec/requests/api/namespaces_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Namespaces do
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 6c1e30791d2..e57d7699892 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Notes do
diff --git a/spec/requests/api/notification_settings_spec.rb b/spec/requests/api/notification_settings_spec.rb
index 4ed667ad0dc..09fc0197c58 100644
--- a/spec/requests/api/notification_settings_spec.rb
+++ b/spec/requests/api/notification_settings_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::NotificationSettings do
diff --git a/spec/requests/api/oauth_tokens_spec.rb b/spec/requests/api/oauth_tokens_spec.rb
index 3811ec751de..8d7b3fa3c09 100644
--- a/spec/requests/api/oauth_tokens_spec.rb
+++ b/spec/requests/api/oauth_tokens_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'OAuth tokens' do
diff --git a/spec/requests/api/pages/internal_access_spec.rb b/spec/requests/api/pages/internal_access_spec.rb
index 28abe1a8456..821a210a414 100644
--- a/spec/requests/api/pages/internal_access_spec.rb
+++ b/spec/requests/api/pages/internal_access_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe "Internal Project Pages Access" do
diff --git a/spec/requests/api/pages/private_access_spec.rb b/spec/requests/api/pages/private_access_spec.rb
index 6af441caf74..ec84762b05a 100644
--- a/spec/requests/api/pages/private_access_spec.rb
+++ b/spec/requests/api/pages/private_access_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe "Private Project Pages Access" do
diff --git a/spec/requests/api/pages/public_access_spec.rb b/spec/requests/api/pages/public_access_spec.rb
index d99224eca5b..67b8cfb8fbc 100644
--- a/spec/requests/api/pages/public_access_spec.rb
+++ b/spec/requests/api/pages/public_access_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe "Public Project Pages Access" do
diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb
index 326b724666d..6b774e9335e 100644
--- a/spec/requests/api/pages_domains_spec.rb
+++ b/spec/requests/api/pages_domains_spec.rb
@@ -1,15 +1,22 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::PagesDomains do
- set(:project) { create(:project, path: 'my.project', pages_https_only: false) }
- set(:user) { create(:user) }
- set(:admin) { create(:admin) }
+ let_it_be(:project) { create(:project, path: 'my.project', pages_https_only: false) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
- set(:pages_domain) { create(:pages_domain, :without_key, :without_certificate, domain: 'www.domain.test', project: project) }
- set(:pages_domain_secure) { create(:pages_domain, domain: 'ssl.domain.test', project: project) }
- set(:pages_domain_expired) { create(:pages_domain, :with_expired_certificate, domain: 'expired.domain.test', project: project) }
+ let_it_be(:pages_domain) { create(:pages_domain, :without_key, :without_certificate, domain: 'www.domain.test', project: project) }
+ let_it_be(:pages_domain_secure) { create(:pages_domain, domain: 'ssl.domain.test', project: project) }
+ let_it_be(:pages_domain_with_letsencrypt) { create(:pages_domain, :letsencrypt, domain: 'letsencrypt.domain.test', project: project) }
+ let_it_be(:pages_domain_expired) { create(:pages_domain, :with_expired_certificate, domain: 'expired.domain.test', project: project) }
let(:pages_domain_params) { build(:pages_domain, :without_key, :without_certificate, domain: 'www.other-domain.test').slice(:domain) }
+ let(:pages_domain_with_letsencrypt_params) do
+ build(:pages_domain, :without_key, :without_certificate, domain: 'www.other-domain.test', auto_ssl_enabled: true)
+ .slice(:domain, :auto_ssl_enabled)
+ end
let(:pages_domain_secure_params) { build(:pages_domain, domain: 'ssl.other-domain.test', project: project).slice(:domain, :certificate, :key) }
let(:pages_domain_secure_key_missmatch_params) {build(:pages_domain, :with_trusted_chain, project: project).slice(:domain, :certificate, :key) }
let(:pages_domain_secure_missing_chain_params) {build(:pages_domain, :with_missing_chain, project: project).slice(:certificate) }
@@ -20,6 +27,7 @@ describe API::PagesDomains do
let(:route_secure_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain_secure.domain}" }
let(:route_expired_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain_expired.domain}" }
let(:route_vacant_domain) { "/projects/#{project.id}/pages/domains/www.vacant-domain.test" }
+ let(:route_letsencrypt_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain_with_letsencrypt.domain}" }
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
@@ -45,9 +53,10 @@ describe API::PagesDomains do
expect(response).to match_response_schema('public_api/v4/pages_domain_basics')
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.size).to eq(3)
+ expect(json_response.size).to eq(4)
expect(json_response.last).to have_key('domain')
expect(json_response.last).to have_key('project_id')
+ expect(json_response.last).to have_key('auto_ssl_enabled')
expect(json_response.last).to have_key('certificate_expiration')
expect(json_response.last['certificate_expiration']['expired']).to be true
expect(json_response.first).not_to have_key('certificate_expiration')
@@ -71,7 +80,7 @@ describe API::PagesDomains do
expect(response).to match_response_schema('public_api/v4/pages_domains')
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.size).to eq(3)
+ expect(json_response.size).to eq(4)
expect(json_response.map { |pages_domain| pages_domain['domain'] }).to include(pages_domain.domain)
expect(json_response.last).to have_key('domain')
end
@@ -164,6 +173,7 @@ describe API::PagesDomains do
expect(json_response['url']).to eq(pages_domain_secure.url)
expect(json_response['certificate']['subject']).to eq(pages_domain_secure.subject)
expect(json_response['certificate']['expired']).to be false
+ expect(json_response['auto_ssl_enabled']).to be false
end
it 'returns pages domain with an expired certificate' do
@@ -173,6 +183,18 @@ describe API::PagesDomains do
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(json_response['certificate']['expired']).to be true
end
+
+ it 'returns pages domain with letsencrypt' do
+ get api(route_letsencrypt_domain, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
+ expect(json_response['domain']).to eq(pages_domain_with_letsencrypt.domain)
+ expect(json_response['url']).to eq(pages_domain_with_letsencrypt.url)
+ expect(json_response['certificate']['subject']).to eq(pages_domain_with_letsencrypt.subject)
+ expect(json_response['certificate']['expired']).to be false
+ expect(json_response['auto_ssl_enabled']).to be true
+ end
end
context 'when domain is vacant' do
@@ -244,6 +266,7 @@ describe API::PagesDomains do
expect(pages_domain.domain).to eq(params[:domain])
expect(pages_domain.certificate).to be_nil
expect(pages_domain.key).to be_nil
+ expect(pages_domain.auto_ssl_enabled).to be false
end
it 'creates a new secure pages domain' do
@@ -255,6 +278,29 @@ describe API::PagesDomains do
expect(pages_domain.domain).to eq(params_secure[:domain])
expect(pages_domain.certificate).to eq(params_secure[:certificate])
expect(pages_domain.key).to eq(params_secure[:key])
+ expect(pages_domain.auto_ssl_enabled).to be false
+ end
+
+ it 'creates domain with letsencrypt enabled' do
+ post api(route, user), params: pages_domain_with_letsencrypt_params
+ pages_domain = PagesDomain.find_by(domain: json_response['domain'])
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
+ expect(pages_domain.domain).to eq(pages_domain_with_letsencrypt_params[:domain])
+ expect(pages_domain.auto_ssl_enabled).to be true
+ end
+
+ it 'creates domain with letsencrypt enabled and provided certificate' do
+ post api(route, user), params: params_secure.merge(auto_ssl_enabled: true)
+ pages_domain = PagesDomain.find_by(domain: json_response['domain'])
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
+ expect(pages_domain.domain).to eq(params_secure[:domain])
+ expect(pages_domain.certificate).to eq(params_secure[:certificate])
+ expect(pages_domain.key).to eq(params_secure[:key])
+ expect(pages_domain.auto_ssl_enabled).to be true
end
it 'fails to create pages domain without key' do
@@ -321,13 +367,14 @@ describe API::PagesDomains do
shared_examples_for 'put pages domain' do
it 'updates pages domain removing certificate' do
- put api(route_secure_domain, user)
+ put api(route_secure_domain, user), params: { certificate: nil, key: nil }
pages_domain_secure.reload
expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(pages_domain_secure.certificate).to be_nil
expect(pages_domain_secure.key).to be_nil
+ expect(pages_domain_secure.auto_ssl_enabled).to be false
end
it 'updates pages domain adding certificate' do
@@ -340,6 +387,37 @@ describe API::PagesDomains do
expect(pages_domain.key).to eq(params_secure[:key])
end
+ it 'updates pages domain adding certificate with letsencrypt' do
+ put api(route_domain, user), params: params_secure.merge(auto_ssl_enabled: true)
+ pages_domain.reload
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
+ expect(pages_domain.certificate).to eq(params_secure[:certificate])
+ expect(pages_domain.key).to eq(params_secure[:key])
+ expect(pages_domain.auto_ssl_enabled).to be true
+ end
+
+ it 'updates pages domain enabling letsencrypt' do
+ put api(route_domain, user), params: { auto_ssl_enabled: true }
+ pages_domain.reload
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
+ expect(pages_domain.auto_ssl_enabled).to be true
+ end
+
+ it 'updates pages domain disabling letsencrypt while preserving the certificate' do
+ put api(route_letsencrypt_domain, user), params: { auto_ssl_enabled: false }
+ pages_domain_with_letsencrypt.reload
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
+ expect(pages_domain_with_letsencrypt.auto_ssl_enabled).to be false
+ expect(pages_domain_with_letsencrypt.key).to be
+ expect(pages_domain_with_letsencrypt.certificate).to be
+ end
+
it 'updates pages domain with expired certificate' do
put api(route_expired_domain, user), params: params_secure
pages_domain_expired.reload
diff --git a/spec/requests/api/pipeline_schedules_spec.rb b/spec/requests/api/pipeline_schedules_spec.rb
index 072bd02f2ac..5c8ccce2e37 100644
--- a/spec/requests/api/pipeline_schedules_spec.rb
+++ b/spec/requests/api/pipeline_schedules_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::PipelineSchedules do
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index 3ac63dc381b..cce52cfc1ca 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -673,7 +673,7 @@ describe API::Pipelines do
let!(:build) { create(:ci_build, :running, pipeline: pipeline) }
context 'authorized user' do
- it 'retries failed builds' do
+ it 'retries failed builds', :sidekiq_might_not_need_inline do
post api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", user)
expect(response).to have_gitlab_http_status(200)
diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb
index a7b919de2ef..04e59238877 100644
--- a/spec/requests/api/project_clusters_spec.rb
+++ b/spec/requests/api/project_clusters_spec.rb
@@ -281,11 +281,14 @@ describe API::ProjectClusters do
let(:api_url) { 'https://kubernetes.example.com' }
let(:namespace) { 'new-namespace' }
let(:platform_kubernetes_attributes) { { namespace: namespace } }
+ let(:management_project) { create(:project, namespace: project.namespace) }
+ let(:management_project_id) { management_project.id }
let(:update_params) do
{
domain: 'new-domain.com',
- platform_kubernetes_attributes: platform_kubernetes_attributes
+ platform_kubernetes_attributes: platform_kubernetes_attributes,
+ management_project_id: management_project_id
}
end
@@ -310,6 +313,8 @@ describe API::ProjectClusters do
context 'authorized user' do
before do
+ management_project.add_maintainer(current_user)
+
put api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: update_params
cluster.reload
@@ -323,6 +328,7 @@ describe API::ProjectClusters do
it 'updates cluster attributes' do
expect(cluster.domain).to eq('new-domain.com')
expect(cluster.platform_kubernetes.namespace).to eq('new-namespace')
+ expect(cluster.management_project).to eq(management_project)
end
end
@@ -336,6 +342,7 @@ describe API::ProjectClusters do
it 'does not update cluster attributes' do
expect(cluster.domain).not_to eq('new_domain.com')
expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace')
+ expect(cluster.management_project).not_to eq(management_project)
end
it 'returns validation errors' do
@@ -343,6 +350,18 @@ describe API::ProjectClusters do
end
end
+ context 'current user does not have access to management_project_id' do
+ let(:management_project_id) { create(:project).id }
+
+ it 'responds with 400' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns validation errors' do
+ expect(json_response['message']['management_project_id'].first).to match('don\'t have permission')
+ end
+ end
+
context 'with a GCP cluster' do
context 'when user tries to change GCP specific fields' do
let(:platform_kubernetes_attributes) do
diff --git a/spec/requests/api/project_container_repositories_spec.rb b/spec/requests/api/project_container_repositories_spec.rb
index 3ac7ff7656b..d04db134db0 100644
--- a/spec/requests/api/project_container_repositories_spec.rb
+++ b/spec/requests/api/project_container_repositories_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectContainerRepositories do
@@ -44,6 +46,7 @@ describe API::ProjectContainerRepositories do
it_behaves_like 'rejected container repository access', :guest, :forbidden
it_behaves_like 'rejected container repository access', :anonymous, :not_found
+ it_behaves_like 'a gitlab tracking event', described_class.name, 'list_repositories'
it_behaves_like 'returns repositories for allowed users', :reporter, 'project' do
let(:object) { project }
@@ -55,6 +58,7 @@ describe API::ProjectContainerRepositories do
it_behaves_like 'rejected container repository access', :developer, :forbidden
it_behaves_like 'rejected container repository access', :anonymous, :not_found
+ it_behaves_like 'a gitlab tracking event', described_class.name, 'delete_repository'
context 'for maintainer' do
let(:api_user) { maintainer }
@@ -83,6 +87,8 @@ describe API::ProjectContainerRepositories do
stub_container_registry_tags(repository: root_repository.path, tags: %w(rootA latest))
end
+ it_behaves_like 'a gitlab tracking event', described_class.name, 'list_tags'
+
it 'returns a list of tags' do
subject
@@ -109,6 +115,7 @@ describe API::ProjectContainerRepositories do
it_behaves_like 'rejected container repository access', :developer, :forbidden
it_behaves_like 'rejected container repository access', :anonymous, :not_found
+ it_behaves_like 'a gitlab tracking event', described_class.name, 'delete_tag_bulk'
end
context 'for maintainer' do
@@ -220,6 +227,7 @@ describe API::ProjectContainerRepositories do
it 'properly removes tag' do
expect(service).to receive(:execute).with(root_repository) { { status: :success } }
expect(Projects::ContainerRepository::DeleteTagsService).to receive(:new).with(root_repository.project, api_user, tags: %w[rootA]) { service }
+ expect(Gitlab::Tracking).to receive(:event).with(described_class.name, 'delete_tag', {})
subject
@@ -235,6 +243,7 @@ describe API::ProjectContainerRepositories do
it 'properly removes tag' do
expect(service).to receive(:execute).with(root_repository) { { status: :success } }
expect(Projects::ContainerRepository::DeleteTagsService).to receive(:new).with(root_repository.project, api_user, tags: %w[rootA]) { service }
+ expect(Gitlab::Tracking).to receive(:event).with(described_class.name, 'delete_tag', {})
subject
diff --git a/spec/requests/api/project_events_spec.rb b/spec/requests/api/project_events_spec.rb
index 8c2db6e4c62..d466dca9884 100644
--- a/spec/requests/api/project_events_spec.rb
+++ b/spec/requests/api/project_events_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectEvents do
diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb
index 7de8935097a..605ff888234 100644
--- a/spec/requests/api/project_export_spec.rb
+++ b/spec/requests/api/project_export_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectExport do
@@ -370,7 +372,7 @@ describe API::ProjectExport do
end
context 'when overriding description' do
- it 'starts' do
+ it 'starts', :sidekiq_might_not_need_inline do
params = { description: "Foo" }
expect_any_instance_of(Projects::ImportExport::ExportService).to receive(:execute)
diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb
index b88a8b95201..06c09b100ac 100644
--- a/spec/requests/api/project_hooks_spec.rb
+++ b/spec/requests/api/project_hooks_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectHooks, 'ProjectHooks' do
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index d2b1fb063b8..866adbd424e 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectImport do
@@ -153,7 +155,7 @@ describe API::ProjectImport do
expect(import_project.import_data.data['override_params']).to be_empty
end
- it 'correctly overrides params during the import' do
+ it 'correctly overrides params during the import', :sidekiq_might_not_need_inline do
override_params = { 'description' => 'Hello world' }
perform_enqueued_jobs do
diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb
index 895f05a98e8..df6d83c1e65 100644
--- a/spec/requests/api/project_milestones_spec.rb
+++ b/spec/requests/api/project_milestones_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectMilestones do
diff --git a/spec/requests/api/project_snapshots_spec.rb b/spec/requests/api/project_snapshots_spec.rb
index 2857715cdbe..cdd44f71649 100644
--- a/spec/requests/api/project_snapshots_spec.rb
+++ b/spec/requests/api/project_snapshots_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectSnapshots do
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index ef0cabad4b0..cac3f07d0d0 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectSnippets do
diff --git a/spec/requests/api/project_templates_spec.rb b/spec/requests/api/project_templates_spec.rb
index 80e5033dab4..2bf864afe87 100644
--- a/spec/requests/api/project_templates_spec.rb
+++ b/spec/requests/api/project_templates_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProjectTemplates do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 99d2a68ef53..f1447536e0f 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
shared_examples 'languages and percentages JSON response' do
@@ -15,7 +17,7 @@ shared_examples 'languages and percentages JSON response' do
end
context "when the languages haven't been detected yet" do
- it 'returns expected language values' do
+ it 'returns expected language values', :sidekiq_might_not_need_inline do
get api("/projects/#{project.id}/languages", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -360,6 +362,30 @@ describe API::Projects do
end
end
+ context 'and using id_after' do
+ it_behaves_like 'projects response' do
+ let(:filter) { { id_after: project2.id } }
+ let(:current_user) { user }
+ let(:projects) { [public_project, project, project2, project3].select { |p| p.id > project2.id } }
+ end
+ end
+
+ context 'and using id_before' do
+ it_behaves_like 'projects response' do
+ let(:filter) { { id_before: project2.id } }
+ let(:current_user) { user }
+ let(:projects) { [public_project, project, project2, project3].select { |p| p.id < project2.id } }
+ end
+ end
+
+ context 'and using both id_after and id_before' do
+ it_behaves_like 'projects response' do
+ let(:filter) { { id_before: project2.id, id_after: public_project.id } }
+ let(:current_user) { user }
+ let(:projects) { [public_project, project, project2, project3].select { |p| p.id < project2.id && p.id > public_project.id } }
+ end
+ end
+
context 'and membership=true' do
it_behaves_like 'projects response' do
let(:filter) { { membership: true } }
@@ -606,6 +632,7 @@ describe API::Projects do
merge_requests_enabled: false,
wiki_enabled: false,
resolve_outdated_diff_discussions: false,
+ remove_source_branch_after_merge: true,
only_allow_merge_if_pipeline_succeeds: false,
request_access_enabled: true,
only_allow_merge_if_all_discussions_are_resolved: false,
@@ -722,6 +749,22 @@ describe API::Projects do
expect(json_response['resolve_outdated_diff_discussions']).to be_truthy
end
+ it 'sets a project as not removing source branches' do
+ project = attributes_for(:project, remove_source_branch_after_merge: false)
+
+ post api('/projects', user), params: project
+
+ expect(json_response['remove_source_branch_after_merge']).to be_falsey
+ end
+
+ it 'sets a project as removing source branches' do
+ project = attributes_for(:project, remove_source_branch_after_merge: true)
+
+ post api('/projects', user), params: project
+
+ expect(json_response['remove_source_branch_after_merge']).to be_truthy
+ end
+
it 'sets a project as allowing merge even if build fails' do
project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: false)
@@ -829,6 +872,63 @@ describe API::Projects do
expect(json_response.map { |project| project['id'] }).to contain_exactly(public_project.id)
end
+ context 'and using id_after' do
+ let!(:another_public_project) { create(:project, :public, name: 'another_public_project', creator_id: user4.id, namespace: user4.namespace) }
+
+ it 'only returns projects with id_after filter given' do
+ get api("/users/#{user4.id}/projects?id_after=#{public_project.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(another_public_project.id)
+ end
+
+ it 'returns both projects without a id_after filter' do
+ get api("/users/#{user4.id}/projects", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(public_project.id, another_public_project.id)
+ end
+ end
+
+ context 'and using id_before' do
+ let!(:another_public_project) { create(:project, :public, name: 'another_public_project', creator_id: user4.id, namespace: user4.namespace) }
+
+ it 'only returns projects with id_before filter given' do
+ get api("/users/#{user4.id}/projects?id_before=#{another_public_project.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(public_project.id)
+ end
+
+ it 'returns both projects without a id_before filter' do
+ get api("/users/#{user4.id}/projects", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(public_project.id, another_public_project.id)
+ end
+ end
+
+ context 'and using both id_before and id_after' do
+ let!(:more_projects) { create_list(:project, 5, :public, creator_id: user4.id, namespace: user4.namespace) }
+
+ it 'only returns projects with id matching the range' do
+ get api("/users/#{user4.id}/projects?id_after=#{more_projects.first.id}&id_before=#{more_projects.last.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(*more_projects[1..-2].map(&:id))
+ end
+ end
+
it 'returns projects filtered by username' do
get api("/users/#{user4.username}/projects/", user)
@@ -980,6 +1080,22 @@ describe API::Projects do
expect(json_response['resolve_outdated_diff_discussions']).to be_truthy
end
+ it 'sets a project as not removing source branches' do
+ project = attributes_for(:project, remove_source_branch_after_merge: false)
+
+ post api("/projects/user/#{user.id}", admin), params: project
+
+ expect(json_response['remove_source_branch_after_merge']).to be_falsey
+ end
+
+ it 'sets a project as removing source branches' do
+ project = attributes_for(:project, remove_source_branch_after_merge: true)
+
+ post api("/projects/user/#{user.id}", admin), params: project
+
+ expect(json_response['remove_source_branch_after_merge']).to be_truthy
+ end
+
it 'sets a project as allowing merge even if build fails' do
project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: false)
post api("/projects/user/#{user.id}", admin), params: project
@@ -1157,6 +1273,7 @@ describe API::Projects do
expect(json_response['wiki_access_level']).to be_present
expect(json_response['builds_access_level']).to be_present
expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions)
+ expect(json_response['remove_source_branch_after_merge']).to be_truthy
expect(json_response['container_registry_enabled']).to be_present
expect(json_response['created_at']).to be_present
expect(json_response['last_activity_at']).to be_present
diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb
index f90558d77a9..67ce704b3f3 100644
--- a/spec/requests/api/protected_branches_spec.rb
+++ b/spec/requests/api/protected_branches_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProtectedBranches do
diff --git a/spec/requests/api/protected_tags_spec.rb b/spec/requests/api/protected_tags_spec.rb
index 41363dcc1c3..5a962cd5667 100644
--- a/spec/requests/api/protected_tags_spec.rb
+++ b/spec/requests/api/protected_tags_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::ProtectedTags do
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index 99d0ceee76b..bf05587fe03 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Releases do
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 6f4bb525c89..ba301147d43 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'mime/types'
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index 70a95663aea..6138036b0af 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Runner, :clean_gitlab_redis_shared_state do
@@ -312,7 +314,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
let(:root_namespace) { create(:namespace) }
let(:namespace) { create(:namespace, parent: root_namespace) }
let(:project) { create(:project, namespace: namespace, shared_runners_enabled: false) }
- let(:pipeline) { create(:ci_pipeline_without_jobs, project: project, ref: 'master') }
+ let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') }
let(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:job) do
create(:ci_build, :artifacts, :extended_options,
@@ -610,7 +612,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
context 'when job is made for merge request' do
- let(:pipeline) { create(:ci_pipeline_without_jobs, source: :merge_request_event, project: project, ref: 'feature', merge_request: merge_request) }
+ let(:pipeline) { create(:ci_pipeline, source: :merge_request_event, project: project, ref: 'feature', merge_request: merge_request) }
let!(:job) { create(:ci_build, pipeline: pipeline, name: 'spinach', ref: 'feature', stage: 'test', stage_idx: 0) }
let(:merge_request) { create(:merge_request) }
diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb
index d26fbee6957..8daba204d50 100644
--- a/spec/requests/api/runners_spec.rb
+++ b/spec/requests/api/runners_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Runners do
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 8abdcaa2e0e..24d7f1e313c 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Search do
@@ -436,6 +438,7 @@ describe API::Search do
expect(response).to have_gitlab_http_status(200)
expect(json_response.size).to eq(2)
+ expect(json_response.first['path']).to eq('PROCESS.md')
expect(json_response.first['filename']).to eq('PROCESS.md')
end
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index 7153fcc99d7..a080b59173f 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe API::Services do
@@ -100,7 +102,7 @@ describe API::Services do
expect(json_response['properties'].keys).to match_array(service_instance.api_field_names)
end
- it "returns empty hash if properties and data fields are empty" do
+ it "returns empty hash or nil values if properties and data fields are empty" do
# deprecated services are not valid for update
initialized_service.update_attribute(:properties, {})
@@ -112,7 +114,7 @@ describe API::Services do
get api("/projects/#{project.id}/services/#{dashed_service}", user)
expect(response).to have_gitlab_http_status(200)
- expect(json_response['properties'].keys).to be_empty
+ expect(json_response['properties'].values.compact).to be_empty
end
it "returns error when authenticated but not a project owner" do
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index f3bfb258029..b7586307929 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Settings, 'Settings' do
@@ -16,6 +18,10 @@ describe API::Settings, 'Settings' do
expect(json_response['password_authentication_enabled']).to be_truthy
expect(json_response['plantuml_enabled']).to be_falsey
expect(json_response['plantuml_url']).to be_nil
+ expect(json_response['default_ci_config_path']).to be_nil
+ expect(json_response['sourcegraph_enabled']).to be_falsey
+ expect(json_response['sourcegraph_url']).to be_nil
+ expect(json_response['sourcegraph_public_only']).to be_truthy
expect(json_response['default_project_visibility']).to be_a String
expect(json_response['default_snippet_visibility']).to be_a String
expect(json_response['default_group_visibility']).to be_a String
@@ -42,17 +48,22 @@ describe API::Settings, 'Settings' do
storages = Gitlab.config.repositories.storages
.merge({ 'custom' => 'tmp/tests/custom_repositories' })
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
+ Feature.get(:sourcegraph).enable
end
it "updates application settings" do
put api("/application/settings", admin),
params: {
+ default_ci_config_path: 'debian/salsa-ci.yml',
default_projects_limit: 3,
default_project_creation: 2,
password_authentication_enabled_for_web: false,
repository_storages: ['custom'],
plantuml_enabled: true,
plantuml_url: 'http://plantuml.example.com',
+ sourcegraph_enabled: true,
+ sourcegraph_url: 'https://sourcegraph.com',
+ sourcegraph_public_only: false,
default_snippet_visibility: 'internal',
restricted_visibility_levels: ['public'],
default_artifacts_expire_in: '2 days',
@@ -78,12 +89,16 @@ describe API::Settings, 'Settings' do
}
expect(response).to have_gitlab_http_status(200)
+ expect(json_response['default_ci_config_path']).to eq('debian/salsa-ci.yml')
expect(json_response['default_projects_limit']).to eq(3)
expect(json_response['default_project_creation']).to eq(::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
expect(json_response['password_authentication_enabled_for_web']).to be_falsey
expect(json_response['repository_storages']).to eq(['custom'])
expect(json_response['plantuml_enabled']).to be_truthy
expect(json_response['plantuml_url']).to eq('http://plantuml.example.com')
+ expect(json_response['sourcegraph_enabled']).to be_truthy
+ expect(json_response['sourcegraph_url']).to eq('https://sourcegraph.com')
+ expect(json_response['sourcegraph_public_only']).to eq(false)
expect(json_response['default_snippet_visibility']).to eq('internal')
expect(json_response['restricted_visibility_levels']).to eq(['public'])
expect(json_response['default_artifacts_expire_in']).to eq('2 days')
@@ -176,7 +191,8 @@ describe API::Settings, 'Settings' do
snowplow_collector_hostname: "snowplow.example.com",
snowplow_cookie_domain: ".example.com",
snowplow_enabled: true,
- snowplow_site_id: "site_id"
+ snowplow_app_id: "app_id",
+ snowplow_iglu_registry_url: 'https://example.com'
}
end
@@ -220,6 +236,61 @@ describe API::Settings, 'Settings' do
end
end
+ context 'EKS integration settings' do
+ let(:attribute_names) { settings.keys.map(&:to_s) }
+ let(:sensitive_attributes) { %w(eks_secret_access_key) }
+ let(:exposed_attributes) { attribute_names - sensitive_attributes }
+
+ let(:settings) do
+ {
+ eks_integration_enabled: true,
+ eks_account_id: '123456789012',
+ eks_access_key_id: 'access-key-id-12',
+ eks_secret_access_key: 'secret-access-key'
+ }
+ end
+
+ it 'includes attributes in the API' do
+ get api("/application/settings", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ exposed_attributes.each do |attribute|
+ expect(json_response.keys).to include(attribute)
+ end
+ end
+
+ it 'does not include sensitive attributes in the API' do
+ get api("/application/settings", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ sensitive_attributes.each do |attribute|
+ expect(json_response.keys).not_to include(attribute)
+ end
+ end
+
+ it 'allows updating the settings' do
+ put api("/application/settings", admin), params: settings
+
+ expect(response).to have_gitlab_http_status(200)
+ settings.each do |attribute, value|
+ expect(ApplicationSetting.current.public_send(attribute)).to eq(value)
+ end
+ end
+
+ context 'EKS integration is enabled but params are blank' do
+ let(:settings) { Hash[eks_integration_enabled: true] }
+
+ it 'does not update the settings' do
+ put api("/application/settings", admin), params: settings
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error']).to include('eks_account_id is missing')
+ expect(json_response['error']).to include('eks_access_key_id is missing')
+ expect(json_response['error']).to include('eks_secret_access_key is missing')
+ end
+ end
+ end
+
context "missing plantuml_url value when plantuml_enabled is true" do
it "returns a blank parameter error message" do
put api("/application/settings", admin), params: { plantuml_enabled: true }
@@ -294,5 +365,14 @@ describe API::Settings, 'Settings' do
expect(json_response['domain_blacklist']).to eq(['domain3.com', '*.domain4.com'])
end
end
+
+ context "missing sourcegraph_url value when sourcegraph_enabled is true" do
+ it "returns a blank parameter error message" do
+ put api("/application/settings", admin), params: { sourcegraph_enabled: true }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error']).to eq('sourcegraph_url is missing')
+ end
+ end
end
end
diff --git a/spec/requests/api/sidekiq_metrics_spec.rb b/spec/requests/api/sidekiq_metrics_spec.rb
index fff9adb7f57..438b1475c54 100644
--- a/spec/requests/api/sidekiq_metrics_spec.rb
+++ b/spec/requests/api/sidekiq_metrics_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::SidekiqMetrics do
@@ -23,6 +25,10 @@ describe API::SidekiqMetrics do
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_a Hash
+ expect(json_response['jobs']).to be_a Hash
+ expect(json_response['jobs'].keys)
+ .to contain_exactly(*%w[processed failed enqueued dead])
+ expect(json_response['jobs'].values).to all(be_an(Integer))
end
it 'defines the `compound_metrics` endpoint' do
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index e7eaaea2418..36d2a0d7ea7 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Snippets do
diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb
index 0e2f3face71..79790b1e999 100644
--- a/spec/requests/api/system_hooks_spec.rb
+++ b/spec/requests/api/system_hooks_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::SystemHooks do
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index c4f4a2cb889..3c6ec631664 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Tags do
diff --git a/spec/requests/api/templates_spec.rb b/spec/requests/api/templates_spec.rb
index d1e16ab9ca9..b6ba417d892 100644
--- a/spec/requests/api/templates_spec.rb
+++ b/spec/requests/api/templates_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Templates do
diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb
index 9f0d5ad5d12..4121a0f3f3a 100644
--- a/spec/requests/api/todos_spec.rb
+++ b/spec/requests/api/todos_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Todos do
diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb
index 8ea3d16a41f..fd1104fa978 100644
--- a/spec/requests/api/triggers_spec.rb
+++ b/spec/requests/api/triggers_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Triggers do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index ee4e783e9ac..1a1e80f1ce3 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Users do
@@ -633,32 +635,6 @@ describe API::Users do
end
end
- describe "GET /users/sign_up" do
- context 'when experimental signup_flow is active' do
- before do
- stub_experiment(signup_flow: true)
- end
-
- it "shows sign up page" do
- get "/users/sign_up"
- expect(response).to have_gitlab_http_status(200)
- expect(response).to render_template(:new)
- end
- end
-
- context 'when experimental signup_flow is not active' do
- before do
- stub_experiment(signup_flow: false)
- end
-
- it "redirects to sign in page" do
- get "/users/sign_up"
- expect(response).to have_gitlab_http_status(302)
- expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane'))
- end
- end
- end
-
describe "PUT /users/:id" do
let!(:admin_user) { create(:admin) }
@@ -1277,7 +1253,7 @@ describe API::Users do
admin
end
- it "deletes user" do
+ it "deletes user", :sidekiq_might_not_need_inline do
perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
expect(response).to have_gitlab_http_status(204)
@@ -1312,7 +1288,7 @@ describe API::Users do
end
context "hard delete disabled" do
- it "moves contributions to the ghost user" do
+ it "moves contributions to the ghost user", :sidekiq_might_not_need_inline do
perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
expect(response).to have_gitlab_http_status(204)
@@ -1322,7 +1298,7 @@ describe API::Users do
end
context "hard delete enabled" do
- it "removes contributions" do
+ it "removes contributions", :sidekiq_might_not_need_inline do
perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
expect(response).to have_gitlab_http_status(204)
diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb
index 69f105b71a8..dfecd43cbfa 100644
--- a/spec/requests/api/variables_spec.rb
+++ b/spec/requests/api/variables_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Variables do
diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb
index e06f8bbc095..e2117ca45ee 100644
--- a/spec/requests/api/version_spec.rb
+++ b/spec/requests/api/version_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe API::Version do
diff --git a/spec/requests/api/wikis_spec.rb b/spec/requests/api/wikis_spec.rb
index 97de26650db..310caa92eb9 100644
--- a/spec/requests/api/wikis_spec.rb
+++ b/spec/requests/api/wikis_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
# For every API endpoint we test 3 states of wikis:
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index e58f1b7d9dc..1b17d492b0c 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Git HTTP requests' do
@@ -87,7 +89,7 @@ describe 'Git HTTP requests' do
end
shared_examples_for 'pulls are allowed' do
- it do
+ it 'allows pulls' do
download(path, env) do |response|
expect(response).to have_gitlab_http_status(:ok)
expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
@@ -96,7 +98,7 @@ describe 'Git HTTP requests' do
end
shared_examples_for 'pushes are allowed' do
- it do
+ it 'allows pushes', :sidekiq_might_not_need_inline do
upload(path, env) do |response|
expect(response).to have_gitlab_http_status(:ok)
expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
@@ -450,16 +452,22 @@ describe 'Git HTTP requests' do
context "when authentication fails" do
context "when the user is IP banned" do
before do
- Gitlab.config.rack_attack.git_basic_auth['enabled'] = true
+ stub_rack_attack_setting(enabled: true, ip_whitelist: [])
end
- it "responds with status 401" do
+ it "responds with status 403" do
expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true)
- allow_any_instance_of(ActionDispatch::Request).to receive(:ip).and_return('1.2.3.4')
+ expect(Gitlab::AuthLogger).to receive(:error).with({
+ message: 'Rack_Attack',
+ env: :blocklist,
+ remote_ip: '127.0.0.1',
+ request_method: 'GET',
+ path: "/#{path}/info/refs?service=git-upload-pack"
+ })
clone_get(path, env)
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
@@ -493,7 +501,7 @@ describe 'Git HTTP requests' do
context "when the user isn't blocked" do
before do
- Gitlab.config.rack_attack.git_basic_auth['enabled'] = true
+ stub_rack_attack_setting(enabled: true, bantime: 1.minute, findtime: 5.minutes, maxretry: 2, ip_whitelist: [])
end
it "resets the IP in Rack Attack on download" do
@@ -652,9 +660,11 @@ describe 'Git HTTP requests' do
response.status
end
+ include_context 'rack attack cache store'
+
it "repeated attempts followed by successful attempt" do
options = Gitlab.config.rack_attack.git_basic_auth
- maxretry = options[:maxretry] - 1
+ maxretry = options[:maxretry]
ip = '1.2.3.4'
allow_any_instance_of(ActionDispatch::Request).to receive(:ip).and_return(ip)
@@ -666,12 +676,6 @@ describe 'Git HTTP requests' do
expect(attempt_login(true)).to eq(200)
expect(Rack::Attack::Allow2Ban.banned?(ip)).to be_falsey
-
- maxretry.times.each do
- expect(attempt_login(false)).to eq(401)
- end
-
- Rack::Attack::Allow2Ban.reset(ip, options)
end
end
@@ -843,8 +847,8 @@ describe 'Git HTTP requests' do
get "/#{project.full_path}/blob/master/info/refs"
end
- it "returns not found" do
- expect(response).to have_gitlab_http_status(:not_found)
+ it "redirects" do
+ expect(response).to have_gitlab_http_status(302)
end
end
end
diff --git a/spec/requests/groups/milestones_controller_spec.rb b/spec/requests/groups/milestones_controller_spec.rb
index af19d931284..977cccad29f 100644
--- a/spec/requests/groups/milestones_controller_spec.rb
+++ b/spec/requests/groups/milestones_controller_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Groups::MilestonesController do
diff --git a/spec/requests/groups/registry/repositories_controller_spec.rb b/spec/requests/groups/registry/repositories_controller_spec.rb
new file mode 100644
index 00000000000..35fdeaab604
--- /dev/null
+++ b/spec/requests/groups/registry/repositories_controller_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Groups::Registry::RepositoriesController do
+ let_it_be(:group, reload: true) { create(:group) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+
+ group.add_reporter(user)
+ login_as(user)
+ end
+
+ describe 'GET groups/:group_id/-/container_registries.json' do
+ it 'avoids N+1 queries' do
+ project = create(:project, group: group)
+ create(:container_repository, project: project)
+ endpoint = group_container_registries_path(group, format: :json)
+
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { get(endpoint) }.count
+
+ create_list(:project, 2, group: group).each do |project|
+ create_list(:container_repository, 2, project: project)
+ end
+
+ expect { get(endpoint) }.not_to exceed_all_query_limit(control_count)
+
+ # sanity check that response is 200
+ expect(response).to have_http_status(200)
+ repositories = json_response
+ expect(repositories.count).to eq(5)
+ end
+ end
+end
diff --git a/spec/requests/health_controller_spec.rb b/spec/requests/health_controller_spec.rb
new file mode 100644
index 00000000000..61412815039
--- /dev/null
+++ b/spec/requests/health_controller_spec.rb
@@ -0,0 +1,227 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe HealthController do
+ include StubENV
+
+ let(:token) { Gitlab::CurrentSettings.health_check_access_token }
+ let(:whitelisted_ip) { '1.1.1.1' }
+ let(:not_whitelisted_ip) { '2.2.2.2' }
+ let(:params) { {} }
+ let(:headers) { {} }
+
+ before do
+ allow(Settings.monitoring).to receive(:ip_whitelist).and_return([whitelisted_ip])
+ stub_storage_settings({}) # Hide the broken storage
+ stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ end
+
+ shared_context 'endpoint querying database' do
+ it 'does query database' do
+ control_count = ActiveRecord::QueryRecorder.new { subject }.count
+
+ expect(control_count).not_to be_zero
+ end
+ end
+
+ shared_context 'endpoint not querying database' do
+ it 'does not query database' do
+ control_count = ActiveRecord::QueryRecorder.new { subject }.count
+
+ expect(control_count).to be_zero
+ end
+ end
+
+ shared_context 'endpoint not found' do
+ it 'responds with resource not found' do
+ subject
+
+ expect(response.status).to eq(404)
+ end
+ end
+
+ describe 'GET /-/health' do
+ subject { get '/-/health', params: params, headers: headers }
+
+ shared_context 'endpoint responding with health data' do
+ it 'responds with health checks data' do
+ subject
+
+ expect(response.status).to eq(200)
+ expect(response.body).to eq('GitLab OK')
+ end
+ end
+
+ context 'accessed from whitelisted ip' do
+ before do
+ stub_remote_addr(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint responding with health data'
+ it_behaves_like 'endpoint not querying database'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ stub_remote_addr(not_whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint not querying database'
+ it_behaves_like 'endpoint not found'
+ end
+ end
+
+ describe 'GET /-/readiness' do
+ subject { get '/-/readiness', params: params, headers: headers }
+
+ shared_context 'endpoint responding with readiness data' do
+ context 'when requesting instance-checks' do
+ it 'responds with readiness checks data' do
+ expect(Gitlab::HealthChecks::MasterCheck).to receive(:check) { true }
+
+ subject
+
+ expect(json_response).to include({ 'status' => 'ok' })
+ expect(json_response['master_check']).to contain_exactly({ 'status' => 'ok' })
+ end
+
+ it 'responds with readiness checks data when a failure happens' do
+ expect(Gitlab::HealthChecks::MasterCheck).to receive(:check) { false }
+
+ subject
+
+ expect(json_response).to include({ 'status' => 'failed' })
+ expect(json_response['master_check']).to contain_exactly(
+ { 'status' => 'failed', 'message' => 'unexpected Master check result: false' })
+
+ expect(response.status).to eq(503)
+ expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
+ end
+ end
+
+ context 'when requesting all checks' do
+ before do
+ params.merge!(all: true)
+ end
+
+ it 'responds with readiness checks data' do
+ subject
+
+ expect(json_response['db_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['queues_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['shared_state_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['gitaly_check']).to contain_exactly(
+ { 'status' => 'ok', 'labels' => { 'shard' => 'default' } })
+ end
+
+ it 'responds with readiness checks data when a failure happens' do
+ allow(Gitlab::HealthChecks::Redis::RedisCheck).to receive(:readiness).and_return(
+ Gitlab::HealthChecks::Result.new('redis_check', false, "check error"))
+
+ subject
+
+ expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['redis_check']).to contain_exactly(
+ { 'status' => 'failed', 'message' => 'check error' })
+
+ expect(response.status).to eq(503)
+ expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
+ end
+ end
+ end
+
+ context 'accessed from whitelisted ip' do
+ before do
+ stub_remote_addr(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint not querying database'
+ it_behaves_like 'endpoint responding with readiness data'
+
+ context 'when requesting all checks' do
+ before do
+ params.merge!(all: true)
+ end
+
+ it_behaves_like 'endpoint querying database'
+ end
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ stub_remote_addr(not_whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint not querying database'
+ it_behaves_like 'endpoint not found'
+ end
+
+ context 'accessed with valid token' do
+ context 'token passed in request header' do
+ let(:headers) { { TOKEN: token } }
+
+ it_behaves_like 'endpoint responding with readiness data'
+ it_behaves_like 'endpoint querying database'
+ end
+
+ context 'token passed as URL param' do
+ let(:params) { { token: token } }
+
+ it_behaves_like 'endpoint responding with readiness data'
+ it_behaves_like 'endpoint querying database'
+ end
+ end
+ end
+
+ describe 'GET /-/liveness' do
+ subject { get '/-/liveness', params: params, headers: headers }
+
+ shared_context 'endpoint responding with liveness data' do
+ it 'responds with liveness checks data' do
+ subject
+
+ expect(json_response).to eq('status' => 'ok')
+ end
+ end
+
+ context 'accessed from whitelisted ip' do
+ before do
+ stub_remote_addr(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint not querying database'
+ it_behaves_like 'endpoint responding with liveness data'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ stub_remote_addr(not_whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint not querying database'
+ it_behaves_like 'endpoint not found'
+
+ context 'accessed with valid token' do
+ context 'token passed in request header' do
+ let(:headers) { { TOKEN: token } }
+
+ it_behaves_like 'endpoint responding with liveness data'
+ it_behaves_like 'endpoint querying database'
+ end
+
+ context 'token passed as URL param' do
+ let(:params) { { token: token } }
+
+ it_behaves_like 'endpoint responding with liveness data'
+ it_behaves_like 'endpoint querying database'
+ end
+ end
+ end
+ end
+
+ def stub_remote_addr(ip)
+ headers.merge!(REMOTE_ADDR: ip)
+ end
+end
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index 8b2c698fee1..c1f99115612 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe JwtController do
diff --git a/spec/requests/lfs_locks_api_spec.rb b/spec/requests/lfs_locks_api_spec.rb
index 11436e5cd0c..41f54162266 100644
--- a/spec/requests/lfs_locks_api_spec.rb
+++ b/spec/requests/lfs_locks_api_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Git LFS File Locking API' do
diff --git a/spec/requests/oauth_tokens_spec.rb b/spec/requests/oauth_tokens_spec.rb
index 3873e754060..bb1c25d686e 100644
--- a/spec/requests/oauth_tokens_spec.rb
+++ b/spec/requests/oauth_tokens_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'OAuth Tokens requests' do
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index dfa17c5ff27..bac1a4e18c8 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'OpenID Connect requests' do
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index 25390f8a23e..93a1aafde23 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'cycle analytics events' do
@@ -48,7 +50,7 @@ describe 'cycle analytics events' do
expect(json_response['events'].first['iid']).to eq(first_mr_iid)
end
- it 'lists the test events' do
+ it 'lists the test events', :sidekiq_might_not_need_inline do
get project_cycle_analytics_test_path(project, format: :json)
expect(json_response['events']).not_to be_empty
@@ -64,14 +66,14 @@ describe 'cycle analytics events' do
expect(json_response['events'].first['iid']).to eq(first_mr_iid)
end
- it 'lists the staging events' do
+ it 'lists the staging events', :sidekiq_might_not_need_inline do
get project_cycle_analytics_staging_path(project, format: :json)
expect(json_response['events']).not_to be_empty
expect(json_response['events'].first['date']).not_to be_empty
end
- it 'lists the production events' do
+ it 'lists the production events', :sidekiq_might_not_need_inline do
get project_cycle_analytics_production_path(project, format: :json)
first_issue_iid = project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
@@ -81,7 +83,7 @@ describe 'cycle analytics events' do
end
context 'specific branch' do
- it 'lists the test events' do
+ it 'lists the test events', :sidekiq_might_not_need_inline do
branch = project.merge_requests.first.source_branch
get project_cycle_analytics_test_path(project, format: :json, branch: branch)
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index ca8720cd414..4d5055a7e27 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Rack Attack global throttles' do
@@ -20,6 +22,7 @@ describe 'Rack Attack global throttles' do
}
end
+ let(:request_method) { 'GET' }
let(:requests_per_period) { 1 }
let(:period_in_seconds) { 10000 }
let(:period) { period_in_seconds.seconds }
@@ -81,7 +84,7 @@ describe 'Rack Attack global throttles' do
expect(response).to have_http_status 200
end
- expect_any_instance_of(Rack::Attack::Request).to receive(:ip).and_return('1.2.3.4')
+ expect_any_instance_of(Rack::Attack::Request).to receive(:ip).at_least(:once).and_return('1.2.3.4')
# would be over limit for the same IP
get url_that_does_not_require_authentication
@@ -141,15 +144,15 @@ describe 'Rack Attack global throttles' do
let(:api_partial_url) { '/todos' }
context 'with the token in the query string' do
- let(:get_args) { [api(api_partial_url, personal_access_token: token)] }
- let(:other_user_get_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
+ let(:request_args) { [api(api_partial_url, personal_access_token: token)] }
+ let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
it_behaves_like 'rate-limited token-authenticated requests'
end
context 'with the token in the headers' do
- let(:get_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(token)) }
- let(:other_user_get_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(other_user_token)) }
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(other_user_token)) }
it_behaves_like 'rate-limited token-authenticated requests'
end
@@ -168,15 +171,15 @@ describe 'Rack Attack global throttles' do
let(:api_partial_url) { '/todos' }
context 'with the token in the query string' do
- let(:get_args) { [api(api_partial_url, oauth_access_token: token)] }
- let(:other_user_get_args) { [api(api_partial_url, oauth_access_token: other_user_token)] }
+ let(:request_args) { [api(api_partial_url, oauth_access_token: token)] }
+ let(:other_user_request_args) { [api(api_partial_url, oauth_access_token: other_user_token)] }
it_behaves_like 'rate-limited token-authenticated requests'
end
context 'with the token in the headers' do
- let(:get_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
- let(:other_user_get_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
it_behaves_like 'rate-limited token-authenticated requests'
end
@@ -188,8 +191,8 @@ describe 'Rack Attack global throttles' do
let(:throttle_setting_prefix) { 'throttle_authenticated_web' }
context 'with the token in the query string' do
- let(:get_args) { [rss_url(user), params: nil] }
- let(:other_user_get_args) { [rss_url(other_user), params: nil] }
+ let(:request_args) { [rss_url(user), params: nil] }
+ let(:other_user_request_args) { [rss_url(other_user), params: nil] }
it_behaves_like 'rate-limited token-authenticated requests'
end
@@ -204,10 +207,13 @@ describe 'Rack Attack global throttles' do
end
describe 'protected paths' do
+ let(:request_method) { 'POST' }
+
context 'unauthenticated requests' do
let(:protected_path_that_does_not_require_authentication) do
- '/users/confirmation'
+ '/users/sign_in'
end
+ let(:post_params) { { user: { login: 'username', password: 'password' } } }
before do
settings_to_set[:throttle_protected_paths_requests_per_period] = requests_per_period # 1
@@ -222,7 +228,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
- get protected_path_that_does_not_require_authentication
+ post protected_path_that_does_not_require_authentication, params: post_params
expect(response).to have_http_status 200
end
end
@@ -236,11 +242,11 @@ describe 'Rack Attack global throttles' do
it 'rejects requests over the rate limit' do
requests_per_period.times do
- get protected_path_that_does_not_require_authentication
+ post protected_path_that_does_not_require_authentication, params: post_params
expect(response).to have_http_status 200
end
- expect_rejection { get protected_path_that_does_not_require_authentication }
+ expect_rejection { post protected_path_that_does_not_require_authentication, params: post_params }
end
context 'when Omnibus throttle is present' do
@@ -251,7 +257,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
- get protected_path_that_does_not_require_authentication
+ post protected_path_that_does_not_require_authentication, params: post_params
expect(response).to have_http_status 200
end
end
@@ -265,11 +271,11 @@ describe 'Rack Attack global throttles' do
let(:other_user) { create(:user) }
let(:other_user_token) { create(:personal_access_token, user: other_user) }
let(:throttle_setting_prefix) { 'throttle_protected_paths' }
- let(:api_partial_url) { '/users' }
+ let(:api_partial_url) { '/user/emails' }
let(:protected_paths) do
[
- '/api/v4/users'
+ '/api/v4/user/emails'
]
end
@@ -279,22 +285,22 @@ describe 'Rack Attack global throttles' do
end
context 'with the token in the query string' do
- let(:get_args) { [api(api_partial_url, personal_access_token: token)] }
- let(:other_user_get_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
+ let(:request_args) { [api(api_partial_url, personal_access_token: token)] }
+ let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
it_behaves_like 'rate-limited token-authenticated requests'
end
context 'with the token in the headers' do
- let(:get_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(token)) }
- let(:other_user_get_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(other_user_token)) }
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(other_user_token)) }
it_behaves_like 'rate-limited token-authenticated requests'
end
context 'when Omnibus throttle is present' do
- let(:get_args) { [api(api_partial_url, personal_access_token: token)] }
- let(:other_user_get_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
+ let(:request_args) { [api(api_partial_url, personal_access_token: token)] }
+ let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
before do
settings_to_set[:"#{throttle_setting_prefix}_requests_per_period"] = requests_per_period
@@ -308,8 +314,8 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
- get(*get_args)
- expect(response).to have_http_status 200
+ post(*request_args)
+ expect(response).not_to have_http_status 429
end
end
end
@@ -318,7 +324,7 @@ describe 'Rack Attack global throttles' do
describe 'web requests authenticated with regular login' do
let(:throttle_setting_prefix) { 'throttle_protected_paths' }
let(:user) { create(:user) }
- let(:url_that_requires_authentication) { '/dashboard/snippets' }
+ let(:url_that_requires_authentication) { '/users/confirmation' }
let(:protected_paths) do
[
@@ -348,8 +354,8 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
- get url_that_requires_authentication
- expect(response).to have_http_status 200
+ post url_that_requires_authentication
+ expect(response).not_to have_http_status 429
end
end
end
diff --git a/spec/requests/request_profiler_spec.rb b/spec/requests/request_profiler_spec.rb
index 851affbcf88..36ccfc6b400 100644
--- a/spec/requests/request_profiler_spec.rb
+++ b/spec/requests/request_profiler_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Request Profiler' do