Commit 7721a229 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '263478-current-group-coverage-summary' into 'master'

Add group coverage metrics to repositories analytics

See merge request gitlab-org/gitlab!46610
parents 04d18a24 ec3095b4
<script>
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import TestCoverageSummary from './test_coverage_summary.vue';
import TestCoverageTable from './test_coverage_table.vue';
import DownloadTestCoverage from './download_test_coverage.vue';
export default {
name: 'GroupRepositoryAnalytics',
components: {
TestCoverageSummary,
TestCoverageTable,
DownloadTestCoverage,
},
......@@ -15,6 +17,9 @@ export default {
codeCoverageHeader: s__('RepositoriesAnalytics|Test Code Coverage'),
},
computed: {
shouldShowCoverageSummary() {
return this.glFeatures.groupCoverageDataReportGraph;
},
shouldShowCoverageReport() {
return this.glFeatures.groupCoverageDataReport;
},
......@@ -27,6 +32,7 @@ export default {
<h4 data-testid="test-coverage-header">
{{ $options.text.codeCoverageHeader }}
</h4>
<test-coverage-summary v-if="shouldShowCoverageSummary" />
<test-coverage-table v-if="shouldShowCoverageReport" class="gl-mb-5" />
<download-test-coverage />
</div>
......
<script>
import { __, s__ } from '~/locale';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
import getGroupTestCoverage from '../graphql/queries/get_group_test_coverage.query.graphql';
export default {
name: 'TestCoverageSummary',
components: {
MetricCard,
},
inject: {
groupFullPath: {
default: '',
},
},
apollo: {
group: {
query: getGroupTestCoverage,
variables() {
const ONE_WEEK = 7 * 24 * 60 * 60 * 1000; // milliseconds
return {
groupFullPath: this.groupFullPath,
startDate: new Date(Date.now() - ONE_WEEK),
};
},
result(res) {
const { projectCount, averageCoverage, coverageCount } =
res.data?.group?.codeCoverageActivities?.nodes?.[0] || {};
this.projectCount = projectCount;
this.averageCoverage = averageCoverage;
this.coverageCount = coverageCount;
},
error() {
this.hasError = true;
this.projectCount = null;
this.averageCoverage = null;
this.coverageCount = null;
},
watchLoading(isLoading) {
this.isLoading = isLoading;
},
},
},
data() {
return {
projectCount: null,
averageCoverage: null,
coverageCount: null,
hasError: false,
isLoading: false,
};
},
i18n: {
cardTitle: __('Overall Activity'),
},
computed: {
metrics() {
return [
{
key: 'projectCount',
value: this.projectCount,
label: s__('RepositoriesAnalytics|Projects with Tests'),
},
{
key: 'averageCoverage',
value: this.averageCoverage,
unit: '%',
label: s__('RepositoriesAnalytics|Average Coverage by Job'),
},
{
key: 'coverageCount',
value: this.coverageCount,
label: s__('RepositoriesAnalytics|Total Number of Coverages'),
},
];
},
},
};
</script>
<template>
<metric-card :title="$options.i18n.cardTitle" :metrics="metrics" :is-loading="isLoading" />
</template>
query getGroupTestCoverage($groupFullPath: ID!, $startDate: Date!, $last: Int = 1) {
group(fullPath: $groupFullPath) {
codeCoverageActivities(startDate: $startDate, last: $last) {
nodes {
projectCount
averageCoverage
coverageCount
date
}
}
}
}
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import { mount, createLocalVue } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import waitForPromises from 'jest/helpers/wait_for_promises';
import TestCoverageSummary from 'ee/analytics/repository_analytics/components/test_coverage_summary.vue';
import getGroupTestCoverage from 'ee/analytics/repository_analytics/graphql/queries/get_group_test_coverage.query.graphql';
const localVue = createLocalVue();
describe('Test coverage table component', () => {
useFakeDate();
let wrapper;
let fakeApollo;
const findProjectsWithTests = () => wrapper.find('.js-metric-card-item:nth-child(1) h3');
const findAverageCoverage = () => wrapper.find('.js-metric-card-item:nth-child(2) h3');
const findTotalCoverages = () => wrapper.find('.js-metric-card-item:nth-child(3) h3');
const findLoadingState = () => wrapper.find(GlSkeletonLoading);
const createComponent = ({ data = {} } = {}, withApollo = false) => {
fakeApollo = createMockApollo([[getGroupTestCoverage, jest.fn().mockResolvedValue()]]);
const props = {
localVue,
data() {
return {
projectCount: null,
averageCoverage: null,
coverageCount: null,
hasError: false,
isLoading: false,
...data,
};
},
};
if (withApollo) {
localVue.use(VueApollo);
props.apolloProvider = fakeApollo;
} else {
props.mocks = {
$apollo: {
queries: {
group: {
query: jest.fn().mockResolvedValue(),
},
},
},
};
}
wrapper = mount(TestCoverageSummary, props);
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('when group code coverage is empty', () => {
it('renders empty metrics', () => {
createComponent();
expect(findProjectsWithTests().text()).toBe('-');
expect(findAverageCoverage().text()).toBe('-');
expect(findTotalCoverages().text()).toBe('-');
});
});
describe('when query is loading', () => {
it('renders loading state', () => {
createComponent({ data: { isLoading: true } });
expect(findLoadingState().exists()).toBe(true);
});
});
describe('when group code coverage is available', () => {
it('renders coverage metrics', () => {
const projectCount = '5';
const averageCoverage = '74.35';
const coverageCount = '5';
createComponent({
data: {
projectCount,
averageCoverage,
coverageCount,
},
});
expect(findProjectsWithTests().text()).toBe(projectCount);
expect(findAverageCoverage().text()).toBe(`${averageCoverage} %`);
expect(findTotalCoverages().text()).toBe(coverageCount);
});
});
describe('when group has no coverage', () => {
it('renders empty metrics', async () => {
createComponent({
withApollo: true,
data: {},
queryData: {
data: {
group: {
codeCoverageActivities: {
nodes: [],
},
},
},
},
});
jest.runOnlyPendingTimers();
await waitForPromises();
expect(findProjectsWithTests().text()).toBe('-');
expect(findAverageCoverage().text()).toBe('-');
expect(findTotalCoverages().text()).toBe('-');
});
});
});
......@@ -19103,6 +19103,9 @@ msgstr ""
msgid "Outdent"
msgstr ""
msgid "Overall Activity"
msgstr ""
msgid "Overridden"
msgstr ""
......@@ -22751,6 +22754,9 @@ msgstr ""
msgid "Repositories Analytics"
msgstr ""
msgid "RepositoriesAnalytics|Average Coverage by Job"
msgstr ""
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
......@@ -22781,12 +22787,18 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
msgid "RepositoriesAnalytics|Projects with Tests"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
msgid "RepositoriesAnalytics|Total Number of Coverages"
msgstr ""
msgid "Repository"
msgstr ""
......
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