diff options
Diffstat (limited to 'spec/frontend/popovers/components/popovers_spec.js')
-rw-r--r-- | spec/frontend/popovers/components/popovers_spec.js | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/spec/frontend/popovers/components/popovers_spec.js b/spec/frontend/popovers/components/popovers_spec.js new file mode 100644 index 00000000000..63e0b3d9c49 --- /dev/null +++ b/spec/frontend/popovers/components/popovers_spec.js @@ -0,0 +1,129 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlPopover } from '@gitlab/ui'; +import { useMockMutationObserver } from 'helpers/mock_dom_observer'; +import Popovers from '~/popovers/components/popovers.vue'; + +describe('popovers/components/popovers.vue', () => { + const { trigger: triggerMutate, observersCount } = useMockMutationObserver(); + let wrapper; + + const buildWrapper = (...targets) => { + wrapper = shallowMount(Popovers); + wrapper.vm.addPopovers(targets); + return wrapper.vm.$nextTick(); + }; + + const createPopoverTarget = (options = {}) => { + const target = document.createElement('button'); + const dataset = { + title: 'default title', + content: 'some content', + ...options, + }; + + Object.entries(dataset).forEach(([key, value]) => { + target.dataset[key] = value; + }); + + document.body.appendChild(target); + + return target; + }; + + const allPopovers = () => wrapper.findAll(GlPopover); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('addPopovers', () => { + it('attaches popovers to the targets specified', async () => { + const target = createPopoverTarget(); + await buildWrapper(target); + expect(wrapper.find(GlPopover).props('target')).toBe(target); + }); + + it('does not attach a popover twice to the same element', async () => { + const target = createPopoverTarget(); + buildWrapper(target); + wrapper.vm.addPopovers([target]); + + await wrapper.vm.$nextTick(); + + expect(wrapper.findAll(GlPopover)).toHaveLength(1); + }); + + it('supports HTML content', async () => { + const content = 'content with <b>HTML</b>'; + await buildWrapper( + createPopoverTarget({ + content, + html: true, + }), + ); + const html = wrapper.find(GlPopover).html(); + + expect(html).toContain(content); + }); + + it.each` + option | value + ${'placement'} | ${'bottom'} + ${'triggers'} | ${'manual'} + `('sets $option to $value when data-$option is set in target', async ({ option, value }) => { + await buildWrapper(createPopoverTarget({ [option]: value })); + + expect(wrapper.find(GlPopover).props(option)).toBe(value); + }); + }); + + describe('dispose', () => { + it('removes all popovers when elements is nil', async () => { + await buildWrapper(createPopoverTarget(), createPopoverTarget()); + + wrapper.vm.dispose(); + await wrapper.vm.$nextTick(); + + expect(allPopovers()).toHaveLength(0); + }); + + it('removes the popovers that target the elements specified', async () => { + const target = createPopoverTarget(); + + await buildWrapper(target, createPopoverTarget()); + + wrapper.vm.dispose(target); + await wrapper.vm.$nextTick(); + + expect(allPopovers()).toHaveLength(1); + }); + }); + + describe('observe', () => { + it('removes popover when target is removed from the document', async () => { + const target = createPopoverTarget(); + await buildWrapper(target); + + wrapper.vm.addPopovers([target, createPopoverTarget()]); + await wrapper.vm.$nextTick(); + + triggerMutate(document.body, { + entry: { removedNodes: [target] }, + options: { childList: true }, + }); + await wrapper.vm.$nextTick(); + + expect(allPopovers()).toHaveLength(1); + }); + }); + + it('disconnects mutation observer on beforeDestroy', async () => { + await buildWrapper(createPopoverTarget()); + + expect(observersCount()).toBe(1); + + wrapper.destroy(); + expect(observersCount()).toBe(0); + }); +}); |