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.js233
1 files changed, 133 insertions, 100 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
index 380b7231acd..9e7e5c1263f 100644
--- a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
+++ b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
@@ -1,25 +1,20 @@
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { hasHorizontalOverflow } from '~/lib/utils/dom_utils';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-const DUMMY_TEXT = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do';
+const MOCK_TITLE = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do';
+const SHORT_TITLE = 'my-text';
-const createChildElement = () => `<a href="#">${DUMMY_TEXT}</a>`;
+const createChildElement = () => `<a href="#">${MOCK_TITLE}</a>`;
jest.mock('~/lib/utils/dom_utils', () => ({
- hasHorizontalOverflow: jest.fn(() => {
+ ...jest.requireActual('~/lib/utils/dom_utils'),
+ hasHorizontalOverflow: jest.fn().mockImplementation(() => {
throw new Error('this needs to be mocked');
}),
}));
-jest.mock('@gitlab/ui', () => ({
- GlTooltipDirective: {
- bind(el, binding) {
- el.classList.add('gl-tooltip');
- el.setAttribute('data-original-title', el.title);
- el.dataset.placement = binding.value.placement;
- },
- },
-}));
describe('TooltipOnTruncate component', () => {
let wrapper;
@@ -27,15 +22,31 @@ describe('TooltipOnTruncate component', () => {
const createComponent = ({ propsData, ...options } = {}) => {
wrapper = shallowMount(TooltipOnTruncate, {
- attachTo: document.body,
propsData: {
+ title: MOCK_TITLE,
...propsData,
},
+ slots: {
+ default: [MOCK_TITLE],
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ GlResizeObserver: createMockDirective(),
+ },
...options,
});
};
const createWrappedComponent = ({ propsData, ...options }) => {
+ const WrappedTooltipOnTruncate = {
+ ...TooltipOnTruncate,
+ directives: {
+ ...TooltipOnTruncate.directives,
+ GlTooltip: createMockDirective(),
+ GlResizeObserver: createMockDirective(),
+ },
+ };
+
// set a parent around the tested component
parent = mount(
{
@@ -43,74 +54,85 @@ describe('TooltipOnTruncate component', () => {
title: { default: '' },
},
template: `
- <TooltipOnTruncate :title="title" truncate-target="child">
- <div>{{title}}</div>
- </TooltipOnTruncate>
+ <TooltipOnTruncate :title="title" truncate-target="child">
+ <div>{{title}}</div>
+ </TooltipOnTruncate>
`,
components: {
- TooltipOnTruncate,
+ TooltipOnTruncate: WrappedTooltipOnTruncate,
},
},
{
propsData: { ...propsData },
- attachTo: document.body,
...options,
},
);
- wrapper = parent.find(TooltipOnTruncate);
+ wrapper = parent.find(WrappedTooltipOnTruncate);
};
- const hasTooltip = () => wrapper.classes('gl-tooltip');
+ const getTooltipValue = () => getBinding(wrapper.element, 'gl-tooltip')?.value;
+ const resize = async ({ truncate }) => {
+ hasHorizontalOverflow.mockReturnValueOnce(truncate);
+ getBinding(wrapper.element, 'gl-resize-observer').value();
+ await nextTick();
+ };
afterEach(() => {
wrapper.destroy();
});
- describe('with default target', () => {
- it('renders tooltip if truncated', () => {
+ describe('when truncated', () => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
- createComponent({
- propsData: {
- title: DUMMY_TEXT,
- },
- slots: {
- default: [DUMMY_TEXT],
- },
- });
+ createComponent();
+ });
- 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('renders tooltip', async () => {
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element);
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ placement: 'top',
+ disabled: false,
});
+ expect(wrapper.classes('js-show-tooltip')).toBe(true);
});
+ });
- it('does not render tooltip if normal', () => {
+ describe('with default target', () => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
- createComponent({
- propsData: {
- title: DUMMY_TEXT,
- },
- slots: {
- default: [DUMMY_TEXT],
- },
+ createComponent();
+ });
+
+ it('does not render tooltip if not truncated', () => {
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element);
+ expect(getTooltipValue()).toMatchObject({
+ disabled: true,
});
+ expect(wrapper.classes('js-show-tooltip')).toBe(false);
+ });
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element);
- expect(hasTooltip()).toBe(false);
+ it('renders tooltip on resize', async () => {
+ await resize({ truncate: true });
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: false,
+ });
+
+ await resize({ truncate: false });
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: true,
});
});
});
describe('with child target', () => {
- it('renders tooltip if truncated', () => {
+ it('renders tooltip if truncated', async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
- title: DUMMY_TEXT,
truncateTarget: 'child',
},
slots: {
@@ -118,13 +140,18 @@ describe('TooltipOnTruncate component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[0]);
- expect(hasTooltip()).toBe(true);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element.childNodes[0]);
+
+ await nextTick();
+
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ placement: 'top',
+ disabled: false,
});
});
- it('does not render tooltip if normal', () => {
+ it('does not render tooltip if normal', async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
createComponent({
propsData: {
@@ -135,19 +162,21 @@ describe('TooltipOnTruncate component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[0]);
- expect(hasTooltip()).toBe(false);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element.childNodes[0]);
+
+ await nextTick();
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: true,
});
});
});
describe('with fn target', () => {
- it('renders tooltip if truncated', () => {
+ it('renders tooltip if truncated', async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
- title: DUMMY_TEXT,
truncateTarget: (el) => el.childNodes[1],
},
slots: {
@@ -155,93 +184,97 @@ describe('TooltipOnTruncate component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[1]);
- expect(hasTooltip()).toBe(true);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element.childNodes[1]);
+
+ await nextTick();
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: false,
});
});
});
describe('placement', () => {
- it('sets data-placement when tooltip is rendered', () => {
- const placement = 'bottom';
+ it('sets placement when tooltip is rendered', () => {
+ const mockPlacement = 'bottom';
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
- placement,
- },
- slots: {
- default: DUMMY_TEXT,
+ placement: mockPlacement,
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasTooltip()).toBe(true);
- expect(wrapper.attributes('data-placement')).toEqual(placement);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element);
+ expect(getTooltipValue()).toMatchObject({
+ placement: mockPlacement,
});
});
});
describe('updates when title and slot content changes', () => {
describe('is initialized with a long text', () => {
- beforeEach(() => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createWrappedComponent({
- propsData: { title: DUMMY_TEXT },
+ propsData: { title: MOCK_TITLE },
});
- return parent.vm.$nextTick();
+ await nextTick();
});
it('renders tooltip', () => {
- expect(hasTooltip()).toBe(true);
- expect(wrapper.attributes('data-original-title')).toEqual(DUMMY_TEXT);
- expect(wrapper.attributes('data-placement')).toEqual('top');
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ placement: 'top',
+ disabled: false,
+ });
});
- it('does not render tooltip after updated to a short text', () => {
+ it('does not render tooltip after updated to a short text', async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
parent.setProps({
- title: 'new-text',
+ title: SHORT_TITLE,
});
- return wrapper.vm
- .$nextTick()
- .then(() => wrapper.vm.$nextTick()) // wait 2 times to get an updated slot
- .then(() => {
- expect(hasTooltip()).toBe(false);
- });
+ await nextTick();
+ await nextTick(); // wait 2 times to get an updated slot
+
+ expect(getTooltipValue()).toMatchObject({
+ title: SHORT_TITLE,
+ disabled: true,
+ });
});
});
- describe('is initialized with a short text', () => {
- beforeEach(() => {
+ describe('is initialized with a short text that does not overflow', () => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
createWrappedComponent({
- propsData: { title: DUMMY_TEXT },
+ propsData: { title: MOCK_TITLE },
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not render tooltip', () => {
- expect(hasTooltip()).toBe(false);
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ disabled: true,
+ });
});
- it('renders tooltip after text is updated', () => {
+ it('renders tooltip after text is updated', async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
- const newText = 'new-text';
parent.setProps({
- title: newText,
+ title: SHORT_TITLE,
});
- 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');
- });
+ await nextTick();
+ await nextTick(); // wait 2 times to get an updated slot
+
+ expect(getTooltipValue()).toMatchObject({
+ title: SHORT_TITLE,
+ disabled: false,
+ });
});
});
});