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 MockAdapter from 'axios-mock-adapter';
import * as actions from 'ee/security_dashboard/store/modules/vulnerabilities/actions';
import { DAYS } from 'ee/security_dashboard/store/modules/vulnerabilities/constants';
import * as types from 'ee/security_dashboard/store/modules/vulnerabilities/mutation_types';
import initialState from 'ee/security_dashboard/store/modules/vulnerabilities/state';
import testAction from 'helpers/vuex_action_helper';
......@@ -10,7 +9,6 @@ import axios from '~/lib/utils/axios_utils';
import toast from '~/vue_shared/plugins/global_toast';
import mockDataVulnerabilities from './data/mock_data_vulnerabilities';
import mockDataVulnerabilitiesHistory from './data/mock_data_vulnerabilities_history.json';
const sourceBranch = 'feature-branch-1';
......@@ -34,38 +32,24 @@ describe('vulnerabilities count actions', () => {
describe('setPipelineId', () => {
const pipelineId = 123;
it('should commit the correct mutation', done => {
testAction(
actions.setPipelineId,
pipelineId,
state,
[
it('should commit the correct mutation', () => {
return testAction(actions.setPipelineId, pipelineId, state, [
{
type: types.SET_PIPELINE_ID,
payload: pipelineId,
},
],
[],
done,
);
]);
});
});
describe('setSourceBranch', () => {
it('should commit the correct mutation', done => {
testAction(
actions.setSourceBranch,
sourceBranch,
state,
[
it('should commit the correct mutation', () => {
return testAction(actions.setSourceBranch, sourceBranch, state, [
{
type: types.SET_SOURCE_BRANCH,
payload: sourceBranch,
},
],
[],
done,
);
]);
});
});
});
......@@ -117,8 +101,8 @@ describe('vulnerabilities actions', () => {
.replyOnce(200, data, headers);
});
it('should dispatch the request and success actions', done => {
testAction(
it('should dispatch the request and success actions', () => {
return testAction(
actions.fetchVulnerabilities,
{},
state,
......@@ -130,12 +114,11 @@ describe('vulnerabilities actions', () => {
payload: { data, headers },
},
],
done,
);
});
it('should pass through the filters', done => {
testAction(
it('should pass through the filters', () => {
return testAction(
actions.fetchVulnerabilities,
params,
state,
......@@ -147,7 +130,6 @@ describe('vulnerabilities actions', () => {
payload: { data: filteredData, headers },
},
],
done,
);
});
});
......@@ -159,8 +141,8 @@ describe('vulnerabilities actions', () => {
mock.onGet(state.vulnerabilitiesEndpoint).replyOnce(errorCode, {});
});
it('should dispatch the request and error actions', done => {
testAction(
it('should dispatch the request and error actions', () => {
return testAction(
actions.fetchVulnerabilities,
{},
state,
......@@ -169,7 +151,6 @@ describe('vulnerabilities actions', () => {
{ type: 'requestVulnerabilities' },
{ type: 'receiveVulnerabilitiesError', payload: errorCode },
],
done,
);
});
});
......@@ -179,95 +160,64 @@ describe('vulnerabilities actions', () => {
state.vulnerabilitiesEndpoint = '';
});
it('should not do anything', done => {
testAction(actions.fetchVulnerabilities, {}, state, [], [], done);
it('should not do anything', () => {
return testAction(actions.fetchVulnerabilities, {}, state);
});
});
});
describe('receiveVulnerabilitiesSuccess', () => {
it('should commit the success mutation', done => {
testAction(
actions.receiveVulnerabilitiesSuccess,
{ headers, data },
state,
[
it('should commit the success mutation', () => {
return testAction(actions.receiveVulnerabilitiesSuccess, { headers, data }, state, [
{
type: types.RECEIVE_VULNERABILITIES_SUCCESS,
payload: { pageInfo, vulnerabilities: data },
},
],
[],
done,
);
]);
});
});
describe('receiveVulnerabilitiesError', () => {
it('should commit the error mutation', done => {
it('should commit the error mutation', () => {
const errorCode = 403;
testAction(
actions.receiveVulnerabilitiesError,
errorCode,
state,
[{ type: types.RECEIVE_VULNERABILITIES_ERROR, payload: errorCode }],
[],
done,
);
return testAction(actions.receiveVulnerabilitiesError, errorCode, state, [
{ type: types.RECEIVE_VULNERABILITIES_ERROR, payload: errorCode },
]);
});
});
describe('requestVulnerabilities', () => {
it('should commit the request mutation', done => {
testAction(
actions.requestVulnerabilities,
{},
state,
[{ type: types.REQUEST_VULNERABILITIES }],
[],
done,
);
it('should commit the request mutation', () => {
return testAction(actions.requestVulnerabilities, {}, state, [
{ type: types.REQUEST_VULNERABILITIES },
]);
});
});
describe('setVulnerabilitiesEndpoint', () => {
it('should commit the correct mutuation', done => {
it('should commit the correct mutuation', () => {
const endpoint = 'fakepath.json';
testAction(
actions.setVulnerabilitiesEndpoint,
endpoint,
state,
[
return testAction(actions.setVulnerabilitiesEndpoint, endpoint, state, [
{
type: types.SET_VULNERABILITIES_ENDPOINT,
payload: endpoint,
},
],
[],
done,
);
]);
});
});
describe('setVulnerabilitiesPage', () => {
it('should commit the correct mutuation', done => {
it('should commit the correct mutuation', () => {
const page = 3;
testAction(
actions.setVulnerabilitiesPage,
page,
state,
[
return testAction(actions.setVulnerabilitiesPage, page, state, [
{
type: types.SET_VULNERABILITIES_PAGE,
payload: page,
},
],
[],
done,
);
]);
});
});
});
......@@ -279,22 +229,15 @@ describe('openModal', () => {
state = initialState();
});
it('should commit the SET_MODAL_DATA mutation', done => {
it('should commit the SET_MODAL_DATA mutation', () => {
const vulnerability = mockDataVulnerabilities[0];
testAction(
actions.openModal,
{ vulnerability },
state,
[
return testAction(actions.openModal, { vulnerability }, state, [
{
type: types.SET_MODAL_DATA,
payload: { vulnerability },
},
],
[],
done,
);
]);
});
});
......@@ -352,8 +295,8 @@ describe('issue creation', () => {
.replyOnce(200, { data });
});
it('should dispatch the request and success actions', done => {
testAction(
it('should dispatch the request and success actions', () => {
return testAction(
actions.createIssue,
{ vulnerability },
{},
......@@ -365,7 +308,6 @@ describe('issue creation', () => {
payload: { data },
},
],
done,
);
});
});
......@@ -375,10 +317,10 @@ describe('issue creation', () => {
mock.onPost(vulnerability.create_vulnerability_feedback_issue_path).replyOnce(404, {});
});
it('should dispatch the request and error actions', done => {
it('should dispatch the request and error actions', () => {
const flashError = false;
testAction(
return testAction(
actions.createIssue,
{ vulnerability, flashError },
{},
......@@ -387,55 +329,37 @@ describe('issue creation', () => {
{ type: 'requestCreateIssue' },
{ type: 'receiveCreateIssueError', payload: { flashError } },
],
done,
);
});
});
});
describe('receiveCreateIssueSuccess', () => {
it('should commit the success mutation', done => {
it('should commit the success mutation', () => {
const data = mockDataVulnerabilities[0];
testAction(
actions.receiveCreateIssueSuccess,
{ data },
state,
[
return testAction(actions.receiveCreateIssueSuccess, { data }, state, [
{
type: types.RECEIVE_CREATE_ISSUE_SUCCESS,
payload: { data },
},
],
[],
done,
);
]);
});
});
describe('receiveCreateIssueError', () => {
it('should commit the error mutation', done => {
testAction(
actions.receiveCreateIssueError,
{},
state,
[{ type: types.RECEIVE_CREATE_ISSUE_ERROR }],
[],
done,
);
it('should commit the error mutation', () => {
return testAction(actions.receiveCreateIssueError, {}, state, [
{ type: types.RECEIVE_CREATE_ISSUE_ERROR },
]);
});
});
describe('requestCreateIssue', () => {
it('should commit the request mutation', done => {
testAction(
actions.requestCreateIssue,
{},
state,
[{ type: types.REQUEST_CREATE_ISSUE }],
[],
done,
);
it('should commit the request mutation', () => {
return testAction(actions.requestCreateIssue, {}, state, [
{ type: types.REQUEST_CREATE_ISSUE },
]);
});
});
});
......@@ -467,8 +391,8 @@ describe('merge request creation', () => {
.replyOnce(200, { data });
});
it('should dispatch the request and success actions', done => {
testAction(
it('should dispatch the request and success actions', () => {
return testAction(
actions.createMergeRequest,
{ vulnerability },
{},
......@@ -480,7 +404,6 @@ describe('merge request creation', () => {
payload: { data },
},
],
done,
);
});
});
......@@ -490,10 +413,10 @@ describe('merge request creation', () => {
mock.onPost(vulnerability.vulnerability_feedback_merge_request_path).replyOnce(404, {});
});
it('should dispatch the request and error actions', done => {
it('should dispatch the request and error actions', () => {
const flashError = false;
testAction(
return testAction(
actions.createMergeRequest,
{ vulnerability, flashError },
{},
......@@ -502,55 +425,37 @@ describe('merge request creation', () => {
{ type: 'requestCreateMergeRequest' },
{ type: 'receiveCreateMergeRequestError', payload: { flashError } },
],
done,
);
});
});
});
describe('receiveCreateMergeRequestSuccess', () => {
it('should commit the success mutation', done => {
it('should commit the success mutation', () => {
const data = mockDataVulnerabilities[0];
testAction(
actions.receiveCreateMergeRequestSuccess,
{ data },
state,
[
return testAction(actions.receiveCreateMergeRequestSuccess, { data }, state, [
{
type: types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS,
payload: { data },
},
],
[],
done,
);
]);
});
});
describe('receiveCreateMergeRequestError', () => {
it('should commit the error mutation', done => {
testAction(
actions.receiveCreateMergeRequestError,
{},
state,
[{ type: types.RECEIVE_CREATE_MERGE_REQUEST_ERROR }],
[],
done,
);
it('should commit the error mutation', () => {
return testAction(actions.receiveCreateMergeRequestError, {}, state, [
{ type: types.RECEIVE_CREATE_MERGE_REQUEST_ERROR },
]);
});
});
describe('requestCreateMergeRequest', () => {
it('should commit the request mutation', done => {
testAction(
actions.requestCreateMergeRequest,
{},
state,
[{ type: types.REQUEST_CREATE_MERGE_REQUEST }],
[],
done,
);
it('should commit the request mutation', () => {
return testAction(actions.requestCreateMergeRequest, {}, state, [
{ type: types.REQUEST_CREATE_MERGE_REQUEST },
]);
});
});
});
......@@ -584,8 +489,8 @@ describe('vulnerability dismissal', () => {
.replyOnce(200, data);
});
it('should dispatch the request and success actions', done => {
testAction(
it('should dispatch the request and success actions', () => {
return testAction(
actions.dismissVulnerability,
{ vulnerability, comment },
{},
......@@ -598,17 +503,15 @@ describe('vulnerability dismissal', () => {
payload: { data, vulnerability },
},
],
done,
);
});
it('should show the dismissal toast message', done => {
it('should show the dismissal toast message', () => {
const checkToastMessage = () => {
expect(toast).toHaveBeenCalledTimes(1);
done();
};
testAction(
return testAction(
actions.dismissVulnerability,
{ vulnerability, comment },
{},
......@@ -631,10 +534,10 @@ describe('vulnerability dismissal', () => {
mock.onPost(vulnerability.create_vulnerability_feedback_dismissal_path).replyOnce(404, {});
});
it('should dispatch the request and error actions', done => {
it('should dispatch the request and error actions', () => {
const flashError = false;
testAction(
return testAction(
actions.dismissVulnerability,
{ vulnerability, flashError },
{},
......@@ -643,7 +546,6 @@ describe('vulnerability dismissal', () => {
{ type: 'requestDismissVulnerability' },
{ type: 'receiveDismissVulnerabilityError', payload: { flashError } },
],
done,
);
});
});
......@@ -661,17 +563,16 @@ describe('vulnerability dismissal', () => {
.replyOnce(200, data);
});
it('should show the dismissal toast message and refresh vulnerabilities', done => {
it('should show the dismissal toast message and refresh vulnerabilities', () => {
const checkToastMessage = () => {
const [message, options] = toast.mock.calls[0];
expect(toast).toHaveBeenCalledTimes(1);
expect(message).toContain('Turn off the hide dismissed toggle to view');
expect(Object.keys(options.action)).toHaveLength(2);
done();
};
testAction(
return testAction(
actions.dismissVulnerability,
{ vulnerability, comment },
state,
......@@ -693,7 +594,7 @@ describe('vulnerability dismissal', () => {
state.vulnerabilities = [mockDataVulnerabilities[0]];
state.pageInfo.page = 3;
testAction(
return testAction(
actions.dismissVulnerability,
{ vulnerability, comment },
state,
......@@ -713,48 +614,31 @@ describe('vulnerability dismissal', () => {
});
describe('receiveDismissVulnerabilitySuccess', () => {
it('should commit the success mutation', done => {
it('should commit the success mutation', () => {
const data = mockDataVulnerabilities[0];
testAction(
actions.receiveDismissVulnerabilitySuccess,
{ data },
state,
[
return testAction(actions.receiveDismissVulnerabilitySuccess, { data }, state, [
{
type: types.RECEIVE_DISMISS_VULNERABILITY_SUCCESS,
payload: { data },
},
],
[],
done,
);
]);
});
});
describe('receiveDismissVulnerabilityError', () => {
it('should commit the error mutation', done => {
testAction(
actions.receiveDismissVulnerabilityError,
{},
state,
[{ type: types.RECEIVE_DISMISS_VULNERABILITY_ERROR }],
[],
done,
);
it('should commit the error mutation', () => {
return testAction(actions.receiveDismissVulnerabilityError, {}, state, [
{ type: types.RECEIVE_DISMISS_VULNERABILITY_ERROR },
]);
});
});
describe('requestDismissVulnerability', () => {
it('should commit the request mutation', done => {
testAction(
actions.requestDismissVulnerability,
{},
state,
[{ type: types.REQUEST_DISMISS_VULNERABILITY }],
[],
done,
);
it('should commit the request mutation', () => {
return testAction(actions.requestDismissVulnerability, {}, state, [
{ type: types.REQUEST_DISMISS_VULNERABILITY },
]);
});
});
});
......@@ -786,17 +670,16 @@ describe('add vulnerability dismissal comment', () => {
mock.onPatch(url).replyOnce(200, data);
});
it('should dispatch the request and success actions', done => {
it('should dispatch the request and success actions', () => {
const checkPassedData = () => {
const { project_id, id } = vulnerability.dismissal_feedback;
const expected = JSON.stringify({ project_id, id, comment });
expect(mock.history.patch[0].data).toBe(expected);
expect(toast).toHaveBeenCalledTimes(1);
done();
};
testAction(
return testAction(
actions.addDismissalComment,
{ vulnerability, comment },
{},
......@@ -810,17 +693,16 @@ describe('add vulnerability dismissal comment', () => {
);
});
it('should show the add dismissal toast message', done => {
it('should show the add dismissal toast message', () => {
const checkPassedData = () => {
const { project_id, id } = vulnerability.dismissal_feedback;
const expected = JSON.stringify({ project_id, id, comment });
expect(mock.history.patch[0].data).toBe(expected);
expect(toast).toHaveBeenCalledTimes(1);
done();
};
testAction(
return testAction(
actions.addDismissalComment,
{ vulnerability, comment },
{},
......@@ -840,54 +722,38 @@ describe('add vulnerability dismissal comment', () => {
mock.onPatch(url).replyOnce(404);
});
it('should dispatch the request and error actions', done => {
testAction(
it('should dispatch the request and error actions', () => {
return testAction(
actions.addDismissalComment,
{ vulnerability, comment },
{},
[],
[{ type: 'requestAddDismissalComment' }, { type: 'receiveAddDismissalCommentError' }],
done,
);
});
});
describe('receiveAddDismissalCommentSuccess', () => {
it('should commit the success mutation', done => {
testAction(
actions.receiveAddDismissalCommentSuccess,
{ data },
state,
[{ type: types.RECEIVE_ADD_DISMISSAL_COMMENT_SUCCESS, payload: { data } }],
[],
done,
);
it('should commit the success mutation', () => {
return testAction(actions.receiveAddDismissalCommentSuccess, { data }, state, [
{ type: types.RECEIVE_ADD_DISMISSAL_COMMENT_SUCCESS, payload: { data } },
]);
});
});
describe('receiveAddDismissalCommentError', () => {
it('should commit the error mutation', done => {
testAction(
actions.receiveAddDismissalCommentError,
{},
state,
[{ type: types.RECEIVE_ADD_DISMISSAL_COMMENT_ERROR }],
[],
done,
);
it('should commit the error mutation', () => {
return testAction(actions.receiveAddDismissalCommentError, {}, state, [
{ type: types.RECEIVE_ADD_DISMISSAL_COMMENT_ERROR },
]);
});
});
describe('requestAddDismissalComment', () => {
it('should commit the request mutation', done => {
testAction(
actions.requestAddDismissalComment,
{},
state,
[{ type: types.REQUEST_ADD_DISMISSAL_COMMENT }],
[],
done,
);
it('should commit the request mutation', () => {
return testAction(actions.requestAddDismissalComment, {}, state, [
{ type: types.REQUEST_ADD_DISMISSAL_COMMENT },
]);
});
});
});
......@@ -912,16 +778,15 @@ describe('add vulnerability dismissal comment', () => {
mock.onPatch(url).replyOnce(200, data);
});
it('should dispatch the request and success actions', done => {
it('should dispatch the request and success actions', () => {
const checkPassedData = () => {
const { project_id } = vulnerability.dismissal_feedback;
const expected = JSON.stringify({ project_id, comment });
expect(mock.history.patch[0].data).toBe(expected);
done();
};
testAction(
return testAction(
actions.deleteDismissalComment,
{ vulnerability },
{},
......@@ -938,17 +803,16 @@ describe('add vulnerability dismissal comment', () => {
);
});
it('should show the delete dismissal comment toast message', done => {
it('should show the delete dismissal comment toast message', () => {
const checkPassedData = () => {
const { project_id } = vulnerability.dismissal_feedback;
const expected = JSON.stringify({ project_id, comment });
expect(mock.history.patch[0].data).toBe(expected);
expect(toast).toHaveBeenCalledTimes(1);
done();
};
testAction(
return testAction(
actions.deleteDismissalComment,
{ vulnerability },
{},
......@@ -971,8 +835,8 @@ describe('add vulnerability dismissal comment', () => {
mock.onPatch(url).replyOnce(404);
});
it('should dispatch the request and error actions', done => {
testAction(
it('should dispatch the request and error actions', () => {
return testAction(
actions.deleteDismissalComment,
{ vulnerability },
{},
......@@ -981,47 +845,31 @@ describe('add vulnerability dismissal comment', () => {
{ type: 'requestDeleteDismissalComment' },
{ type: 'receiveDeleteDismissalCommentError' },
],
done,
);
});
});
describe('receiveDeleteDismissalCommentSuccess', () => {
it('should commit the success mutation', done => {
testAction(
actions.receiveDeleteDismissalCommentSuccess,
{ data },
state,
[{ type: types.RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS, payload: { data } }],
[],
done,
);
it('should commit the success mutation', () => {
return testAction(actions.receiveDeleteDismissalCommentSuccess, { data }, state, [
{ type: types.RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS, payload: { data } },
]);
});
});
describe('receiveDeleteDismissalCommentError', () => {
it('should commit the error mutation', done => {
testAction(
actions.receiveDeleteDismissalCommentError,
{},
state,
[{ type: types.RECEIVE_DELETE_DISMISSAL_COMMENT_ERROR }],
[],
done,
);
it('should commit the error mutation', () => {
return testAction(actions.receiveDeleteDismissalCommentError, {}, state, [
{ type: types.RECEIVE_DELETE_DISMISSAL_COMMENT_ERROR },
]);
});
});
describe('requestDeleteDismissalComment', () => {
it('should commit the request mutation', done => {
testAction(
actions.requestDeleteDismissalComment,
{},
state,
[{ type: types.REQUEST_DELETE_DISMISSAL_COMMENT }],
[],
done,
);
it('should commit the request mutation', () => {
return testAction(actions.requestDeleteDismissalComment, {}, state, [
{ type: types.REQUEST_DELETE_DISMISSAL_COMMENT },
]);
});
});
});
......@@ -1052,14 +900,14 @@ describe('dismiss multiple vulnerabilities', () => {
mock.restore();
});
it('should fire the dismissSelected mutations when all is well', done => {
it('should fire the dismissSelected mutations when all is well', () => {
mock
.onPost(state.vulnerabilities[0].create_vulnerability_feedback_dismissal_path)
.replyOnce(200)
.onPost(state.vulnerabilities[1].create_vulnerability_feedback_dismissal_path)
.replyOnce(200);
testAction(
return testAction(
actions.dismissSelectedVulnerabilities,
{},
state,
......@@ -1075,19 +923,18 @@ describe('dismiss multiple vulnerabilities', () => {
expect(mock.history.post[0].url).toEqual(
state.vulnerabilities[0].create_vulnerability_feedback_dismissal_path,
);
done();
},
);
});
it('should trigger the error state when something goes wrong', done => {
it('should trigger the error state when something goes wrong', () => {
mock
.onPost(state.vulnerabilities[0].create_vulnerability_feedback_dismissal_path)
.replyOnce(200)
.onPost(state.vulnerabilities[1].create_vulnerability_feedback_dismissal_path)
.replyOnce(500);
testAction(
return testAction(
actions.dismissSelectedVulnerabilities,
{},
state,
......@@ -1096,33 +943,25 @@ describe('dismiss multiple vulnerabilities', () => {
{ type: 'requestDismissSelectedVulnerabilities' },
{ type: 'receiveDismissSelectedVulnerabilitiesError', payload: { flashError: true } },
],
done,
);
});
describe('receiveDismissSelectedVulnerabilitiesSuccess', () => {
it(`should commit ${types.RECEIVE_DISMISS_SELECTED_VULNERABILITIES_SUCCESS}`, done => {
testAction(
it(`should commit ${types.RECEIVE_DISMISS_SELECTED_VULNERABILITIES_SUCCESS}`, () => {
return testAction(
actions.receiveDismissSelectedVulnerabilitiesSuccess,
{ selectedVulnerabilities },
state,
[{ type: types.RECEIVE_DISMISS_SELECTED_VULNERABILITIES_SUCCESS }],
[],
done,
);
});
});
describe('receiveDismissSelectedVulnerabilitiesError', () => {
it(`should commit ${types.RECEIVE_DISMISS_SELECTED_VULNERABILITIES_ERROR}`, done => {
testAction(
actions.receiveDismissSelectedVulnerabilitiesError,
{},
state,
[{ type: types.RECEIVE_DISMISS_SELECTED_VULNERABILITIES_ERROR }],
[],
done,
);
it(`should commit ${types.RECEIVE_DISMISS_SELECTED_VULNERABILITIES_ERROR}`, () => {
return testAction(actions.receiveDismissSelectedVulnerabilitiesError, {}, state, [
{ type: types.RECEIVE_DISMISS_SELECTED_VULNERABILITIES_ERROR },
]);
});
});
});
......@@ -1136,58 +975,38 @@ describe('selecting vulnerabilities', () => {
});
describe('selectVulnerability', () => {
it(`selectVulnerability should commit ${types.SELECT_VULNERABILITY}`, done => {
it(`selectVulnerability should commit ${types.SELECT_VULNERABILITY}`, () => {
const id = 1234;
testAction(
actions.selectVulnerability,
{ id },
state,
[{ type: types.SELECT_VULNERABILITY, payload: id }],
[],
done,
);
return testAction(actions.selectVulnerability, { id }, state, [
{ type: types.SELECT_VULNERABILITY, payload: id },
]);
});
});
describe('deselectVulnerability', () => {
it(`should commit ${types.DESELECT_VULNERABILITY}`, done => {
it(`should commit ${types.DESELECT_VULNERABILITY}`, () => {
const id = 1234;
testAction(
actions.deselectVulnerability,
{ id },
state,
[{ type: types.DESELECT_VULNERABILITY, payload: id }],
[],
done,
);
return testAction(actions.deselectVulnerability, { id }, state, [
{ type: types.DESELECT_VULNERABILITY, payload: id },
]);
});
});
describe('selectAllVulnerabilities', () => {
it(`should commit ${types.SELECT_ALL_VULNERABILITIES}`, done => {
testAction(
actions.selectAllVulnerabilities,
{},
state,
[{ type: types.SELECT_ALL_VULNERABILITIES }],
[],
done,
);
it(`should commit ${types.SELECT_ALL_VULNERABILITIES}`, () => {
return testAction(actions.selectAllVulnerabilities, {}, state, [
{ type: types.SELECT_ALL_VULNERABILITIES },
]);
});
});
describe('deselectAllVulnerabilities', () => {
it(`should commit ${types.DESELECT_ALL_VULNERABILITIES}`, done => {
testAction(
actions.deselectAllVulnerabilities,
{},
state,
[{ type: types.DESELECT_ALL_VULNERABILITIES }],
[],
done,
);
it(`should commit ${types.DESELECT_ALL_VULNERABILITIES}`, () => {
return testAction(actions.deselectAllVulnerabilities, {}, state, [
{ type: types.DESELECT_ALL_VULNERABILITIES },
]);
});
});
});
......@@ -1199,19 +1018,12 @@ describe('showDismissalDeleteButtons', () => {
state = initialState();
});
it('commits show dismissal delete buttons', done => {
testAction(
actions.showDismissalDeleteButtons,
null,
state,
[
it('commits show dismissal delete buttons', () => {
return testAction(actions.showDismissalDeleteButtons, null, state, [
{
type: types.SHOW_DISMISSAL_DELETE_BUTTONS,
},
],
[],
done,
);
]);
});
});
......@@ -1222,19 +1034,12 @@ describe('hideDismissalDeleteButtons', () => {
state = initialState();
});
it('commits hide dismissal delete buttons', done => {
testAction(
actions.hideDismissalDeleteButtons,
null,
state,
[
it('commits hide dismissal delete buttons', () => {
return testAction(actions.hideDismissalDeleteButtons, null, state, [
{
type: types.HIDE_DISMISSAL_DELETE_BUTTONS,
},
],
[],
done,
);
]);
});
});
......@@ -1257,8 +1062,8 @@ describe('revert vulnerability dismissal', () => {
mock.onDelete(url).replyOnce(200, {});
});
it('should dispatch the request and success actions', done => {
testAction(
it('should dispatch the request and success actions', () => {
return testAction(
actions.undoDismiss,
{ vulnerability },
{},
......@@ -1267,7 +1072,6 @@ describe('revert vulnerability dismissal', () => {
{ type: 'requestUndoDismiss' },
{ type: 'receiveUndoDismissSuccess', payload: { vulnerability } },
],
done,
);
});
});
......@@ -1277,10 +1081,10 @@ describe('revert vulnerability dismissal', () => {
mock.onDelete(url).replyOnce(404, {});
});
it('should dispatch the request and error actions', done => {
it('should dispatch the request and error actions', () => {
const flashError = false;
testAction(
return testAction(
actions.undoDismiss,
{ vulnerability, flashError },
{},
......@@ -1289,262 +1093,56 @@ describe('revert vulnerability dismissal', () => {
{ type: 'requestUndoDismiss' },
{ type: 'receiveUndoDismissError', payload: { flashError } },
],
done,
);
});
});
});
describe('receiveUndoDismissSuccess', () => {
it('should commit the success mutation', done => {
it('should commit the success mutation', () => {
const state = initialState;
const data = mockDataVulnerabilities[0];
testAction(
actions.receiveUndoDismissSuccess,
{ data },
state,
[
return testAction(actions.receiveUndoDismissSuccess, { data }, state, [
{
type: types.RECEIVE_REVERT_DISMISSAL_SUCCESS,
payload: { data },
},
],
[],
done,
);
]);
});
});
describe('receiveUndoDismissError', () => {
it('should commit the error mutation', done => {
it('should commit the error mutation', () => {
const state = initialState;
testAction(
actions.receiveUndoDismissError,
{},
state,
[{ type: types.RECEIVE_REVERT_DISMISSAL_ERROR }],
[],
done,
);
return testAction(actions.receiveUndoDismissError, {}, state, [
{ type: types.RECEIVE_REVERT_DISMISSAL_ERROR },
]);
});
});
describe('requestUndoDismiss', () => {
it('should commit the request mutation', done => {
it('should commit the request mutation', () => {
const state = initialState;
testAction(
actions.requestUndoDismiss,
{},
state,
[{ type: types.REQUEST_REVERT_DISMISSAL }],
[],
done,
);
return testAction(actions.requestUndoDismiss, {}, state, [
{ type: types.REQUEST_REVERT_DISMISSAL },
]);
});
});
});
describe('vulnerabilities history actions', () => {
const data = mockDataVulnerabilitiesHistory;
const params = { filters: { severity: ['critical'] } };
const filteredData = mockDataVulnerabilitiesHistory.critical;
let state;
beforeEach(() => {
state = initialState();
describe('dismissal comment box', () => {
it('should commit the open comment mutation with a default payload', () => {
return testAction(actions.openDismissalCommentBox, undefined, undefined, [
{ type: types.OPEN_DISMISSAL_COMMENT_BOX },
]);
});
describe('setVulnerabilitiesHistoryEndpoint', () => {
it('should commit the correct mutuation', done => {
const endpoint = 'fakepath.json';
testAction(
actions.setVulnerabilitiesHistoryEndpoint,
endpoint,
state,
[
{
type: types.SET_VULNERABILITIES_HISTORY_ENDPOINT,
payload: endpoint,
},
],
[],
done,
);
});
});
describe('setVulnerabilitiesHistoryDayRange', () => {
it('should commit the number of past days to show', done => {
const days = DAYS.THIRTY;
testAction(
actions.setVulnerabilitiesHistoryDayRange,
days,
state,
[
{
type: types.SET_VULNERABILITIES_HISTORY_DAY_RANGE,
payload: days,
},
],
[],
done,
);
});
});
describe('fetchVulnerabilitiesHistory', () => {
let mock;
beforeEach(() => {
state.vulnerabilitiesHistoryEndpoint = `${TEST_HOST}/vulnerabilitIES_HISTORY.json`;
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
describe('on success', () => {
beforeEach(() => {
mock
.onGet(state.vulnerabilitiesHistoryEndpoint, { params })
.replyOnce(200, filteredData)
.onGet(state.vulnerabilitiesHistoryEndpoint)
.replyOnce(200, data);
});
it('should dispatch the request and success actions', done => {
testAction(
actions.fetchVulnerabilitiesHistory,
{},
state,
[],
[
{ type: 'requestVulnerabilitiesHistory' },
{
type: 'receiveVulnerabilitiesHistorySuccess',
payload: { data },
},
],
done,
);
});
it('return the filtered results', done => {
testAction(
actions.fetchVulnerabilitiesHistory,
params,
state,
[],
[
{ type: 'requestVulnerabilitiesHistory' },
{
type: 'receiveVulnerabilitiesHistorySuccess',
payload: { data: filteredData },
},
],
done,
);
});
});
describe('on error', () => {
beforeEach(() => {
mock.onGet(state.vulnerabilitiesHistoryEndpoint).replyOnce(404, {});
});
it('should dispatch the request and error actions', done => {
testAction(
actions.fetchVulnerabilitiesHistory,
{},
state,
[],
[
{ type: 'requestVulnerabilitiesHistory' },
{ type: 'receiveVulnerabilitiesHistoryError' },
],
done,
);
});
});
describe('with an empty endpoint', () => {
beforeEach(() => {
state.vulnerabilitiesHistoryEndpoint = '';
});
it('should not do anything', done => {
testAction(actions.fetchVulnerabilitiesHistory, {}, state, [], [], done);
});
});
});
describe('requestVulnerabilitiesHistory', () => {
it('should commit the request mutation', done => {
testAction(
actions.requestVulnerabilitiesHistory,
{},
state,
[{ type: types.REQUEST_VULNERABILITIES_HISTORY }],
[],
done,
);
});
});
describe('receiveVulnerabilitiesHistorySuccess', () => {
it('should commit the success mutation', done => {
testAction(
actions.receiveVulnerabilitiesHistorySuccess,
{ data },
state,
[{ type: types.RECEIVE_VULNERABILITIES_HISTORY_SUCCESS, payload: data }],
[],
done,
);
});
});
describe('receiveVulnerabilitiesHistoryError', () => {
it('should commit the error mutation', done => {
testAction(
actions.receiveVulnerabilitiesHistoryError,
{},
state,
[{ type: types.RECEIVE_VULNERABILITIES_HISTORY_ERROR }],
[],
done,
);
});
});
describe('openDismissalCommentBox', () => {
it('should commit the open comment mutation with a default payload', done => {
testAction(
actions.openDismissalCommentBox,
undefined,
state,
[{ type: types.OPEN_DISMISSAL_COMMENT_BOX }],
[],
done,
);
});
});
describe('closeDismissalCommentBox', () => {
it('should commit the close comment mutation', done => {
testAction(
actions.closeDismissalCommentBox,
{},
state,
[{ type: types.CLOSE_DISMISSAL_COMMENT_BOX }],
[],
done,
);
});
it('should commit the close comment mutation', () => {
return testAction(actions.closeDismissalCommentBox, {}, undefined, [
{ type: types.CLOSE_DISMISSAL_COMMENT_BOX },
]);
});
});
{
"low": {
"2018-10-1": 87,
"2018-10-2": 88,
"2018-10-3": 90,
"2018-10-4": 89,
"2018-10-5": 89,
"2018-10-6": 80,
"2018-10-7": 85,
"2018-10-8": 67,
"2018-10-9": 84,
"2018-10-10": 72,
"2018-10-11": 67,
"2018-10-12": 86,
"2018-10-13": 70,
"2018-10-14": 68,
"2018-10-15": 61,
"2018-10-16": 74,
"2018-10-17": 67,
"2018-10-18": 78,
"2018-10-19": 65,
"2018-10-20": 72,
"2018-10-21": 78,
"2018-10-22": 81,
"2018-10-23": 62,
"2018-10-24": 86,
"2018-10-25": 79,
"2018-10-26": 86,
"2018-10-27": 78,
"2018-10-28": 75,
"2018-10-29": 67,
"2018-10-30": 87,
"2018-10-31": 86,
"2018-11-1": 75,
"2018-11-2": 81,
"2018-11-3": 88,
"2018-11-4": 82,
"2018-11-5": 76,
"2018-11-6": 76,
"2018-11-7": 68,
"2018-11-8": 86,
"2018-11-9": 70,
"2018-11-10": 74,
"2018-11-11": 60,
"2018-11-12": 61,
"2018-11-13": 73,
"2018-11-14": 90,
"2018-11-15": 69,
"2018-11-16": 78,
"2018-11-17": 81,
"2018-11-18": 60,
"2018-11-19": 86,
"2018-11-20": 72,
"2018-11-21": 73,
"2018-11-22": 60,
"2018-11-23": 88,
"2018-11-24": 70,
"2018-11-25": 60,
"2018-11-26": 72,
"2018-11-27": 71,
"2018-11-28": 77,
"2018-11-29": 77,
"2018-11-30": 70,
"2018-12-1": 69,
"2018-12-2": 80,
"2018-12-3": 73,
"2018-12-4": 71,
"2018-12-5": 84,
"2018-12-6": 82,
"2018-12-7": 68,
"2018-12-8": 66,
"2018-12-9": 76,
"2018-12-10": 81,
"2018-12-11": 61,
"2018-12-12": 78,
"2018-12-13": 85,
"2018-12-14": 74,
"2018-12-15": 65,
"2018-12-16": 90,
"2018-12-17": 87,
"2018-12-18": 83,
"2018-12-19": 72,
"2018-12-20": 79,
"2018-12-21": 83,
"2018-12-22": 70,
"2018-12-23": 75,
"2018-12-24": 77,
"2018-12-25": 68,
"2018-12-26": 86,
"2018-12-27": 76,
"2018-12-28": 86,
"2018-12-29": 89,
"2018-12-30": 73,
"2018-12-31": 70
},
"medium": {
"2018-10-1": 73,
"2018-10-2": 76,
"2018-10-3": 101,
"2018-10-4": 84,
"2018-10-5": 90,
"2018-10-6": 97,
"2018-10-7": 77,
"2018-10-8": 81,
"2018-10-9": 98,
"2018-10-10": 83,
"2018-10-11": 82,
"2018-10-12": 70,
"2018-10-13": 99,
"2018-10-14": 83,
"2018-10-15": 81,
"2018-10-16": 80,
"2018-10-17": 82,
"2018-10-18": 89,
"2018-10-19": 89,
"2018-10-20": 71,
"2018-10-21": 73,
"2018-10-22": 74,
"2018-10-23": 83,
"2018-10-24": 91,
"2018-10-25": 85,
"2018-10-26": 90,
"2018-10-27": 77,
"2018-10-28": 102,
"2018-10-29": 75,
"2018-10-30": 78,
"2018-10-31": 70,
"2018-11-1": 90,
"2018-11-2": 96,
"2018-11-3": 98,
"2018-11-4": 88,
"2018-11-5": 79,
"2018-11-6": 91,
"2018-11-7": 101,
"2018-11-8": 75,
"2018-11-9": 75,
"2018-11-10": 84,
"2018-11-11": 70,
"2018-11-12": 89,
"2018-11-13": 104,
"2018-11-14": 90,
"2018-11-15": 81,
"2018-11-16": 102,
"2018-11-17": 86,
"2018-11-18": 80,
"2018-11-19": 71,
"2018-11-20": 72,
"2018-11-21": 103,
"2018-11-22": 89,
"2018-11-23": 83,
"2018-11-24": 79,
"2018-11-25": 87,
"2018-11-26": 79,
"2018-11-27": 104,
"2018-11-28": 70,
"2018-11-29": 103,
"2018-11-30": 86,
"2018-12-1": 86,
"2018-12-2": 77,
"2018-12-3": 96,
"2018-12-4": 95,
"2018-12-5": 74,
"2018-12-6": 99,
"2018-12-7": 101,
"2018-12-8": 78,
"2018-12-9": 83,
"2018-12-10": 76,
"2018-12-11": 77,
"2018-12-12": 105,
"2018-12-13": 81,
"2018-12-14": 82,
"2018-12-15": 90,
"2018-12-16": 88,
"2018-12-17": 78,
"2018-12-18": 82,
"2018-12-19": 83,
"2018-12-20": 105,
"2018-12-21": 70,
"2018-12-22": 85,
"2018-12-23": 91,
"2018-12-24": 89,
"2018-12-25": 83,
"2018-12-26": 73,
"2018-12-27": 91,
"2018-12-28": 77,
"2018-12-29": 101,
"2018-12-30": 83,
"2018-12-31": 94
},
"high": {
"2018-10-1": 43,
"2018-10-2": 42,
"2018-10-3": 42,
"2018-10-4": 49,
"2018-10-5": 44,
"2018-10-6": 59,
"2018-10-7": 49,
"2018-10-8": 53,
"2018-10-9": 44,
"2018-10-10": 51,
"2018-10-11": 43,
"2018-10-12": 53,
"2018-10-13": 52,
"2018-10-14": 43,
"2018-10-15": 60,
"2018-10-16": 53,
"2018-10-17": 57,
"2018-10-18": 42,
"2018-10-19": 46,
"2018-10-20": 43,
"2018-10-21": 43,
"2018-10-22": 41,
"2018-10-23": 47,
"2018-10-24": 44,
"2018-10-25": 43,
"2018-10-26": 60,
"2018-10-27": 43,
"2018-10-28": 59,
"2018-10-29": 55,
"2018-10-30": 45,
"2018-10-31": 51,
"2018-11-1": 55,
"2018-11-2": 50,
"2018-11-3": 43,
"2018-11-4": 41,
"2018-11-5": 51,
"2018-11-6": 49,
"2018-11-7": 49,
"2018-11-8": 60,
"2018-11-9": 60,
"2018-11-10": 43,
"2018-11-11": 57,
"2018-11-12": 42,
"2018-11-13": 59,
"2018-11-14": 41,
"2018-11-15": 53,
"2018-11-16": 53,
"2018-11-17": 43,
"2018-11-18": 53,
"2018-11-19": 48,
"2018-11-20": 56,
"2018-11-21": 51,
"2018-11-22": 42,
"2018-11-23": 60,
"2018-11-24": 50,
"2018-11-25": 49,
"2018-11-26": 47,
"2018-11-27": 46,
"2018-11-28": 40,
"2018-11-29": 41,
"2018-11-30": 57,
"2018-12-1": 57,
"2018-12-2": 45,
"2018-12-3": 52,
"2018-12-4": 46,
"2018-12-5": 56,
"2018-12-6": 48,
"2018-12-7": 58,
"2018-12-8": 59,
"2018-12-9": 47,
"2018-12-10": 58,
"2018-12-11": 50,
"2018-12-12": 45,
"2018-12-13": 59,
"2018-12-14": 40,
"2018-12-15": 40,
"2018-12-16": 48,
"2018-12-17": 44,
"2018-12-18": 54,
"2018-12-19": 44,
"2018-12-20": 57,
"2018-12-21": 54,
"2018-12-22": 44,
"2018-12-23": 59,
"2018-12-24": 41,
"2018-12-25": 52,
"2018-12-26": 52,
"2018-12-27": 50,
"2018-12-28": 49,
"2018-12-29": 45,
"2018-12-30": 44,
"2018-12-31": 60
},
"critical": {
"2018-10-1": 54,
"2018-10-2": 67,
"2018-10-3": 62,
"2018-10-4": 63,
"2018-10-5": 51,
"2018-10-6": 56,
"2018-10-7": 66,
"2018-10-8": 69,
"2018-10-9": 58,
"2018-10-10": 61,
"2018-10-11": 69,
"2018-10-12": 73,
"2018-10-13": 68,
"2018-10-14": 64,
"2018-10-15": 69,
"2018-10-16": 63,
"2018-10-17": 72,
"2018-10-18": 71,
"2018-10-19": 56,
"2018-10-20": 71,
"2018-10-21": 59,
"2018-10-22": 55,
"2018-10-23": 51,
"2018-10-24": 74,
"2018-10-25": 68,
"2018-10-26": 74,
"2018-10-27": 53,
"2018-10-28": 73,
"2018-10-29": 54,
"2018-10-30": 53,
"2018-10-31": 53,
"2018-11-1": 68,
"2018-11-2": 71,
"2018-11-3": 57,
"2018-11-4": 59,
"2018-11-5": 58,
"2018-11-6": 67,
"2018-11-7": 56,
"2018-11-8": 74,
"2018-11-9": 54,
"2018-11-10": 67,
"2018-11-11": 61,
"2018-11-12": 73,
"2018-11-13": 58,
"2018-11-14": 56,
"2018-11-15": 55,
"2018-11-16": 72,
"2018-11-17": 53,
"2018-11-18": 68,
"2018-11-19": 52,
"2018-11-20": 64,
"2018-11-21": 72,
"2018-11-22": 50,
"2018-11-23": 59,
"2018-11-24": 56,
"2018-11-25": 74,
"2018-11-26": 71,
"2018-11-27": 66,
"2018-11-28": 55,
"2018-11-29": 51,
"2018-11-30": 63,
"2018-12-1": 54,
"2018-12-2": 63,
"2018-12-3": 64,
"2018-12-4": 51,
"2018-12-5": 66,
"2018-12-6": 61,
"2018-12-7": 62,
"2018-12-8": 59,
"2018-12-9": 69,
"2018-12-10": 73,
"2018-12-11": 67,
"2018-12-12": 58,
"2018-12-13": 69,
"2018-12-14": 71,
"2018-12-15": 69,
"2018-12-16": 72,
"2018-12-17": 73,
"2018-12-18": 59,
"2018-12-19": 60,
"2018-12-20": 52,
"2018-12-21": 71,
"2018-12-22": 56,
"2018-12-23": 61,
"2018-12-24": 61,
"2018-12-25": 72,
"2018-12-26": 66,
"2018-12-27": 67,
"2018-12-28": 72,
"2018-12-29": 58,
"2018-12-30": 68,
"2018-12-31": 54,
"2019-1-1": 139,
"2019-1-2": 137,
"2019-1-3": 142,
"2019-1-4": 137,
"2019-1-5": 134,
"2019-1-6": 133,
"2019-1-7": 137,
"2019-1-8": 140,
"2019-1-9": 130,
"2019-1-10": 132,
"2019-1-11": 134,
"2019-1-12": 143,
"2019-1-13": 130,
"2019-1-14": 133,
"2019-1-15": 137,
"2019-1-16": 141,
"2019-1-17": 139,
"2019-1-18": 145,
"2019-1-19": 141,
"2019-1-20": 137,
"2019-1-21": 139,
"2019-1-22": 131,
"2019-1-23": 134,
"2019-1-24": 144,
"2019-1-25": 140,
"2019-1-26": 145,
"2019-1-27": 138,
"2019-1-28": 136,
"2019-1-29": 144,
"2019-1-30": 131,
"2019-1-31": 142
},
"unknown": {
"2018-10-1": 39,
"2018-10-2": 44,
"2018-10-3": 35,
"2018-10-4": 34,
"2018-10-5": 38,
"2018-10-6": 34,
"2018-10-7": 34,
"2018-10-8": 43,
"2018-10-9": 41,
"2018-10-10": 45,
"2018-10-11": 41,
"2018-10-12": 37,
"2018-10-13": 34,
"2018-10-14": 41,
"2018-10-15": 45,
"2018-10-16": 33,
"2018-10-17": 40,
"2018-10-18": 31,
"2018-10-19": 42,
"2018-10-20": 33,
"2018-10-21": 44,
"2018-10-22": 33,
"2018-10-23": 35,
"2018-10-24": 37,
"2018-10-25": 43,
"2018-10-26": 33,
"2018-10-27": 43,
"2018-10-28": 39,
"2018-10-29": 37,
"2018-10-30": 36,
"2018-10-31": 37,
"2018-11-1": 42,
"2018-11-2": 41,
"2018-11-3": 36,
"2018-11-4": 31,
"2018-11-5": 41,
"2018-11-6": 37,
"2018-11-7": 42,
"2018-11-8": 42,
"2018-11-9": 45,
"2018-11-10": 34,
"2018-11-11": 30,
"2018-11-12": 40,
"2018-11-13": 39,
"2018-11-14": 44,
"2018-11-15": 36,
"2018-11-16": 35,
"2018-11-17": 30,
"2018-11-18": 31,
"2018-11-19": 34,
"2018-11-20": 31,
"2018-11-21": 36,
"2018-11-22": 37,
"2018-11-23": 41,
"2018-11-24": 38,
"2018-11-25": 42,
"2018-11-26": 41,
"2018-11-27": 36,
"2018-11-28": 32,
"2018-11-29": 43,
"2018-11-30": 36,
"2018-12-1": 44,
"2018-12-2": 34,
"2018-12-3": 42,
"2018-12-4": 32,
"2018-12-5": 44,
"2018-12-6": 31,
"2018-12-7": 39,
"2018-12-8": 37,
"2018-12-9": 33,
"2018-12-10": 37,
"2018-12-11": 38,
"2018-12-12": 35,
"2018-12-13": 34,
"2018-12-14": 40,
"2018-12-15": 35,
"2018-12-16": 42,
"2018-12-17": 44,
"2018-12-18": 40,
"2018-12-19": 40,
"2018-12-20": 30,
"2018-12-21": 44,
"2018-12-22": 32,
"2018-12-23": 39,
"2018-12-24": 37,
"2018-12-25": 35,
"2018-12-26": 39,
"2018-12-27": 38,
"2018-12-28": 44,
"2018-12-29": 42,
"2018-12-30": 37,
"2018-12-31": 35
},
"all": {
"2018-10-1": 143,
"2018-10-2": 130,
"2018-10-3": 139,
"2018-10-4": 134,
"2018-10-5": 138,
"2018-10-6": 131,
"2018-10-7": 137,
"2018-10-8": 144,
"2018-10-9": 140,
"2018-10-10": 134,
"2018-10-11": 142,
"2018-10-12": 132,
"2018-10-13": 136,
"2018-10-14": 141,
"2018-10-15": 134,
"2018-10-16": 139,
"2018-10-17": 141,
"2018-10-18": 134,
"2018-10-19": 131,
"2018-10-20": 141,
"2018-10-21": 139,
"2018-10-22": 145,
"2018-10-23": 142,
"2018-10-24": 143,
"2018-10-25": 143,
"2018-10-26": 135,
"2018-10-27": 136,
"2018-10-28": 143,
"2018-10-29": 142,
"2018-10-30": 131,
"2018-10-31": 141,
"2018-11-1": 134,
"2018-11-2": 134,
"2018-11-3": 130,
"2018-11-4": 137,
"2018-11-5": 145,
"2018-11-6": 137,
"2018-11-7": 135,
"2018-11-8": 145,
"2018-11-9": 132,
"2018-11-10": 134,
"2018-11-11": 139,
"2018-11-12": 139,
"2018-11-13": 130,
"2018-11-14": 137,
"2018-11-15": 136,
"2018-11-16": 145,
"2018-11-17": 130,
"2018-11-18": 143,
"2018-11-19": 134,
"2018-11-20": 145,
"2018-11-21": 137,
"2018-11-22": 140,
"2018-11-23": 138,
"2018-11-24": 132,
"2018-11-25": 143,
"2018-11-26": 131,
"2018-11-27": 130,
"2018-11-28": 144,
"2018-11-29": 139,
"2018-11-30": 143,
"2018-12-1": 139,
"2018-12-2": 137,
"2018-12-3": 142,
"2018-12-4": 137,
"2018-12-5": 134,
"2018-12-6": 133,
"2018-12-7": 137,
"2018-12-8": 140,
"2018-12-9": 130,
"2018-12-10": 132,
"2018-12-11": 134,
"2018-12-12": 143,
"2018-12-13": 130,
"2018-12-14": 133,
"2018-12-15": 137,
"2018-12-16": 141,
"2018-12-17": 139,
"2018-12-18": 145,
"2018-12-19": 141,
"2018-12-20": 137,
"2018-12-21": 139,
"2018-12-22": 131,
"2018-12-23": 134,
"2018-12-24": 144,
"2018-12-25": 140,
"2018-12-26": 145,
"2018-12-27": 138,
"2018-12-28": 136,
"2018-12-29": 144,
"2018-12-30": 131,
"2018-12-31": 142,
"2019-1-1": 139,
"2019-1-2": 137,
"2019-1-3": 142,
"2019-1-4": 137,
"2019-1-5": 134,
"2019-1-6": 133,
"2019-1-7": 137,
"2019-1-8": 140,
"2019-1-9": 130,
"2019-1-10": 132,
"2019-1-11": 134,
"2019-1-12": 143,
"2019-1-13": 130,
"2019-1-14": 133,
"2019-1-15": 137,
"2019-1-16": 141,
"2019-1-17": 139,
"2019-1-18": 145,
"2019-1-19": 141,
"2019-1-20": 137,
"2019-1-21": 139,
"2019-1-22": 131,
"2019-1-23": 134,
"2019-1-24": 144,
"2019-1-25": 140,
"2019-1-26": 145,
"2019-1-27": 138,
"2019-1-28": 136,
"2019-1-29": 144,
"2019-1-30": 131,
"2019-1-31": 142
}
}
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