text: 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);
    });
  });
  