text: import { shallowMount } from '@vue/test-utils';
  import Vue from 'vue';
  import VueApollo from 'vue-apollo';
  import createMockApollo from 'helpers/mock_apollo_helper';
  import waitForPromises from 'helpers/wait_for_promises';
  import createFlash from '~/flash';
  import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
  import DropdownContents from '~/vue_shared/components/color_select_dropdown/dropdown_contents.vue';
  import DropdownValue from '~/vue_shared/components/color_select_dropdown/dropdown_value.vue';
  import epicColorQuery from '~/vue_shared/components/color_select_dropdown/graphql/epic_color.query.graphql';
  import updateEpicColorMutation from '~/vue_shared/components/color_select_dropdown/graphql/epic_update_color.mutation.graphql';
  import ColorSelectRoot from '~/vue_shared/components/color_select_dropdown/color_select_root.vue';
  import { DROPDOWN_VARIANT } from '~/vue_shared/components/color_select_dropdown/constants';
  import { colorQueryResponse, updateColorMutationResponse, color } from './mock_data';
  
  jest.mock('~/flash');
  
  Vue.use(VueApollo);
  
  const successfulQueryHandler = jest.fn().mockResolvedValue(colorQueryResponse);
  const successfulMutationHandler = jest.fn().mockResolvedValue(updateColorMutationResponse);
  const errorQueryHandler = jest.fn().mockRejectedValue('Error fetching epic color.');
  const errorMutationHandler = jest.fn().mockRejectedValue('An error occurred while updating color.');
  
  const defaultProps = {
    allowEdit: true,
    iid: '1',
    fullPath: 'workspace-1',
  };
  
  describe('LabelsSelectRoot', () => {
    let wrapper;
  
    const findSidebarEditableItem = () => wrapper.findComponent(SidebarEditableItem);
    const findDropdownValue = () => wrapper.findComponent(DropdownValue);
    const findDropdownContents = () => wrapper.findComponent(DropdownContents);
  
    const createComponent = ({
      queryHandler = successfulQueryHandler,
      mutationHandler = successfulMutationHandler,
      propsData,
    } = {}) => {
      const mockApollo = createMockApollo([
        [epicColorQuery, queryHandler],
        [updateEpicColorMutation, mutationHandler],
      ]);
  
      wrapper = shallowMount(ColorSelectRoot, {
        apolloProvider: mockApollo,
        propsData: {
          ...defaultProps,
          ...propsData,
        },
        provide: {
          canUpdate: true,
        },
        stubs: {
          SidebarEditableItem,
        },
      });
    };
  
    afterEach(() => {
      wrapper.destroy();
    });
  
    describe('template', () => {
      const defaultClasses = ['labels-select-wrapper', 'gl-relative'];
  
      it.each`
        variant       | cssClass
        ${'sidebar'}  | ${defaultClasses}
        ${'embedded'} | ${[...defaultClasses, 'is-embedded']}
      `(
        'renders component root element with CSS class `$cssClass` when variant is "$variant"',
        async ({ variant, cssClass }) => {
          createComponent({
            propsData: { variant },
          });
  
          expect(wrapper.classes()).toEqual(cssClass);
        },
      );
    });
  
    describe('if the variant is `sidebar`', () => {
      beforeEach(() => {
        createComponent();
      });
  
      it('renders SidebarEditableItem component', () => {
        expect(findSidebarEditableItem().exists()).toBe(true);
      });
  
      it('renders correct props for the SidebarEditableItem component', () => {
        expect(findSidebarEditableItem().props()).toMatchObject({
          title: wrapper.vm.$options.i18n.widgetTitle,
          canEdit: defaultProps.allowEdit,
          loading: true,
        });
      });
  
      describe('when colors are loaded', () => {
        beforeEach(async () => {
          createComponent();
          await waitForPromises();
        });
  
        it('passes false `loading` prop to sidebar editable item', () => {
          expect(findSidebarEditableItem().props('loading')).toBe(false);
        });
  
        it('renders dropdown value component when query colors is resolved', () => {
          expect(findDropdownValue().props('selectedColor')).toMatchObject(color);
        });
      });
    });
  
    describe('if the variant is `embedded`', () => {
      beforeEach(() => {
        createComponent({ propsData: { iid: undefined, variant: DROPDOWN_VARIANT.Embedded } });
      });
  
      it('renders DropdownContents component', () => {
        expect(findDropdownContents().exists()).toBe(true);
      });
  
      it('renders correct props for the DropdownContents component', () => {
        expect(findDropdownContents().props()).toMatchObject({
          variant: DROPDOWN_VARIANT.Embedded,
          dropdownTitle: wrapper.vm.$options.i18n.assignColor,
          dropdownButtonText: wrapper.vm.$options.i18n.dropdownButtonText,
        });
      });
  
      it('handles DropdownContents setColor', () => {
        findDropdownContents().vm.$emit('setColor', color);
        expect(wrapper.emitted('updateSelectedColor')).toEqual([[color]]);
      });
    });
  
    describe('when epicColorQuery errored', () => {
      beforeEach(async () => {
        createComponent({ queryHandler: errorQueryHandler });
        await waitForPromises();
      });
  
      it('creates flash with error message', () => {
        expect(createFlash).toHaveBeenCalledWith({
          captureError: true,
          message: 'Error fetching epic color.',
        });
      });
    });
  
    it('emits `updateSelectedColor` event on dropdown contents `setColor` event if iid is not set', () => {
      createComponent({ propsData: { iid: undefined } });
  
      findDropdownContents().vm.$emit('setColor', color);
      expect(wrapper.emitted('updateSelectedColor')).toEqual([[color]]);
    });
  
    describe('when updating color for epic', () => {
      beforeEach(() => {
        createComponent();
        findDropdownContents().vm.$emit('setColor', color);
      });
  
      it('sets the loading state', () => {
        expect(findSidebarEditableItem().props('loading')).toBe(true);
      });
  
      it('updates color correctly after successful mutation', async () => {
        await waitForPromises();
        expect(findDropdownValue().props('selectedColor').color).toEqual(
          updateColorMutationResponse.data.updateIssuableColor.issuable.color,
        );
      });
  
      it('displays an error if mutation was rejected', async () => {
        createComponent({ mutationHandler: errorMutationHandler });
        findDropdownContents().vm.$emit('setColor', color);
        await waitForPromises();
  
        expect(createFlash).toHaveBeenCalledWith({
          captureError: true,
          error: expect.anything(),
          message: 'An error occurred while updating color.',
        });
      });
    });
  });
  