Commit 362e0f54 authored by Savas Vedova's avatar Savas Vedova

Merge branch '327386-gfm-component' into 'master'

Generic Security Reports GFM component

See merge request gitlab-org/gitlab!62788
parents 781f6dbd 86ef40a1
import axios from '../lib/utils/axios_utils';
import { buildApiUrl } from './api_utils';
const MARKDOWN_PATH = '/api/:version/markdown';
export function getMarkdown(options) {
const url = buildApiUrl(MARKDOWN_PATH);
return axios.post(url, {
...options,
});
}
export * from './api/groups_api';
export * from './api/projects_api';
export * from './api/user_api';
export * from './api/markdown_api';
// Note: It's not possible to spy on methods imported from this file in
// Jest tests. See https://stackoverflow.com/a/53307822/1063392.
......
......@@ -11,6 +11,7 @@ export const REPORT_TYPES = {
fileLocation: 'file-location',
table: 'table',
code: 'code',
markdown: 'markdown',
};
const REPORT_TYPE_TO_COMPONENT_MAP = {
......@@ -24,6 +25,7 @@ const REPORT_TYPE_TO_COMPONENT_MAP = {
[REPORT_TYPES.fileLocation]: () => import('./file_location.vue'),
[REPORT_TYPES.table]: () => import('./table.vue'),
[REPORT_TYPES.code]: () => import('./code.vue'),
[REPORT_TYPES.markdown]: () => import('./markdown.vue'),
};
export const getComponentNameForType = (reportType) =>
......
<script>
import { GlSkeletonLoader, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import { getMarkdown } from '~/rest_api';
export default {
components: { GlSkeletonLoader },
directives: {
SafeHtml,
},
inheritAttrs: false,
props: {
value: {
type: String,
required: true,
},
},
data() {
return {
markdown: '',
loading: true,
error: false,
};
},
mounted() {
this.renderMarkdown();
},
methods: {
async renderMarkdown() {
this.loading = true;
try {
const { data } = await getMarkdown({ text: this.value, gfm: true });
this.markdown = data.html;
} catch (e) {
Sentry.captureException(e);
this.error = true;
}
this.loading = false;
},
},
};
</script>
<template>
<div>
<gl-skeleton-loader v-if="loading" :width="200" :lines="2" />
<div v-if="markdown" v-safe-html="markdown" data-testid="markdown"></div>
</div>
</template>
......@@ -34,6 +34,10 @@ const TEST_DATA = {
lineStart: '1',
lineEnd: '2',
},
[REPORT_TYPES.markdown]: {
name: 'Markdown:',
value: 'Checkout [GitLab](http://gitlab.com)',
},
};
describe('ee/vulnerabilities/components/generic_report/report_item.vue', () => {
......
import { GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Markdown from 'ee/vulnerabilities/components/generic_report/types/markdown.vue';
import { buildApiUrl } from '~/api/api_utils';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
const MARKDOWN_PATH = '/api/:version/markdown';
// Original markdown
const MARKDOWN = 'Checkout [GitLab](http://gitlab.com) "><script>alert(1)</script>';
// HTML returned from /api/v4/markdown
const RENDERED_MARKDOWN =
'\u003cp data-sourcepos="1:1-1:79" dir="auto"\u003eCheckout \u003ca href="http://gitlab.com"\u003eGitLab\u003c/a\u003e Hello! Welcome "\u0026gt;\u003c/p\u003e';
// HTML with v-safe-html
const HTML_SAFE_RENDERED_MARKDOWN =
'\u003cp dir="auto" data-sourcepos="1:1-1:79"\u003eCheckout \u003ca href="http://gitlab.com"\u003eGitLab\u003c/a\u003e Hello! Welcome "\u0026gt;\u003c/p\u003e';
describe('ee/vulnerabilities/components/generic_report/types/markdown.vue', () => {
let wrapper;
let mock;
const createWrapper = () => {
return shallowMount(Markdown, {
propsData: {
value: MARKDOWN,
},
});
};
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findMarkdown = () => wrapper.find('[data-testid="markdown"]');
const setUpMockMarkdown = () => {
const url = buildApiUrl(MARKDOWN_PATH);
mock
.onPost(url, {
text: MARKDOWN,
gfm: true,
})
.replyOnce(httpStatusCodes.OK, { html: RENDERED_MARKDOWN });
};
beforeEach(() => {
mock = new MockAdapter(axios);
setUpMockMarkdown();
wrapper = createWrapper();
});
afterEach(() => {
mock.restore();
wrapper.destroy();
});
describe('when loading', () => {
it('shows the loading icon', () => {
expect(findSkeletonLoader().exists()).toBe(true);
});
});
describe('when loaded', () => {
it('shows markdown', async () => {
await axios.waitForAll();
expect(findSkeletonLoader().exists()).toBe(false);
expect(findMarkdown().element.innerHTML).toBe(HTML_SAFE_RENDERED_MARKDOWN);
});
});
});
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