Commit 31c993cd authored by Dave Pisek's avatar Dave Pisek

Vulnerability Chart: Fix selected state of buttons

This commit changes the buttons on the over-time vulnerabilities to
the recommended 'gl-segmented-control' component.

Changelog: changed
EE: true
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73516
parent 2a3aa782
......@@ -203,7 +203,7 @@ export default {
v-if="!isLoadingHistory"
:days="$options.days"
:active-day="vulnerabilitiesHistoryDayRange"
@click="setVulnerabilitiesHistoryDayRange"
@days-selected="setVulnerabilitiesHistoryDayRange"
/>
</div>
......
<script>
import { GlButton } from '@gitlab/ui';
import { GlSegmentedControl } from '@gitlab/ui';
import { n__ } from '~/locale';
export default {
name: 'VulnerabilityChartButtons',
components: {
GlButton,
GlSegmentedControl,
},
props: {
days: {
......@@ -18,28 +18,23 @@ export default {
},
},
computed: {
buttonContent() {
return (days) => n__('1 Day', '%d Days', days);
controlOptions() {
return this.days.map((day) => ({ text: n__('1 Day', '%d Days', day), value: day }));
},
},
methods: {
clickHandler(days) {
this.$emit('click', days);
inputHandler(days) {
this.$emit('days-selected', days);
},
},
};
</script>
<template>
<div class="btn-group w-100">
<gl-button
v-for="day in days"
:key="day"
:class="{ selected: activeDay === day }"
:data-days="day"
@click="clickHandler(day)"
>
{{ buttonContent(day) }}
</gl-button>
</div>
<gl-segmented-control
:options="controlOptions"
:checked="activeDay"
class="gl-display-flex"
@input="inputHandler"
/>
</template>
import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import Vue from 'vue';
import component from 'ee/security_dashboard/components/shared/vulnerabilities_over_time_chart_buttons.vue';
import { GlSegmentedControl } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import VulnerabilitiesOverTimeChartButtons from 'ee/security_dashboard/components/shared/vulnerabilities_over_time_chart_buttons.vue';
import { DAYS } from 'ee/security_dashboard/store/constants';
const localVue = createLocalVue();
describe('Vulnerability Chart Buttons', () => {
let wrapper;
const Component = Vue.extend(component);
const days = Object.values(DAYS);
const createWrapper = (props = {}, mountfn = shallowMount) => {
wrapper = mountfn(localVue.extend(Component), {
const findSegmentedControlButtons = () => wrapper.findComponent(GlSegmentedControl);
const createWrapper = (props = { activeDay: DAYS.thirty }) => {
wrapper = shallowMountExtended(VulnerabilitiesOverTimeChartButtons, {
propsData: { days, ...props },
localVue,
});
};
......@@ -21,53 +19,29 @@ describe('Vulnerability Chart Buttons', () => {
wrapper.destroy();
});
describe('when rendering the buttons', () => {
it('should render with 90 days selected', () => {
const activeDay = DAYS.ninety;
createWrapper({ activeDay });
const activeButton = wrapper.find('[data-days="90"].selected');
expect(activeButton.attributes('data-days')).toMatch('90');
});
it('should render with 60 days selected', () => {
const activeDay = DAYS.sixty;
createWrapper({ activeDay });
const activeButton = wrapper.find('[data-days="60"].selected');
it('should pass the correct options to the segmented control group', () => {
createWrapper();
expect(activeButton.attributes('data-days')).toMatch('60');
expect(findSegmentedControlButtons().props('options')).toStrictEqual([
{ value: DAYS.thirty, text: '30 Days' },
{ value: DAYS.sixty, text: '60 Days' },
{ value: DAYS.ninety, text: '90 Days' },
]);
});
it('should render with 30 days selected', () => {
const activeDay = DAYS.thirty;
it.each(days)('should set "%s days" as selected', (activeDay) => {
createWrapper({ activeDay });
const activeButton = wrapper.find('[data-days="30"].selected');
expect(activeButton.attributes('data-days')).toMatch('30');
});
});
describe('when clicking the button', () => {
const activeDay = DAYS.thirty;
beforeEach(() => {
createWrapper({ activeDay }, mount);
expect(findSegmentedControlButtons().props('checked')).toBe(activeDay);
});
it('should call the clickHandler', () => {
jest.spyOn(wrapper.vm, 'clickHandler');
wrapper.find('[data-days="30"].selected').trigger('click', DAYS.thirty);
it('should emit a "days-selected" event with the correct payload when the selection changes', () => {
createWrapper();
expect(wrapper.vm.clickHandler).toHaveBeenCalledWith(DAYS.thirty);
});
expect(wrapper.emitted('days-selected')).toBeFalsy();
it('should emit a click event', () => {
wrapper.find('[data-days="30"].selected').trigger('click', DAYS.thirty);
findSegmentedControlButtons().vm.$emit('input', DAYS.thirty);
expect(wrapper.emitted().click[0]).toEqual([DAYS.thirty]);
});
expect(wrapper.emitted('days-selected')).toEqual([[DAYS.thirty]]);
});
});
import { nextTick } from 'vue';
import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import VulnerabilitiesOverTimeChart from 'ee/security_dashboard/components/shared/vulnerabilities_over_time_chart.vue';
......@@ -19,8 +20,6 @@ describe('Vulnerabilities Over Time Chart Component', () => {
const findTimeInfo = () => wrapper.findByTestId('timeInfo');
const findChartButtons = () => wrapper.findComponent(ChartButtons);
const findSelectedChartButton = () => findChartButtons().find('.selected');
const find90DaysChartButton = () => findChartButtons().find('[data-days="90"]');
const mockApollo = (options) => {
return {
......@@ -69,26 +68,24 @@ describe('Vulnerabilities Over Time Chart Component', () => {
describe('date range selectors', () => {
beforeEach(() => {
wrapper = createComponent({
stubs: { ChartButtons },
$apollo: { refetch: jest.fn() },
});
});
it('should contain the chart buttons', () => {
expect(findChartButtons().text()).toContain('30 Days');
expect(findChartButtons().text()).toContain('60 Days');
expect(findChartButtons().text()).toContain('90 Days');
expect(findChartButtons().props('days')).toEqual([30, 60, 90]);
});
it('should change the actively selected chart button and refetch the new data', () => {
expect(findSelectedChartButton().text()).toContain('30 Days');
find90DaysChartButton().vm.$emit('click');
return wrapper.vm.$nextTick(() => {
expect(findSelectedChartButton().text()).toContain('90 Days');
it('should change the actively selected chart button and refetch the new data', async () => {
expect(findChartButtons().props('activeDay')).toBe(30);
findChartButtons().vm.$emit('days-selected', 90);
await nextTick();
expect(findChartButtons().props('activeDay')).toBe(90);
expect(wrapper.vm.$apollo.queries.vulnerabilitiesHistory.refetch).toHaveBeenCalledTimes(1);
});
});
});
describe('when loading the history chart for group level dashboard', () => {
beforeEach(() => {
......
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