Commit 3306d030 authored by Fernando Arias's avatar Fernando Arias

Add Security Group Vuln Graph Date Ranges

First pass at filtering vuln history table history

* Added button markup
* Added actions, mutators, and store properties
* Added filter method

Push current iteration of the code to allow for UX feedback

More Vuln Chart Graph changes

* Only show dots on last 30 days graph
* Fix placement of day range button group
* Show active button for day range

Additional UX tweaks for sexure graph

* Show vertical lines in grid only for 60 and 90 days
* Set min date to 30, 60, 90 days ago
* Show dots for all date ranges

Clean up code for MR add unit tests

* Remove stray debuggers
* Remove use of dummy data
* Add unit tests for mutators and actions

Refactor vuln chart buttons into view

* Refactor vuln graph days ago buttons into seperate view

Update vuln graph button titles

Add unit tests for secure graph buttons

Run Prettier

Fix linting errors

Remove host file

* Remove accidentally committed host file

Update pot file

Run prettier

Add new line to vuln chart stylesheet

Refactor filtered vulns function

* Refactor into getter
* Add getter unit tests

Add change log entry

Fix linter errors in getters_spec

Run prettier and fix linter errors

First set of code review changes

Fix vuln chart getter specs

Update vuln chart button specs

* Update specs to make use of shallowRender from vue test utils

Update security vuln chart buttons to use I18n

Add Days contants for days vuln chart

* Swap out references to integers for constants

Run prettier

Update POT file

Fix linter errors

* Fix linter errors in spec files

Refactor vuln chart buttons

Make merge request review changes

* Updated specs
* Updated code based on feedback

Run Prettier

Frefactor vuln chart buttons to emit events

* Refactor vuln chart buttons to be a 'dumb' component
* emit click event

Fix failing karma job

* Assertion timeouts fail only on build servers

Remove failing tests

Fix linter errors

Restore Karma tests

* Restore karma tests and use sync:false option
parent 16c2a35b
...@@ -90,9 +90,9 @@ export default { ...@@ -90,9 +90,9 @@ export default {
<div> <div>
<filters :dashboard-documentation="dashboardDocumentation" /> <filters :dashboard-documentation="dashboardDocumentation" />
<vulnerability-count-list /> <vulnerability-count-list />
<h4 class="my-4">{{ __('Vulnerability Chart') }}</h4>
<vulnerability-chart /> <vulnerability-chart />
<h4 class="my-4">{{ __('Vulnerability List') }}</h4>
<security-dashboard-table <security-dashboard-table
:dashboard-documentation="dashboardDocumentation" :dashboard-documentation="dashboardDocumentation"
:empty-state-svg-path="emptyStateSvgPath" :empty-state-svg-path="emptyStateSvgPath"
......
...@@ -54,6 +54,8 @@ export default { ...@@ -54,6 +54,8 @@ export default {
<template> <template>
<div class="ci-table"> <div class="ci-table">
<h4 class="my-4">{{ __('Vulnerability List') }}</h4>
<div <div
class="gl-responsive-table-row table-row-header vulnerabilities-row-header px-2" class="gl-responsive-table-row table-row-header vulnerabilities-row-header px-2"
role="row" role="row"
......
<script> <script>
import dateFormat from 'dateformat'; import dateFormat from 'dateformat';
import { mapState } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import { GlChart } from '@gitlab/ui/dist/charts'; import { GlChart } from '@gitlab/ui/dist/charts';
import ChartTooltip from './vulnerability_chart_tooltip.vue'; import ChartTooltip from './vulnerability_chart_tooltip.vue';
import ChartButtons from './vulnerability_chart_buttons.vue';
import { DAY_IN_MS, DAYS } from '../store/modules/vulnerabilities/constants';
export default { export default {
name: 'VulnerabilityChart', name: 'VulnerabilityChart',
components: { components: {
GlChart, GlChart,
ChartTooltip, ChartTooltip,
ChartButtons,
}, },
DAYS,
data: () => ({ data: () => ({
tooltipTitle: '', tooltipTitle: '',
tooltipEntries: [], tooltipEntries: [],
...@@ -37,12 +41,17 @@ export default { ...@@ -37,12 +41,17 @@ export default {
], ],
}), }),
computed: { computed: {
...mapState('vulnerabilities', ['vulnerabilitiesHistory']), ...mapState('vulnerabilities', [
'vulnerabilitiesHistory',
'vulnerabilitiesHistoryDayRange',
'vulnerabilitiesHistoryShowSplitLine',
'vulnerabilitiesHistoryMaxDayInterval',
]),
...mapGetters('vulnerabilities', ['getFilteredVulnerabilitiesHistory']),
series() { series() {
return this.lines.map(line => { return this.lines.map(line => {
const { name, color } = line; const { name, color } = line;
const history = this.vulnerabilitiesHistory[name.toLowerCase()]; const data = this.getFilteredVulnerabilitiesHistory(name);
const data = history ? Object.entries(history) : [];
return { return {
borderWidth: 2, borderWidth: 2,
...@@ -88,11 +97,14 @@ export default { ...@@ -88,11 +97,14 @@ export default {
width: 2, width: 2,
}, },
}, },
splitLine: {
show: this.vulnerabilitiesHistoryShowSplitLine,
},
axisTick: { axisTick: {
show: false, show: false,
}, },
maxInterval: 1000 * 60 * 60 * 24 * 7, maxInterval: DAY_IN_MS * this.vulnerabilitiesHistoryMaxDayInterval,
min: Date.now() - 1000 * 60 * 60 * 24 * 28, min: Date.now() - DAY_IN_MS * this.vulnerabilitiesHistoryDayRange,
name: 'Date', name: 'Date',
nameGap: 50, nameGap: 50,
nameLocation: 'center', nameLocation: 'center',
...@@ -141,8 +153,13 @@ export default { ...@@ -141,8 +153,13 @@ export default {
series: this.series, series: this.series,
}; };
}, },
days() {
const { $options } = this;
return [$options.DAYS.THIRTY, $options.DAYS.SIXTY, $options.DAYS.NINETY];
},
}, },
methods: { methods: {
...mapActions('vulnerabilities', ['setVulnerabilitiesHistoryDayRange']),
renderTooltip(params, ticket, callback) { renderTooltip(params, ticket, callback) {
this.tooltipTitle = dateFormat(params[0].axisValue, 'd mmmm'); this.tooltipTitle = dateFormat(params[0].axisValue, 'd mmmm');
this.tooltipEntries = params; this.tooltipEntries = params;
...@@ -154,10 +171,29 @@ export default { ...@@ -154,10 +171,29 @@ export default {
</script> </script>
<template> <template>
<div class="vulnerabilities-chart"> <div>
<div class="vulnerabilities-chart-wrapper"> <div class="d-flex justify-content-between">
<gl-chart :options="options" :width="1240" /> <h4 class="my-4">{{ __('Vulnerability Chart') }}</h4>
<chart-tooltip v-show="false" ref="tooltip" :title="tooltipTitle" :entries="tooltipEntries" />
<div class="align-self-center">
<chart-buttons
:days="days"
:active-day="vulnerabilitiesHistoryDayRange"
@click="setVulnerabilitiesHistoryDayRange"
/>
</div>
</div>
<div class="vulnerabilities-chart">
<div class="vulnerabilities-chart-wrapper">
<gl-chart :options="options" />
<chart-tooltip
v-show="false"
ref="tooltip"
:title="tooltipTitle"
:entries="tooltipEntries"
/>
</div>
</div> </div>
</div> </div>
</template> </template>
<script>
import { GlButton } from '@gitlab/ui';
import { n__ } from '~/locale';
export default {
name: 'VulnerabilityChartButtons',
components: {
GlButton,
},
props: {
days: {
type: Array,
required: true,
},
activeDay: {
type: Number,
required: true,
},
},
computed: {
buttonContent() {
return days => n__('1 Day', '%d Days', days);
},
},
methods: {
clickHandler(days) {
this.$emit('click', days);
},
},
};
</script>
<template>
<div class="btn-group">
<gl-button
v-for="day in days"
:key="day"
:class="{ active: activeDay === day }"
variant="secondary"
:data-days="day"
@click="clickHandler(day)"
>
{{ buttonContent(day) }}
</gl-button>
</div>
</template>
...@@ -233,6 +233,10 @@ export const fetchVulnerabilitiesHistory = ({ state, dispatch }, params = {}) => ...@@ -233,6 +233,10 @@ export const fetchVulnerabilitiesHistory = ({ state, dispatch }, params = {}) =>
}); });
}; };
export const setVulnerabilitiesHistoryDayRange = ({ commit }, days) => {
commit(types.SET_VULNERABILITIES_HISTORY_DAY_RANGE, days);
};
export const requestVulnerabilitiesHistory = ({ commit }) => { export const requestVulnerabilitiesHistory = ({ commit }) => {
commit(types.REQUEST_VULNERABILITIES_HISTORY); commit(types.REQUEST_VULNERABILITIES_HISTORY);
}; };
......
...@@ -2,3 +2,11 @@ export const CRITICAL = 'critical'; ...@@ -2,3 +2,11 @@ export const CRITICAL = 'critical';
export const HIGH = 'high'; export const HIGH = 'high';
export const MEDIUM = 'medium'; export const MEDIUM = 'medium';
export const LOW = 'low'; export const LOW = 'low';
export const DAY_IN_MS = 1000 * 60 * 60 * 24;
export const DAYS = {
THIRTY: 30,
SIXTY: 60,
NINETY: 90,
};
...@@ -5,4 +5,27 @@ export const dashboardListError = state => ...@@ -5,4 +5,27 @@ export const dashboardListError = state =>
export const dashboardCountError = state => export const dashboardCountError = state =>
!state.errorLoadingVulnerabilities && state.errorLoadingVulnerabilitiesCount; !state.errorLoadingVulnerabilities && state.errorLoadingVulnerabilitiesCount;
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 default () => {}; export default () => {};
...@@ -9,6 +9,7 @@ export const RECEIVE_VULNERABILITIES_COUNT_SUCCESS = 'RECEIVE_VULNERABILITIES_CO ...@@ -9,6 +9,7 @@ export const RECEIVE_VULNERABILITIES_COUNT_SUCCESS = 'RECEIVE_VULNERABILITIES_CO
export const RECEIVE_VULNERABILITIES_COUNT_ERROR = 'RECEIVE_VULNERABILITIES_COUNT_ERROR'; export const RECEIVE_VULNERABILITIES_COUNT_ERROR = 'RECEIVE_VULNERABILITIES_COUNT_ERROR';
export const SET_VULNERABILITIES_HISTORY_ENDPOINT = 'SET_VULNERABILITIES_HISTORY_ENDPOINT'; 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 REQUEST_VULNERABILITIES_HISTORY = 'REQUEST_VULNERABILITIES_HISTORY';
export const RECEIVE_VULNERABILITIES_HISTORY_SUCCESS = 'RECEIVE_VULNERABILITIES_HISTORY_SUCCESS'; export const RECEIVE_VULNERABILITIES_HISTORY_SUCCESS = 'RECEIVE_VULNERABILITIES_HISTORY_SUCCESS';
export const RECEIVE_VULNERABILITIES_HISTORY_ERROR = 'RECEIVE_VULNERABILITIES_HISTORY_ERROR'; export const RECEIVE_VULNERABILITIES_HISTORY_ERROR = 'RECEIVE_VULNERABILITIES_HISTORY_ERROR';
......
...@@ -2,6 +2,7 @@ import Vue from 'vue'; ...@@ -2,6 +2,7 @@ import Vue from 'vue';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import * as types from './mutation_types'; import * as types from './mutation_types';
import { DAYS } from './constants';
export default { export default {
[types.SET_VULNERABILITIES_ENDPOINT](state, payload) { [types.SET_VULNERABILITIES_ENDPOINT](state, payload) {
...@@ -38,6 +39,18 @@ export default { ...@@ -38,6 +39,18 @@ export default {
[types.SET_VULNERABILITIES_HISTORY_ENDPOINT](state, payload) { [types.SET_VULNERABILITIES_HISTORY_ENDPOINT](state, payload) {
state.vulnerabilitiesHistoryEndpoint = payload; state.vulnerabilitiesHistoryEndpoint = payload;
}, },
[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, days) {
state.vulnerabilitiesHistoryDayRange = days;
state.vulnerabilitiesHistoryShowSplitLine = days <= DAYS.THIRTY;
if (days <= DAYS.THIRTY) {
state.vulnerabilitiesHistoryMaxDayInterval = 1;
} else if (days > DAYS.THIRTY && days <= DAYS.SIXTY) {
state.vulnerabilitiesHistoryMaxDayInterval = 7;
} else if (days > DAYS.SIXTY) {
state.vulnerabilitiesHistoryMaxDayInterval = 14;
}
},
[types.REQUEST_VULNERABILITIES_HISTORY](state) { [types.REQUEST_VULNERABILITIES_HISTORY](state) {
state.isLoadingVulnerabilitiesHistory = true; state.isLoadingVulnerabilitiesHistory = true;
state.errorLoadingVulnerabilitiesHistory = false; state.errorLoadingVulnerabilitiesHistory = false;
......
...@@ -10,6 +10,9 @@ export default () => ({ ...@@ -10,6 +10,9 @@ export default () => ({
isLoadingVulnerabilitiesHistory: true, isLoadingVulnerabilitiesHistory: true,
errorLoadingVulnerabilitiesHistory: false, errorLoadingVulnerabilitiesHistory: false,
vulnerabilitiesHistory: {}, vulnerabilitiesHistory: {},
vulnerabilitiesHistoryDayRange: 90,
vulnerabilitiesHistoryShowSplitLine: false,
vulnerabilitiesHistoryMaxDayInterval: 7,
pageInfo: {}, pageInfo: {},
vulnerabilitiesCountEndpoint: null, vulnerabilitiesCountEndpoint: null,
vulnerabilitiesHistoryEndpoint: null, vulnerabilitiesHistoryEndpoint: null,
......
...@@ -2,7 +2,7 @@ $trans-white: rgba(255, 255, 255, 0); ...@@ -2,7 +2,7 @@ $trans-white: rgba(255, 255, 255, 0);
.vulnerabilities-chart-wrapper { .vulnerabilities-chart-wrapper {
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
overflow: scroll; overflow: auto;
} }
@media screen and (max-width: 1240px) { @media screen and (max-width: 1240px) {
...@@ -14,7 +14,7 @@ $trans-white: rgba(255, 255, 255, 0); ...@@ -14,7 +14,7 @@ $trans-white: rgba(255, 255, 255, 0);
background-image: linear-gradient(to right, $trans-white, $gl-gray-350); background-image: linear-gradient(to right, $trans-white, $gl-gray-350);
bottom: 0; bottom: 0;
content: ''; content: '';
height: 310px; height: 305px;
position: absolute; position: absolute;
right: -1px; right: -1px;
top: 10px; top: 10px;
......
---
title: Add date range for security dashboard graph
merge_request: 9446
author:
type: added
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 { shallowMount, mount } from '@vue/test-utils';
describe('Vulnerability Chart Buttons', () => {
const Component = Vue.extend(component);
const days = [DAYS.THIRTY, DAYS.SIXTY, DAYS.NINETY];
describe('when rendering the buttons', () => {
it('should render with 90 days selected', () => {
const activeDay = DAYS.NINETY;
const wrapper = shallowMount(Component, { propsData: { days, activeDay } });
const activeButton = wrapper.find('[data-days="90"].active');
expect(activeButton.attributes('data-days')).toMatch('90');
});
it('should render with 60 days selected', () => {
const activeDay = DAYS.SIXTY;
const wrapper = shallowMount(Component, { propsData: { days, activeDay } });
const activeButton = wrapper.find('[data-days="60"].active');
expect(activeButton.attributes('data-days')).toMatch('60');
});
it('should render with 30 days selected', () => {
const activeDay = DAYS.THIRTY;
const wrapper = shallowMount(Component, { propsData: { days, activeDay } });
const activeButton = wrapper.find('[data-days="30"].active');
expect(activeButton.attributes('data-days')).toMatch('30');
});
});
describe('when clicking the button', () => {
const activeDay = DAYS.THIRTY;
let wrapper;
beforeEach(() => {
wrapper = mount(Component, { propsData: { days, activeDay }, sync: false });
});
it('should call the clickHandler', () => {
spyOn(wrapper.vm, 'clickHandler').and.stub();
wrapper.find('[data-days="30"].active').trigger('click', 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);
expect(wrapper.emitted().click[0]).toEqual([DAYS.THIRTY]);
});
});
});
...@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import testAction from 'spec/helpers/vuex_action_helper'; import testAction from 'spec/helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import { DAYS } from 'ee/security_dashboard/store/modules/vulnerabilities/constants';
import initialState from 'ee/security_dashboard/store/modules/vulnerabilities/state'; import initialState from 'ee/security_dashboard/store/modules/vulnerabilities/state';
import * as types from 'ee/security_dashboard/store/modules/vulnerabilities/mutation_types'; import * as types from 'ee/security_dashboard/store/modules/vulnerabilities/mutation_types';
...@@ -708,6 +709,26 @@ describe('vulnerabilities history actions', () => { ...@@ -708,6 +709,26 @@ describe('vulnerabilities history actions', () => {
}); });
}); });
describe('setVulnerabilitiesHistoryDayRange', () => {
it('should commit the number of past days to show', done => {
const state = initialState;
const days = DAYS.THIRTY;
testAction(
actions.setVulnerabilitiesHistoryDayRange,
days,
state,
[
{
type: types.SET_VULNERABILITIES_HISTORY_DAY_RANGE,
payload: days,
},
],
[],
done,
);
});
});
describe('fetchVulnerabilitiesTimeline', () => { describe('fetchVulnerabilitiesTimeline', () => {
let mock; let mock;
const state = initialState; const state = initialState;
......
...@@ -373,7 +373,38 @@ ...@@ -373,7 +373,38 @@
"2018-12-28": 72, "2018-12-28": 72,
"2018-12-29": 58, "2018-12-29": 58,
"2018-12-30": 68, "2018-12-30": 68,
"2018-12-31": 54 "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": { "unknown": {
"2018-10-1": 39, "2018-10-1": 39,
...@@ -561,6 +592,37 @@ ...@@ -561,6 +592,37 @@
"2018-12-28": 136, "2018-12-28": 136,
"2018-12-29": 144, "2018-12-29": 144,
"2018-12-30": 131, "2018-12-30": 131,
"2018-12-31": 142 "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
} }
} }
\ No newline at end of file
import createState from 'ee/security_dashboard/store/modules/vulnerabilities/state';
import { DAYS } from 'ee/security_dashboard/store/modules/vulnerabilities/constants';
import * as getters from 'ee/security_dashboard/store/modules/vulnerabilities/getters'; import * as getters from 'ee/security_dashboard/store/modules/vulnerabilities/getters';
import mockHistoryData from '../vulnerabilities/data/mock_data_vulnerabilities_history.json';
describe('vulnerabilities module getters', () => { describe('vulnerabilities module getters', () => {
describe('dashboardError', () => { describe('dashboardError', () => {
...@@ -53,4 +56,52 @@ describe('vulnerabilities module getters', () => { ...@@ -53,4 +56,52 @@ describe('vulnerabilities module getters', () => {
expect(result).toBe(false); expect(result).toBe(false);
}); });
}); });
describe('getFilteredVulnerabilitiesHistory', () => {
let state;
const mockedGetters = () => {
const getVulnerabilityHistoryByName = name =>
getters.getVulnerabilityHistoryByName(state)(name);
return { getVulnerabilityHistoryByName };
};
beforeEach(() => {
state = createState();
state.vulnerabilitiesHistory = mockHistoryData;
jasmine.clock().install();
jasmine.clock().mockDate(new Date(2019, 1, 2));
});
afterEach(function() {
jasmine.clock().uninstall();
});
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.length).toEqual(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.length).toEqual(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.length).toEqual(88);
});
});
}); });
import createState from 'ee/security_dashboard/store/modules/vulnerabilities/state'; import createState from 'ee/security_dashboard/store/modules/vulnerabilities/state';
import * as types from 'ee/security_dashboard/store/modules/vulnerabilities/mutation_types'; import * as types from 'ee/security_dashboard/store/modules/vulnerabilities/mutation_types';
import mutations from 'ee/security_dashboard/store/modules/vulnerabilities/mutations'; import mutations from 'ee/security_dashboard/store/modules/vulnerabilities/mutations';
import { DAYS } from 'ee/security_dashboard/store/modules/vulnerabilities/constants';
import mockData from './data/mock_data_vulnerabilities.json'; import mockData from './data/mock_data_vulnerabilities.json';
describe('vulnerabilities module mutations', () => { describe('vulnerabilities module mutations', () => {
...@@ -191,6 +192,52 @@ describe('vulnerabilities module mutations', () => { ...@@ -191,6 +192,52 @@ describe('vulnerabilities module mutations', () => {
}); });
}); });
describe('SET_VULNERABILITIES_HISTORY_DAY_RANGE', () => {
let state;
beforeEach(() => {
state = createState();
});
it('should set the vulnerabilitiesHistoryDayRange to number of days', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.THIRTY);
expect(state.vulnerabilitiesHistoryDayRange).toEqual(DAYS.THIRTY);
});
it('should set the vulnerabilitiesHistoryShowSplitLine to true if 30 days or under', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.THIRTY);
expect(state.vulnerabilitiesHistoryShowSplitLine).toEqual(true);
});
it('should set the vulnerabilitiesHistoryShowSplitLine to false if 30 days or over', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.SIXTY);
expect(state.vulnerabilitiesHistoryShowSplitLine).toEqual(false);
});
it('should set the vulnerabilitiesHistoryMaxDayInterval to 1 if days are 30 and under', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.THIRTY);
expect(state.vulnerabilitiesHistoryMaxDayInterval).toEqual(1);
});
it('should set the vulnerabilitiesHistoryMaxDayInterval to 7 if between 30 and 60', () => {
const days = 45;
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, days);
expect(state.vulnerabilitiesHistoryMaxDayInterval).toEqual(7);
});
it('should set the vulnerabilitiesHistoryMaxDayInterval to 14 if over 60', () => {
mutations[types.SET_VULNERABILITIES_HISTORY_DAY_RANGE](state, DAYS.NINETY);
expect(state.vulnerabilitiesHistoryMaxDayInterval).toEqual(14);
});
});
describe('SET_MODAL_DATA', () => { describe('SET_MODAL_DATA', () => {
describe('with all the data', () => { describe('with all the data', () => {
const vulnerability = mockData[0]; const vulnerability = mockData[0];
......
...@@ -268,6 +268,11 @@ msgid_plural "%{count} %{type} modifications" ...@@ -268,6 +268,11 @@ msgid_plural "%{count} %{type} modifications"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "1 Day"
msgid_plural "%d Days"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue" msgid "1 closed issue"
msgid_plural "%d closed issues" msgid_plural "%d closed issues"
msgstr[0] "" msgstr[0] ""
......
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