Commit b2c4afb9 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch '210327-show-vulnerability-report-type' into 'master'

Add scanner column to the project-level security dashboard and pipeline security tab

See merge request gitlab-org/gitlab!35150
parents 3dbea317 3fe2890d
...@@ -80,6 +80,9 @@ export default { ...@@ -80,6 +80,9 @@ export default {
<div class="table-section section-15" role="rowheader"> <div class="table-section section-15" role="rowheader">
{{ s__('Reports|Identifier') }} {{ s__('Reports|Identifier') }}
</div> </div>
<div class="table-section section-15" role="rowheader">
{{ s__('Reports|Scanner') }}
</div>
<div class="table-section section-20" role="rowheader"></div> <div class="table-section section-20" role="rowheader"></div>
</div> </div>
......
...@@ -6,6 +6,7 @@ import Icon from '~/vue_shared/components/icon.vue'; ...@@ -6,6 +6,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import VulnerabilityActionButtons from './vulnerability_action_buttons.vue'; import VulnerabilityActionButtons from './vulnerability_action_buttons.vue';
import VulnerabilityIssueLink from './vulnerability_issue_link.vue'; import VulnerabilityIssueLink from './vulnerability_issue_link.vue';
import { DASHBOARD_TYPES } from '../store/constants'; import { DASHBOARD_TYPES } from '../store/constants';
import convertReportType from 'ee/vue_shared/security_reports/store/utils/convert_report_type';
import getPrimaryIdentifier from 'ee/vue_shared/security_reports/store/utils/get_primary_identifier'; import getPrimaryIdentifier from 'ee/vue_shared/security_reports/store/utils/get_primary_identifier';
export default { export default {
...@@ -66,6 +67,9 @@ export default { ...@@ -66,6 +67,9 @@ export default {
isSelected() { isSelected() {
return Boolean(this.selectedVulnerabilities[this.vulnerability.id]); return Boolean(this.selectedVulnerabilities[this.vulnerability.id]);
}, },
useConvertReportType() {
return convertReportType(this.vulnerability.report_type);
},
}, },
methods: { methods: {
...mapActions('vulnerabilities', ['openModal', 'selectVulnerability', 'deselectVulnerability']), ...mapActions('vulnerabilities', ['openModal', 'selectVulnerability', 'deselectVulnerability']),
...@@ -146,6 +150,13 @@ export default { ...@@ -146,6 +150,13 @@ export default {
</div> </div>
</div> </div>
<div class="table-section section-15">
<div class="table-mobile-header" role="rowheader">{{ s__('Reports|Scanner') }}</div>
<div class="table-mobile-content text-capitalize">
{{ useConvertReportType }}
</div>
</div>
<div class="table-section section-20"> <div class="table-section section-20">
<div class="table-mobile-header" role="rowheader">{{ s__('Reports|Actions') }}</div> <div class="table-mobile-header" role="rowheader">{{ s__('Reports|Actions') }}</div>
<div class="table-mobile-content action-buttons d-flex justify-content-end"> <div class="table-mobile-content action-buttons d-flex justify-content-end">
......
...@@ -29,7 +29,7 @@ export const initFirstClassVulnerabilityFilters = projects => { ...@@ -29,7 +29,7 @@ export const initFirstClassVulnerabilityFilters = projects => {
selection: new Set([ALL]), selection: new Set([ALL]),
}, },
{ {
name: s__('SecurityReports|Report type'), name: s__('Reports|Scanner'),
id: 'reportType', id: 'reportType',
options: [BASE_FILTERS.report_type, ...parseOptions(REPORT_TYPES)], options: [BASE_FILTERS.report_type, ...parseOptions(REPORT_TYPES)],
selection: new Set([ALL]), selection: new Set([ALL]),
......
...@@ -8,7 +8,7 @@ export const BASE_FILTERS = { ...@@ -8,7 +8,7 @@ export const BASE_FILTERS = {
id: ALL, id: ALL,
}, },
report_type: { report_type: {
name: s__('ciReport|All report types'), name: s__('ciReport|All scanner types'),
id: ALL, id: ALL,
}, },
project_id: { project_id: {
......
...@@ -14,7 +14,7 @@ export default () => ({ ...@@ -14,7 +14,7 @@ export default () => ({
selection: new Set([BASE_FILTERS.severity.id]), selection: new Set([BASE_FILTERS.severity.id]),
}, },
{ {
name: s__('SecurityReports|Report type'), name: s__('SecurityReports|Scanner type'),
id: 'report_type', id: 'report_type',
options: [BASE_FILTERS.report_type, ...optionsObjectToArray(REPORT_TYPES)], options: [BASE_FILTERS.report_type, ...optionsObjectToArray(REPORT_TYPES)],
hidden: false, hidden: false,
......
import { REPORT_TYPES } from 'ee/security_dashboard/store/constants';
import { humanize } from '~/lib/utils/text_utility';
/**
* Takes the report type, that is not human-readable and converts it to be human-readable
* @param {string} reportType that is not human-readable
* @returns {string} a human-readable version of the report type
*/
const convertReportType = reportType => {
if (!reportType) return '';
const lowerCaseType = reportType.toLowerCase();
return REPORT_TYPES[lowerCaseType] || humanize(lowerCaseType);
};
export default convertReportType;
...@@ -109,6 +109,7 @@ export default { ...@@ -109,6 +109,7 @@ export default {
:empty-state-svg-path="emptyStateSvgPath" :empty-state-svg-path="emptyStateSvgPath"
:filters="filters" :filters="filters"
:vulnerabilities="vulnerabilities" :vulnerabilities="vulnerabilities"
should-show-report-type
@refetch-vulnerabilities="refetchVulnerabilities" @refetch-vulnerabilities="refetchVulnerabilities"
> >
<template #emptyState> <template #emptyState>
......
...@@ -6,6 +6,7 @@ import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_ba ...@@ -6,6 +6,7 @@ import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_ba
import SelectionSummary from 'ee/security_dashboard/components/selection_summary.vue'; import SelectionSummary from 'ee/security_dashboard/components/selection_summary.vue';
import IssueLink from './issue_link.vue'; import IssueLink from './issue_link.vue';
import { VULNERABILITIES_PER_PAGE } from '../constants'; import { VULNERABILITIES_PER_PAGE } from '../constants';
import convertReportType from 'ee/vue_shared/security_reports/store/utils/convert_report_type';
export default { export default {
name: 'VulnerabilityList', name: 'VulnerabilityList',
...@@ -34,6 +35,11 @@ export default { ...@@ -34,6 +35,11 @@ export default {
required: false, required: false,
default: null, default: null,
}, },
shouldShowReportType: {
type: Boolean,
required: false,
default: false,
},
shouldShowSelection: { shouldShowSelection: {
type: Boolean, type: Boolean,
required: false, required: false,
...@@ -69,20 +75,12 @@ export default { ...@@ -69,20 +75,12 @@ export default {
shouldShowSelectionSummary() { shouldShowSelectionSummary() {
return this.shouldShowSelection && Boolean(this.numOfSelectedVulnerabilities); return this.shouldShowSelection && Boolean(this.numOfSelectedVulnerabilities);
}, },
checkboxClass() {
return this.shouldShowSelection ? '' : 'gl-display-none';
},
theadClass() { theadClass() {
return this.shouldShowSelectionSummary ? 'below-selection-summary' : ''; return this.shouldShowSelectionSummary ? 'below-selection-summary' : '';
}, },
fields() { fields() {
const commonThClass = ['table-th-transparent', 'original-gl-th', 'gl-bg-white!'].join(' '); const commonThClass = ['table-th-transparent', 'original-gl-th', 'gl-bg-white!'].join(' ');
return [ const baseFields = [
{
key: 'checkbox',
class: this.checkboxClass,
thClass: `gl-w-9 ${commonThClass}`,
},
{ {
key: 'state', key: 'state',
label: s__('Vulnerability|Status'), label: s__('Vulnerability|Status'),
...@@ -100,6 +98,22 @@ export default { ...@@ -100,6 +98,22 @@ export default {
tdClass: 'gl-word-break-all', tdClass: 'gl-word-break-all',
}, },
]; ];
if (this.shouldShowSelection) {
baseFields.unshift({
key: 'checkbox',
thClass: `gl-w-9 ${commonThClass}`,
});
}
if (this.shouldShowReportType) {
baseFields.push({
key: 'reportType',
label: s__('Reports|Scanner'),
thClass: commonThClass,
});
}
return baseFields;
}, },
}, },
watch: { watch: {
...@@ -151,6 +165,9 @@ export default { ...@@ -151,6 +165,9 @@ export default {
issue(item) { issue(item) {
return item.issueLinks?.nodes[0]?.issue; return item.issueLinks?.nodes[0]?.issue;
}, },
useConvertReportType(reportType) {
return convertReportType(reportType);
},
}, },
VULNERABILITIES_PER_PAGE, VULNERABILITIES_PER_PAGE,
}; };
...@@ -176,6 +193,7 @@ export default { ...@@ -176,6 +193,7 @@ export default {
<template #head(checkbox)> <template #head(checkbox)>
<gl-form-checkbox <gl-form-checkbox
class="mr-0 mb-0" class="mr-0 mb-0"
data-testid="vulnerability-checkbox-all"
:checked="hasSelectedAllVulnerabilities" :checked="hasSelectedAllVulnerabilities"
@change="toggleAllVulnerabilities" @change="toggleAllVulnerabilities"
/> />
...@@ -184,6 +202,7 @@ export default { ...@@ -184,6 +202,7 @@ export default {
<template #cell(checkbox)="{ item }"> <template #cell(checkbox)="{ item }">
<gl-form-checkbox <gl-form-checkbox
class="d-inline-block mr-0 mb-0" class="d-inline-block mr-0 mb-0"
data-testid="vulnerability-checkbox"
:checked="isSelected(item)" :checked="isSelected(item)"
@change="toggleVulnerability(item)" @change="toggleVulnerability(item)"
/> />
...@@ -224,6 +243,12 @@ export default { ...@@ -224,6 +243,12 @@ export default {
<remediated-badge v-if="item.resolved_on_default_branch" class="ml-2" /> <remediated-badge v-if="item.resolved_on_default_branch" class="ml-2" />
</template> </template>
<template #cell(reportType)="{ item }">
<span data-testid="vulnerability-report-type" class="text-capitalize">{{
useConvertReportType(item.reportType)
}}</span>
</template>
<template #table-busy> <template #table-busy>
<gl-skeleton-loading <gl-skeleton-loading
v-for="n in $options.VULNERABILITIES_PER_PAGE" v-for="n in $options.VULNERABILITIES_PER_PAGE"
......
...@@ -31,4 +31,5 @@ fragment Vulnerability on Vulnerability { ...@@ -31,4 +31,5 @@ fragment Vulnerability on Vulnerability {
project { project {
nameWithNamespace nameWithNamespace
} }
reportType
} }
---
title: Add scanner type to vulnerability row
merge_request: 35150
author:
type: changed
...@@ -52,6 +52,7 @@ describe('First Class Group Dashboard Vulnerabilities Component', () => { ...@@ -52,6 +52,7 @@ describe('First Class Group Dashboard Vulnerabilities Component', () => {
emptyStateSvgPath, emptyStateSvgPath,
filters: null, filters: null,
isLoading: true, isLoading: true,
shouldShowReportType: false,
shouldShowSelection: true, shouldShowSelection: true,
shouldShowProjectNamespace: true, shouldShowProjectNamespace: true,
vulnerabilities: [], vulnerabilities: [],
...@@ -143,6 +144,7 @@ describe('First Class Group Dashboard Vulnerabilities Component', () => { ...@@ -143,6 +144,7 @@ describe('First Class Group Dashboard Vulnerabilities Component', () => {
emptyStateSvgPath, emptyStateSvgPath,
filters: null, filters: null,
isLoading: false, isLoading: false,
shouldShowReportType: false,
shouldShowSelection: true, shouldShowSelection: true,
shouldShowProjectNamespace: true, shouldShowProjectNamespace: true,
vulnerabilities, vulnerabilities,
......
...@@ -77,6 +77,7 @@ describe('First Class Instance Dashboard Vulnerabilities Component', () => { ...@@ -77,6 +77,7 @@ describe('First Class Instance Dashboard Vulnerabilities Component', () => {
emptyStateSvgPath, emptyStateSvgPath,
filters: null, filters: null,
isLoading: true, isLoading: true,
shouldShowReportType: false,
shouldShowSelection: true, shouldShowSelection: true,
shouldShowProjectNamespace: true, shouldShowProjectNamespace: true,
vulnerabilities: [], vulnerabilities: [],
...@@ -159,6 +160,7 @@ describe('First Class Instance Dashboard Vulnerabilities Component', () => { ...@@ -159,6 +160,7 @@ describe('First Class Instance Dashboard Vulnerabilities Component', () => {
emptyStateSvgPath, emptyStateSvgPath,
filters: null, filters: null,
isLoading: false, isLoading: false,
shouldShowReportType: false,
shouldShowSelection: true, shouldShowSelection: true,
shouldShowProjectNamespace: true, shouldShowProjectNamespace: true,
vulnerabilities, vulnerabilities,
......
...@@ -81,6 +81,14 @@ describe('Security Dashboard Table Row', () => { ...@@ -81,6 +81,14 @@ describe('Security Dashboard Table Row', () => {
expect(findContent(2).text()).toContain(vulnerability.identifiers[0].name); expect(findContent(2).text()).toContain(vulnerability.identifiers[0].name);
}); });
it('should render the report type', () => {
expect(
findContent(3)
.text()
.toLowerCase(),
).toContain(vulnerability.report_type.toLowerCase());
});
describe('the project name', () => { describe('the project name', () => {
it('should render the name', () => { it('should render the name', () => {
expect(findContent(1).text()).toContain(vulnerability.name); expect(findContent(1).text()).toContain(vulnerability.name);
......
...@@ -5,6 +5,7 @@ import { ...@@ -5,6 +5,7 @@ import {
countVulnerabilities, countVulnerabilities,
groupedReportText, groupedReportText,
} from 'ee/vue_shared/security_reports/store/utils'; } from 'ee/vue_shared/security_reports/store/utils';
import convertReportType from 'ee/vue_shared/security_reports/store/utils/convert_report_type';
import filterByKey from 'ee/vue_shared/security_reports/store/utils/filter_by_key'; import filterByKey from 'ee/vue_shared/security_reports/store/utils/filter_by_key';
import getFileLocation from 'ee/vue_shared/security_reports/store/utils/get_file_location'; import getFileLocation from 'ee/vue_shared/security_reports/store/utils/get_file_location';
import { import {
...@@ -44,6 +45,24 @@ describe('security reports utils', () => { ...@@ -44,6 +45,24 @@ describe('security reports utils', () => {
}); });
}); });
describe('convertReportType', () => {
it.each`
reportType | output
${'sast'} | ${'SAST'}
${'dependency_scanning'} | ${'Dependency Scanning'}
${'CONTAINER_SCANNING'} | ${'Container Scanning'}
${'CUSTOM_SCANNER'} | ${'Custom scanner'}
${'mast'} | ${'Mast'}
${'TAST'} | ${'Tast'}
${undefined} | ${''}
`(
'converts the report type "$reportType" to the human-readable string "$output"',
({ reportType, output }) => {
expect(convertReportType(reportType)).toEqual(output);
},
);
});
describe('filterByKey', () => { describe('filterByKey', () => {
it('filters the array with the provided key', () => { it('filters the array with the provided key', () => {
const array1 = [{ id: '1234' }, { id: 'abg543' }, { id: '214swfA' }]; const array1 = [{ id: '1234' }, { id: 'abg543' }, { id: '214swfA' }];
......
export const generateVulnerabilities = () => [ export const generateVulnerabilities = () => [
{ {
id: 'id_0', id: 'id_0',
title: 'Vulnerability 1', title: 'Vulnerability 0',
severity: 'critical', severity: 'critical',
state: 'dismissed', state: 'dismissed',
reportType: 'SAST',
location: { location: {
image: image:
'registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff', 'registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff',
...@@ -14,9 +15,10 @@ export const generateVulnerabilities = () => [ ...@@ -14,9 +15,10 @@ export const generateVulnerabilities = () => [
}, },
{ {
id: 'id_1', id: 'id_1',
title: 'Vulnerability 2', title: 'Vulnerability 1',
severity: 'high', severity: 'high',
state: 'opened', state: 'opened',
reportType: 'DEPENDENCY_SCANNING',
location: { location: {
file: 'src/main/java/com/gitlab/security_products/tests/App.java', file: 'src/main/java/com/gitlab/security_products/tests/App.java',
}, },
...@@ -24,6 +26,31 @@ export const generateVulnerabilities = () => [ ...@@ -24,6 +26,31 @@ export const generateVulnerabilities = () => [
nameWithNamespace: 'Administrator / Vulnerability reports', nameWithNamespace: 'Administrator / Vulnerability reports',
}, },
}, },
{
id: 'id_2',
title: 'Vulnerability 2',
severity: 'high',
state: 'opened',
reportType: 'CUSTOM_SCANNER_WITHOUT_TRANSLATION',
location: {
file: 'yarn.lock',
},
project: {
nameWithNamespace: 'Mixed Vulnerabilities / Dependency List Test 01',
},
},
{
id: 'id_3',
title: 'Vulnerability 3',
severity: 'high',
state: 'opened',
location: {
file: 'yarn.lock',
},
project: {
nameWithNamespace: 'Mixed Vulnerabilities / Dependency List Test 01',
},
},
]; ];
export const vulnerabilities = generateVulnerabilities(); export const vulnerabilities = generateVulnerabilities();
...@@ -31,9 +31,8 @@ describe('Vulnerability list component', () => { ...@@ -31,9 +31,8 @@ describe('Vulnerability list component', () => {
const findCell = label => wrapper.find(`.js-${label}`); const findCell = label => wrapper.find(`.js-${label}`);
const findRow = (index = 0) => wrapper.findAll('tbody tr').at(index); const findRow = (index = 0) => wrapper.findAll('tbody tr').at(index);
const findSelectionSummary = () => wrapper.find(SelectionSummary); const findSelectionSummary = () => wrapper.find(SelectionSummary);
const findCheckAllCheckboxCell = () => wrapper.find('thead tr th'); const findDataCell = label => wrapper.find(`[data-testid="${label}"]`);
const findFirstCheckboxCell = () => wrapper.find('tbody tr td'); const findDataCells = label => wrapper.findAll(`[data-testid="${label}"]`);
const findLocation = id => wrapper.find(`[data-testid="location-${id}"]`);
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
...@@ -74,9 +73,7 @@ describe('Vulnerability list component', () => { ...@@ -74,9 +73,7 @@ describe('Vulnerability list component', () => {
}); });
it('should show the selection summary when a checkbox is selected', () => { it('should show the selection summary when a checkbox is selected', () => {
findFirstCheckboxCell() findDataCell('vulnerability-checkbox').setChecked(true);
.find('input')
.setChecked(true);
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
expect(findSelectionSummary().exists()).toBe(true); expect(findSelectionSummary().exists()).toBe(true);
...@@ -84,9 +81,7 @@ describe('Vulnerability list component', () => { ...@@ -84,9 +81,7 @@ describe('Vulnerability list component', () => {
}); });
it('should sync selected vulnerabilities when the vulnerability list is updated', () => { it('should sync selected vulnerabilities when the vulnerability list is updated', () => {
findFirstCheckboxCell() findDataCell('vulnerability-checkbox').setChecked(true);
.find('input')
.setChecked(true);
expect(findSelectionSummary().props('selectedVulnerabilities')).toHaveLength(1); expect(findSelectionSummary().props('selectedVulnerabilities')).toHaveLength(1);
wrapper.setProps({ vulnerabilities: [] }); wrapper.setProps({ vulnerabilities: [] });
...@@ -101,38 +96,44 @@ describe('Vulnerability list component', () => { ...@@ -101,38 +96,44 @@ describe('Vulnerability list component', () => {
wrapper = createWrapper({ wrapper = createWrapper({
props: { vulnerabilities, shouldShowSelection: false }, props: { vulnerabilities, shouldShowSelection: false },
}); });
findFirstCheckboxCell()
.find('input')
.setChecked(true);
}); });
it('should not show the checkboxes if shouldShowSelection is passed in', () => { it('should not show the checkboxes if shouldShowSelection is passed in', () => {
expect(findCheckAllCheckboxCell().classes()).toContain('gl-display-none'); expect(findDataCell('vulnerability-checkbox-all').exists()).toBe(false);
expect(findFirstCheckboxCell().classes()).toContain('gl-display-none'); expect(findDataCell('vulnerability-checkbox').exists()).toBe(false);
}); });
}); });
describe('when displayed on instance or group level dashboard', () => { describe('when displayed on instance or group level dashboard', () => {
it('should display the vulnerability locations', () => { let newVulnerabilities;
const newVulnerabilities = generateVulnerabilities();
beforeEach(() => {
newVulnerabilities = generateVulnerabilities();
wrapper = createWrapper({ wrapper = createWrapper({
props: { vulnerabilities: newVulnerabilities, shouldShowProjectNamespace: true }, props: { vulnerabilities: newVulnerabilities, shouldShowProjectNamespace: true },
}); });
expect(findLocation(newVulnerabilities[0].id).text()).toContain( });
it('should display the vulnerability locations', () => {
expect(findDataCell(`location-${newVulnerabilities[0].id}`).text()).toContain(
'Administrator / Security reports', 'Administrator / Security reports',
); );
expect(findLocation(newVulnerabilities[0].id).text()).toContain( expect(findDataCell(`location-${newVulnerabilities[0].id}`).text()).toContain(
'registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff', 'registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff',
); );
expect(findLocation(newVulnerabilities[1].id).text()).toContain( expect(findDataCell(`location-${newVulnerabilities[1].id}`).text()).toContain(
'Administrator / Vulnerability reports', 'Administrator / Vulnerability reports',
); );
expect(findLocation(newVulnerabilities[1].id).text()).toContain( expect(findDataCell(`location-${newVulnerabilities[1].id}`).text()).toContain(
'src/main/java/com/gitlab/security_products/tests/App.java', 'src/main/java/com/gitlab/security_products/tests/App.java',
); );
}); });
it('should not display the vulnerability report type', () => {
const scannerCell = findRow().find('[data-testid="vulnerability-report-type"');
expect(scannerCell.exists()).toBe(false);
});
it('should not display the vulnerability locations', () => { it('should not display the vulnerability locations', () => {
const vulnerabilityWithoutLocation = [ const vulnerabilityWithoutLocation = [
{ {
...@@ -149,10 +150,12 @@ describe('Vulnerability list component', () => { ...@@ -149,10 +150,12 @@ describe('Vulnerability list component', () => {
wrapper = createWrapper({ wrapper = createWrapper({
props: { vulnerabilities: vulnerabilityWithoutLocation, shouldShowProjectNamespace: true }, props: { vulnerabilities: vulnerabilityWithoutLocation, shouldShowProjectNamespace: true },
}); });
expect(findLocation(vulnerabilityWithoutLocation[0].id).text()).toContain( expect(findDataCell(`location-${vulnerabilityWithoutLocation[0].id}`).text()).toContain(
'Administrator / Security reports', 'Administrator / Security reports',
); );
expect(findLocation(vulnerabilityWithoutLocation[0].id).findAll('div').length).toBe(2); expect(
findDataCell(`location-${vulnerabilityWithoutLocation[0].id}`).findAll('div').length,
).toBe(2);
}); });
}); });
...@@ -161,24 +164,32 @@ describe('Vulnerability list component', () => { ...@@ -161,24 +164,32 @@ describe('Vulnerability list component', () => {
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
wrapper = createWrapper({ wrapper = createWrapper({
props: { vulnerabilities: newVulnerabilities }, props: { vulnerabilities: newVulnerabilities, shouldShowReportType: true },
}); });
}); });
it('should not display the vulnerability locations', () => { it('should not display the vulnerability locations', () => {
expect(findLocation(newVulnerabilities[0].id).text()).not.toContain( expect(findDataCell(`location-${newVulnerabilities[0].id}`).text()).not.toContain(
'Administrator / Security reports', 'Administrator / Security reports',
); );
expect(findLocation(newVulnerabilities[0].id).text()).toContain( expect(findDataCell(`location-${newVulnerabilities[0].id}`).text()).toContain(
'registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff', 'registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff',
); );
expect(findLocation(newVulnerabilities[1].id).text()).not.toContain( expect(findDataCell(`location-${newVulnerabilities[1].id}`).text()).not.toContain(
'Administrator / Vulnerability reports', 'Administrator / Vulnerability reports',
); );
expect(findLocation(newVulnerabilities[1].id).text()).toContain( expect(findDataCell(`location-${newVulnerabilities[1].id}`).text()).toContain(
'src/main/java/com/gitlab/security_products/tests/App.java', 'src/main/java/com/gitlab/security_products/tests/App.java',
); );
}); });
it('should display the vulnerability report type', () => {
const cells = findDataCells('vulnerability-report-type');
expect(cells.at(0).text()).toBe('SAST');
expect(cells.at(1).text()).toBe('Dependency Scanning');
expect(cells.at(2).text()).toBe('Custom scanner without translation');
expect(cells.at(3).text()).toBe('');
});
}); });
describe('when has an issue associated', () => { describe('when has an issue associated', () => {
......
...@@ -19150,6 +19150,9 @@ msgstr "" ...@@ -19150,6 +19150,9 @@ msgstr ""
msgid "Reports|Metrics reports failed loading results" msgid "Reports|Metrics reports failed loading results"
msgstr "" msgstr ""
msgid "Reports|Scanner"
msgstr ""
msgid "Reports|Severity" msgid "Reports|Severity"
msgstr "" msgstr ""
...@@ -20115,15 +20118,15 @@ msgstr "" ...@@ -20115,15 +20118,15 @@ msgstr ""
msgid "SecurityReports|Remove project from dashboard" msgid "SecurityReports|Remove project from dashboard"
msgstr "" msgstr ""
msgid "SecurityReports|Report type"
msgstr ""
msgid "SecurityReports|Return to dashboard" msgid "SecurityReports|Return to dashboard"
msgstr "" msgstr ""
msgid "SecurityReports|Scan details" msgid "SecurityReports|Scan details"
msgstr "" msgstr ""
msgid "SecurityReports|Scanner type"
msgstr ""
msgid "SecurityReports|Security Dashboard" msgid "SecurityReports|Security Dashboard"
msgstr "" msgstr ""
...@@ -26702,7 +26705,7 @@ msgstr "" ...@@ -26702,7 +26705,7 @@ msgstr ""
msgid "ciReport|All projects" msgid "ciReport|All projects"
msgstr "" msgstr ""
msgid "ciReport|All report types" msgid "ciReport|All scanner types"
msgstr "" msgstr ""
msgid "ciReport|All severities" msgid "ciReport|All severities"
......
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