diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-27 15:08:39 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-27 15:08:39 +0000 |
commit | 2b1e7f7dac0fa5d7bb3bdf415cec1b3c67ed77b0 (patch) | |
tree | 725ae8200573957bff6fa03aee237f738dadf1d7 /spec/frontend/popovers | |
parent | eb004dc626d3a1c9497e8b9dc0f3f578afd05fd9 (diff) | |
download | gitlab-ce-2b1e7f7dac0fa5d7bb3bdf415cec1b3c67ed77b0.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/popovers')
-rw-r--r-- | spec/frontend/popovers/components/popovers_spec.js | 129 | ||||
-rw-r--r-- | spec/frontend/popovers/index_spec.js | 104 |
2 files changed, 233 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); + }); +}); diff --git a/spec/frontend/popovers/index_spec.js b/spec/frontend/popovers/index_spec.js new file mode 100644 index 00000000000..ea3b78332d7 --- /dev/null +++ b/spec/frontend/popovers/index_spec.js @@ -0,0 +1,104 @@ +import { initPopovers, dispose, destroy } from '~/popovers'; + +describe('popovers/index.js', () => { + let popoversApp; + + const createPopoverTarget = (trigger = 'hover') => { + const target = document.createElement('button'); + const dataset = { + title: 'default title', + content: 'some content', + toggle: 'popover', + trigger, + }; + + Object.entries(dataset).forEach(([key, value]) => { + target.dataset[key] = value; + }); + + document.body.appendChild(target); + + return target; + }; + + const buildPopoversApp = () => { + popoversApp = initPopovers('[data-toggle="popover"]'); + }; + + const triggerEvent = (target, eventName = 'mouseenter') => { + const event = new Event(eventName); + + target.dispatchEvent(event); + }; + + afterEach(() => { + document.body.innerHTML = ''; + destroy(); + }); + + describe('initPopover', () => { + it('attaches a GlPopover for the elements specified in the selector', async () => { + const target = createPopoverTarget(); + + buildPopoversApp(); + + triggerEvent(target); + + await popoversApp.$nextTick(); + const html = document.querySelector('.gl-popover').innerHTML; + + expect(document.querySelector('.gl-popover')).not.toBe(null); + expect(html).toContain('default title'); + expect(html).toContain('some content'); + }); + + it('supports triggering a popover via custom events', async () => { + const trigger = 'click'; + const target = createPopoverTarget(trigger); + + buildPopoversApp(); + triggerEvent(target, trigger); + + await popoversApp.$nextTick(); + + expect(document.querySelector('.gl-popover')).not.toBe(null); + expect(document.querySelector('.gl-popover').innerHTML).toContain('default title'); + }); + + it('inits popovers on targets added after content load', async () => { + buildPopoversApp(); + + expect(document.querySelector('.gl-popover')).toBe(null); + + const trigger = 'click'; + const target = createPopoverTarget(trigger); + triggerEvent(target, trigger); + await popoversApp.$nextTick(); + + expect(document.querySelector('.gl-popover')).not.toBe(null); + }); + }); + + describe('dispose', () => { + it('removes popovers that target the elements specified', async () => { + const fakeTarget = createPopoverTarget(); + const target = createPopoverTarget(); + buildPopoversApp(); + triggerEvent(target); + triggerEvent(createPopoverTarget()); + await popoversApp.$nextTick(); + + expect(document.querySelectorAll('.gl-popover')).toHaveLength(2); + + dispose([fakeTarget]); + await popoversApp.$nextTick(); + + expect(document.querySelectorAll('.gl-popover')).toHaveLength(2); + + dispose([target]); + await popoversApp.$nextTick(); + + expect(document.querySelectorAll('.gl-popover')).toHaveLength(1); + }); + }); +}); |