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'; ...@@ -6,6 +6,8 @@ import VulnerabilityReportHeader from './vulnerability_report_header.vue';
import VulnerabilityReport from './vulnerability_report.vue'; import VulnerabilityReport from './vulnerability_report.vue';
import { REPORT_TAB } from './constants'; import { REPORT_TAB } from './constants';
const OPERATIONAL_TAB_INDEX = 1;
export default { export default {
components: { components: {
GlTabs, GlTabs,
...@@ -26,8 +28,24 @@ export default { ...@@ -26,8 +28,24 @@ export default {
default: false, 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: { i18n: {
operationalTabParameter: REPORT_TAB.OPERATIONAL.toLowerCase(),
developmentTab: s__('SecurityReports|Development vulnerabilities'), developmentTab: s__('SecurityReports|Development vulnerabilities'),
operationalTab: s__('SecurityReports|Operational vulnerabilities'), operationalTab: s__('SecurityReports|Operational vulnerabilities'),
operationalTabMessage: s__( operationalTabMessage: s__(
...@@ -44,7 +62,7 @@ export default { ...@@ -44,7 +62,7 @@ export default {
<vulnerability-report-header /> <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> <gl-tab :title="$options.i18n.developmentTab" lazy>
<slot name="header-development"></slot> <slot name="header-development"></slot>
...@@ -55,11 +73,7 @@ export default { ...@@ -55,11 +73,7 @@ export default {
/> />
</gl-tab> </gl-tab>
<gl-tab <gl-tab :title="$options.i18n.operationalTab" lazy>
:title="$options.i18n.operationalTab"
:query-param-value="$options.i18n.operationalTabParameter"
lazy
>
<gl-card body-class="gl-p-6">{{ $options.i18n.operationalTabMessage }}</gl-card> <gl-card body-class="gl-p-6">{{ $options.i18n.operationalTabMessage }}</gl-card>
<slot name="header-operational"></slot> <slot name="header-operational"></slot>
......
...@@ -2,6 +2,7 @@ import { nextTick } from 'vue'; ...@@ -2,6 +2,7 @@ import { nextTick } from 'vue';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import VueRouter from 'vue-router';
import ProjectVulnerabilityReport from 'ee/security_dashboard/components/project/project_vulnerability_report.vue'; 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 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'; 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'; ...@@ -15,6 +16,8 @@ import createMockApollo from 'helpers/mock_apollo_helper';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueApollo); localVue.use(VueApollo);
localVue.use(VueRouter);
const router = new VueRouter();
describe('Project vulnerability report app component', () => { describe('Project vulnerability report app component', () => {
useLocalStorageSpy(); useLocalStorageSpy();
...@@ -38,6 +41,7 @@ describe('Project vulnerability report app component', () => { ...@@ -38,6 +41,7 @@ describe('Project vulnerability report app component', () => {
} = {}) => { } = {}) => {
wrapper = shallowMount(ProjectVulnerabilityReport, { wrapper = shallowMount(ProjectVulnerabilityReport, {
localVue, localVue,
router,
apolloProvider: createMockApollo([ apolloProvider: createMockApollo([
[securityScannersQuery, securityScannersHandler(securityScanners)], [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 { 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 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 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 SurveyRequestBanner from 'ee/security_dashboard/components/shared/survey_request_banner.vue';
import projectVulnerabilitiesQuery from 'ee/security_dashboard/graphql/queries/project_vulnerabilities.query.graphql'; 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', () => { describe('Vulnerability report tabs component', () => {
let wrapper; let wrapper;
const createWrapper = ({ showProjectFilter = false } = {}) => { const createWrapper = ({ showProjectFilter = false } = {}) => {
wrapper = shallowMount(VulnerabilityReportTabs, { wrapper = shallowMount(VulnerabilityReportTabs, {
localVue,
router,
propsData: { propsData: {
query: projectVulnerabilitiesQuery, query: projectVulnerabilitiesQuery,
showProjectFilter, showProjectFilter,
...@@ -17,6 +26,7 @@ describe('Vulnerability report tabs component', () => { ...@@ -17,6 +26,7 @@ describe('Vulnerability report tabs component', () => {
}); });
}; };
const findTabs = () => wrapper.findComponent(GlTabs);
const findVulnerabilityReports = () => wrapper.findAllComponents(VulnerabilityReport); const findVulnerabilityReports = () => wrapper.findAllComponents(VulnerabilityReport);
afterEach(() => { afterEach(() => {
...@@ -35,13 +45,43 @@ describe('Vulnerability report tabs component', () => { ...@@ -35,13 +45,43 @@ describe('Vulnerability report tabs component', () => {
it('renders 2 tabs', () => { it('renders 2 tabs', () => {
createWrapper(); createWrapper();
expect(wrapper.findComponent(GlTabs).exists()).toBe(true); expect(findTabs().exists()).toBe(true);
const tabs = wrapper.findAllComponents(GlTab); const tabs = wrapper.findAllComponents(GlTab);
expect(tabs).toHaveLength(2); expect(tabs).toHaveLength(2);
expect(tabs.at(0).attributes('title')).toBe('Development vulnerabilities'); expect(tabs.at(0).attributes('title')).toBe('Development vulnerabilities');
expect(tabs.at(1).attributes('title')).toBe('Operational 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', () => { 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