diff options
Diffstat (limited to 'spec/frontend/issuable/related_issues/components/related_issues_root_spec.js')
-rw-r--r-- | spec/frontend/issuable/related_issues/components/related_issues_root_spec.js | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js new file mode 100644 index 00000000000..2544d0bd030 --- /dev/null +++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js @@ -0,0 +1,341 @@ +import { mount, shallowMount } from '@vue/test-utils'; +import MockAdapter from 'axios-mock-adapter'; +import waitForPromises from 'helpers/wait_for_promises'; +import { + defaultProps, + issuable1, + issuable2, +} from 'jest/vue_shared/components/issue/related_issuable_mock_data'; +import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue'; +import relatedIssuesService from '~/related_issues/services/related_issues_service'; +import { linkedIssueTypesMap } from '~/related_issues/constants'; +import axios from '~/lib/utils/axios_utils'; +import { deprecatedCreateFlash as createFlash } from '~/flash'; + +jest.mock('~/flash'); + +describe('RelatedIssuesRoot', () => { + let wrapper; + let mock; + + beforeEach(() => { + mock = new MockAdapter(axios); + mock.onGet(defaultProps.endpoint).reply(200, []); + }); + + afterEach(() => { + mock.restore(); + if (wrapper) { + wrapper.destroy(); + wrapper = null; + } + }); + + const createComponent = (mountFn = mount) => { + wrapper = mountFn(RelatedIssuesRoot, { + propsData: defaultProps, + }); + + // Wait for fetch request `fetchRelatedIssues` to complete before starting to test + return waitForPromises(); + }; + + describe('methods', () => { + describe('onRelatedIssueRemoveRequest', () => { + beforeEach(() => { + jest + .spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues') + .mockReturnValue(Promise.reject()); + + return createComponent().then(() => { + wrapper.vm.store.setRelatedIssues([issuable1]); + }); + }); + + it('remove related issue and succeeds', () => { + mock.onDelete(issuable1.referencePath).reply(200, { issues: [] }); + + wrapper.vm.onRelatedIssueRemoveRequest(issuable1.id); + + return axios.waitForAll().then(() => { + expect(wrapper.vm.state.relatedIssues).toEqual([]); + }); + }); + + it('remove related issue, fails, and restores to related issues', () => { + mock.onDelete(issuable1.referencePath).reply(422, {}); + + wrapper.vm.onRelatedIssueRemoveRequest(issuable1.id); + + return axios.waitForAll().then(() => { + expect(wrapper.vm.state.relatedIssues).toHaveLength(1); + expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); + }); + }); + }); + + describe('onToggleAddRelatedIssuesForm', () => { + beforeEach(() => createComponent(shallowMount)); + + it('toggle related issues form to visible', () => { + wrapper.vm.onToggleAddRelatedIssuesForm(); + + expect(wrapper.vm.isFormVisible).toEqual(true); + }); + + it('show add related issues form to hidden', () => { + wrapper.vm.isFormVisible = true; + + wrapper.vm.onToggleAddRelatedIssuesForm(); + + expect(wrapper.vm.isFormVisible).toEqual(false); + }); + }); + + describe('onPendingIssueRemoveRequest', () => { + beforeEach(() => + createComponent().then(() => { + wrapper.vm.store.setPendingReferences([issuable1.reference]); + }), + ); + + it('remove pending related issue', () => { + expect(wrapper.vm.state.pendingReferences).toHaveLength(1); + + wrapper.vm.onPendingIssueRemoveRequest(0); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(0); + }); + }); + + describe('onPendingFormSubmit', () => { + beforeEach(() => { + jest + .spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues') + .mockReturnValue(Promise.reject()); + + return createComponent().then(() => { + jest.spyOn(wrapper.vm, 'processAllReferences'); + jest.spyOn(wrapper.vm.service, 'addRelatedIssues'); + createFlash.mockClear(); + }); + }); + + it('processes references before submitting', () => { + const input = '#123'; + const linkedIssueType = linkedIssueTypesMap.RELATES_TO; + const emitObj = { + pendingReferences: input, + linkedIssueType, + }; + + wrapper.vm.onPendingFormSubmit(emitObj); + + expect(wrapper.vm.processAllReferences).toHaveBeenCalledWith(input); + expect(wrapper.vm.service.addRelatedIssues).toHaveBeenCalledWith([input], linkedIssueType); + }); + + it('submit zero pending issue as related issue', () => { + wrapper.vm.store.setPendingReferences([]); + wrapper.vm.onPendingFormSubmit({}); + + return waitForPromises().then(() => { + expect(wrapper.vm.state.pendingReferences).toHaveLength(0); + expect(wrapper.vm.state.relatedIssues).toHaveLength(0); + }); + }); + + it('submit pending issue as related issue', () => { + mock.onPost(defaultProps.endpoint).reply(200, { + issuables: [issuable1], + result: { + message: 'something was successfully related', + status: 'success', + }, + }); + + wrapper.vm.store.setPendingReferences([issuable1.reference]); + wrapper.vm.onPendingFormSubmit({}); + + return waitForPromises().then(() => { + expect(wrapper.vm.state.pendingReferences).toHaveLength(0); + expect(wrapper.vm.state.relatedIssues).toHaveLength(1); + expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); + }); + }); + + it('submit multiple pending issues as related issues', () => { + mock.onPost(defaultProps.endpoint).reply(200, { + issuables: [issuable1, issuable2], + result: { + message: 'something was successfully related', + status: 'success', + }, + }); + + wrapper.vm.store.setPendingReferences([issuable1.reference, issuable2.reference]); + wrapper.vm.onPendingFormSubmit({}); + + return waitForPromises().then(() => { + expect(wrapper.vm.state.pendingReferences).toHaveLength(0); + expect(wrapper.vm.state.relatedIssues).toHaveLength(2); + expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); + expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id); + }); + }); + + it('displays a message from the backend upon error', () => { + const input = '#123'; + const message = 'error'; + + mock.onPost(defaultProps.endpoint).reply(409, { message }); + wrapper.vm.store.setPendingReferences([issuable1.reference, issuable2.reference]); + + expect(createFlash).not.toHaveBeenCalled(); + wrapper.vm.onPendingFormSubmit(input); + + return waitForPromises().then(() => { + expect(createFlash).toHaveBeenCalledWith(message); + }); + }); + }); + + describe('onPendingFormCancel', () => { + beforeEach(() => + createComponent().then(() => { + wrapper.vm.isFormVisible = true; + wrapper.vm.inputValue = 'foo'; + }), + ); + + it('when canceling and hiding add issuable form', () => { + wrapper.vm.onPendingFormCancel(); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.vm.isFormVisible).toEqual(false); + expect(wrapper.vm.inputValue).toEqual(''); + expect(wrapper.vm.state.pendingReferences).toHaveLength(0); + }); + }); + }); + + describe('fetchRelatedIssues', () => { + beforeEach(() => createComponent()); + + it('sets isFetching while fetching', () => { + wrapper.vm.fetchRelatedIssues(); + + expect(wrapper.vm.isFetching).toEqual(true); + + return waitForPromises().then(() => { + expect(wrapper.vm.isFetching).toEqual(false); + }); + }); + + it('should fetch related issues', () => { + mock.onGet(defaultProps.endpoint).reply(200, [issuable1, issuable2]); + + wrapper.vm.fetchRelatedIssues(); + + return waitForPromises().then(() => { + expect(wrapper.vm.state.relatedIssues).toHaveLength(2); + expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); + expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id); + }); + }); + }); + + describe('onInput', () => { + beforeEach(() => createComponent()); + + it('fill in issue number reference and adds to pending related issues', () => { + const input = '#123 '; + wrapper.vm.onInput({ + untouchedRawReferences: [input.trim()], + touchedReference: input, + }); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(1); + expect(wrapper.vm.state.pendingReferences[0]).toEqual('#123'); + }); + + it('fill in with full reference', () => { + const input = 'asdf/qwer#444 '; + wrapper.vm.onInput({ untouchedRawReferences: [input.trim()], touchedReference: input }); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(1); + expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf/qwer#444'); + }); + + it('fill in with issue link', () => { + const link = 'http://localhost:3000/foo/bar/issues/111'; + const input = `${link} `; + wrapper.vm.onInput({ untouchedRawReferences: [input.trim()], touchedReference: input }); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(1); + expect(wrapper.vm.state.pendingReferences[0]).toEqual(link); + }); + + it('fill in with multiple references', () => { + const input = 'asdf/qwer#444 #12 '; + wrapper.vm.onInput({ + untouchedRawReferences: input.trim().split(/\s/), + touchedReference: 2, + }); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(2); + expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf/qwer#444'); + expect(wrapper.vm.state.pendingReferences[1]).toEqual('#12'); + }); + + it('fill in with some invalid things', () => { + const input = 'something random '; + wrapper.vm.onInput({ + untouchedRawReferences: input.trim().split(/\s/), + touchedReference: 2, + }); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(2); + expect(wrapper.vm.state.pendingReferences[0]).toEqual('something'); + expect(wrapper.vm.state.pendingReferences[1]).toEqual('random'); + }); + }); + + describe('onBlur', () => { + beforeEach(() => + createComponent().then(() => { + jest.spyOn(wrapper.vm, 'processAllReferences').mockImplementation(() => {}); + }), + ); + + it('add any references to pending when blurring', () => { + const input = '#123'; + + wrapper.vm.onBlur(input); + + expect(wrapper.vm.processAllReferences).toHaveBeenCalledWith(input); + }); + }); + + describe('processAllReferences', () => { + beforeEach(() => createComponent()); + + it('add valid reference to pending', () => { + const input = '#123'; + wrapper.vm.processAllReferences(input); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(1); + expect(wrapper.vm.state.pendingReferences[0]).toEqual('#123'); + }); + + it('add any valid references to pending', () => { + const input = 'asdf #123'; + wrapper.vm.processAllReferences(input); + + expect(wrapper.vm.state.pendingReferences).toHaveLength(2); + expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf'); + expect(wrapper.vm.state.pendingReferences[1]).toEqual('#123'); + }); + }); + }); +}); |