diff options
Diffstat (limited to 'spec/javascripts/notes')
7 files changed, 176 insertions, 50 deletions
diff --git a/spec/javascripts/notes/components/comment_form_spec.js b/spec/javascripts/notes/components/comment_form_spec.js index 362963ddaf4..88c86746992 100644 --- a/spec/javascripts/notes/components/comment_form_spec.js +++ b/spec/javascripts/notes/components/comment_form_spec.js @@ -251,6 +251,21 @@ describe('issue_comment_form component', () => { }); }); }); + + describe('when toggling state', () => { + it('should update MR count', done => { + spyOn(vm, 'closeIssue').and.returnValue(Promise.resolve()); + + const updateMrCountSpy = spyOnDependency(CommentForm, 'refreshUserMergeRequestCounts'); + vm.toggleIssueState(); + + Vue.nextTick(() => { + expect(updateMrCountSpy).toHaveBeenCalled(); + + done(); + }); + }); + }); }); describe('issue is confidential', () => { diff --git a/spec/javascripts/notes/components/diff_with_note_spec.js b/spec/javascripts/notes/components/diff_with_note_spec.js index 0752bd05904..f849fe9d8bb 100644 --- a/spec/javascripts/notes/components/diff_with_note_spec.js +++ b/spec/javascripts/notes/components/diff_with_note_spec.js @@ -47,6 +47,19 @@ describe('diff_with_note', () => { vm = mountComponentWithStore(Component, { props, store }); }); + it('removes trailing "+" char', () => { + const richText = vm.$el.querySelectorAll('.line_holder')[4].querySelector('.line_content') + .textContent[0]; + + expect(richText).not.toEqual('+'); + }); + + it('removes trailing "-" char', () => { + const richText = vm.$el.querySelector('#LC13').parentNode.textContent[0]; + + expect(richText).not.toEqual('-'); + }); + it('shows text diff', () => { expect(selectors.container).toHaveClass('text-file'); expect(selectors.diffTable).toExist(); diff --git a/spec/javascripts/notes/components/note_actions/reply_button_spec.js b/spec/javascripts/notes/components/note_actions/reply_button_spec.js index 11fb89808d9..003773d07ea 100644 --- a/spec/javascripts/notes/components/note_actions/reply_button_spec.js +++ b/spec/javascripts/notes/components/note_actions/reply_button_spec.js @@ -25,8 +25,7 @@ describe('ReplyButton', () => { button.trigger('click'); - expect(wrapper.emitted()).toEqual({ - startReplying: [[]], - }); + expect(wrapper.emitted().startReplying).toBeTruthy(); + expect(wrapper.emitted().startReplying.length).toBe(1); }); }); diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js index efa864e7d00..74805ca8c00 100644 --- a/spec/javascripts/notes/components/noteable_discussion_spec.js +++ b/spec/javascripts/notes/components/noteable_discussion_spec.js @@ -36,14 +36,20 @@ describe('noteable_discussion component', () => { }); it('should render user avatar', () => { + const discussion = { ...discussionMock }; + discussion.diff_file = mockDiffFile; + discussion.diff_discussion = true; + + wrapper.setProps({ discussion, renderDiffFile: true }); + expect(wrapper.find('.user-avatar-link').exists()).toBe(true); }); - it('should not render discussion header for non diff discussions', () => { + it('should not render thread header for non diff threads', () => { expect(wrapper.find('.discussion-header').exists()).toBe(false); }); - it('should render discussion header', done => { + it('should render thread header', done => { const discussion = { ...discussionMock }; discussion.diff_file = mockDiffFile; discussion.diff_discussion = true; @@ -90,16 +96,16 @@ describe('noteable_discussion component', () => { .catch(done.fail); }); - it('does not render jump to discussion button', () => { - expect( - wrapper.find('*[data-original-title="Jump to next unresolved discussion"]').exists(), - ).toBe(false); + it('does not render jump to thread button', () => { + expect(wrapper.find('*[data-original-title="Jump to next unresolved thread"]').exists()).toBe( + false, + ); }); }); describe('methods', () => { describe('jumpToNextDiscussion', () => { - it('expands next unresolved discussion', done => { + it('expands next unresolved thread', done => { const discussion2 = getJSONFixture(discussionWithTwoUnresolvedNotes)[0]; discussion2.resolved = false; discussion2.active = true; @@ -114,9 +120,7 @@ describe('noteable_discussion component', () => { const nextDiscussionId = discussion2.id; - setFixtures(` - <div class="discussion" data-discussion-id="${nextDiscussionId}"></div> - `); + setFixtures(`<div class="discussion" data-discussion-id="${nextDiscussionId}"></div>`); wrapper.vm.jumpToNextDiscussion(); @@ -162,20 +166,20 @@ describe('noteable_discussion component', () => { .catch(done.fail); }); - describe('for commit discussions', () => { - it('should display a monospace started a discussion on commit', () => { - expect(wrapper.text()).toContain(`started a discussion on commit ${truncatedCommitId}`); + describe('for commit threads', () => { + it('should display a monospace started a thread on commit', () => { + expect(wrapper.text()).toContain(`started a thread on commit ${truncatedCommitId}`); expect(commitElement.exists()).toBe(true); expect(commitElement.text()).toContain(truncatedCommitId); }); }); - describe('for diff discussion with a commit id', () => { - it('should display started discussion on commit header', done => { + describe('for diff thread with a commit id', () => { + it('should display started thread on commit header', done => { wrapper.vm.discussion.for_commit = false; wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain(`started a discussion on commit ${truncatedCommitId}`); + expect(wrapper.text()).toContain(`started a thread on commit ${truncatedCommitId}`); expect(commitElement).not.toBe(null); @@ -189,7 +193,7 @@ describe('noteable_discussion component', () => { wrapper.vm.$nextTick(() => { expect(wrapper.text()).toContain( - `started a discussion on an outdated change in commit ${truncatedCommitId}`, + `started a thread on an outdated change in commit ${truncatedCommitId}`, ); expect(commitElement).not.toBe(null); @@ -199,21 +203,21 @@ describe('noteable_discussion component', () => { }); }); - describe('for diff discussions without a commit id', () => { - it('should show started a discussion on the diff text', done => { + describe('for diff threads without a commit id', () => { + it('should show started a thread on the diff text', done => { Object.assign(wrapper.vm.discussion, { for_commit: false, commit_id: null, }); wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain('started a discussion on the diff'); + expect(wrapper.text()).toContain('started a thread on the diff'); done(); }); }); - it('should show discussion on older version text', done => { + it('should show thread on older version text', done => { Object.assign(wrapper.vm.discussion, { for_commit: false, commit_id: null, @@ -221,7 +225,7 @@ describe('noteable_discussion component', () => { }); wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain('started a discussion on an old version of the diff'); + expect(wrapper.text()).toContain('started a thread on an old version of the diff'); done(); }); @@ -229,7 +233,7 @@ describe('noteable_discussion component', () => { }); }); - describe('for resolved discussion', () => { + describe('for resolved thread', () => { beforeEach(() => { const discussion = getJSONFixture(discussionWithTwoUnresolvedNotes)[0]; wrapper.setProps({ discussion }); @@ -242,7 +246,7 @@ describe('noteable_discussion component', () => { }); }); - describe('for unresolved discussion', () => { + describe('for unresolved thread', () => { beforeEach(done => { const discussion = { ...getJSONFixture(discussionWithTwoUnresolvedNotes)[0], diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js index 1df5cf9ef68..5f81a168498 100644 --- a/spec/javascripts/notes/mock_data.js +++ b/spec/javascripts/notes/mock_data.js @@ -1,3 +1,5 @@ +// Copied to ee/spec/frontend/notes/mock_data.js + export const notesDataMock = { discussionsPath: '/gitlab-org/gitlab-ce/issues/26/discussions.json', lastFetchedAt: 1501862675, diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js index 7a9f32ddcff..e55aa0e965a 100644 --- a/spec/javascripts/notes/stores/actions_spec.js +++ b/spec/javascripts/notes/stores/actions_spec.js @@ -1,6 +1,7 @@ import Vue from 'vue'; import $ from 'jquery'; import _ from 'underscore'; +import Api from '~/api'; import { TEST_HOST } from 'spec/test_constants'; import { headersInterceptor } from 'spec/helpers/vue_resource_helper'; import actionsModule, * as actions from '~/notes/stores/actions'; @@ -8,7 +9,6 @@ import * as mutationTypes from '~/notes/stores/mutation_types'; import * as notesConstants from '~/notes/constants'; import createStore from '~/notes/stores'; import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub'; -import service from '~/notes/services/notes_service'; import testAction from '../../helpers/vuex_action_helper'; import { resetStore } from '../helpers'; import { @@ -18,6 +18,8 @@ import { noteableDataMock, individualNote, } from '../mock_data'; +import AxiosMockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; const TEST_ERROR_MESSAGE = 'Test error message'; @@ -335,28 +337,24 @@ describe('Actions Notes Store', () => { }); describe('deleteNote', () => { - const interceptor = (request, next) => { - next( - request.respondWith(JSON.stringify({}), { - status: 200, - }), - ); - }; + const endpoint = `${TEST_HOST}/note`; + let axiosMock; beforeEach(() => { - Vue.http.interceptors.push(interceptor); + axiosMock = new AxiosMockAdapter(axios); + axiosMock.onDelete(endpoint).replyOnce(200, {}); $('body').attr('data-page', ''); }); afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); + axiosMock.restore(); $('body').attr('data-page', ''); }); it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', done => { - const note = { path: `${gl.TEST_HOST}`, id: 1 }; + const note = { path: endpoint, id: 1 }; testAction( actions.deleteNote, @@ -373,7 +371,7 @@ describe('Actions Notes Store', () => { type: 'updateMergeRequestWidget', }, { - type: 'updateResolvableDiscussonsCounts', + type: 'updateResolvableDiscussionsCounts', }, ], done, @@ -381,7 +379,7 @@ describe('Actions Notes Store', () => { }); it('dispatches removeDiscussionsFromDiff on merge request page', done => { - const note = { path: `${gl.TEST_HOST}`, id: 1 }; + const note = { path: endpoint, id: 1 }; $('body').attr('data-page', 'projects:merge_requests:show'); @@ -400,7 +398,7 @@ describe('Actions Notes Store', () => { type: 'updateMergeRequestWidget', }, { - type: 'updateResolvableDiscussonsCounts', + type: 'updateResolvableDiscussionsCounts', }, { type: 'diffs/removeDiscussionsFromDiff', @@ -452,7 +450,7 @@ describe('Actions Notes Store', () => { type: 'startTaskList', }, { - type: 'updateResolvableDiscussonsCounts', + type: 'updateResolvableDiscussionsCounts', }, ], done, @@ -527,7 +525,7 @@ describe('Actions Notes Store', () => { ], [ { - type: 'updateResolvableDiscussonsCounts', + type: 'updateResolvableDiscussionsCounts', }, { type: 'updateMergeRequestWidget', @@ -552,7 +550,7 @@ describe('Actions Notes Store', () => { ], [ { - type: 'updateResolvableDiscussonsCounts', + type: 'updateResolvableDiscussionsCounts', }, { type: 'updateMergeRequestWidget', @@ -587,10 +585,10 @@ describe('Actions Notes Store', () => { }); }); - describe('updateResolvableDiscussonsCounts', () => { + describe('updateResolvableDiscussionsCounts', () => { it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', done => { testAction( - actions.updateResolvableDiscussonsCounts, + actions.updateResolvableDiscussionsCounts, null, {}, [{ type: 'UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS' }], @@ -712,7 +710,7 @@ describe('Actions Notes Store', () => { [ { type: 'updateMergeRequestWidget' }, { type: 'startTaskList' }, - { type: 'updateResolvableDiscussonsCounts' }, + { type: 'updateResolvableDiscussionsCounts' }, ], done, ); @@ -846,9 +844,9 @@ describe('Actions Notes Store', () => { let flashContainer; beforeEach(() => { - spyOn(service, 'applySuggestion'); + spyOn(Api, 'applySuggestion'); dispatch.and.returnValue(Promise.resolve()); - service.applySuggestion.and.returnValue(Promise.resolve()); + Api.applySuggestion.and.returnValue(Promise.resolve()); flashContainer = {}; }); @@ -877,7 +875,7 @@ describe('Actions Notes Store', () => { it('when service fails, flashes error message', done => { const response = { response: { data: { message: TEST_ERROR_MESSAGE } } }; - service.applySuggestion.and.returnValue(Promise.reject(response)); + Api.applySuggestion.and.returnValue(Promise.reject(response)); testSubmitSuggestion(done, () => { expect(commit).not.toHaveBeenCalled(); @@ -894,4 +892,31 @@ describe('Actions Notes Store', () => { }); }); }); + + describe('filterDiscussion', () => { + const path = 'some-discussion-path'; + const filter = 0; + + beforeEach(() => { + dispatch.and.returnValue(new Promise(() => {})); + }); + + it('fetches discussions with filter and persistFilter false', () => { + actions.filterDiscussion({ dispatch }, { path, filter, persistFilter: false }); + + expect(dispatch.calls.allArgs()).toEqual([ + ['setLoadingState', true], + ['fetchDiscussions', { path, filter, persistFilter: false }], + ]); + }); + + it('fetches discussions with filter and persistFilter true', () => { + actions.filterDiscussion({ dispatch }, { path, filter, persistFilter: true }); + + expect(dispatch.calls.allArgs()).toEqual([ + ['setLoadingState', true], + ['fetchDiscussions', { path, filter, persistFilter: true }], + ]); + }); + }); }); diff --git a/spec/javascripts/notes/stores/getters_spec.js b/spec/javascripts/notes/stores/getters_spec.js index 8f3c493dd4c..71dcba114a9 100644 --- a/spec/javascripts/notes/stores/getters_spec.js +++ b/spec/javascripts/notes/stores/getters_spec.js @@ -32,6 +32,26 @@ describe('Getters Notes Store', () => { }; }); + describe('showJumpToNextDiscussion', () => { + it('should return true if there are 2 or more unresolved discussions', () => { + const localGetters = { + unresolvedDiscussionsIdsByDate: ['123', '456'], + allResolvableDiscussions: [], + }; + + expect(getters.showJumpToNextDiscussion(state, localGetters)()).toBe(true); + }); + + it('should return false if there are 1 or less unresolved discussions', () => { + const localGetters = { + unresolvedDiscussionsIdsByDate: ['123'], + allResolvableDiscussions: [], + }; + + expect(getters.showJumpToNextDiscussion(state, localGetters)()).toBe(false); + }); + }); + describe('discussions', () => { it('should return all discussions in the store', () => { expect(getters.discussions(state)).toEqual([individualNote]); @@ -236,6 +256,54 @@ describe('Getters Notes Store', () => { }); }); + describe('previousUnresolvedDiscussionId', () => { + describe('with unresolved discussions', () => { + const localGetters = { + unresolvedDiscussionsIdsOrdered: () => ['123', '456', '789'], + }; + + it('with bogus returns falsey', () => { + expect(getters.previousUnresolvedDiscussionId(state, localGetters)('bogus')).toBe('456'); + }); + + [ + { id: '123', expected: '789' }, + { id: '456', expected: '123' }, + { id: '789', expected: '456' }, + ].forEach(({ id, expected }) => { + it(`with ${id}, returns previous value`, () => { + expect(getters.previousUnresolvedDiscussionId(state, localGetters)(id)).toBe(expected); + }); + }); + }); + + describe('with 1 unresolved discussion', () => { + const localGetters = { + unresolvedDiscussionsIdsOrdered: () => ['123'], + }; + + it('with bogus returns id', () => { + expect(getters.previousUnresolvedDiscussionId(state, localGetters)('bogus')).toBe('123'); + }); + + it('with match, returns value', () => { + expect(getters.previousUnresolvedDiscussionId(state, localGetters)('123')).toEqual('123'); + }); + }); + + describe('with 0 unresolved discussions', () => { + const localGetters = { + unresolvedDiscussionsIdsOrdered: () => [], + }; + + it('returns undefined', () => { + expect( + getters.previousUnresolvedDiscussionId(state, localGetters)('bogus'), + ).toBeUndefined(); + }); + }); + }); + describe('firstUnresolvedDiscussionId', () => { const localGetters = { unresolvedDiscussionsIdsByDate: ['123', '456'], |
