Commit 1dc2c70b authored by Kushal Pandya's avatar Kushal Pandya

Add IssuableTitle component

Adds IssuableTitle component to use with
Issuable Show app.
parent ad9886b9
<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>
...@@ -9509,6 +9509,9 @@ msgstr "" ...@@ -9509,6 +9509,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