Commit 1fa5509a authored by Miranda Fluharty's avatar Miranda Fluharty Committed by Scott Hampton

Add Project Quality tab to pipeline charts

Blank placeholder tab for now
Only show it if the licensed feature is available
and the feature flag is enabled
parent c5fbcdd5
...@@ -11,12 +11,17 @@ export default { ...@@ -11,12 +11,17 @@ export default {
DeploymentFrequencyCharts: () => DeploymentFrequencyCharts: () =>
import('ee_component/dora/components/deployment_frequency_charts.vue'), import('ee_component/dora/components/deployment_frequency_charts.vue'),
LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'), LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'),
ProjectQualitySummary: () => import('ee_component/project_quality_summary/app.vue'),
}, },
inject: { inject: {
shouldRenderDoraCharts: { shouldRenderDoraCharts: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
shouldRenderQualitySummary: {
type: Boolean,
default: false,
},
}, },
data() { data() {
return { return {
...@@ -31,6 +36,10 @@ export default { ...@@ -31,6 +36,10 @@ export default {
chartsToShow.push('deployment-frequency', 'lead-time'); chartsToShow.push('deployment-frequency', 'lead-time');
} }
if (this.shouldRenderQualitySummary) {
chartsToShow.push('project-quality');
}
return chartsToShow; return chartsToShow;
}, },
}, },
...@@ -68,6 +77,9 @@ export default { ...@@ -68,6 +77,9 @@ export default {
<lead-time-charts /> <lead-time-charts />
</gl-tab> </gl-tab>
</template> </template>
<gl-tab v-if="shouldRenderQualitySummary" :title="s__('QualitySummary|Project quality')">
<project-quality-summary />
</gl-tab>
</gl-tabs> </gl-tabs>
<pipeline-charts v-else /> <pipeline-charts v-else />
</div> </div>
......
...@@ -14,6 +14,7 @@ const mountPipelineChartsApp = (el) => { ...@@ -14,6 +14,7 @@ const mountPipelineChartsApp = (el) => {
const { projectPath } = el.dataset; const { projectPath } = el.dataset;
const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts); const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
const shouldRenderQualitySummary = parseBoolean(el.dataset.shouldRenderQualitySummary);
return new Vue({ return new Vue({
el, el,
...@@ -25,6 +26,7 @@ const mountPipelineChartsApp = (el) => { ...@@ -25,6 +26,7 @@ const mountPipelineChartsApp = (el) => {
provide: { provide: {
projectPath, projectPath,
shouldRenderDoraCharts, shouldRenderDoraCharts,
shouldRenderQualitySummary,
}, },
render: (createElement) => createElement(ProjectPipelinesCharts, {}), render: (createElement) => createElement(ProjectPipelinesCharts, {}),
}); });
......
...@@ -26,6 +26,10 @@ module GraphHelper ...@@ -26,6 +26,10 @@ module GraphHelper
def should_render_dora_charts def should_render_dora_charts
false false
end end
def should_render_quality_summary
false
end
end end
GraphHelper.prepend_mod_with('GraphHelper') GraphHelper.prepend_mod_with('GraphHelper')
- page_title _('CI/CD Analytics') - page_title _('CI/CD Analytics')
#js-project-pipelines-charts-app{ data: { project_path: @project.full_path, #js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
should_render_dora_charts: should_render_dora_charts.to_s } } should_render_dora_charts: should_render_dora_charts.to_s,
should_render_quality_summary: should_render_quality_summary.to_s } }
<script>
export default {};
</script>
<template><div></div></template>
...@@ -12,5 +12,11 @@ module EE ...@@ -12,5 +12,11 @@ module EE
can?(current_user, :read_dora4_analytics, container) can?(current_user, :read_dora4_analytics, container)
end end
override :should_render_quality_summary
def should_render_quality_summary
@project.feature_available?(:project_quality_summary) &&
::Feature.enabled?(:project_quality_summary_page, @project, default_enabled: :yaml)
end
end end
end end
...@@ -177,6 +177,7 @@ class License < ApplicationRecord ...@@ -177,6 +177,7 @@ class License < ApplicationRecord
kubernetes_cluster_vulnerabilities kubernetes_cluster_vulnerabilities
license_scanning license_scanning
personal_access_token_expiration_policy personal_access_token_expiration_policy
project_quality_summary
prometheus_alerts prometheus_alerts
pseudonymizer pseudonymizer
quality_management quality_management
......
---
name: project_quality_summary_page
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72724
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343687
milestone: '14.4'
type: development
group: group::testing
default_enabled: false
...@@ -58,4 +58,38 @@ RSpec.describe EE::GraphHelper do ...@@ -58,4 +58,38 @@ RSpec.describe EE::GraphHelper do
it_behaves_like '#should_render_dora_charts for a specific type of container' it_behaves_like '#should_render_dora_charts for a specific type of container'
end end
end end
describe '#should_render_quality_summary' do
subject { helper.should_render_quality_summary }
before do
self.instance_variable_set(:@project, project)
end
context 'when licensed feature is available' do
before do
stub_licensed_features(project_quality_summary: true)
end
context 'when feature flag is enabled' do
it { is_expected.to eq(true) }
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(project_quality_summary_page: false)
end
it { is_expected.to eq(false) }
end
end
context 'when licensed feature is not available' do
before do
stub_licensed_features(project_quality_summary: false)
end
it { is_expected.to eq(false) }
end
end
end end
...@@ -28215,6 +28215,9 @@ msgstr "" ...@@ -28215,6 +28215,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}" msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "" msgstr ""
msgid "QualitySummary|Project quality"
msgstr ""
msgid "Quarters" msgid "Quarters"
msgstr "" msgstr ""
......
...@@ -11,6 +11,7 @@ jest.mock('~/lib/utils/url_utility'); ...@@ -11,6 +11,7 @@ jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} }; const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} }; const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} };
const ProjectQualitySummaryStub = { name: 'ProjectQualitySummary', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => { describe('ProjectsPipelinesChartsApp', () => {
let wrapper; let wrapper;
...@@ -23,10 +24,12 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -23,10 +24,12 @@ describe('ProjectsPipelinesChartsApp', () => {
{ {
provide: { provide: {
shouldRenderDoraCharts: true, shouldRenderDoraCharts: true,
shouldRenderQualitySummary: true,
}, },
stubs: { stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub, DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
LeadTimeCharts: LeadTimeChartsStub, LeadTimeCharts: LeadTimeChartsStub,
ProjectQualitySummary: ProjectQualitySummaryStub,
}, },
}, },
mountOptions, mountOptions,
...@@ -44,6 +47,7 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -44,6 +47,7 @@ describe('ProjectsPipelinesChartsApp', () => {
const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub); const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub);
const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub); const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findPipelineCharts = () => wrapper.find(PipelineCharts); const findPipelineCharts = () => wrapper.find(PipelineCharts);
const findProjectQualitySummary = () => wrapper.find(ProjectQualitySummaryStub);
describe('when all charts are available', () => { describe('when all charts are available', () => {
beforeEach(() => { beforeEach(() => {
...@@ -70,6 +74,10 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -70,6 +74,10 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findLeadTimeCharts().exists()).toBe(true); expect(findLeadTimeCharts().exists()).toBe(true);
}); });
it('renders the project quality summary', () => {
expect(findProjectQualitySummary().exists()).toBe(true);
});
it('sets the tab and url when a tab is clicked', async () => { it('sets the tab and url when a tab is clicked', async () => {
let chartsPath; let chartsPath;
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`); setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
...@@ -163,9 +171,11 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -163,9 +171,11 @@ describe('ProjectsPipelinesChartsApp', () => {
}); });
}); });
describe('when the dora charts are not available', () => { describe('when the dora charts are not available and project quality summary is not available', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ provide: { shouldRenderDoraCharts: false } }); createComponent({
provide: { shouldRenderDoraCharts: false, shouldRenderQualitySummary: false },
});
}); });
it('does not render tabs', () => { it('does not render tabs', () => {
...@@ -176,4 +186,14 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -176,4 +186,14 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findPipelineCharts().exists()).toBe(true); expect(findPipelineCharts().exists()).toBe(true);
}); });
}); });
describe('when the project quality summary is not available', () => {
beforeEach(() => {
createComponent({ provide: { shouldRenderQualitySummary: false } });
});
it('does not render the tab', () => {
expect(findProjectQualitySummary().exists()).toBe(false);
});
});
}); });
...@@ -27,4 +27,16 @@ RSpec.describe GraphHelper do ...@@ -27,4 +27,16 @@ RSpec.describe GraphHelper do
expect(should_render_dora_charts).to be(false) expect(should_render_dora_charts).to be(false)
end end
end end
describe '#should_render_quality_summary' do
let(:project) { create(:project, :private) }
before do
self.instance_variable_set(:@project, project)
end
it 'always returns false' do
expect(should_render_quality_summary).to be(false)
end
end
end end
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