Fixed MR widget unresolved discussions state

After resolving a discussion on a merge request page the merge request
widget state would not get updated meaning users would need to refresh
the page to merge (if that option is enabled in the projects settings)

https://gitlab.com/gitlab-org/gitlab-ce/issues/42882
This commit is contained in:
Phil Hughes 2018-09-12 16:46:09 +01:00
parent f87809f78d
commit 8287f3477f
No known key found for this signature in database
GPG Key ID: 32245528C52E0F9F
3 changed files with 211 additions and 3 deletions

View File

@ -61,9 +61,11 @@ export const refetchDiscussionById = ({ commit, state }, { path, discussionId })
.catch(() => {});
});
export const deleteNote = ({ commit }, note) =>
export const deleteNote = ({ commit, dispatch }, note) =>
service.deleteNote(note.path).then(() => {
commit(types.DELETE_NOTE, note);
dispatch('updateMergeRequestWidget');
});
export const updateNote = ({ commit }, { endpoint, note }) =>
@ -84,20 +86,22 @@ export const replyToDiscussion = ({ commit }, { endpoint, data }) =>
return res;
});
export const createNewNote = ({ commit }, { endpoint, data }) =>
export const createNewNote = ({ commit, dispatch }, { endpoint, data }) =>
service
.createNewNote(endpoint, data)
.then(res => res.json())
.then(res => {
if (!res.errors) {
commit(types.ADD_NEW_NOTE, res);
dispatch('updateMergeRequestWidget');
}
return res;
});
export const removePlaceholderNotes = ({ commit }) => commit(types.REMOVE_PLACEHOLDER_NOTES);
export const toggleResolveNote = ({ commit }, { endpoint, isResolved, discussion }) =>
export const toggleResolveNote = ({ commit, dispatch }, { endpoint, isResolved, discussion }) =>
service
.toggleResolveNote(endpoint, isResolved)
.then(res => res.json())
@ -105,6 +109,8 @@ export const toggleResolveNote = ({ commit }, { endpoint, isResolved, discussion
const mutationType = discussion ? types.UPDATE_DISCUSSION : types.UPDATE_NOTE;
commit(mutationType, res);
dispatch('updateMergeRequestWidget');
});
export const closeIssue = ({ commit, dispatch, state }) => {
@ -333,5 +339,9 @@ export const fetchDiscussionDiffLines = ({ commit }, discussion) =>
});
});
export const updateMergeRequestWidget = () => {
if (gl.mrWidget) gl.mrWidget.checkStatus();
};
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};

View File

@ -0,0 +1,5 @@
---
title: Fixed merge request widget discussion state not updating after resolving discussions
merge_request: 21705
author:
type: fixed

View File

@ -317,4 +317,197 @@ describe('Actions Notes Store', () => {
);
});
});
describe('deleteNote', () => {
const interceptor = (request, next) => {
next(
request.respondWith(JSON.stringify({}), {
status: 200,
}),
);
};
beforeEach(() => {
Vue.http.interceptors.push(interceptor);
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', done => {
const note = { path: `${gl.TEST_HOST}`, id: 1 };
testAction(
actions.deleteNote,
note,
store.state,
[
{
type: 'DELETE_NOTE',
payload: note,
},
],
[
{
type: 'updateMergeRequestWidget',
},
],
done,
);
});
});
describe('createNewNote', () => {
describe('success', () => {
const res = {
id: 1,
valid: true,
};
const interceptor = (request, next) => {
next(
request.respondWith(JSON.stringify(res), {
status: 200,
}),
);
};
beforeEach(() => {
Vue.http.interceptors.push(interceptor);
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
it('commits ADD_NEW_NOTE and dispatches updateMergeRequestWidget', done => {
testAction(
actions.createNewNote,
{ endpoint: `${gl.TEST_HOST}`, data: {} },
store.state,
[
{
type: 'ADD_NEW_NOTE',
payload: res,
},
],
[
{
type: 'updateMergeRequestWidget',
},
],
done,
);
});
});
describe('error', () => {
const res = {
errors: ['error'],
};
const interceptor = (request, next) => {
next(
request.respondWith(JSON.stringify(res), {
status: 200,
}),
);
};
beforeEach(() => {
Vue.http.interceptors.push(interceptor);
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
it('does not commit ADD_NEW_NOTE or dispatch updateMergeRequestWidget', done => {
testAction(
actions.createNewNote,
{ endpoint: `${gl.TEST_HOST}`, data: {} },
store.state,
[],
[],
done,
);
});
});
});
describe('toggleResolveNote', () => {
const res = {
resolved: true,
};
const interceptor = (request, next) => {
next(
request.respondWith(JSON.stringify(res), {
status: 200,
}),
);
};
beforeEach(() => {
Vue.http.interceptors.push(interceptor);
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
describe('as note', () => {
it('commits UPDATE_NOTE and dispatches updateMergeRequestWidget', done => {
testAction(
actions.toggleResolveNote,
{ endpoint: `${gl.TEST_HOST}`, isResolved: true, discussion: false },
store.state,
[
{
type: 'UPDATE_NOTE',
payload: res,
},
],
[
{
type: 'updateMergeRequestWidget',
},
],
done,
);
});
});
describe('as discussion', () => {
it('commits UPDATE_DISCUSSION and dispatches updateMergeRequestWidget', done => {
testAction(
actions.toggleResolveNote,
{ endpoint: `${gl.TEST_HOST}`, isResolved: true, discussion: true },
store.state,
[
{
type: 'UPDATE_DISCUSSION',
payload: res,
},
],
[
{
type: 'updateMergeRequestWidget',
},
],
done,
);
});
});
});
describe('updateMergeRequestWidget', () => {
it('calls mrWidget checkStatus', () => {
gl.mrWidget = {
checkStatus: jasmine.createSpy('checkStatus'),
};
actions.updateMergeRequestWidget();
expect(gl.mrWidget.checkStatus).toHaveBeenCalled();
});
});
});