boards_selector_spec.js 5.66 KB
Newer Older
1
import { nextTick } from 'vue';
2
import { mount } from '@vue/test-utils';
3
import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui';
4 5 6 7 8 9 10
import { TEST_HOST } from 'spec/test_constants';
import BoardsSelector from '~/boards/components/boards_selector.vue';
import boardsStore from '~/boards/stores/boards_store';

const throttleDuration = 1;

function boardGenerator(n) {
11 12
  return new Array(n).fill().map((board, index) => {
    const id = `${index}`;
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
    const name = `board${id}`;

    return {
      id,
      name,
    };
  });
}

describe('BoardsSelector', () => {
  let wrapper;
  let allBoardsResponse;
  let recentBoardsResponse;
  const boards = boardGenerator(20);
  const recentBoards = boardGenerator(5);

29
  const fillSearchBox = (filterTerm) => {
30 31 32 33 34 35 36
    const searchBox = wrapper.find({ ref: 'searchBox' });
    const searchBoxInput = searchBox.find('input');
    searchBoxInput.setValue(filterTerm);
    searchBoxInput.trigger('input');
  };

  const getDropdownItems = () => wrapper.findAll('.js-dropdown-item');
37
  const getDropdownHeaders = () => wrapper.findAll(GlDropdownSectionHeader);
38
  const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
39
  const findDropdown = () => wrapper.find(GlDropdown);
40 41

  beforeEach(() => {
42 43 44 45 46 47 48 49
    const $apollo = {
      queries: {
        boards: {
          loading: false,
        },
      },
    };

50 51 52 53 54 55 56 57 58
    boardsStore.setEndpoints({
      boardsEndpoint: '',
      recentBoardsEndpoint: '',
      listsEndpoint: '',
      bulkUpdatePath: '',
      boardId: '',
    });

    allBoardsResponse = Promise.resolve({
59 60 61
      data: {
        group: {
          boards: {
62
            edges: boards.map((board) => ({ node: board })),
63 64 65
          },
        },
      },
66 67 68 69 70 71 72 73
    });
    recentBoardsResponse = Promise.resolve({
      data: recentBoards,
    });

    boardsStore.allBoards = jest.fn(() => allBoardsResponse);
    boardsStore.recentBoards = jest.fn(() => recentBoardsResponse);

74
    wrapper = mount(BoardsSelector, {
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
      propsData: {
        throttleDuration,
        currentBoard: {
          id: 1,
          name: 'Development',
          milestone_id: null,
          weight: null,
          assignee_id: null,
          labels: [],
        },
        boardBaseUrl: `${TEST_HOST}/board/base/url`,
        hasMissingBoards: false,
        canAdminBoard: true,
        multipleIssueBoardsAvailable: true,
        labelsPath: `${TEST_HOST}/labels/path`,
90
        labelsWebUrl: `${TEST_HOST}/labels`,
91 92 93 94 95
        projectId: 42,
        groupId: 19,
        scopedIssueBoardFeatureEnabled: true,
        weights: [],
      },
96
      mocks: { $apollo },
97
      attachTo: document.body,
98 99
    });

100 101 102 103 104 105
    wrapper.vm.$apollo.addSmartQuery = jest.fn((_, options) => {
      wrapper.setData({
        [options.loadingKey]: true,
      });
    });

106
    // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
107
    findDropdown().vm.$emit('show');
108 109 110 111 112 113 114
  });

  afterEach(() => {
    wrapper.destroy();
    wrapper = null;
  });

115 116 117 118
  describe('loading', () => {
    // we are testing loading state, so don't resolve responses until after the tests
    afterEach(() => {
      return Promise.all([allBoardsResponse, recentBoardsResponse]).then(() => nextTick());
119 120
    });

121 122 123 124 125 126
    it('shows loading spinner', () => {
      expect(getDropdownHeaders()).toHaveLength(0);
      expect(getDropdownItems()).toHaveLength(0);
      expect(getLoadingIcon().exists()).toBe(true);
    });
  });
127

128
  describe('loaded', () => {
129 130 131 132
    beforeEach(async () => {
      await wrapper.setData({
        loadingBoards: false,
      });
133 134
      return Promise.all([allBoardsResponse, recentBoardsResponse]).then(() => nextTick());
    });
135

136 137
    it('hides loading spinner', () => {
      expect(getLoadingIcon().exists()).toBe(false);
138 139
    });

140 141 142 143 144
    describe('filtering', () => {
      beforeEach(() => {
        wrapper.setData({
          boards,
        });
145

146
        return nextTick();
147 148
      });

149 150 151
      it('shows all boards without filtering', () => {
        expect(getDropdownItems()).toHaveLength(boards.length + recentBoards.length);
      });
152

153 154
      it('shows only matching boards when filtering', () => {
        const filterTerm = 'board1';
155
        const expectedCount = boards.filter((board) => board.name.includes(filterTerm)).length;
156

157 158 159 160 161
        fillSearchBox(filterTerm);

        return nextTick().then(() => {
          expect(getDropdownItems()).toHaveLength(expectedCount);
        });
162 163
      });

164 165 166 167 168 169 170
      it('shows message if there are no matching boards', () => {
        fillSearchBox('does not exist');

        return nextTick().then(() => {
          expect(getDropdownItems()).toHaveLength(0);
          expect(wrapper.text().includes('No matching boards found')).toBe(true);
        });
171 172 173
      });
    });

174 175 176 177 178 179 180 181 182
    describe('recent boards section', () => {
      it('shows only when boards are greater than 10', () => {
        wrapper.setData({
          boards,
        });

        return nextTick().then(() => {
          expect(getDropdownHeaders()).toHaveLength(2);
        });
183 184
      });

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
      it('does not show when boards are less than 10', () => {
        wrapper.setData({
          boards: boards.slice(0, 5),
        });

        return nextTick().then(() => {
          expect(getDropdownHeaders()).toHaveLength(0);
        });
      });

      it('does not show when recentBoards api returns empty array', () => {
        wrapper.setData({
          recentBoards: [],
        });

        return nextTick().then(() => {
          expect(getDropdownHeaders()).toHaveLength(0);
        });
203 204
      });

205 206
      it('does not show when search is active', () => {
        fillSearchBox('Random string');
207

208 209 210
        return nextTick().then(() => {
          expect(getDropdownHeaders()).toHaveLength(0);
        });
211 212 213 214
      });
    });
  });
});