summaryrefslogtreecommitdiff
path: root/spec/requests/api/projects_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/api/projects_spec.rb')
-rw-r--r--spec/requests/api/projects_spec.rb214
1 files changed, 186 insertions, 28 deletions
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 7f804186bc7..e7e26c34a83 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe API::Projects do
let_it_be(:user2) { create(:user) }
let_it_be(:user3) { create(:user) }
let_it_be(:admin) { create(:admin) }
- let_it_be(:project, reload: true) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:project, reload: true) { create(:project, :repository, create_branch: 'something_else', namespace: user.namespace) }
let_it_be(:project2, reload: true) { create(:project, namespace: user.namespace) }
let_it_be(:project_member) { create(:project_member, :developer, user: user3, project: project) }
let_it_be(:user4) { create(:user, username: 'user.with.dot') }
@@ -109,6 +109,43 @@ RSpec.describe API::Projects do
end
end
+ shared_examples_for 'create project with default branch parameter' do
+ let(:params) { { name: 'Foo Project', initialize_with_readme: true, default_branch: default_branch } }
+ let(:default_branch) { 'main' }
+
+ it 'creates project with provided default branch name' do
+ expect { request }.to change { Project.count }.by(1)
+ expect(response).to have_gitlab_http_status(:created)
+
+ project = Project.find(json_response['id'])
+ expect(project.default_branch).to eq(default_branch)
+ end
+
+ context 'when branch name is empty' do
+ let(:default_branch) { '' }
+
+ it 'creates project with a default project branch name' do
+ expect { request }.to change { Project.count }.by(1)
+ expect(response).to have_gitlab_http_status(:created)
+
+ project = Project.find(json_response['id'])
+ expect(project.default_branch).to eq('master')
+ end
+ end
+
+ context 'when initialize with readme is not set' do
+ let(:params) { super().merge(initialize_with_readme: nil) }
+
+ it 'creates project with a default project branch name' do
+ expect { request }.to change { Project.count }.by(1)
+ expect(response).to have_gitlab_http_status(:created)
+
+ project = Project.find(json_response['id'])
+ expect(project.default_branch).to be_nil
+ end
+ end
+ end
+
describe 'GET /projects' do
shared_examples_for 'projects response' do
it 'returns an array of projects' do
@@ -184,13 +221,40 @@ RSpec.describe API::Projects do
end
end
- it 'includes the project labels as the tag_list' do
+ it 'includes correct value of container_registry_enabled', :aggregate_failures do
+ project.update_column(:container_registry_enabled, true)
+ project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
+
+ get api('/projects', user)
+ project_response = json_response.find { |p| p['id'] == project.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(project_response['container_registry_enabled']).to eq(false)
+ end
+
+ it 'reads projects.container_registry_enabled when read_container_registry_access_level is disabled' do
+ stub_feature_flags(read_container_registry_access_level: false)
+
+ project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
+ project.update_column(:container_registry_enabled, true)
+
+ get api('/projects', user)
+ project_response = json_response.find { |p| p['id'] == project.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(project_response['container_registry_enabled']).to eq(true)
+ end
+
+ it 'includes project topics' do
get api('/projects', user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.first.keys).to include('tag_list')
+ expect(json_response.first.keys).to include('tag_list') # deprecated in favor of 'topics'
+ expect(json_response.first.keys).to include('topics')
end
it 'includes open_issues_count' do
@@ -223,9 +287,9 @@ RSpec.describe API::Projects do
expect(json_response.find { |hash| hash['id'] == project.id }.keys).not_to include('open_issues_count')
end
- context 'filter by topic (column tag_list)' do
+ context 'filter by topic (column topic_list)' do
before do
- project.update!(tag_list: %w(ruby javascript))
+ project.update!(topic_list: %w(ruby javascript))
end
it 'returns no projects' do
@@ -742,10 +806,6 @@ RSpec.describe API::Projects do
it 'includes a pagination header with link to the next page' do
get api('/projects', current_user), params: params
- expect(response.header).to include('Links')
- expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_after=#{first_project_id}")
-
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
expect(response.header['Link']).to include("id_after=#{first_project_id}")
@@ -762,10 +822,6 @@ RSpec.describe API::Projects do
it 'still includes a link if the end has reached and there is no more data after this page' do
get api('/projects', current_user), params: params.merge(id_after: project2.id)
- expect(response.header).to include('Links')
- expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_after=#{project3.id}")
-
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
expect(response.header['Link']).to include("id_after=#{project3.id}")
@@ -774,7 +830,6 @@ RSpec.describe API::Projects do
it 'does not include a next link when the page does not have any records' do
get api('/projects', current_user), params: params.merge(id_after: Project.maximum(:id))
- expect(response.header).not_to include('Links')
expect(response.header).not_to include('Link')
end
@@ -798,10 +853,6 @@ RSpec.describe API::Projects do
it 'includes a pagination header with link to the next page' do
get api('/projects', current_user), params: params
- expect(response.header).to include('Links')
- expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_before=#{last_project_id}")
-
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
expect(response.header['Link']).to include("id_before=#{last_project_id}")
@@ -828,11 +879,6 @@ RSpec.describe API::Projects do
requests += 1
get api(url, current_user), params: params
- links = response.header['Links']
- url = links&.match(/<[^>]+(\/projects\?[^>]+)>; rel="next"/) do |match|
- match[1]
- end
-
link = response.header['Link']
url = link&.match(/<[^>]+(\/projects\?[^>]+)>; rel="next"/) do |match|
match[1]
@@ -938,6 +984,10 @@ RSpec.describe API::Projects do
expect(project.path).to eq('path-project-Foo')
end
+ it_behaves_like 'create project with default branch parameter' do
+ let(:request) { post api('/projects', user), params: params }
+ end
+
it 'creates last project before reaching project limit' do
allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1)
post api('/projects', user2), params: { name: 'foo' }
@@ -1050,12 +1100,20 @@ RSpec.describe API::Projects do
expect(json_response['readme_url']).to eql("#{Gitlab.config.gitlab.url}/#{json_response['namespace']['full_path']}/somewhere/-/blob/master/README.md")
end
- it 'sets tag list to a project' do
+ it 'sets tag list to a project (deprecated)' do
project = attributes_for(:project, tag_list: %w[tagFirst tagSecond])
post api('/projects', user), params: project
- expect(json_response['tag_list']).to eq(%w[tagFirst tagSecond])
+ expect(json_response['topics']).to eq(%w[tagFirst tagSecond])
+ end
+
+ it 'sets topics to a project' do
+ project = attributes_for(:project, topics: %w[topic1 topics2])
+
+ post api('/projects', user), params: project
+
+ expect(json_response['topics']).to eq(%w[topic1 topics2])
end
it 'uploads avatar for project a project' do
@@ -1410,6 +1468,10 @@ RSpec.describe API::Projects do
expect(project.path).to eq('path-project-Foo')
end
+ it_behaves_like 'create project with default branch parameter' do
+ let(:request) { post api("/projects/user/#{user.id}", admin), params: params }
+ end
+
it 'responds with 400 on failure and not project' do
expect { post api("/projects/user/#{user.id}", admin) }
.not_to change { Project.count }
@@ -1910,7 +1972,8 @@ RSpec.describe API::Projects do
expect(json_response['id']).to eq(project.id)
expect(json_response['description']).to eq(project.description)
expect(json_response['default_branch']).to eq(project.default_branch)
- expect(json_response['tag_list']).to be_an Array
+ expect(json_response['tag_list']).to be_an Array # deprecated in favor of 'topics'
+ expect(json_response['topics']).to be_an Array
expect(json_response['archived']).to be_falsey
expect(json_response['visibility']).to be_present
expect(json_response['ssh_url_to_repo']).to be_present
@@ -1987,7 +2050,8 @@ RSpec.describe API::Projects do
expect(json_response['id']).to eq(project.id)
expect(json_response['description']).to eq(project.description)
expect(json_response['default_branch']).to eq(project.default_branch)
- expect(json_response['tag_list']).to be_an Array
+ expect(json_response['tag_list']).to be_an Array # deprecated in favor of 'topics'
+ expect(json_response['topics']).to be_an Array
expect(json_response['archived']).to be_falsey
expect(json_response['visibility']).to be_present
expect(json_response['ssh_url_to_repo']).to be_present
@@ -2043,8 +2107,10 @@ RSpec.describe API::Projects do
expect(json_response['ci_default_git_depth']).to eq(project.ci_default_git_depth)
expect(json_response['ci_forward_deployment_enabled']).to eq(project.ci_forward_deployment_enabled)
expect(json_response['merge_method']).to eq(project.merge_method.to_s)
+ expect(json_response['squash_option']).to eq(project.squash_option.to_s)
expect(json_response['readme_url']).to eq(project.readme_url)
expect(json_response).to have_key 'packages_enabled'
+ expect(json_response['keep_latest_artifact']).to be_present
end
it 'returns a group link with expiration date' do
@@ -2755,7 +2821,7 @@ RSpec.describe API::Projects do
expect(project.project_group_links).to be_empty
end
- it 'updates project authorization' do
+ it 'updates project authorization', :sidekiq_inline do
expect do
delete api("/projects/#{project.id}/share/#{group.id}", user)
end.to(
@@ -2902,6 +2968,18 @@ RSpec.describe API::Projects do
end
end
+ it 'updates default_branch' do
+ project_param = { default_branch: 'something_else' }
+
+ put api("/projects/#{project.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ project_param.each_pair do |k, v|
+ expect(json_response[k.to_s]).to eq(v)
+ end
+ end
+
it 'updates jobs_enabled' do
project_param = { jobs_enabled: true }
@@ -3027,6 +3105,26 @@ RSpec.describe API::Projects do
expect(json_response['auto_devops_enabled']).to eq(false)
end
+
+ it 'updates topics using tag_list (deprecated)' do
+ project_param = { tag_list: 'topic1' }
+
+ put api("/projects/#{project3.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(json_response['topics']).to eq(%w[topic1])
+ end
+
+ it 'updates topics' do
+ project_param = { topics: 'topic2' }
+
+ put api("/projects/#{project3.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(json_response['topics']).to eq(%w[topic2])
+ end
end
context 'when authenticated as project maintainer' do
@@ -3203,6 +3301,24 @@ RSpec.describe API::Projects do
expect { subject }.to change { project.reload.service_desk_enabled }.to(true)
end
end
+
+ context 'when updating keep latest artifact' do
+ subject { put(api("/projects/#{project.id}", user), params: { keep_latest_artifact: true }) }
+
+ before do
+ project.update!(keep_latest_artifact: false)
+ end
+
+ it 'returns 200' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'enables keep_latest_artifact' do
+ expect { subject }.to change { project.reload.keep_latest_artifact }.to(true)
+ end
+ end
end
describe 'POST /projects/:id/archive' do
@@ -3882,6 +3998,48 @@ RSpec.describe API::Projects do
end
end
+ describe 'GET /projects/:id/storage' do
+ context 'when unauthenticated' do
+ it 'does not return project storage data' do
+ get api("/projects/#{project.id}/storage")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ it 'returns project storage data when user is admin' do
+ get api("/projects/#{project.id}/storage", create(:admin))
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['project_id']).to eq(project.id)
+ expect(json_response['disk_path']).to eq(project.repository.disk_path)
+ expect(json_response['created_at']).to be_present
+ expect(json_response['repository_storage']).to eq(project.repository_storage)
+ end
+
+ it 'does not return project storage data when user is not admin' do
+ get api("/projects/#{project.id}/storage", user3)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'responds with a 401 for unauthenticated users trying to access a non-existent project id' do
+ expect(Project.find_by(id: non_existing_record_id)).to be_nil
+
+ get api("/projects/#{non_existing_record_id}/storage")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'responds with a 403 for non-admin users trying to access a non-existent project id' do
+ expect(Project.find_by(id: non_existing_record_id)).to be_nil
+
+ get api("/projects/#{non_existing_record_id}/storage", user3)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
it_behaves_like 'custom attributes endpoints', 'projects' do
let(:attributable) { project }
let(:other_attributable) { project2 }