diff options
Diffstat (limited to 'spec/frontend/projects/settings_service_desk')
3 files changed, 186 insertions, 351 deletions
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js index c83b1852147..f9fbb1b3016 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js @@ -1,20 +1,36 @@ -import { mount } from '@vue/test-utils'; +import { GlAlert } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; import waitForPromises from 'helpers/wait_for_promises'; -import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue'; -import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue'; import axios from '~/lib/utils/axios_utils'; import httpStatusCodes from '~/lib/utils/http_status'; +import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue'; +import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue'; describe('ServiceDeskRoot', () => { - const endpoint = '/gitlab-org/gitlab-test/service_desk'; - const initialIncomingEmail = 'servicedeskaddress@example.com'; let axiosMock; let wrapper; let spy; + const provideData = { + customEmail: 'custom.email@example.com', + customEmailEnabled: true, + endpoint: '/gitlab-org/gitlab-test/service_desk', + initialIncomingEmail: 'servicedeskaddress@example.com', + initialIsEnabled: true, + outgoingName: 'GitLab Support Bot', + projectKey: 'key', + selectedTemplate: 'Bug', + templates: ['Bug', 'Documentation'], + }; + + const getAlertText = () => wrapper.find(GlAlert).text(); + + const createComponent = () => shallowMount(ServiceDeskRoot, { provide: provideData }); + beforeEach(() => { axiosMock = new AxiosMockAdapter(axios); + spy = jest.spyOn(axios, 'put'); }); afterEach(() => { @@ -25,156 +41,122 @@ describe('ServiceDeskRoot', () => { } }); - it('sends a request to toggle service desk off when the toggle is clicked from the on state', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK); + describe('ServiceDeskSetting component', () => { + it('is rendered', () => { + wrapper = createComponent(); + + expect(wrapper.find(ServiceDeskSetting).props()).toEqual({ + customEmail: provideData.customEmail, + customEmailEnabled: provideData.customEmailEnabled, + incomingEmail: provideData.initialIncomingEmail, + initialOutgoingName: provideData.outgoingName, + initialProjectKey: provideData.projectKey, + initialSelectedTemplate: provideData.selectedTemplate, + isEnabled: provideData.initialIsEnabled, + isTemplateSaving: false, + templates: provideData.templates, + }); + }); + + describe('toggle event', () => { + describe('when toggling service desk on', () => { + beforeEach(async () => { + wrapper = createComponent(); - spy = jest.spyOn(axios, 'put'); + wrapper.find(ServiceDeskSetting).vm.$emit('toggle', true); - wrapper = mount(ServiceDeskRoot, { - propsData: { - initialIsEnabled: true, - initialIncomingEmail, - endpoint, - }, - }); + await waitForPromises(); + }); + + it('sends a request to turn service desk on', () => { + axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK); - wrapper.find('button.gl-toggle').trigger('click'); + expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: true }); + }); - return wrapper.vm - .$nextTick() - .then(waitForPromises) - .then(() => { - expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: false }); + it('shows a message when there is an error', () => { + axiosMock.onPut(provideData.endpoint).networkError(); + + expect(getAlertText()).toContain('An error occurred while enabling Service Desk.'); + }); }); - }); - it('sends a request to toggle service desk on when the toggle is clicked from the off state', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK); + describe('when toggling service desk off', () => { + beforeEach(async () => { + wrapper = createComponent(); - spy = jest.spyOn(axios, 'put'); + wrapper.find(ServiceDeskSetting).vm.$emit('toggle', false); - wrapper = mount(ServiceDeskRoot, { - propsData: { - initialIsEnabled: false, - initialIncomingEmail: '', - endpoint, - }, - }); + await waitForPromises(); + }); - wrapper.find('button.gl-toggle').trigger('click'); + it('sends a request to turn service desk off', () => { + axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK); - return wrapper.vm.$nextTick(() => { - expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: true }); - }); - }); + expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: false }); + }); - it('shows an error message when there is an issue toggling service desk on', () => { - axiosMock.onPut(endpoint).networkError(); + it('shows a message when there is an error', () => { + axiosMock.onPut(provideData.endpoint).networkError(); - wrapper = mount(ServiceDeskRoot, { - propsData: { - initialIsEnabled: false, - initialIncomingEmail: '', - endpoint, - }, + expect(getAlertText()).toContain('An error occurred while disabling Service Desk.'); + }); + }); }); - wrapper.find('button.gl-toggle').trigger('click'); + describe('save event', () => { + describe('successful request', () => { + beforeEach(async () => { + axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK); - return wrapper.vm - .$nextTick() - .then(waitForPromises) - .then(() => { - expect(wrapper.html()).toContain('An error occurred while enabling Service Desk.'); - }); - }); + wrapper = createComponent(); - it('sends a request to update template when the "Save template" button is clicked', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK); + const payload = { + selectedTemplate: 'Bug', + outgoingName: 'GitLab Support Bot', + projectKey: 'key', + }; - spy = jest.spyOn(axios, 'put'); + wrapper.find(ServiceDeskSetting).vm.$emit('save', payload); - wrapper = mount(ServiceDeskRoot, { - propsData: { - initialIsEnabled: true, - endpoint, - initialIncomingEmail, - selectedTemplate: 'Bug', - outgoingName: 'GitLab Support Bot', - templates: ['Bug', 'Documentation'], - projectKey: 'key', - }, - }); + await waitForPromises(); + }); - wrapper.find('button.btn-success').trigger('click'); + it('sends a request to update template', async () => { + expect(spy).toHaveBeenCalledWith(provideData.endpoint, { + issue_template_key: 'Bug', + outgoing_name: 'GitLab Support Bot', + project_key: 'key', + service_desk_enabled: true, + }); + }); - return wrapper.vm.$nextTick(() => { - expect(spy).toHaveBeenCalledWith(endpoint, { - issue_template_key: 'Bug', - outgoing_name: 'GitLab Support Bot', - project_key: 'key', - service_desk_enabled: true, + it('shows success message', () => { + expect(getAlertText()).toContain('Changes saved.'); + }); }); - }); - }); - it('saves the template when the "Save template" button is clicked', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK); - - wrapper = mount(ServiceDeskRoot, { - propsData: { - initialIsEnabled: true, - endpoint, - initialIncomingEmail, - selectedTemplate: 'Bug', - templates: ['Bug', 'Documentation'], - }, - }); + describe('unsuccessful request', () => { + beforeEach(async () => { + axiosMock.onPut(provideData.endpoint).networkError(); - wrapper.find('button.btn-success').trigger('click'); + wrapper = createComponent(); - return wrapper.vm - .$nextTick() - .then(waitForPromises) - .then(() => { - expect(wrapper.html()).toContain('Changes saved.'); - }); - }); + const payload = { + selectedTemplate: 'Bug', + outgoingName: 'GitLab Support Bot', + projectKey: 'key', + }; - it('shows an error message when there is an issue saving the template', () => { - axiosMock.onPut(endpoint).networkError(); - - wrapper = mount(ServiceDeskRoot, { - propsData: { - initialIsEnabled: true, - endpoint, - initialIncomingEmail, - selectedTemplate: 'Bug', - templates: ['Bug', 'Documentation'], - }, - }); + wrapper.find(ServiceDeskSetting).vm.$emit('save', payload); - wrapper.find('button.btn-success').trigger('click'); + await waitForPromises(); + }); - return wrapper.vm - .$nextTick() - .then(waitForPromises) - .then(() => { - expect(wrapper.html()).toContain('An error occured while saving changes:'); + it('shows an error message', () => { + expect(getAlertText()).toContain('An error occured while saving changes:'); + }); }); - }); - - it('passes customEmail through updatedCustomEmail correctly', () => { - const customEmail = 'foo'; - - wrapper = mount(ServiceDeskRoot, { - propsData: { - initialIsEnabled: true, - endpoint, - customEmail, - }, }); - - expect(wrapper.find(ServiceDeskSetting).props('customEmail')).toEqual(customEmail); }); }); diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js index ddd9a7b2fad..f6744f4971e 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js @@ -1,63 +1,68 @@ +import { GlButton, GlFormSelect, GlLoadingIcon, GlToggle } from '@gitlab/ui'; import { shallowMount, mount } from '@vue/test-utils'; -import { GlLoadingIcon } from '@gitlab/ui'; -import eventHub from '~/projects/settings_service_desk/event_hub'; +import { nextTick } from 'vue'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue'; +import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; describe('ServiceDeskSetting', () => { let wrapper; + const findButton = () => wrapper.find(GlButton); + const findClipboardButton = () => wrapper.find(ClipboardButton); + const findIncomingEmail = () => wrapper.findByTestId('incoming-email'); + const findIncomingEmailLabel = () => wrapper.findByTestId('incoming-email-describer'); + const findLoadingIcon = () => wrapper.find(GlLoadingIcon); + const findTemplateDropdown = () => wrapper.find(GlFormSelect); + const findToggle = () => wrapper.find(GlToggle); + + const createComponent = ({ props = {}, mountFunction = shallowMount } = {}) => + extendedWrapper( + mountFunction(ServiceDeskSetting, { + propsData: { + isEnabled: true, + ...props, + }, + }), + ); + afterEach(() => { if (wrapper) { wrapper.destroy(); } }); - const findTemplateDropdown = () => wrapper.find('#service-desk-template-select'); - const findIncomingEmail = () => wrapper.find('[data-testid="incoming-email"]'); - describe('when isEnabled=true', () => { describe('only isEnabled', () => { describe('as project admin', () => { beforeEach(() => { - wrapper = shallowMount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - }, - }); + wrapper = createComponent(); }); it('should see activation checkbox', () => { - expect(wrapper.find('#service-desk-checkbox').exists()).toBe(true); + expect(findToggle().exists()).toBe(true); }); it('should see main panel with the email info', () => { - expect(wrapper.find('#incoming-email-describer').exists()).toBe(true); + expect(findIncomingEmailLabel().exists()).toBe(true); }); it('should see loading spinner and not the incoming email', () => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + expect(findLoadingIcon().exists()).toBe(true); expect(findIncomingEmail().exists()).toBe(false); }); }); }); describe('service desk toggle', () => { - it('emits an event to turn on Service Desk when clicked', () => { - const eventSpy = jest.fn(); - eventHub.$on('serviceDeskEnabledCheckboxToggled', eventSpy); - - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: false, - }, - }); + it('emits an event to turn on Service Desk when clicked', async () => { + wrapper = createComponent(); - wrapper.find('#service-desk-checkbox').trigger('click'); + findToggle().vm.$emit('change', true); - expect(eventSpy).toHaveBeenCalledWith(true); + await nextTick(); - eventHub.$off('serviceDeskEnabledCheckboxToggled', eventSpy); - eventSpy.mockRestore(); + expect(wrapper.emitted('toggle')[0]).toEqual([true]); }); }); @@ -65,23 +70,23 @@ describe('ServiceDeskSetting', () => { const incomingEmail = 'foo@bar.com'; beforeEach(() => { - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - incomingEmail, - }, + wrapper = createComponent({ + props: { incomingEmail }, }); }); it('should see email and not the loading spinner', () => { expect(findIncomingEmail().element.value).toEqual(incomingEmail); - expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); + expect(findLoadingIcon().exists()).toBe(false); }); it('renders a copy to clipboard button', () => { - expect(wrapper.find('.qa-clipboard-button').exists()).toBe(true); - expect(wrapper.find('.qa-clipboard-button').element.dataset.clipboardText).toBe( - incomingEmail, + expect(findClipboardButton().exists()).toBe(true); + expect(findClipboardButton().props()).toEqual( + expect.objectContaining({ + title: 'Copy', + text: incomingEmail, + }), ); }); }); @@ -92,12 +97,8 @@ describe('ServiceDeskSetting', () => { const customEmail = 'custom@bar.com'; beforeEach(() => { - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - incomingEmail, - customEmail, - }, + wrapper = createComponent({ + props: { incomingEmail, customEmail }, }); }); @@ -110,12 +111,8 @@ describe('ServiceDeskSetting', () => { const email = 'foo@bar.com'; beforeEach(() => { - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - incomingEmail: email, - customEmail: email, - }, + wrapper = createComponent({ + props: { incomingEmail: email, customEmail: email }, }); }); @@ -127,21 +124,13 @@ describe('ServiceDeskSetting', () => { describe('templates dropdown', () => { it('renders a dropdown to choose a template', () => { - wrapper = shallowMount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - }, - }); + wrapper = createComponent(); - expect(wrapper.find('#service-desk-template-select').exists()).toBe(true); + expect(findTemplateDropdown().exists()).toBe(true); }); it('renders a dropdown with a default value of ""', () => { - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - }, - }); + wrapper = createComponent({ mountFunction: mount }); expect(findTemplateDropdown().element.value).toEqual(''); }); @@ -149,23 +138,18 @@ describe('ServiceDeskSetting', () => { it('renders a dropdown with a value of "Bug" when it is the initial value', () => { const templates = ['Bug', 'Documentation', 'Security release']; - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - initialSelectedTemplate: 'Bug', - templates, - }, + wrapper = createComponent({ + props: { initialSelectedTemplate: 'Bug', templates }, + mountFunction: mount, }); expect(findTemplateDropdown().element.value).toEqual('Bug'); }); it('renders a dropdown with no options when the project has no templates', () => { - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - templates: [], - }, + wrapper = createComponent({ + props: { templates: [] }, + mountFunction: mount, }); // The dropdown by default has one empty option @@ -174,11 +158,10 @@ describe('ServiceDeskSetting', () => { it('renders a dropdown with options when the project has templates', () => { const templates = ['Bug', 'Documentation', 'Security release']; - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - templates, - }, + + wrapper = createComponent({ + props: { templates }, + mountFunction: mount, }); // An empty-named template is prepended so the user can select no template @@ -199,78 +182,59 @@ describe('ServiceDeskSetting', () => { describe('save button', () => { it('renders a save button to save a template', () => { - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - }, - }); + wrapper = createComponent(); - expect(wrapper.find('button.btn-success').text()).toContain('Save changes'); + expect(findButton().text()).toContain('Save changes'); }); - it('emits a save event with the chosen template when the save button is clicked', () => { - const eventSpy = jest.fn(); - eventHub.$on('serviceDeskTemplateSave', eventSpy); - - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, + it('emits a save event with the chosen template when the save button is clicked', async () => { + wrapper = createComponent({ + props: { initialSelectedTemplate: 'Bug', initialOutgoingName: 'GitLab Support Bot', initialProjectKey: 'key', }, }); - wrapper.find('button.btn-success').trigger('click'); + findButton().vm.$emit('click'); + + await nextTick(); - expect(eventSpy).toHaveBeenCalledWith({ + const payload = { selectedTemplate: 'Bug', outgoingName: 'GitLab Support Bot', projectKey: 'key', - }); + }; - eventHub.$off('serviceDeskTemplateSave', eventSpy); - eventSpy.mockRestore(); + expect(wrapper.emitted('save')[0]).toEqual([payload]); }); }); describe('when isEnabled=false', () => { beforeEach(() => { - wrapper = shallowMount(ServiceDeskSetting, { - propsData: { - isEnabled: false, - }, + wrapper = createComponent({ + props: { isEnabled: false }, }); }); it('does not render email panel', () => { - expect(wrapper.find('#incoming-email-describer').exists()).toBe(false); + expect(findIncomingEmailLabel().exists()).toBe(false); }); it('does not render template dropdown', () => { - expect(wrapper.find('#service-desk-template-select').exists()).toBe(false); + expect(findTemplateDropdown().exists()).toBe(false); }); it('does not render template save button', () => { - expect(wrapper.find('button.btn-success').exists()).toBe(false); + expect(findButton().exists()).toBe(false); }); - it('emits an event to turn on Service Desk when the toggle is clicked', () => { - const eventSpy = jest.fn(); - eventHub.$on('serviceDeskEnabledCheckboxToggled', eventSpy); - - wrapper = mount(ServiceDeskSetting, { - propsData: { - isEnabled: true, - }, - }); - - wrapper.find('#service-desk-checkbox').trigger('click'); + it('emits an event to turn on Service Desk when the toggle is clicked', async () => { + findToggle().vm.$emit('change', false); - expect(eventSpy).toHaveBeenCalledWith(false); + await nextTick(); - eventHub.$off('serviceDeskEnabledCheckboxToggled', eventSpy); - eventSpy.mockRestore(); + expect(wrapper.emitted('toggle')[0]).toEqual([false]); }); }); }); diff --git a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js b/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js deleted file mode 100644 index d5340df03fe..00000000000 --- a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js +++ /dev/null @@ -1,111 +0,0 @@ -import AxiosMockAdapter from 'axios-mock-adapter'; -import ServiceDeskService from '~/projects/settings_service_desk/services/service_desk_service'; -import axios from '~/lib/utils/axios_utils'; -import httpStatusCodes from '~/lib/utils/http_status'; - -describe('ServiceDeskService', () => { - const endpoint = `/gitlab-org/gitlab-test/service_desk`; - const dummyResponse = { message: 'Dummy response' }; - const errorMessage = 'Network Error'; - let axiosMock; - let service; - - beforeEach(() => { - axiosMock = new AxiosMockAdapter(axios); - service = new ServiceDeskService(endpoint); - }); - - afterEach(() => { - axiosMock.restore(); - }); - - describe('toggleServiceDesk', () => { - it('makes a request to set service desk', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse); - - return service.toggleServiceDesk(true).then((response) => { - expect(response.data).toEqual(dummyResponse); - }); - }); - - it('fails on error response', () => { - axiosMock.onPut(endpoint).networkError(); - - return service.toggleServiceDesk(true).catch((error) => { - expect(error.message).toBe(errorMessage); - }); - }); - - it('makes a request with the expected body', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse); - - const spy = jest.spyOn(axios, 'put'); - - service.toggleServiceDesk(true); - - expect(spy).toHaveBeenCalledWith(endpoint, { - service_desk_enabled: true, - }); - - spy.mockRestore(); - }); - }); - - describe('updateTemplate', () => { - it('makes a request to update template', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse); - - return service - .updateTemplate( - { - selectedTemplate: 'Bug', - outgoingName: 'GitLab Support Bot', - }, - true, - ) - .then((response) => { - expect(response.data).toEqual(dummyResponse); - }); - }); - - it('fails on error response', () => { - axiosMock.onPut(endpoint).networkError(); - - return service - .updateTemplate( - { - selectedTemplate: 'Bug', - outgoingName: 'GitLab Support Bot', - }, - true, - ) - .catch((error) => { - expect(error.message).toBe(errorMessage); - }); - }); - - it('makes a request with the expected body', () => { - axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse); - - const spy = jest.spyOn(axios, 'put'); - - service.updateTemplate( - { - selectedTemplate: 'Bug', - outgoingName: 'GitLab Support Bot', - projectKey: 'key', - }, - true, - ); - - expect(spy).toHaveBeenCalledWith(endpoint, { - issue_template_key: 'Bug', - outgoing_name: 'GitLab Support Bot', - project_key: 'key', - service_desk_enabled: true, - }); - - spy.mockRestore(); - }); - }); -}); |