text: import { shallowMount, createLocalVue } from '@vue/test-utils';
  import Vuex from 'vuex';
  
  import { isInViewport } from '~/lib/utils/common_utils';
  import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
  import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue';
  import DropdownContents from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue';
  import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
  import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue';
  import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue';
  import LabelsSelectRoot from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
  
  import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
  
  import { mockConfig } from './mock_data';
  
  jest.mock('~/lib/utils/common_utils', () => ({
    isInViewport: jest.fn().mockReturnValue(true),
  }));
  
  const localVue = createLocalVue();
  localVue.use(Vuex);
  
  describe('LabelsSelectRoot', () => {
    let wrapper;
    let store;
  
    const createComponent = (config = mockConfig, slots = {}) => {
      wrapper = shallowMount(LabelsSelectRoot, {
        localVue,
        slots,
        store,
        propsData: config,
        stubs: {
          'dropdown-contents': DropdownContents,
        },
      });
    };
  
    beforeEach(() => {
      store = new Vuex.Store(labelsSelectModule());
    });
  
    afterEach(() => {
      wrapper.destroy();
    });
  
    describe('methods', () => {
      describe('handleVuexActionDispatch', () => {
        it('calls `handleDropdownClose` when params `action.type` is `toggleDropdownContents` and state has `showDropdownButton` & `showDropdownContents` props `false`', () => {
          createComponent();
          jest.spyOn(wrapper.vm, 'handleDropdownClose').mockImplementation();
  
          wrapper.vm.handleVuexActionDispatch(
            { type: 'toggleDropdownContents' },
            {
              showDropdownButton: false,
              showDropdownContents: false,
              labels: [{ id: 1 }, { id: 2, touched: true }],
            },
          );
  
          expect(wrapper.vm.handleDropdownClose).toHaveBeenCalledWith(
            expect.arrayContaining([
              {
                id: 2,
                touched: true,
              },
            ]),
          );
        });
  
        it('calls `handleDropdownClose` with state.labels filterd using `set` prop when dropdown variant is `embedded`', () => {
          createComponent({
            ...mockConfig,
            variant: 'embedded',
          });
  
          jest.spyOn(wrapper.vm, 'handleDropdownClose').mockImplementation();
  
          wrapper.vm.handleVuexActionDispatch(
            { type: 'toggleDropdownContents' },
            {
              showDropdownButton: false,
              showDropdownContents: false,
              labels: [{ id: 1 }, { id: 2, set: true }],
            },
          );
  
          expect(wrapper.vm.handleDropdownClose).toHaveBeenCalledWith(
            expect.arrayContaining([
              {
                id: 2,
                set: true,
              },
            ]),
          );
        });
      });
  
      describe('handleDropdownClose', () => {
        beforeEach(() => {
          createComponent();
        });
  
        it('emits `updateSelectedLabels` & `onDropdownClose` events on component when provided `labels` param is not empty', () => {
          wrapper.vm.handleDropdownClose([{ id: 1 }, { id: 2 }]);
  
          expect(wrapper.emitted().updateSelectedLabels).toBeTruthy();
          expect(wrapper.emitted().onDropdownClose).toBeTruthy();
        });
  
        it('emits only `onDropdownClose` event on component when provided `labels` param is empty', () => {
          wrapper.vm.handleDropdownClose([]);
  
          expect(wrapper.emitted().updateSelectedLabels).toBeFalsy();
          expect(wrapper.emitted().onDropdownClose).toBeTruthy();
        });
      });
  
      describe('handleCollapsedValueClick', () => {
        it('emits `toggleCollapse` event on component', () => {
          createComponent();
          wrapper.vm.handleCollapsedValueClick();
  
          expect(wrapper.emitted().toggleCollapse).toBeTruthy();
        });
      });
    });
  
    describe('template', () => {
      it('renders component with classes `labels-select-wrapper position-relative`', () => {
        createComponent();
        expect(wrapper.attributes('class')).toContain('labels-select-wrapper position-relative');
      });
  
      it.each`
        variant         | cssClass
        ${'standalone'} | ${'is-standalone'}
        ${'embedded'}   | ${'is-embedded'}
      `(
        'renders component root element with CSS class `$cssClass` when `state.variant` is "$variant"',
        ({ variant, cssClass }) => {
          createComponent({
            ...mockConfig,
            variant,
          });
  
          return wrapper.vm.$nextTick(() => {
            expect(wrapper.classes()).toContain(cssClass);
          });
        },
      );
  
      it('renders `dropdown-value-collapsed` component when `allowLabelCreate` prop is `true`', async () => {
        createComponent();
        await wrapper.vm.$nextTick;
        expect(wrapper.find(DropdownValueCollapsed).exists()).toBe(true);
      });
  
      it('renders `dropdown-title` component', async () => {
        createComponent();
        await wrapper.vm.$nextTick;
        expect(wrapper.find(DropdownTitle).exists()).toBe(true);
      });
  
      it('renders `dropdown-value` component', async () => {
        createComponent(mockConfig, {
          default: 'None',
        });
        await wrapper.vm.$nextTick;
  
        const valueComp = wrapper.find(DropdownValue);
  
        expect(valueComp.exists()).toBe(true);
        expect(valueComp.text()).toBe('None');
      });
  
      it('renders `dropdown-button` component when `showDropdownButton` prop is `true`', async () => {
        createComponent();
        wrapper.vm.$store.dispatch('toggleDropdownButton');
        await wrapper.vm.$nextTick;
        expect(wrapper.find(DropdownButton).exists()).toBe(true);
      });
  
      it('renders `dropdown-contents` component when `showDropdownButton` & `showDropdownContents` prop is `true`', async () => {
        createComponent();
        wrapper.vm.$store.dispatch('toggleDropdownContents');
        await wrapper.vm.$nextTick;
        expect(wrapper.find(DropdownContents).exists()).toBe(true);
      });
  
      describe('sets content direction based on viewport', () => {
        describe.each(Object.values(DropdownVariant))(
          'when labels variant is "%s"',
          ({ variant }) => {
            beforeEach(() => {
              createComponent({ ...mockConfig, variant });
              wrapper.vm.$store.dispatch('toggleDropdownContents');
            });
  
            it('set direction when out of viewport', () => {
              isInViewport.mockImplementation(() => false);
              wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state);
  
              return wrapper.vm.$nextTick().then(() => {
                expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(true);
              });
            });
  
            it('does not set direction when inside of viewport', () => {
              isInViewport.mockImplementation(() => true);
              wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state);
  
              return wrapper.vm.$nextTick().then(() => {
                expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false);
              });
            });
          },
        );
      });
    });
  
    it('calls toggleDropdownContents action when isEditing prop is changing to true', async () => {
      createComponent();
  
      jest.spyOn(store, 'dispatch').mockResolvedValue();
      await wrapper.setProps({ isEditing: true });
  
      expect(store.dispatch).toHaveBeenCalledWith('toggleDropdownContents');
    });
  
    it('does not call toggleDropdownContents action when isEditing prop is changing to false', async () => {
      createComponent();
  
      jest.spyOn(store, 'dispatch').mockResolvedValue();
      await wrapper.setProps({ isEditing: false });
  
      expect(store.dispatch).not.toHaveBeenCalled();
    });
  });
  