diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 14:18:50 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 14:18:50 +0300 |
commit | 8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781 (patch) | |
tree | a77e7fe7a93de11213032ed4ab1f33a3db51b738 /spec/frontend/notes/stores | |
parent | 00b35af3db1abfe813a778f643dad221aad51fca (diff) |
Add latest changes from gitlab-org/gitlab@13-1-stable-ee
Diffstat (limited to 'spec/frontend/notes/stores')
-rw-r--r-- | spec/frontend/notes/stores/actions_spec.js | 214 | ||||
-rw-r--r-- | spec/frontend/notes/stores/mutation_spec.js | 117 |
2 files changed, 330 insertions, 1 deletions
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js index cbfb9597159..ef87cb3bee7 100644 --- a/spec/frontend/notes/stores/actions_spec.js +++ b/spec/frontend/notes/stores/actions_spec.js @@ -15,6 +15,7 @@ import { userDataMock, noteableDataMock, individualNote, + batchSuggestionsInfoMock, } from '../mock_data'; import axios from '~/lib/utils/axios_utils'; @@ -890,7 +891,23 @@ describe('Actions Notes Store', () => { testSubmitSuggestion(done, () => { expect(commit).not.toHaveBeenCalled(); expect(dispatch).not.toHaveBeenCalled(); - expect(Flash).toHaveBeenCalledWith(`${TEST_ERROR_MESSAGE}.`, 'alert', flashContainer); + expect(Flash).toHaveBeenCalledWith(TEST_ERROR_MESSAGE, 'alert', flashContainer); + }); + }); + + it('when service fails, and no error message available, uses default message', done => { + const response = { response: 'foo' }; + + Api.applySuggestion.mockReturnValue(Promise.reject(response)); + + testSubmitSuggestion(done, () => { + expect(commit).not.toHaveBeenCalled(); + expect(dispatch).not.toHaveBeenCalled(); + expect(Flash).toHaveBeenCalledWith( + 'Something went wrong while applying the suggestion. Please try again.', + 'alert', + flashContainer, + ); }); }); @@ -903,6 +920,130 @@ describe('Actions Notes Store', () => { }); }); + describe('submitSuggestionBatch', () => { + const discussionIds = batchSuggestionsInfoMock.map(({ discussionId }) => discussionId); + const batchSuggestionsInfo = batchSuggestionsInfoMock; + + let flashContainer; + + beforeEach(() => { + jest.spyOn(Api, 'applySuggestionBatch'); + dispatch.mockReturnValue(Promise.resolve()); + Api.applySuggestionBatch.mockReturnValue(Promise.resolve()); + state = { batchSuggestionsInfo }; + flashContainer = {}; + }); + + const testSubmitSuggestionBatch = (done, expectFn) => { + actions + .submitSuggestionBatch({ commit, dispatch, state }, { flashContainer }) + .then(expectFn) + .then(done) + .catch(done.fail); + }; + + it('when service succeeds, commits, resolves discussions, resets batch and applying batch state', done => { + testSubmitSuggestionBatch(done, () => { + expect(commit.mock.calls).toEqual([ + [mutationTypes.SET_APPLYING_BATCH_STATE, true], + [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]], + [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]], + [mutationTypes.CLEAR_SUGGESTION_BATCH], + [mutationTypes.SET_APPLYING_BATCH_STATE, false], + ]); + + expect(dispatch.mock.calls).toEqual([ + ['resolveDiscussion', { discussionId: discussionIds[0] }], + ['resolveDiscussion', { discussionId: discussionIds[1] }], + ]); + + expect(Flash).not.toHaveBeenCalled(); + }); + }); + + it('when service fails, flashes error message, resets applying batch state', done => { + const response = { response: { data: { message: TEST_ERROR_MESSAGE } } }; + + Api.applySuggestionBatch.mockReturnValue(Promise.reject(response)); + + testSubmitSuggestionBatch(done, () => { + expect(commit.mock.calls).toEqual([ + [mutationTypes.SET_APPLYING_BATCH_STATE, true], + [mutationTypes.SET_APPLYING_BATCH_STATE, false], + ]); + + expect(dispatch).not.toHaveBeenCalled(); + expect(Flash).toHaveBeenCalledWith(TEST_ERROR_MESSAGE, 'alert', flashContainer); + }); + }); + + it('when service fails, and no error message available, uses default message', done => { + const response = { response: 'foo' }; + + Api.applySuggestionBatch.mockReturnValue(Promise.reject(response)); + + testSubmitSuggestionBatch(done, () => { + expect(commit.mock.calls).toEqual([ + [mutationTypes.SET_APPLYING_BATCH_STATE, true], + [mutationTypes.SET_APPLYING_BATCH_STATE, false], + ]); + + expect(dispatch).not.toHaveBeenCalled(); + expect(Flash).toHaveBeenCalledWith( + 'Something went wrong while applying the batch of suggestions. Please try again.', + 'alert', + flashContainer, + ); + }); + }); + + it('when resolve discussions fails, fails gracefully, resets batch and applying batch state', done => { + dispatch.mockReturnValue(Promise.reject()); + + testSubmitSuggestionBatch(done, () => { + expect(commit.mock.calls).toEqual([ + [mutationTypes.SET_APPLYING_BATCH_STATE, true], + [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]], + [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]], + [mutationTypes.CLEAR_SUGGESTION_BATCH], + [mutationTypes.SET_APPLYING_BATCH_STATE, false], + ]); + + expect(Flash).not.toHaveBeenCalled(); + }); + }); + }); + + describe('addSuggestionInfoToBatch', () => { + const suggestionInfo = batchSuggestionsInfoMock[0]; + + it("adds a suggestion's info to the current batch", done => { + testAction( + actions.addSuggestionInfoToBatch, + suggestionInfo, + { batchSuggestionsInfo: [] }, + [{ type: 'ADD_SUGGESTION_TO_BATCH', payload: suggestionInfo }], + [], + done, + ); + }); + }); + + describe('removeSuggestionInfoFromBatch', () => { + const suggestionInfo = batchSuggestionsInfoMock[0]; + + it("removes a suggestion's info the current batch", done => { + testAction( + actions.removeSuggestionInfoFromBatch, + suggestionInfo.suggestionId, + { batchSuggestionsInfo: [suggestionInfo] }, + [{ type: 'REMOVE_SUGGESTION_FROM_BATCH', payload: suggestionInfo.suggestionId }], + [], + done, + ); + }); + }); + describe('filterDiscussion', () => { const path = 'some-discussion-path'; const filter = 0; @@ -942,4 +1083,75 @@ describe('Actions Notes Store', () => { ); }); }); + + describe('softDeleteDescriptionVersion', () => { + const endpoint = '/path/to/diff/1'; + const payload = { + endpoint, + startingVersion: undefined, + versionId: 1, + }; + + describe('if response contains no errors', () => { + it('dispatches requestDeleteDescriptionVersion', done => { + axiosMock.onDelete(endpoint).replyOnce(200); + testAction( + actions.softDeleteDescriptionVersion, + payload, + {}, + [], + [ + { + type: 'requestDeleteDescriptionVersion', + }, + { + type: 'receiveDeleteDescriptionVersion', + payload: payload.versionId, + }, + ], + done, + ); + }); + }); + + describe('if response contains errors', () => { + const errorMessage = 'Request failed with status code 503'; + it('dispatches receiveDeleteDescriptionVersionError and throws an error', done => { + axiosMock.onDelete(endpoint).replyOnce(503); + testAction( + actions.softDeleteDescriptionVersion, + payload, + {}, + [], + [ + { + type: 'requestDeleteDescriptionVersion', + }, + { + type: 'receiveDeleteDescriptionVersionError', + payload: new Error(errorMessage), + }, + ], + ) + .then(() => done.fail('Expected error to be thrown')) + .catch(() => { + expect(Flash).toHaveBeenCalled(); + done(); + }); + }); + }); + }); + + describe('updateAssignees', () => { + it('update the assignees state', done => { + testAction( + actions.updateAssignees, + [userDataMock.id], + { state: noteableDataMock }, + [{ type: mutationTypes.UPDATE_ASSIGNEES, payload: [userDataMock.id] }], + [], + done, + ); + }); + }); }); diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js index 27e3490d64b..75ef007b78d 100644 --- a/spec/frontend/notes/stores/mutation_spec.js +++ b/spec/frontend/notes/stores/mutation_spec.js @@ -9,6 +9,7 @@ import { noteableDataMock, individualNote, notesWithDescriptionChanges, + batchSuggestionsInfoMock, } from '../mock_data'; const RESOLVED_NOTE = { resolvable: true, resolved: true }; @@ -700,4 +701,120 @@ describe('Notes Store mutations', () => { expect(state.isToggleBlockedIssueWarning).toEqual(false); }); }); + + describe('SET_APPLYING_BATCH_STATE', () => { + const buildDiscussions = suggestionsInfo => { + const suggestions = suggestionsInfo.map(({ suggestionId }) => ({ id: suggestionId })); + + const notes = suggestionsInfo.map(({ noteId }, index) => ({ + id: noteId, + suggestions: [suggestions[index]], + })); + + return suggestionsInfo.map(({ discussionId }, index) => ({ + id: discussionId, + notes: [notes[index]], + })); + }; + + let state; + let batchedSuggestionInfo; + let discussions; + let suggestions; + + beforeEach(() => { + [batchedSuggestionInfo] = batchSuggestionsInfoMock; + suggestions = batchSuggestionsInfoMock.map(({ suggestionId }) => ({ id: suggestionId })); + discussions = buildDiscussions(batchSuggestionsInfoMock); + state = { + batchSuggestionsInfo: [batchedSuggestionInfo], + discussions, + }; + }); + + it('sets is_applying_batch to a boolean value for all batched suggestions', () => { + mutations.SET_APPLYING_BATCH_STATE(state, true); + + const updatedSuggestion = { + ...suggestions[0], + is_applying_batch: true, + }; + + const expectedSuggestions = [updatedSuggestion, suggestions[1]]; + + const actualSuggestions = state.discussions + .map(discussion => discussion.notes.map(n => n.suggestions)) + .flat(2); + + expect(actualSuggestions).toEqual(expectedSuggestions); + }); + }); + + describe('ADD_SUGGESTION_TO_BATCH', () => { + let state; + + beforeEach(() => { + state = { batchSuggestionsInfo: [] }; + }); + + it("adds a suggestion's info to a batch", () => { + const suggestionInfo = { + suggestionId: 'a123', + noteId: 'b456', + discussionId: 'c789', + }; + + mutations.ADD_SUGGESTION_TO_BATCH(state, suggestionInfo); + + expect(state.batchSuggestionsInfo).toEqual([suggestionInfo]); + }); + }); + + describe('REMOVE_SUGGESTION_FROM_BATCH', () => { + let state; + let suggestionInfo1; + let suggestionInfo2; + + beforeEach(() => { + [suggestionInfo1, suggestionInfo2] = batchSuggestionsInfoMock; + + state = { + batchSuggestionsInfo: [suggestionInfo1, suggestionInfo2], + }; + }); + + it("removes a suggestion's info from a batch", () => { + mutations.REMOVE_SUGGESTION_FROM_BATCH(state, suggestionInfo1.suggestionId); + + expect(state.batchSuggestionsInfo).toEqual([suggestionInfo2]); + }); + }); + + describe('CLEAR_SUGGESTION_BATCH', () => { + let state; + + beforeEach(() => { + state = { + batchSuggestionsInfo: batchSuggestionsInfoMock, + }; + }); + + it('removes info for all suggestions from a batch', () => { + mutations.CLEAR_SUGGESTION_BATCH(state); + + expect(state.batchSuggestionsInfo.length).toEqual(0); + }); + }); + + describe('UPDATE_ASSIGNEES', () => { + it('should update assignees', () => { + const state = { + noteableData: noteableDataMock, + }; + + mutations.UPDATE_ASSIGNEES(state, [userDataMock.id]); + + expect(state.noteableData.assignees).toEqual([userDataMock.id]); + }); + }); }); |