Commit 375c56a6 authored by Daniel Tian's avatar Daniel Tian Committed by Vitaly Slobodin

Remove unused vulnerability chart from Vuex vulnerability list

Remove unused vulnerability chart from Vuex vulnerability list, which
is only used on the pipeline security tab
parent cf8034d1
......@@ -11,10 +11,9 @@ import {
} from '~/lib/utils/datetime_utility';
import { formattedChangeInPercent } from '~/lib/utils/number_utils';
import ChartButtons from './vulnerability_chart_buttons.vue';
import { SEVERITY_LEVELS } from '../store/constants';
import { SEVERITY_LEVELS, DAYS } from '../store/constants';
const ISO_DATE = 'isoDate';
const DAYS = { thirty: 30, sixty: 60, ninety: 90 };
export default {
components: {
......
......@@ -4,7 +4,6 @@ import IssueModal from 'ee/vue_shared/security_reports/components/modal.vue';
import Filters from './filters.vue';
import SecurityDashboardLayout from './security_dashboard_layout.vue';
import SecurityDashboardTable from './security_dashboard_table.vue';
import VulnerabilityChart from './vulnerability_chart.vue';
import FuzzingArtifactsDownload from './fuzzing_artifacts_download.vue';
import LoadingError from './loading_error.vue';
......@@ -14,7 +13,6 @@ export default {
IssueModal,
SecurityDashboardLayout,
SecurityDashboardTable,
VulnerabilityChart,
FuzzingArtifactsDownload,
LoadingError,
},
......@@ -23,11 +21,6 @@ export default {
type: String,
required: true,
},
vulnerabilitiesHistoryEndpoint: {
type: String,
required: false,
default: '',
},
pipelineId: {
type: Number,
required: false,
......@@ -67,19 +60,11 @@ export default {
vulnerability() {
return this.modal.vulnerability;
},
shouldShowAside() {
return this.shouldShowChart;
},
shouldShowChart() {
return Boolean(this.vulnerabilitiesHistoryEndpoint);
},
},
created() {
this.setPipelineId(this.pipelineId);
this.setVulnerabilitiesEndpoint(this.vulnerabilitiesEndpoint);
this.setVulnerabilitiesHistoryEndpoint(this.vulnerabilitiesHistoryEndpoint);
this.fetchVulnerabilities({ ...this.filters, page: this.pageInfo.page });
this.fetchVulnerabilitiesHistory(this.filters);
this.fetchPipelineJobs();
},
methods: {
......@@ -91,11 +76,9 @@ export default {
'createMergeRequest',
'dismissVulnerability',
'fetchVulnerabilities',
'fetchVulnerabilitiesHistory',
'openDismissalCommentBox',
'setPipelineId',
'setVulnerabilitiesEndpoint',
'setVulnerabilitiesHistoryEndpoint',
'showDismissalDeleteButtons',
'hideDismissalDeleteButtons',
'undoDismiss',
......@@ -133,10 +116,6 @@ export default {
<slot name="empty-state"></slot>
</template>
</security-dashboard-table>
<template v-if="shouldShowAside" #aside>
<vulnerability-chart v-if="shouldShowChart" class="mb-3" />
</template>
</security-dashboard-layout>
<issue-modal
......
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
import dateFormat from 'dateformat';
import { GlTooltipDirective, GlTable } from '@gitlab/ui';
import { GlSparklineChart } from '@gitlab/ui/dist/charts';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import { s__, sprintf } from '~/locale';
import { firstAndLastY } from '~/lib/utils/chart_utils';
import { formattedChangeInPercent } from '~/lib/utils/number_utils';
import { differenceInMilliseconds, millisecondsPerDay } from '~/lib/utils/datetime_utility';
import ChartButtons from './vulnerability_chart_buttons.vue';
import { DAYS } from '../store/modules/vulnerabilities/constants';
import { SEVERITY_LEVELS } from '../store/constants';
export default {
name: 'VulnerabilityChart',
components: {
ChartButtons,
GlSparklineChart,
GlTable,
SeverityBadge,
},
directives: {
GlTooltip: GlTooltipDirective,
},
DAYS,
fields: [
{ key: 'severityLevel', label: s__('VulnerabilityChart|Severity'), tdClass: 'border-0' },
{ key: 'chartData', label: '', tdClass: 'border-0 w-100' },
{ key: 'changeInPercent', label: '%', thClass: 'text-right', tdClass: 'border-0 text-right' },
{
key: 'currentVulnerabilitiesCount',
label: '#',
thClass: 'text-right',
tdClass: 'border-0 text-right',
},
],
severityLevels: [
SEVERITY_LEVELS.critical,
SEVERITY_LEVELS.high,
SEVERITY_LEVELS.medium,
SEVERITY_LEVELS.low,
],
computed: {
...mapState('vulnerabilities', [
'vulnerabilitiesHistory',
'vulnerabilitiesHistoryDayRange',
'vulnerabilitiesHistoryMaxDayInterval',
]),
...mapGetters('vulnerabilities', ['getFilteredVulnerabilitiesHistory']),
charts() {
const { severityLevels } = this.$options;
return severityLevels.map(severityLevel => {
const history = this.getFilteredVulnerabilitiesHistory(severityLevel);
const chartData = history.length ? history : this.emptyDataSet;
const [pastVulnerabilitiesCount, currentVulnerabilitiesCount] = firstAndLastY(chartData);
const changeInPercent = formattedChangeInPercent(
pastVulnerabilitiesCount,
currentVulnerabilitiesCount,
);
return {
severityLevel,
chartData,
currentVulnerabilitiesCount,
changeInPercent,
};
});
},
startDate() {
return differenceInMilliseconds(millisecondsPerDay * this.vulnerabilitiesHistoryDayRange);
},
dateInfo() {
const formattedStartDate = dateFormat(this.startDate, 'mmmm dS');
return sprintf(s__('VulnerabilityChart|%{formattedStartDate} to today'), {
formattedStartDate,
});
},
days() {
const { $options } = this;
return [$options.DAYS.THIRTY, $options.DAYS.SIXTY, $options.DAYS.NINETY];
},
emptyDataSet() {
const format = 'isoDate';
const formattedStartDate = dateFormat(this.startDate, format);
const formattedEndDate = dateFormat(Date.now(), format);
return [[formattedStartDate, 0], [formattedEndDate, 0]];
},
},
methods: {
...mapActions('vulnerabilities', ['setVulnerabilitiesHistoryDayRange']),
},
};
</script>
<template>
<section class="border rounded p-0">
<div class="p-3">
<header id="vulnerability-chart-header">
<h4 class="my-0">
{{ __('Vulnerabilities over time') }}
</h4>
<p ref="timeInfo" class="text-secondary mt-0 js-vulnerabilities-chart-time-info">
{{ dateInfo }}
</p>
</header>
<chart-buttons
:days="days"
:active-day="vulnerabilitiesHistoryDayRange"
@click="setVulnerabilitiesHistoryDayRange"
/>
</div>
<gl-table
:fields="$options.fields"
:items="charts"
:borderless="true"
thead-class="thead-white"
class="js-vulnerabilities-chart-severity-level-breakdown mb-2"
>
<template #head(changeInPercent)="{ label }">
<span v-gl-tooltip :title="__('Difference between start date and now')">{{ label }}</span>
</template>
<template #head(currentVulnerabilitiesCount)="{ label }">
<span v-gl-tooltip :title="__('Current vulnerabilities count')">{{ label }}</span>
</template>
<template #cell(severityLevel)="{ value }">
<severity-badge :ref="`severityBadge${value}`" :severity="value" />
</template>
<template #cell(chartData)="{ item }">
<div class="position-relative h-32-px">
<gl-sparkline-chart
:ref="`sparklineChart${item.severityLevel}`"
:height="32"
:data="item.chartData"
:tooltip-label="__('Vulnerabilities')"
:show-last-y-value="false"
class="position-absolute w-100 position-top-0 position-left-0"
/>
</div>
</template>
<template #cell(changeInPercent)="{ value }">
<span ref="changeInPercent">{{ value }}</span>
</template>
<template #cell(currentVulnerabilitiesCount)="{ value }">
<span ref="currentVulnerabilitiesCount">{{ value }}</span>
</template>
</gl-table>
</section>
</template>
......@@ -36,3 +36,5 @@ export const UNSCANNED_PROJECTS_DATE_RANGES = [
];
export const PRIMARY_IDENTIFIER_TYPE = 'cve';
export const DAYS = { thirty: 30, sixty: 60, ninety: 90 };
......@@ -477,46 +477,6 @@ export const receiveCreateMergeRequestError = ({ commit }, { flashError }) => {
}
};
export const setVulnerabilitiesHistoryEndpoint = ({ commit }, endpoint) => {
commit(types.SET_VULNERABILITIES_HISTORY_ENDPOINT, endpoint);
};
export const fetchVulnerabilitiesHistory = ({ state, dispatch }, params = {}) => {
if (!state.vulnerabilitiesHistoryEndpoint) {
return;
}
dispatch('requestVulnerabilitiesHistory');
axios({
method: 'GET',
url: state.vulnerabilitiesHistoryEndpoint,
params,
})
.then(response => {
const { data } = response;
dispatch('receiveVulnerabilitiesHistorySuccess', { data });
})
.catch(() => {
dispatch('receiveVulnerabilitiesHistoryError');
});
};
export const setVulnerabilitiesHistoryDayRange = ({ commit }, days) => {
commit(types.SET_VULNERABILITIES_HISTORY_DAY_RANGE, days);
};
export const requestVulnerabilitiesHistory = ({ commit }) => {
commit(types.REQUEST_VULNERABILITIES_HISTORY);
};
export const receiveVulnerabilitiesHistorySuccess = ({ commit }, { data }) => {
commit(types.RECEIVE_VULNERABILITIES_HISTORY_SUCCESS, data);
};
export const receiveVulnerabilitiesHistoryError = ({ commit }) => {
commit(types.RECEIVE_VULNERABILITIES_HISTORY_ERROR);
};
export const openDismissalCommentBox = ({ commit }) => {
commit(types.OPEN_DISMISSAL_COMMENT_BOX);
};
......
......@@ -10,12 +10,6 @@ export {
SEVERITIES,
} from '~/vulnerabilities/constants';
export const DAYS = {
THIRTY: 30,
SIXTY: 60,
NINETY: 90,
};
export const LOADING_VULNERABILITIES_ERROR_CODES = {
UNAUTHORIZED: httpStatusCodes.UNAUTHORIZED,
FORBIDDEN: httpStatusCodes.FORBIDDEN,
......
......@@ -13,29 +13,6 @@ export const loadingVulnerabilitiesFailedWithRecognizedErrorCode = state =>
state.loadingVulnerabilitiesErrorCode,
);
export const getVulnerabilityHistoryByName = state => name =>
state.vulnerabilitiesHistory[name.toLowerCase()];
export const getFilteredVulnerabilitiesHistory = (state, getters) => name => {
const history = getters.getVulnerabilityHistoryByName(name);
const days = state.vulnerabilitiesHistoryDayRange;
if (!history) {
return [];
}
const data = Object.entries(history);
const currentDate = new Date();
const startDate = new Date();
startDate.setDate(currentDate.getDate() - days);
return data.filter(date => {
const parsedDate = Date.parse(date[0]);
return parsedDate > startDate;
});
};
export const selectedVulnerabilitiesCount = state =>
Object.keys(state.selectedVulnerabilities).length;
......
......@@ -6,12 +6,6 @@ export const REQUEST_VULNERABILITIES = 'REQUEST_VULNERABILITIES';
export const RECEIVE_VULNERABILITIES_SUCCESS = 'RECEIVE_VULNERABILITIES_SUCCESS';
export const RECEIVE_VULNERABILITIES_ERROR = 'RECEIVE_VULNERABILITIES_ERROR';
export const SET_VULNERABILITIES_HISTORY_ENDPOINT = 'SET_VULNERABILITIES_HISTORY_ENDPOINT';
export const SET_VULNERABILITIES_HISTORY_DAY_RANGE = 'SET_VULNERABILITIES_HISTORY_DAY_RANGE';
export const REQUEST_VULNERABILITIES_HISTORY = 'REQUEST_VULNERABILITIES_HISTORY';
export const RECEIVE_VULNERABILITIES_HISTORY_SUCCESS = 'RECEIVE_VULNERABILITIES_HISTORY_SUCCESS';
export const RECEIVE_VULNERABILITIES_HISTORY_ERROR = 'RECEIVE_VULNERABILITIES_HISTORY_ERROR';
export const SET_MODAL_DATA = 'SET_MODAL_DATA';
export const REQUEST_CREATE_ISSUE = 'REQUEST_CREATE_ISSUE';
......
......@@ -2,7 +2,6 @@ import Vue from 'vue';
import { s__, __ } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import * as types from './mutation_types';
import { DAYS } from './constants';
import { isSameVulnerability } from './utils';
export default {
......@@ -34,30 +33,6 @@ export default {
[types.SET_VULNERABILITIES_PAGE](state, payload) {
state.pageInfo = { ...state.pageInfo, page: payload };
},
[types.SET_VULNERABILITIES_HISTORY_ENDPOINT](state, payload) {
state.vulnerabilitiesHistoryEndpoint = payload;
},
[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, days) {
state.vulnerabilitiesHistoryDayRange = days;
if (days <= DAYS.THIRTY) {
state.vulnerabilitiesHistoryMaxDayInterval = 7;
} else if (days > DAYS.SIXTY) {
state.vulnerabilitiesHistoryMaxDayInterval = 14;
}
},
[types.REQUEST_VULNERABILITIES_HISTORY](state) {
state.isLoadingVulnerabilitiesHistory = true;
state.errorLoadingVulnerabilitiesHistory = false;
},
[types.RECEIVE_VULNERABILITIES_HISTORY_SUCCESS](state, payload) {
state.isLoadingVulnerabilitiesHistory = false;
state.vulnerabilitiesHistory = payload;
},
[types.RECEIVE_VULNERABILITIES_HISTORY_ERROR](state) {
state.isLoadingVulnerabilitiesHistory = false;
state.errorLoadingVulnerabilitiesHistory = true;
},
[types.SET_MODAL_DATA](state, payload) {
const { vulnerability } = payload;
......
......@@ -5,14 +5,8 @@ export default () => ({
vulnerabilities: [],
errorLoadingVulnerabilitiesCount: false,
vulnerabilitiesCount: {},
isLoadingVulnerabilitiesHistory: true,
errorLoadingVulnerabilitiesHistory: false,
vulnerabilitiesHistory: {},
vulnerabilitiesHistoryDayRange: 90,
vulnerabilitiesHistoryMaxDayInterval: 7,
pageInfo: {},
pipelineId: null,
vulnerabilitiesHistoryEndpoint: null,
vulnerabilitiesEndpoint: null,
activeVulnerability: null,
sourceBranch: null,
......
......@@ -5,7 +5,6 @@ const refreshTypes = [`filters/${SET_FILTER}`, `filters/${SET_HIDE_DISMISSED}`];
export default store => {
const refreshVulnerabilities = payload => {
store.dispatch('vulnerabilities/fetchVulnerabilities', payload);
store.dispatch('vulnerabilities/fetchVulnerabilitiesHistory', payload);
};
store.subscribe(({ type }) => {
......
......@@ -6,7 +6,6 @@ import LoadingError from 'ee/security_dashboard/components/loading_error.vue';
import SecurityDashboardLayout from 'ee/security_dashboard/components/security_dashboard_layout.vue';
import SecurityDashboardTable from 'ee/security_dashboard/components/security_dashboard_table.vue';
import SecurityDashboard from 'ee/security_dashboard/components/security_dashboard_vuex.vue';
import VulnerabilityChart from 'ee/security_dashboard/components/vulnerability_chart.vue';
import createStore from 'ee/security_dashboard/store';
import IssueModal from 'ee/vue_shared/security_reports/components/modal.vue';
......@@ -15,7 +14,6 @@ import axios from '~/lib/utils/axios_utils';
const pipelineId = 123;
const vulnerabilitiesEndpoint = `${TEST_HOST}/vulnerabilities`;
const vulnerabilitiesHistoryEndpoint = `${TEST_HOST}/vulnerabilities_history`;
jest.mock('~/lib/utils/url_utility', () => ({
getParameterValues: jest.fn().mockReturnValue([]),
......@@ -41,7 +39,6 @@ describe('Security Dashboard component', () => {
propsData: {
dashboardDocumentation: '',
vulnerabilitiesEndpoint,
vulnerabilitiesHistoryEndpoint,
pipelineId,
...props,
},
......@@ -75,10 +72,6 @@ describe('Security Dashboard component', () => {
expect(wrapper.find(SecurityDashboardTable).exists()).toBe(true);
});
it('renders the vulnerability chart', () => {
expect(wrapper.find(VulnerabilityChart).exists()).toBe(true);
});
it('sets the pipeline id', () => {
expect(setPipelineIdSpy).toHaveBeenCalledWith(pipelineId);
});
......@@ -143,21 +136,6 @@ describe('Security Dashboard component', () => {
);
});
describe.each`
endpointProp | Component
${'vulnerabilitiesHistoryEndpoint'} | ${VulnerabilityChart}
`('with an empty $endpointProp', ({ endpointProp, Component }) => {
beforeEach(() => {
createComponent({
[endpointProp]: '',
});
});
it(`does not show the ${Component.name}`, () => {
expect(wrapper.find(Component).exists()).toBe(false);
});
});
describe('on error', () => {
beforeEach(() => {
createComponent();
......
import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import Vue from 'vue';
import component from 'ee/security_dashboard/components/vulnerability_chart_buttons.vue';
import { DAYS } from 'ee/security_dashboard/store/modules/vulnerabilities/constants';
import { DAYS } from 'ee/security_dashboard/store/constants';
const localVue = createLocalVue();
describe('Vulnerability Chart Buttons', () => {
let wrapper;
const Component = Vue.extend(component);
const days = [DAYS.THIRTY, DAYS.SIXTY, DAYS.NINETY];
const days = Object.values(DAYS);
const createWrapper = (props = {}, mountfn = shallowMount) => {
wrapper = mountfn(localVue.extend(Component), {
......@@ -23,7 +23,7 @@ describe('Vulnerability Chart Buttons', () => {
describe('when rendering the buttons', () => {
it('should render with 90 days selected', () => {
const activeDay = DAYS.NINETY;
const activeDay = DAYS.ninety;
createWrapper({ activeDay });
const activeButton = wrapper.find('[data-days="90"].active');
......@@ -32,7 +32,7 @@ describe('Vulnerability Chart Buttons', () => {
});
it('should render with 60 days selected', () => {
const activeDay = DAYS.SIXTY;
const activeDay = DAYS.sixty;
createWrapper({ activeDay });
const activeButton = wrapper.find('[data-days="60"].active');
......@@ -41,7 +41,7 @@ describe('Vulnerability Chart Buttons', () => {
});
it('should render with 30 days selected', () => {
const activeDay = DAYS.THIRTY;
const activeDay = DAYS.thirty;
createWrapper({ activeDay });
const activeButton = wrapper.find('[data-days="30"].active');
......@@ -51,7 +51,7 @@ describe('Vulnerability Chart Buttons', () => {
});
describe('when clicking the button', () => {
const activeDay = DAYS.THIRTY;
const activeDay = DAYS.thirty;
beforeEach(() => {
createWrapper({ activeDay }, mount);
......@@ -59,15 +59,15 @@ describe('Vulnerability Chart Buttons', () => {
it('should call the clickHandler', () => {
jest.spyOn(wrapper.vm, 'clickHandler');
wrapper.find('[data-days="30"].active').trigger('click', DAYS.THIRTY);
wrapper.find('[data-days="30"].active').trigger('click', DAYS.thirty);
expect(wrapper.vm.clickHandler).toHaveBeenCalledWith(DAYS.THIRTY);
expect(wrapper.vm.clickHandler).toHaveBeenCalledWith(DAYS.thirty);
});
it('should emit a click event', () => {
wrapper.find('[data-days="30"].active').trigger('click', DAYS.THIRTY);
wrapper.find('[data-days="30"].active').trigger('click', DAYS.thirty);
expect(wrapper.emitted().click[0]).toEqual([DAYS.THIRTY]);
expect(wrapper.emitted().click[0]).toEqual([DAYS.thirty]);
});
});
});
import { GlSparklineChart } from '@gitlab/ui/dist/charts';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import Chart from 'ee/security_dashboard/components/vulnerability_chart.vue';
import ChartButtons from 'ee/security_dashboard/components/vulnerability_chart_buttons.vue';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import stubChildren from 'helpers/stub_children';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Vulnerability Chart component', () => {
let actions;
let getters;
let state;
let store;
let wrapper;
const findTimeInfo = () => wrapper.find({ ref: 'timeInfo' });
const findSeverityBadgeForLevel = severityLevel =>
wrapper.find(SeverityBadge, { ref: `severityBadge${severityLevel}` });
const findSparklineChartForLevel = severityLevel =>
wrapper.find(GlSparklineChart, { ref: `sparklineChart${severityLevel}` });
const findChangeInPercent = () => wrapper.find({ ref: 'changeInPercent' });
const findCurrentVulnerabilitiesCount = () =>
wrapper.find({ ref: 'currentVulnerabilitiesCount' });
const factory = ({ vulnerabilitiesCount = [], stubs = {} } = {}) => {
actions = {
setVulnerabilitiesHistoryDayRange: jest.fn(),
};
getters = {
getFilteredVulnerabilitiesHistory: () => () =>
vulnerabilitiesCount.map(c => ['some-date', c]),
getVulnerabilityHistoryByName: () => () => [],
};
state = {
vulnerabilitiesHistory: {},
vulnerabilitiesHistoryDayRange: 90,
vulnerabilitiesHistoryMaxDayInterval: 7,
};
store = new Vuex.Store({
modules: {
vulnerabilities: {
namespaced: true,
actions,
getters,
state,
},
},
});
wrapper = mount(Chart, {
localVue,
store,
stubs: {
...stubChildren(Chart),
...stubs,
},
});
};
afterEach(() => {
wrapper.destroy();
jest.restoreAllMocks();
});
describe('header', () => {
it.each`
mockDate | dayRange | expectedStartDate
${'2000-01-01T00:00:00Z'} | ${90} | ${'October 3rd'}
${'2000-01-01T00:00:00Z'} | ${60} | ${'November 2nd'}
${'2000-01-01T00:00:00Z'} | ${30} | ${'December 2nd'}
`(
'shows "$expectedStartDate" when the date range is set to "$dayRange" days',
({ mockDate, dayRange, expectedStartDate }) => {
jest.spyOn(global.Date, 'now').mockImplementation(() => new Date(mockDate));
factory();
store.state.vulnerabilities.vulnerabilitiesHistoryDayRange = dayRange;
return wrapper.vm.$nextTick().then(() => {
expect(findTimeInfo().text()).toContain(expectedStartDate);
});
},
);
});
describe('date range selectors', () => {
beforeEach(factory);
it('shows a set of buttons to select the supported day ranges', () => {
const supportedDayRanges = [30, 60, 90];
expect(wrapper.find(ChartButtons).props('days')).toEqual(supportedDayRanges);
});
it('dispatches "setVulnerabilitiesHistoryDayRange" when a day range is selected', () => {
const selectedDayRange = 30;
wrapper.find(ChartButtons).vm.$emit('click', selectedDayRange);
expect(actions.setVulnerabilitiesHistoryDayRange).toHaveBeenCalledTimes(1);
expect(actions.setVulnerabilitiesHistoryDayRange.mock.calls[0][1]).toBe(selectedDayRange);
});
});
describe('charts table', () => {
describe.each(['Critical', 'Medium', 'High', 'Low'])(
'for the given severity level "%s"',
severityLevel => {
beforeEach(() => {
factory({ stubs: { GlTable: false } });
});
it('shows a severity badge', () => {
expect(findSeverityBadgeForLevel(severityLevel).exists()).toBe(true);
});
it('shows a chart', () => {
expect(findSparklineChartForLevel(severityLevel).exists()).toBe(true);
});
},
);
it.each`
countPast | countCurrent | expectedOutput
${1} | ${2} | ${'+100%'}
${100} | ${1} | ${'-99%'}
${1} | ${1} | ${'+0%'}
${0} | ${1} | ${'-'}
`(
'shows "$expectedOutput" when the vulnerabilities changed from "$countPast" to "$countCurrent"',
({ countPast, countCurrent, expectedOutput }) => {
factory({
vulnerabilitiesCount: [countPast, countCurrent],
stubs: {
GlTable: false,
},
});
expect(findChangeInPercent().text()).toBe(expectedOutput);
},
);
it.each`
vulnerabilitiesCount | expectedOutput
${[1, 2, 3]} | ${'3'}
`('shows the current vulnerabilities count', ({ vulnerabilitiesCount, expectedOutput }) => {
factory({ vulnerabilitiesCount, stubs: { GlTable: false } });
expect(findCurrentVulnerabilitiesCount().text()).toBe(expectedOutput);
});
});
});
import { DAYS } from 'ee/security_dashboard/store/modules/vulnerabilities/constants';
import * as getters from 'ee/security_dashboard/store/modules/vulnerabilities/getters';
import createState from 'ee/security_dashboard/store/modules/vulnerabilities/state';
import mockHistoryData from './data/mock_data_vulnerabilities_history.json';
describe('vulnerabilities module getters', () => {
describe('dashboardError', () => {
......@@ -57,55 +54,6 @@ describe('vulnerabilities module getters', () => {
});
});
describe('getFilteredVulnerabilitiesHistory', () => {
let state;
const mockedGetters = () => {
const getVulnerabilityHistoryByName = name =>
getters.getVulnerabilityHistoryByName(state)(name);
return { getVulnerabilityHistoryByName };
};
beforeEach(() => {
state = createState();
state.vulnerabilitiesHistory = mockHistoryData;
const mockDate = new Date(2019, 1, 2);
const originalDate = Date;
jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
global.Date.now = originalDate.now;
global.Date.parse = originalDate.parse;
global.Date.UTC = originalDate.UTC;
});
it('should filter the data to the last 30 days and days we have data for', () => {
state.vulnerabilitiesHistoryDayRange = DAYS.THIRTY;
const filteredResults = getters.getFilteredVulnerabilitiesHistory(state, mockedGetters())(
'critical',
);
expect(filteredResults).toHaveLength(28);
});
it('should filter the data to the last 60 days and days we have data for', () => {
state.vulnerabilitiesHistoryDayRange = DAYS.SIXTY;
const filteredResults = getters.getFilteredVulnerabilitiesHistory(state, mockedGetters())(
'critical',
);
expect(filteredResults).toHaveLength(58);
});
it('should filter the data to the last 90 days and days we have data for', () => {
state.vulnerabilitiesHistoryDayRange = DAYS.NINETY;
const filteredResults = getters.getFilteredVulnerabilitiesHistory(state, mockedGetters())(
'critical',
);
expect(filteredResults).toHaveLength(88);
});
});
describe('isSelectingVulnerabilities', () => {
it('should return true if we have selected vulnerabilities', () => {
const mockedGetters = { selectedVulnerabilitiesCount: 3 };
......
import { DAYS } from 'ee/security_dashboard/store/modules/vulnerabilities/constants';
import * as types from 'ee/security_dashboard/store/modules/vulnerabilities/mutation_types';
import mutations from 'ee/security_dashboard/store/modules/vulnerabilities/mutations';
import createState from 'ee/security_dashboard/store/modules/vulnerabilities/state';
......@@ -113,76 +112,6 @@ describe('vulnerabilities module mutations', () => {
});
});
describe('SET_VULNERABILITIES_HISTORY_ENDPOINT', () => {
it('should set `vulnerabilitiesHistoryEndpoint` to `fakepath.json`', () => {
const endpoint = 'fakepath.json';
mutations[types.SET_VULNERABILITIES_HISTORY_ENDPOINT](state, endpoint);
expect(state.vulnerabilitiesHistoryEndpoint).toBe(endpoint);
});
});
describe('REQUEST_VULNERABILITIES_HISTORY', () => {
beforeEach(() => {
state.errorLoadingVulnerabilitiesHistory = true;
mutations[types.REQUEST_VULNERABILITIES_HISTORY](state);
});
it('should set `isLoadingVulnerabilitiesHistory` to `true`', () => {
expect(state.isLoadingVulnerabilitiesHistory).toBeTruthy();
});
it('should set `errorLoadingVulnerabilitiesHistory` to `false`', () => {
expect(state.errorLoadingVulnerabilitiesHistory).toBeFalsy();
});
});
describe('RECEIVE_VULNERABILITIES_HISTORY_SUCCESS', () => {
let payload;
beforeEach(() => {
payload = mockData;
mutations[types.RECEIVE_VULNERABILITIES_HISTORY_SUCCESS](state, payload);
});
it('should set `isLoadingVulnerabilitiesHistory` to `false`', () => {
expect(state.isLoadingVulnerabilitiesHistory).toBeFalsy();
});
it('should set `vulnerabilitiesHistory`', () => {
expect(state.vulnerabilitiesHistory).toBe(payload);
});
});
describe('RECEIVE_VULNERABILITIES_HISTORY_ERROR', () => {
it('should set `isLoadingVulnerabilitiesHistory` to `false`', () => {
mutations[types.RECEIVE_VULNERABILITIES_HISTORY_ERROR](state);
expect(state.isLoadingVulnerabilitiesHistory).toBeFalsy();
});
});
describe('SET_VULNERABILITIES_HISTORY_DAY_RANGE', () => {
it('should set the vulnerabilitiesHistoryDayRange to number of days', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.THIRTY);
expect(state.vulnerabilitiesHistoryDayRange).toBe(DAYS.THIRTY);
});
it('should set the vulnerabilitiesHistoryMaxDayInterval to 7 if days are 60 and under', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.THIRTY);
expect(state.vulnerabilitiesHistoryMaxDayInterval).toBe(7);
});
it('should set the vulnerabilitiesHistoryMaxDayInterval to 14 if over 60', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.NINETY);
expect(state.vulnerabilitiesHistoryMaxDayInterval).toBe(14);
});
});
describe('SET_MODAL_DATA', () => {
describe('with all the data', () => {
const vulnerability = mockData[0];
......
......@@ -5,12 +5,8 @@ import {
} from 'ee/security_dashboard/store/modules/filters/mutation_types';
function expectRefreshDispatches(store, payload) {
expect(store.dispatch).toHaveBeenCalledTimes(2);
expect(store.dispatch).toHaveBeenCalledTimes(1);
expect(store.dispatch).toHaveBeenCalledWith('vulnerabilities/fetchVulnerabilities', payload);
expect(store.dispatch).toHaveBeenCalledWith(
'vulnerabilities/fetchVulnerabilitiesHistory',
payload,
);
}
describe('mediator', () => {
......
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