Commit d1082011 authored by Eulyeon Ko's avatar Eulyeon Ko Committed by Simon Knox

Use global ids when updating board scope

The serialized board data used to initialize
BoardForm contains non-global ids for assignee,
milestone and iterations.
(we will be using graphql to fetch the initial data
in the future).

This commit fixes BoardForm to convert non-global assignee id
into a global id before requesting an update.

Changelog: fixed
EE: true
parent 5e00874a
<script> <script>
import { GlModal, GlAlert } from '@gitlab/ui'; import { GlModal, GlAlert } from '@gitlab/ui';
import { mapGetters, mapActions, mapState } from 'vuex'; import { mapGetters, mapActions, mapState } from 'vuex';
import { TYPE_ITERATION, TYPE_MILESTONE } from '~/graphql_shared/constants'; import { TYPE_USER, TYPE_ITERATION, TYPE_MILESTONE } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils'; import { convertToGraphQLId } from '~/graphql_shared/utils';
import { getParameterByName, visitUrl } from '~/lib/utils/url_utility'; import { getParameterByName, visitUrl } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
...@@ -188,7 +188,9 @@ export default { ...@@ -188,7 +188,9 @@ export default {
issueBoardScopeMutationVariables() { issueBoardScopeMutationVariables() {
return { return {
weight: this.board.weight, weight: this.board.weight,
assigneeId: this.board.assignee?.id || null, assigneeId: this.board.assignee?.id
? convertToGraphQLId(TYPE_USER, this.board.assignee.id)
: null,
milestoneId: this.board.milestone?.id milestoneId: this.board.milestone?.id
? convertToGraphQLId(TYPE_MILESTONE, this.board.milestone.id) ? convertToGraphQLId(TYPE_MILESTONE, this.board.milestone.id)
: null, : null,
......
...@@ -12,11 +12,13 @@ import { TEST_HOST } from 'helpers/test_constants'; ...@@ -12,11 +12,13 @@ import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { formType } from '~/boards/constants'; import { formType } from '~/boards/constants';
import updateBoardMutation from '~/boards/graphql/board_update.mutation.graphql';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({ jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrlMock'), visitUrl: jest.fn().mockName('visitUrlMock'),
stripFinalUrlSegment: jest.requireActual('~/lib/utils/url_utility').stripFinalUrlSegment, stripFinalUrlSegment: jest.requireActual('~/lib/utils/url_utility').stripFinalUrlSegment,
getParameterByName: jest.fn().mockName('getParameterByName'),
})); }));
Vue.use(Vuex); Vue.use(Vuex);
...@@ -44,6 +46,7 @@ const defaultProps = { ...@@ -44,6 +46,7 @@ const defaultProps = {
describe('BoardForm', () => { describe('BoardForm', () => {
let wrapper; let wrapper;
let mutate; let mutate;
let store;
const findModal = () => wrapper.findComponent(GlModal); const findModal = () => wrapper.findComponent(GlModal);
const findModalActionPrimary = () => findModal().props('actionPrimary'); const findModalActionPrimary = () => findModal().props('actionPrimary');
...@@ -51,19 +54,18 @@ describe('BoardForm', () => { ...@@ -51,19 +54,18 @@ describe('BoardForm', () => {
const findDeleteConfirmation = () => wrapper.find('[data-testid="delete-confirmation-message"]'); const findDeleteConfirmation = () => wrapper.find('[data-testid="delete-confirmation-message"]');
const findInput = () => wrapper.find('#board-new-name'); const findInput = () => wrapper.find('#board-new-name');
const createStore = () => { const createStore = ({ getters = {} } = {}) => {
return new Vuex.Store({ store = new Vuex.Store({
getters: { getters: {
isIssueBoard: () => false, isIssueBoard: () => false,
isEpicBoard: () => true, isEpicBoard: () => true,
isGroupBoard: () => true, isGroupBoard: () => true,
isProjectBoard: () => false, isProjectBoard: () => false,
...getters,
}, },
}); });
}; };
const store = createStore();
const createComponent = (props) => { const createComponent = (props) => {
wrapper = shallowMount(BoardForm, { wrapper = shallowMount(BoardForm, {
propsData: { ...defaultProps, ...props }, propsData: { ...defaultProps, ...props },
...@@ -84,9 +86,14 @@ describe('BoardForm', () => { ...@@ -84,9 +86,14 @@ describe('BoardForm', () => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
mutate = null; mutate = null;
store = null;
}); });
describe('when creating a new epic board', () => { describe('when creating a new epic board', () => {
beforeEach(() => {
createStore();
});
describe('on non-scoped-board', () => { describe('on non-scoped-board', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ canAdminBoard: true, currentPage: formType.new }); createComponent({ canAdminBoard: true, currentPage: formType.new });
...@@ -176,7 +183,62 @@ describe('BoardForm', () => { ...@@ -176,7 +183,62 @@ describe('BoardForm', () => {
}); });
}); });
describe('when editing a scoped issue board', () => {
beforeEach(() => {
createStore({
getters: {
isIssueBoard: () => true,
isEpicBoard: () => false,
},
});
});
it('should use global ids for assignee, milestone and iteration when calling GraphQL mutation', async () => {
mutate = jest.fn().mockResolvedValue({
data: {
updateBoard: { board: { id: 'gid://gitlab/Board/321' } },
},
});
createComponent({
currentBoard: {
...currentBoard,
assignee: {
id: 1,
},
milestone: {
id: 2,
},
iteration_id: 3,
},
canAdminBoard: true,
currentPage: formType.edit,
scopedIssueBoardFeatureEnabled: true,
});
findInput().trigger('keyup.enter', { metaKey: true });
await waitForPromises();
expect(mutate).toHaveBeenCalledWith({
mutation: updateBoardMutation,
variables: {
input: expect.objectContaining({
id: `gid://gitlab/Board/${currentBoard.id}`,
assigneeId: 'gid://gitlab/User/1',
milestoneId: 'gid://gitlab/Milestone/2',
iterationId: 'gid://gitlab/Iteration/3',
}),
},
});
});
});
describe('when editing an epic board', () => { describe('when editing an epic board', () => {
beforeEach(() => {
createStore();
});
it('calls GraphQL mutation with correct parameters', async () => { it('calls GraphQL mutation with correct parameters', async () => {
mutate = jest.fn().mockResolvedValue({ mutate = jest.fn().mockResolvedValue({
data: { data: {
...@@ -221,6 +283,10 @@ describe('BoardForm', () => { ...@@ -221,6 +283,10 @@ describe('BoardForm', () => {
}); });
describe('when deleting an epic board', () => { describe('when deleting an epic board', () => {
beforeEach(() => {
createStore();
});
it('passes correct primary action text and variant', () => { it('passes correct primary action text and variant', () => {
createComponent({ canAdminBoard: true, currentPage: formType.delete }); createComponent({ canAdminBoard: true, currentPage: formType.delete });
expect(findModalActionPrimary().text).toBe('Delete'); expect(findModalActionPrimary().text).toBe('Delete');
......
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