diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 09:55:51 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 09:55:51 +0000 |
commit | e8d2c2579383897a1dd7f9debd359abe8ae8373d (patch) | |
tree | c42be41678c2586d49a75cabce89322082698334 /spec/frontend/boards | |
parent | fc845b37ec3a90aaa719975f607740c22ba6a113 (diff) | |
download | gitlab-ce-e8d2c2579383897a1dd7f9debd359abe8ae8373d.tar.gz |
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'spec/frontend/boards')
-rw-r--r-- | spec/frontend/boards/board_card_inner_spec.js | 126 | ||||
-rw-r--r-- | spec/frontend/boards/board_list_helper.js | 95 | ||||
-rw-r--r-- | spec/frontend/boards/board_list_spec.js | 96 | ||||
-rw-r--r-- | spec/frontend/boards/boards_util_spec.js | 33 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_column_spec.js | 37 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_content_sidebar_spec.js | 20 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_content_spec.js | 7 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_form_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_settings_sidebar_spec.js | 11 | ||||
-rw-r--r-- | spec/frontend/boards/components/issue_board_filtered_search_spec.js | 44 | ||||
-rw-r--r-- | spec/frontend/boards/mock_data.js | 47 | ||||
-rw-r--r-- | spec/frontend/boards/stores/actions_spec.js | 88 | ||||
-rw-r--r-- | spec/frontend/boards/stores/getters_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/boards/stores/mutations_spec.js | 3 |
14 files changed, 449 insertions, 162 deletions
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js index 15ea5d4eec4..87f9a68f5dd 100644 --- a/spec/frontend/boards/board_card_inner_spec.js +++ b/spec/frontend/boards/board_card_inner_spec.js @@ -1,7 +1,7 @@ -import { GlLabel, GlLoadingIcon } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; +import { GlLabel, GlLoadingIcon, GlTooltip } from '@gitlab/ui'; import { range } from 'lodash'; import Vuex from 'vuex'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue'; import BoardCardInner from '~/boards/components/board_card_inner.vue'; import { issuableTypes } from '~/boards/constants'; @@ -35,8 +35,16 @@ describe('Board card component', () => { let store; const findBoardBlockedIcon = () => wrapper.find(BoardBlockedIcon); - - const createStore = () => { + const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + const findEpicCountablesTotalTooltip = () => wrapper.findComponent(GlTooltip); + const findEpicCountables = () => wrapper.findByTestId('epic-countables'); + const findEpicCountablesBadgeIssues = () => wrapper.findByTestId('epic-countables-counts-issues'); + const findEpicCountablesBadgeWeight = () => wrapper.findByTestId('epic-countables-weight-issues'); + const findEpicBadgeProgress = () => wrapper.findByTestId('epic-progress'); + const findEpicCountablesTotalWeight = () => wrapper.findByTestId('epic-countables-total-weight'); + const findEpicProgressTooltip = () => wrapper.findByTestId('epic-progress-tooltip-content'); + + const createStore = ({ isEpicBoard = false } = {}) => { store = new Vuex.Store({ ...defaultStore, state: { @@ -45,16 +53,14 @@ describe('Board card component', () => { }, getters: { isGroupBoard: () => true, - isEpicBoard: () => false, + isEpicBoard: () => isEpicBoard, isProjectBoard: () => false, }, }); }; const createWrapper = (props = {}) => { - createStore(); - - wrapper = mount(BoardCardInner, { + wrapper = mountExtended(BoardCardInner, { store, propsData: { list, @@ -88,6 +94,7 @@ describe('Board card component', () => { weight: 1, }; + createStore(); createWrapper({ item: issue, list }); }); @@ -414,7 +421,108 @@ describe('Board card component', () => { }, }); - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true); + expect(findLoadingIcon().exists()).toBe(true); + }); + }); + + describe('is an epic board', () => { + const descendantCounts = { + closedEpics: 0, + closedIssues: 0, + openedEpics: 0, + openedIssues: 0, + }; + + const descendantWeightSum = { + closedIssues: 0, + openedIssues: 0, + }; + + beforeEach(() => { + createStore({ isEpicBoard: true }); + }); + + it('should render if the item has issues', () => { + createWrapper({ + item: { + ...issue, + descendantCounts, + descendantWeightSum, + hasIssues: true, + }, + }); + + expect(findEpicCountables().exists()).toBe(true); + }); + + it('should not render if the item does not have issues', () => { + createWrapper({ + item: { + ...issue, + descendantCounts, + descendantWeightSum, + hasIssues: false, + }, + }); + + expect(findEpicCountablesBadgeIssues().exists()).toBe(false); + }); + + it('shows render item countBadge, weights, and progress correctly', () => { + createWrapper({ + item: { + ...issue, + descendantCounts: { + ...descendantCounts, + openedIssues: 1, + }, + descendantWeightSum: { + closedIssues: 10, + openedIssues: 5, + }, + hasIssues: true, + }, + }); + + expect(findEpicCountablesBadgeIssues().text()).toBe('1'); + expect(findEpicCountablesBadgeWeight().text()).toBe('15'); + expect(findEpicBadgeProgress().text()).toBe('67%'); + }); + + it('does not render progress when weight is zero', () => { + createWrapper({ + item: { + ...issue, + descendantCounts: { + ...descendantCounts, + openedIssues: 1, + }, + descendantWeightSum, + hasIssues: true, + }, + }); + + expect(findEpicBadgeProgress().exists()).toBe(false); + }); + + it('renders the tooltip with the correct data', () => { + createWrapper({ + item: { + ...issue, + descendantCounts, + descendantWeightSum: { + closedIssues: 10, + openedIssues: 5, + }, + hasIssues: true, + }, + }); + + const tooltip = findEpicCountablesTotalTooltip(); + expect(tooltip).toBeDefined(); + + expect(findEpicCountablesTotalWeight().text()).toBe('15'); + expect(findEpicProgressTooltip().text()).toBe('10 of 15 weight completed'); }); }); }); diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js index 915b470df8d..c440c110094 100644 --- a/spec/frontend/boards/board_list_helper.js +++ b/spec/frontend/boards/board_list_helper.js @@ -1,34 +1,57 @@ -/* global List */ -/* global ListIssue */ -import MockAdapter from 'axios-mock-adapter'; -import Sortable from 'sortablejs'; -import Vue from 'vue'; -import BoardList from '~/boards/components/board_list_deprecated.vue'; -import '~/boards/models/issue'; -import '~/boards/models/list'; -import store from '~/boards/stores'; -import boardsStore from '~/boards/stores/boards_store'; -import axios from '~/lib/utils/axios_utils'; -import { listObj, boardsMockInterceptor } from './mock_data'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import Vuex from 'vuex'; -window.Sortable = Sortable; +import BoardCard from '~/boards/components/board_card.vue'; +import BoardList from '~/boards/components/board_list.vue'; +import BoardNewIssue from '~/boards/components/board_new_issue.vue'; +import defaultState from '~/boards/stores/state'; +import { mockList, mockIssuesByListId, issues } from './mock_data'; export default function createComponent({ - done, listIssueProps = {}, componentProps = {}, listProps = {}, -}) { - const el = document.createElement('div'); + actions = {}, + getters = {}, + provide = {}, + state = defaultState, + stubs = { + BoardNewIssue, + BoardCard, + }, +} = {}) { + const localVue = createLocalVue(); + localVue.use(Vuex); - document.body.appendChild(el); - const mock = new MockAdapter(axios); - mock.onAny().reply(boardsMockInterceptor); - boardsStore.create(); + const store = new Vuex.Store({ + state: { + boardItemsByListId: mockIssuesByListId, + boardItems: issues, + pageInfoByListId: { + 'gid://gitlab/List/1': { hasNextPage: true }, + 'gid://gitlab/List/2': {}, + }, + listsFlags: { + 'gid://gitlab/List/1': {}, + 'gid://gitlab/List/2': {}, + }, + selectedBoardItems: [], + ...state, + }, + getters: { + isGroupBoard: () => false, + isProjectBoard: () => true, + isEpicBoard: () => false, + ...getters, + }, + actions, + }); - const BoardListComp = Vue.extend(BoardList); - const list = new List({ ...listObj, ...listProps }); - const issue = new ListIssue({ + const list = { + ...mockList, + ...listProps, + }; + const issue = { title: 'Testing', id: 1, iid: 1, @@ -36,31 +59,31 @@ export default function createComponent({ labels: [], assignees: [], ...listIssueProps, - }); - if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesSize')) { - list.issuesSize = 1; + }; + if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesCount')) { + list.issuesCount = 1; } - list.issues.push(issue); - const component = new BoardListComp({ - el, + const component = shallowMount(BoardList, { + localVue, store, propsData: { disabled: false, list, - issues: list.issues, - loading: false, + boardItems: [issue], + canAdminList: true, ...componentProps, }, provide: { groupId: null, rootPath: '/', + weightFeatureAvailable: false, + boardWeight: null, + canAdminList: true, + ...provide, }, - }).$mount(); - - Vue.nextTick(() => { - done(); + stubs, }); - return { component, mock }; + return component; } diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js index 76629c96f22..a3b1810ab80 100644 --- a/spec/frontend/boards/board_list_spec.js +++ b/spec/frontend/boards/board_list_spec.js @@ -1,95 +1,9 @@ -import { createLocalVue, shallowMount } from '@vue/test-utils'; -import Vuex from 'vuex'; import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame'; +import createComponent from 'jest/boards/board_list_helper'; import BoardCard from '~/boards/components/board_card.vue'; -import BoardList from '~/boards/components/board_list.vue'; -import BoardNewIssue from '~/boards/components/board_new_issue.vue'; import eventHub from '~/boards/eventhub'; -import defaultState from '~/boards/stores/state'; -import { mockList, mockIssuesByListId, issues, mockIssues } from './mock_data'; - -const localVue = createLocalVue(); -localVue.use(Vuex); - -const actions = { - fetchItemsForList: jest.fn(), -}; - -const createStore = (state = defaultState) => { - return new Vuex.Store({ - state, - actions, - getters: { - isGroupBoard: () => false, - isProjectBoard: () => true, - isEpicBoard: () => false, - }, - }); -}; - -const createComponent = ({ - listIssueProps = {}, - componentProps = {}, - listProps = {}, - state = {}, -} = {}) => { - const store = createStore({ - boardItemsByListId: mockIssuesByListId, - boardItems: issues, - pageInfoByListId: { - 'gid://gitlab/List/1': { hasNextPage: true }, - 'gid://gitlab/List/2': {}, - }, - listsFlags: { - 'gid://gitlab/List/1': {}, - 'gid://gitlab/List/2': {}, - }, - selectedBoardItems: [], - ...state, - }); - const list = { - ...mockList, - ...listProps, - }; - const issue = { - title: 'Testing', - id: 1, - iid: 1, - confidential: false, - labels: [], - assignees: [], - ...listIssueProps, - }; - if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesCount')) { - list.issuesCount = 1; - } - - const component = shallowMount(BoardList, { - localVue, - propsData: { - disabled: false, - list, - boardItems: [issue], - canAdminList: true, - ...componentProps, - }, - store, - provide: { - groupId: null, - rootPath: '/', - weightFeatureAvailable: false, - boardWeight: null, - canAdminList: true, - }, - stubs: { - BoardCard, - BoardNewIssue, - }, - }); - - return component; -}; +import { mockIssues } from './mock_data'; describe('Board list component', () => { let wrapper; @@ -101,7 +15,6 @@ describe('Board list component', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; }); describe('When Expanded', () => { @@ -176,6 +89,10 @@ describe('Board list component', () => { }); describe('load more issues', () => { + const actions = { + fetchItemsForList: jest.fn(), + }; + beforeEach(() => { wrapper = createComponent({ listProps: { issuesCount: 25 }, @@ -184,6 +101,7 @@ describe('Board list component', () => { it('does not load issues if already loading', () => { wrapper = createComponent({ + actions, state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } }, }); wrapper.vm.listRef.dispatchEvent(new Event('scroll')); diff --git a/spec/frontend/boards/boards_util_spec.js b/spec/frontend/boards/boards_util_spec.js index 289905a1948..d45b6e35a45 100644 --- a/spec/frontend/boards/boards_util_spec.js +++ b/spec/frontend/boards/boards_util_spec.js @@ -1,4 +1,35 @@ -import { filterVariables } from '~/boards/boards_util'; +import { formatIssueInput, filterVariables } from '~/boards/boards_util'; + +describe('formatIssueInput', () => { + it('correctly merges boardConfig into the issue', () => { + const boardConfig = { + labels: [ + { + type: 'GroupLabel', + id: 44, + }, + ], + assigneeId: '55', + milestoneId: 66, + 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', + id: 'gid://gitlab/Issue/11', + labelIds: ['gid://gitlab/GroupLabel/5', 'gid://gitlab/GroupLabel/44'], + assigneeIds: ['gid://gitlab/User/55'], + milestoneId: 'gid://gitlab/Milestone/66', + }); + }); +}); describe('filterVariables', () => { it.each([ diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js index 4e523d636cd..f1964daa8b2 100644 --- a/spec/frontend/boards/components/board_column_spec.js +++ b/spec/frontend/boards/components/board_column_spec.js @@ -15,6 +15,10 @@ describe('Board Column Component', () => { wrapper = null; }); + const initStore = () => { + store = createStore(); + }; + const createComponent = ({ listType = ListType.backlog, collapsed = false } = {}) => { const boardId = '1'; @@ -29,8 +33,6 @@ describe('Board Column Component', () => { listMock.assignee = {}; } - store = createStore(); - wrapper = shallowMount(BoardColumn, { store, propsData: { @@ -47,6 +49,10 @@ describe('Board Column Component', () => { const isCollapsed = () => wrapper.classes('is-collapsed'); describe('Given different list types', () => { + beforeEach(() => { + initStore(); + }); + it('is expandable when List Type is `backlog`', () => { createComponent({ listType: ListType.backlog }); @@ -79,4 +85,31 @@ describe('Board Column Component', () => { expect(wrapper.element.scrollIntoView).toHaveBeenCalled(); }); }); + + describe('on mount', () => { + beforeEach(async () => { + initStore(); + jest.spyOn(store, 'dispatch').mockImplementation(); + }); + + describe('when list is collapsed', () => { + it('does not call fetchItemsForList when', async () => { + createComponent({ collapsed: true }); + + await nextTick(); + + expect(store.dispatch).toHaveBeenCalledTimes(0); + }); + }); + + describe('when the list is not collapsed', () => { + it('calls fetchItemsForList when', async () => { + createComponent({ collapsed: false }); + + await nextTick(); + + expect(store.dispatch).toHaveBeenCalledWith('fetchItemsForList', { listId: 300 }); + }); + }); + }); }); diff --git a/spec/frontend/boards/components/board_content_sidebar_spec.js b/spec/frontend/boards/components/board_content_sidebar_spec.js index 10d739c65f5..8a8250205d0 100644 --- a/spec/frontend/boards/components/board_content_sidebar_spec.js +++ b/spec/frontend/boards/components/board_content_sidebar_spec.js @@ -1,5 +1,6 @@ import { GlDrawer } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { MountingPortal } from 'portal-vue'; import Vuex from 'vuex'; import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue'; import { stubComponent } from 'helpers/stub_component'; @@ -9,7 +10,8 @@ import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.v import { ISSUABLE } from '~/boards/constants'; import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue'; import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue'; -import { mockIssue, mockIssueGroupPath, mockIssueProjectPath } from '../mock_data'; +import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue'; +import { mockActiveIssue, mockIssue, mockIssueGroupPath, mockIssueProjectPath } from '../mock_data'; describe('BoardContentSidebar', () => { let wrapper; @@ -25,7 +27,7 @@ describe('BoardContentSidebar', () => { }, getters: { activeBoardItem: () => { - return { ...mockIssue, epic: null }; + return { ...mockActiveIssue, epic: null }; }, groupPathForActiveIssue: () => mockIssueGroupPath, projectPathForActiveIssue: () => mockIssueProjectPath, @@ -90,6 +92,14 @@ describe('BoardContentSidebar', () => { expect(wrapper.findComponent(GlDrawer).exists()).toBe(true); }); + it('confirms we render MountingPortal', () => { + expect(wrapper.find(MountingPortal).props()).toMatchObject({ + mountTo: '#js-right-sidebar-portal', + append: true, + name: 'board-content-sidebar', + }); + }); + it('does not render GlDrawer when isSidebarOpen is false', () => { createStore({ mockGetters: { isSidebarOpen: () => false } }); createComponent(); @@ -101,6 +111,10 @@ describe('BoardContentSidebar', () => { expect(wrapper.findComponent(GlDrawer).props('open')).toBe(true); }); + it('renders SidebarTodoWidget', () => { + expect(wrapper.findComponent(SidebarTodoWidget).exists()).toBe(true); + }); + it('renders BoardSidebarLabelsSelect', () => { expect(wrapper.findComponent(BoardSidebarLabelsSelect).exists()).toBe(true); }); @@ -138,7 +152,7 @@ describe('BoardContentSidebar', () => { expect(toggleBoardItem).toHaveBeenCalledTimes(1); expect(toggleBoardItem).toHaveBeenCalledWith(expect.any(Object), { - boardItem: { ...mockIssue, epic: null }, + boardItem: { ...mockActiveIssue, epic: null }, sidebarType: ISSUABLE, }); }); diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js index 8c1a7bd3947..5a799b6388e 100644 --- a/spec/frontend/boards/components/board_content_spec.js +++ b/spec/frontend/boards/components/board_content_spec.js @@ -1,5 +1,6 @@ import { GlAlert } from '@gitlab/ui'; -import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import Draggable from 'vuedraggable'; import Vuex from 'vuex'; import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue'; @@ -8,8 +9,7 @@ import BoardColumnDeprecated from '~/boards/components/board_column_deprecated.v import BoardContent from '~/boards/components/board_content.vue'; import { mockLists, mockListsWithModel } from '../mock_data'; -const localVue = createLocalVue(); -localVue.use(Vuex); +Vue.use(Vuex); const actions = { moveList: jest.fn(), @@ -44,7 +44,6 @@ describe('BoardContent', () => { ...state, }); wrapper = shallowMount(BoardContent, { - localVue, propsData: { lists: mockListsWithModel, disabled: false, diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js index 80d740458dc..3966c3e6b87 100644 --- a/spec/frontend/boards/components/board_form_spec.js +++ b/spec/frontend/boards/components/board_form_spec.js @@ -12,8 +12,8 @@ import { createStore } from '~/boards/stores'; import { visitUrl } from '~/lib/utils/url_utility'; jest.mock('~/lib/utils/url_utility', () => ({ + ...jest.requireActual('~/lib/utils/url_utility'), visitUrl: jest.fn().mockName('visitUrlMock'), - stripFinalUrlSegment: jest.requireActual('~/lib/utils/url_utility').stripFinalUrlSegment, })); const currentBoard = { diff --git a/spec/frontend/boards/components/board_settings_sidebar_spec.js b/spec/frontend/boards/components/board_settings_sidebar_spec.js index 464331b6e30..20a08be6c19 100644 --- a/spec/frontend/boards/components/board_settings_sidebar_spec.js +++ b/spec/frontend/boards/components/board_settings_sidebar_spec.js @@ -3,6 +3,7 @@ import { GlDrawer, GlLabel } from '@gitlab/ui'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; +import { MountingPortal } from 'portal-vue'; import Vuex from 'vuex'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue'; @@ -51,6 +52,16 @@ describe('BoardSettingsSidebar', () => { wrapper.destroy(); }); + it('finds a MountingPortal component', () => { + createComponent(); + + expect(wrapper.find(MountingPortal).props()).toMatchObject({ + mountTo: '#js-right-sidebar-portal', + append: true, + name: 'board-settings-sidebar', + }); + }); + describe('when sidebarType is "list"', () => { it('finds a GlDrawer component', () => { createComponent(); diff --git a/spec/frontend/boards/components/issue_board_filtered_search_spec.js b/spec/frontend/boards/components/issue_board_filtered_search_spec.js new file mode 100644 index 00000000000..0e3cf59901e --- /dev/null +++ b/spec/frontend/boards/components/issue_board_filtered_search_spec.js @@ -0,0 +1,44 @@ +import { shallowMount } from '@vue/test-utils'; +import BoardFilteredSearch from '~/boards/components/board_filtered_search.vue'; +import IssueBoardFilteredSpec from '~/boards/components/issue_board_filtered_search.vue'; +import { BoardType } from '~/boards/constants'; +import issueBoardFilters from '~/boards/issue_board_filters'; +import { mockTokens } from '../mock_data'; + +describe('IssueBoardFilter', () => { + let wrapper; + + const createComponent = ({ initialFilterParams = {} } = {}) => { + wrapper = shallowMount(IssueBoardFilteredSpec, { + provide: { initialFilterParams }, + props: { fullPath: '', boardType: '' }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('default', () => { + beforeEach(() => { + createComponent(); + }); + + it('finds BoardFilteredSearch', () => { + expect(wrapper.find(BoardFilteredSearch).exists()).toBe(true); + }); + + it.each([[BoardType.group], [BoardType.project]])( + 'when boardType is %s we pass the correct tokens to BoardFilteredSearch', + (boardType) => { + const { fetchAuthors, fetchLabels } = issueBoardFilters({}, '', boardType); + + const tokens = mockTokens(fetchLabels, fetchAuthors); + + expect(wrapper.find(BoardFilteredSearch).props('tokens').toString()).toBe( + tokens.toString(), + ); + }, + ); + }); +}); diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js index bcaca9522e4..6ac4db8cdaa 100644 --- a/spec/frontend/boards/mock_data.js +++ b/spec/frontend/boards/mock_data.js @@ -5,6 +5,9 @@ import Vue from 'vue'; import '~/boards/models/list'; import { ListType } from '~/boards/constants'; import boardsStore from '~/boards/stores/boards_store'; +import { __ } from '~/locale'; +import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; +import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; export const boardObj = { id: 1, @@ -179,6 +182,7 @@ export const mockIssue = { export const mockActiveIssue = { ...mockIssue, + fullId: 'gid://gitlab/Issue/436', id: 436, iid: '27', subscribed: false, @@ -287,7 +291,7 @@ export const setMockEndpoints = (opts = {}) => { export const mockList = { id: 'gid://gitlab/List/1', - title: 'Backlog', + title: 'Open', position: -Infinity, listType: 'backlog', collapsed: false, @@ -526,3 +530,44 @@ export const mockMoveData = { originalIssue: { foo: 'bar' }, ...mockMoveIssueParams, }; + +export const mockTokens = (fetchLabels, fetchAuthors) => [ + { + icon: 'labels', + title: __('Label'), + type: 'label_name', + operators: [ + { value: '=', description: 'is' }, + { value: '!=', description: 'is not' }, + ], + token: LabelToken, + unique: false, + symbol: '~', + fetchLabels, + }, + { + icon: 'pencil', + title: __('Author'), + type: 'author_username', + operators: [ + { value: '=', description: 'is' }, + { value: '!=', description: 'is not' }, + ], + symbol: '@', + token: AuthorToken, + unique: true, + fetchAuthors, + }, + { + icon: 'user', + title: __('Assignee'), + type: 'assignee_username', + operators: [ + { value: '=', description: 'is' }, + { value: '!=', description: 'is not' }, + ], + token: AuthorToken, + unique: true, + fetchAuthors, + }, +]; diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index b28412f2127..5e16e389ddc 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -492,6 +492,63 @@ describe('moveList', () => { }); describe('updateList', () => { + const listId = 'gid://gitlab/List/1'; + const createState = (boardItemsByListId = {}) => ({ + fullPath: 'gitlab-org', + fullBoardId: 'gid://gitlab/Board/1', + boardType: 'group', + disabled: false, + boardLists: [{ type: 'closed' }], + issuableType: issuableTypes.issue, + boardItemsByListId, + }); + + describe('when state doesnt have list items', () => { + it('calls fetchItemsByList', async () => { + const dispatch = jest.fn(); + + jest.spyOn(gqlClient, 'mutate').mockResolvedValue({ + data: { + updateBoardList: { + errors: [], + list: { + id: listId, + }, + }, + }, + }); + + await actions.updateList({ commit: () => {}, state: createState(), dispatch }, { listId }); + + expect(dispatch.mock.calls).toEqual([['fetchItemsForList', { listId }]]); + }); + }); + + describe('when state has list items', () => { + it('doesnt call fetchItemsByList', async () => { + const commit = jest.fn(); + const dispatch = jest.fn(); + + jest.spyOn(gqlClient, 'mutate').mockResolvedValue({ + data: { + updateBoardList: { + errors: [], + list: { + id: listId, + }, + }, + }, + }); + + await actions.updateList( + { commit, state: createState({ [listId]: [] }), dispatch }, + { listId }, + ); + + expect(dispatch.mock.calls).toEqual([]); + }); + }); + it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', (done) => { jest.spyOn(gqlClient, 'mutate').mockResolvedValue({ data: { @@ -502,19 +559,10 @@ describe('updateList', () => { }, }); - const state = { - fullPath: 'gitlab-org', - fullBoardId: 'gid://gitlab/Board/1', - boardType: 'group', - disabled: false, - boardLists: [{ type: 'closed' }], - issuableType: issuableTypes.issue, - }; - testAction( actions.updateList, { listId: 'gid://gitlab/List/1', position: 1 }, - state, + createState(), [{ type: types.UPDATE_LIST_FAILURE }], [], done, @@ -667,6 +715,19 @@ describe('fetchItemsForList', () => { [listId]: pageInfo, }; + describe('when list id is undefined', () => { + it('does not call the query', async () => { + jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse); + + await actions.fetchItemsForList( + { state, getters: () => {}, commit: () => {} }, + { listId: undefined }, + ); + + expect(gqlClient.query).toHaveBeenCalledTimes(0); + }); + }); + it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_SUCCESS on success', (done) => { jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse); @@ -1111,16 +1172,13 @@ describe('updateIssueOrder', () => { describe('setAssignees', () => { const node = { username: 'name' }; - const projectPath = 'h/h'; - const refPath = `${projectPath}#3`; - const iid = '1'; describe('when succeeds', () => { it('calls the correct mutation with the correct values', (done) => { testAction( actions.setAssignees, - [node], - { activeBoardItem: { iid, referencePath: refPath }, commit: () => {} }, + { assignees: [node], iid: '1' }, + { commit: () => {} }, [ { type: 'UPDATE_BOARD_ITEM_BY_ID', diff --git a/spec/frontend/boards/stores/getters_spec.js b/spec/frontend/boards/stores/getters_spec.js index e7efb21bee5..c0774dd3ae1 100644 --- a/spec/frontend/boards/stores/getters_spec.js +++ b/spec/frontend/boards/stores/getters_spec.js @@ -92,7 +92,7 @@ describe('Boards - Getters', () => { it.each` id | expected ${'1'} | ${'issue'} - ${''} | ${{}} + ${''} | ${{ id: '', iid: '', fullId: '' }} `('returns $expected when $id is passed to state', ({ id, expected }) => { const state = { boardItems: { 1: 'issue' }, activeId: id }; diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js index 5b38f04e77b..37f0969a39a 100644 --- a/spec/frontend/boards/stores/mutations_spec.js +++ b/spec/frontend/boards/stores/mutations_spec.js @@ -35,6 +35,7 @@ describe('Board Store Mutations', () => { describe('SET_INITIAL_BOARD_DATA', () => { it('Should set initial Boards data to state', () => { + const allowSubEpics = true; const boardId = 1; const fullPath = 'gitlab-org'; const boardType = 'group'; @@ -45,6 +46,7 @@ describe('Board Store Mutations', () => { const issuableType = issuableTypes.issue; mutations[types.SET_INITIAL_BOARD_DATA](state, { + allowSubEpics, boardId, fullPath, boardType, @@ -53,6 +55,7 @@ describe('Board Store Mutations', () => { issuableType, }); + expect(state.allowSubEpics).toBe(allowSubEpics); expect(state.boardId).toEqual(boardId); expect(state.fullPath).toEqual(fullPath); expect(state.boardType).toEqual(boardType); |