Commit 1b4edb67 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '330248-scanner-filter-header' into 'master'

Hide scanner filter vendor header when there's only the default vendor

See merge request gitlab-org/gitlab!63596
parents c3d21c44 b6a51e4c
...@@ -82,6 +82,9 @@ export default { ...@@ -82,6 +82,9 @@ export default {
return { scannerId: ids }; return { scannerId: ids };
}, },
hasCustomVendor() {
return Object.keys(this.groups).length > 1;
},
}, },
methods: { methods: {
toggleGroup(groupName) { toggleGroup(groupName) {
...@@ -112,9 +115,10 @@ export default { ...@@ -112,9 +115,10 @@ export default {
/> />
<template v-for="[groupName, groupOptions] in Object.entries(groups)"> <template v-for="[groupName, groupOptions] in Object.entries(groups)">
<gl-dropdown-divider :key="`${groupName}:divider`" /> <gl-dropdown-divider v-if="hasCustomVendor" :key="`${groupName}:divider`" />
<gl-dropdown-item <gl-dropdown-item
v-if="hasCustomVendor"
:key="`${groupName}:header`" :key="`${groupName}:header`"
:data-testid="`${groupName}Header`" :data-testid="`${groupName}Header`"
@click.native.capture.stop="toggleGroup(groupName)" @click.native.capture.stop="toggleGroup(groupName)"
......
import { GlDropdownItem } from '@gitlab/ui'; import { GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import { sampleSize, cloneDeep } from 'lodash'; import { sampleSize, cloneDeep } from 'lodash';
import VueRouter from 'vue-router'; import VueRouter from 'vue-router';
...@@ -17,7 +17,7 @@ const createScannerConfig = (vendor, reportType, id) => ({ ...@@ -17,7 +17,7 @@ const createScannerConfig = (vendor, reportType, id) => ({
id, id,
}); });
const scanners = [ const defaultScanners = [
createScannerConfig(DEFAULT_SCANNER, 'DEPENDENCY_SCANNING', 1), createScannerConfig(DEFAULT_SCANNER, 'DEPENDENCY_SCANNING', 1),
createScannerConfig(DEFAULT_SCANNER, 'DEPENDENCY_SCANNING', 2), createScannerConfig(DEFAULT_SCANNER, 'DEPENDENCY_SCANNING', 2),
createScannerConfig(DEFAULT_SCANNER, 'SAST', 3), createScannerConfig(DEFAULT_SCANNER, 'SAST', 3),
...@@ -26,6 +26,10 @@ const scanners = [ ...@@ -26,6 +26,10 @@ const scanners = [
createScannerConfig(DEFAULT_SCANNER, 'CONTAINER_SCANNING', 6), createScannerConfig(DEFAULT_SCANNER, 'CONTAINER_SCANNING', 6),
createScannerConfig(DEFAULT_SCANNER, 'DAST', 7), createScannerConfig(DEFAULT_SCANNER, 'DAST', 7),
createScannerConfig(DEFAULT_SCANNER, 'DAST', 8), createScannerConfig(DEFAULT_SCANNER, 'DAST', 8),
];
const customScanners = [
...defaultScanners,
createScannerConfig('Custom', 'SAST', 9), createScannerConfig('Custom', 'SAST', 9),
createScannerConfig('Custom', 'SAST', 10), createScannerConfig('Custom', 'SAST', 10),
createScannerConfig('Custom', 'DAST', 11), createScannerConfig('Custom', 'DAST', 11),
...@@ -35,7 +39,7 @@ describe('Scanner Filter component', () => { ...@@ -35,7 +39,7 @@ describe('Scanner Filter component', () => {
let wrapper; let wrapper;
let filter; let filter;
const createWrapper = () => { const createWrapper = ({ scanners = customScanners } = {}) => {
filter = cloneDeep(scannerFilter); filter = cloneDeep(scannerFilter);
wrapper = shallowMount(ScannerFilter, { wrapper = shallowMount(ScannerFilter, {
...@@ -46,6 +50,9 @@ describe('Scanner Filter component', () => { ...@@ -46,6 +50,9 @@ describe('Scanner Filter component', () => {
}); });
}; };
const getTestIds = (selector) =>
wrapper.findAll(selector).wrappers.map((x) => x.attributes('data-testid'));
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
// Clear out the querystring if one exists, it persists between tests. // Clear out the querystring if one exists, it persists between tests.
...@@ -54,67 +61,81 @@ describe('Scanner Filter component', () => { ...@@ -54,67 +61,81 @@ describe('Scanner Filter component', () => {
} }
}); });
it('shows the correct dropdown items', () => { describe('default scanners only', () => {
createWrapper(); it('shows the dropdown items with no headers or dividers', () => {
const getTestIds = (selector) => createWrapper({ scanners: defaultScanners });
wrapper.findAll(selector).wrappers.map((x) => x.attributes('data-testid')); const options = getTestIds(FilterItem);
const expectedOptions = ['all', ...filter.options.map((x) => x.id)];
const options = getTestIds(FilterItem); expect(options).toEqual(expectedOptions);
const expectedOptions = [ expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
'all', expect(wrapper.find(GlDropdownItem).exists()).toBe(false);
...filter.options.map((x) => x.id), });
'Custom.SAST', });
'Custom.DAST',
];
const headers = getTestIds(GlDropdownItem); describe('default and custom scanners', () => {
const expectedHeaders = ['GitLabHeader', 'CustomHeader']; it('shows the correct dropdown items', () => {
createWrapper();
expect(options).toEqual(expectedOptions); const options = getTestIds(FilterItem);
expect(headers).toEqual(expectedHeaders); const expectedOptions = [
}); 'all',
...filter.options.map((x) => x.id),
'Custom.SAST',
'Custom.DAST',
];
it('toggles selection of all items in a group when the group header is clicked', async () => { const headers = getTestIds(GlDropdownItem);
createWrapper(); const expectedHeaders = ['GitLabHeader', 'CustomHeader'];
const expectSelectedItems = (items) => {
const checkedItems = wrapper
.findAll(FilterItem)
.wrappers.filter((x) => x.props('isChecked'))
.map((x) => x.attributes('data-testid'));
const expectedItems = items.map((x) => x.id);
expect(checkedItems.sort()).toEqual(expectedItems.sort()); expect(options).toEqual(expectedOptions);
}; expect(headers).toEqual(expectedHeaders);
});
const clickAndCheck = async (expectedOptions) => { it('toggles selection of all items in a group when the group header is clicked', async () => {
await wrapper.find('[data-testid="GitLabHeader"]').trigger('click'); createWrapper();
const expectSelectedItems = (items) => {
const checkedItems = wrapper
.findAll(FilterItem)
.wrappers.filter((x) => x.props('isChecked'))
.map((x) => x.attributes('data-testid'));
const expectedItems = items.map((x) => x.id);
expectSelectedItems(expectedOptions); expect(checkedItems.sort()).toEqual(expectedItems.sort());
}; };
const selectedOptions = sampleSize(filter.options, 3); // Randomly select some options. const clickAndCheck = async (expectedOptions) => {
await wrapper.setData({ selectedOptions }); await wrapper.find('[data-testid="GitLabHeader"]').trigger('click');
expectSelectedItems(selectedOptions); expectSelectedItems(expectedOptions);
};
await clickAndCheck(filter.options); // First click selects all. const selectedOptions = sampleSize(filter.options, 3); // Randomly select some options.
await clickAndCheck([filter.allOption]); // Second check unselects all. await wrapper.setData({ selectedOptions });
await clickAndCheck(filter.options); // Third click selects all again.
}); expectSelectedItems(selectedOptions);
await clickAndCheck(filter.options); // First click selects all.
await clickAndCheck([filter.allOption]); // Second check unselects all.
await clickAndCheck(filter.options); // Third click selects all again.
});
it('emits filter-changed event with expected data for selected options', async () => { it('emits filter-changed event with expected data for selected options', async () => {
const ids = ['GitLab.SAST', 'Custom.SAST', 'GitLab.API_FUZZING', 'GitLab.COVERAGE_FUZZING']; const ids = ['GitLab.SAST', 'Custom.SAST', 'GitLab.API_FUZZING', 'GitLab.COVERAGE_FUZZING'];
router.replace({ query: { [scannerFilter.id]: ids } }); router.replace({ query: { [scannerFilter.id]: ids } });
const selectedScanners = scanners.filter((x) => ids.includes(`${x.vendor}.${x.report_type}`)); const selectedScanners = customScanners.filter((x) =>
createWrapper(); ids.includes(`${x.vendor}.${x.report_type}`),
await wrapper.vm.$nextTick(); );
createWrapper();
expect(wrapper.emitted('filter-changed')[0][0]).toEqual({ await wrapper.vm.$nextTick();
scannerId: expect.arrayContaining([
...selectedScanners.map((x) => `${SCANNER_ID_PREFIX}${x.id}`), expect(wrapper.emitted('filter-changed')[0][0]).toEqual({
`${SCANNER_ID_PREFIX}COVERAGE_FUZZING:null`, scannerId: expect.arrayContaining([
`${SCANNER_ID_PREFIX}API_FUZZING:null`, ...selectedScanners.map((x) => `${SCANNER_ID_PREFIX}${x.id}`),
]), `${SCANNER_ID_PREFIX}COVERAGE_FUZZING:null`,
`${SCANNER_ID_PREFIX}API_FUZZING:null`,
]),
});
}); });
}); });
}); });
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