Commit cb8b4e44 authored by Daniel Tian's avatar Daniel Tian Committed by Savas Vedova

Add ability to pass in fields to new vulnerability list component

parent d850bb85
import { __, s__ } from '~/locale';
export const FIELDS = {
CHECKBOX: {
key: 'checkbox',
class: 'checkbox',
},
DETECTED: {
key: 'detected',
label: s__('Vulnerability|Detected'),
class: 'detected',
sortable: true,
},
STATUS: {
key: 'state',
label: s__('Vulnerability|Status'),
class: 'status',
sortable: true,
},
SEVERITY: {
key: 'severity',
label: s__('Vulnerability|Severity'),
class: 'severity',
sortable: true,
},
DESCRIPTION: {
key: 'title',
label: __('Description'),
class: 'description gl-word-break-all',
sortable: true,
},
IDENTIFIER: {
key: 'identifier',
label: s__('Vulnerability|Identifier'),
class: 'identifier gl-word-break-all',
},
TOOL: {
key: 'reportType',
label: s__('Reports|Tool'),
class: 'scanner',
sortable: true,
},
ACTIVITY: {
key: 'activity',
label: s__('Vulnerability|Activity'),
thClass: 'gl-text-right ',
class: 'activity',
},
};
...@@ -10,7 +10,7 @@ import { ...@@ -10,7 +10,7 @@ import {
} from '@gitlab/ui'; } from '@gitlab/ui';
import DashboardHasNoVulnerabilities from 'ee/security_dashboard/components/shared/empty_states/dashboard_has_no_vulnerabilities.vue'; import DashboardHasNoVulnerabilities from 'ee/security_dashboard/components/shared/empty_states/dashboard_has_no_vulnerabilities.vue';
import FiltersProducedNoResults from 'ee/security_dashboard/components/shared/empty_states/filters_produced_no_results.vue'; import FiltersProducedNoResults from 'ee/security_dashboard/components/shared/empty_states/filters_produced_no_results.vue';
import { VULNERABILITIES_PER_PAGE, DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants'; import { VULNERABILITIES_PER_PAGE } from 'ee/security_dashboard/store/constants';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue'; import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import convertReportType from 'ee/vue_shared/security_reports/store/utils/convert_report_type'; 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';
...@@ -19,7 +19,6 @@ import RemediatedBadge from 'ee/vulnerabilities/components/remediated_badge.vue' ...@@ -19,7 +19,6 @@ import RemediatedBadge from 'ee/vulnerabilities/components/remediated_badge.vue'
import { VULNERABILITY_STATES } from 'ee/vulnerabilities/constants'; import { VULNERABILITY_STATES } from 'ee/vulnerabilities/constants';
import { formatDate } from '~/lib/utils/datetime_utility'; import { formatDate } from '~/lib/utils/datetime_utility';
import { convertToSnakeCase } from '~/lib/utils/text_utility'; import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { s__, __ } from '~/locale';
import AutoFixHelpText from '../auto_fix_help_text.vue'; import AutoFixHelpText from '../auto_fix_help_text.vue';
import IssuesBadge from '../issues_badge.vue'; import IssuesBadge from '../issues_badge.vue';
import SelectionSummary from '../selection_summary.vue'; import SelectionSummary from '../selection_summary.vue';
...@@ -53,16 +52,11 @@ export default { ...@@ -53,16 +52,11 @@ export default {
hasJiraVulnerabilitiesIntegrationEnabled: { hasJiraVulnerabilitiesIntegrationEnabled: {
default: false, default: false,
}, },
canAdminVulnerability: {
default: false,
},
dashboardType: {},
}, },
props: { props: {
filters: { fields: {
type: Object, type: Array,
required: false, required: true,
default: () => ({}),
}, },
vulnerabilities: { vulnerabilities: {
type: Array, type: Array,
...@@ -87,12 +81,6 @@ export default { ...@@ -87,12 +81,6 @@ export default {
}; };
}, },
computed: { computed: {
isSortable() {
return Boolean(this.$listeners['sort-changed']);
},
isPipelineDashboard() {
return this.dashboardType === DASHBOARD_TYPES.PIPELINE;
},
hasAnyScannersOtherThanGitLab() { hasAnyScannersOtherThanGitLab() {
return this.vulnerabilities.some( return this.vulnerabilities.some(
(v) => v.scanner?.vendor !== 'GitLab' && v.scanner?.vendor !== '', (v) => v.scanner?.vendor !== 'GitLab' && v.scanner?.vendor !== '',
...@@ -108,75 +96,13 @@ export default { ...@@ -108,75 +96,13 @@ export default {
return Object.keys(this.selectedVulnerabilities).length; return Object.keys(this.selectedVulnerabilities).length;
}, },
shouldShowSelectionSummary() { shouldShowSelectionSummary() {
return this.canAdminVulnerability && this.numOfSelectedVulnerabilities > 0; return this.numOfSelectedVulnerabilities > 0;
}, },
theadClass() { theadClass() {
return this.shouldShowSelectionSummary ? 'below-selection-summary' : ''; return this.shouldShowSelectionSummary ? 'below-selection-summary' : '';
}, },
fields() {
const baseFields = [
{
key: 'checkbox',
class: 'checkbox',
skip: !this.canAdminVulnerability,
},
{
key: 'detected',
label: s__('Vulnerability|Detected'),
class: 'detected',
sortable: this.isSortable,
skip: this.isPipelineDashboard,
},
{
key: 'state',
label: s__('Vulnerability|Status'),
class: 'status',
sortable: this.isSortable,
},
{
key: 'severity',
label: s__('Vulnerability|Severity'),
class: 'severity',
sortable: this.isSortable,
},
{
key: 'title',
label: __('Description'),
class: 'description gl-word-break-all',
sortable: this.isSortable,
},
{
key: 'identifier',
label: s__('Vulnerability|Identifier'),
class: 'identifier gl-word-break-all',
},
{
key: 'reportType',
label: s__('Reports|Tool'),
class: 'scanner',
sortable: this.isSortable,
},
{
key: 'activity',
label: s__('Vulnerability|Activity'),
thClass: 'gl-text-right',
class: 'activity',
skip: this.isPipelineDashboard,
},
].filter((f) => !f.skip);
// Apply gl-bg-white! to every header.
baseFields.forEach((field) => {
field.thClass = [field.thClass, 'gl-bg-white!']; // eslint-disable-line no-param-reassign
});
return baseFields;
},
}, },
watch: { watch: {
filters() {
this.selectedVulnerabilities = {};
},
vulnerabilities() { vulnerabilities() {
const ids = new Set(this.vulnerabilities.map((v) => v.id)); const ids = new Set(this.vulnerabilities.map((v) => v.id));
...@@ -282,10 +208,11 @@ export default { ...@@ -282,10 +208,11 @@ export default {
useConvertReportType(reportType) { useConvertReportType(reportType) {
return convertReportType(reportType); return convertReportType(reportType);
}, },
handleSortChange(args) { handleSortChange(context) {
if (args.sortBy) { const fieldName = convertToSnakeCase(context.sortBy);
this.$emit('sort-changed', { ...args, sortBy: convertToSnakeCase(args.sortBy) }); const direction = context.sortDesc ? 'desc' : 'asc';
}
this.$emit('sort-changed', `${fieldName}_${direction}`);
}, },
getVulnerabilityState(state = '') { getVulnerabilityState(state = '') {
const stateName = state.toLowerCase(); const stateName = state.toLowerCase();
...@@ -306,7 +233,6 @@ export default { ...@@ -306,7 +233,6 @@ export default {
@vulnerability-updated="deselectVulnerability" @vulnerability-updated="deselectVulnerability"
/> />
<gl-table <gl-table
v-if="filters"
:busy="isLoading" :busy="isLoading"
:fields="fields" :fields="fields"
:items="vulnerabilities" :items="vulnerabilities"
...@@ -316,12 +242,12 @@ export default { ...@@ -316,12 +242,12 @@ export default {
sort-icon-left sort-icon-left
no-local-sorting no-local-sorting
stacked="sm" stacked="sm"
class="vulnerability-list"
show-empty show-empty
responsive responsive
hover hover
primary-key="id" primary-key="id"
:tbody-tr-class="{ 'gl-cursor-pointer': vulnerabilities.length }" :tbody-tr-class="{ 'gl-cursor-pointer': vulnerabilities.length }"
head-variant="white"
@sort-changed="handleSortChange" @sort-changed="handleSortChange"
@row-clicked="toggleVulnerability" @row-clicked="toggleVulnerability"
> >
......
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlTable, GlTruncate } from '@gitlab/ui'; import { GlSkeletonLoading, GlTable, GlTruncate } from '@gitlab/ui';
import { capitalize } from 'lodash'; import { capitalize } from 'lodash';
import DashboardHasNoVulnerabilities from 'ee/security_dashboard/components/shared/empty_states/dashboard_has_no_vulnerabilities.vue'; import DashboardHasNoVulnerabilities from 'ee/security_dashboard/components/shared/empty_states/dashboard_has_no_vulnerabilities.vue';
import FiltersProducedNoResults from 'ee/security_dashboard/components/shared/empty_states/filters_produced_no_results.vue'; import FiltersProducedNoResults from 'ee/security_dashboard/components/shared/empty_states/filters_produced_no_results.vue';
import IssuesBadge from 'ee/security_dashboard/components/shared/issues_badge.vue'; import IssuesBadge from 'ee/security_dashboard/components/shared/issues_badge.vue';
import SelectionSummary from 'ee/security_dashboard/components/shared/selection_summary.vue'; import SelectionSummary from 'ee/security_dashboard/components/shared/selection_summary.vue';
import VulnerabilityCommentIcon from 'ee/security_dashboard/components/shared/vulnerability_comment_icon.vue'; import VulnerabilityCommentIcon from 'ee/security_dashboard/components/shared/vulnerability_comment_icon.vue';
import VulnerabilityList from 'ee/security_dashboard/components/shared/vulnerability_list.vue'; import VulnerabilityList from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_list.vue';
import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants'; import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants';
import FalsePositiveBadge from 'ee/vulnerabilities/components/false_positive_badge.vue'; import FalsePositiveBadge from 'ee/vulnerabilities/components/false_positive_badge.vue';
import RemediatedBadge from 'ee/vulnerabilities/components/remediated_badge.vue'; import RemediatedBadge from 'ee/vulnerabilities/components/remediated_badge.vue';
import { trimText } from 'helpers/text_helper'; import { trimText } from 'helpers/text_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper'; import { mountExtended } from 'helpers/vue_test_utils_helper';
import { FIELDS } from 'ee/security_dashboard/components/shared/vulnerability_report/constants';
import { generateVulnerabilities, vulnerabilities } from '../../mock_data'; import { generateVulnerabilities, vulnerabilities } from '../../mock_data';
const { CHECKBOX, DETECTED, STATUS, SEVERITY, DESCRIPTION, IDENTIFIER, TOOL, ACTIVITY } = FIELDS;
describe('Vulnerability list component', () => { describe('Vulnerability list component', () => {
let wrapper; let wrapper;
const createWrapper = ({ props = {}, listeners, provide = {}, stubs } = {}) => { const createWrapper = ({ props = {}, listeners, provide = {}, stubs } = {}) => {
return mountExtended(VulnerabilityList, { wrapper = mountExtended(VulnerabilityList, {
propsData: { propsData: {
vulnerabilities: [], vulnerabilities: [],
fields: [CHECKBOX, DETECTED, STATUS, SEVERITY, DESCRIPTION, IDENTIFIER, TOOL, ACTIVITY],
...props, ...props,
}, },
stubs: { stubs: {
...@@ -44,12 +48,9 @@ describe('Vulnerability list component', () => { ...@@ -44,12 +48,9 @@ describe('Vulnerability list component', () => {
const locationText = ({ file, startLine }) => `${file}:${startLine}`; const locationText = ({ file, startLine }) => `${file}:${startLine}`;
const findTable = () => wrapper.findComponent(GlTable); const findTable = () => wrapper.findComponent(GlTable);
const findSortableColumn = () => wrapper.find('[aria-sort="descending"]');
const findCell = (label) => wrapper.find(`.js-${label}`); const findCell = (label) => wrapper.find(`.js-${label}`);
const findRows = () => wrapper.findAll('tbody tr'); const findRows = () => wrapper.findAll('tbody tr');
const findRow = (index = 0) => findRows().at(index); const findRow = (index = 0) => findRows().at(index);
const findColumn = (className) => wrapper.find(`[role="columnheader"].${className}`);
const findRowById = (id) => wrapper.find(`tbody tr[data-pk="${id}"`);
const findAutoFixBulbInRow = (row) => row.find('[data-testid="vulnerability-solutions-bulb"]'); const findAutoFixBulbInRow = (row) => row.find('[data-testid="vulnerability-solutions-bulb"]');
const findIssuesBadge = (index = 0) => wrapper.findAllComponents(IssuesBadge).at(index); const findIssuesBadge = (index = 0) => wrapper.findAllComponents(IssuesBadge).at(index);
const findRemediatedBadge = () => wrapper.findComponent(RemediatedBadge); const findRemediatedBadge = () => wrapper.findComponent(RemediatedBadge);
...@@ -75,7 +76,7 @@ describe('Vulnerability list component', () => { ...@@ -75,7 +76,7 @@ describe('Vulnerability list component', () => {
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
wrapper = createWrapper({ props: { vulnerabilities: newVulnerabilities } }); createWrapper({ props: { vulnerabilities: newVulnerabilities } });
}); });
it('should render a list of vulnerabilities', () => { it('should render a list of vulnerabilities', () => {
...@@ -183,7 +184,7 @@ describe('Vulnerability list component', () => { ...@@ -183,7 +184,7 @@ describe('Vulnerability list component', () => {
'issues badge when "hasJiraVulnerabilitiesIntegrationEnabled" is set to "%s"', 'issues badge when "hasJiraVulnerabilitiesIntegrationEnabled" is set to "%s"',
(hasJiraVulnerabilitiesIntegrationEnabled) => { (hasJiraVulnerabilitiesIntegrationEnabled) => {
beforeEach(() => { beforeEach(() => {
wrapper = createWrapper({ createWrapper({
props: { vulnerabilities: generateVulnerabilities() }, props: { vulnerabilities: generateVulnerabilities() },
provide: { hasJiraVulnerabilitiesIntegrationEnabled }, provide: { hasJiraVulnerabilitiesIntegrationEnabled },
}); });
...@@ -204,28 +205,12 @@ describe('Vulnerability list component', () => { ...@@ -204,28 +205,12 @@ describe('Vulnerability list component', () => {
); );
}); });
describe('when user has no permission to admin vulnerabilities', () => {
beforeEach(() => {
wrapper = createWrapper({
props: { vulnerabilities },
provide: {
canAdminVulnerability: false,
},
});
});
it('should not show the checkboxes', () => {
expect(findDataCell('vulnerability-checkbox-all').exists()).toBe(false);
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', () => {
let newVulnerabilities; let newVulnerabilities;
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
wrapper = createWrapper({ createWrapper({
props: { vulnerabilities: newVulnerabilities, shouldShowProjectNamespace: true }, props: { vulnerabilities: newVulnerabilities, shouldShowProjectNamespace: true },
}); });
}); });
...@@ -282,7 +267,7 @@ describe('Vulnerability list component', () => { ...@@ -282,7 +267,7 @@ describe('Vulnerability list component', () => {
let newVulnerabilities; let newVulnerabilities;
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
wrapper = createWrapper({ createWrapper({
props: { props: {
vulnerabilities: newVulnerabilities, vulnerabilities: newVulnerabilities,
shouldShowIdentifier: true, shouldShowIdentifier: true,
...@@ -358,7 +343,7 @@ describe('Vulnerability list component', () => { ...@@ -358,7 +343,7 @@ describe('Vulnerability list component', () => {
}, },
], ],
}; };
wrapper = createWrapper({ props: { vulnerabilities: newVulnerabilities } }); createWrapper({ props: { vulnerabilities: newVulnerabilities } });
}); });
it('should emit "vulnerability-clicked" with the vulnerability as a payload when a vulnerability-link is clicked', async () => { it('should emit "vulnerability-clicked" with the vulnerability as a payload when a vulnerability-link is clicked', async () => {
...@@ -382,7 +367,7 @@ describe('Vulnerability list component', () => { ...@@ -382,7 +367,7 @@ describe('Vulnerability list component', () => {
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
newVulnerabilities[0].userNotesCount = 1; newVulnerabilities[0].userNotesCount = 1;
wrapper = createWrapper({ props: { vulnerabilities: newVulnerabilities } }); createWrapper({ props: { vulnerabilities: newVulnerabilities } });
}); });
it('should render the comments badge on the first vulnerability', () => { it('should render the comments badge on the first vulnerability', () => {
...@@ -403,7 +388,7 @@ describe('Vulnerability list component', () => { ...@@ -403,7 +388,7 @@ describe('Vulnerability list component', () => {
...v, ...v,
scanner: { vendor: 'GitLab' }, scanner: { vendor: 'GitLab' },
})); }));
wrapper = createWrapper({ createWrapper({
props: { props: {
vulnerabilities: newVulnerabilities, vulnerabilities: newVulnerabilities,
shouldShowReportType: true, shouldShowReportType: true,
...@@ -422,7 +407,7 @@ describe('Vulnerability list component', () => { ...@@ -422,7 +407,7 @@ describe('Vulnerability list component', () => {
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
newVulnerabilities = newVulnerabilities.map((v) => ({ ...v, scanner: { vendor: '' } })); newVulnerabilities = newVulnerabilities.map((v) => ({ ...v, scanner: { vendor: '' } }));
wrapper = createWrapper({ createWrapper({
props: { props: {
vulnerabilities: newVulnerabilities, vulnerabilities: newVulnerabilities,
shouldShowReportType: true, shouldShowReportType: true,
...@@ -442,7 +427,7 @@ describe('Vulnerability list component', () => { ...@@ -442,7 +427,7 @@ describe('Vulnerability list component', () => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
newVulnerabilities[0].scanner = { vendor: 'GitLab' }; newVulnerabilities[0].scanner = { vendor: 'GitLab' };
newVulnerabilities[1].scanner = { vendor: 'Third Party Scanner' }; newVulnerabilities[1].scanner = { vendor: 'Third Party Scanner' };
wrapper = createWrapper({ createWrapper({
props: { props: {
vulnerabilities: newVulnerabilities, vulnerabilities: newVulnerabilities,
shouldShowReportType: true, shouldShowReportType: true,
...@@ -461,7 +446,7 @@ describe('Vulnerability list component', () => { ...@@ -461,7 +446,7 @@ describe('Vulnerability list component', () => {
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
newVulnerabilities[0].falsePositive = true; newVulnerabilities[0].falsePositive = true;
wrapper = createWrapper({ createWrapper({
props: { vulnerabilities: newVulnerabilities }, props: { vulnerabilities: newVulnerabilities },
provide: { provide: {
falsePositiveDocUrl: '/docs', falsePositiveDocUrl: '/docs',
...@@ -491,7 +476,7 @@ describe('Vulnerability list component', () => { ...@@ -491,7 +476,7 @@ describe('Vulnerability list component', () => {
beforeEach(() => { beforeEach(() => {
newVulnerabilities = generateVulnerabilities(); newVulnerabilities = generateVulnerabilities();
newVulnerabilities[0].resolvedOnDefaultBranch = true; newVulnerabilities[0].resolvedOnDefaultBranch = true;
wrapper = createWrapper({ props: { vulnerabilities: newVulnerabilities } }); createWrapper({ props: { vulnerabilities: newVulnerabilities } });
}); });
it('should render the remediated info badge on the first vulnerability', () => { it('should render the remediated info badge on the first vulnerability', () => {
...@@ -509,20 +494,22 @@ describe('Vulnerability list component', () => { ...@@ -509,20 +494,22 @@ describe('Vulnerability list component', () => {
}); });
}); });
describe('when loading', () => { describe('loading prop', () => {
beforeEach(() => { it.each`
wrapper = createWrapper({ props: { isLoading: true } }); phrase | isLoading
}); ${'show'} | ${true}
${'not show'} | ${false}
`('should $phrase the loading state', ({ isLoading }) => {
createWrapper({ props: { isLoading, vulnerabilities } });
it('should show the loading state', () => { expect(findCell('status').exists()).toEqual(!isLoading);
expect(findCell('status').exists()).toEqual(false); expect(wrapper.find(GlSkeletonLoading).exists()).toEqual(isLoading);
expect(wrapper.find(GlSkeletonLoading).exists()).toEqual(true);
}); });
}); });
describe('with no vulnerabilities', () => { describe('with no vulnerabilities', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createWrapper({ props: { filters: { someFilter: 'true' } } }); createWrapper();
}); });
it('should show the empty state', () => { it('should show the empty state', () => {
...@@ -532,65 +519,13 @@ describe('Vulnerability list component', () => { ...@@ -532,65 +519,13 @@ describe('Vulnerability list component', () => {
}); });
}); });
describe('with vulnerabilities when there are filters', () => { describe('sort-changed listener', () => {
it.each` it('emits sort by data in expected format', () => {
state createWrapper();
${['DETECTED']}
${['DISMISSED']}
${[]}
${['DETECTED', 'DISMISSED']}
`('should only show vulnerabilities that match filter $state', (state) => {
wrapper = createWrapper({ props: { vulnerabilities, filters: { state } } });
const filteredVulnerabilities = vulnerabilities.filter((x) =>
state.length ? state.includes(x.state) : true,
);
expect(findRows().length).toBe(filteredVulnerabilities.length);
filteredVulnerabilities.forEach((vulnerability) => {
expect(findRowById(vulnerability.id).exists()).toBe(true);
});
});
});
describe('when has a sort-changed listener defined', () => {
let spy;
beforeEach(() => {
spy = jest.fn();
wrapper = createWrapper({
listeners: { 'sort-changed': spy },
});
});
it('is sortable', () => {
expect(findSortableColumn().attributes('class')).toContain('severity');
});
it('triggers the listener when sortBy is not an empty value', () => {
const args = { sortBy: 'severity', sortDesc: false };
findTable().vm.$emit('sort-changed', args);
expect(spy).toHaveBeenCalledWith(args);
});
it('triggers the listener when sortBy is camelCased and transforms it to snake_case', () => {
const args = { sortBy: 'reportType', sortDesc: false };
findTable().vm.$emit('sort-changed', args);
expect(spy).toHaveBeenCalledWith({ ...args, sortBy: 'report_type' });
});
it('does not trigger the listener when sortBy is an empty value', () => {
findTable().vm.$emit('sort-changed', {});
expect(spy).not.toHaveBeenCalled();
});
});
describe('when does not have a sort-changed listener defined', () => { findTable().vm.$emit('sort-changed', { sortBy: 'state', sortDesc: true });
beforeEach(() => {
wrapper = createWrapper();
});
it('is not sortable', () => { expect(wrapper.emitted('sort-changed')[0][0]).toBe('state_desc');
expect(findSortableColumn().exists()).toBe(false);
}); });
}); });
...@@ -599,7 +534,7 @@ describe('Vulnerability list component', () => { ...@@ -599,7 +534,7 @@ describe('Vulnerability list component', () => {
findRow(index).find('[data-testid="vulnerability-checkbox"]'); findRow(index).find('[data-testid="vulnerability-checkbox"]');
beforeEach(() => { beforeEach(() => {
wrapper = createWrapper({ props: { vulnerabilities } }); createWrapper({ props: { vulnerabilities } });
}); });
it('will select and deselect vulnerabilities', async () => { it('will select and deselect vulnerabilities', async () => {
...@@ -621,26 +556,15 @@ describe('Vulnerability list component', () => { ...@@ -621,26 +556,15 @@ describe('Vulnerability list component', () => {
}); });
}); });
describe('when it is the pipeline dashboard', () => { describe('fields prop', () => {
beforeEach(() => { it('shows the expected columns in the table', () => {
wrapper = createWrapper({ const fields = [STATUS, SEVERITY];
props: { vulnerabilities }, createWrapper({ props: { fields, vulnerabilities } });
provide: { dashboardType: DASHBOARD_TYPES.PIPELINE },
stubs: {
GlTable,
},
});
});
it.each([['detected'], ['activity']])('does not render %s column', (className) => { // Check that there are only 2 columns.
expect(findColumn(className).exists()).toBe(false); expect(findRow().element.cells).toHaveLength(2);
expect(findCell(STATUS.class).exists()).toBe(true);
expect(findCell(SEVERITY.class).exists()).toBe(true);
}); });
it.each([['status'], ['severity'], ['description'], ['identifier'], ['scanner']])(
'renders %s column',
(className) => {
expect(findColumn(className).exists()).toBe(true);
},
);
}); });
}); });
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