Commit c6eaabd0 authored by Jan Provaznik's avatar Jan Provaznik

Merge branch '36667-add-release-count-to-project-homepage' into 'master'

Resolve "Add release count to project homepage"

Closes #36667

See merge request gitlab-org/gitlab!21350
parents 3abd7b97 23003bdd
......@@ -24,7 +24,8 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
commits_anchor_data,
branches_anchor_data,
tags_anchor_data,
files_anchor_data
files_anchor_data,
releases_anchor_data
].compact.select(&:is_link)
end
......@@ -153,6 +154,22 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
empty_repo? ? nil : project_tree_path(project))
end
def releases_anchor_data
return unless can?(current_user, :read_release, project)
releases_count = project.releases.count
return if releases_count < 1
AnchorData.new(true,
statistic_icon('rocket') +
n_('%{strong_start}%{release_count}%{strong_end} Release', '%{strong_start}%{release_count}%{strong_end} Releases', releases_count).html_safe % {
release_count: number_with_delimiter(releases_count),
strong_start: '<strong class="project-stat-value">'.html_safe,
strong_end: '</strong>'.html_safe
},
project_releases_path(project))
end
def commits_anchor_data
AnchorData.new(true,
statistic_icon('commit') +
......
---
title: Add release count to project homepage
merge_request: 21350
author:
type: added
......@@ -401,6 +401,11 @@ msgstr[1] ""
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
msgid "%{strong_start}%{release_count}%{strong_end} Release"
msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
msgstr[0] ""
msgstr[1] ""
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
msgstr[0] ""
......
......@@ -33,10 +33,10 @@ describe ProjectPresenter do
describe '#default_view' do
context 'user not signed in' do
let(:user) { nil }
let_it_be(:user) { nil }
context 'when repository is empty' do
let(:project) { create(:project_empty_repo, :public) }
let_it_be(:project) { create(:project_empty_repo, :public) }
it 'returns activity if user has repository access' do
allow(presenter).to receive(:can?).with(nil, :download_code, project).and_return(true)
......@@ -52,7 +52,8 @@ describe ProjectPresenter do
end
context 'when repository is not empty' do
let(:project) { create(:project, :public, :repository) }
let_it_be(:project) { create(:project, :public, :repository) }
let(:release) { create(:release, project: project, author: user) }
it 'returns files and readme if user has repository access' do
allow(presenter).to receive(:can?).with(nil, :download_code, project).and_return(true)
......@@ -65,6 +66,15 @@ describe ProjectPresenter do
expect(presenter.default_view).to eq('activity')
end
it 'returns releases anchor' do
expect(release).to be_truthy
expect(presenter.releases_anchor_data).to have_attributes(
is_link: true,
label: a_string_including("#{project.releases.count}"),
link: presenter.project_releases_path(project)
)
end
end
end
......@@ -121,10 +131,8 @@ describe ProjectPresenter do
end
describe '#can_current_user_push_code?' do
let(:project) { create(:project, :repository) }
context 'empty repo' do
let(:project) { create(:project) }
let_it_be(:project) { create(:project) }
it 'returns true if user can push_code' do
project.add_developer(user)
......@@ -150,6 +158,7 @@ describe ProjectPresenter do
it 'returns false if default branch is protected' do
project.add_developer(user)
create(:protected_branch, project: project, name: project.default_branch)
expect(presenter.can_current_user_push_code?).to be(false)
......@@ -158,73 +167,125 @@ describe ProjectPresenter do
end
context 'statistics anchors (empty repo)' do
let(:project) { create(:project, :empty_repo) }
let_it_be(:project) { create(:project, :empty_repo) }
describe '#files_anchor_data' do
it 'returns files data' do
expect(presenter.files_anchor_data).to have_attributes(is_link: true,
label: a_string_including('0 Bytes'),
link: nil)
expect(presenter.files_anchor_data).to have_attributes(
is_link: true,
label: a_string_including('0 Bytes'),
link: nil
)
end
end
describe '#releases_anchor_data' do
it 'does not return release count' do
expect(presenter.releases_anchor_data).to be_nil
end
end
describe '#commits_anchor_data' do
it 'returns commits data' do
expect(presenter.commits_anchor_data).to have_attributes(is_link: true,
label: a_string_including('0'),
link: nil)
expect(presenter.commits_anchor_data).to have_attributes(
is_link: true,
label: a_string_including('0'),
link: nil
)
end
end
describe '#branches_anchor_data' do
it 'returns branches data' do
expect(presenter.branches_anchor_data).to have_attributes(is_link: true,
label: a_string_including('0'),
link: nil)
expect(presenter.branches_anchor_data).to have_attributes(
is_link: true,
label: a_string_including('0'),
link: nil
)
end
end
describe '#tags_anchor_data' do
it 'returns tags data' do
expect(presenter.tags_anchor_data).to have_attributes(is_link: true,
label: a_string_including('0'),
link: nil)
expect(presenter.tags_anchor_data).to have_attributes(
is_link: true,
label: a_string_including('0'),
link: nil
)
end
end
end
context 'statistics anchors' do
let(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:release) { create(:release, project: project, author: user) }
let(:presenter) { described_class.new(project, current_user: user) }
describe '#files_anchor_data' do
it 'returns files data' do
expect(presenter.files_anchor_data).to have_attributes(is_link: true,
label: a_string_including('0 Bytes'),
link: presenter.project_tree_path(project))
expect(presenter.files_anchor_data).to have_attributes(
is_link: true,
label: a_string_including('0 Bytes'),
link: presenter.project_tree_path(project)
)
end
end
describe '#releases_anchor_data' do
it 'returns release count if user can read release' do
project.add_maintainer(user)
expect(release).to be_truthy
expect(presenter.releases_anchor_data).to have_attributes(
is_link: true,
label: a_string_including("#{project.releases.count}"),
link: presenter.project_releases_path(project)
)
end
it 'returns nil if user cannot read release' do
expect(release).to be_truthy
expect(presenter.releases_anchor_data).to be_nil
end
context 'user not signed in' do
let_it_be(:user) { nil }
it 'returns nil if user is signed out' do
expect(release).to be_truthy
expect(presenter.releases_anchor_data).to be_nil
end
end
end
describe '#commits_anchor_data' do
it 'returns commits data' do
expect(presenter.commits_anchor_data).to have_attributes(is_link: true,
label: a_string_including('0'),
link: presenter.project_commits_path(project, project.repository.root_ref))
expect(presenter.commits_anchor_data).to have_attributes(
is_link: true,
label: a_string_including('0'),
link: presenter.project_commits_path(project, project.repository.root_ref)
)
end
end
describe '#branches_anchor_data' do
it 'returns branches data' do
expect(presenter.branches_anchor_data).to have_attributes(is_link: true,
label: a_string_including("#{project.repository.branches.size}"),
link: presenter.project_branches_path(project))
expect(presenter.branches_anchor_data).to have_attributes(
is_link: true,
label: a_string_including("#{project.repository.branches.size}"),
link: presenter.project_branches_path(project)
)
end
end
describe '#tags_anchor_data' do
it 'returns tags data' do
expect(presenter.tags_anchor_data).to have_attributes(is_link: true,
label: a_string_including("#{project.repository.tags.size}"),
link: presenter.project_tags_path(project))
expect(presenter.tags_anchor_data).to have_attributes(
is_link: true,
label: a_string_including("#{project.repository.tags.size}"),
link: presenter.project_tags_path(project)
)
end
end
......@@ -232,10 +293,12 @@ describe ProjectPresenter do
it 'returns new file data if user can push' do
project.add_developer(user)
expect(presenter.new_file_anchor_data).to have_attributes(is_link: false,
label: a_string_including("New file"),
link: presenter.project_new_blob_path(project, 'master'),
class_modifier: 'success')
expect(presenter.new_file_anchor_data).to have_attributes(
is_link: false,
label: a_string_including("New file"),
link: presenter.project_new_blob_path(project, 'master'),
class_modifier: 'success'
)
end
it 'returns nil if user cannot push' do
......@@ -243,7 +306,7 @@ describe ProjectPresenter do
end
context 'when the project is empty' do
let(:project) { create(:project, :empty_repo) }
let_it_be(:project) { create(:project, :empty_repo) }
# Since we protect the default branch for empty repos
it 'is empty for a developer' do
......@@ -258,11 +321,14 @@ describe ProjectPresenter do
context 'when user can push and README does not exists' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:readme).and_return(nil)
expect(presenter.readme_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Add README'),
link: presenter.add_readme_path)
expect(presenter.readme_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Add README'),
link: presenter.add_readme_path
)
end
end
......@@ -270,9 +336,11 @@ describe ProjectPresenter do
it 'returns anchor data' do
allow(project.repository).to receive(:readme).and_return(double(name: 'readme'))
expect(presenter.readme_anchor_data).to have_attributes(is_link: false,
label: a_string_including('README'),
link: presenter.readme_path)
expect(presenter.readme_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('README'),
link: presenter.readme_path
)
end
end
end
......@@ -281,11 +349,14 @@ describe ProjectPresenter do
context 'when user can push and CHANGELOG does not exist' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:changelog).and_return(nil)
expect(presenter.changelog_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Add CHANGELOG'),
link: presenter.add_changelog_path)
expect(presenter.changelog_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Add CHANGELOG'),
link: presenter.add_changelog_path
)
end
end
......@@ -293,9 +364,11 @@ describe ProjectPresenter do
it 'returns anchor data' do
allow(project.repository).to receive(:changelog).and_return(double(name: 'foo'))
expect(presenter.changelog_anchor_data).to have_attributes(is_link: false,
label: a_string_including('CHANGELOG'),
link: presenter.changelog_path)
expect(presenter.changelog_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('CHANGELOG'),
link: presenter.changelog_path
)
end
end
end
......@@ -304,11 +377,14 @@ describe ProjectPresenter do
context 'when user can push and LICENSE does not exist' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:license_blob).and_return(nil)
expect(presenter.license_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Add LICENSE'),
link: presenter.add_license_path)
expect(presenter.license_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Add LICENSE'),
link: presenter.add_license_path
)
end
end
......@@ -316,9 +392,11 @@ describe ProjectPresenter do
it 'returns anchor data' do
allow(project.repository).to receive(:license_blob).and_return(double(name: 'foo'))
expect(presenter.license_anchor_data).to have_attributes(is_link: false,
label: a_string_including(presenter.license_short_name),
link: presenter.license_path)
expect(presenter.license_anchor_data).to have_attributes(
is_link: false,
label: a_string_including(presenter.license_short_name),
link: presenter.license_path
)
end
end
end
......@@ -327,11 +405,14 @@ describe ProjectPresenter do
context 'when user can push and CONTRIBUTING does not exist' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:contribution_guide).and_return(nil)
expect(presenter.contribution_guide_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Add CONTRIBUTING'),
link: presenter.add_contribution_guide_path)
expect(presenter.contribution_guide_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Add CONTRIBUTING'),
link: presenter.add_contribution_guide_path
)
end
end
......@@ -339,9 +420,11 @@ describe ProjectPresenter do
it 'returns anchor data' do
allow(project.repository).to receive(:contribution_guide).and_return(double(name: 'foo'))
expect(presenter.contribution_guide_anchor_data).to have_attributes(is_link: false,
label: a_string_including('CONTRIBUTING'),
link: presenter.contribution_guide_path)
expect(presenter.contribution_guide_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('CONTRIBUTING'),
link: presenter.contribution_guide_path
)
end
end
end
......@@ -351,21 +434,26 @@ describe ProjectPresenter do
it 'returns anchor data' do
allow(project).to receive(:auto_devops_enabled?).and_return(true)
expect(presenter.autodevops_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Auto DevOps enabled'),
link: nil)
expect(presenter.autodevops_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Auto DevOps enabled'),
link: nil
)
end
end
context 'when user can admin pipeline and CI yml does not exist' do
it 'returns anchor data' do
project.add_maintainer(user)
allow(project).to receive(:auto_devops_enabled?).and_return(false)
allow(project.repository).to receive(:gitlab_ci_yml).and_return(nil)
expect(presenter.autodevops_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Enable Auto DevOps'),
link: presenter.project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
expect(presenter.autodevops_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Enable Auto DevOps'),
link: presenter.project_settings_ci_cd_path(project, anchor: 'autodevops-settings')
)
end
end
end
......@@ -374,29 +462,37 @@ describe ProjectPresenter do
context 'when user can create Kubernetes cluster' do
it 'returns link to cluster if only one exists' do
project.add_maintainer(user)
cluster = create(:cluster, projects: [project])
expect(presenter.kubernetes_cluster_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Kubernetes configured'),
link: presenter.project_cluster_path(project, cluster))
expect(presenter.kubernetes_cluster_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Kubernetes configured'),
link: presenter.project_cluster_path(project, cluster)
)
end
it 'returns link to clusters page if more than one exists' do
project.add_maintainer(user)
create(:cluster, :production_environment, projects: [project])
create(:cluster, projects: [project])
expect(presenter.kubernetes_cluster_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Kubernetes configured'),
link: presenter.project_clusters_path(project))
expect(presenter.kubernetes_cluster_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Kubernetes configured'),
link: presenter.project_clusters_path(project)
)
end
it 'returns link to create a cluster if no cluster exists' do
project.add_maintainer(user)
expect(presenter.kubernetes_cluster_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Add Kubernetes cluster'),
link: presenter.new_project_cluster_path(project))
expect(presenter.kubernetes_cluster_anchor_data).to have_attributes(
is_link: false,
label: a_string_including('Add Kubernetes cluster'),
link: presenter.new_project_cluster_path(project)
)
end
end
......@@ -464,7 +560,7 @@ describe ProjectPresenter do
end
context 'initialized repo' do
let(:project) { create(:project, :repository) }
let_it_be(:project) { create(:project, :repository) }
it 'orders the items correctly' do
expect(empty_repo_statistics_buttons.map(&:label)).to start_with(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment