diff options
author | Phil Hughes <me@iamphill.com> | 2018-09-12 16:46:09 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2018-09-12 16:46:09 +0100 |
commit | 8287f3477f4aaaa50f900ec06bef6e86f489a16d (patch) | |
tree | 8bfecb843a540fe4a7d0721abab0ae9c3914e5da | |
parent | f87809f78de9da04f38134ba5ce0cf9ddebf2f63 (diff) | |
download | gitlab-ce-8287f3477f4aaaa50f900ec06bef6e86f489a16d.tar.gz |
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
-rw-r--r-- | app/assets/javascripts/notes/stores/actions.js | 16 | ||||
-rw-r--r-- | changelogs/unreleased/mr-widget-discussion-state-fix.yml | 5 | ||||
-rw-r--r-- | spec/javascripts/notes/stores/actions_spec.js | 193 |
3 files changed, 211 insertions, 3 deletions
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 9a2ec15debd..17ff0a63833 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -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 () => {}; diff --git a/changelogs/unreleased/mr-widget-discussion-state-fix.yml b/changelogs/unreleased/mr-widget-discussion-state-fix.yml new file mode 100644 index 00000000000..562d78a7aa7 --- /dev/null +++ b/changelogs/unreleased/mr-widget-discussion-state-fix.yml @@ -0,0 +1,5 @@ +--- +title: Fixed merge request widget discussion state not updating after resolving discussions +merge_request: 21705 +author: +type: fixed diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js index b66e8e1ceb3..350162d5bb6 100644 --- a/spec/javascripts/notes/stores/actions_spec.js +++ b/spec/javascripts/notes/stores/actions_spec.js @@ -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(); + }); + }); }); |