Commit 48b29935 authored by Coung Ngo's avatar Coung Ngo Committed by Brandon Labuschagne

Improve service desk frontend code

Improve code as a result of
https://gitlab.com/gitlab-org/gitlab/-/issues/288339

This commit:

- Fixes `service_desk_root.vue` `incomingEmail` prop from being mutated
- Removes data properties in the Vue root component
- Converts root component props to provide/inject
- Removes an event hub in favour of component events
- Removes service class
- Completely overhauls the related tests
parent ca67c9c7
......@@ -2,60 +2,42 @@
import { GlAlert } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import ServiceDeskSetting from './service_desk_setting.vue';
import ServiceDeskService from '../services/service_desk_service';
import eventHub from '../event_hub';
import axios from '~/lib/utils/axios_utils';
export default {
name: 'ServiceDeskRoot',
components: {
GlAlert,
ServiceDeskSetting,
},
props: {
inject: {
initialIsEnabled: {
type: Boolean,
required: true,
default: false,
},
endpoint: {
type: String,
required: true,
default: '',
},
incomingEmail: {
type: String,
required: false,
initialIncomingEmail: {
default: '',
},
customEmail: {
type: String,
required: false,
default: '',
},
customEmailEnabled: {
type: Boolean,
required: false,
default: false,
},
selectedTemplate: {
type: String,
required: false,
default: '',
},
outgoingName: {
type: String,
required: false,
default: '',
},
projectKey: {
type: String,
required: false,
default: '',
},
templates: {
type: Array,
required: false,
default: () => [],
default: [],
},
},
data() {
return {
isEnabled: this.initialIsEnabled,
......@@ -63,28 +45,21 @@ export default {
isAlertShowing: false,
alertVariant: 'danger',
alertMessage: '',
incomingEmail: this.initialIncomingEmail,
updatedCustomEmail: this.customEmail,
};
},
created() {
eventHub.$on('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
eventHub.$on('serviceDeskTemplateSave', this.onSaveTemplate);
this.service = new ServiceDeskService(this.endpoint);
},
beforeDestroy() {
eventHub.$off('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
eventHub.$off('serviceDeskTemplateSave', this.onSaveTemplate);
},
methods: {
onEnableToggled(isChecked) {
this.isEnabled = isChecked;
this.incomingEmail = '';
this.service
.toggleServiceDesk(isChecked)
const body = {
service_desk_enabled: isChecked,
};
return axios
.put(this.endpoint, body)
.then(({ data }) => {
const email = data.service_desk_address;
if (isChecked && !email) {
......@@ -104,8 +79,16 @@ export default {
onSaveTemplate({ selectedTemplate, outgoingName, projectKey }) {
this.isTemplateSaving = true;
this.service
.updateTemplate({ selectedTemplate, outgoingName, projectKey }, this.isEnabled)
const body = {
issue_template_key: selectedTemplate,
outgoing_name: outgoingName,
project_key: projectKey,
service_desk_enabled: this.isEnabled,
};
return axios
.put(this.endpoint, body)
.then(({ data }) => {
this.updatedCustomEmail = data?.service_desk_address;
this.showAlert(__('Changes saved.'), 'success');
......@@ -150,6 +133,8 @@ export default {
:initial-project-key="projectKey"
:templates="templates"
:is-template-saving="isTemplateSaving"
@save="onSaveTemplate"
@toggle="onEnableToggled"
/>
</div>
</template>
<script>
import { GlButton, GlFormSelect, GlToggle, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../event_hub';
export default {
name: 'ServiceDeskSetting',
components: {
ClipboardButton,
GlButton,
......@@ -15,7 +12,6 @@ export default {
GlLoadingIcon,
GlSprintf,
},
mixins: [glFeatureFlagsMixin()],
props: {
isEnabled: {
type: Boolean,
......@@ -84,10 +80,10 @@ export default {
},
methods: {
onCheckboxToggle(isChecked) {
eventHub.$emit('serviceDeskEnabledCheckboxToggled', isChecked);
this.$emit('toggle', isChecked);
},
onSaveTemplate() {
eventHub.$emit('serviceDeskTemplateSave', {
this.$emit('save', {
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
projectKey: this.projectKey,
......@@ -111,7 +107,11 @@ export default {
</label>
<div v-if="isEnabled" class="row mt-3">
<div class="col-md-9 mb-0">
<strong id="incoming-email-describer" class="d-block mb-1">
<strong
id="incoming-email-describer"
class="gl-display-block gl-mb-1"
data-testid="incoming-email-describer"
>
{{ __('Email address to use for Support Desk') }}
</strong>
<template v-if="email">
......@@ -128,11 +128,7 @@ export default {
disabled="true"
/>
<div class="input-group-append">
<clipboard-button
:title="__('Copy')"
:text="email"
css-class="input-group-text qa-clipboard-button"
/>
<clipboard-button :title="__('Copy')" :text="email" css-class="input-group-text" />
</div>
</div>
<span v-if="hasCustomEmail" class="form-text text-muted">
......
import createEventHub from '~/helpers/event_hub_factory';
export default createEventHub();
......@@ -3,43 +3,37 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import ServiceDeskRoot from './components/service_desk_root.vue';
export default () => {
const serviceDeskRootElement = document.querySelector('.js-service-desk-setting-root');
if (serviceDeskRootElement) {
// eslint-disable-next-line no-new
new Vue({
el: serviceDeskRootElement,
components: {
ServiceDeskRoot,
},
data() {
const { dataset } = serviceDeskRootElement;
return {
initialIsEnabled: parseBoolean(dataset.enabled),
endpoint: dataset.endpoint,
incomingEmail: dataset.incomingEmail,
customEmail: dataset.customEmail,
customEmailEnabled: parseBoolean(dataset.customEmailEnabled),
selectedTemplate: dataset.selectedTemplate,
outgoingName: dataset.outgoingName,
projectKey: dataset.projectKey,
templates: JSON.parse(dataset.templates),
};
},
render(createElement) {
return createElement('service-desk-root', {
props: {
initialIsEnabled: this.initialIsEnabled,
endpoint: this.endpoint,
incomingEmail: this.incomingEmail,
customEmail: this.customEmail,
customEmailEnabled: this.customEmailEnabled,
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
projectKey: this.projectKey,
templates: this.templates,
},
});
const el = document.querySelector('.js-service-desk-setting-root');
if (!el) {
return false;
}
const {
customEmail,
customEmailEnabled,
enabled,
endpoint,
incomingEmail,
outgoingName,
projectKey,
selectedTemplate,
templates,
} = el.dataset;
return new Vue({
el,
provide: {
customEmail,
customEmailEnabled: parseBoolean(customEmailEnabled),
endpoint,
initialIncomingEmail: incomingEmail,
initialIsEnabled: parseBoolean(enabled),
outgoingName,
projectKey,
selectedTemplate,
templates: JSON.parse(templates),
},
render: (createElement) => createElement(ServiceDeskRoot),
});
}
};
import axios from '~/lib/utils/axios_utils';
class ServiceDeskService {
constructor(endpoint) {
this.endpoint = endpoint;
}
toggleServiceDesk(enable) {
return axios.put(this.endpoint, { service_desk_enabled: enable });
}
updateTemplate({ selectedTemplate, outgoingName, projectKey = '' }, isEnabled) {
const body = {
issue_template_key: selectedTemplate,
outgoing_name: outgoingName,
project_key: projectKey,
service_desk_enabled: isEnabled,
};
return axios.put(this.endpoint, body);
}
}
export default ServiceDeskService;
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();
spy = jest.spyOn(axios, 'put');
wrapper = mount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: true,
initialIncomingEmail,
endpoint,
},
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,
});
});
wrapper.find('button.gl-toggle').trigger('click');
describe('toggle event', () => {
describe('when toggling service desk on', () => {
beforeEach(async () => {
wrapper = createComponent();
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: false });
});
wrapper.find(ServiceDeskSetting).vm.$emit('toggle', true);
await waitForPromises();
});
it('sends a request to toggle service desk on when the toggle is clicked from the off state', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
it('sends a request to turn service desk on', () => {
axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
spy = jest.spyOn(axios, 'put');
wrapper = mount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: false,
initialIncomingEmail: '',
endpoint,
},
expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: true });
});
wrapper.find('button.gl-toggle').trigger('click');
it('shows a message when there is an error', () => {
axiosMock.onPut(provideData.endpoint).networkError();
return wrapper.vm.$nextTick(() => {
expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: true });
expect(getAlertText()).toContain('An error occurred while enabling Service Desk.');
});
});
describe('when toggling service desk off', () => {
beforeEach(async () => {
wrapper = createComponent();
wrapper.find(ServiceDeskSetting).vm.$emit('toggle', false);
await waitForPromises();
});
it('shows an error message when there is an issue toggling service desk on', () => {
axiosMock.onPut(endpoint).networkError();
it('sends a request to turn service desk off', () => {
axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
wrapper = mount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: false,
initialIncomingEmail: '',
endpoint,
},
expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: false });
});
wrapper.find('button.gl-toggle').trigger('click');
it('shows a message when there is an error', () => {
axiosMock.onPut(provideData.endpoint).networkError();
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(wrapper.html()).toContain('An error occurred while enabling Service Desk.');
expect(getAlertText()).toContain('An error occurred while disabling Service Desk.');
});
});
});
it('sends a request to update template when the "Save template" button is clicked', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
describe('save event', () => {
describe('successful request', () => {
beforeEach(async () => {
axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
spy = jest.spyOn(axios, 'put');
wrapper = createComponent();
wrapper = mount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: true,
endpoint,
initialIncomingEmail,
const payload = {
selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
templates: ['Bug', 'Documentation'],
projectKey: 'key',
},
});
};
wrapper.find('button.btn-success').trigger('click');
wrapper.find(ServiceDeskSetting).vm.$emit('save', payload);
return wrapper.vm.$nextTick(() => {
expect(spy).toHaveBeenCalledWith(endpoint, {
await waitForPromises();
});
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,
});
});
});
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'],
},
});
wrapper.find('button.btn-success').trigger('click');
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(wrapper.html()).toContain('Changes saved.');
it('shows success message', () => {
expect(getAlertText()).toContain('Changes saved.');
});
});
it('shows an error message when there is an issue saving the template', () => {
axiosMock.onPut(endpoint).networkError();
describe('unsuccessful request', () => {
beforeEach(async () => {
axiosMock.onPut(provideData.endpoint).networkError();
wrapper = mount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: true,
endpoint,
initialIncomingEmail,
wrapper = createComponent();
const payload = {
selectedTemplate: 'Bug',
templates: ['Bug', 'Documentation'],
},
});
outgoingName: 'GitLab Support Bot',
projectKey: 'key',
};
wrapper.find('button.btn-success').trigger('click');
wrapper.find(ServiceDeskSetting).vm.$emit('save', payload);
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(wrapper.html()).toContain('An error occured while saving changes:');
await waitForPromises();
});
});
it('passes customEmail through updatedCustomEmail correctly', () => {
const customEmail = 'foo';
wrapper = mount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: true,
endpoint,
customEmail,
},
it('shows an error message', () => {
expect(getAlertText()).toContain('An error occured while saving changes:');
});
});
});
expect(wrapper.find(ServiceDeskSetting).props('customEmail')).toEqual(customEmail);
});
});
import { shallowMount, mount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '~/projects/settings_service_desk/event_hub';
import { GlButton, GlFormSelect, GlLoadingIcon, GlToggle } from '@gitlab/ui';
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);
it('emits an event to turn on Service Desk when clicked', async () => {
wrapper = createComponent();
wrapper = mount(ServiceDeskSetting, {
propsData: {
isEnabled: false,
},
});
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');
expect(eventSpy).toHaveBeenCalledWith({
await nextTick();
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);
});
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,
},
expect(findButton().exists()).toBe(false);
});
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]);
});
});
});
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();
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment