Commit 3443f46b authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch '331562-fix-pipeline-security-tab-scanner-filter' into 'master'

Fix pipeline security tab scanner filter not working

See merge request gitlab-org/gitlab!62276
parents faf4cc2d 77cc57a6
<script> <script>
import { GlToggle } from '@gitlab/ui'; import { GlToggle } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { severityFilter, scannerFilter } from 'ee/security_dashboard/helpers'; import { severityFilter, pipelineScannerFilter } from 'ee/security_dashboard/helpers';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { DISMISSAL_STATES } from '../store/modules/filters/constants'; import { DISMISSAL_STATES } from '../store/modules/filters/constants';
import StandardFilter from './filters/standard_filter.vue'; import StandardFilter from './filters/standard_filter.vue';
...@@ -16,7 +16,7 @@ export default { ...@@ -16,7 +16,7 @@ export default {
}, },
data() { data() {
return { return {
filterConfigs: [severityFilter, scannerFilter], filterConfigs: [severityFilter, pipelineScannerFilter],
}; };
}, },
computed: { computed: {
...@@ -44,6 +44,7 @@ export default { ...@@ -44,6 +44,7 @@ export default {
:key="filter.id" :key="filter.id"
class="col-sm-6 col-md-4 col-lg-2 p-2 js-filter" class="col-sm-6 col-md-4 col-lg-2 p-2 js-filter"
:filter="filter" :filter="filter"
:data-testid="filter.id"
@filter-changed="setFilter" @filter-changed="setFilter"
/> />
<div class="gl-display-flex ml-lg-auto p-2"> <div class="gl-display-flex ml-lg-auto p-2">
......
...@@ -132,7 +132,7 @@ export default { ...@@ -132,7 +132,7 @@ export default {
:key="option.id" :key="option.id"
:is-checked="isSelected(option)" :is-checked="isSelected(option)"
:text="option.name" :text="option.name"
data-testid="filterOption" :data-testid="`${filter.id}:${option.id}`"
@click="toggleOption(option)" @click="toggleOption(option)"
/> />
</filter-body> </filter-body>
......
...@@ -43,6 +43,14 @@ export const createScannerOption = (vendor, reportType) => { ...@@ -43,6 +43,14 @@ export const createScannerOption = (vendor, reportType) => {
}; };
}; };
export const pipelineScannerFilter = {
name: s__('SecurityReports|Scanner'),
id: 'reportType',
options: parseOptions(REPORT_TYPES),
allOption: BASE_FILTERS.report_type,
defaultOptions: [],
};
export const scannerFilter = { export const scannerFilter = {
name: s__('SecurityReports|Scanner'), name: s__('SecurityReports|Scanner'),
id: 'scanner', id: 'scanner',
......
import Vue from 'vue'; import Vue from 'vue';
import PipelineSecurityDashboard from './components/pipeline_security_dashboard.vue'; import PipelineSecurityDashboard from './components/pipeline_security_dashboard.vue';
import apolloProvider from './graphql/provider'; import apolloProvider from './graphql/provider';
import createRouter from './router';
import createDashboardStore from './store'; import createDashboardStore from './store';
import { DASHBOARD_TYPES } from './store/constants'; import { DASHBOARD_TYPES } from './store/constants';
import { LOADING_VULNERABILITIES_ERROR_CODES } from './store/modules/vulnerabilities/constants'; import { LOADING_VULNERABILITIES_ERROR_CODES } from './store/modules/vulnerabilities/constants';
...@@ -32,11 +31,8 @@ export default () => { ...@@ -32,11 +31,8 @@ export default () => {
[LOADING_VULNERABILITIES_ERROR_CODES.FORBIDDEN]: emptyStateForbiddenSvgPath, [LOADING_VULNERABILITIES_ERROR_CODES.FORBIDDEN]: emptyStateForbiddenSvgPath,
}; };
const router = createRouter();
return new Vue({ return new Vue({
el, el,
router,
apolloProvider, apolloProvider,
store: createDashboardStore({ store: createDashboardStore({
dashboardType: DASHBOARD_TYPES.PIPELINE, dashboardType: DASHBOARD_TYPES.PIPELINE,
......
...@@ -31,7 +31,7 @@ describe('Standard Filter component', () => { ...@@ -31,7 +31,7 @@ describe('Standard Filter component', () => {
}); });
}; };
const dropdownItems = () => wrapper.findAll('[data-testid="filterOption"]'); const dropdownItems = () => wrapper.findAll(`[data-testid^=${filter.id}]`);
const dropdownItemAt = (index) => dropdownItems().at(index); const dropdownItemAt = (index) => dropdownItems().at(index);
const allOptionItem = () => wrapper.find('[data-testid="allOption"]'); const allOptionItem = () => wrapper.find('[data-testid="allOption"]');
const isChecked = (item) => item.props('isChecked'); const isChecked = (item) => item.props('isChecked');
......
import { GlToggle } from '@gitlab/ui'; import { GlToggle } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import Filters from 'ee/security_dashboard/components/filters.vue'; import Filters from 'ee/security_dashboard/components/filters.vue';
import { pipelineScannerFilter } from 'ee/security_dashboard/helpers';
import createStore from 'ee/security_dashboard/store'; import createStore from 'ee/security_dashboard/store';
import state from 'ee/security_dashboard/store/modules/filters/state';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
...@@ -11,17 +14,16 @@ describe('Filter component', () => { ...@@ -11,17 +14,16 @@ describe('Filter component', () => {
let wrapper; let wrapper;
let store; let store;
const createWrapper = (props = {}) => { const createWrapper = ({ mountFn = shallowMount } = {}) => {
wrapper = shallowMount(Filters, { wrapper = extendedWrapper(
localVue, mountFn(Filters, {
store, localVue,
propsData: { store,
...props, slots: {
}, buttons: '<div class="button-slot"></div>',
slots: { },
buttons: '<div class="button-slot"></div>', }),
}, );
});
}; };
beforeEach(() => { beforeEach(() => {
...@@ -53,4 +55,34 @@ describe('Filter component', () => { ...@@ -53,4 +55,34 @@ describe('Filter component', () => {
expect(wrapper.find('.button-slot').exists()).toBe(true); expect(wrapper.find('.button-slot').exists()).toBe(true);
}); });
}); });
describe('scanner filter', () => {
it('should call the setFilter action with the correct data when the scanner filter is changed', async () => {
const mock = jest.fn();
store = new Vuex.Store({
modules: {
filters: {
namespaced: true,
state,
actions: { setFilter: mock },
},
},
});
createWrapper({ mountFn: mount });
await wrapper.vm.$nextTick();
// The other filters will trigger the mock as well, so we'll clear it before clicking on a
// scanner filter item.
mock.mockClear();
const filterId = pipelineScannerFilter.id;
const optionId = pipelineScannerFilter.options[2].id;
const option = wrapper.findByTestId(`${filterId}:${optionId}`);
option.vm.$emit('click');
await wrapper.vm.$nextTick();
expect(mock).toHaveBeenCalledTimes(1);
expect(mock).toHaveBeenCalledWith(expect.any(Object), { [filterId]: [optionId] });
});
});
}); });
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