221 lines
5.9 KiB
JavaScript
221 lines
5.9 KiB
JavaScript
import { GlTooltip } from '@gitlab/ui';
|
|
import { shallowMount } from '@vue/test-utils';
|
|
import { useMockMutationObserver } from 'helpers/mock_dom_observer';
|
|
import Tooltips from '~/tooltips/components/tooltips.vue';
|
|
|
|
describe('tooltips/components/tooltips.vue', () => {
|
|
const { trigger: triggerMutate, observersCount } = useMockMutationObserver();
|
|
let wrapper;
|
|
|
|
const buildWrapper = () => {
|
|
wrapper = shallowMount(Tooltips);
|
|
};
|
|
|
|
const createTooltipTarget = (attributes = {}) => {
|
|
const target = document.createElement('button');
|
|
const defaults = {
|
|
title: 'default title',
|
|
...attributes,
|
|
};
|
|
|
|
Object.keys(defaults).forEach((name) => {
|
|
target.setAttribute(name, defaults[name]);
|
|
});
|
|
|
|
document.body.appendChild(target);
|
|
|
|
return target;
|
|
};
|
|
|
|
const allTooltips = () => wrapper.findAll(GlTooltip);
|
|
|
|
afterEach(() => {
|
|
wrapper.destroy();
|
|
wrapper = null;
|
|
});
|
|
|
|
describe('addTooltips', () => {
|
|
let target;
|
|
|
|
beforeEach(() => {
|
|
buildWrapper();
|
|
|
|
target = createTooltipTarget();
|
|
});
|
|
|
|
it('attaches tooltips to the targets specified', async () => {
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.find(GlTooltip).props('target')).toBe(target);
|
|
});
|
|
|
|
it('does not attach a tooltip to a target with empty title', async () => {
|
|
target.setAttribute('title', '');
|
|
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.find(GlTooltip).exists()).toBe(false);
|
|
});
|
|
|
|
it('does not attach a tooltip twice to the same element', async () => {
|
|
wrapper.vm.addTooltips([target]);
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.findAll(GlTooltip)).toHaveLength(1);
|
|
});
|
|
|
|
it('sets tooltip content from title attribute', async () => {
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.find(GlTooltip).text()).toBe(target.getAttribute('title'));
|
|
});
|
|
|
|
it('supports HTML content', async () => {
|
|
target = createTooltipTarget({
|
|
title: 'content with <b>HTML</b>',
|
|
'data-html': true,
|
|
});
|
|
wrapper.vm.addTooltips([target]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.find(GlTooltip).html()).toContain(target.getAttribute('title'));
|
|
});
|
|
|
|
it('sets the configuration values passed in the config object', async () => {
|
|
const config = { show: true };
|
|
target = createTooltipTarget();
|
|
wrapper.vm.addTooltips([target], config);
|
|
await wrapper.vm.$nextTick();
|
|
expect(wrapper.find(GlTooltip).props()).toMatchObject(config);
|
|
});
|
|
|
|
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]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.find(GlTooltip).props(prop)).toBe(value);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('dispose', () => {
|
|
beforeEach(() => {
|
|
buildWrapper();
|
|
});
|
|
|
|
it('removes all tooltips when elements is nil', async () => {
|
|
wrapper.vm.addTooltips([createTooltipTarget(), createTooltipTarget()]);
|
|
await wrapper.vm.$nextTick();
|
|
|
|
wrapper.vm.dispose();
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(allTooltips()).toHaveLength(0);
|
|
});
|
|
|
|
it('removes the tooltips that target the elements specified', async () => {
|
|
const target = createTooltipTarget();
|
|
|
|
wrapper.vm.addTooltips([target, createTooltipTarget()]);
|
|
await wrapper.vm.$nextTick();
|
|
|
|
wrapper.vm.dispose(target);
|
|
await wrapper.vm.$nextTick();
|
|
|
|
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()]);
|
|
await wrapper.vm.$nextTick();
|
|
|
|
triggerMutate(document.body, {
|
|
entry: { removedNodes: [target] },
|
|
options: { childList: true },
|
|
});
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(allTooltips()).toHaveLength(1);
|
|
});
|
|
});
|
|
|
|
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]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
wrapper.vm.triggerEvent(target, event);
|
|
|
|
expect(wrapper.find(GlTooltip).emitted(event)).toHaveLength(1);
|
|
});
|
|
});
|
|
|
|
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]);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.find(GlTooltip).text()).toBe(currentTitle);
|
|
|
|
target.setAttribute('title', newTitle);
|
|
wrapper.vm.fixTitle(target);
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
expect(wrapper.find(GlTooltip).text()).toBe(newTitle);
|
|
});
|
|
});
|
|
|
|
it('disconnects mutation observer on beforeDestroy', () => {
|
|
buildWrapper();
|
|
wrapper.vm.addTooltips([createTooltipTarget()]);
|
|
|
|
expect(observersCount()).toBe(1);
|
|
|
|
wrapper.destroy();
|
|
expect(observersCount()).toBe(0);
|
|
});
|
|
});
|