Коммит 43cc6292 создал по автору Simon Knox's avatar Simon Knox
Просмотр файлов

Merge branch...

Merge branch '378889-refactor-removing-board-list-from-vuex-action-to-apollo-mutation' into 'master'

Apollo boards - Refactor deleting list

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119428



Merged-by: default avatarSimon Knox <simon@gitlab.com>
Approved-by: default avatarDeepika Guliani <dguliani@gitlab.com>
Approved-by: default avatarSimon Knox <simon@gitlab.com>
Reviewed-by: default avatarSimon Knox <simon@gitlab.com>
Reviewed-by: default avatarFlorie Guibert <fguibert@gitlab.com>
Reviewed-by: default avatarDeepika Guliani <dguliani@gitlab.com>
Co-authored-by: default avatarFlorie Guibert <fguibert@gitlab.com>
владельцы 13c2936e 76dc2ba1
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { refreshCurrentPage, queryToObject } from '~/lib/utils/url_utility'; import { refreshCurrentPage, queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import BoardContent from '~/boards/components/board_content.vue'; import BoardContent from '~/boards/components/board_content.vue';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue'; import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
import BoardTopBar from '~/boards/components/board_top_bar.vue'; import BoardTopBar from '~/boards/components/board_top_bar.vue';
import { listsQuery } from 'ee_else_ce/boards/constants';
import { formatBoardLists } from 'ee_else_ce/boards/boards_util';
import activeBoardItemQuery from 'ee_else_ce/boards/graphql/client/active_board_item.query.graphql'; import activeBoardItemQuery from 'ee_else_ce/boards/graphql/client/active_board_item.query.graphql';
export default { export default {
i18n: {
fetchError: s__(
'Boards|An error occurred while fetching the board lists. Please reload the page.',
),
},
components: { components: {
BoardContent, BoardContent,
BoardSettingsSidebar, BoardSettingsSidebar,
BoardTopBar, BoardTopBar,
}, },
inject: ['initialBoardId', 'initialFilterParams', 'isIssueBoard', 'isApolloBoard'], inject: [
'fullPath',
'initialBoardId',
'initialFilterParams',
'isIssueBoard',
'isGroupBoard',
'issuableType',
'boardType',
'isApolloBoard',
],
data() { data() {
return { return {
activeListId: '', activeListId: '',
boardId: this.initialBoardId, boardId: this.initialBoardId,
filterParams: { ...this.initialFilterParams }, filterParams: { ...this.initialFilterParams },
isShowingEpicsSwimlanes: Boolean(queryToObject(window.location.search).group_by), isShowingEpicsSwimlanes: Boolean(queryToObject(window.location.search).group_by),
apolloError: null,
}; };
}, },
apollo: { apollo: {
...@@ -38,10 +56,39 @@ export default { ...@@ -38,10 +56,39 @@ export default {
return !this.isApolloBoard; return !this.isApolloBoard;
}, },
}, },
boardListsApollo: {
query() {
return listsQuery[this.issuableType].query;
},
variables() {
return this.listQueryVariables;
},
skip() {
return !this.isApolloBoard;
},
update(data) {
const { lists } = data[this.boardType].board;
return formatBoardLists(lists);
},
error() {
this.apolloError = this.$options.i18n.fetchError;
},
},
}, },
computed: { computed: {
...mapGetters(['isSidebarOpen']), ...mapGetters(['isSidebarOpen']),
listQueryVariables() {
return {
...(this.isIssueBoard && {
isGroup: this.isGroupBoard,
isProject: !this.isGroupBoard,
}),
fullPath: this.fullPath,
boardId: this.boardId,
filters: this.filterParams,
};
},
isSwimlanesOn() { isSwimlanesOn() {
return (gon?.licensed_features?.swimlanes && this.isShowingEpicsSwimlanes) ?? false; return (gon?.licensed_features?.swimlanes && this.isShowingEpicsSwimlanes) ?? false;
}, },
...@@ -51,6 +98,9 @@ export default { ...@@ -51,6 +98,9 @@ export default {
} }
return this.isSidebarOpen; return this.isSidebarOpen;
}, },
activeList() {
return this.activeListId ? this.boardListsApollo[this.activeListId] : undefined;
},
}, },
created() { created() {
window.addEventListener('popstate', refreshCurrentPage); window.addEventListener('popstate', refreshCurrentPage);
...@@ -85,14 +135,20 @@ export default { ...@@ -85,14 +135,20 @@ export default {
@toggleSwimlanes="isShowingEpicsSwimlanes = $event" @toggleSwimlanes="isShowingEpicsSwimlanes = $event"
/> />
<board-content <board-content
v-if="!isApolloBoard || boardListsApollo"
:board-id="boardId" :board-id="boardId"
:is-swimlanes-on="isSwimlanesOn" :is-swimlanes-on="isSwimlanesOn"
:filter-params="filterParams" :filter-params="filterParams"
:board-lists-apollo="boardListsApollo"
:apollo-error="apolloError"
@setActiveList="setActiveId" @setActiveList="setActiveId"
/> />
<board-settings-sidebar <board-settings-sidebar
v-if="!isApolloBoard || activeList"
:list="activeList"
:list-id="activeListId" :list-id="activeListId"
:board-id="boardId" :board-id="boardId"
:query-variables="listQueryVariables"
@unsetActiveId="setActiveId('')" @unsetActiveId="setActiveId('')"
/> />
</div> </div>
......
...@@ -5,20 +5,13 @@ import { sortBy, throttle } from 'lodash'; ...@@ -5,20 +5,13 @@ import { sortBy, throttle } from 'lodash';
import Draggable from 'vuedraggable'; import Draggable from 'vuedraggable';
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { contentTop } from '~/lib/utils/common_utils'; import { contentTop } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import eventHub from '~/boards/eventhub'; import eventHub from '~/boards/eventhub';
import { formatBoardLists } from 'ee_else_ce/boards/boards_util';
import BoardAddNewColumn from 'ee_else_ce/boards/components/board_add_new_column.vue'; import BoardAddNewColumn from 'ee_else_ce/boards/components/board_add_new_column.vue';
import { defaultSortableOptions } from '~/sortable/constants'; import { defaultSortableOptions } from '~/sortable/constants';
import { DraggableItemTypes, listsQuery } from 'ee_else_ce/boards/constants'; import { DraggableItemTypes } from 'ee_else_ce/boards/constants';
import BoardColumn from './board_column.vue'; import BoardColumn from './board_column.vue';
export default { export default {
i18n: {
fetchError: s__(
'Boards|An error occurred while fetching the board lists. Please reload the page.',
),
},
draggableItemTypes: DraggableItemTypes, draggableItemTypes: DraggableItemTypes,
components: { components: {
BoardAddNewColumn, BoardAddNewColumn,
...@@ -29,17 +22,7 @@ export default { ...@@ -29,17 +22,7 @@ export default {
EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'), EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'),
GlAlert, GlAlert,
}, },
inject: [ inject: ['canAdminList', 'isIssueBoard', 'isEpicBoard', 'disabled', 'isApolloBoard'],
'canAdminList',
'boardType',
'fullPath',
'issuableType',
'isIssueBoard',
'isEpicBoard',
'isGroupBoard',
'disabled',
'isApolloBoard',
],
props: { props: {
boardId: { boardId: {
type: String, type: String,
...@@ -53,56 +36,27 @@ export default { ...@@ -53,56 +36,27 @@ export default {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
boardListsApollo: {
type: Object,
required: false,
default: () => {},
},
apolloError: {
type: String,
required: false,
default: null,
},
}, },
data() { data() {
return { return {
boardHeight: null, boardHeight: null,
boardListsApollo: {},
apolloError: null,
updatedBoardId: this.boardId,
}; };
}, },
apollo: {
boardListsApollo: {
query() {
return listsQuery[this.issuableType].query;
},
variables() {
return this.queryVariables;
},
skip() {
return !this.isApolloBoard;
},
update(data) {
const { lists } = data[this.boardType].board;
return formatBoardLists(lists);
},
result() {
// this allows us to delay fetching lists when we switch a board to fetch the actual board lists
// instead of fetching lists for the "previous" board
this.updatedBoardId = this.boardId;
},
error() {
this.apolloError = this.$options.i18n.fetchError;
},
},
},
computed: { computed: {
...mapState(['boardLists', 'error', 'addColumnForm']), ...mapState(['boardLists', 'error', 'addColumnForm']),
addColumnFormVisible() { addColumnFormVisible() {
return this.addColumnForm?.visible; return this.addColumnForm?.visible;
}, },
queryVariables() {
return {
...(this.isIssueBoard && {
isGroup: this.isGroupBoard,
isProject: !this.isGroupBoard,
}),
fullPath: this.fullPath,
boardId: this.boardId,
filters: this.filterParams,
};
},
boardListsToUse() { boardListsToUse() {
const lists = this.isApolloBoard ? this.boardListsApollo : this.boardLists; const lists = this.isApolloBoard ? this.boardListsApollo : this.boardLists;
return sortBy([...Object.values(lists)], 'position'); return sortBy([...Object.values(lists)], 'position');
......
<script> <script>
import { GlButton, GlDrawer, GlLabel, GlLoadingIcon, GlModal, GlModalDirective } from '@gitlab/ui'; import produce from 'immer';
import { GlButton, GlDrawer, GlLabel, GlModal, GlModalDirective } from '@gitlab/ui';
import { MountingPortal } from 'portal-vue'; import { MountingPortal } from 'portal-vue';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { LIST, ListType, ListTypeTitles, listsQuery } from 'ee_else_ce/boards/constants'; import {
LIST,
ListType,
ListTypeTitles,
listsQuery,
deleteListQueries,
} from 'ee_else_ce/boards/constants';
import { isScopedLabel } from '~/lib/utils/common_utils'; import { isScopedLabel } from '~/lib/utils/common_utils';
import { __ } from '~/locale'; import { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub'; import eventHub from '~/sidebar/event_hub';
...@@ -21,7 +28,6 @@ export default { ...@@ -21,7 +28,6 @@ export default {
GlModal, GlModal,
GlDrawer, GlDrawer,
GlLabel, GlLabel,
GlLoadingIcon,
MountingPortal, MountingPortal,
BoardSettingsSidebarWipLimit: () => BoardSettingsSidebarWipLimit: () =>
import('ee_component/boards/components/board_settings_wip_limit.vue'), import('ee_component/boards/components/board_settings_wip_limit.vue'),
...@@ -35,11 +41,9 @@ export default { ...@@ -35,11 +41,9 @@ export default {
inject: [ inject: [
'boardType', 'boardType',
'canAdminList', 'canAdminList',
'fullPath',
'issuableType', 'issuableType',
'scopedLabelsAvailable', 'scopedLabelsAvailable',
'isIssueBoard', 'isIssueBoard',
'isGroupBoard',
'isApolloBoard', 'isApolloBoard',
], ],
inheritAttrs: false, inheritAttrs: false,
...@@ -52,57 +56,33 @@ export default { ...@@ -52,57 +56,33 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
list: {
type: Object,
required: false,
default: () => null,
},
queryVariables: {
type: Object,
required: true,
},
}, },
data() { data() {
return { return {
ListType, ListType,
list: {},
}; };
}, },
modalId: 'board-settings-sidebar-modal', modalId: 'board-settings-sidebar-modal',
apollo: {
list: {
query() {
return listsQuery[this.issuableType].query;
},
variables() {
return this.queryVariables;
},
update(data) {
const { lists } = data[this.boardType].board;
return lists.nodes[0];
},
skip() {
return !this.isApolloBoard || !this.listId;
},
error() {
this.error = this.$options.i18n.fetchError;
},
},
},
computed: { computed: {
...mapGetters(['isSidebarOpen']), ...mapGetters(['isSidebarOpen']),
...mapState(['activeId', 'sidebarType', 'boardLists']), ...mapState(['activeId', 'sidebarType', 'boardLists']),
isWipLimitsOn() { isWipLimitsOn() {
return this.glFeatures.wipLimits && this.isIssueBoard; return this.glFeatures.wipLimits && this.isIssueBoard;
}, },
queryVariables() {
return {
...(this.isIssueBoard && {
isGroup: this.isGroupBoard,
isProject: !this.isGroupBoard,
}),
fullPath: this.fullPath,
boardId: this.boardId,
filters: this.filterParams,
listId: this.activeListId,
};
},
activeListId() { activeListId() {
return this.isApolloBoard ? this.listId : this.activeId; return this.isApolloBoard ? this.listId : this.activeId;
}, },
activeList() { activeList() {
return this.isApolloBoard ? this.list : this.boardLists[this.activeId] || {}; return (this.isApolloBoard ? this.list : this.boardLists[this.activeId]) || {};
}, },
activeListLabel() { activeListLabel() {
return this.activeList.label; return this.activeList.label;
...@@ -119,9 +99,6 @@ export default { ...@@ -119,9 +99,6 @@ export default {
} }
return this.sidebarType === LIST && this.isSidebarOpen; return this.sidebarType === LIST && this.isSidebarOpen;
}, },
isLoading() {
return this.isApolloBoard && this.$apollo.queries.list.loading;
},
}, },
created() { created() {
eventHub.$on('sidebar.closeAll', this.unsetActiveListId); eventHub.$on('sidebar.closeAll', this.unsetActiveListId);
...@@ -132,14 +109,18 @@ export default { ...@@ -132,14 +109,18 @@ export default {
methods: { methods: {
...mapActions(['unsetActiveId', 'removeList']), ...mapActions(['unsetActiveId', 'removeList']),
handleModalPrimary() { handleModalPrimary() {
this.deleteBoard(); this.deleteBoardList();
}, },
showScopedLabels(label) { showScopedLabels(label) {
return this.scopedLabelsAvailable && isScopedLabel(label); return this.scopedLabelsAvailable && isScopedLabel(label);
}, },
deleteBoard() { async deleteBoardList() {
this.track('click_button', { label: 'remove_list' }); this.track('click_button', { label: 'remove_list' });
this.removeList(this.activeId); if (this.isApolloBoard) {
await this.deleteList(this.activeListId);
} else {
this.removeList(this.activeId);
}
this.unsetActiveListId(); this.unsetActiveListId();
}, },
unsetActiveListId() { unsetActiveListId() {
...@@ -149,6 +130,25 @@ export default { ...@@ -149,6 +130,25 @@ export default {
this.unsetActiveId(); this.unsetActiveId();
} }
}, },
async deleteList(listId) {
await this.$apollo.mutate({
mutation: deleteListQueries[this.issuableType].mutation,
variables: {
listId,
},
update: (store) => {
store.updateQuery(
{ query: listsQuery[this.issuableType].query, variables: this.queryVariables },
(sourceData) =>
produce(sourceData, (draftData) => {
draftData[this.boardType].board.lists.nodes = draftData[
this.boardType
].board.lists.nodes.filter((list) => list.id !== listId);
}),
);
},
});
},
}, },
}; };
</script> </script>
...@@ -166,9 +166,8 @@ export default { ...@@ -166,9 +166,8 @@ export default {
<h2 class="gl-my-0 gl-font-size-h2 gl-line-height-24"> <h2 class="gl-my-0 gl-font-size-h2 gl-line-height-24">
{{ $options.listSettingsText }} {{ $options.listSettingsText }}
</h2> </h2>
<gl-loading-icon v-if="isLoading" />
</template> </template>
<template v-if="!isLoading" #header> <template #header>
<div v-if="canAdminList && activeList.id" class="gl-mt-3"> <div v-if="canAdminList && activeList.id" class="gl-mt-3">
<gl-button <gl-button
v-gl-modal="$options.modalId" v-gl-modal="$options.modalId"
...@@ -179,7 +178,7 @@ export default { ...@@ -179,7 +178,7 @@ export default {
</gl-button> </gl-button>
</div> </div>
</template> </template>
<template v-if="showSidebar && !isLoading"> <template v-if="showSidebar">
<div v-if="boardListType === ListType.label"> <div v-if="boardListType === ListType.label">
<label class="js-list-label gl-display-block">{{ listTypeTitle }}</label> <label class="js-list-label gl-display-block">{{ listTypeTitle }}</label>
<gl-label <gl-label
......
...@@ -144,6 +144,9 @@ export default { ...@@ -144,6 +144,9 @@ export default {
}, },
methods: { methods: {
...mapActions(['setError', 'fetchBoard', 'unsetActiveId']), ...mapActions(['setError', 'fetchBoard', 'unsetActiveId']),
fullBoardId(boardId) {
return fullBoardId(boardId);
},
showPage(page) { showPage(page) {
this.currentPage = page; this.currentPage = page;
}, },
...@@ -254,7 +257,8 @@ export default { ...@@ -254,7 +257,8 @@ export default {
if (isMetaKey(e)) { if (isMetaKey(e)) {
window.open(`${this.boardBaseUrl}/${boardId}`, '_blank'); window.open(`${this.boardBaseUrl}/${boardId}`, '_blank');
} else if (this.isApolloBoard) { } else if (this.isApolloBoard) {
this.$emit('switchBoard', fullBoardId(boardId)); // Epic board ID is supported in EE version of this file
this.$emit('switchBoard', this.fullBoardId(boardId));
updateHistory({ url: `${this.boardBaseUrl}/${boardId}` }); updateHistory({ url: `${this.boardBaseUrl}/${boardId}` });
} else { } else {
this.unsetActiveId(); this.unsetActiveId();
......
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { issueBoardListsQueryResponse } from 'jest/boards/mock_data';
import createMockApollo from 'helpers/mock_apollo_helper';
import BoardApp from '~/boards/components/board_app.vue';
import epicBoardListsQuery from 'ee_component/boards/graphql/epic_board_lists.query.graphql';
import activeBoardItemQuery from 'ee_else_ce/boards/graphql/client/active_board_item.query.graphql';
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
import { rawIssue, epicBoardListsQueryResponse } from '../mock_data';
describe('BoardApp', () => {
const boardListQueryHandler = jest.fn().mockResolvedValue(issueBoardListsQueryResponse);
const epicBoardListQueryHandler = jest.fn().mockResolvedValue(epicBoardListsQueryResponse);
const mockApollo = createMockApollo([
[boardListsQuery, boardListQueryHandler],
[epicBoardListsQuery, epicBoardListQueryHandler],
]);
Vue.use(VueApollo);
const createComponent = ({ issue = rawIssue, provide = {} } = {}) => {
mockApollo.clients.defaultClient.cache.writeQuery({
query: activeBoardItemQuery,
data: {
activeBoardItem: issue,
},
});
shallowMount(BoardApp, {
apolloProvider: mockApollo,
provide: {
fullPath: 'gitlab-org',
initialBoardId: 'gid://gitlab/Board/1',
initialFilterParams: {},
issuableType: 'issue',
boardType: 'group',
isIssueBoard: true,
isGroupBoard: true,
isApolloBoard: true,
...provide,
},
});
};
it.each`
issuableType | isIssueBoard | isEpicBoard | queryHandler | notCalledHandler
${'epic'} | ${false} | ${true} | ${epicBoardListQueryHandler} | ${boardListQueryHandler}
${'issue'} | ${true} | ${false} | ${boardListQueryHandler} | ${epicBoardListQueryHandler}
`(
'fetches $issuableType lists',
({ issuableType, isIssueBoard, isEpicBoard, queryHandler, notCalledHandler }) => {
createComponent({
provide: { isApolloBoard: true, issuableType, isEpicBoard, isIssueBoard },
});
expect(queryHandler).toHaveBeenCalled();
expect(notCalledHandler).not.toHaveBeenCalled();
},
);
});
import { GlLabel } from '@gitlab/ui'; import { GlLabel } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo';
import Vuex from 'vuex'; import Vuex from 'vuex';
import createMockApollo from 'helpers/mock_apollo_helper';
import BoardSettingsListTypes from 'ee_component/boards/components/board_settings_list_types.vue'; import BoardSettingsListTypes from 'ee_component/boards/components/board_settings_list_types.vue';
import BoardSettingsWipLimit from 'ee_component/boards/components/board_settings_wip_limit.vue'; import BoardSettingsWipLimit from 'ee_component/boards/components/board_settings_wip_limit.vue';
import epicBoardListsQuery from 'ee_component/boards/graphql/epic_board_lists.query.graphql'; import { mockLabelList, mockMilestoneList } from 'jest/boards/mock_data';
import {
mockLabelList,
mockMilestoneList,
issueBoardListsQueryResponse,
} from 'jest/boards/mock_data';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue'; import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
import { LIST } from '~/boards/constants'; import { LIST } from '~/boards/constants';
import getters from '~/boards/stores/getters'; import getters from '~/boards/stores/getters';
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
import { epicBoardListsQueryResponse } from '../mock_data';
Vue.use(VueApollo);
Vue.use(Vuex); Vue.use(Vuex);
describe('ee/BoardSettingsSidebar', () => { describe('ee/BoardSettingsSidebar', () => {
let wrapper; let wrapper;
let mockApollo;
let storeActions; let storeActions;
const boardListQueryHandler = jest.fn().mockResolvedValue(issueBoardListsQueryResponse);
const epicBoardListQueryHandler = jest.fn().mockResolvedValue(epicBoardListsQueryResponse);
const createComponent = ({ const createComponent = ({
actions = {}, actions = {},
isWipLimitsOn = false, isWipLimitsOn = false,
...@@ -46,13 +32,7 @@ describe('ee/BoardSettingsSidebar', () => { ...@@ -46,13 +32,7 @@ describe('ee/BoardSettingsSidebar', () => {
actions: storeActions, actions: storeActions,
}); });
mockApollo = createMockApollo([
[boardListsQuery, boardListQueryHandler],
[epicBoardListsQuery, epicBoardListQueryHandler],
]);
wrapper = shallowMount(BoardSettingsSidebar, { wrapper = shallowMount(BoardSettingsSidebar, {
apolloProvider: mockApollo,
store, store,
provide: { provide: {
glFeatures: { glFeatures: {
...@@ -62,15 +42,15 @@ describe('ee/BoardSettingsSidebar', () => { ...@@ -62,15 +42,15 @@ describe('ee/BoardSettingsSidebar', () => {
scopedLabelsAvailable: true, scopedLabelsAvailable: true,
isIssueBoard: true, isIssueBoard: true,
boardType: 'group', boardType: 'group',
fullPath: 'gitlab-org',
issuableType: 'issue', issuableType: 'issue',
isGroupBoard: true,
isApolloBoard: false, isApolloBoard: false,
...provide, ...provide,
}, },
propsData: { propsData: {
listId: 'gid://gitlab/List/1', listId: list.id,
boardId: 'gid://gitlab/Board/1', boardId: 'gid://gitlab/Board/1',
list,
queryVariables: {},
}, },
stubs: { stubs: {
'board-settings-sidebar-wip-limit': BoardSettingsWipLimit, 'board-settings-sidebar-wip-limit': BoardSettingsWipLimit,
...@@ -98,22 +78,4 @@ describe('ee/BoardSettingsSidebar', () => { ...@@ -98,22 +78,4 @@ describe('ee/BoardSettingsSidebar', () => {
expect(wrapper.findComponent(GlLabel).props('scoped')).toBe(true); expect(wrapper.findComponent(GlLabel).props('scoped')).toBe(true);
}); });
describe('Apollo boards', () => {
it.each`
issuableType | isIssueBoard | isEpicBoard | queryHandler | notCalledHandler
${'epic'} | ${false} | ${true} | ${epicBoardListQueryHandler} | ${boardListQueryHandler}
${'issue'} | ${true} | ${false} | ${boardListQueryHandler} | ${epicBoardListQueryHandler}
`(
'fetches $issuableType list info',
({ issuableType, isIssueBoard, isEpicBoard, queryHandler, notCalledHandler }) => {
createComponent({
provide: { isApolloBoard: true, issuableType, isEpicBoard, isIssueBoard },
});
expect(queryHandler).toHaveBeenCalled();
expect(notCalledHandler).not.toHaveBeenCalled();
},
);
});
}); });
...@@ -6,12 +6,14 @@ import Vuex from 'vuex'; ...@@ -6,12 +6,14 @@ import Vuex from 'vuex';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import BoardApp from '~/boards/components/board_app.vue'; import BoardApp from '~/boards/components/board_app.vue';
import activeBoardItemQuery from 'ee_else_ce/boards/graphql/client/active_board_item.query.graphql'; import activeBoardItemQuery from 'ee_else_ce/boards/graphql/client/active_board_item.query.graphql';
import { rawIssue } from '../mock_data'; import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
import { rawIssue, boardListsQueryResponse } from '../mock_data';
describe('BoardApp', () => { describe('BoardApp', () => {
let wrapper; let wrapper;
let store; let store;
const mockApollo = createMockApollo(); const boardListQueryHandler = jest.fn().mockResolvedValue(boardListsQueryResponse);
const mockApollo = createMockApollo([[boardListsQuery, boardListQueryHandler]]);
Vue.use(Vuex); Vue.use(Vuex);
Vue.use(VueApollo); Vue.use(VueApollo);
...@@ -41,9 +43,13 @@ describe('BoardApp', () => { ...@@ -41,9 +43,13 @@ describe('BoardApp', () => {
apolloProvider: mockApollo, apolloProvider: mockApollo,
store, store,
provide: { provide: {
fullPath: 'gitlab-org',
initialBoardId: 'gid://gitlab/Board/1', initialBoardId: 'gid://gitlab/Board/1',
initialFilterParams: {}, initialFilterParams: {},
issuableType: 'issue',
boardType: 'group',
isIssueBoard: true, isIssueBoard: true,
isGroupBoard: true,
isApolloBoard, isApolloBoard,
}, },
}); });
...@@ -73,6 +79,10 @@ describe('BoardApp', () => { ...@@ -73,6 +79,10 @@ describe('BoardApp', () => {
await nextTick(); await nextTick();
}); });
it('fetches lists', () => {
expect(boardListQueryHandler).toHaveBeenCalled();
});
it('should have is-compact class when a card is selected', () => { it('should have is-compact class when a card is selected', () => {
expect(wrapper.classes()).toContain('is-compact'); expect(wrapper.classes()).toContain('is-compact');
}); });
......
import { GlAlert } from '@gitlab/ui'; import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue'; import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import Draggable from 'vuedraggable'; import Draggable from 'vuedraggable';
import Vuex from 'vuex'; import Vuex from 'vuex';
import eventHub from '~/boards/eventhub'; import eventHub from '~/boards/eventhub';
import { stubComponent } from 'helpers/stub_component'; import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import createMockApollo from 'helpers/mock_apollo_helper';
import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue'; import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
import getters from 'ee_else_ce/boards/stores/getters'; import getters from 'ee_else_ce/boards/stores/getters';
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
import BoardColumn from '~/boards/components/board_column.vue'; import BoardColumn from '~/boards/components/board_column.vue';
import BoardContent from '~/boards/components/board_content.vue'; import BoardContent from '~/boards/components/board_content.vue';
import BoardContentSidebar from '~/boards/components/board_content_sidebar.vue'; import BoardContentSidebar from '~/boards/components/board_content_sidebar.vue';
import { mockLists, boardListsQueryResponse } from '../mock_data'; import { mockLists, mockListsById } from '../mock_data';
Vue.use(VueApollo);
Vue.use(Vuex); Vue.use(Vuex);
const actions = { const actions = {
...@@ -26,7 +22,6 @@ const actions = { ...@@ -26,7 +22,6 @@ const actions = {
describe('BoardContent', () => { describe('BoardContent', () => {
let wrapper; let wrapper;
let fakeApollo;
const defaultState = { const defaultState = {
isShowingEpicsSwimlanes: false, isShowingEpicsSwimlanes: false,
...@@ -51,26 +46,21 @@ describe('BoardContent', () => { ...@@ -51,26 +46,21 @@ describe('BoardContent', () => {
issuableType = 'issue', issuableType = 'issue',
isIssueBoard = true, isIssueBoard = true,
isEpicBoard = false, isEpicBoard = false,
boardListQueryHandler = jest.fn().mockResolvedValue(boardListsQueryResponse),
} = {}) => { } = {}) => {
fakeApollo = createMockApollo([[boardListsQuery, boardListQueryHandler]]);
const store = createStore({ const store = createStore({
...defaultState, ...defaultState,
...state, ...state,
}); });
wrapper = shallowMount(BoardContent, { wrapper = shallowMount(BoardContent, {
apolloProvider: fakeApollo,
propsData: { propsData: {
boardId: 'gid://gitlab/Board/1', boardId: 'gid://gitlab/Board/1',
filterParams: {}, filterParams: {},
isSwimlanesOn: false, isSwimlanesOn: false,
boardListsApollo: mockListsById,
...props, ...props,
}, },
provide: { provide: {
canAdminList, canAdminList,
boardType: 'group',
fullPath: 'gitlab-org/gitlab',
issuableType, issuableType,
isIssueBoard, isIssueBoard,
isEpicBoard, isEpicBoard,
...@@ -110,10 +100,6 @@ describe('BoardContent', () => { ...@@ -110,10 +100,6 @@ describe('BoardContent', () => {
}; };
}); });
afterEach(() => {
fakeApollo = null;
});
describe('default', () => { describe('default', () => {
beforeEach(() => { beforeEach(() => {
createComponent(); createComponent();
......
...@@ -10,12 +10,12 @@ import { stubComponent } from 'helpers/stub_component'; ...@@ -10,12 +10,12 @@ import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue'; import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
import { inactiveId, LIST } from '~/boards/constants'; import { inactiveId, LIST } from '~/boards/constants';
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
import actions from '~/boards/stores/actions'; import actions from '~/boards/stores/actions';
import getters from '~/boards/stores/getters'; import getters from '~/boards/stores/getters';
import mutations from '~/boards/stores/mutations'; import mutations from '~/boards/stores/mutations';
import sidebarEventHub from '~/sidebar/event_hub'; import sidebarEventHub from '~/sidebar/event_hub';
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql'; import { mockLabelList, destroyBoardListMutationResponse } from '../mock_data';
import { mockLabelList, issueBoardListsQueryResponse } from '../mock_data';
Vue.use(VueApollo); Vue.use(VueApollo);
Vue.use(Vuex); Vue.use(Vuex);
...@@ -28,7 +28,9 @@ describe('BoardSettingsSidebar', () => { ...@@ -28,7 +28,9 @@ describe('BoardSettingsSidebar', () => {
const listId = mockLabelList.id; const listId = mockLabelList.id;
const modalID = 'board-settings-sidebar-modal'; const modalID = 'board-settings-sidebar-modal';
const boardListQueryHandler = jest.fn().mockResolvedValue(issueBoardListsQueryResponse); const destroyBoardListMutationHandlerSuccess = jest
.fn()
.mockResolvedValue(destroyBoardListMutationResponse);
const createComponent = ({ const createComponent = ({
canAdminList = false, canAdminList = false,
...@@ -46,25 +48,28 @@ describe('BoardSettingsSidebar', () => { ...@@ -46,25 +48,28 @@ describe('BoardSettingsSidebar', () => {
mutations, mutations,
actions, actions,
}); });
mockApollo = createMockApollo([[boardListsQuery, boardListQueryHandler]]);
mockApollo = createMockApollo([
[destroyBoardListMutation, destroyBoardListMutationHandlerSuccess],
]);
wrapper = extendedWrapper( wrapper = extendedWrapper(
shallowMount(BoardSettingsSidebar, { shallowMount(BoardSettingsSidebar, {
apolloProvider: mockApollo,
store, store,
apolloProvider: mockApollo,
provide: { provide: {
canAdminList, canAdminList,
scopedLabelsAvailable: false, scopedLabelsAvailable: false,
isIssueBoard: true, isIssueBoard: true,
boardType: 'group', boardType: 'group',
fullPath: 'gitlab-org',
issuableType: 'issue', issuableType: 'issue',
isGroupBoard: true,
isApolloBoard, isApolloBoard,
}, },
propsData: { propsData: {
listId: 'gid://gitlab/List/1', listId: list.id || '',
boardId: 'gid://gitlab/Board/1', boardId: 'gid://gitlab/Board/1',
list,
queryVariables: {},
}, },
directives: { directives: {
GlModal: createMockDirective('gl-modal'), GlModal: createMockDirective('gl-modal'),
...@@ -76,6 +81,9 @@ describe('BoardSettingsSidebar', () => { ...@@ -76,6 +81,9 @@ describe('BoardSettingsSidebar', () => {
}, },
}), }),
); );
// Necessary for cache update
mockApollo.clients.defaultClient.cache.updateQuery = jest.fn();
}; };
const findLabel = () => wrapper.findComponent(GlLabel); const findLabel = () => wrapper.findComponent(GlLabel);
const findDrawer = () => wrapper.findComponent(GlDrawer); const findDrawer = () => wrapper.findComponent(GlDrawer);
...@@ -185,6 +193,21 @@ describe('BoardSettingsSidebar', () => { ...@@ -185,6 +193,21 @@ describe('BoardSettingsSidebar', () => {
expect(findRemoveButton().exists()).toBe(true); expect(findRemoveButton().exists()).toBe(true);
}); });
it('removes the list', () => {
createComponent({
canAdminList: true,
activeId: listId,
list: mockLabelList,
isApolloBoard: true,
});
findRemoveButton().vm.$emit('click');
wrapper.findComponent(GlModal).vm.$emit('primary');
expect(destroyBoardListMutationHandlerSuccess).toHaveBeenCalled();
});
it('has the correct ID on the button', () => { it('has the correct ID on the button', () => {
createComponent({ canAdminList: true, activeId: listId, list: mockLabelList }); createComponent({ canAdminList: true, activeId: listId, list: mockLabelList });
const binding = getBinding(findRemoveButton().element, 'gl-modal'); const binding = getBinding(findRemoveButton().element, 'gl-modal');
...@@ -196,12 +219,4 @@ describe('BoardSettingsSidebar', () => { ...@@ -196,12 +219,4 @@ describe('BoardSettingsSidebar', () => {
expect(findModal().props('modalId')).toBe(modalID); expect(findModal().props('modalId')).toBe(modalID);
}); });
}); });
describe('Apollo boards', () => {
it('fetches list', () => {
createComponent({ isApolloBoard: true });
expect(boardListQueryHandler).toHaveBeenCalled();
});
});
}); });
...@@ -997,4 +997,13 @@ export const updateBoardListResponse = { ...@@ -997,4 +997,13 @@ export const updateBoardListResponse = {
}, },
}; };
export const destroyBoardListMutationResponse = {
data: {
destroyBoardList: {
errors: [],
__typename: 'DestroyBoardListPayload',
},
},
};
export const DEFAULT_COLOR = '#1068bf'; export const DEFAULT_COLOR = '#1068bf';
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать