text: import { shallowMount } from '@vue/test-utils';
  import { pick } from 'lodash';
  
  import EpicsListRoot from 'ee/epics_list/components/epics_list_root.vue';
  import { EpicsSortOptions } from 'ee/epics_list/constants';
  import { mockFormattedEpic } from 'ee_jest/roadmap/mock_data';
  import { stubComponent } from 'helpers/stub_component';
  import { mockAuthor, mockLabels } from 'jest/issuable_list/mock_data';
  
  import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
  import { IssuableListTabs } from '~/issuable_list/constants';
  
  jest.mock('~/issuable_list/constants', () => ({
    DEFAULT_PAGE_SIZE: 2,
    IssuableListTabs: jest.requireActual('~/issuable_list/constants').IssuableListTabs,
    AvailableSortOptions: jest.requireActual('~/issuable_list/constants').AvailableSortOptions,
  }));
  
  const mockRawEpic = {
    ...pick(mockFormattedEpic, [
      'title',
      'createdAt',
      'updatedAt',
      'webUrl',
      'userDiscussionsCount',
      'confidential',
    ]),
    author: mockAuthor,
    labels: {
      nodes: mockLabels,
    },
    startDate: '2021-04-01',
    dueDate: '2021-06-30',
  };
  
  const mockEpics = new Array(5)
    .fill()
    .map((_, i) => ({ ...mockRawEpic, id: i + 1, iid: (i + 1) * 10 }));
  
  const mockProvide = {
    canCreateEpic: true,
    canBulkEditEpics: true,
    page: 1,
    prev: '',
    next: '',
    initialState: 'opened',
    initialSortBy: 'created_desc',
    epicsCount: {
      opened: 5,
      closed: 0,
      all: 5,
    },
    epicNewPath: '/groups/gitlab-org/-/epics/new',
    groupFullPath: 'gitlab-org',
    groupLabelsPath: '/gitlab-org/-/labels.json',
    groupMilestonesPath: '/gitlab-org/-/milestone.json',
    listEpicsPath: '/gitlab-org/-/epics',
    emptyStatePath: '/assets/illustrations/empty-state/epics.svg',
  };
  
  const mockPageInfo = {
    startCursor: 'eyJpZCI6IjI1IiwiY3JlYXRlZF9hdCI6IjIwMjAtMDMtMzEgMTM6MzI6MTQgVVRDIn0',
    endCursor: 'eyJpZCI6IjIxIiwiY3JlYXRlZF9hdCI6IjIwMjAtMDMtMzEgMTM6MzE6MTUgVVRDIn0',
  };
  
  const createComponent = ({
    provide = mockProvide,
    initialFilterParams = {},
    epicsLoading = false,
    epicsList = mockEpics,
  } = {}) =>
    shallowMount(EpicsListRoot, {
      propsData: {
        initialFilterParams,
      },
      provide,
      mocks: {
        $apollo: {
          queries: {
            epics: {
              loading: epicsLoading,
              list: epicsList,
              pageInfo: mockPageInfo,
            },
          },
        },
      },
      stubs: {
        IssuableList: stubComponent(IssuableList),
      },
    });
  
  describe('EpicsListRoot', () => {
    let wrapper;
  
    beforeEach(() => {
      wrapper = createComponent();
    });
  
    afterEach(() => {
      wrapper.destroy();
    });
  
    describe('methods', () => {
      describe('epicTimeframe', () => {
        it.each`
          startDate     | dueDate        | returnValue
          ${'2021-1-1'} | ${'2021-2-28'} | ${'Jan 1 – Feb 28, 2021'}
          ${'2021-1-1'} | ${'2022-2-28'} | ${'Jan 1, 2021 – Feb 28, 2022'}
          ${'2021-1-1'} | ${null}        | ${'Jan 1, 2021 – No due date'}
          ${null}       | ${'2021-2-28'} | ${'No start date – Feb 28, 2021'}
        `(
          'returns string "$returnValue" when startDate is $startDate and dueDate is $dueDate',
          ({ startDate, dueDate, returnValue }) => {
            expect(
              wrapper.vm.epicTimeframe({
                startDate,
                dueDate,
              }),
            ).toBe(returnValue);
          },
        );
      });
  
      describe('fetchEpicsBy', () => {
        it('updates prevPageCursor and nextPageCursor values when provided propsName param is "currentPage"', async () => {
          wrapper.setData({
            epics: {
              pageInfo: mockPageInfo,
            },
          });
          wrapper.vm.fetchEpicsBy('currentPage', 2);
  
          await wrapper.vm.$nextTick();
  
          expect(wrapper.vm.prevPageCursor).toBe('');
          expect(wrapper.vm.nextPageCursor).toBe(mockPageInfo.endCursor);
          expect(wrapper.vm.currentPage).toBe(2);
        });
      });
    });
  
    describe('template', () => {
      const getIssuableList = () => wrapper.find(IssuableList);
  
      it('renders issuable-list component', async () => {
        wrapper.setData({
          filterParams: {
            search: 'foo',
          },
        });
  
        await wrapper.vm.$nextTick();
  
        expect(getIssuableList().exists()).toBe(true);
        expect(getIssuableList().props()).toMatchObject({
          namespace: mockProvide.groupFullPath,
          tabs: IssuableListTabs,
          currentTab: 'opened',
          tabCounts: mockProvide.epicsCount,
          searchInputPlaceholder: 'Search or filter results...',
          sortOptions: EpicsSortOptions,
          initialFilterValue: ['foo'],
          initialSortBy: 'created_desc',
          urlParams: wrapper.vm.urlParams,
          issuableSymbol: '&',
          recentSearchesStorageKey: 'epics',
        });
      });
  
      it.each`
        hasPreviousPage | hasNextPage  | returnValue
        ${true}         | ${undefined} | ${true}
        ${undefined}    | ${true}      | ${true}
        ${false}        | ${undefined} | ${false}
        ${undefined}    | ${false}     | ${false}
        ${false}        | ${false}     | ${false}
        ${true}         | ${true}      | ${true}
      `(
        'sets showPaginationControls prop value as $returnValue when hasPreviousPage is $hasPreviousPage and hasNextPage is $hasNextPage within `epics.pageInfo`',
        async ({ hasPreviousPage, hasNextPage, returnValue }) => {
          wrapper.setData({
            epics: {
              pageInfo: {
                hasPreviousPage,
                hasNextPage,
              },
            },
          });
  
          await wrapper.vm.$nextTick();
  
          expect(getIssuableList().props('showPaginationControls')).toBe(returnValue);
        },
      );
  
      it('sets previousPage prop value a number representing previous page based on currentPage value', async () => {
        wrapper.setData({
          currentPage: 3,
        });
  
        await wrapper.vm.$nextTick();
  
        expect(wrapper.vm.previousPage).toBe(2);
      });
  
      it('sets nextPage prop value a number representing next page based on currentPage value', async () => {
        wrapper.setData({
          currentPage: 1,
          epicsCount: {
            opened: 5,
            closed: 0,
            all: 5,
          },
        });
  
        await wrapper.vm.$nextTick();
  
        expect(getIssuableList().props('nextPage')).toBe(2);
      });
  
      it('sets nextPage prop value as `null` when currentPage is already last page', async () => {
        wrapper.setData({
          currentPage: 3,
          epicsCount: {
            opened: 5,
            closed: 0,
            all: 5,
          },
        });
  
        await wrapper.vm.$nextTick();
  
        expect(getIssuableList().props('nextPage')).toBeNull();
      });
    });
  });
  