Commit e6fca870 authored by 🕺 Winnie 🕺's avatar 🕺 Winnie 🕺 Committed by Paul Slaughter

Migrate tooltip_on_truncate_spec.js to Jest

https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47582
parent 8ca85a26
import { has } from 'lodash';
import { isInIssuePage, isInMRPage, isInEpicPage } from './common_utils';
/**
* Checks whether an element's content exceeds the element's width.
*
* @param element DOM element to check
*/
export const hasHorizontalOverflow = element =>
Boolean(element && element.scrollWidth > element.offsetWidth);
export const addClassIfElementExists = (element, className) => {
if (element) {
element.classList.add(className);
......
......@@ -49,5 +49,3 @@ export const toggleDisableButton = ($button, disable) => {
if (disable && $button.prop('disabled')) return;
$button.prop('disabled', disable);
};
export default {};
<script>
import { isFunction } from 'lodash';
import tooltip from '../directives/tooltip';
import { hasHorizontalOverflow } from '~/lib/utils/dom_utils';
export default {
directives: {
......@@ -49,7 +50,7 @@ export default {
},
updateTooltip() {
const target = this.selectTarget();
this.showTooltip = Boolean(target && target.scrollWidth > target.offsetWidth);
this.showTooltip = hasHorizontalOverflow(target);
},
},
};
......
// this file can't be migrated to jest because it relies on the browser to perform integration tests:
// (specifically testing around css properties `overflow` and `white-space`)
// see: https://gitlab.com/groups/gitlab-org/-/epics/895#what-if-theres-a-karma-spec-which-is-simply-unmovable-to-jest-ie-it-is-dependent-on-a-running-browser-environment
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 TEXT_SHORT = 'lorem';
const TEXT_LONG = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do';
const DUMMY_TEXT = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do';
const TEXT_TRUNCATE = 'white-space: nowrap; overflow:hidden;';
const STYLE_NORMAL = `${TEXT_TRUNCATE} display: inline-block; max-width: 1000px;`; // does not overflows
const STYLE_OVERFLOWED = `${TEXT_TRUNCATE} display: inline-block; max-width: 50px;`; // overflowed when text is long
const createChildElement = () => `<a href="#">${DUMMY_TEXT}</a>`;
const createElementWithStyle = (style, content) => `<a href="#" style="${style}">${content}</a>`;
jest.mock('~/lib/utils/dom_utils', () => ({
hasHorizontalOverflow: jest.fn(() => {
throw new Error('this needs to be mocked');
}),
}));
describe('TooltipOnTruncate component', () => {
let wrapper;
......@@ -24,9 +22,6 @@ describe('TooltipOnTruncate component', () => {
propsData: {
...propsData,
},
attrs: {
style: STYLE_OVERFLOWED,
},
...options,
});
};
......@@ -39,7 +34,7 @@ describe('TooltipOnTruncate component', () => {
title: { default: '' },
},
template: `
<TooltipOnTruncate :title="title" truncate-target="child" style="${STYLE_OVERFLOWED}">
<TooltipOnTruncate :title="title" truncate-target="child">
<div>{{title}}</div>
</TooltipOnTruncate>
`,
......@@ -65,33 +60,37 @@ describe('TooltipOnTruncate component', () => {
describe('with default target', () => {
it('renders tooltip if truncated', () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
title: TEXT_LONG,
title: DUMMY_TEXT,
},
slots: {
default: [TEXT_LONG],
default: [DUMMY_TEXT],
},
});
return wrapper.vm.$nextTick().then(() => {
expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element);
expect(hasTooltip()).toBe(true);
expect(wrapper.attributes('data-original-title')).toEqual(TEXT_LONG);
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: TEXT_SHORT,
title: DUMMY_TEXT,
},
slots: {
default: [TEXT_SHORT],
default: [DUMMY_TEXT],
},
});
return wrapper.vm.$nextTick().then(() => {
expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element);
expect(hasTooltip()).toBe(false);
});
});
......@@ -99,35 +98,36 @@ describe('TooltipOnTruncate component', () => {
describe('with child target', () => {
it('renders tooltip if truncated', () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
attrs: {
style: STYLE_NORMAL,
},
propsData: {
title: TEXT_LONG,
title: DUMMY_TEXT,
truncateTarget: 'child',
},
slots: {
default: createElementWithStyle(STYLE_OVERFLOWED, TEXT_LONG),
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: createElementWithStyle(STYLE_NORMAL, TEXT_LONG),
default: createChildElement(),
},
});
return wrapper.vm.$nextTick().then(() => {
expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[0]);
expect(hasTooltip()).toBe(false);
});
});
......@@ -135,23 +135,19 @@ describe('TooltipOnTruncate component', () => {
describe('with fn target', () => {
it('renders tooltip if truncated', () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
attrs: {
style: STYLE_NORMAL,
},
propsData: {
title: TEXT_LONG,
title: DUMMY_TEXT,
truncateTarget: el => el.childNodes[1],
},
slots: {
default: [
createElementWithStyle('', TEXT_LONG),
createElementWithStyle(STYLE_OVERFLOWED, TEXT_LONG),
],
default: [createChildElement(), createChildElement()],
},
});
return wrapper.vm.$nextTick().then(() => {
expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[1]);
expect(hasTooltip()).toBe(true);
});
});
......@@ -161,15 +157,13 @@ describe('TooltipOnTruncate component', () => {
it('sets data-placement when tooltip is rendered', () => {
const placement = 'bottom';
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
placement,
},
attrs: {
style: STYLE_OVERFLOWED,
},
slots: {
default: TEXT_LONG,
default: DUMMY_TEXT,
},
});
......@@ -183,21 +177,23 @@ describe('TooltipOnTruncate component', () => {
describe('updates when title and slot content changes', () => {
describe('is initialized with a long text', () => {
beforeEach(() => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createWrappedComponent({
propsData: { title: TEXT_LONG },
propsData: { title: DUMMY_TEXT },
});
return parent.vm.$nextTick();
});
it('renders tooltip', () => {
expect(hasTooltip()).toBe(true);
expect(wrapper.attributes('data-original-title')).toEqual(TEXT_LONG);
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: TEXT_SHORT,
title: 'new-text',
});
return wrapper.vm
......@@ -211,8 +207,9 @@ describe('TooltipOnTruncate component', () => {
describe('is initialized with a short text', () => {
beforeEach(() => {
hasHorizontalOverflow.mockReturnValueOnce(false);
createWrappedComponent({
propsData: { title: TEXT_SHORT },
propsData: { title: DUMMY_TEXT },
});
return wrapper.vm.$nextTick();
});
......@@ -221,9 +218,11 @@ describe('TooltipOnTruncate component', () => {
expect(hasTooltip()).toBe(false);
});
it('renders tooltip after updated to a long text', () => {
it('renders tooltip after text is updated', () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
const newText = 'new-text';
parent.setProps({
title: TEXT_LONG,
title: newText,
});
return wrapper.vm
......@@ -231,7 +230,7 @@ describe('TooltipOnTruncate component', () => {
.then(() => wrapper.vm.$nextTick()) // wait 2 times to get an updated slot
.then(() => {
expect(hasTooltip()).toBe(true);
expect(wrapper.attributes('data-original-title')).toEqual(TEXT_LONG);
expect(wrapper.attributes('data-original-title')).toEqual(newText);
expect(wrapper.attributes('data-placement')).toEqual('top');
});
});
......
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