Commit 6f3b675c authored by Peter Hegman's avatar Peter Hegman

Merge branch '347159-fix-tab-querystring-getting-zapped' into 'master'

Fix vulnerability report tab querystring removed when filters changed

See merge request gitlab-org/gitlab!76208
parents 805dc68d aaf6dc48
...@@ -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