Commit ed280250 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'kp-add-issuable-show-app-title' into 'master'

Issuable Show: Add IssuableTitle component

See merge request gitlab-org/gitlab!44732
parents 3381411d 1dc2c70b
<script>
import {
GlIcon,
GlButton,
GlIntersectionObserver,
GlTooltipDirective,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
export default {
components: {
GlIcon,
GlButton,
GlIntersectionObserver,
},
directives: {
GlTooltip: GlTooltipDirective,
SafeHtml,
},
props: {
issuable: {
type: Object,
required: true,
},
statusBadgeClass: {
type: String,
required: true,
},
statusIcon: {
type: String,
required: true,
},
enableEdit: {
type: Boolean,
required: true,
},
},
data() {
return {
stickyTitleVisible: false,
};
},
methods: {
handleTitleAppear() {
this.stickyTitleVisible = false;
},
handleTitleDisappear() {
this.stickyTitleVisible = true;
},
},
};
</script>
<template>
<div>
<div class="title-container">
<h2 v-safe-html="issuable.titleHtml" class="title qa-title" dir="auto"></h2>
<gl-button
v-if="enableEdit"
v-gl-tooltip.bottom
:title="__('Edit title and description')"
icon="pencil"
class="btn-edit js-issuable-edit qa-edit-button"
@click="$emit('edit-issuable', $event)"
/>
</div>
<gl-intersection-observer @appear="handleTitleAppear" @disappear="handleTitleDisappear">
<transition name="issuable-header-slide">
<div
v-if="stickyTitleVisible"
class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
data-testid="header"
>
<div
class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-mx-auto gl-px-5"
>
<p
data-testid="status"
class="issuable-status-box status-box gl-my-0"
:class="statusBadgeClass"
>
<gl-icon :name="statusIcon" class="gl-display-block d-sm-none gl-h-6!" />
<span class="gl-display-none d-sm-block"><slot name="status-badge"></slot></span>
</p>
<p
class="gl-font-weight-bold gl-overflow-hidden gl-white-space-nowrap gl-text-overflow-ellipsis gl-my-0"
:title="issuable.title"
>
{{ issuable.title }}
</p>
</div>
</div>
</transition>
</gl-intersection-observer>
</div>
</template>
...@@ -9524,6 +9524,9 @@ msgstr "" ...@@ -9524,6 +9524,9 @@ msgstr ""
msgid "Edit this release" msgid "Edit this release"
msgstr "" msgstr ""
msgid "Edit title and description"
msgstr ""
msgid "Edit wiki page" msgid "Edit wiki page"
msgstr "" msgstr ""
......
import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import IssuableTitle from '~/issuable_show/components/issuable_title.vue';
import { mockIssuableShowProps, mockIssuable } from '../mock_data';
const issuableTitleProps = {
issuable: mockIssuable,
...mockIssuableShowProps,
};
const createComponent = (propsData = issuableTitleProps) =>
shallowMount(IssuableTitle, {
propsData,
stubs: {
transition: true,
},
slots: {
'status-badge': 'Open',
},
directives: {
GlTooltip: createMockDirective(),
},
});
describe('IssuableTitle', () => {
let wrapper;
beforeEach(() => {
wrapper = createComponent();
});
afterEach(() => {
wrapper.destroy();
});
describe('methods', () => {
describe('handleTitleAppear', () => {
it('sets value of `stickyTitleVisible` prop to false', () => {
wrapper.find(GlIntersectionObserver).vm.$emit('appear');
expect(wrapper.vm.stickyTitleVisible).toBe(false);
});
});
describe('handleTitleDisappear', () => {
it('sets value of `stickyTitleVisible` prop to true', () => {
wrapper.find(GlIntersectionObserver).vm.$emit('disappear');
expect(wrapper.vm.stickyTitleVisible).toBe(true);
});
});
});
describe('template', () => {
it('renders issuable title', async () => {
const wrapperWithTitle = createComponent({
...mockIssuableShowProps,
issuable: {
...mockIssuable,
titleHtml: '<b>Sample</b> title',
},
});
await wrapperWithTitle.vm.$nextTick();
const titleEl = wrapperWithTitle.find('h2');
expect(titleEl.exists()).toBe(true);
expect(titleEl.html()).toBe('<h2 dir="auto" class="title qa-title"><b>Sample</b> title</h2>');
wrapperWithTitle.destroy();
});
it('renders edit button', () => {
const editButtonEl = wrapper.find(GlButton);
const tooltip = getBinding(editButtonEl.element, 'gl-tooltip');
expect(editButtonEl.exists()).toBe(true);
expect(editButtonEl.props('icon')).toBe('pencil');
expect(editButtonEl.attributes('title')).toBe('Edit title and description');
expect(tooltip).toBeDefined();
});
it('renders sticky header when `stickyTitleVisible` prop is true', async () => {
wrapper.setData({
stickyTitleVisible: true,
});
await wrapper.vm.$nextTick();
const stickyHeaderEl = wrapper.find('[data-testid="header"]');
expect(stickyHeaderEl.exists()).toBe(true);
expect(stickyHeaderEl.find(GlIcon).props('name')).toBe(issuableTitleProps.statusIcon);
expect(stickyHeaderEl.text()).toContain('Open');
expect(stickyHeaderEl.text()).toContain(issuableTitleProps.issuable.title);
});
});
});
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