debian-mirror-gitlab/spec/frontend/boards/stores/actions_spec.js

1813 lines
45 KiB
JavaScript
Raw Normal View History

2021-04-29 21:17:54 +05:30
import * as Sentry from '@sentry/browser';
2021-06-08 01:23:25 +05:30
import {
inactiveId,
ISSUABLE,
ListType,
issuableTypes,
BoardType,
listsQuery,
} from 'ee_else_ce/boards/constants';
2021-04-29 21:17:54 +05:30
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
2020-10-24 23:57:45 +05:30
import testAction from 'helpers/vuex_action_helper';
2021-03-11 19:13:27 +05:30
import {
formatListIssues,
formatBoardLists,
formatIssueInput,
2021-04-29 21:17:54 +05:30
formatIssue,
getMoveData,
2021-09-04 01:27:46 +05:30
updateListPosition,
2021-03-11 19:13:27 +05:30
} from '~/boards/boards_util';
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
import actions, { gqlClient } from '~/boards/stores/actions';
import * as types from '~/boards/stores/mutation_types';
2021-04-29 21:17:54 +05:30
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
2020-11-24 15:15:51 +05:30
import {
mockLists,
2021-01-29 00:20:46 +05:30
mockListsById,
2020-11-24 15:15:51 +05:30
mockIssue,
2021-02-22 17:27:13 +05:30
mockIssue2,
2020-11-24 15:15:51 +05:30
rawIssue,
2021-01-03 14:25:43 +05:30
mockIssues,
labels,
2021-01-29 00:20:46 +05:30
mockActiveIssue,
2021-03-08 18:12:59 +05:30
mockGroupProjects,
2021-04-29 21:17:54 +05:30
mockMoveIssueParams,
mockMoveState,
mockMoveData,
2021-09-04 01:27:46 +05:30
mockList,
2020-11-24 15:15:51 +05:30
} from '../mock_data';
2021-02-22 17:27:13 +05:30
jest.mock('~/flash');
2019-09-04 21:01:54 +05:30
2020-11-24 15:15:51 +05:30
// We need this helper to make sure projectPath is including
// subgroups when the movIssue action is called.
2021-03-08 18:12:59 +05:30
const getProjectPath = (path) => path.split('#')[0];
2020-11-24 15:15:51 +05:30
2021-02-22 17:27:13 +05:30
beforeEach(() => {
window.gon = { features: {} };
});
2020-10-24 23:57:45 +05:30
describe('setInitialBoardData', () => {
it('sets data object', () => {
const mockData = {
2020-06-23 00:09:42 +05:30
foo: 'bar',
bar: 'baz',
};
return testAction(
2020-10-24 23:57:45 +05:30
actions.setInitialBoardData,
mockData,
2020-06-23 00:09:42 +05:30
{},
2020-10-24 23:57:45 +05:30
[{ type: types.SET_INITIAL_BOARD_DATA, payload: mockData }],
[],
);
});
});
2020-11-24 15:15:51 +05:30
describe('setFilters', () => {
2021-06-08 01:23:25 +05:30
it.each([
[
'with correct filters as payload',
{
2021-09-04 01:27:46 +05:30
filters: { labelName: 'label', foobar: 'not-a-filter', search: 'quick brown fox' },
filterVariables: { labelName: 'label', search: 'quick brown fox', not: {} },
2021-06-08 01:23:25 +05:30
},
],
[
2021-09-04 01:27:46 +05:30
"and use 'assigneeWildcardId' as filter variable for 'assigneId' param",
2021-06-08 01:23:25 +05:30
{
filters: { assigneeId: 'None' },
2021-09-04 01:27:46 +05:30
filterVariables: { assigneeWildcardId: 'NONE', not: {} },
2021-06-08 01:23:25 +05:30
},
],
2021-09-04 01:27:46 +05:30
])('should commit mutation SET_FILTERS %s', (_, { filters, filterVariables }) => {
2020-11-24 15:15:51 +05:30
const state = {
filters: {},
2021-09-04 01:27:46 +05:30
issuableType: issuableTypes.issue,
2020-11-24 15:15:51 +05:30
};
testAction(
actions.setFilters,
filters,
state,
2021-09-04 01:27:46 +05:30
[{ type: types.SET_FILTERS, payload: filterVariables }],
2020-11-24 15:15:51 +05:30
[],
);
});
});
2021-02-22 17:27:13 +05:30
describe('performSearch', () => {
2021-03-08 18:12:59 +05:30
it('should dispatch setFilters action', (done) => {
2021-02-22 17:27:13 +05:30
testAction(actions.performSearch, {}, {}, [], [{ type: 'setFilters', payload: {} }], done);
});
2021-03-08 18:12:59 +05:30
it('should dispatch setFilters, fetchLists and resetIssues action when graphqlBoardLists FF is on', (done) => {
2021-02-22 17:27:13 +05:30
window.gon = { features: { graphqlBoardLists: true } };
testAction(
actions.performSearch,
{},
{},
[],
[{ type: 'setFilters', payload: {} }, { type: 'fetchLists' }, { type: 'resetIssues' }],
done,
);
});
});
2020-10-24 23:57:45 +05:30
describe('setActiveId', () => {
2021-03-08 18:12:59 +05:30
it('should commit mutation SET_ACTIVE_ID', (done) => {
2020-10-24 23:57:45 +05:30
const state = {
activeId: inactiveId,
};
testAction(
actions.setActiveId,
2020-11-24 15:15:51 +05:30
{ id: 1, sidebarType: 'something' },
2020-10-24 23:57:45 +05:30
state,
2020-11-24 15:15:51 +05:30
[{ type: types.SET_ACTIVE_ID, payload: { id: 1, sidebarType: 'something' } }],
2020-06-23 00:09:42 +05:30
[],
2020-10-24 23:57:45 +05:30
done,
2020-06-23 00:09:42 +05:30
);
});
2019-09-04 21:01:54 +05:30
});
2021-01-03 14:25:43 +05:30
describe('fetchLists', () => {
2021-06-08 01:23:25 +05:30
let state = {
2021-03-08 18:12:59 +05:30
fullPath: 'gitlab-org',
2021-06-08 01:23:25 +05:30
fullBoardId: 'gid://gitlab/Board/1',
2021-01-03 14:25:43 +05:30
filterParams: {},
boardType: 'group',
2021-06-08 01:23:25 +05:30
issuableType: 'issue',
2021-01-03 14:25:43 +05:30
};
let queryResponse = {
data: {
group: {
board: {
hideBacklogList: true,
lists: {
nodes: [mockLists[1]],
},
},
},
},
};
const formattedLists = formatBoardLists(queryResponse.data.group.board.lists);
2021-03-08 18:12:59 +05:30
it('should commit mutations RECEIVE_BOARD_LISTS_SUCCESS on success', (done) => {
2021-01-03 14:25:43 +05:30
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
2021-06-08 01:23:25 +05:30
actions.fetchLists,
2021-01-03 14:25:43 +05:30
{},
state,
[
{
type: types.RECEIVE_BOARD_LISTS_SUCCESS,
payload: formattedLists,
},
],
2021-02-22 17:27:13 +05:30
[],
2021-01-03 14:25:43 +05:30
done,
);
});
2021-04-17 20:07:23 +05:30
it('should commit mutations RECEIVE_BOARD_LISTS_FAILURE on failure', (done) => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(Promise.reject());
testAction(
2021-06-08 01:23:25 +05:30
actions.fetchLists,
2021-04-17 20:07:23 +05:30
{},
state,
[
{
type: types.RECEIVE_BOARD_LISTS_FAILURE,
},
],
[],
done,
);
});
2021-03-08 18:12:59 +05:30
it('dispatch createList action when backlog list does not exist and is not hidden', (done) => {
2021-01-03 14:25:43 +05:30
queryResponse = {
data: {
group: {
board: {
hideBacklogList: false,
lists: {
nodes: [mockLists[1]],
},
},
},
},
};
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
2021-06-08 01:23:25 +05:30
actions.fetchLists,
2021-01-03 14:25:43 +05:30
{},
state,
[
{
type: types.RECEIVE_BOARD_LISTS_SUCCESS,
payload: formattedLists,
},
],
2021-02-22 17:27:13 +05:30
[{ type: 'createList', payload: { backlog: true } }],
2021-01-03 14:25:43 +05:30
done,
);
});
2021-06-08 01:23:25 +05:30
it.each`
issuableType | boardType | fullBoardId | isGroup | isProject
${issuableTypes.issue} | ${BoardType.group} | ${'gid://gitlab/Board/1'} | ${true} | ${false}
${issuableTypes.issue} | ${BoardType.project} | ${'gid://gitlab/Board/1'} | ${false} | ${true}
`(
'calls $issuableType query with correct variables',
async ({ issuableType, boardType, fullBoardId, isGroup, isProject }) => {
const commit = jest.fn();
const dispatch = jest.fn();
state = {
fullPath: 'gitlab-org',
fullBoardId,
filterParams: {},
boardType,
issuableType,
};
const variables = {
query: listsQuery[issuableType].query,
variables: {
fullPath: 'gitlab-org',
boardId: fullBoardId,
filters: {},
isGroup,
isProject,
},
};
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
await actions.fetchLists({ commit, state, dispatch });
expect(gqlClient.query).toHaveBeenCalledWith(variables);
},
);
2021-01-03 14:25:43 +05:30
});
2019-09-04 21:01:54 +05:30
describe('createList', () => {
2021-04-17 20:07:23 +05:30
it('should dispatch createIssueList action', () => {
testAction({
action: actions.createList,
payload: { backlog: true },
expectedActions: [{ type: 'createIssueList', payload: { backlog: true } }],
});
});
});
describe('createIssueList', () => {
2021-03-11 19:13:27 +05:30
let commit;
let dispatch;
let getters;
let state;
beforeEach(() => {
state = {
fullPath: 'gitlab-org',
2021-06-08 01:23:25 +05:30
fullBoardId: 'gid://gitlab/Board/1',
2021-03-11 19:13:27 +05:30
boardType: 'group',
disabled: false,
boardLists: [{ type: 'closed' }],
};
commit = jest.fn();
dispatch = jest.fn();
getters = {
getListByLabelId: jest.fn(),
};
});
it('should dispatch addList action when creating backlog list', async () => {
2020-11-24 15:15:51 +05:30
const backlogList = {
id: 'gid://gitlab/List/1',
listType: 'backlog',
title: 'Open',
position: 0,
};
jest.spyOn(gqlClient, 'mutate').mockReturnValue(
Promise.resolve({
data: {
boardListCreate: {
list: backlogList,
errors: [],
},
},
}),
);
2021-04-17 20:07:23 +05:30
await actions.createIssueList({ getters, state, commit, dispatch }, { backlog: true });
2021-03-11 19:13:27 +05:30
expect(dispatch).toHaveBeenCalledWith('addList', backlogList);
});
it('dispatches highlightList after addList has succeeded', async () => {
const list = {
id: 'gid://gitlab/List/1',
listType: 'label',
title: 'Open',
labelId: '4',
2020-11-24 15:15:51 +05:30
};
2021-03-11 19:13:27 +05:30
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
boardListCreate: {
list,
errors: [],
},
},
});
2021-04-17 20:07:23 +05:30
await actions.createIssueList({ getters, state, commit, dispatch }, { labelId: '4' });
2021-03-11 19:13:27 +05:30
expect(dispatch).toHaveBeenCalledWith('addList', list);
expect(dispatch).toHaveBeenCalledWith('highlightList', list.id);
2020-11-24 15:15:51 +05:30
});
2021-03-11 19:13:27 +05:30
it('should commit CREATE_LIST_FAILURE mutation when API returns an error', async () => {
2020-11-24 15:15:51 +05:30
jest.spyOn(gqlClient, 'mutate').mockReturnValue(
Promise.resolve({
data: {
boardListCreate: {
list: {},
2021-04-17 20:07:23 +05:30
errors: ['foo'],
2020-11-24 15:15:51 +05:30
},
},
}),
);
2021-04-17 20:07:23 +05:30
await actions.createIssueList({ getters, state, commit, dispatch }, { backlog: true });
2021-03-11 19:13:27 +05:30
2021-04-17 20:07:23 +05:30
expect(commit).toHaveBeenCalledWith(types.CREATE_LIST_FAILURE, 'foo');
2021-03-11 19:13:27 +05:30
});
it('highlights list and does not re-query if it already exists', async () => {
const existingList = {
id: 'gid://gitlab/List/1',
listType: 'label',
title: 'Some label',
position: 1,
2020-11-24 15:15:51 +05:30
};
2021-03-11 19:13:27 +05:30
getters = {
getListByLabelId: jest.fn().mockReturnValue(existingList),
};
2021-04-17 20:07:23 +05:30
await actions.createIssueList({ getters, state, commit, dispatch }, { backlog: true });
2021-03-11 19:13:27 +05:30
expect(dispatch).toHaveBeenCalledWith('highlightList', existingList.id);
expect(dispatch).toHaveBeenCalledTimes(1);
expect(commit).not.toHaveBeenCalled();
});
});
2021-09-04 01:27:46 +05:30
describe('addList', () => {
const getters = {
getListByTitle: jest.fn().mockReturnValue(mockList),
};
it('should commit RECEIVE_ADD_LIST_SUCCESS mutation and dispatch fetchItemsForList action', () => {
testAction({
action: actions.addList,
payload: mockLists[1],
state: { ...getters },
expectedMutations: [
{ type: types.RECEIVE_ADD_LIST_SUCCESS, payload: updateListPosition(mockLists[1]) },
],
expectedActions: [{ type: 'fetchItemsForList', payload: { listId: mockList.id } }],
});
});
});
2021-03-11 19:13:27 +05:30
describe('fetchLabels', () => {
it('should commit mutation RECEIVE_LABELS_SUCCESS on success', async () => {
const queryResponse = {
data: {
group: {
labels: {
nodes: labels,
},
},
},
};
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
2021-04-17 20:07:23 +05:30
const commit = jest.fn();
const getters = {
shouldUseGraphQL: () => true,
};
const state = { boardType: 'group' };
await actions.fetchLabels({ getters, state, commit });
expect(commit).toHaveBeenCalledWith(types.RECEIVE_LABELS_SUCCESS, labels);
2020-11-24 15:15:51 +05:30
});
});
describe('moveList', () => {
2021-03-08 18:12:59 +05:30
it('should commit MOVE_LIST mutation and dispatch updateList action', (done) => {
2021-01-03 14:25:43 +05:30
const initialBoardListsState = {
2021-02-22 17:27:13 +05:30
'gid://gitlab/List/1': mockLists[0],
'gid://gitlab/List/2': mockLists[1],
2021-01-03 14:25:43 +05:30
};
2020-11-24 15:15:51 +05:30
const state = {
2021-03-08 18:12:59 +05:30
fullPath: 'gitlab-org',
2021-06-08 01:23:25 +05:30
fullBoardId: 'gid://gitlab/Board/1',
2020-11-24 15:15:51 +05:30
boardType: 'group',
disabled: false,
2021-01-03 14:25:43 +05:30
boardLists: initialBoardListsState,
2020-11-24 15:15:51 +05:30
};
testAction(
actions.moveList,
2021-01-03 14:25:43 +05:30
{
listId: 'gid://gitlab/List/1',
replacedListId: 'gid://gitlab/List/2',
newIndex: 1,
adjustmentValue: 1,
},
2020-11-24 15:15:51 +05:30
state,
[
{
type: types.MOVE_LIST,
2021-02-22 17:27:13 +05:30
payload: { movedList: mockLists[0], listAtNewIndex: mockLists[1] },
2020-11-24 15:15:51 +05:30
},
],
[
{
type: 'updateList',
2021-01-03 14:25:43 +05:30
payload: {
listId: 'gid://gitlab/List/1',
position: 0,
backupList: initialBoardListsState,
},
2020-11-24 15:15:51 +05:30
},
],
done,
);
});
2021-02-22 17:27:13 +05:30
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],
};
const state = {
2021-03-08 18:12:59 +05:30
fullPath: 'gitlab-org',
2021-06-08 01:23:25 +05:30
fullBoardId: 'gid://gitlab/Board/1',
2021-02-22 17:27:13 +05:30
boardType: 'group',
disabled: false,
boardLists: initialBoardListsState,
};
testAction(
actions.moveList,
{
listId: 'gid://gitlab/List/1',
replacedListId: 'gid://gitlab/List/1',
newIndex: 1,
adjustmentValue: 1,
},
state,
[],
[],
);
});
2019-09-04 21:01:54 +05:30
});
describe('updateList', () => {
2021-09-30 23:02:18 +05:30
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([]);
});
});
2021-03-08 18:12:59 +05:30
it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', (done) => {
2020-11-24 15:15:51 +05:30
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
updateBoardList: {
list: {},
errors: [{ foo: 'bar' }],
},
},
});
testAction(
actions.updateList,
{ listId: 'gid://gitlab/List/1', position: 1 },
2021-09-30 23:02:18 +05:30
createState(),
2020-11-24 15:15:51 +05:30
[{ type: types.UPDATE_LIST_FAILURE }],
[],
done,
);
});
2019-09-04 21:01:54 +05:30
});
2021-04-17 20:07:23 +05:30
describe('toggleListCollapsed', () => {
it('should commit TOGGLE_LIST_COLLAPSED mutation', async () => {
const payload = { listId: 'gid://gitlab/List/1', collapsed: true };
await testAction({
action: actions.toggleListCollapsed,
payload,
expectedMutations: [
{
type: types.TOGGLE_LIST_COLLAPSED,
payload,
},
],
});
});
});
2021-01-29 00:20:46 +05:30
describe('removeList', () => {
let state;
2021-09-04 01:27:46 +05:30
let getters;
const list = mockLists[1];
2021-01-29 00:20:46 +05:30
const listId = list.id;
const mutationVariables = {
mutation: destroyBoardListMutation,
variables: {
listId,
},
};
beforeEach(() => {
state = {
boardLists: mockListsById,
2021-06-08 01:23:25 +05:30
issuableType: issuableTypes.issue,
2021-01-29 00:20:46 +05:30
};
2021-09-04 01:27:46 +05:30
getters = {
getListByTitle: jest.fn().mockReturnValue(mockList),
};
2021-01-29 00:20:46 +05:30
});
afterEach(() => {
state = null;
});
it('optimistically deletes the list', () => {
const commit = jest.fn();
2021-09-04 01:27:46 +05:30
actions.removeList({ commit, state, getters, dispatch: () => {} }, listId);
2021-01-29 00:20:46 +05:30
expect(commit.mock.calls).toEqual([[types.REMOVE_LIST, listId]]);
});
it('keeps the updated list if remove succeeds', async () => {
const commit = jest.fn();
2021-09-04 01:27:46 +05:30
const dispatch = jest.fn();
2021-01-29 00:20:46 +05:30
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
destroyBoardList: {
errors: [],
},
},
});
2021-09-04 01:27:46 +05:30
await actions.removeList({ commit, state, getters, dispatch }, listId);
2021-01-29 00:20:46 +05:30
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
expect(commit.mock.calls).toEqual([[types.REMOVE_LIST, listId]]);
2021-09-04 01:27:46 +05:30
expect(dispatch.mock.calls).toEqual([['fetchItemsForList', { listId: mockList.id }]]);
2021-01-29 00:20:46 +05:30
});
it('restores the list if update fails', async () => {
const commit = jest.fn();
jest.spyOn(gqlClient, 'mutate').mockResolvedValue(Promise.reject());
2021-09-04 01:27:46 +05:30
await actions.removeList({ commit, state, getters, dispatch: () => {} }, listId);
2021-01-29 00:20:46 +05:30
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
expect(commit.mock.calls).toEqual([
[types.REMOVE_LIST, listId],
[types.REMOVE_LIST_FAILURE, mockListsById],
]);
});
it('restores the list if update response has errors', async () => {
const commit = jest.fn();
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
destroyBoardList: {
errors: ['update failed, ID invalid'],
},
},
});
2021-09-04 01:27:46 +05:30
await actions.removeList({ commit, state, getters, dispatch: () => {} }, listId);
2021-01-29 00:20:46 +05:30
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
expect(commit.mock.calls).toEqual([
[types.REMOVE_LIST, listId],
[types.REMOVE_LIST_FAILURE, mockListsById],
]);
});
2019-09-04 21:01:54 +05:30
});
2021-04-17 20:07:23 +05:30
describe('fetchItemsForList', () => {
2021-01-03 14:25:43 +05:30
const listId = mockLists[0].id;
const state = {
2021-03-08 18:12:59 +05:30
fullPath: 'gitlab-org',
2021-06-08 01:23:25 +05:30
fullBoardId: 'gid://gitlab/Board/1',
2021-01-03 14:25:43 +05:30
filterParams: {},
boardType: 'group',
};
2021-03-08 18:12:59 +05:30
const mockIssuesNodes = mockIssues.map((issue) => ({ node: issue }));
2021-01-03 14:25:43 +05:30
const pageInfo = {
endCursor: '',
hasNextPage: false,
};
const queryResponse = {
data: {
group: {
board: {
lists: {
nodes: [
{
id: listId,
issues: {
edges: mockIssuesNodes,
pageInfo,
},
},
],
},
},
},
},
};
const formattedIssues = formatListIssues(queryResponse.data.group.board.lists);
const listPageInfo = {
[listId]: pageInfo,
};
2021-09-30 23:02:18 +05:30
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);
});
});
2021-04-17 20:07:23 +05:30
it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_SUCCESS on success', (done) => {
2021-01-03 14:25:43 +05:30
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
2021-04-17 20:07:23 +05:30
actions.fetchItemsForList,
2021-01-03 14:25:43 +05:30
{ listId },
state,
[
2021-09-04 01:27:46 +05:30
{
type: types.RESET_ITEMS_FOR_LIST,
payload: listId,
},
2021-01-03 14:25:43 +05:30
{
2021-04-17 20:07:23 +05:30
type: types.REQUEST_ITEMS_FOR_LIST,
2021-01-03 14:25:43 +05:30
payload: { listId, fetchNext: false },
},
{
2021-04-17 20:07:23 +05:30
type: types.RECEIVE_ITEMS_FOR_LIST_SUCCESS,
payload: { listItems: formattedIssues, listPageInfo, listId },
2021-01-03 14:25:43 +05:30
},
],
[],
done,
);
});
2021-04-17 20:07:23 +05:30
it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_FAILURE on failure', (done) => {
2021-01-03 14:25:43 +05:30
jest.spyOn(gqlClient, 'query').mockResolvedValue(Promise.reject());
testAction(
2021-04-17 20:07:23 +05:30
actions.fetchItemsForList,
2021-01-03 14:25:43 +05:30
{ listId },
state,
[
2021-09-04 01:27:46 +05:30
{
type: types.RESET_ITEMS_FOR_LIST,
payload: listId,
},
2021-01-03 14:25:43 +05:30
{
2021-04-17 20:07:23 +05:30
type: types.REQUEST_ITEMS_FOR_LIST,
2021-01-03 14:25:43 +05:30
payload: { listId, fetchNext: false },
},
2021-04-17 20:07:23 +05:30
{ type: types.RECEIVE_ITEMS_FOR_LIST_FAILURE, payload: listId },
2021-01-03 14:25:43 +05:30
],
[],
done,
);
});
});
describe('resetIssues', () => {
it('commits RESET_ISSUES mutation', () => {
return testAction(actions.resetIssues, {}, {}, [{ type: types.RESET_ISSUES }], []);
});
});
2021-04-17 20:07:23 +05:30
describe('moveItem', () => {
2021-04-29 21:17:54 +05:30
it('should dispatch moveIssue action with payload', () => {
const payload = { mock: 'payload' };
2021-04-17 20:07:23 +05:30
testAction({
action: actions.moveItem,
2021-04-29 21:17:54 +05:30
payload,
expectedActions: [{ type: 'moveIssue', payload }],
2021-04-17 20:07:23 +05:30
});
});
});
2019-09-04 21:01:54 +05:30
describe('moveIssue', () => {
2021-04-29 21:17:54 +05:30
it('should dispatch a correct set of actions', () => {
testAction({
action: actions.moveIssue,
payload: mockMoveIssueParams,
state: mockMoveState,
expectedActions: [
{ type: 'moveIssueCard', payload: mockMoveData },
{ type: 'updateMovedIssue', payload: mockMoveData },
{ type: 'updateIssueOrder', payload: { moveData: mockMoveData } },
],
});
});
});
2020-11-24 15:15:51 +05:30
2021-04-29 21:17:54 +05:30
describe('moveIssueCard and undoMoveIssueCard', () => {
describe('card should move without clonning', () => {
let state;
let params;
let moveMutations;
let undoMutations;
describe('when re-ordering card', () => {
beforeEach(
({
itemId = 123,
fromListId = 'gid://gitlab/List/1',
toListId = 'gid://gitlab/List/1',
originalIssue = { foo: 'bar' },
originalIndex = 0,
moveBeforeId = undefined,
moveAfterId = undefined,
} = {}) => {
state = {
boardLists: {
[toListId]: { listType: ListType.backlog },
[fromListId]: { listType: ListType.backlog },
},
boardItems: { [itemId]: originalIssue },
boardItemsByListId: { [fromListId]: [123] },
};
params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
moveMutations = [
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
},
];
undoMutations = [
{ type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: { itemId, listId: fromListId, atIndex: originalIndex },
},
];
2020-11-24 15:15:51 +05:30
},
2021-04-29 21:17:54 +05:30
);
it('moveIssueCard commits a correct set of actions', () => {
testAction({
action: actions.moveIssueCard,
state,
payload: getMoveData(state, params),
expectedMutations: moveMutations,
});
});
it('undoMoveIssueCard commits a correct set of actions', () => {
testAction({
action: actions.undoMoveIssueCard,
state,
payload: getMoveData(state, params),
expectedMutations: undoMutations,
});
});
2020-11-24 15:15:51 +05:30
});
2021-04-29 21:17:54 +05:30
describe.each([
2020-11-24 15:15:51 +05:30
[
2021-04-29 21:17:54 +05:30
'issue moves out of backlog',
2020-11-24 15:15:51 +05:30
{
2021-04-29 21:17:54 +05:30
fromListType: ListType.backlog,
toListType: ListType.label,
2020-11-24 15:15:51 +05:30
},
2021-04-29 21:17:54 +05:30
],
[
'issue card moves to closed',
2020-11-24 15:15:51 +05:30
{
2021-04-29 21:17:54 +05:30
fromListType: ListType.label,
toListType: ListType.closed,
2020-11-24 15:15:51 +05:30
},
],
2021-04-29 21:17:54 +05:30
[
'issue card moves to non-closed, non-backlog list of the same type',
{
fromListType: ListType.label,
toListType: ListType.label,
},
],
])('when %s', (_, { toListType, fromListType }) => {
beforeEach(
({
itemId = 123,
fromListId = 'gid://gitlab/List/1',
toListId = 'gid://gitlab/List/2',
originalIssue = { foo: 'bar' },
originalIndex = 0,
moveBeforeId = undefined,
moveAfterId = undefined,
} = {}) => {
state = {
boardLists: {
[fromListId]: { listType: fromListType },
[toListId]: { listType: toListType },
},
boardItems: { [itemId]: originalIssue },
boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
};
params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
moveMutations = [
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
},
];
undoMutations = [
{ type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: { itemId, listId: fromListId, atIndex: originalIndex },
},
];
},
);
it('moveIssueCard commits a correct set of actions', () => {
testAction({
action: actions.moveIssueCard,
state,
payload: getMoveData(state, params),
expectedMutations: moveMutations,
});
});
it('undoMoveIssueCard commits a correct set of actions', () => {
testAction({
action: actions.undoMoveIssueCard,
state,
payload: getMoveData(state, params),
expectedMutations: undoMutations,
});
});
});
});
describe('card should clone on move', () => {
let state;
let params;
let moveMutations;
let undoMutations;
describe.each([
[
'issue card moves to non-closed, non-backlog list of a different type',
{
fromListType: ListType.label,
toListType: ListType.assignee,
},
],
])('when %s', (_, { toListType, fromListType }) => {
beforeEach(
({
itemId = 123,
fromListId = 'gid://gitlab/List/1',
toListId = 'gid://gitlab/List/2',
originalIssue = { foo: 'bar' },
originalIndex = 0,
moveBeforeId = undefined,
moveAfterId = undefined,
} = {}) => {
state = {
boardLists: {
[fromListId]: { listType: fromListType },
[toListId]: { listType: toListType },
},
boardItems: { [itemId]: originalIssue },
boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
};
params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
moveMutations = [
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
},
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: { itemId, listId: fromListId, atIndex: originalIndex },
},
];
undoMutations = [
{ type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: { itemId, listId: fromListId, atIndex: originalIndex },
},
];
},
);
it('moveIssueCard commits a correct set of actions', () => {
testAction({
action: actions.moveIssueCard,
state,
payload: getMoveData(state, params),
expectedMutations: moveMutations,
});
});
it('undoMoveIssueCard commits a correct set of actions', () => {
testAction({
action: actions.undoMoveIssueCard,
state,
payload: getMoveData(state, params),
expectedMutations: undoMutations,
});
});
});
2020-11-24 15:15:51 +05:30
});
2021-04-29 21:17:54 +05:30
});
describe('updateMovedIssueCard', () => {
const label1 = {
id: 'label1',
};
it.each([
[
'issue without a label is moved to a label list',
{
state: {
boardLists: {
from: {},
to: {
listType: ListType.label,
label: label1,
},
},
boardItems: {
1: {
labels: [],
},
},
},
moveData: {
itemId: 1,
fromListId: 'from',
toListId: 'to',
},
updatedIssue: { labels: [label1] },
},
],
])(
'should commit UPDATE_BOARD_ITEM with a correctly updated issue data when %s',
(_, { state, moveData, updatedIssue }) => {
testAction({
action: actions.updateMovedIssue,
payload: moveData,
state,
expectedMutations: [{ type: types.UPDATE_BOARD_ITEM, payload: updatedIssue }],
});
},
);
});
describe('updateIssueOrder', () => {
const issues = {
436: mockIssue,
437: mockIssue2,
};
const state = {
boardItems: issues,
2021-06-08 01:23:25 +05:30
fullBoardId: 'gid://gitlab/Board/1',
2021-04-29 21:17:54 +05:30
};
const moveData = {
itemId: 436,
fromListId: 'gid://gitlab/List/1',
toListId: 'gid://gitlab/List/2',
};
2020-11-24 15:15:51 +05:30
it('calls mutate with the correct variables', () => {
const mutationVariables = {
mutation: issueMoveListMutation,
variables: {
projectPath: getProjectPath(mockIssue.referencePath),
2021-06-08 01:23:25 +05:30
boardId: state.fullBoardId,
2020-11-24 15:15:51 +05:30
iid: mockIssue.iid,
fromListId: 1,
toListId: 2,
moveBeforeId: undefined,
moveAfterId: undefined,
},
};
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
issueMoveList: {
issue: rawIssue,
errors: [],
},
},
});
2021-04-29 21:17:54 +05:30
actions.updateIssueOrder({ state, commit: () => {}, dispatch: () => {} }, { moveData });
2020-11-24 15:15:51 +05:30
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
});
2021-04-29 21:17:54 +05:30
it('should commit MUTATE_ISSUE_SUCCESS mutation when successful', () => {
2020-11-24 15:15:51 +05:30
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
issueMoveList: {
2021-04-29 21:17:54 +05:30
issue: rawIssue,
errors: [],
2020-11-24 15:15:51 +05:30
},
},
});
testAction(
2021-04-29 21:17:54 +05:30
actions.updateIssueOrder,
{ moveData },
2020-11-24 15:15:51 +05:30
state,
[
{
2021-04-29 21:17:54 +05:30
type: types.MUTATE_ISSUE_SUCCESS,
payload: { issue: rawIssue },
2020-11-24 15:15:51 +05:30
},
2021-04-29 21:17:54 +05:30
],
[],
);
});
it('should commit SET_ERROR and dispatch undoMoveIssueCard', () => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
issueMoveList: {
issue: {},
errors: [{ foo: 'bar' }],
},
},
});
testAction(
actions.updateIssueOrder,
{ moveData },
state,
[
2020-11-24 15:15:51 +05:30
{
2021-04-29 21:17:54 +05:30
type: types.SET_ERROR,
payload: 'An error occurred while moving the issue. Please try again.',
2020-11-24 15:15:51 +05:30
},
],
2021-04-29 21:17:54 +05:30
[{ type: 'undoMoveIssueCard', payload: moveData }],
2020-11-24 15:15:51 +05:30
);
});
2019-09-04 21:01:54 +05:30
});
2021-01-29 00:20:46 +05:30
describe('setAssignees', () => {
const node = { username: 'name' };
2021-02-22 17:27:13 +05:30
describe('when succeeds', () => {
2021-03-08 18:12:59 +05:30
it('calls the correct mutation with the correct values', (done) => {
2021-02-22 17:27:13 +05:30
testAction(
actions.setAssignees,
2021-09-30 23:02:18 +05:30
{ assignees: [node], iid: '1' },
{ commit: () => {} },
2021-02-22 17:27:13 +05:30
[
{
2021-04-29 21:17:54 +05:30
type: 'UPDATE_BOARD_ITEM_BY_ID',
payload: { prop: 'assignees', itemId: undefined, value: [node] },
2021-02-22 17:27:13 +05:30
},
],
[],
done,
);
2021-01-29 00:20:46 +05:30
});
});
2019-09-04 21:01:54 +05:30
});
2021-04-29 21:17:54 +05:30
describe('addListItem', () => {
it('should commit ADD_BOARD_ITEM_TO_LIST and UPDATE_BOARD_ITEM mutations', () => {
const payload = {
list: mockLists[0],
item: mockIssue,
position: 0,
};
testAction(actions.addListItem, payload, {}, [
{
type: types.ADD_BOARD_ITEM_TO_LIST,
payload: {
listId: mockLists[0].id,
itemId: mockIssue.id,
atIndex: 0,
2021-09-04 01:27:46 +05:30
inProgress: false,
2021-04-29 21:17:54 +05:30
},
},
{ type: types.UPDATE_BOARD_ITEM, payload: mockIssue },
]);
});
});
describe('removeListItem', () => {
it('should commit REMOVE_BOARD_ITEM_FROM_LIST and REMOVE_BOARD_ITEM mutations', () => {
const payload = {
listId: mockLists[0].id,
itemId: mockIssue.id,
};
testAction(actions.removeListItem, payload, {}, [
{ type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload },
{ type: types.REMOVE_BOARD_ITEM, payload: mockIssue.id },
]);
});
});
describe('addListNewIssue', () => {
2021-01-29 00:20:46 +05:30
const state = {
boardType: 'group',
2021-03-08 18:12:59 +05:30
fullPath: 'gitlab-org/gitlab',
boardConfig: {
labelIds: [],
assigneeId: null,
milestoneId: -1,
},
};
const stateWithBoardConfig = {
boardConfig: {
labels: [
{
id: 5,
title: 'Test',
color: '#ff0000',
description: 'testing;',
textColor: 'white',
},
],
assigneeId: 2,
milestoneId: 3,
2021-01-29 00:20:46 +05:30
},
};
2021-04-29 21:17:54 +05:30
const fakeList = { id: 'gid://gitlab/List/123' };
2021-01-29 00:20:46 +05:30
2021-03-08 18:12:59 +05:30
it('should add board scope to the issue being created', async () => {
2021-01-29 00:20:46 +05:30
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
createIssue: {
2021-03-08 18:12:59 +05:30
issue: mockIssue,
errors: [],
},
},
});
2021-04-29 21:17:54 +05:30
await actions.addListNewIssue(
{ dispatch: jest.fn(), commit: jest.fn(), state: stateWithBoardConfig },
{ issueInput: mockIssue, list: fakeList },
);
2021-03-08 18:12:59 +05:30
expect(gqlClient.mutate).toHaveBeenCalledWith({
mutation: issueCreateMutation,
variables: {
input: formatIssueInput(mockIssue, stateWithBoardConfig.boardConfig),
},
});
});
it('should add board scope by merging attributes to the issue being created', async () => {
const issue = {
...mockIssue,
assigneeIds: ['gid://gitlab/User/1'],
labelIds: ['gid://gitlab/GroupLabel/4'],
};
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
createIssue: {
issue,
errors: [],
},
},
});
const payload = formatIssueInput(issue, stateWithBoardConfig.boardConfig);
2021-04-29 21:17:54 +05:30
await actions.addListNewIssue(
{ dispatch: jest.fn(), commit: jest.fn(), state: stateWithBoardConfig },
{ issueInput: issue, list: fakeList },
);
2021-03-08 18:12:59 +05:30
expect(gqlClient.mutate).toHaveBeenCalledWith({
mutation: issueCreateMutation,
variables: {
input: formatIssueInput(issue, stateWithBoardConfig.boardConfig),
},
});
expect(payload.labelIds).toEqual(['gid://gitlab/GroupLabel/4', 'gid://gitlab/GroupLabel/5']);
expect(payload.assigneeIds).toEqual(['gid://gitlab/User/1', 'gid://gitlab/User/2']);
});
2021-04-29 21:17:54 +05:30
describe('when issue creation mutation request succeeds', () => {
it('dispatches a correct set of mutations', () => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
createIssue: {
issue: mockIssue,
errors: [],
},
2021-01-29 00:20:46 +05:30
},
2021-04-29 21:17:54 +05:30
});
testAction({
action: actions.addListNewIssue,
payload: {
issueInput: mockIssue,
list: fakeList,
placeholderId: 'tmp',
},
state,
expectedActions: [
{
type: 'addListItem',
payload: {
list: fakeList,
2021-09-04 01:27:46 +05:30
item: formatIssue({ ...mockIssue, id: 'tmp', isLoading: true }),
2021-04-29 21:17:54 +05:30
position: 0,
2021-09-04 01:27:46 +05:30
inProgress: true,
2021-04-29 21:17:54 +05:30
},
},
{ type: 'removeListItem', payload: { listId: fakeList.id, itemId: 'tmp' } },
{
type: 'addListItem',
payload: {
list: fakeList,
item: formatIssue({ ...mockIssue, id: getIdFromGraphQLId(mockIssue.id) }),
position: 0,
},
},
],
});
2021-01-29 00:20:46 +05:30
});
2020-11-24 15:15:51 +05:30
});
2021-04-29 21:17:54 +05:30
describe('when issue creation mutation request fails', () => {
it('dispatches a correct set of mutations', () => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
createIssue: {
issue: mockIssue,
errors: [{ foo: 'bar' }],
},
},
});
testAction({
action: actions.addListNewIssue,
payload: {
issueInput: mockIssue,
list: fakeList,
placeholderId: 'tmp',
},
state,
expectedActions: [
{
type: 'addListItem',
payload: {
list: fakeList,
2021-09-04 01:27:46 +05:30
item: formatIssue({ ...mockIssue, id: 'tmp', isLoading: true }),
2021-04-29 21:17:54 +05:30
position: 0,
2021-09-04 01:27:46 +05:30
inProgress: true,
2021-04-29 21:17:54 +05:30
},
},
{ type: 'removeListItem', payload: { listId: fakeList.id, itemId: 'tmp' } },
],
expectedMutations: [
{
type: types.SET_ERROR,
payload: 'An error occurred while creating the issue. Please try again.',
},
],
});
});
2020-11-24 15:15:51 +05:30
});
});
2021-01-03 14:25:43 +05:30
describe('setActiveIssueLabels', () => {
2021-04-17 20:07:23 +05:30
const state = { boardItems: { [mockIssue.id]: mockIssue } };
2021-04-29 21:17:54 +05:30
const getters = { activeBoardItem: mockIssue };
2021-03-08 18:12:59 +05:30
const testLabelIds = labels.map((label) => label.id);
2021-01-03 14:25:43 +05:30
const input = {
addLabelIds: testLabelIds,
removeLabelIds: [],
projectPath: 'h/b',
};
2021-03-08 18:12:59 +05:30
it('should assign labels on success', (done) => {
2021-01-03 14:25:43 +05:30
jest
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { updateIssue: { issue: { labels: { nodes: labels } } } } });
const payload = {
2021-04-29 21:17:54 +05:30
itemId: getters.activeBoardItem.id,
2021-01-03 14:25:43 +05:30
prop: 'labels',
value: labels,
};
testAction(
actions.setActiveIssueLabels,
input,
{ ...state, ...getters },
[
{
2021-04-29 21:17:54 +05:30
type: types.UPDATE_BOARD_ITEM_BY_ID,
2021-01-03 14:25:43 +05:30
payload,
},
],
[],
done,
);
});
it('throws error if fails', async () => {
jest
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
await expect(actions.setActiveIssueLabels({ getters }, input)).rejects.toThrow(Error);
});
});
2021-04-29 21:17:54 +05:30
describe('setActiveItemSubscribed', () => {
const state = {
boardItems: {
[mockActiveIssue.id]: mockActiveIssue,
},
fullPath: 'gitlab-org',
2021-06-08 01:23:25 +05:30
issuableType: issuableTypes.issue,
2021-04-29 21:17:54 +05:30
};
const getters = { activeBoardItem: mockActiveIssue, isEpicBoard: false };
2021-01-29 00:20:46 +05:30
const subscribedState = true;
const input = {
subscribedState,
projectPath: 'gitlab-org/gitlab-test',
};
2021-03-08 18:12:59 +05:30
it('should commit subscribed status', (done) => {
2021-01-29 00:20:46 +05:30
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
2021-04-29 21:17:54 +05:30
updateIssuableSubscription: {
2021-01-29 00:20:46 +05:30
issue: {
subscribed: subscribedState,
},
errors: [],
},
},
});
const payload = {
2021-04-29 21:17:54 +05:30
itemId: getters.activeBoardItem.id,
2021-01-29 00:20:46 +05:30
prop: 'subscribed',
value: subscribedState,
};
testAction(
2021-04-29 21:17:54 +05:30
actions.setActiveItemSubscribed,
2021-01-29 00:20:46 +05:30
input,
{ ...state, ...getters },
[
{
2021-04-29 21:17:54 +05:30
type: types.UPDATE_BOARD_ITEM_BY_ID,
2021-01-29 00:20:46 +05:30
payload,
},
],
[],
done,
);
});
it('throws error if fails', async () => {
jest
.spyOn(gqlClient, 'mutate')
2021-04-29 21:17:54 +05:30
.mockResolvedValue({ data: { updateIssuableSubscription: { errors: ['failed mutation'] } } });
2021-01-29 00:20:46 +05:30
2021-04-29 21:17:54 +05:30
await expect(actions.setActiveItemSubscribed({ getters }, input)).rejects.toThrow(Error);
2021-01-29 00:20:46 +05:30
});
});
2021-04-29 21:17:54 +05:30
describe('setActiveItemTitle', () => {
const state = {
boardItems: { [mockIssue.id]: mockIssue },
2021-06-08 01:23:25 +05:30
issuableType: issuableTypes.issue,
2021-04-29 21:17:54 +05:30
fullPath: 'path/f',
};
const getters = { activeBoardItem: mockIssue, isEpicBoard: false };
2021-03-08 18:12:59 +05:30
const testTitle = 'Test Title';
const input = {
title: testTitle,
projectPath: 'h/b',
};
it('should commit title after setting the issue', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
2021-04-29 21:17:54 +05:30
updateIssuableTitle: {
2021-03-08 18:12:59 +05:30
issue: {
title: testTitle,
},
errors: [],
},
},
});
const payload = {
2021-04-29 21:17:54 +05:30
itemId: getters.activeBoardItem.id,
2021-03-08 18:12:59 +05:30
prop: 'title',
value: testTitle,
};
testAction(
2021-04-29 21:17:54 +05:30
actions.setActiveItemTitle,
2021-03-08 18:12:59 +05:30
input,
{ ...state, ...getters },
[
{
2021-04-29 21:17:54 +05:30
type: types.UPDATE_BOARD_ITEM_BY_ID,
2021-03-08 18:12:59 +05:30
payload,
},
],
[],
done,
);
});
it('throws error if fails', async () => {
jest
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
2021-04-29 21:17:54 +05:30
await expect(actions.setActiveItemTitle({ getters }, input)).rejects.toThrow(Error);
2021-03-08 18:12:59 +05:30
});
});
2021-06-08 01:23:25 +05:30
describe('setActiveItemConfidential', () => {
const state = { boardItems: { [mockIssue.id]: mockIssue } };
const getters = { activeBoardItem: mockIssue };
it('set confidential value on board item', (done) => {
const payload = {
itemId: getters.activeBoardItem.id,
prop: 'confidential',
value: true,
};
testAction(
actions.setActiveItemConfidential,
true,
{ ...state, ...getters },
[
{
type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
[],
done,
);
});
});
2021-03-08 18:12:59 +05:30
describe('fetchGroupProjects', () => {
const state = {
fullPath: 'gitlab-org',
};
const pageInfo = {
endCursor: '',
hasNextPage: false,
};
const queryResponse = {
data: {
group: {
projects: {
nodes: mockGroupProjects,
pageInfo: {
endCursor: '',
hasNextPage: false,
},
},
},
},
};
it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_SUCCESS on success', (done) => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
actions.fetchGroupProjects,
{},
state,
[
{
type: types.REQUEST_GROUP_PROJECTS,
payload: false,
},
{
type: types.RECEIVE_GROUP_PROJECTS_SUCCESS,
payload: { projects: mockGroupProjects, pageInfo, fetchNext: false },
},
],
[],
done,
);
});
it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_FAILURE on failure', (done) => {
jest.spyOn(gqlClient, 'query').mockRejectedValue();
testAction(
actions.fetchGroupProjects,
{},
state,
[
{
type: types.REQUEST_GROUP_PROJECTS,
payload: false,
},
{
type: types.RECEIVE_GROUP_PROJECTS_FAILURE,
},
],
[],
done,
);
});
});
describe('setSelectedProject', () => {
it('should commit mutation SET_SELECTED_PROJECT', (done) => {
const project = mockGroupProjects[0];
testAction(
actions.setSelectedProject,
project,
{},
[
{
type: types.SET_SELECTED_PROJECT,
payload: project,
},
],
[],
done,
);
});
});
2021-03-11 19:13:27 +05:30
describe('toggleBoardItemMultiSelection', () => {
const boardItem = mockIssue;
2021-04-17 20:07:23 +05:30
const boardItem2 = mockIssue2;
2021-03-11 19:13:27 +05:30
it('should commit mutation ADD_BOARD_ITEM_TO_SELECTION if item is not on selection state', () => {
testAction(
actions.toggleBoardItemMultiSelection,
boardItem,
{ selectedBoardItems: [] },
[
{
type: types.ADD_BOARD_ITEM_TO_SELECTION,
payload: boardItem,
},
],
[],
);
});
it('should commit mutation REMOVE_BOARD_ITEM_FROM_SELECTION if item is on selection state', () => {
testAction(
actions.toggleBoardItemMultiSelection,
boardItem,
{ selectedBoardItems: [mockIssue] },
[
{
type: types.REMOVE_BOARD_ITEM_FROM_SELECTION,
payload: boardItem,
},
],
[],
);
});
2021-04-17 20:07:23 +05:30
it('should additionally commit mutation ADD_BOARD_ITEM_TO_SELECTION for active issue and dispatch unsetActiveId', () => {
testAction(
actions.toggleBoardItemMultiSelection,
boardItem2,
2021-04-29 21:17:54 +05:30
{ activeId: mockActiveIssue.id, activeBoardItem: mockActiveIssue, selectedBoardItems: [] },
2021-04-17 20:07:23 +05:30
[
{
type: types.ADD_BOARD_ITEM_TO_SELECTION,
payload: mockActiveIssue,
},
{
type: types.ADD_BOARD_ITEM_TO_SELECTION,
payload: boardItem2,
},
],
[{ type: 'unsetActiveId' }],
);
});
});
describe('resetBoardItemMultiSelection', () => {
it('should commit mutation RESET_BOARD_ITEM_SELECTION', () => {
testAction({
action: actions.resetBoardItemMultiSelection,
state: { selectedBoardItems: [mockIssue] },
expectedMutations: [
{
type: types.RESET_BOARD_ITEM_SELECTION,
},
],
});
});
});
describe('toggleBoardItem', () => {
it('should dispatch resetBoardItemMultiSelection and unsetActiveId when boardItem is the active item', () => {
testAction({
action: actions.toggleBoardItem,
payload: { boardItem: mockIssue },
state: {
activeId: mockIssue.id,
},
expectedActions: [{ type: 'resetBoardItemMultiSelection' }, { type: 'unsetActiveId' }],
});
});
it('should dispatch resetBoardItemMultiSelection and setActiveId when boardItem is not the active item', () => {
testAction({
action: actions.toggleBoardItem,
payload: { boardItem: mockIssue },
state: {
activeId: inactiveId,
},
expectedActions: [
{ type: 'resetBoardItemMultiSelection' },
{ type: 'setActiveId', payload: { id: mockIssue.id, sidebarType: ISSUABLE } },
],
});
});
2021-03-11 19:13:27 +05:30
});
2021-04-29 21:17:54 +05:30
describe('setError', () => {
it('should commit mutation SET_ERROR', () => {
testAction({
action: actions.setError,
payload: { message: 'mayday' },
expectedMutations: [
{
payload: 'mayday',
type: types.SET_ERROR,
},
],
});
});
it('should capture error using Sentry when captureError is true', () => {
jest.spyOn(Sentry, 'captureException');
const mockError = new Error();
actions.setError(
{ commit: () => {} },
{
message: 'mayday',
error: mockError,
captureError: true,
},
);
expect(Sentry.captureException).toHaveBeenNthCalledWith(1, mockError);
});
});
describe('unsetError', () => {
it('should commit mutation SET_ERROR with undefined as payload', () => {
testAction({
action: actions.unsetError,
expectedMutations: [
{
payload: undefined,
type: types.SET_ERROR,
},
],
});
});
});