summaryrefslogtreecommitdiff
path: root/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js')
-rw-r--r--spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js239
1 files changed, 239 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
new file mode 100644
index 00000000000..175abf5aae0
--- /dev/null
+++ b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
@@ -0,0 +1,239 @@
+import { mount, shallowMount } from '@vue/test-utils';
+import { hasHorizontalOverflow } from '~/lib/utils/dom_utils';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+
+const DUMMY_TEXT = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do';
+
+const createChildElement = () => `<a href="#">${DUMMY_TEXT}</a>`;
+
+jest.mock('~/lib/utils/dom_utils', () => ({
+ hasHorizontalOverflow: jest.fn(() => {
+ throw new Error('this needs to be mocked');
+ }),
+}));
+
+describe('TooltipOnTruncate component', () => {
+ let wrapper;
+ let parent;
+
+ const createComponent = ({ propsData, ...options } = {}) => {
+ wrapper = shallowMount(TooltipOnTruncate, {
+ attachToDocument: true,
+ propsData: {
+ ...propsData,
+ },
+ ...options,
+ });
+ };
+
+ const createWrappedComponent = ({ propsData, ...options }) => {
+ // set a parent around the tested component
+ parent = mount(
+ {
+ props: {
+ title: { default: '' },
+ },
+ template: `
+ <TooltipOnTruncate :title="title" truncate-target="child">
+ <div>{{title}}</div>
+ </TooltipOnTruncate>
+ `,
+ components: {
+ TooltipOnTruncate,
+ },
+ },
+ {
+ propsData: { ...propsData },
+ attachToDocument: true,
+ ...options,
+ },
+ );
+
+ wrapper = parent.find(TooltipOnTruncate);
+ };
+
+ const hasTooltip = () => wrapper.classes('js-show-tooltip');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with default target', () => {
+ it('renders tooltip if truncated', () => {
+ hasHorizontalOverflow.mockReturnValueOnce(true);
+ createComponent({
+ propsData: {
+ title: DUMMY_TEXT,
+ },
+ slots: {
+ default: [DUMMY_TEXT],
+ },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element);
+ expect(hasTooltip()).toBe(true);
+ expect(wrapper.attributes('data-original-title')).toEqual(DUMMY_TEXT);
+ expect(wrapper.attributes('data-placement')).toEqual('top');
+ });
+ });
+
+ it('does not render tooltip if normal', () => {
+ hasHorizontalOverflow.mockReturnValueOnce(false);
+ createComponent({
+ propsData: {
+ title: DUMMY_TEXT,
+ },
+ slots: {
+ default: [DUMMY_TEXT],
+ },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element);
+ expect(hasTooltip()).toBe(false);
+ });
+ });
+ });
+
+ describe('with child target', () => {
+ it('renders tooltip if truncated', () => {
+ hasHorizontalOverflow.mockReturnValueOnce(true);
+ createComponent({
+ propsData: {
+ title: DUMMY_TEXT,
+ truncateTarget: 'child',
+ },
+ slots: {
+ default: createChildElement(),
+ },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[0]);
+ expect(hasTooltip()).toBe(true);
+ });
+ });
+
+ it('does not render tooltip if normal', () => {
+ hasHorizontalOverflow.mockReturnValueOnce(false);
+ createComponent({
+ propsData: {
+ truncateTarget: 'child',
+ },
+ slots: {
+ default: createChildElement(),
+ },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[0]);
+ expect(hasTooltip()).toBe(false);
+ });
+ });
+ });
+
+ describe('with fn target', () => {
+ it('renders tooltip if truncated', () => {
+ hasHorizontalOverflow.mockReturnValueOnce(true);
+ createComponent({
+ propsData: {
+ title: DUMMY_TEXT,
+ truncateTarget: el => el.childNodes[1],
+ },
+ slots: {
+ default: [createChildElement(), createChildElement()],
+ },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[1]);
+ expect(hasTooltip()).toBe(true);
+ });
+ });
+ });
+
+ describe('placement', () => {
+ it('sets data-placement when tooltip is rendered', () => {
+ const placement = 'bottom';
+
+ hasHorizontalOverflow.mockReturnValueOnce(true);
+ createComponent({
+ propsData: {
+ placement,
+ },
+ slots: {
+ default: DUMMY_TEXT,
+ },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(hasTooltip()).toBe(true);
+ expect(wrapper.attributes('data-placement')).toEqual(placement);
+ });
+ });
+ });
+
+ describe('updates when title and slot content changes', () => {
+ describe('is initialized with a long text', () => {
+ beforeEach(() => {
+ hasHorizontalOverflow.mockReturnValueOnce(true);
+ createWrappedComponent({
+ propsData: { title: DUMMY_TEXT },
+ });
+ return parent.vm.$nextTick();
+ });
+
+ it('renders tooltip', () => {
+ expect(hasTooltip()).toBe(true);
+ expect(wrapper.attributes('data-original-title')).toEqual(DUMMY_TEXT);
+ expect(wrapper.attributes('data-placement')).toEqual('top');
+ });
+
+ it('does not render tooltip after updated to a short text', () => {
+ hasHorizontalOverflow.mockReturnValueOnce(false);
+ parent.setProps({
+ title: 'new-text',
+ });
+
+ return wrapper.vm
+ .$nextTick()
+ .then(() => wrapper.vm.$nextTick()) // wait 2 times to get an updated slot
+ .then(() => {
+ expect(hasTooltip()).toBe(false);
+ });
+ });
+ });
+
+ describe('is initialized with a short text', () => {
+ beforeEach(() => {
+ hasHorizontalOverflow.mockReturnValueOnce(false);
+ createWrappedComponent({
+ propsData: { title: DUMMY_TEXT },
+ });
+ return wrapper.vm.$nextTick();
+ });
+
+ it('does not render tooltip', () => {
+ expect(hasTooltip()).toBe(false);
+ });
+
+ it('renders tooltip after text is updated', () => {
+ hasHorizontalOverflow.mockReturnValueOnce(true);
+ const newText = 'new-text';
+ parent.setProps({
+ title: newText,
+ });
+
+ return wrapper.vm
+ .$nextTick()
+ .then(() => wrapper.vm.$nextTick()) // wait 2 times to get an updated slot
+ .then(() => {
+ expect(hasTooltip()).toBe(true);
+ expect(wrapper.attributes('data-original-title')).toEqual(newText);
+ expect(wrapper.attributes('data-placement')).toEqual('top');
+ });
+ });
+ });
+ });
+});