diff options
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.js | 239 |
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'); + }); + }); + }); + }); +}); |