Commit 17781208 authored by Peter Hegman's avatar Peter Hegman

Merge branch 'djadmin-vuln-desc-render-md' into 'master'

Render markdown for Vulnerability Description

See merge request gitlab-org/gitlab!75859
parents f3ba00e6 0a6c6fdd
<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