Commit 791de1f5 authored by Simon Knox's avatar Simon Knox

Merge branch...

Merge branch '328564-use-a-correct-group-path-when-fetching-an-epic-in-graphql-boards' into 'master'

Use a correct group path when fetching epic in graphql boards

See merge request gitlab-org/gitlab!59937
parents 45e56844 deb8bb3f
......@@ -21,6 +21,9 @@ fragment IssueNode on Issue {
epic {
id
iid
group {
fullPath
}
}
milestone {
id
......
......@@ -382,10 +382,10 @@ export default {
}
const {
epic: { id, iid },
epic: { id, iid, group: { fullPath } = {} },
} = getters.activeBoardItem;
if (state.epicsCacheById[id]) {
if (!iid || !fullPath || state.epicsCacheById[id]) {
return false;
}
......@@ -399,7 +399,7 @@ export default {
} = await gqlClient.query({
query: epicQuery,
variables: {
fullPath: getters.groupPathForActiveIssue,
fullPath,
iid,
},
});
......@@ -440,7 +440,7 @@ export default {
commit(typesCE.UPDATE_BOARD_ITEM_BY_ID, {
itemId: getters.activeBoardItem.id,
prop: 'epic',
value: epic ? { id: epic.id, iid: epic.iid } : null,
value: epic ? { id: epic.id, iid: epic.iid, group: { fullPath: epic.group.fullPath } } : null,
});
commit(types.SET_EPIC_FETCH_IN_PROGRESS, false);
},
......
fragment EpicNode on Epic {
id
iid
group {
fullPath
}
title
state
reference
......
......@@ -170,6 +170,7 @@ export const mockIssue = {
epic: {
id: 'gid://gitlab/Epic/41',
iid: 2,
group: { fullPath: mockIssueGroupPath },
},
};
......@@ -188,6 +189,7 @@ export const mockIssue2 = {
epic: {
id: 'gid://gitlab/Epic/40',
iid: 1,
group: { fullPath: 'gitlab-org' },
},
};
......@@ -229,6 +231,7 @@ export const mockEpic = {
title: 'Epic title',
state: 'opened',
webUrl: '/groups/gitlab-org/-/epics/1',
group: { fullPath: 'gitlab-org' },
descendantCounts: {
openedIssues: 3,
closedIssues: 2,
......@@ -237,6 +240,13 @@ export const mockEpic = {
labels: [],
};
export const mockEpic2 = {
id: 'gid://gitlab/Epic/42',
iid: '2',
group: { fullPath: 'gitlab-org' },
title: 'Epic title 2',
};
export const mockIssueWithEpic = {
...mockIssue3,
epic: {
......
......@@ -22,6 +22,7 @@ import {
mockIssue,
mockIssues,
mockEpic,
mockEpic2,
mockMilestones,
mockAssignees,
} from '../mock_data';
......@@ -657,8 +658,7 @@ describe('resetEpics', () => {
describe('fetchEpicForActiveIssue', () => {
const assignedEpic = {
id: mockIssue.epic.id,
iid: mockIssue.epic.iid,
...mockIssue.epic,
};
describe("when active issue doesn't have an assigned epic", () => {
......@@ -669,6 +669,19 @@ describe('fetchEpicForActiveIssue', () => {
});
});
describe("when active issue doesn't have the full epic information", () => {
// Edge Case: when user drops/moves a card onto an epic swimlane,
// until IssueMoveList request is completed, the issue item only has epic id.
// This causes a problem when user also has the sidebar open because
// board_sidebar_epic_select watches for the issue item's `epic` field
// and tries to extract epic id, epic iid and fullpath to request for detailed epic info.
const getters = { activeBoardItem: { ...mockIssue, epic: { id: 'something' } } };
it('should not fetch any epic', async () => {
await testAction(actions.fetchEpicForActiveIssue, undefined, { ...getters }, [], []);
});
});
describe('when the assigned epic for active issue is found in state.epicsCacheById', () => {
const getters = { activeBoardItem: { ...mockIssue, epic: assignedEpic } };
const state = { epicsCacheById: { [assignedEpic.id]: assignedEpic } };
......@@ -749,21 +762,16 @@ describe('setActiveIssueEpic', () => {
epics: [{ id: 'gid://gitlab/Epic/422', iid: 99, title: 'existing epic' }],
};
const getters = { activeBoardItem: { ...mockIssue, projectPath: 'h/b' } };
const epicWithData = {
id: 'gid://gitlab/Epic/42',
iid: 1,
title: 'Epic title',
};
describe('when the updated issue has an assigned epic', () => {
it('should commit mutation RECEIVE_EPICS_SUCCESS, UPDATE_CACHED_EPICS and UPDATE_BOARD_ITEM_BY_ID on success', async () => {
jest
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { issueSetEpic: { issue: { epic: epicWithData } } } });
.mockResolvedValue({ data: { issueSetEpic: { issue: { epic: mockEpic2 } } } });
await testAction(
actions.setActiveIssueEpic,
epicWithData.id,
mockEpic2.id,
{ ...state, ...getters },
[
{
......@@ -772,18 +780,18 @@ describe('setActiveIssueEpic', () => {
},
{
type: types.RECEIVE_EPICS_SUCCESS,
payload: { epics: [epicWithData, ...state.epics] },
payload: { epics: [mockEpic2, ...state.epics] },
},
{
type: types.UPDATE_CACHED_EPICS,
payload: [epicWithData],
payload: [mockEpic2],
},
{
type: typesCE.UPDATE_BOARD_ITEM_BY_ID,
payload: {
itemId: mockIssue.id,
prop: 'epic',
value: { id: epicWithData.id, iid: epicWithData.iid },
value: { id: mockEpic2.id, iid: mockEpic2.iid, group: mockEpic2.group },
},
},
{
......@@ -830,7 +838,7 @@ describe('setActiveIssueEpic', () => {
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { issueSetEpic: { errors: ['failed mutation'] } } });
await expect(actions.setActiveIssueEpic({ getters }, epicWithData.id)).rejects.toThrow(Error);
await expect(actions.setActiveIssueEpic({ getters }, mockEpic2.id)).rejects.toThrow(Error);
});
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment