Commit f61756d7 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 64bf537f c866f1f5
<script>
import { GlDropdown, GlDropdownItem, GlDropdownText, GlSearchBoxByType } from '@gitlab/ui';
import {
GlAvatarLabeled,
GlDropdown,
GlDropdownItem,
GlDropdownText,
GlSearchBoxByType,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
import { s__ } from '~/locale';
......@@ -8,6 +14,7 @@ import { SEARCH_DELAY } from '../constants';
export default {
name: 'GroupSelect',
components: {
GlAvatarLabeled,
GlDropdown,
GlDropdownItem,
GlDropdownText,
......@@ -49,6 +56,7 @@ export default {
id: group.id,
name: group.full_name,
path: group.path,
avatarUrl: group.avatar_url,
}));
this.isFetching = false;
})
......@@ -82,7 +90,7 @@ export default {
menu-class="gl-w-full!"
>
<gl-search-box-by-type
v-model.trim="searchTerm"
v-model="searchTerm"
:is-loading="isFetching"
:placeholder="$options.i18n.searchPlaceholder"
data-qa-selector="group_select_dropdown_search_field"
......@@ -93,7 +101,13 @@ export default {
:name="group.name"
@click="selectGroup(group)"
>
{{ group.name }}
<gl-avatar-labeled
:label="group.name"
:src="group.avatarUrl"
:entity-id="group.id"
:entity-name="group.name"
:size="32"
/>
</gl-dropdown-item>
<gl-dropdown-text v-if="isFetchResultEmpty && !isFetching" data-testid="empty-result-message">
<span class="gl-text-gray-500">{{ $options.i18n.emptySearchResult }}</span>
......
......@@ -30,6 +30,7 @@ export default {
return dateInWords(date);
},
},
safeHtmlConfig: { ADD_ATTR: ['target'] },
};
</script>
......@@ -71,7 +72,10 @@ export default {
<gl-icon name="license" />{{ packageName }}
</gl-badge>
</div>
<div v-safe-html="feature.body" class="gl-pt-3 gl-line-height-20"></div>
<div
v-safe-html:[$options.safeHtmlConfig]="feature.body"
class="gl-pt-3 gl-line-height-20"
></div>
<gl-button
:href="feature.url"
target="_blank"
......
......@@ -33,7 +33,7 @@ class ReleaseHighlight
next unless include_item?(item)
begin
item.tap {|i| i['body'] = Kramdown::Document.new(i['body']).to_html }
item.tap {|i| i['body'] = Banzai.render(i['body'], { project: nil }) }
rescue StandardError => e
Gitlab::ErrorTracking.track_exception(e, file_path: file_path)
......
---
- title: bright and sunshinin' day
body: |
## bright and sunshinin' day
bright and sunshinin' [day](https://en.wikipedia.org/wiki/Day)
self-managed: true
gitlab-com: false
packages: ["Premium", "Ultimate"]
......
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import { GlAvatarLabeled, GlDropdown, GlSearchBoxByType } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
......@@ -8,8 +8,8 @@ const createComponent = () => {
return mount(GroupSelect, {});
};
const group1 = { id: 1, full_name: 'Group One' };
const group2 = { id: 2, full_name: 'Group Two' };
const group1 = { id: 1, full_name: 'Group One', avatar_url: 'test' };
const group2 = { id: 2, full_name: 'Group Two', avatar_url: 'test' };
const allGroups = [group1, group2];
describe('GroupSelect', () => {
......@@ -29,10 +29,10 @@ describe('GroupSelect', () => {
const findSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType);
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findDropdownToggle = () => findDropdown().find('button[aria-haspopup="true"]');
const findDropdownItemByText = (text) =>
const findAvatarByLabel = (text) =>
wrapper
.findAllComponents(GlDropdownItem)
.wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.text() === text);
.findAllComponents(GlAvatarLabeled)
.wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.props('label') === text);
it('renders GlSearchBoxByType with default attributes', () => {
expect(findSearchBoxByType().exists()).toBe(true);
......@@ -74,9 +74,20 @@ describe('GroupSelect', () => {
});
});
describe('avatar label', () => {
it('includes the correct attributes with name and avatar_url', () => {
expect(findAvatarByLabel(group1.full_name).attributes()).toMatchObject({
src: group1.avatar_url,
'entity-id': `${group1.id}`,
'entity-name': group1.full_name,
size: '32',
});
});
});
describe('when group is selected from the dropdown', () => {
beforeEach(() => {
findDropdownItemByText(group1.full_name).vm.$emit('click');
findAvatarByLabel(group1.full_name).trigger('click');
});
it('emits `input` event used by `v-model`', () => {
......
......@@ -8,7 +8,7 @@ describe("What's new single feature", () => {
const exampleFeature = {
title: 'Compliance pipeline configurations',
body:
'<p>We are thrilled to announce that it is now possible to define enforceable pipelines that will run for any project assigned a corresponding compliance framework.</p>',
'<p data-testid="body-content">We are thrilled to announce that it is now possible to define enforceable pipelines that will run for any project assigned a corresponding <a href="https://en.wikipedia.org/wiki/Compliance_(psychology)" target="_blank" rel="noopener noreferrer" onload="alert(xss)">compliance</a> framework.</p>',
stage: 'Manage',
'self-managed': true,
'gitlab-com': true,
......@@ -20,6 +20,7 @@ describe("What's new single feature", () => {
};
const findReleaseDate = () => wrapper.find('[data-testid="release-date"]');
const findBodyAnchor = () => wrapper.find('[data-testid="body-content"] a');
const createWrapper = ({ feature } = {}) => {
wrapper = shallowMount(Feature, {
......@@ -43,4 +44,13 @@ describe("What's new single feature", () => {
expect(findReleaseDate().exists()).toBe(false);
});
});
it('safe-html config allows target attribute on elements', () => {
createWrapper({ feature: exampleFeature });
expect(findBodyAnchor().attributes()).toEqual({
href: expect.any(String),
rel: 'noopener noreferrer',
target: '_blank',
});
});
});
......@@ -67,12 +67,12 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
expect(subject[:next_page]).to eq(2)
end
it 'parses the body as markdown and returns html' do
expect(subject[:items].first['body']).to match("<h2 id=\"bright-and-sunshinin-day\">bright and sunshinin’ day</h2>")
it 'parses the body as markdown and returns html, and links are target="_blank"' do
expect(subject[:items].first['body']).to match('<p data-sourcepos="1:1-1:62" dir="auto">bright and sunshinin\' <a href="https://en.wikipedia.org/wiki/Day" rel="nofollow noreferrer noopener" target="_blank">day</a></p>')
end
it 'logs an error if theres an error parsing markdown for an item, and skips it' do
allow(Kramdown::Document).to receive(:new).and_raise
allow(Banzai).to receive(:render).and_raise
expect(Gitlab::ErrorTracking).to receive(:track_exception)
expect(subject[:items]).to be_empty
......
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