Commit b0f8a7a4 authored by Robert Hunt's avatar Robert Hunt

Merge branch '355864-gl-avatar-design-note' into 'master'

Use GlAvatar in design note

See merge request gitlab-org/gitlab!84033
parents 07d5eba6 e5deffc4
<script> <script>
import { GlTooltipDirective, GlIcon, GlLink, GlSafeHtmlDirective } from '@gitlab/ui'; import {
GlTooltipDirective,
GlIcon,
GlLink,
GlSafeHtmlDirective,
GlAvatar,
GlAvatarLink,
} from '@gitlab/ui';
import { ApolloMutation } from 'vue-apollo'; import { ApolloMutation } from 'vue-apollo';
import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale'; import { __ } from '~/locale';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql'; import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
import { hasErrors } from '../../utils/cache_update'; import { hasErrors } from '../../utils/cache_update';
import { findNoteId, extractDesignNoteId } from '../../utils/design_management_utils'; import { findNoteId, extractDesignNoteId } from '../../utils/design_management_utils';
...@@ -16,7 +22,8 @@ export default { ...@@ -16,7 +22,8 @@ export default {
editCommentLabel: __('Edit comment'), editCommentLabel: __('Edit comment'),
}, },
components: { components: {
UserAvatarLink, GlAvatar,
GlAvatarLink,
TimelineEntryItem, TimelineEntryItem,
TimeAgoTooltip, TimeAgoTooltip,
DesignReplyForm, DesignReplyForm,
...@@ -86,18 +93,17 @@ export default { ...@@ -86,18 +93,17 @@ export default {
<template> <template>
<timeline-entry-item :id="`note_${noteAnchorId}`" class="design-note note-form"> <timeline-entry-item :id="`note_${noteAnchorId}`" class="design-note note-form">
<user-avatar-link <gl-avatar-link :href="author.webUrl" class="gl-float-left gl-mr-3">
:link-href="author.webUrl" <gl-avatar :size="32" :src="author.avatarUrl" :entity-name="author.username" />
:img-src="author.avatarUrl" </gl-avatar-link>
:img-alt="author.username"
:img-size="40"
/>
<div class="gl-display-flex gl-justify-content-space-between"> <div class="gl-display-flex gl-justify-content-space-between">
<div> <div>
<gl-link <gl-link
v-once v-once
:href="author.webUrl" :href="author.webUrl"
class="js-user-link" class="js-user-link"
data-testid="user-link"
:data-user-id="authorId" :data-user-id="authorId"
:data-username="author.username" :data-username="author.username"
> >
...@@ -123,7 +129,8 @@ export default { ...@@ -123,7 +129,8 @@ export default {
type="button" type="button"
:title="$options.i18n.editCommentLabel" :title="$options.i18n.editCommentLabel"
:aria-label="$options.i18n.editCommentLabel" :aria-label="$options.i18n.editCommentLabel"
class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button" class="note-action-button btn btn-transparent qa-note-edit-button"
data-testid="note-edit"
@click="isEditing = true" @click="isEditing = true"
> >
<gl-icon name="pencil" class="link-highlight" /> <gl-icon name="pencil" class="link-highlight" />
...@@ -133,8 +140,9 @@ export default { ...@@ -133,8 +140,9 @@ export default {
<template v-if="!isEditing"> <template v-if="!isEditing">
<div <div
v-safe-html="note.bodyHtml" v-safe-html="note.bodyHtml"
class="note-text js-note-text md" class="note-text md"
data-qa-selector="note_content" data-qa-selector="note_content"
data-testid="note-text"
></div> ></div>
<slot name="resolved-status"></slot> <slot name="resolved-status"></slot>
</template> </template>
......
...@@ -5,16 +5,19 @@ exports[`Design note component should match the snapshot 1`] = ` ...@@ -5,16 +5,19 @@ exports[`Design note component should match the snapshot 1`] = `
class="design-note note-form" class="design-note note-form"
id="note_123" id="note_123"
> >
<user-avatar-link-stub <gl-avatar-link-stub
imgalt="foo-bar" class="gl-float-left gl-mr-3"
imgcssclasses="" href="https://gitlab.com/user"
imgsize="40" >
imgsrc="" <gl-avatar-stub
linkhref="" alt="avatar"
tooltipplacement="top" entityid="0"
tooltiptext="" entityname="foo-bar"
username="" shape="circle"
/> size="32"
src="https://gitlab.com/avatar"
/>
</gl-avatar-link-stub>
<div <div
class="gl-display-flex gl-justify-content-space-between" class="gl-display-flex gl-justify-content-space-between"
...@@ -22,8 +25,10 @@ exports[`Design note component should match the snapshot 1`] = ` ...@@ -22,8 +25,10 @@ exports[`Design note component should match the snapshot 1`] = `
<div> <div>
<gl-link-stub <gl-link-stub
class="js-user-link" class="js-user-link"
data-testid="user-link"
data-user-id="1" data-user-id="1"
data-username="foo-bar" data-username="foo-bar"
href="https://gitlab.com/user"
> >
<span <span
class="note-header-author-name gl-font-weight-bold" class="note-header-author-name gl-font-weight-bold"
...@@ -69,8 +74,9 @@ exports[`Design note component should match the snapshot 1`] = ` ...@@ -69,8 +74,9 @@ exports[`Design note component should match the snapshot 1`] = `
</div> </div>
<div <div
class="note-text js-note-text md" class="note-text md"
data-qa-selector="note_content" data-qa-selector="note_content"
data-testid="note-text"
/> />
</timeline-entry-item-stub> </timeline-entry-item-stub>
......
import { shallowMount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo'; import { ApolloMutation } from 'vue-apollo';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { GlAvatar, GlAvatarLink } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import DesignNote from '~/design_management/components/design_notes/design_note.vue'; import DesignNote from '~/design_management/components/design_notes/design_note.vue';
import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue'; import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
const scrollIntoViewMock = jest.fn(); const scrollIntoViewMock = jest.fn();
const note = { const note = {
...@@ -12,6 +12,8 @@ const note = { ...@@ -12,6 +12,8 @@ const note = {
author: { author: {
id: 'gid://gitlab/User/1', id: 'gid://gitlab/User/1',
username: 'foo-bar', username: 'foo-bar',
avatarUrl: 'https://gitlab.com/avatar',
webUrl: 'https://gitlab.com/user',
}, },
body: 'test', body: 'test',
userPermissions: { userPermissions: {
...@@ -30,14 +32,15 @@ const mutate = jest.fn().mockResolvedValue({ data: { updateNote: {} } }); ...@@ -30,14 +32,15 @@ const mutate = jest.fn().mockResolvedValue({ data: { updateNote: {} } });
describe('Design note component', () => { describe('Design note component', () => {
let wrapper; let wrapper;
const findUserAvatar = () => wrapper.find(UserAvatarLink); const findUserAvatar = () => wrapper.findComponent(GlAvatar);
const findUserLink = () => wrapper.find('.js-user-link'); const findUserAvatarLink = () => wrapper.findComponent(GlAvatarLink);
const findReplyForm = () => wrapper.find(DesignReplyForm); const findUserLink = () => wrapper.findByTestId('user-link');
const findEditButton = () => wrapper.find('.js-note-edit'); const findReplyForm = () => wrapper.findComponent(DesignReplyForm);
const findNoteContent = () => wrapper.find('.js-note-text'); const findEditButton = () => wrapper.findByTestId('note-edit');
const findNoteContent = () => wrapper.findByTestId('note-text');
function createComponent(props = {}, data = { isEditing: false }) { function createComponent(props = {}, data = { isEditing: false }) {
wrapper = shallowMount(DesignNote, { wrapper = shallowMountExtended(DesignNote, {
propsData: { propsData: {
note: {}, note: {},
...props, ...props,
...@@ -71,12 +74,24 @@ describe('Design note component', () => { ...@@ -71,12 +74,24 @@ describe('Design note component', () => {
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('should render an author', () => { it('should render avatar with correct props', () => {
createComponent({
note,
});
expect(findUserAvatar().props()).toMatchObject({
src: note.author.avatarUrl,
entityName: note.author.username,
});
expect(findUserAvatarLink().attributes('href')).toBe(note.author.webUrl);
});
it('should render author details', () => {
createComponent({ createComponent({
note, note,
}); });
expect(findUserAvatar().exists()).toBe(true);
expect(findUserLink().exists()).toBe(true); expect(findUserLink().exists()).toBe(true);
}); });
......
...@@ -41,7 +41,7 @@ describe('Shortcuts', () => { ...@@ -41,7 +41,7 @@ describe('Shortcuts', () => {
).toHaveBeenCalled(); ).toHaveBeenCalled();
}); });
it('focues preview button inside edit comment form', () => { it('focuses preview button inside edit comment form', () => {
document.querySelector('.js-note-edit').click(); document.querySelector('.js-note-edit').click();
Shortcuts.toggleMarkdownPreview( Shortcuts.toggleMarkdownPreview(
......
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