summaryrefslogtreecommitdiff
path: root/spec/frontend/boards/stores/actions_spec.js
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 09:08:42 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 09:08:42 +0000
commitb76ae638462ab0f673e5915986070518dd3f9ad3 (patch)
treebdab0533383b52873be0ec0eb4d3c66598ff8b91 /spec/frontend/boards/stores/actions_spec.js
parent434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff)
downloadgitlab-ce-b76ae638462ab0f673e5915986070518dd3f9ad3.tar.gz
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'spec/frontend/boards/stores/actions_spec.js')
-rw-r--r--spec/frontend/boards/stores/actions_spec.js274
1 files changed, 208 insertions, 66 deletions
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 5e16e389ddc..1272a573d2f 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -1,4 +1,7 @@
import * as Sentry from '@sentry/browser';
+import { cloneDeep } from 'lodash';
+import Vue from 'vue';
+import Vuex from 'vuex';
import {
inactiveId,
ISSUABLE,
@@ -6,6 +9,7 @@ import {
issuableTypes,
BoardType,
listsQuery,
+ DraggableItemTypes,
} from 'ee_else_ce/boards/constants';
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
import testAction from 'helpers/vuex_action_helper';
@@ -21,6 +25,7 @@ import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutati
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
import actions, { gqlClient } from '~/boards/stores/actions';
import * as types from '~/boards/stores/mutation_types';
+import mutations from '~/boards/stores/mutations';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import {
@@ -37,6 +42,7 @@ import {
mockMoveState,
mockMoveData,
mockList,
+ mockMilestones,
} from '../mock_data';
jest.mock('~/flash');
@@ -45,6 +51,8 @@ jest.mock('~/flash');
// subgroups when the movIssue action is called.
const getProjectPath = (path) => path.split('#')[0];
+Vue.use(Vuex);
+
beforeEach(() => {
window.gon = { features: {} };
});
@@ -260,6 +268,87 @@ describe('fetchLists', () => {
);
});
+describe('fetchMilestones', () => {
+ const queryResponse = {
+ data: {
+ project: {
+ milestones: {
+ nodes: mockMilestones,
+ },
+ },
+ },
+ };
+
+ const queryErrors = {
+ data: {
+ project: {
+ errors: ['You cannot view these milestones'],
+ milestones: {},
+ },
+ },
+ };
+
+ function createStore({
+ state = {
+ boardType: 'project',
+ fullPath: 'gitlab-org/gitlab',
+ milestones: [],
+ milestonesLoading: false,
+ },
+ } = {}) {
+ return new Vuex.Store({
+ state,
+ mutations,
+ });
+ }
+
+ it('throws error if state.boardType is not group or project', () => {
+ const store = createStore({
+ state: {
+ boardType: 'invalid',
+ },
+ });
+
+ expect(() => actions.fetchMilestones(store)).toThrow(new Error('Unknown board type'));
+ });
+
+ it('sets milestonesLoading to true', async () => {
+ jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
+
+ const store = createStore();
+
+ actions.fetchMilestones(store);
+
+ expect(store.state.milestonesLoading).toBe(true);
+ });
+
+ describe('success', () => {
+ it('sets state.milestones from query result', async () => {
+ jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
+
+ const store = createStore();
+
+ await actions.fetchMilestones(store);
+
+ expect(store.state.milestonesLoading).toBe(false);
+ expect(store.state.milestones).toBe(mockMilestones);
+ });
+ });
+
+ describe('failure', () => {
+ it('sets state.milestones from query result', async () => {
+ jest.spyOn(gqlClient, 'query').mockResolvedValue(queryErrors);
+
+ const store = createStore();
+
+ await expect(actions.fetchMilestones(store)).rejects.toThrow();
+
+ expect(store.state.milestonesLoading).toBe(false);
+ expect(store.state.error).toBe('Failed to load milestones.');
+ });
+ });
+});
+
describe('createList', () => {
it('should dispatch createIssueList action', () => {
testAction({
@@ -419,75 +508,114 @@ describe('fetchLabels', () => {
});
describe('moveList', () => {
- it('should commit MOVE_LIST mutation and dispatch updateList action', (done) => {
- const initialBoardListsState = {
- 'gid://gitlab/List/1': mockLists[0],
- 'gid://gitlab/List/2': mockLists[1],
- };
+ const backlogListId = 'gid://1';
+ const closedListId = 'gid://5';
- const state = {
- fullPath: 'gitlab-org',
- fullBoardId: 'gid://gitlab/Board/1',
- boardType: 'group',
- disabled: false,
- boardLists: initialBoardListsState,
- };
+ const boardLists1 = {
+ 'gid://3': { listType: '', position: 0 },
+ 'gid://4': { listType: '', position: 1 },
+ 'gid://5': { listType: '', position: 2 },
+ };
- testAction(
- actions.moveList,
- {
- listId: 'gid://gitlab/List/1',
- replacedListId: 'gid://gitlab/List/2',
- newIndex: 1,
- adjustmentValue: 1,
- },
- state,
- [
- {
- type: types.MOVE_LIST,
- payload: { movedList: mockLists[0], listAtNewIndex: mockLists[1] },
- },
- ],
- [
- {
- type: 'updateList',
- payload: {
- listId: 'gid://gitlab/List/1',
- position: 0,
- backupList: initialBoardListsState,
- },
+ const boardLists2 = {
+ [backlogListId]: { listType: ListType.backlog, position: -Infinity },
+ [closedListId]: { listType: ListType.closed, position: Infinity },
+ ...cloneDeep(boardLists1),
+ };
+
+ const movableListsOrder = ['gid://3', 'gid://4', 'gid://5'];
+ const allListsOrder = [backlogListId, ...movableListsOrder, closedListId];
+
+ it(`should not handle the event if the dragged item is not a "${DraggableItemTypes.list}"`, () => {
+ return testAction({
+ action: actions.moveList,
+ payload: {
+ item: { dataset: { listId: '', draggableItemType: DraggableItemTypes.card } },
+ to: {
+ children: [],
},
- ],
- done,
- );
+ },
+ state: {},
+ expectedMutations: [],
+ expectedActions: [],
+ });
});
- it('should not commit MOVE_LIST or dispatch updateList if listId and replacedListId are the same', () => {
- const initialBoardListsState = {
- 'gid://gitlab/List/1': mockLists[0],
- 'gid://gitlab/List/2': mockLists[1],
- };
+ describe.each`
+ draggableFrom | draggableTo | boardLists | boardListsOrder | expectedMovableListsOrder
+ ${0} | ${2} | ${boardLists1} | ${movableListsOrder} | ${['gid://4', 'gid://5', 'gid://3']}
+ ${2} | ${0} | ${boardLists1} | ${movableListsOrder} | ${['gid://5', 'gid://3', 'gid://4']}
+ ${0} | ${1} | ${boardLists1} | ${movableListsOrder} | ${['gid://4', 'gid://3', 'gid://5']}
+ ${1} | ${2} | ${boardLists1} | ${movableListsOrder} | ${['gid://3', 'gid://5', 'gid://4']}
+ ${2} | ${1} | ${boardLists1} | ${movableListsOrder} | ${['gid://3', 'gid://5', 'gid://4']}
+ ${1} | ${3} | ${boardLists2} | ${allListsOrder} | ${['gid://4', 'gid://5', 'gid://3']}
+ ${3} | ${1} | ${boardLists2} | ${allListsOrder} | ${['gid://5', 'gid://3', 'gid://4']}
+ ${1} | ${2} | ${boardLists2} | ${allListsOrder} | ${['gid://4', 'gid://3', 'gid://5']}
+ ${2} | ${3} | ${boardLists2} | ${allListsOrder} | ${['gid://3', 'gid://5', 'gid://4']}
+ ${3} | ${2} | ${boardLists2} | ${allListsOrder} | ${['gid://3', 'gid://5', 'gid://4']}
+ `(
+ 'when moving a list from position $draggableFrom to $draggableTo with lists $boardListsOrder',
+ ({ draggableFrom, draggableTo, boardLists, boardListsOrder, expectedMovableListsOrder }) => {
+ const movedListId = boardListsOrder[draggableFrom];
+ const displacedListId = boardListsOrder[draggableTo];
+ const buildDraggablePayload = () => {
+ return {
+ item: {
+ dataset: {
+ listId: boardListsOrder[draggableFrom],
+ draggableItemType: DraggableItemTypes.list,
+ },
+ },
+ newIndex: draggableTo,
+ to: {
+ children: boardListsOrder.map((listId) => ({ dataset: { listId } })),
+ },
+ };
+ };
- const state = {
- fullPath: 'gitlab-org',
- fullBoardId: 'gid://gitlab/Board/1',
- boardType: 'group',
- disabled: false,
- boardLists: initialBoardListsState,
- };
+ it('should commit MOVE_LIST mutations and dispatch updateList action with correct payloads', () => {
+ return testAction({
+ action: actions.moveList,
+ payload: buildDraggablePayload(),
+ state: { boardLists },
+ expectedMutations: [
+ {
+ type: types.MOVE_LISTS,
+ payload: expectedMovableListsOrder.map((listId, i) => ({ listId, position: i })),
+ },
+ ],
+ expectedActions: [
+ {
+ type: 'updateList',
+ payload: {
+ listId: movedListId,
+ position: movableListsOrder.findIndex((i) => i === displacedListId),
+ },
+ },
+ ],
+ });
+ });
+ },
+ );
- testAction(
- actions.moveList,
- {
- listId: 'gid://gitlab/List/1',
- replacedListId: 'gid://gitlab/List/1',
- newIndex: 1,
- adjustmentValue: 1,
- },
- state,
- [],
- [],
- );
+ describe('when moving from and to the same position', () => {
+ it('should not commit MOVE_LIST and should not dispatch updateList', () => {
+ const listId = 'gid://1000';
+
+ return testAction({
+ action: actions.moveList,
+ payload: {
+ item: { dataset: { listId, draggbaleItemType: DraggableItemTypes.list } },
+ newIndex: 0,
+ to: {
+ children: [{ dataset: { listId } }],
+ },
+ },
+ state: { boardLists: { [listId]: { position: 0 } } },
+ expectedMutations: [],
+ expectedActions: [],
+ });
+ });
});
});
@@ -549,7 +677,7 @@ describe('updateList', () => {
});
});
- it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', (done) => {
+ it('should dispatch handleUpdateListFailure when API returns an error', () => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
updateBoardList: {
@@ -559,17 +687,31 @@ describe('updateList', () => {
},
});
- testAction(
+ return testAction(
actions.updateList,
{ listId: 'gid://gitlab/List/1', position: 1 },
createState(),
- [{ type: types.UPDATE_LIST_FAILURE }],
[],
- done,
+ [{ type: 'handleUpdateListFailure' }],
);
});
});
+describe('handleUpdateListFailure', () => {
+ it('should dispatch fetchLists action and commit SET_ERROR mutation', async () => {
+ await testAction({
+ action: actions.handleUpdateListFailure,
+ expectedMutations: [
+ {
+ type: types.SET_ERROR,
+ payload: 'An error occurred while updating the board list. Please try again.',
+ },
+ ],
+ expectedActions: [{ type: 'fetchLists' }],
+ });
+ });
+});
+
describe('toggleListCollapsed', () => {
it('should commit TOGGLE_LIST_COLLAPSED mutation', async () => {
const payload = { listId: 'gid://gitlab/List/1', collapsed: true };