Commit aaf6dc48 authored by Daniel Tian's avatar Daniel Tian

Fix vulnerability report tab querystring removed when filters changed

Fixes an issue where when the vulnerability report tab is changed to
the operational tab, the tab querystring is added. But when a
vulnerability filter is changed, the tab querystring was incorrectly
removed.

Changelog: fixed
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76208
EE: true
parent 47a789eb
......@@ -6,6 +6,8 @@ import VulnerabilityReportHeader from './vulnerability_report_header.vue';
import VulnerabilityReport from './vulnerability_report.vue';
import { REPORT_TAB } from './constants';
const OPERATIONAL_TAB_INDEX = 1;
export default {
components: {
GlTabs,
......@@ -26,8 +28,24 @@ export default {
default: false,
},
},
data() {
return {
tabIndex: this.$route.query.tab === REPORT_TAB.OPERATIONAL ? OPERATIONAL_TAB_INDEX : 0,
};
},
watch: {
tabIndex(index) {
// Set tab querystring value to 'OPERATIONAL' if it's the operational tab, otherwise remove it
// for the development tab.
const query = {
...this.$route.query,
tab: index === OPERATIONAL_TAB_INDEX ? REPORT_TAB.OPERATIONAL : undefined,
};
this.$router.push({ query });
},
},
i18n: {
operationalTabParameter: REPORT_TAB.OPERATIONAL.toLowerCase(),
developmentTab: s__('SecurityReports|Development vulnerabilities'),
operationalTab: s__('SecurityReports|Operational vulnerabilities'),
operationalTabMessage: s__(
......@@ -44,7 +62,7 @@ export default {
<vulnerability-report-header />
<gl-tabs class="gl-mt-5" content-class="gl-pt-0" sync-active-tab-with-query-params>
<gl-tabs v-model="tabIndex" class="gl-mt-5" content-class="gl-pt-0">
<gl-tab :title="$options.i18n.developmentTab" lazy>
<slot name="header-development"></slot>
......@@ -55,11 +73,7 @@ export default {
/>
</gl-tab>
<gl-tab
:title="$options.i18n.operationalTab"
:query-param-value="$options.i18n.operationalTabParameter"
lazy
>
<gl-tab :title="$options.i18n.operationalTab" lazy>
<gl-card body-class="gl-p-6">{{ $options.i18n.operationalTabMessage }}</gl-card>
<slot name="header-operational"></slot>
......
......@@ -2,6 +2,7 @@ import { nextTick } from 'vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import Cookies from 'js-cookie';
import VueRouter from 'vue-router';
import ProjectVulnerabilityReport from 'ee/security_dashboard/components/project/project_vulnerability_report.vue';
import ReportNotConfiguredProject from 'ee/security_dashboard/components/shared/empty_states/report_not_configured_project.vue';
import VulnerabilityReportTabs from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_report_tabs.vue';
......@@ -15,6 +16,8 @@ import createMockApollo from 'helpers/mock_apollo_helper';
const localVue = createLocalVue();
localVue.use(VueApollo);
localVue.use(VueRouter);
const router = new VueRouter();
describe('Project vulnerability report app component', () => {
useLocalStorageSpy();
......@@ -38,6 +41,7 @@ describe('Project vulnerability report app component', () => {
} = {}) => {
wrapper = shallowMount(ProjectVulnerabilityReport, {
localVue,
router,
apolloProvider: createMockApollo([
[securityScannersQuery, securityScannersHandler(securityScanners)],
]),
......
import { shallowMount } from '@vue/test-utils';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import { GlTabs, GlTab } from '@gitlab/ui';
import VueRouter from 'vue-router';
import VulnerabilityReportTabs from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_report_tabs.vue';
import VulnerabilityReport from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_report.vue';
import SurveyRequestBanner from 'ee/security_dashboard/components/shared/survey_request_banner.vue';
import projectVulnerabilitiesQuery from 'ee/security_dashboard/graphql/queries/project_vulnerabilities.query.graphql';
import { REPORT_TAB } from 'ee/security_dashboard/components/shared/vulnerability_report/constants';
const localVue = createLocalVue();
localVue.use(VueRouter);
const router = new VueRouter();
describe('Vulnerability report tabs component', () => {
let wrapper;
const createWrapper = ({ showProjectFilter = false } = {}) => {
wrapper = shallowMount(VulnerabilityReportTabs, {
localVue,
router,
propsData: {
query: projectVulnerabilitiesQuery,
showProjectFilter,
......@@ -17,6 +26,7 @@ describe('Vulnerability report tabs component', () => {
});
};
const findTabs = () => wrapper.findComponent(GlTabs);
const findVulnerabilityReports = () => wrapper.findAllComponents(VulnerabilityReport);
afterEach(() => {
......@@ -35,13 +45,43 @@ describe('Vulnerability report tabs component', () => {
it('renders 2 tabs', () => {
createWrapper();
expect(wrapper.findComponent(GlTabs).exists()).toBe(true);
expect(findTabs().exists()).toBe(true);
const tabs = wrapper.findAllComponents(GlTab);
expect(tabs).toHaveLength(2);
expect(tabs.at(0).attributes('title')).toBe('Development vulnerabilities');
expect(tabs.at(1).attributes('title')).toBe('Operational vulnerabilities');
});
it.each`
queryParam | tabIndex
${undefined} | ${0}
${REPORT_TAB.OPERATIONAL} | ${1}
`(
'shows tab with tabIndex $tabIndex when querystring is "$queryParam"',
({ queryParam, tabIndex }) => {
router.replace({ query: { tab: queryParam } });
createWrapper();
expect(findTabs().props('value')).toBe(tabIndex);
},
);
it.each`
tabIndex | queryParam
${0} | ${undefined}
${1} | ${REPORT_TAB.OPERATIONAL}
`(
'changes the tab when tabIndex $tabIndex is clicked and sets querystring to "$queryParam"',
async ({ tabIndex, queryParam }) => {
createWrapper();
findTabs().vm.$emit('input', tabIndex);
await nextTick();
expect(findTabs().props('value')).toBe(tabIndex);
expect(router.currentRoute.query.tab).toBe(queryParam);
},
);
});
describe('vulnerability report components', () => {
......
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