diff options
Diffstat (limited to 'spec/frontend/boards')
-rw-r--r-- | spec/frontend/boards/board_card_inner_spec.js | 19 | ||||
-rw-r--r-- | spec/frontend/boards/board_list_helper.js | 2 | ||||
-rw-r--r-- | spec/frontend/boards/board_list_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_card_spec.js | 37 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_form_spec.js | 19 | ||||
-rw-r--r-- | spec/frontend/boards/components/boards_selector_spec.js | 79 | ||||
-rw-r--r-- | spec/frontend/boards/components/issue_board_filtered_search_spec.js | 5 | ||||
-rw-r--r-- | spec/frontend/boards/mock_data.js | 10 |
8 files changed, 107 insertions, 66 deletions
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js index 95b5712bab0..8314cbda7a1 100644 --- a/spec/frontend/boards/board_card_inner_spec.js +++ b/spec/frontend/boards/board_card_inner_spec.js @@ -10,6 +10,7 @@ import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue'; import BoardCardInner from '~/boards/components/board_card_inner.vue'; +import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql'; import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue'; import eventHub from '~/boards/eventhub'; import defaultStore from '~/boards/stores'; @@ -63,17 +64,23 @@ describe('Board card component', () => { actions: { performSearch: performSearchMock, }, - state: { - ...defaultStore.state, - isShowingLabels: true, - }, + state: defaultStore.state, }); }; + const mockApollo = createMockApollo(); + const createWrapper = ({ props = {}, isEpicBoard = false, isGroupBoard = true } = {}) => { + mockApollo.clients.defaultClient.cache.writeQuery({ + query: isShowingLabelsQuery, + data: { + isShowingLabels: true, + }, + }); + wrapper = mountExtended(BoardCardInner, { store, - apolloProvider: createMockApollo(), + apolloProvider: mockApollo, propsData: { list, item: issue, @@ -235,7 +242,7 @@ describe('Board card component', () => { expect(tooltip).toBeDefined(); expect(findHiddenIssueIcon().attributes('title')).toBe( - 'This issue is hidden because its author has been banned', + 'This issue is hidden because its author has been banned.', ); }); }); diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js index 7367b34c4df..5bafd9a8d0e 100644 --- a/spec/frontend/boards/board_list_helper.js +++ b/spec/frontend/boards/board_list_helper.js @@ -122,5 +122,7 @@ export default function createComponent({ }, }); + jest.spyOn(store, 'dispatch').mockImplementation(() => {}); + return component; } diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js index e0a110678b1..30bb4fba4e3 100644 --- a/spec/frontend/boards/board_list_spec.js +++ b/spec/frontend/boards/board_list_spec.js @@ -202,8 +202,6 @@ describe('Board list component', () => { describe('handleDragOnEnd', () => { beforeEach(() => { - jest.spyOn(wrapper.vm, 'moveItem').mockImplementation(() => {}); - startDrag(); }); diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js index f0d40af94fe..11f9a4f6ff2 100644 --- a/spec/frontend/boards/components/board_card_spec.js +++ b/spec/frontend/boards/components/board_card_spec.js @@ -4,11 +4,14 @@ import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import VueApollo from 'vue-apollo'; +import waitForPromises from 'helpers/wait_for_promises'; import createMockApollo from 'helpers/mock_apollo_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import BoardCard from '~/boards/components/board_card.vue'; import BoardCardInner from '~/boards/components/board_card_inner.vue'; import { inactiveId } from '~/boards/constants'; +import selectedBoardItemsQuery from '~/boards/graphql/client/selected_board_items.query.graphql'; +import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql'; import { mockLabelList, mockIssue, DEFAULT_COLOR } from '../mock_data'; describe('Board card', () => { @@ -20,9 +23,11 @@ describe('Board card', () => { Vue.use(VueApollo); const mockSetActiveBoardItemResolver = jest.fn(); + const mockSetSelectedBoardItemsResolver = jest.fn(); const mockApollo = createMockApollo([], { Mutation: { setActiveBoardItem: mockSetActiveBoardItemResolver, + setSelectedBoardItems: mockSetSelectedBoardItemsResolver, }, }); @@ -49,7 +54,21 @@ describe('Board card', () => { provide = {}, stubs = { BoardCardInner }, item = mockIssue, + selectedBoardItems = [], } = {}) => { + mockApollo.clients.defaultClient.cache.writeQuery({ + query: isShowingLabelsQuery, + data: { + isShowingLabels: true, + }, + }); + mockApollo.clients.defaultClient.cache.writeQuery({ + query: selectedBoardItemsQuery, + data: { + selectedBoardItems, + }, + }); + wrapper = shallowMountExtended(BoardCard, { apolloProvider: mockApollo, stubs: { @@ -99,7 +118,7 @@ describe('Board card', () => { describe('when GlLabel is clicked in BoardCardInner', () => { it('doesnt call toggleBoardItem', () => { - createStore({ initialState: { isShowingLabels: true } }); + createStore(); mountComponent(); wrapper.findComponent(GlLabel).trigger('mouseup'); @@ -132,10 +151,9 @@ describe('Board card', () => { createStore({ initialState: { activeId: inactiveId, - selectedBoardItems: [mockIssue], }, }); - mountComponent(); + mountComponent({ selectedBoardItems: [mockIssue.id] }); expect(wrapper.classes()).toContain('multi-select'); expect(wrapper.classes()).not.toContain('is-active'); @@ -163,13 +181,17 @@ describe('Board card', () => { window.gon = { features: { boardMultiSelect: true } }; }); - it('should call vuex action "multiSelectBoardItem" with correct parameters', async () => { + it('should call setSelectedBoardItemsMutation with correct parameters', async () => { await multiSelectCard(); - expect(mockActions.toggleBoardItemMultiSelection).toHaveBeenCalledTimes(1); - expect(mockActions.toggleBoardItemMultiSelection).toHaveBeenCalledWith( + expect(mockSetSelectedBoardItemsResolver).toHaveBeenCalledTimes(1); + expect(mockSetSelectedBoardItemsResolver).toHaveBeenCalledWith( expect.any(Object), - mockIssue, + { + itemId: mockIssue.id, + }, + expect.anything(), + expect.anything(), ); }); }); @@ -240,6 +262,7 @@ describe('Board card', () => { it('set active board item on client when clicking on card', async () => { await selectCard(); + await waitForPromises(); expect(mockSetActiveBoardItemResolver).toHaveBeenCalledWith( {}, diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js index 15ee3976fb1..a0dacf085e2 100644 --- a/spec/frontend/boards/components/board_form_spec.js +++ b/spec/frontend/boards/components/board_form_spec.js @@ -14,6 +14,7 @@ import createBoardMutation from '~/boards/graphql/board_create.mutation.graphql' import destroyBoardMutation from '~/boards/graphql/board_destroy.mutation.graphql'; import updateBoardMutation from '~/boards/graphql/board_update.mutation.graphql'; import eventHub from '~/boards/eventhub'; +import * as cacheUpdates from '~/boards/graphql/cache_updates'; import { visitUrl } from '~/lib/utils/url_utility'; jest.mock('~/lib/utils/url_utility', () => ({ @@ -55,12 +56,10 @@ describe('BoardForm', () => { const findInput = () => wrapper.find('#board-new-name'); const setBoardMock = jest.fn(); - const setErrorMock = jest.fn(); const store = new Vuex.Store({ actions: { setBoard: setBoardMock, - setError: setErrorMock, }, }); @@ -113,6 +112,10 @@ describe('BoardForm', () => { }); }; + beforeEach(() => { + cacheUpdates.setError = jest.fn(); + }); + describe('when user can not admin the board', () => { beforeEach(() => { createComponent({ @@ -237,7 +240,7 @@ describe('BoardForm', () => { await waitForPromises(); expect(setBoardMock).not.toHaveBeenCalled(); - expect(setErrorMock).toHaveBeenCalled(); + expect(cacheUpdates.setError).toHaveBeenCalled(); }); describe('when Apollo boards FF is on', () => { @@ -353,7 +356,7 @@ describe('BoardForm', () => { await waitForPromises(); expect(setBoardMock).not.toHaveBeenCalled(); - expect(setErrorMock).toHaveBeenCalled(); + expect(cacheUpdates.setError).toHaveBeenCalled(); }); describe('when Apollo boards FF is on', () => { @@ -434,9 +437,11 @@ describe('BoardForm', () => { await waitForPromises(); expect(visitUrl).not.toHaveBeenCalled(); - expect(store.dispatch).toHaveBeenCalledWith('setError', { - message: 'Failed to delete board. Please try again.', - }); + expect(cacheUpdates.setError).toHaveBeenCalledWith( + expect.objectContaining({ + message: 'Failed to delete board. Please try again.', + }), + ); }); }); }); diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js index fa18b47cf54..0a628af9939 100644 --- a/spec/frontend/boards/components/boards_selector_spec.js +++ b/spec/frontend/boards/components/boards_selector_spec.js @@ -1,4 +1,4 @@ -import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui'; +import { GlCollapsibleListbox } from '@gitlab/ui'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; // eslint-disable-next-line no-restricted-imports @@ -13,7 +13,7 @@ import projectRecentBoardsQuery from '~/boards/graphql/project_recent_boards.que import * as cacheUpdates from '~/boards/graphql/cache_updates'; import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import createMockApollo from 'helpers/mock_apollo_helper'; -import { mountExtended } from 'helpers/vue_test_utils_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { mockBoard, mockGroupAllBoardsResponse, @@ -47,17 +47,11 @@ describe('BoardsSelector', () => { }); }; - const fillSearchBox = (filterTerm) => { - const searchBox = wrapper.findComponent({ ref: 'searchBox' }); - const searchBoxInput = searchBox.find('input'); - searchBoxInput.setValue(filterTerm); - searchBoxInput.trigger('input'); - }; + const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox); - const getDropdownItems = () => wrapper.findAllByTestId('dropdown-item'); - const getDropdownHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader); - const getLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); - const findDropdown = () => wrapper.findComponent(GlDropdown); + const fillSearchBox = async (filterTerm) => { + await findDropdown().vm.$emit('search', filterTerm); + }; const projectBoardsQueryHandlerSuccess = jest .fn() @@ -96,7 +90,7 @@ describe('BoardsSelector', () => { [groupRecentBoardsQuery, groupRecentBoardsQueryHandlerSuccess], ]); - wrapper = mountExtended(BoardsSelector, { + wrapper = shallowMountExtended(BoardsSelector, { store, apolloProvider: fakeApollo, propsData: { @@ -142,13 +136,19 @@ describe('BoardsSelector', () => { }); it('shows loading spinner', async () => { + createComponent({ + provide: { + isApolloBoard: true, + }, + props: { + isCurrentBoardLoading: true, + }, + }); // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time - findDropdown().vm.$emit('show'); + findDropdown().vm.$emit('shown'); await nextTick(); - expect(getLoadingIcon().exists()).toBe(true); - expect(getDropdownHeaders()).toHaveLength(0); - expect(getDropdownItems()).toHaveLength(0); + expect(findDropdown().props('loading')).toBe(true); }); }); @@ -158,7 +158,7 @@ describe('BoardsSelector', () => { await nextTick(); // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time - findDropdown().vm.$emit('show'); + findDropdown().vm.$emit('shown'); await nextTick(); }); @@ -167,9 +167,8 @@ describe('BoardsSelector', () => { expect(projectBoardsQueryHandlerSuccess).toHaveBeenCalled(); }); - it('hides loading spinner', async () => { - await nextTick(); - expect(getLoadingIcon().exists()).toBe(false); + it('hides loading spinner', () => { + expect(findDropdown().props('loading')).toBe(false); }); describe('filtering', () => { @@ -178,25 +177,26 @@ describe('BoardsSelector', () => { }); it('shows all boards without filtering', () => { - expect(getDropdownItems()).toHaveLength(boards.length + recentIssueBoards.length); + expect(findDropdown().props('items')[0].text).toBe('Recent'); + expect(findDropdown().props('items')[0].options).toHaveLength(recentIssueBoards.length); + expect(findDropdown().props('items')[1].text).toBe('All'); + expect(findDropdown().props('items')[1].options).toHaveLength( + boards.length - recentIssueBoards.length, + ); }); 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(); - expect(getDropdownItems()).toHaveLength(expectedCount); + await fillSearchBox(filterTerm); + expect(findDropdown().props('items')).toHaveLength(expectedCount); }); it('shows message if there are no matching boards', async () => { - fillSearchBox('does not exist'); + await fillSearchBox('does not exist'); - await nextTick(); - expect(getDropdownItems()).toHaveLength(0); - expect(wrapper.text().includes('No matching boards found')).toBe(true); + expect(findDropdown().props('noResultsText')).toBe('No matching boards found'); }); }); @@ -204,14 +204,18 @@ describe('BoardsSelector', () => { it('shows only when boards are greater than 10', async () => { await nextTick(); expect(projectRecentBoardsQueryHandlerSuccess).toHaveBeenCalled(); - expect(getDropdownHeaders()).toHaveLength(2); + + expect(findDropdown().props('items')).toHaveLength(2); + expect(findDropdown().props('items')[0].text).toBe('Recent'); + expect(findDropdown().props('items')[1].text).toBe('All'); }); it('does not show when boards are less than 10', async () => { createComponent({ projectBoardsQueryHandler: smallBoardsQueryHandlerSuccess }); await nextTick(); - expect(getDropdownHeaders()).toHaveLength(0); + + expect(findDropdown().props('items')).toHaveLength(0); }); it('does not show when recentIssueBoards api returns empty array', async () => { @@ -220,14 +224,14 @@ describe('BoardsSelector', () => { }); await nextTick(); - expect(getDropdownHeaders()).toHaveLength(0); + expect(findDropdown().props('items')).toHaveLength(0); }); it('does not show when search is active', async () => { fillSearchBox('Random string'); await nextTick(); - expect(getDropdownHeaders()).toHaveLength(0); + expect(findDropdown().props('items')).toHaveLength(0); }); }); }); @@ -248,7 +252,7 @@ describe('BoardsSelector', () => { await nextTick(); // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time - findDropdown().vm.$emit('show'); + findDropdown().vm.$emit('shown'); await nextTick(); @@ -272,7 +276,7 @@ describe('BoardsSelector', () => { await nextTick(); // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time - findDropdown().vm.$emit('show'); + findDropdown().vm.$emit('shown'); await waitForPromises(); @@ -286,6 +290,7 @@ describe('BoardsSelector', () => { createStore(); createComponent({ provide: { multipleIssueBoardsAvailable: true } }); expect(findDropdown().exists()).toBe(true); + expect(findDropdown().props('toggleText')).toBe('Select board'); }); }); @@ -296,6 +301,7 @@ describe('BoardsSelector', () => { provide: { multipleIssueBoardsAvailable: false, hasMissingBoards: true }, }); expect(findDropdown().exists()).toBe(true); + expect(findDropdown().props('toggleText')).toBe('Select board'); }); }); @@ -317,6 +323,7 @@ describe('BoardsSelector', () => { provide: { isApolloBoard: true }, }); expect(findDropdown().props('loading')).toBe(true); + expect(findDropdown().props('toggleText')).toBe('Select board'); }); }); }); diff --git a/spec/frontend/boards/components/issue_board_filtered_search_spec.js b/spec/frontend/boards/components/issue_board_filtered_search_spec.js index 16ad54f0854..1edb6812af0 100644 --- a/spec/frontend/boards/components/issue_board_filtered_search_spec.js +++ b/spec/frontend/boards/components/issue_board_filtered_search_spec.js @@ -26,14 +26,11 @@ describe('IssueBoardFilter', () => { }); }; - let fetchUsersSpy; let fetchLabelsSpy; beforeEach(() => { - fetchUsersSpy = jest.fn(); fetchLabelsSpy = jest.fn(); issueBoardFilters.mockReturnValue({ - fetchUsers: fetchUsersSpy, fetchLabels: fetchLabelsSpy, }); }); @@ -61,7 +58,7 @@ describe('IssueBoardFilter', () => { ({ isSignedIn }) => { createComponent({ isSignedIn }); - const tokens = mockTokens(fetchLabelsSpy, fetchUsersSpy, isSignedIn); + const tokens = mockTokens(fetchLabelsSpy, isSignedIn); expect(findBoardsFilteredSearch().props('tokens')).toEqual(orderBy(tokens, ['title'])); }, diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js index dfcdb4c05d0..dfc8b18e197 100644 --- a/spec/frontend/boards/mock_data.js +++ b/spec/frontend/boards/mock_data.js @@ -827,7 +827,7 @@ export const mockConfidentialToken = { ], }; -export const mockTokens = (fetchLabels, fetchUsers, isSignedIn) => [ +export const mockTokens = (fetchLabels, isSignedIn) => [ { icon: 'user', title: TOKEN_TITLE_ASSIGNEE, @@ -836,7 +836,8 @@ export const mockTokens = (fetchLabels, fetchUsers, isSignedIn) => [ token: UserToken, dataType: 'user', unique: true, - fetchUsers, + fullPath: 'gitlab-org', + isProject: false, preloadedUsers: [], }, { @@ -848,7 +849,8 @@ export const mockTokens = (fetchLabels, fetchUsers, isSignedIn) => [ token: UserToken, dataType: 'user', unique: true, - fetchUsers, + fullPath: 'gitlab-org', + isProject: false, preloadedUsers: [], }, { @@ -973,7 +975,7 @@ export const boardListQueryResponse = ({ boardList: { __typename: 'BoardList', id: listId, - totalWeight: 5, + totalIssueWeight: '5', issuesCount, }, }, |