Skip to content
Snippets Groups Projects
Commit 3eeb9015 authored by Savas Vedova's avatar Savas Vedova
Browse files

Merge branch '431633-add-grouping-to-group-report' into 'master'

parents 55557141 916c2099
No related branches found
No related tags found
No related merge requests found
---
name: group_level_vulnerability_report_grouping
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137778
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/432778
milestone: '16.7'
type: development
group: group::threat insights
default_enabled: false
......@@ -8,6 +8,9 @@ export default {
VulnerabilityReportTabs,
},
inject: ['hasProjects'],
provide: {
isGroupVulnerabilityReport: true,
},
};
</script>
......
......@@ -11,6 +11,7 @@ import { createAlert } from '~/alert';
import countsQuery from 'ee/security_dashboard/graphql/queries/vulnerability_severities_count.query.graphql';
import SummaryHighlights from 'ee/vue_shared/security_reports/components/summary_highlights.vue';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __, s__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { scrollToElement, contentTop } from '~/lib/utils/common_utils';
......@@ -54,10 +55,14 @@ export default {
GlSprintf,
UserCalloutDismisser,
},
mixins: [glFeatureFlagsMixin()],
inject: {
fullPath: {
default: '',
},
isGroupVulnerabilityReport: {
default: false,
},
isProjectVulnerabilityReport: {
default: false,
},
......@@ -109,7 +114,18 @@ export default {
return this.filterDropdowns.includes(FILTERS.PROJECT);
},
shouldShowGroupByButton() {
return this.isProjectVulnerabilityReport && this.isVisible;
if (!this.isVisible) {
return false;
}
if (
this.isGroupVulnerabilityReport &&
this.glFeatures.groupLevelVulnerabilityReportGrouping
) {
return true;
}
return this.isProjectVulnerabilityReport;
},
groups() {
if (!this.groupBy) {
......@@ -310,8 +326,8 @@ export default {
const queryName = `groupCounts.${value}`;
const variables = {
fullPath: this.fullPath,
isProject: true,
isGroup: false,
isProject: this.isProjectVulnerabilityReport,
isGroup: this.isGroupVulnerabilityReport,
isInstance: false,
...this.graphqlFilters,
...this.formatGroupFilters(value),
......@@ -329,8 +345,10 @@ export default {
return variables;
},
update(data) {
this.$set(this.groupCounts, value, data.project?.vulnerabilitySeveritiesCount);
return data.project?.vulnerabilitySeveritiesCount;
const level = this.isProjectVulnerabilityReport ? 'project' : 'group';
this.$set(this.groupCounts, value, data[level]?.vulnerabilitySeveritiesCount);
return data[level]?.vulnerabilitySeveritiesCount;
},
error() {
createAlert({
......
......@@ -14,6 +14,7 @@ class VulnerabilitiesController < Groups::ApplicationController
before_action do
push_frontend_feature_flag(:activity_filter_has_mr, @project)
push_frontend_feature_flag(:activity_filter_has_remediations, @project)
push_frontend_feature_flag(:group_level_vulnerability_report_grouping, @project)
end
def index
......
......@@ -40,7 +40,9 @@ describe('Vulnerability report component', () => {
fullPath,
filterFn,
scanners,
isGroupVulnerabilityReport,
isProjectVulnerabilityReport = true,
glFeatures,
shouldShowCallout = false,
} = {}) => {
router = new VueRouter({
......@@ -54,9 +56,11 @@ describe('Vulnerability report component', () => {
apolloProvider,
router,
provide: {
isGroupVulnerabilityReport,
isProjectVulnerabilityReport,
fullPath,
scanners,
glFeatures,
},
propsData: {
query,
......@@ -212,13 +216,14 @@ describe('Vulnerability report component', () => {
});
});
describe('group by', () => {
describe.each`
dashboardType
${DASHBOARD_TYPES.PROJECT}
${DASHBOARD_TYPES.GROUP}
`('group by: $dashboardType', ({ dashboardType }) => {
const counts = { critical: 1, high: 2, medium: 5, low: 4, info: 3, unknown: 6 };
const getCountsRequestHandler = ({
data = counts,
dashboardType = DASHBOARD_TYPES.PROJECT,
} = {}) => {
const getCountsRequestHandler = ({ data = counts } = {}) => {
return jest.fn().mockResolvedValue({
data: {
[dashboardType]: {
......@@ -249,10 +254,17 @@ describe('Vulnerability report component', () => {
} = {}) => {
createWrapper({
apolloProvider: createMockApollo([[countsQuery, getCountsRequestHandler()]]),
isProjectVulnerabilityReport: true,
isProjectVulnerabilityReport: dashboardType === DASHBOARD_TYPES.PROJECT,
isGroupVulnerabilityReport: dashboardType === DASHBOARD_TYPES.GROUP,
fullPath: 'gitlab-org/gitlab',
shouldShowCallout,
scanners,
glFeatures:
DASHBOARD_TYPES.GROUP === dashboardType
? {
groupLevelVulnerabilityReportGrouping: true,
}
: {},
});
// Reset filters
......@@ -267,26 +279,6 @@ describe('Vulnerability report component', () => {
await waitForPromises();
};
it.each`
isProjectVulnerabilityReport | isVisible | shouldDisplay
${false} | ${true} | ${false}
${true} | ${true} | ${true}
${true} | ${false} | ${false}
`(
'displays the group by button correctly ' +
'project: $isProjectVulnerabilityReport, ' +
'isVisible: $isVisible, ' +
'should display: $shouldDisplay',
({ isProjectVulnerabilityReport, isVisible, shouldDisplay }) => {
createWrapper({
isProjectVulnerabilityReport,
isVisible,
});
expect(findGroupByButton().exists()).toBe(shouldDisplay);
},
);
it('displays the group by label', () => {
createWrapperWithFilters();
expect(wrapper.findByText('Group by:').exists()).toBe(true);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment