Commit a7e9994f authored by Daniel Tian's avatar Daniel Tian Committed by Brandon Labuschagne

Use provide/inject for vulnerabilities export endpoint

Use provide/inject instead of props to pass the vulnerabilites export
endpoint URL to the CSV export button on the vulnerability report page
parent 4b6c31c7
<script>
import { GlPopover, GlIcon, GlLink, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import AccessorUtils from '~/lib/utils/accessor';
import axios from '~/lib/utils/axios_utils';
import { formatDate } from '~/lib/utils/datetime_utility';
import download from '~/lib/utils/downloader';
......@@ -19,12 +20,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
vulnerabilitiesExportEndpoint: {
type: String,
required: true,
},
},
inject: ['vulnerabilitiesExportEndpoint'],
data() {
return {
isPreparingCsvExport: false,
......@@ -45,10 +41,8 @@ export default {
closePopover() {
this.showPopover = false;
try {
if (AccessorUtils.isLocalStorageAccessSafe()) {
localStorage.setItem(STORAGE_KEY, 'true');
} catch (e) {
// Ignore the error - this is just a safety measure.
}
},
initiateCsvExport() {
......@@ -87,9 +81,10 @@ export default {
>
{{ __('Export') }}
<gl-popover
v-if="showPopover"
ref="popover"
:target="() => $refs.csvExportButton.$el"
:show="showPopover"
show
placement="left"
triggers="manual"
>
......
......@@ -20,12 +20,6 @@ export default {
VulnerabilitiesCountList,
},
inject: ['groupFullPath'],
props: {
vulnerabilitiesExportEndpoint: {
type: String,
required: true,
},
},
apollo: {
projects: {
query: vulnerableProjectsQuery,
......@@ -74,7 +68,7 @@ export default {
<h2 class="gl-flex-grow-1 gl-my-0">
{{ s__('SecurityReports|Vulnerability Report') }}
</h2>
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
<csv-export-button />
</header>
<vulnerabilities-count-list
:scope="$options.vulnerabilitiesSeverityCountScopes.group"
......
......@@ -19,12 +19,6 @@ export default {
DashboardNotConfigured,
VulnerabilitiesCountList,
},
props: {
vulnerabilitiesExportEndpoint: {
type: String,
required: true,
},
},
apollo: {
projects: {
query: projectsQuery,
......@@ -75,7 +69,7 @@ export default {
<h2 class="gl-flex-grow-1 gl-my-0">
{{ s__('SecurityReports|Vulnerability Report') }}
</h2>
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
<csv-export-button />
</header>
<vulnerabilities-count-list
:scope="$options.vulnerabilitiesSeverityCountScopes.instance"
......
......@@ -34,11 +34,6 @@ export default {
required: false,
default: () => ({}),
},
vulnerabilitiesExportEndpoint: {
type: String,
required: false,
default: '',
},
},
data() {
const shouldShowAutoFixUserCallout =
......@@ -73,7 +68,7 @@ export default {
<template #header>
<div class="gl-mt-6 gl-display-flex">
<h4 class="gl-flex-grow-1 gl-my-0">{{ __('Vulnerability Report') }}</h4>
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
<csv-export-button />
</div>
<project-pipeline-status :pipeline="pipeline" />
<vulnerabilities-count-list
......
......@@ -65,6 +65,7 @@ export default (el, dashboardType) => {
groupFullPath,
securityConfigurationPath,
surveyRequestSvgPath,
vulnerabilitiesExportEndpoint,
hasVulnerabilities: parseBoolean(hasVulnerabilities),
scanners: scanners ? JSON.parse(scanners) : [],
hasJiraVulnerabilitiesIntegrationEnabled: parseBoolean(
......@@ -76,7 +77,6 @@ export default (el, dashboardType) => {
securityDashboardHelpPath,
projectAddEndpoint,
projectListEndpoint,
vulnerabilitiesExportEndpoint,
};
let component;
......
---
title: Use provide/inject for vulnerabilities export endpoint
merge_request: 57639
author:
type: other
......@@ -4,8 +4,10 @@ import MockAdapter from 'axios-mock-adapter';
import CsvExportButton, {
STORAGE_KEY,
} from 'ee/security_dashboard/components/csv_export_button.vue';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import AccessorUtils from '~/lib/utils/accessor';
import axios from '~/lib/utils/axios_utils';
import { formatDate } from '~/lib/utils/datetime_utility';
import downloader from '~/lib/utils/downloader';
......@@ -14,6 +16,8 @@ import statusCodes from '~/lib/utils/http_status';
jest.mock('~/flash');
jest.mock('~/lib/utils/downloader');
useLocalStorageSpy();
const mockReportDate = formatDate(new Date(), 'isoDateTime');
const vulnerabilitiesExportEndpoint = `${TEST_HOST}/vulnerability_findings.csv`;
......@@ -29,7 +33,7 @@ describe('Csv Button Export', () => {
const createComponent = () => {
return shallowMount(CsvExportButton, {
propsData: {
provide: {
vulnerabilitiesExportEndpoint,
},
stubs: {
......@@ -49,7 +53,7 @@ describe('Csv Button Export', () => {
afterEach(() => {
wrapper.destroy();
localStorage.removeItem(STORAGE_KEY);
localStorage.clear();
});
describe('when the user sees the button for the first time', () => {
......@@ -117,16 +121,33 @@ describe('Csv Button Export', () => {
});
it('displays the popover by default', () => {
expect(findPopover().attributes('show')).toBeTruthy();
expect(findPopover().exists()).toBe(true);
});
it('closes the popover when the button is clicked', async () => {
const button = findPopoverButton();
expect(button.text().trim()).toBe('Got it!');
button.vm.$emit('click');
await wrapper.vm.$nextTick();
describe('closing the popover', () => {
it('closes the popover when the button is clicked', async () => {
expect(findPopoverButton().text()).toBe('Got it!');
findPopoverButton().vm.$emit('click');
await wrapper.vm.$nextTick();
expect(findPopover().exists()).toBe(false);
});
it('sets localStorage', async () => {
jest.spyOn(AccessorUtils, 'isLocalStorageAccessSafe').mockImplementation(() => true);
findPopoverButton().vm.$emit('click');
await wrapper.vm.$nextTick();
expect(findPopover().attributes('show')).toBeUndefined();
expect(localStorage.setItem).toHaveBeenCalledTimes(1);
});
it(`does not set localStorage if it's not available`, async () => {
jest.spyOn(AccessorUtils, 'isLocalStorageAccessSafe').mockImplementation(() => false);
findPopoverButton().vm.$emit('click');
await wrapper.vm.$nextTick();
expect(localStorage.setItem).toHaveBeenCalledTimes(0);
});
});
});
......@@ -137,7 +158,7 @@ describe('Csv Button Export', () => {
});
it('does not display the popover anymore', () => {
expect(findPopover().attributes('show')).toBeFalsy();
expect(findPopover().exists()).toBe(false);
});
});
});
......@@ -14,7 +14,6 @@ describe('First Class Group Dashboard Component', () => {
const dashboardDocumentation = 'dashboard-documentation';
const emptyStateSvgPath = 'empty-state-path';
const groupFullPath = 'group-full-path';
const vulnerabilitiesExportEndpoint = '/vulnerabilities/exports';
const findDashboardLayout = () => wrapper.find(SecurityDashboardLayout);
const findGroupVulnerabilities = () => wrapper.find(FirstClassGroupVulnerabilities);
......@@ -29,7 +28,6 @@ describe('First Class Group Dashboard Component', () => {
propsData: {
dashboardDocumentation,
emptyStateSvgPath,
vulnerabilitiesExportEndpoint,
},
provide: { groupFullPath },
data,
......@@ -89,9 +87,7 @@ describe('First Class Group Dashboard Component', () => {
});
it('displays the csv export button', () => {
expect(findCsvExportButton().props('vulnerabilitiesExportEndpoint')).toBe(
vulnerabilitiesExportEndpoint,
);
expect(findCsvExportButton().exists()).toBe(true);
});
it('loading button should not be rendered', () => {
......
......@@ -14,8 +14,6 @@ describe('First Class Instance Dashboard Component', () => {
$apollo: { queries: { projects: { loading } } },
});
const vulnerabilitiesExportEndpoint = '/vulnerabilities/exports';
const findInstanceVulnerabilities = () => wrapper.find(FirstClassInstanceVulnerabilities);
const findCsvExportButton = () => wrapper.find(CsvExportButton);
const findEmptyState = () => wrapper.find(DashboardNotConfigured);
......@@ -29,9 +27,6 @@ describe('First Class Instance Dashboard Component', () => {
return { ...data };
},
mocks,
propsData: {
vulnerabilitiesExportEndpoint,
},
stubs: {
...stubs,
SecurityDashboardLayout,
......@@ -77,9 +72,7 @@ describe('First Class Instance Dashboard Component', () => {
});
it('displays the csv export button', () => {
expect(findCsvExportButton().props('vulnerabilitiesExportEndpoint')).toBe(
vulnerabilitiesExportEndpoint,
);
expect(findCsvExportButton().exists()).toBe(true);
});
it('displays the vulnerability count list with the correct data', () => {
......
......@@ -21,7 +21,6 @@ const props = {
path: '/mixed-vulnerabilities/dependency-list-test-01/-/pipelines/214',
},
securityDashboardHelpPath: '/security/dashboard/help-path',
vulnerabilitiesExportEndpoint: '/vulnerabilities/exports',
};
const provide = {
......
......@@ -52,7 +52,6 @@ describe('ErrorTrackingList', () => {
beforeEach(() => {
actions = {
getErrorList: () => {},
startPolling: jest.fn(),
restartPolling: jest.fn().mockName('restartPolling'),
addRecentSearch: jest.fn(),
......
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