Commit 35ff3879 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '348774-weight-is-assigned-to-a-wrong-card-in-boards' into 'master'

Boards - Fix weight assigned to wrong card

See merge request gitlab-org/gitlab!78161
parents c8fc575a fe2abc0b
...@@ -404,9 +404,9 @@ export default { ...@@ -404,9 +404,9 @@ export default {
commit(types.RESET_EPICS); commit(types.RESET_EPICS);
}, },
setActiveItemWeight: async ({ commit, getters }, weight) => { setActiveItemWeight: async ({ commit }, { weight, id }) => {
commit(typesCE.UPDATE_BOARD_ITEM_BY_ID, { commit(typesCE.UPDATE_BOARD_ITEM_BY_ID, {
itemId: getters.activeBoardItem.id, itemId: id,
prop: 'weight', prop: 'weight',
value: weight, value: weight,
}); });
......
...@@ -53,6 +53,7 @@ export default { ...@@ -53,6 +53,7 @@ export default {
return { return {
weight: null, weight: null,
loading: false, loading: false,
oldIid: null,
}; };
}, },
apollo: { apollo: {
...@@ -70,7 +71,7 @@ export default { ...@@ -70,7 +71,7 @@ export default {
return data.workspace?.issuable?.weight; return data.workspace?.issuable?.weight;
}, },
result({ data }) { result({ data }) {
this.$emit('weightUpdated', data.workspace?.issuable?.weight); return data.workspace?.issuable?.weight;
}, },
error() { error() {
createFlash({ createFlash({
...@@ -106,10 +107,16 @@ export default { ...@@ -106,10 +107,16 @@ export default {
: this.$options.i18n.noWeightLabel; : this.$options.i18n.noWeightLabel;
}, },
}, },
watch: {
iid(_, oldVal) {
this.oldIid = oldVal;
},
},
methods: { methods: {
setWeight(remove) { setWeight(remove) {
const shouldRemoveWeight = remove || this.weight === ''; const shouldRemoveWeight = remove || this.weight === '';
const weight = shouldRemoveWeight ? null : this.weight; const weight = shouldRemoveWeight ? null : this.weight;
const currentIid = shouldRemoveWeight ? this.iid : this.oldIid || this.iid;
this.loading = true; this.loading = true;
this.$apollo this.$apollo
.mutate({ .mutate({
...@@ -117,24 +124,23 @@ export default { ...@@ -117,24 +124,23 @@ export default {
variables: { variables: {
input: { input: {
projectPath: this.fullPath, projectPath: this.fullPath,
iid: this.iid, iid: currentIid,
weight, weight,
}, },
}, },
}) })
.then( .then(({ data: { issuableSetWeight } }) => {
({ if (issuableSetWeight.errors?.length) {
data: {
issuableSetWeight: { errors },
},
}) => {
if (errors.length) {
createFlash({ createFlash({
message: errors[0], message: issuableSetWeight.errors[0],
});
} else {
this.$emit('weightUpdated', {
weight: issuableSetWeight?.issuable?.weight,
id: issuableSetWeight?.issuable?.id,
}); });
} }
}, })
)
.catch(() => { .catch(() => {
createFlash({ createFlash({
message: sprintf(__('Something went wrong while setting %{issuableType} weight.'), { message: sprintf(__('Something went wrong while setting %{issuableType} weight.'), {
...@@ -173,6 +179,7 @@ export default { ...@@ -173,6 +179,7 @@ export default {
:loading="isLoading" :loading="isLoading"
class="block weight" class="block weight"
data-testid="sidebar-weight" data-testid="sidebar-weight"
@open="oldIid = null"
@close="setWeight()" @close="setWeight()"
> >
<template #collapsed> <template #collapsed>
......
...@@ -265,6 +265,20 @@ RSpec.describe 'Issue Boards', :js do ...@@ -265,6 +265,20 @@ RSpec.describe 'Issue Boards', :js do
expect(weight_value).to have_content 'None' expect(weight_value).to have_content 'None'
end end
it 'updates the original card when another card is clicked' do
click_card(card1)
within weight_widget do
click_button 'Edit'
find('.weight input').send_keys 1
end
click_card(card2)
click_card(card1)
expect(weight_value).to have_content '1'
end
context 'unlicensed' do context 'unlicensed' do
before do before do
stub_licensed_features(issue_weights: false) stub_licensed_features(issue_weights: false)
......
...@@ -685,7 +685,7 @@ describe('setActiveItemWeight', () => { ...@@ -685,7 +685,7 @@ describe('setActiveItemWeight', () => {
const state = { boardItems: { [mockIssue.id]: mockIssue } }; const state = { boardItems: { [mockIssue.id]: mockIssue } };
const getters = { activeBoardItem: mockIssue }; const getters = { activeBoardItem: mockIssue };
const testWeight = mockIssue.weight + 1; const testWeight = mockIssue.weight + 1;
const input = testWeight; const input = { weight: testWeight, id: mockIssue.id };
it('should commit weight', (done) => { it('should commit weight', (done) => {
const payload = { const payload = {
......
import { GlButton, GlForm, GlFormInput } 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 VueApollo from 'vue-apollo';
import SidebarWeightWidget from 'ee_component/sidebar/components/weight/sidebar_weight_widget.vue'; import SidebarWeightWidget from 'ee_component/sidebar/components/weight/sidebar_weight_widget.vue';
import issueWeightQuery from 'ee_component/sidebar/queries/issue_weight.query.graphql'; import issueWeightQuery from 'ee_component/sidebar/queries/issue_weight.query.graphql';
import updateIssueWeightMutation from 'ee_component/sidebar/queries/update_issue_weight.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { preventDefault, stopPropagation } from 'ee_jest/admin/test_helpers';
import createFlash from '~/flash'; import createFlash from '~/flash';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import { issueNoWeightResponse, issueWeightResponse } from '../../mock_data'; import {
issueNoWeightResponse,
issueWeightResponse,
setWeightResponse,
removeWeightResponse,
mockIssueId,
} from '../../mock_data';
jest.mock('~/flash'); jest.mock('~/flash');
...@@ -19,12 +28,20 @@ describe('Sidebar Weight Widget', () => { ...@@ -19,12 +28,20 @@ describe('Sidebar Weight Widget', () => {
let fakeApollo; let fakeApollo;
const findEditableItem = () => wrapper.findComponent(SidebarEditableItem); const findEditableItem = () => wrapper.findComponent(SidebarEditableItem);
const findRemoveButton = () => wrapper.findComponent(GlButton);
const findWeightValue = () => wrapper.findByTestId('sidebar-weight-value'); const findWeightValue = () => wrapper.findByTestId('sidebar-weight-value');
const findFormInput = () => wrapper.findComponent(GlFormInput);
const findForm = () => wrapper.findComponent(GlForm);
const createFakeEvent = () => ({ preventDefault, stopPropagation });
const createComponent = ({ const createComponent = ({
weightQueryHandler = jest.fn().mockResolvedValue(issueNoWeightResponse()), weightQueryHandler = jest.fn().mockResolvedValue(issueNoWeightResponse()),
weightMutationHandler = jest.fn().mockResolvedValue(setWeightResponse()),
} = {}) => { } = {}) => {
fakeApollo = createMockApollo([[issueWeightQuery, weightQueryHandler]]); fakeApollo = createMockApollo([
[issueWeightQuery, weightQueryHandler],
[updateIssueWeightMutation, weightMutationHandler],
]);
wrapper = extendedWrapper( wrapper = extendedWrapper(
shallowMount(SidebarWeightWidget, { shallowMount(SidebarWeightWidget, {
...@@ -37,9 +54,6 @@ describe('Sidebar Weight Widget', () => { ...@@ -37,9 +54,6 @@ describe('Sidebar Weight Widget', () => {
iid: '1', iid: '1',
issuableType: 'issue', issuableType: 'issue',
}, },
stubs: {
SidebarEditableItem,
},
}), }),
); );
}; };
...@@ -58,6 +72,7 @@ describe('Sidebar Weight Widget', () => { ...@@ -58,6 +72,7 @@ describe('Sidebar Weight Widget', () => {
describe('when issue has no weight', () => { describe('when issue has no weight', () => {
beforeEach(() => { beforeEach(() => {
createComponent(); createComponent();
wrapper.vm.$refs.editable.collapse = jest.fn();
return waitForPromises(); return waitForPromises();
}); });
...@@ -69,8 +84,18 @@ describe('Sidebar Weight Widget', () => { ...@@ -69,8 +84,18 @@ describe('Sidebar Weight Widget', () => {
expect(findWeightValue().text()).toBe('None'); expect(findWeightValue().text()).toBe('None');
}); });
it('emits `weightUpdated` event with a `null` payload', () => { it('does not display remove option', () => {
expect(wrapper.emitted('weightUpdated')).toEqual([[null]]); expect(findRemoveButton().exists()).toBe(false);
});
it('sets weight', async () => {
findEditableItem().vm.$emit('open');
findFormInput().vm.$emit('input', '2');
findForm().vm.$emit('submit', createFakeEvent());
await waitForPromises();
expect(findWeightValue().text()).toBe('2');
expect(wrapper.emitted('weightUpdated')).toEqual([[{ id: mockIssueId, weight: 2 }]]);
}); });
}); });
...@@ -78,6 +103,7 @@ describe('Sidebar Weight Widget', () => { ...@@ -78,6 +103,7 @@ describe('Sidebar Weight Widget', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ createComponent({
weightQueryHandler: jest.fn().mockResolvedValue(issueWeightResponse(true)), weightQueryHandler: jest.fn().mockResolvedValue(issueWeightResponse(true)),
weightMutationHandler: jest.fn().mockResolvedValue(removeWeightResponse()),
}); });
return waitForPromises(); return waitForPromises();
}); });
...@@ -90,8 +116,13 @@ describe('Sidebar Weight Widget', () => { ...@@ -90,8 +116,13 @@ describe('Sidebar Weight Widget', () => {
expect(findWeightValue().text()).toBe('0'); expect(findWeightValue().text()).toBe('0');
}); });
it('emits `weightUpdated` event with a `true` payload', () => { it('displays remove option - removes weight', async () => {
expect(wrapper.emitted('weightUpdated')).toEqual([[0]]); expect(findRemoveButton().exists()).toBe(true);
findRemoveButton().vm.$emit('click');
await waitForPromises();
expect(findWeightValue().text()).toBe('None');
expect(wrapper.emitted('weightUpdated')).toEqual([[{ id: mockIssueId, weight: null }]]);
}); });
}); });
......
...@@ -193,3 +193,23 @@ export const issueWeightResponse = () => ({ ...@@ -193,3 +193,23 @@ export const issueWeightResponse = () => ({
}, },
}, },
}); });
export const setWeightResponse = () => ({
data: {
issuableSetWeight: {
issuable: { id: mockIssueId, weight: 2, __typename: 'Issue' },
errors: [],
__typename: 'Project',
},
},
});
export const removeWeightResponse = () => ({
data: {
issuableSetWeight: {
issuable: { id: mockIssueId, weight: null, __typename: 'Issue' },
errors: [],
__typename: 'Project',
},
},
});
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