2021-02-22 17:27:13 +05:30
|
|
|
import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui';
|
2021-03-11 19:13:27 +05:30
|
|
|
import { mount } from '@vue/test-utils';
|
|
|
|
import MockAdapter from 'axios-mock-adapter';
|
2021-12-11 22:18:48 +05:30
|
|
|
import Vue, { nextTick } from 'vue';
|
|
|
|
import VueApollo from 'vue-apollo';
|
|
|
|
import Vuex from 'vuex';
|
2020-04-08 14:13:33 +05:30
|
|
|
import { TEST_HOST } from 'spec/test_constants';
|
|
|
|
import BoardsSelector from '~/boards/components/boards_selector.vue';
|
2021-12-11 22:18:48 +05:30
|
|
|
import groupBoardQuery from '~/boards/graphql/group_board.query.graphql';
|
|
|
|
import projectBoardQuery from '~/boards/graphql/project_board.query.graphql';
|
|
|
|
import defaultStore from '~/boards/stores';
|
2021-03-11 19:13:27 +05:30
|
|
|
import axios from '~/lib/utils/axios_utils';
|
2021-12-11 22:18:48 +05:30
|
|
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
|
|
|
import { mockGroupBoardResponse, mockProjectBoardResponse } from '../mock_data';
|
2020-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
const throttleDuration = 1;
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
Vue.use(VueApollo);
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
function boardGenerator(n) {
|
|
|
|
return new Array(n).fill().map((board, index) => {
|
|
|
|
const id = `${index}`;
|
|
|
|
const name = `board${id}`;
|
|
|
|
|
|
|
|
return {
|
|
|
|
id,
|
|
|
|
name,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('BoardsSelector', () => {
|
|
|
|
let wrapper;
|
|
|
|
let allBoardsResponse;
|
|
|
|
let recentBoardsResponse;
|
2021-03-11 19:13:27 +05:30
|
|
|
let mock;
|
2021-12-11 22:18:48 +05:30
|
|
|
let fakeApollo;
|
|
|
|
let store;
|
2020-04-08 14:13:33 +05:30
|
|
|
const boards = boardGenerator(20);
|
|
|
|
const recentBoards = boardGenerator(5);
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
const createStore = ({ isGroupBoard = false, isProjectBoard = false } = {}) => {
|
|
|
|
store = new Vuex.Store({
|
|
|
|
...defaultStore,
|
|
|
|
actions: {
|
|
|
|
setError: jest.fn(),
|
|
|
|
},
|
|
|
|
getters: {
|
|
|
|
isGroupBoard: () => isGroupBoard,
|
|
|
|
isProjectBoard: () => isProjectBoard,
|
|
|
|
},
|
|
|
|
state: {
|
|
|
|
boardType: isGroupBoard ? 'group' : 'project',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
const fillSearchBox = (filterTerm) => {
|
2020-04-08 14:13:33 +05:30
|
|
|
const searchBox = wrapper.find({ ref: 'searchBox' });
|
|
|
|
const searchBoxInput = searchBox.find('input');
|
|
|
|
searchBoxInput.setValue(filterTerm);
|
|
|
|
searchBoxInput.trigger('input');
|
|
|
|
};
|
|
|
|
|
|
|
|
const getDropdownItems = () => wrapper.findAll('.js-dropdown-item');
|
2021-02-22 17:27:13 +05:30
|
|
|
const getDropdownHeaders = () => wrapper.findAll(GlDropdownSectionHeader);
|
2020-04-08 14:13:33 +05:30
|
|
|
const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
|
2021-02-22 17:27:13 +05:30
|
|
|
const findDropdown = () => wrapper.find(GlDropdown);
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
const projectBoardQueryHandlerSuccess = jest.fn().mockResolvedValue(mockProjectBoardResponse);
|
|
|
|
const groupBoardQueryHandlerSuccess = jest.fn().mockResolvedValue(mockGroupBoardResponse);
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
const createComponent = () => {
|
|
|
|
fakeApollo = createMockApollo([
|
|
|
|
[projectBoardQuery, projectBoardQueryHandlerSuccess],
|
|
|
|
[groupBoardQuery, groupBoardQueryHandlerSuccess],
|
|
|
|
]);
|
2020-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
wrapper = mount(BoardsSelector, {
|
2021-12-11 22:18:48 +05:30
|
|
|
store,
|
|
|
|
apolloProvider: fakeApollo,
|
2020-04-08 14:13:33 +05:30
|
|
|
propsData: {
|
|
|
|
throttleDuration,
|
|
|
|
boardBaseUrl: `${TEST_HOST}/board/base/url`,
|
|
|
|
hasMissingBoards: false,
|
|
|
|
canAdminBoard: true,
|
|
|
|
multipleIssueBoardsAvailable: true,
|
|
|
|
scopedIssueBoardFeatureEnabled: true,
|
|
|
|
weights: [],
|
|
|
|
},
|
2021-03-08 18:12:59 +05:30
|
|
|
attachTo: document.body,
|
2021-03-11 19:13:27 +05:30
|
|
|
provide: {
|
|
|
|
fullPath: '',
|
|
|
|
recentBoardsEndpoint: `${TEST_HOST}/recent`,
|
|
|
|
},
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
wrapper.vm.$apollo.addSmartQuery = jest.fn((_, options) => {
|
|
|
|
wrapper.setData({
|
|
|
|
[options.loadingKey]: true,
|
|
|
|
});
|
|
|
|
});
|
2021-12-11 22:18:48 +05:30
|
|
|
};
|
2020-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
wrapper = null;
|
2021-03-11 19:13:27 +05:30
|
|
|
mock.restore();
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
describe('fetching all boards', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mock = new MockAdapter(axios);
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
allBoardsResponse = Promise.resolve({
|
|
|
|
data: {
|
|
|
|
group: {
|
|
|
|
boards: {
|
|
|
|
edges: boards.map((board) => ({ node: board })),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
recentBoardsResponse = Promise.resolve({
|
|
|
|
data: recentBoards,
|
|
|
|
});
|
|
|
|
|
|
|
|
createStore();
|
|
|
|
createComponent();
|
|
|
|
|
|
|
|
mock.onGet(`${TEST_HOST}/recent`).replyOnce(200, recentBoards);
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
describe('loading', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
// Wait for current board to be loaded
|
|
|
|
await nextTick();
|
|
|
|
|
|
|
|
// Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
|
|
|
|
findDropdown().vm.$emit('show');
|
|
|
|
});
|
|
|
|
|
|
|
|
// we are testing loading state, so don't resolve responses until after the tests
|
|
|
|
afterEach(async () => {
|
|
|
|
await Promise.all([allBoardsResponse, recentBoardsResponse]);
|
|
|
|
await nextTick();
|
2021-02-22 17:27:13 +05:30
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('shows loading spinner', () => {
|
|
|
|
expect(getDropdownHeaders()).toHaveLength(0);
|
|
|
|
expect(getDropdownItems()).toHaveLength(0);
|
|
|
|
expect(getLoadingIcon().exists()).toBe(true);
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
describe('loaded', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
// Wait for current board to be loaded
|
|
|
|
await nextTick();
|
|
|
|
|
|
|
|
// Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
|
|
|
|
findDropdown().vm.$emit('show');
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
await wrapper.setData({
|
|
|
|
loadingBoards: false,
|
|
|
|
loadingRecentBoards: false,
|
|
|
|
});
|
|
|
|
await Promise.all([allBoardsResponse, recentBoardsResponse]);
|
|
|
|
await nextTick();
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('hides loading spinner', async () => {
|
|
|
|
await nextTick();
|
|
|
|
expect(getLoadingIcon().exists()).toBe(false);
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
describe('filtering', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
wrapper.setData({
|
|
|
|
boards,
|
|
|
|
});
|
|
|
|
|
|
|
|
await nextTick();
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('shows all boards without filtering', () => {
|
|
|
|
expect(getDropdownItems()).toHaveLength(boards.length + recentBoards.length);
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('shows only matching boards when filtering', async () => {
|
|
|
|
const filterTerm = 'board1';
|
|
|
|
const expectedCount = boards.filter((board) => board.name.includes(filterTerm)).length;
|
|
|
|
|
|
|
|
fillSearchBox(filterTerm);
|
|
|
|
|
|
|
|
await nextTick();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(getDropdownItems()).toHaveLength(expectedCount);
|
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('shows message if there are no matching boards', async () => {
|
|
|
|
fillSearchBox('does not exist');
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
await nextTick();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(getDropdownItems()).toHaveLength(0);
|
|
|
|
expect(wrapper.text().includes('No matching boards found')).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
describe('recent boards section', () => {
|
|
|
|
it('shows only when boards are greater than 10', async () => {
|
|
|
|
wrapper.setData({
|
|
|
|
boards,
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
await nextTick();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(getDropdownHeaders()).toHaveLength(2);
|
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('does not show when boards are less than 10', async () => {
|
|
|
|
wrapper.setData({
|
|
|
|
boards: boards.slice(0, 5),
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
await nextTick();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(getDropdownHeaders()).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('does not show when recentBoards api returns empty array', async () => {
|
|
|
|
wrapper.setData({
|
|
|
|
recentBoards: [],
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
await nextTick();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(getDropdownHeaders()).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
it('does not show when search is active', async () => {
|
|
|
|
fillSearchBox('Random string');
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
await nextTick();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(getDropdownHeaders()).toHaveLength(0);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2021-12-11 22:18:48 +05:30
|
|
|
|
|
|
|
describe('fetching current board', () => {
|
|
|
|
it.each`
|
|
|
|
boardType | queryHandler | notCalledHandler
|
|
|
|
${'group'} | ${groupBoardQueryHandlerSuccess} | ${projectBoardQueryHandlerSuccess}
|
|
|
|
${'project'} | ${projectBoardQueryHandlerSuccess} | ${groupBoardQueryHandlerSuccess}
|
|
|
|
`('fetches $boardType board', async ({ boardType, queryHandler, notCalledHandler }) => {
|
|
|
|
createStore({
|
|
|
|
isProjectBoard: boardType === 'project',
|
|
|
|
isGroupBoard: boardType === 'group',
|
|
|
|
});
|
|
|
|
createComponent();
|
|
|
|
|
|
|
|
await nextTick();
|
|
|
|
|
|
|
|
expect(queryHandler).toHaveBeenCalled();
|
|
|
|
expect(notCalledHandler).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|