2020-08-26 11:10:29 -04:00
|
|
|
import { GlTooltip } from '@gitlab/ui';
|
2021-02-14 13:09:20 -05:00
|
|
|
import { shallowMount } from '@vue/test-utils';
|
2022-01-25 07:14:14 -05:00
|
|
|
import { nextTick } from 'vue';
|
2020-08-30 23:10:13 -04:00
|
|
|
import { useMockMutationObserver } from 'helpers/mock_dom_observer';
|
2020-08-26 11:10:29 -04:00
|
|
|
import Tooltips from '~/tooltips/components/tooltips.vue';
|
|
|
|
|
|
|
|
describe('tooltips/components/tooltips.vue', () => {
|
2021-08-03 08:09:42 -04:00
|
|
|
const { trigger: triggerMutate } = useMockMutationObserver();
|
2020-08-26 11:10:29 -04:00
|
|
|
let wrapper;
|
|
|
|
|
|
|
|
const buildWrapper = () => {
|
|
|
|
wrapper = shallowMount(Tooltips);
|
|
|
|
};
|
|
|
|
|
|
|
|
const createTooltipTarget = (attributes = {}) => {
|
|
|
|
const target = document.createElement('button');
|
|
|
|
const defaults = {
|
|
|
|
title: 'default title',
|
|
|
|
...attributes,
|
|
|
|
};
|
|
|
|
|
2020-12-23 16:10:24 -05:00
|
|
|
Object.keys(defaults).forEach((name) => {
|
2020-08-26 11:10:29 -04:00
|
|
|
target.setAttribute(name, defaults[name]);
|
|
|
|
});
|
|
|
|
|
2020-08-30 23:10:13 -04:00
|
|
|
document.body.appendChild(target);
|
|
|
|
|
2020-08-26 11:10:29 -04:00
|
|
|
return target;
|
|
|
|
};
|
|
|
|
|
2022-09-13 14:12:21 -04:00
|
|
|
const allTooltips = () => wrapper.findAllComponents(GlTooltip);
|
2020-08-30 23:10:13 -04:00
|
|
|
|
2020-08-26 11:10:29 -04:00
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
2020-08-30 23:10:13 -04:00
|
|
|
wrapper = null;
|
2020-08-26 11:10:29 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('addTooltips', () => {
|
|
|
|
let target;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
buildWrapper();
|
|
|
|
|
|
|
|
target = createTooltipTarget();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('attaches tooltips to the targets specified', async () => {
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-26 11:10:29 -04:00
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).props('target')).toBe(target);
|
2020-08-26 11:10:29 -04:00
|
|
|
});
|
|
|
|
|
2020-12-23 10:09:54 -05:00
|
|
|
it('does not attach a tooltip to a target with empty title', async () => {
|
|
|
|
target.setAttribute('title', '');
|
|
|
|
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-12-23 10:09:54 -05:00
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).exists()).toBe(false);
|
2020-12-23 10:09:54 -05:00
|
|
|
});
|
|
|
|
|
2020-08-26 11:10:29 -04:00
|
|
|
it('does not attach a tooltip twice to the same element', async () => {
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-26 11:10:29 -04:00
|
|
|
|
2022-09-13 14:12:21 -04:00
|
|
|
expect(wrapper.findAllComponents(GlTooltip)).toHaveLength(1);
|
2020-08-26 11:10:29 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('sets tooltip content from title attribute', async () => {
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-26 11:10:29 -04:00
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).text()).toBe(target.getAttribute('title'));
|
2020-08-26 11:10:29 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('supports HTML content', async () => {
|
|
|
|
target = createTooltipTarget({
|
|
|
|
title: 'content with <b>HTML</b>',
|
|
|
|
'data-html': true,
|
|
|
|
});
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-26 11:10:29 -04:00
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).html()).toContain(target.getAttribute('title'));
|
2020-08-26 11:10:29 -04:00
|
|
|
});
|
|
|
|
|
2020-10-21 17:09:00 -04:00
|
|
|
it('sets the configuration values passed in the config object', async () => {
|
|
|
|
const config = { show: true };
|
|
|
|
target = createTooltipTarget();
|
|
|
|
wrapper.vm.addTooltips([target], config);
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).props()).toMatchObject(config);
|
2020-10-21 17:09:00 -04:00
|
|
|
});
|
|
|
|
|
2020-08-26 11:10:29 -04:00
|
|
|
it.each`
|
|
|
|
attribute | value | prop
|
|
|
|
${'data-placement'} | ${'bottom'} | ${'placement'}
|
|
|
|
${'data-container'} | ${'custom-container'} | ${'container'}
|
|
|
|
${'data-boundary'} | ${'viewport'} | ${'boundary'}
|
|
|
|
${'data-triggers'} | ${'manual'} | ${'triggers'}
|
|
|
|
`(
|
|
|
|
'sets $prop to $value when $attribute is set in target',
|
|
|
|
async ({ attribute, value, prop }) => {
|
|
|
|
target = createTooltipTarget({ [attribute]: value });
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-26 11:10:29 -04:00
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).props(prop)).toBe(value);
|
2020-08-26 11:10:29 -04:00
|
|
|
},
|
|
|
|
);
|
|
|
|
});
|
2020-08-30 23:10:13 -04:00
|
|
|
|
|
|
|
describe('dispose', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
buildWrapper();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('removes all tooltips when elements is nil', async () => {
|
|
|
|
wrapper.vm.addTooltips([createTooltipTarget(), createTooltipTarget()]);
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-30 23:10:13 -04:00
|
|
|
|
|
|
|
wrapper.vm.dispose();
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-30 23:10:13 -04:00
|
|
|
|
|
|
|
expect(allTooltips()).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('removes the tooltips that target the elements specified', async () => {
|
|
|
|
const target = createTooltipTarget();
|
|
|
|
|
|
|
|
wrapper.vm.addTooltips([target, createTooltipTarget()]);
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-30 23:10:13 -04:00
|
|
|
|
2020-09-11 05:08:44 -04:00
|
|
|
wrapper.vm.dispose(target);
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-30 23:10:13 -04:00
|
|
|
|
|
|
|
expect(allTooltips()).toHaveLength(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('observe', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
buildWrapper();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('removes tooltip when target is removed from the document', async () => {
|
|
|
|
const target = createTooltipTarget();
|
|
|
|
|
|
|
|
wrapper.vm.addTooltips([target, createTooltipTarget()]);
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-30 23:10:13 -04:00
|
|
|
|
|
|
|
triggerMutate(document.body, {
|
|
|
|
entry: { removedNodes: [target] },
|
|
|
|
options: { childList: true },
|
|
|
|
});
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-08-30 23:10:13 -04:00
|
|
|
|
|
|
|
expect(allTooltips()).toHaveLength(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-09-11 05:08:44 -04:00
|
|
|
describe('triggerEvent', () => {
|
|
|
|
it('triggers a bootstrap-vue tooltip global event for the tooltip specified', async () => {
|
|
|
|
const target = createTooltipTarget();
|
|
|
|
const event = 'hide';
|
|
|
|
|
|
|
|
buildWrapper();
|
|
|
|
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-09-11 05:08:44 -04:00
|
|
|
|
|
|
|
wrapper.vm.triggerEvent(target, event);
|
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).emitted(event)).toHaveLength(1);
|
2020-09-11 05:08:44 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('fixTitle', () => {
|
|
|
|
it('updates tooltip content with the latest value the target title property', async () => {
|
|
|
|
const target = createTooltipTarget();
|
|
|
|
const currentTitle = 'title';
|
|
|
|
const newTitle = 'new title';
|
|
|
|
|
|
|
|
target.setAttribute('title', currentTitle);
|
|
|
|
|
|
|
|
buildWrapper();
|
|
|
|
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-09-11 05:08:44 -04:00
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).text()).toBe(currentTitle);
|
2020-09-11 05:08:44 -04:00
|
|
|
|
|
|
|
target.setAttribute('title', newTitle);
|
|
|
|
wrapper.vm.fixTitle(target);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2020-09-11 05:08:44 -04:00
|
|
|
|
2022-09-21 11:14:09 -04:00
|
|
|
expect(wrapper.findComponent(GlTooltip).text()).toBe(newTitle);
|
2020-09-11 05:08:44 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-08-30 23:10:13 -04:00
|
|
|
it('disconnects mutation observer on beforeDestroy', () => {
|
|
|
|
buildWrapper();
|
|
|
|
wrapper.vm.addTooltips([createTooltipTarget()]);
|
2021-08-03 08:09:42 -04:00
|
|
|
const { observer } = wrapper.vm;
|
|
|
|
jest.spyOn(observer, 'disconnect');
|
2020-08-30 23:10:13 -04:00
|
|
|
|
2021-08-03 08:09:42 -04:00
|
|
|
expect(observer.disconnect).toHaveBeenCalledTimes(0);
|
2020-08-30 23:10:13 -04:00
|
|
|
|
|
|
|
wrapper.destroy();
|
2021-08-03 08:09:42 -04:00
|
|
|
|
|
|
|
expect(observer.disconnect).toHaveBeenCalledTimes(1);
|
2020-08-30 23:10:13 -04:00
|
|
|
});
|
2021-02-23 10:10:47 -05:00
|
|
|
|
|
|
|
it('exposes hidden event', async () => {
|
|
|
|
buildWrapper();
|
|
|
|
wrapper.vm.addTooltips([createTooltipTarget()]);
|
|
|
|
|
2022-01-25 07:14:14 -05:00
|
|
|
await nextTick();
|
2021-02-23 10:10:47 -05:00
|
|
|
|
|
|
|
wrapper.findComponent(GlTooltip).vm.$emit('hidden');
|
|
|
|
expect(wrapper.emitted('hidden')).toHaveLength(1);
|
|
|
|
});
|
2020-08-26 11:10:29 -04:00
|
|
|
});
|