Commit d59eb9c9 authored by Sam Beckham's avatar Sam Beckham Committed by Mark Florian

Adds a remediation badge on vuln list

Adds, translates, and tests a remediation badge on the vulnerability
list component.
parent 2abade0e
<script>
import { GlBadge, GlPopover } from '@gitlab/ui';
export default {
name: 'RemediatedBadge',
components: {
GlBadge,
GlPopover,
},
};
</script>
<template>
<div class="d-inline-block">
<gl-badge ref="badge" variant="info">{{ __('Remediated: needs review') }}</gl-badge>
<gl-popover
ref="popover"
:content="
__(
'The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status.',
)
"
:target="() => $refs.badge.$el"
:title="__('Vulnerability remediated. Review before resolving.')"
placement="top"
triggers="hover focus"
/>
</div>
</template>
<script>
import { s__, __ } from '~/locale';
import { GlEmptyState, GlLink, GlSkeletonLoading, GlTable } from '@gitlab/ui';
import RemediatedBadge from './remediated_badge.vue';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
export default {
......@@ -10,6 +11,7 @@ export default {
GlLink,
GlSkeletonLoading,
GlTable,
RemediatedBadge,
SeverityBadge,
},
props: {
......@@ -77,9 +79,10 @@ export default {
</template>
<template #cell(title)="{ item }">
<gl-link class="text-body js-description" :href="vulnerabilityPath(item)">{{
item.title
}}</gl-link>
<gl-link class="text-body js-description" :href="vulnerabilityPath(item)">
{{ item.title }}
</gl-link>
<remediated-badge v-if="item.resolved_on_default_branch" class="ml-2" />
</template>
<template #table-busy>
......
// eslint-disable-next-line import/prefer-default-export
export const vulnerabilities = [
export const generateVulnerabilities = () => [
{
id: 'id_0',
title: 'Vuln1',
title: 'Vulnerability 1',
severity: 'critical',
state: 'dismissed',
},
{
id: 'id_1',
title: 'Vuln2',
title: 'Vulnerability 2',
severity: 'high',
state: 'opened',
},
];
export const vulnerabilities = generateVulnerabilities();
import { shallowMount } from '@vue/test-utils';
import { GlBadge, GlPopover } from '@gitlab/ui';
import RemediatedBadge from 'ee/vulnerabilities/components/remediated_badge.vue';
const POPOVER_TITLE = 'Vulnerability remediated. Review before resolving.';
const POPOVER_CONTENT =
'The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status.';
describe('Remediated badge component', () => {
let wrapper;
const createWrapper = () => {
return shallowMount(RemediatedBadge);
};
beforeEach(() => {
wrapper = createWrapper();
});
afterEach(() => wrapper.destroy());
it('should link the badge and the popover', () => {
const badge = wrapper.find(GlBadge);
const { popover } = wrapper.vm.$refs;
expect(popover.$attrs.target()).toEqual(badge.element);
});
it('should pass down the data to the popover', () => {
const popoverAttributes = wrapper.find(GlPopover).attributes();
expect(popoverAttributes.title).toEqual(POPOVER_TITLE);
expect(popoverAttributes.content).toEqual(POPOVER_CONTENT);
});
});
import { mount } from '@vue/test-utils';
import { GlEmptyState, GlSkeletonLoading } from '@gitlab/ui';
import RemediatedBadge from 'ee/vulnerabilities/components/remediated_badge.vue';
import VulnerabilityList from 'ee/vulnerabilities/components/vulnerability_list.vue';
import { vulnerabilities } from './mock_data';
import { generateVulnerabilities } from './mock_data';
describe('Vulnerability list component', () => {
let wrapper;
......@@ -14,15 +15,23 @@ describe('Vulnerability list component', () => {
vulnerabilities: [],
...props,
},
stubs: {
GlPopover: true,
},
attachToDocument: true,
});
};
const findCell = label => wrapper.find(`.js-${label}`);
const findRow = (index = 0) => wrapper.findAll('tbody tr').at(index);
afterEach(() => wrapper.destroy());
describe('with vulnerabilities', () => {
let vulnerabilities;
beforeEach(() => {
vulnerabilities = generateVulnerabilities();
wrapper = createWrapper({ vulnerabilities });
});
......@@ -48,6 +57,30 @@ describe('Vulnerability list component', () => {
});
});
describe('when a vulnerability is resolved on the default branch', () => {
let vulnerabilities;
beforeEach(() => {
vulnerabilities = generateVulnerabilities();
vulnerabilities[0].resolved_on_default_branch = true;
wrapper = createWrapper({ vulnerabilities });
});
it('should render the remediated info badge on the first vulnerability', () => {
const row = findRow(0);
const badge = row.find(RemediatedBadge);
expect(badge.exists()).toEqual(true);
});
it('should not render the remediated info badge on the second vulnerability', () => {
const row = findRow(1);
const badge = row.find(RemediatedBadge);
expect(badge.exists()).toEqual(false);
});
});
describe('when loading', () => {
beforeEach(() => {
wrapper = createWrapper({ isLoading: true });
......
......@@ -16433,6 +16433,9 @@ msgstr ""
msgid "Release|Something went wrong while saving the release details"
msgstr ""
msgid "Remediated: needs review"
msgstr ""
msgid "Remember me"
msgstr ""
......@@ -19961,6 +19964,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
msgid "There are no GPG keys associated with this account."
msgstr ""
......@@ -22364,6 +22370,9 @@ msgstr ""
msgid "Vulnerability List"
msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
msgid "Vulnerability-Check"
msgstr ""
......
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