Commit d61c5521 authored by David O'Regan's avatar David O'Regan

Merge branch '284471-simplify-vulnerability-count-list' into 'master'

Simplify vulnerability count list GraphQL query variables

See merge request gitlab-org/gitlab!58522
parents a950f7ac 1c2efd38
<script>
import Cookies from 'js-cookie';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { vulnerabilitiesSeverityCountScopes } from '../constants';
import AutoFixUserCallout from './auto_fix_user_callout.vue';
import CsvExportButton from './csv_export_button.vue';
import ReportsNotConfigured from './empty_states/reports_not_configured.vue';
......@@ -54,7 +53,6 @@ export default {
this.shouldShowAutoFixUserCallout = false;
},
},
vulnerabilitiesSeverityCountScopes,
};
</script>
......@@ -79,7 +77,6 @@ export default {
<project-pipeline-status :pipeline="pipeline" />
<vulnerabilities-count-list
class="gl-mt-6"
:scope="$options.vulnerabilitiesSeverityCountScopes.project"
:full-path="projectFullPath"
:filters="filters"
/>
......
<script>
import { vulnerabilitiesSeverityCountScopes } from '../constants';
import vulnerabilitySeveritiesCountQuery from '../graphql/queries/vulnerability_severities_count.query.graphql';
import { DASHBOARD_TYPES } from '../store/constants';
import eventHub from '../utils/event_hub';
import VulnerabilityCountListLayout from './vulnerability_count_list_layout.vue';
......@@ -8,12 +8,8 @@ export default {
components: {
VulnerabilityCountListLayout,
},
inject: ['dashboardType'],
props: {
scope: {
type: String,
required: true,
validator: (value) => Object.values(vulnerabilitiesSeverityCountScopes).includes(value),
},
fullPath: {
type: String,
required: false,
......@@ -45,13 +41,12 @@ export default {
vulnerabilitiesCount: {
query: vulnerabilitySeveritiesCountQuery,
variables() {
const { scope, fullPath } = this;
const { instance, group, project } = vulnerabilitiesSeverityCountScopes;
const { dashboardType, fullPath } = this;
return {
fullPath,
isInstance: scope === instance,
isGroup: scope === group,
isProject: scope === project,
isInstance: dashboardType === DASHBOARD_TYPES.INSTANCE,
isGroup: dashboardType === DASHBOARD_TYPES.GROUP,
isProject: dashboardType === DASHBOARD_TYPES.PROJECT,
...this.filters,
};
},
......
......@@ -6,7 +6,6 @@ import Filters from 'ee/security_dashboard/components/first_class_vulnerability_
import SecurityDashboardLayout from 'ee/security_dashboard/components/security_dashboard_layout.vue';
import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants';
import { s__ } from '~/locale';
import { vulnerabilitiesSeverityCountScopes } from '../constants';
import vulnerableProjectsGroupQuery from '../graphql/queries/vulnerable_projects_group.query.graphql';
import vulnerableProjectsInstanceQuery from '../graphql/queries/vulnerable_projects_instance.query.graphql';
import CsvExportButton from './csv_export_button.vue';
......@@ -28,14 +27,7 @@ export default {
GlLoadingIcon,
VulnerabilitiesCountList,
},
inject: ['groupFullPath'],
props: {
dashboardType: {
type: String,
required: true,
validator: (value) => Object.values(DASHBOARD_TYPES).includes(value),
},
},
inject: ['groupFullPath', 'dashboardType'],
queries: {
[DASHBOARD_TYPES.GROUP]: vulnerableProjectsGroupQuery,
[DASHBOARD_TYPES.INSTANCE]: vulnerableProjectsInstanceQuery,
......@@ -68,11 +60,6 @@ export default {
projectsWereFetched() {
return !this.$apollo.queries.projects?.loading;
},
scope() {
return this.isGroup
? vulnerabilitiesSeverityCountScopes.group
: vulnerabilitiesSeverityCountScopes.instance;
},
isGroup() {
return this.dashboardType === DASHBOARD_TYPES.GROUP;
},
......@@ -111,7 +98,7 @@ export default {
</h2>
<csv-export-button />
</header>
<vulnerabilities-count-list :scope="scope" :full-path="groupFullPath" :filters="filters" />
<vulnerabilities-count-list :full-path="groupFullPath" :filters="filters" />
</template>
<template #sticky>
<filters :projects="projects" @filterChange="handleFilterChange" />
......
......@@ -6,10 +6,4 @@ export const SURVEY_BANNER_LOCAL_STORAGE_KEY = 'vulnerability_management_survey_
// word 'survey' and the number, or else it will parse to a valid date.
export const SURVEY_BANNER_CURRENT_ID = 'survey1';
export const vulnerabilitiesSeverityCountScopes = {
instance: 'instance',
group: 'group',
project: 'project',
};
export const DEFAULT_SCANNER = 'GitLab';
......@@ -56,6 +56,7 @@ export default (el, dashboardType) => {
}
const provide = {
dashboardType,
dashboardDocumentation,
noVulnerabilitiesSvgPath,
emptyStateSvgPath,
......
......@@ -92,7 +92,6 @@ describe('First class Project Security Dashboard component', () => {
it('should pass down the properties correctly to the vulnerability count list', () => {
expect(findVulnerabilityCountList().props()).toEqual({
scope: 'project',
fullPath: provide.projectFullPath,
filters,
});
......
......@@ -3,6 +3,7 @@ import VueApollo from 'vue-apollo';
import VulnerabilityCountList from 'ee/security_dashboard/components/vulnerability_count_list.vue';
import VulnerabilityCountListLayout from 'ee/security_dashboard/components/vulnerability_count_list_layout.vue';
import countQuery from 'ee/security_dashboard/graphql/queries/vulnerability_severities_count.query.graphql';
import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants';
import eventHub from 'ee/security_dashboard/utils/event_hub';
import createMockApollo from 'helpers/mock_apollo_helper';
......@@ -15,11 +16,12 @@ describe('Vulnerabilities count list component', () => {
const findVulnerabilityLayout = () => wrapper.find(VulnerabilityCountListLayout);
const createWrapper = ({ query = { isLoading: false }, props = { scope: 'project' } } = {}) => {
const createWrapper = ({ query = { isLoading: false }, provide, data = {} } = {}) => {
refetchSpy = jest.fn();
return shallowMount(VulnerabilityCountList, {
propsData: props,
provide: { dashboardType: DASHBOARD_TYPES.PROJECT, ...provide },
data: () => data,
mocks: {
$apollo: { queries: { vulnerabilitiesCount: { ...query, refetch: refetchSpy } } },
},
......@@ -74,15 +76,15 @@ describe('Vulnerabilities count list component', () => {
});
describe.each`
givenScope | expectedContainedQueryVariables
${'instance'} | ${{ isInstance: true, isGroup: false, isProject: false }}
${'group'} | ${{ isInstance: false, isGroup: true, isProject: false }}
${'project'} | ${{ isInstance: false, isGroup: false, isProject: true }}
dashboardType | expectedContainedQueryVariables
${DASHBOARD_TYPES.INSTANCE} | ${{ isInstance: true, isGroup: false, isProject: false }}
${DASHBOARD_TYPES.GROUP} | ${{ isInstance: false, isGroup: true, isProject: false }}
${DASHBOARD_TYPES.PROJECT} | ${{ isInstance: false, isGroup: false, isProject: true }}
`(
'when the scope prop is set to "$givenScope"',
({ givenScope, expectedContainedQueryVariables }) => {
'when the dashboard type is $dashboardType',
({ dashboardType, expectedContainedQueryVariables }) => {
beforeEach(() => {
wrapper = createWrapper({ props: { scope: givenScope } });
wrapper = createWrapper({ provide: { dashboardType } });
return wrapper.vm.$nextTick();
});
......@@ -96,8 +98,7 @@ describe('Vulnerabilities count list component', () => {
describe('when there is an error', () => {
beforeEach(() => {
wrapper = createWrapper({ query: {} });
wrapper.setData({ queryError: true });
wrapper = createWrapper({ data: { queryError: true } });
});
it('should tell the layout to display an error', () => {
......@@ -112,7 +113,8 @@ describe('Vulnerabilities count list component', () => {
wrapper = shallowMount(VulnerabilityCountList, {
localVue,
apolloProvider: createMockApollo([[countQuery, query]]),
propsData: { scope: 'project', filters },
provide: { dashboardType: DASHBOARD_TYPES.PROJECT },
propsData: { filters },
});
};
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import CsvExportButton from 'ee/security_dashboard/components/csv_export_button.vue';
import DashboardNotConfiguredGroup from 'ee/security_dashboard/components/empty_states/group_dashboard_not_configured.vue';
......@@ -31,14 +32,7 @@ describe('Vulnerability Report', () => {
const findVulnerabilitiesCountList = () => wrapper.findComponent(VulnerabilitiesCountList);
const findHeader = () => wrapper.find('h2');
const createWrapper = ({
data = {},
mocks,
propsData,
provide = { groupFullPath: undefined },
apolloProvider,
stubs,
}) => {
const createWrapper = ({ data = {}, mocks, propsData, provide, apolloProvider }) => {
const localVue = createLocalVue();
if (apolloProvider) {
......@@ -48,16 +42,11 @@ describe('Vulnerability Report', () => {
return shallowMount(VulnerabilityReport, {
localVue,
apolloProvider,
data() {
return { ...data };
},
data: () => data,
mocks,
propsData,
provide,
stubs: {
...stubs,
SecurityDashboardLayout,
},
provide: { groupFullPath: undefined, ...provide },
stubs: { SecurityDashboardLayout },
});
};
......@@ -68,7 +57,7 @@ describe('Vulnerability Report', () => {
describe('when initialized - all levels', () => {
beforeEach(() => {
wrapper = createWrapper({
propsData: {
provide: {
dashboardType: DASHBOARD_TYPES.INSTANCE,
},
apolloProvider: createApolloProvider([
......@@ -88,12 +77,12 @@ describe('Vulnerability Report', () => {
expect(findFilters().exists()).toBe(true);
});
it('responds to the filterChange event', () => {
it('responds to the filterChange event', async () => {
const filters = { severity: 'critical' };
findFilters().vm.$listeners.filterChange(filters);
return wrapper.vm.$nextTick(() => {
expect(findInstanceVulnerabilities().props('filters')).toEqual(filters);
});
await nextTick();
expect(findInstanceVulnerabilities().props('filters')).toBe(filters);
});
it('displays the csv export button', () => {
......@@ -106,11 +95,14 @@ describe('Vulnerability Report', () => {
});
describe('when initialized - instance level', () => {
const filters = {};
beforeEach(() => {
wrapper = createWrapper({
propsData: {
provide: {
dashboardType: DASHBOARD_TYPES.INSTANCE,
},
data: { filters },
apolloProvider: createApolloProvider([
[
vulnerableProjectsInstanceQuery,
......@@ -124,22 +116,17 @@ describe('Vulnerability Report', () => {
expect(findInstanceVulnerabilities().exists()).toBe(true);
});
it('displays the vulnerability count list with the correct data', () => {
expect(findVulnerabilitiesCountList().props()).toMatchObject({
scope: 'instance',
filters: wrapper.vm.filters,
});
it('shows the vulnerability count list and passes the filters prop', () => {
expect(findVulnerabilitiesCountList().props('filters')).toBe(filters);
});
});
describe('when initialized - group level', () => {
beforeEach(() => {
wrapper = createWrapper({
propsData: {
dashboardType: DASHBOARD_TYPES.GROUP,
},
provide: {
groupFullPath: 'gitlab-org',
dashboardType: DASHBOARD_TYPES.GROUP,
},
apolloProvider: createApolloProvider([
[
......@@ -156,7 +143,6 @@ describe('Vulnerability Report', () => {
it('displays the vulnerability count list with the correct data', () => {
expect(findVulnerabilitiesCountList().props()).toEqual({
scope: 'group',
fullPath: 'gitlab-org',
filters: wrapper.vm.filters,
});
......@@ -166,8 +152,10 @@ describe('Vulnerability Report', () => {
describe('when uninitialized', () => {
beforeEach(() => {
wrapper = createWrapper({
propsData: { dashboardType: DASHBOARD_TYPES.GROUP },
provide: { groupFullPath: 'gitlab-org' },
provide: {
groupFullPath: 'gitlab-org',
dashboardType: DASHBOARD_TYPES.GROUP,
},
apolloProvider: createApolloProvider([
[
vulnerableProjectsGroupQuery,
......@@ -194,7 +182,7 @@ describe('Vulnerability Report', () => {
describe('when loading projects', () => {
beforeEach(() => {
wrapper = createWrapper({
propsData: { dashboardType: DASHBOARD_TYPES.INSTANCE },
provide: { dashboardType: DASHBOARD_TYPES.INSTANCE },
mocks: { $apollo: { queries: { projects: { loading: true } } } },
});
});
......
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