Commit 0a6c6fdd authored by Dheeraj Joshi's avatar Dheeraj Joshi Committed by Peter Hegman

Add markdown support for Vulnerability Description

This change would start rendering markdown content
for vulnerability page when description_html field
value is present. It should render markdown as plain
text otherwise, which is the current behavior.

Changelog: added
EE: true
parent 749370c5
<script> <script>
import { GlLink, GlSprintf } from '@gitlab/ui'; import { GlLink, GlSprintf, GlSafeHtmlDirective } from '@gitlab/ui';
import { bodyWithFallBack } from 'ee/vue_shared/security_reports/components/helpers'; import { bodyWithFallBack } from 'ee/vue_shared/security_reports/components/helpers';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue'; import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import convertReportType from 'ee/vue_shared/security_reports/store/utils/convert_report_type'; import convertReportType from 'ee/vue_shared/security_reports/store/utils/convert_report_type';
...@@ -19,6 +19,9 @@ export default { ...@@ -19,6 +19,9 @@ export default {
GlSprintf, GlSprintf,
VulnerabilityDetailSection, VulnerabilityDetailSection,
}, },
directives: {
SafeHtml: GlSafeHtmlDirective,
},
props: { props: {
vulnerability: { vulnerability: {
type: Object, type: Object,
...@@ -192,7 +195,13 @@ export default { ...@@ -192,7 +195,13 @@ export default {
{{ vulnerability.title }} {{ vulnerability.title }}
</h1> </h1>
<h3 class="mt-0">{{ __('Description') }}</h3> <h3 class="mt-0">{{ __('Description') }}</h3>
<p data-testid="description" data-qa-selector="vulnerability_description"> <p
v-if="vulnerability.descriptionHtml"
v-safe-html="vulnerability.descriptionHtml"
data-testid="description"
data-qa-selector="vulnerability_description"
></p>
<p v-else data-testid="description" data-qa-selector="vulnerability_description">
{{ vulnerability.description }} {{ vulnerability.description }}
</p> </p>
......
...@@ -73,6 +73,7 @@ module VulnerabilitiesHelper ...@@ -73,6 +73,7 @@ module VulnerabilitiesHelper
def vulnerability_finding_data(vulnerability) def vulnerability_finding_data(vulnerability)
data = Vulnerabilities::FindingSerializer.new(current_user: current_user).represent(vulnerability.finding, only: FINDING_FIELDS) data = Vulnerabilities::FindingSerializer.new(current_user: current_user).represent(vulnerability.finding, only: FINDING_FIELDS)
data[:location].merge!('blob_path' => vulnerability.blob_path).compact! data[:location].merge!('blob_path' => vulnerability.blob_path).compact!
data[:description_html] = markdown_field(vulnerability, :description)
data data
end end
......
...@@ -13,13 +13,13 @@ describe('Vulnerability Details', () => { ...@@ -13,13 +13,13 @@ describe('Vulnerability Details', () => {
confidence: 'high confidence', confidence: 'high confidence',
reportType: 'Some report type', reportType: 'Some report type',
description: 'vulnerability description', description: 'vulnerability description',
descriptionHtml: 'vulnerability description <code>sample</code>',
}; };
const createWrapper = (vulnerabilityOverrides) => { const createWrapper = (vulnerabilityOverrides) => {
const propsData = { const propsData = {
vulnerability: { ...vulnerability, ...vulnerabilityOverrides }, vulnerability: { ...vulnerability, ...vulnerabilityOverrides },
}; };
wrapper = mount(VulnerabilityDetails, { propsData }); wrapper = mount(VulnerabilityDetails, { propsData });
}; };
...@@ -33,7 +33,7 @@ describe('Vulnerability Details', () => { ...@@ -33,7 +33,7 @@ describe('Vulnerability Details', () => {
it('shows the properties that should always be shown', () => { it('shows the properties that should always be shown', () => {
createWrapper(); createWrapper();
expect(getText('description')).toBe(vulnerability.description); expect(getById('description').html()).toContain(vulnerability.descriptionHtml);
expect(wrapper.find(SeverityBadge).props('severity')).toBe(vulnerability.severity); expect(wrapper.find(SeverityBadge).props('severity')).toBe(vulnerability.severity);
expect(getText('reportType')).toBe(`Tool: ${vulnerability.reportType}`); expect(getText('reportType')).toBe(`Tool: ${vulnerability.reportType}`);
...@@ -49,6 +49,14 @@ describe('Vulnerability Details', () => { ...@@ -49,6 +49,14 @@ describe('Vulnerability Details', () => {
expect(getAllById('identifier')).toHaveLength(0); expect(getAllById('identifier')).toHaveLength(0);
}); });
it('renders description when descriptionHtml is not present', () => {
createWrapper({
descriptionHtml: null,
});
expect(getById('description').html()).not.toContain(vulnerability.descriptionHtml);
expect(getText('description')).toBe(vulnerability.description);
});
it.each` it.each`
reportType | expectedOutput reportType | expectedOutput
${'SAST'} | ${'SAST'} ${'SAST'} | ${'SAST'}
......
...@@ -2,6 +2,7 @@ export const mockVulnerability = { ...@@ -2,6 +2,7 @@ export const mockVulnerability = {
id: 1, id: 1,
title: 'Vulnerability Title', title: 'Vulnerability Title',
description: 'Vulnerability Description', description: 'Vulnerability Description',
descriptionHtml: 'Vulnerability Description <code>sample</code>',
created_at: new Date(2020, 0, 1).toISOString(), created_at: new Date(2020, 0, 1).toISOString(),
severity: 'medium', severity: 'medium',
state: 'detected', state: 'detected',
......
...@@ -60,7 +60,10 @@ describe('Vulnerability Report', () => { ...@@ -60,7 +60,10 @@ describe('Vulnerability Report', () => {
}); });
it("displays the vulnerability's description", () => { it("displays the vulnerability's description", () => {
expect(screen.getByText(mockVulnerability.description)).toBeInstanceOf(HTMLElement); const section = screen.getByTestId('description');
expect(section).toBeInstanceOf(HTMLElement);
expect(section.innerHTML).toBe(mockVulnerability.descriptionHtml);
}); });
it('displays related issues', async () => { it('displays related issues', async () => {
......
...@@ -306,6 +306,7 @@ RSpec.describe VulnerabilitiesHelper do ...@@ -306,6 +306,7 @@ RSpec.describe VulnerabilitiesHelper do
it 'returns finding information' do it 'returns finding information' do
expect(subject.to_h).to match( expect(subject.to_h).to match(
description: finding.description, description: finding.description,
description_html: anything,
identifiers: kind_of(Array), identifiers: kind_of(Array),
issue_feedback: anything, issue_feedback: anything,
links: finding.links, links: finding.links,
......
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