diff options
Diffstat (limited to 'spec/frontend/boards')
10 files changed, 160 insertions, 98 deletions
diff --git a/spec/frontend/boards/boards_util_spec.js b/spec/frontend/boards/boards_util_spec.js index d45b6e35a45..ab3cf072357 100644 --- a/spec/frontend/boards/boards_util_spec.js +++ b/spec/frontend/boards/boards_util_spec.js @@ -1,6 +1,12 @@ import { formatIssueInput, filterVariables } from '~/boards/boards_util'; describe('formatIssueInput', () => { + const issueInput = { + labelIds: ['gid://gitlab/GroupLabel/5'], + projectPath: 'gitlab-org/gitlab-test', + id: 'gid://gitlab/Issue/11', + }; + it('correctly merges boardConfig into the issue', () => { const boardConfig = { labels: [ @@ -14,12 +20,6 @@ describe('formatIssueInput', () => { weight: 1, }; - const issueInput = { - labelIds: ['gid://gitlab/GroupLabel/5'], - projectPath: 'gitlab-org/gitlab-test', - id: 'gid://gitlab/Issue/11', - }; - const result = formatIssueInput(issueInput, boardConfig); expect(result).toEqual({ projectPath: 'gitlab-org/gitlab-test', @@ -27,8 +27,26 @@ describe('formatIssueInput', () => { labelIds: ['gid://gitlab/GroupLabel/5', 'gid://gitlab/GroupLabel/44'], assigneeIds: ['gid://gitlab/User/55'], milestoneId: 'gid://gitlab/Milestone/66', + weight: 1, }); }); + + it('does not add weight to input if weight is NONE', () => { + const boardConfig = { + weight: -2, // NO_WEIGHT + }; + + const result = formatIssueInput(issueInput, boardConfig); + const expected = { + projectPath: 'gitlab-org/gitlab-test', + id: 'gid://gitlab/Issue/11', + labelIds: ['gid://gitlab/GroupLabel/5'], + assigneeIds: [], + milestoneId: undefined, + }; + + expect(result).toEqual(expected); + }); }); describe('filterVariables', () => { diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js index 85ba703a6ee..731578e15a3 100644 --- a/spec/frontend/boards/components/board_filtered_search_spec.js +++ b/spec/frontend/boards/components/board_filtered_search_spec.js @@ -124,7 +124,7 @@ describe('BoardFilteredSearch', () => { { type: 'milestone', value: { data: 'New Milestone', operator: '=' } }, { type: 'type', value: { data: 'INCIDENT', operator: '=' } }, { type: 'weight', value: { data: '2', operator: '=' } }, - { type: 'iteration', value: { data: '3341', operator: '=' } }, + { type: 'iteration', value: { data: 'Any&3', operator: '=' } }, { type: 'release', value: { data: 'v1.0.0', operator: '=' } }, ]; jest.spyOn(urlUtility, 'updateHistory'); @@ -134,7 +134,7 @@ describe('BoardFilteredSearch', () => { title: '', replace: true, url: - 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label%262&assignee_username=root&milestone_title=New%20Milestone&iteration_id=3341&types=INCIDENT&weight=2&release_tag=v1.0.0', + 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label%262&assignee_username=root&milestone_title=New%20Milestone&iteration_id=Any&iteration_cadence_id=3&types=INCIDENT&weight=2&release_tag=v1.0.0', }); }); diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js index c976ba7525b..6a659623b53 100644 --- a/spec/frontend/boards/components/board_form_spec.js +++ b/spec/frontend/boards/components/board_form_spec.js @@ -62,7 +62,7 @@ describe('BoardForm', () => { }; }, provide: { - rootPath: 'root', + boardBaseUrl: 'root', }, mocks: { $apollo: { diff --git a/spec/frontend/boards/components/board_top_bar_spec.js b/spec/frontend/boards/components/board_top_bar_spec.js new file mode 100644 index 00000000000..997768a0cc7 --- /dev/null +++ b/spec/frontend/boards/components/board_top_bar_spec.js @@ -0,0 +1,88 @@ +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +import Vuex from 'vuex'; + +import BoardTopBar from '~/boards/components/board_top_bar.vue'; +import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue'; +import BoardsSelector from '~/boards/components/boards_selector.vue'; +import ConfigToggle from '~/boards/components/config_toggle.vue'; +import IssueBoardFilteredSearch from '~/boards/components/issue_board_filtered_search.vue'; +import NewBoardButton from '~/boards/components/new_board_button.vue'; +import ToggleFocus from '~/boards/components/toggle_focus.vue'; + +describe('BoardTopBar', () => { + let wrapper; + + Vue.use(Vuex); + + const createStore = ({ mockGetters = {} } = {}) => { + return new Vuex.Store({ + state: {}, + getters: { + isEpicBoard: () => false, + ...mockGetters, + }, + }); + }; + + const createComponent = ({ provide = {}, mockGetters = {} } = {}) => { + const store = createStore({ mockGetters }); + wrapper = shallowMount(BoardTopBar, { + store, + provide: { + swimlanesFeatureAvailable: false, + canAdminList: false, + isSignedIn: false, + fullPath: 'gitlab-org', + boardType: 'group', + releasesFetchPath: '/releases', + ...provide, + }, + stubs: { IssueBoardFilteredSearch }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('base template', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders BoardsSelector component', () => { + expect(wrapper.findComponent(BoardsSelector).exists()).toBe(true); + }); + + it('renders IssueBoardFilteredSearch component', () => { + expect(wrapper.findComponent(IssueBoardFilteredSearch).exists()).toBe(true); + }); + + it('renders NewBoardButton component', () => { + expect(wrapper.findComponent(NewBoardButton).exists()).toBe(true); + }); + + it('renders ConfigToggle component', () => { + expect(wrapper.findComponent(ConfigToggle).exists()).toBe(true); + }); + + it('renders ToggleFocus component', () => { + expect(wrapper.findComponent(ToggleFocus).exists()).toBe(true); + }); + + it('does not render BoardAddNewColumnTrigger component', () => { + expect(wrapper.findComponent(BoardAddNewColumnTrigger).exists()).toBe(false); + }); + }); + + describe('when user can admin list', () => { + beforeEach(() => { + createComponent({ provide: { canAdminList: true } }); + }); + + it('renders BoardAddNewColumnTrigger component', () => { + expect(wrapper.findComponent(BoardAddNewColumnTrigger).exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js index 0c044deb78c..f60d04af4fc 100644 --- a/spec/frontend/boards/components/boards_selector_spec.js +++ b/spec/frontend/boards/components/boards_selector_spec.js @@ -1,5 +1,4 @@ import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import Vuex from 'vuex'; @@ -14,6 +13,7 @@ import groupRecentBoardsQuery from '~/boards/graphql/group_recent_boards.query.g import projectRecentBoardsQuery from '~/boards/graphql/project_recent_boards.query.graphql'; import defaultStore from '~/boards/stores'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import { mockGroupBoardResponse, mockProjectBoardResponse, @@ -60,7 +60,7 @@ describe('BoardsSelector', () => { searchBoxInput.trigger('input'); }; - const getDropdownItems = () => wrapper.findAll('.js-dropdown-item'); + const getDropdownItems = () => wrapper.findAllByTestId('dropdown-item'); const getDropdownHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader); const getLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findDropdown = () => wrapper.findComponent(GlDropdown); @@ -100,11 +100,15 @@ describe('BoardsSelector', () => { [groupRecentBoardsQuery, groupRecentBoardsQueryHandlerSuccess], ]); - wrapper = mount(BoardsSelector, { + wrapper = mountExtended(BoardsSelector, { store, apolloProvider: fakeApollo, propsData: { throttleDuration, + }, + attachTo: document.body, + provide: { + fullPath: '', boardBaseUrl: `${TEST_HOST}/board/base/url`, hasMissingBoards: false, canAdminBoard: true, @@ -112,10 +116,6 @@ describe('BoardsSelector', () => { scopedIssueBoardFeatureEnabled: true, weights: [], }, - attachTo: document.body, - provide: { - fullPath: '', - }, }); }; diff --git a/spec/frontend/boards/components/issuable_title_spec.js b/spec/frontend/boards/components/issuable_title_spec.js deleted file mode 100644 index 4b7f491b998..00000000000 --- a/spec/frontend/boards/components/issuable_title_spec.js +++ /dev/null @@ -1,33 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import IssuableTitle from '~/boards/components/issuable_title.vue'; - -describe('IssuableTitle', () => { - let wrapper; - const defaultProps = { - title: 'One', - refPath: 'path', - }; - const createComponent = () => { - wrapper = shallowMount(IssuableTitle, { - propsData: { ...defaultProps }, - }); - }; - const findIssueContent = () => wrapper.find('[data-testid="issue-title"]'); - - beforeEach(() => { - createComponent(); - }); - - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - - it('renders a title of an issue in the sidebar', () => { - expect(findIssueContent().text()).toContain('One'); - }); - - it('renders a referencePath of an issue in the sidebar', () => { - expect(findIssueContent().text()).toContain('path'); - }); -}); 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 76e8b84d8ef..e4a6a2b8b76 100644 --- a/spec/frontend/boards/components/issue_board_filtered_search_spec.js +++ b/spec/frontend/boards/components/issue_board_filtered_search_spec.js @@ -14,10 +14,11 @@ describe('IssueBoardFilter', () => { const createComponent = ({ isSignedIn = false } = {}) => { wrapper = shallowMount(IssueBoardFilteredSpec, { - propsData: { fullPath: 'gitlab-org', boardType: 'group' }, provide: { isSignedIn, releasesFetchPath: '/releases', + fullPath: 'gitlab-org', + boardType: 'group', }, }); }; diff --git a/spec/frontend/boards/components/issue_time_estimate_spec.js b/spec/frontend/boards/components/issue_time_estimate_spec.js index 635964b6b4a..948a7a20f7f 100644 --- a/spec/frontend/boards/components/issue_time_estimate_spec.js +++ b/spec/frontend/boards/components/issue_time_estimate_spec.js @@ -5,6 +5,8 @@ import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue'; describe('Issue Time Estimate component', () => { let wrapper; + const findIssueTimeEstimate = () => wrapper.find('[data-testid="issue-time-estimate"]'); + afterEach(() => { wrapper.destroy(); }); @@ -26,7 +28,7 @@ describe('Issue Time Estimate component', () => { }); it('renders expanded time estimate in tooltip', () => { - expect(wrapper.find('.js-issue-time-estimate').text()).toContain('2 weeks 3 days 1 minute'); + expect(findIssueTimeEstimate().text()).toContain('2 weeks 3 days 1 minute'); }); it('prevents tooltip xss', async () => { @@ -42,7 +44,7 @@ describe('Issue Time Estimate component', () => { expect(alertSpy).not.toHaveBeenCalled(); expect(wrapper.find('time').text().trim()).toEqual('0m'); - expect(wrapper.find('.js-issue-time-estimate').text()).toContain('0m'); + expect(findIssueTimeEstimate().text()).toContain('0m'); }); }); @@ -63,7 +65,7 @@ describe('Issue Time Estimate component', () => { }); it('renders expanded time estimate in tooltip', () => { - expect(wrapper.find('.js-issue-time-estimate').text()).toContain('104 hours 1 minute'); + expect(findIssueTimeEstimate().text()).toContain('104 hours 1 minute'); }); }); }); diff --git a/spec/frontend/boards/components/item_count_spec.js b/spec/frontend/boards/components/item_count_spec.js index 45980c36f1c..06cd3910fc0 100644 --- a/spec/frontend/boards/components/item_count_spec.js +++ b/spec/frontend/boards/components/item_count_spec.js @@ -29,7 +29,7 @@ describe('IssueCount', () => { }); it('does not contains maxIssueCount in the template', () => { - expect(vm.find('.js-max-issue-size').exists()).toBe(false); + expect(vm.find('.max-issue-size').exists()).toBe(false); }); }); @@ -50,7 +50,7 @@ describe('IssueCount', () => { }); it('contains maxIssueCount in the template', () => { - expect(vm.find('.js-max-issue-size').text()).toEqual(String(maxIssueCount)); + expect(vm.find('.max-issue-size').text()).toEqual(String(maxIssueCount)); }); it('does not have text-danger class when issueSize is less than maxIssueCount', () => { @@ -75,7 +75,7 @@ describe('IssueCount', () => { }); it('contains maxIssueCount in the template', () => { - expect(vm.find('.js-max-issue-size').text()).toEqual(String(maxIssueCount)); + expect(vm.find('.max-issue-size').text()).toEqual(String(maxIssueCount)); }); it('has text-danger class', () => { diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index ad661a31556..eacf9db191e 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -166,31 +166,29 @@ describe('setFilters', () => { }); describe('performSearch', () => { - it('should dispatch setFilters, fetchLists and resetIssues action', (done) => { - testAction( + it('should dispatch setFilters, fetchLists and resetIssues action', () => { + return testAction( actions.performSearch, {}, {}, [], [{ type: 'setFilters', payload: {} }, { type: 'fetchLists' }, { type: 'resetIssues' }], - done, ); }); }); describe('setActiveId', () => { - it('should commit mutation SET_ACTIVE_ID', (done) => { + it('should commit mutation SET_ACTIVE_ID', () => { const state = { activeId: inactiveId, }; - testAction( + return testAction( actions.setActiveId, { id: 1, sidebarType: 'something' }, state, [{ type: types.SET_ACTIVE_ID, payload: { id: 1, sidebarType: 'something' } }], [], - done, ); }); }); @@ -219,10 +217,10 @@ describe('fetchLists', () => { const formattedLists = formatBoardLists(queryResponse.data.group.board.lists); - it('should commit mutations RECEIVE_BOARD_LISTS_SUCCESS on success', (done) => { + it('should commit mutations RECEIVE_BOARD_LISTS_SUCCESS on success', () => { jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse); - testAction( + return testAction( actions.fetchLists, {}, state, @@ -233,14 +231,13 @@ describe('fetchLists', () => { }, ], [], - done, ); }); - it('should commit mutations RECEIVE_BOARD_LISTS_FAILURE on failure', (done) => { + it('should commit mutations RECEIVE_BOARD_LISTS_FAILURE on failure', () => { jest.spyOn(gqlClient, 'query').mockResolvedValue(Promise.reject()); - testAction( + return testAction( actions.fetchLists, {}, state, @@ -250,11 +247,10 @@ describe('fetchLists', () => { }, ], [], - done, ); }); - it('dispatch createList action when backlog list does not exist and is not hidden', (done) => { + it('dispatch createList action when backlog list does not exist and is not hidden', () => { queryResponse = { data: { group: { @@ -269,7 +265,7 @@ describe('fetchLists', () => { }; jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse); - testAction( + return testAction( actions.fetchLists, {}, state, @@ -280,7 +276,6 @@ describe('fetchLists', () => { }, ], [{ type: 'createList', payload: { backlog: true } }], - done, ); }); @@ -951,10 +946,10 @@ describe('fetchItemsForList', () => { }); }); - it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_SUCCESS on success', (done) => { + it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_SUCCESS on success', () => { jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse); - testAction( + return testAction( actions.fetchItemsForList, { listId }, state, @@ -973,14 +968,13 @@ describe('fetchItemsForList', () => { }, ], [], - done, ); }); - it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_FAILURE on failure', (done) => { + it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_FAILURE on failure', () => { jest.spyOn(gqlClient, 'query').mockResolvedValue(Promise.reject()); - testAction( + return testAction( actions.fetchItemsForList, { listId }, state, @@ -996,7 +990,6 @@ describe('fetchItemsForList', () => { { type: types.RECEIVE_ITEMS_FOR_LIST_FAILURE, payload: listId }, ], [], - done, ); }); }); @@ -1398,8 +1391,8 @@ describe('setAssignees', () => { const node = { username: 'name' }; describe('when succeeds', () => { - it('calls the correct mutation with the correct values', (done) => { - testAction( + it('calls the correct mutation with the correct values', () => { + return testAction( actions.setAssignees, { assignees: [node], iid: '1' }, { commit: () => {} }, @@ -1410,7 +1403,6 @@ describe('setAssignees', () => { }, ], [], - done, ); }); }); @@ -1728,7 +1720,7 @@ describe('setActiveItemSubscribed', () => { projectPath: 'gitlab-org/gitlab-test', }; - it('should commit subscribed status', (done) => { + it('should commit subscribed status', () => { jest.spyOn(gqlClient, 'mutate').mockResolvedValue({ data: { updateIssuableSubscription: { @@ -1746,7 +1738,7 @@ describe('setActiveItemSubscribed', () => { value: subscribedState, }; - testAction( + return testAction( actions.setActiveItemSubscribed, input, { ...state, ...getters }, @@ -1757,7 +1749,6 @@ describe('setActiveItemSubscribed', () => { }, ], [], - done, ); }); @@ -1783,7 +1774,7 @@ describe('setActiveItemTitle', () => { projectPath: 'h/b', }; - it('should commit title after setting the issue', (done) => { + it('should commit title after setting the issue', () => { jest.spyOn(gqlClient, 'mutate').mockResolvedValue({ data: { updateIssuableTitle: { @@ -1801,7 +1792,7 @@ describe('setActiveItemTitle', () => { value: testTitle, }; - testAction( + return testAction( actions.setActiveItemTitle, input, { ...state, ...getters }, @@ -1812,7 +1803,6 @@ describe('setActiveItemTitle', () => { }, ], [], - done, ); }); @@ -1829,14 +1819,14 @@ describe('setActiveItemConfidential', () => { const state = { boardItems: { [mockIssue.id]: mockIssue } }; const getters = { activeBoardItem: mockIssue }; - it('set confidential value on board item', (done) => { + it('set confidential value on board item', () => { const payload = { itemId: getters.activeBoardItem.id, prop: 'confidential', value: true, }; - testAction( + return testAction( actions.setActiveItemConfidential, true, { ...state, ...getters }, @@ -1847,7 +1837,6 @@ describe('setActiveItemConfidential', () => { }, ], [], - done, ); }); }); @@ -1876,10 +1865,10 @@ describe('fetchGroupProjects', () => { }, }; - it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_SUCCESS on success', (done) => { + it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_SUCCESS on success', () => { jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse); - testAction( + return testAction( actions.fetchGroupProjects, {}, state, @@ -1894,14 +1883,13 @@ describe('fetchGroupProjects', () => { }, ], [], - done, ); }); - it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_FAILURE on failure', (done) => { + it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_FAILURE on failure', () => { jest.spyOn(gqlClient, 'query').mockRejectedValue(); - testAction( + return testAction( actions.fetchGroupProjects, {}, state, @@ -1915,16 +1903,15 @@ describe('fetchGroupProjects', () => { }, ], [], - done, ); }); }); describe('setSelectedProject', () => { - it('should commit mutation SET_SELECTED_PROJECT', (done) => { + it('should commit mutation SET_SELECTED_PROJECT', () => { const project = mockGroupProjects[0]; - testAction( + return testAction( actions.setSelectedProject, project, {}, @@ -1935,7 +1922,6 @@ describe('setSelectedProject', () => { }, ], [], - done, ); }); }); |