Commit 55d57c62 authored by Miguel Rincon's avatar Miguel Rincon

Merge branch '268518-fix-generic-incoming-email-address-in-service-desk-form' into 'master'

Updated service desk incoming email to use custom email

See merge request gitlab-org/gitlab!46053
parents b957737f 9d3ff990
......@@ -20,7 +20,12 @@ export default {
type: String,
required: true,
},
initialIncomingEmail: {
incomingEmail: {
type: String,
required: false,
default: '',
},
customEmail: {
type: String,
required: false,
default: '',
......@@ -50,23 +55,18 @@ export default {
data() {
return {
isEnabled: this.initialIsEnabled,
incomingEmail: this.initialIncomingEmail,
isTemplateSaving: false,
isAlertShowing: false,
alertVariant: 'danger',
alertMessage: '',
updatedCustomEmail: this.customEmail,
};
},
created() {
eventHub.$on('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
eventHub.$on('serviceDeskTemplateSave', this.onSaveTemplate);
this.service = new ServiceDeskService(this.endpoint);
if (this.isEnabled && !this.incomingEmail) {
this.fetchIncomingEmail();
}
},
beforeDestroy() {
......@@ -75,22 +75,6 @@ export default {
},
methods: {
fetchIncomingEmail() {
this.service
.fetchIncomingEmail()
.then(({ data }) => {
const email = data.service_desk_address;
if (!email) {
throw new Error(__("Response didn't include `service_desk_address`"));
}
this.incomingEmail = email;
})
.catch(() =>
this.showAlert(__('An error occurred while fetching the Service Desk address.')),
);
},
onEnableToggled(isChecked) {
this.isEnabled = isChecked;
this.incomingEmail = '';
......@@ -119,7 +103,7 @@ export default {
this.service
.updateTemplate({ selectedTemplate, outgoingName, projectKey }, this.isEnabled)
.then(({ data }) => {
this.incomingEmail = data?.service_desk_address;
this.updatedCustomEmail = data?.service_desk_address;
this.showAlert(__('Changes were successfully made.'), 'success');
})
.catch(err => {
......@@ -155,6 +139,7 @@ export default {
<service-desk-setting
:is-enabled="isEnabled"
:incoming-email="incomingEmail"
:custom-email="updatedCustomEmail"
:initial-selected-template="selectedTemplate"
:initial-outgoing-name="outgoingName"
:initial-project-key="projectKey"
......
......@@ -26,6 +26,11 @@ export default {
required: false,
default: '',
},
customEmail: {
type: String,
required: false,
default: '',
},
initialSelectedTemplate: {
type: String,
required: false,
......@@ -57,7 +62,6 @@ export default {
selectedTemplate: this.initialSelectedTemplate,
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
projectKey: this.initialProjectKey,
baseEmail: this.incomingEmail.replace(this.initialProjectKey, ''),
};
},
computed: {
......@@ -67,6 +71,12 @@ export default {
hasProjectKeySupport() {
return Boolean(this.glFeatures.serviceDeskCustomAddress);
},
email() {
return this.customEmail || this.incomingEmail;
},
hasCustomEmail() {
return this.customEmail && this.customEmail !== this.incomingEmail;
},
},
methods: {
onCheckboxToggle(isChecked) {
......@@ -101,30 +111,31 @@ export default {
<strong id="incoming-email-describer" class="d-block mb-1">
{{ __('Forward external support email address to') }}
</strong>
<template v-if="incomingEmail">
<template v-if="email">
<div class="input-group">
<input
ref="service-desk-incoming-email"
type="text"
class="form-control incoming-email"
class="form-control"
data-testid="incoming-email"
:placeholder="__('Incoming email')"
:aria-label="__('Incoming email')"
aria-describedby="incoming-email-describer"
:value="incomingEmail"
:value="email"
disabled="true"
/>
<div class="input-group-append">
<clipboard-button
:title="__('Copy')"
:text="incomingEmail"
:text="email"
css-class="input-group-text qa-clipboard-button"
/>
</div>
</div>
<span v-if="projectKey" class="form-text text-muted">
<span v-if="hasCustomEmail" class="form-text text-muted">
<gl-sprintf :message="__('Emails sent to %{email} will still be supported')">
<template #email>
<code>{{ baseEmail }}</code>
<code>{{ incomingEmail }}</code>
</template>
</gl-sprintf>
</span>
......
......@@ -17,6 +17,7 @@ export default () => {
initialIsEnabled: parseBoolean(dataset.enabled),
endpoint: dataset.endpoint,
incomingEmail: dataset.incomingEmail,
customEmail: dataset.customEmail,
selectedTemplate: dataset.selectedTemplate,
outgoingName: dataset.outgoingName,
projectKey: dataset.projectKey,
......@@ -28,7 +29,8 @@ export default () => {
props: {
initialIsEnabled: this.initialIsEnabled,
endpoint: this.endpoint,
initialIncomingEmail: this.incomingEmail,
incomingEmail: this.incomingEmail,
customEmail: this.customEmail,
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
projectKey: this.projectKey,
......
......@@ -5,10 +5,6 @@ class ServiceDeskService {
this.endpoint = endpoint;
}
fetchIncomingEmail() {
return axios.get(this.endpoint);
}
toggleServiceDesk(enable) {
return axios.put(this.endpoint, { service_desk_enabled: enable });
}
......
......@@ -10,7 +10,7 @@
- if ::Gitlab::ServiceDesk.supported?
.js-service-desk-setting-root{ data: { endpoint: project_service_desk_path(@project),
enabled: "#{@project.service_desk_enabled}",
incoming_email: (@project.service_desk_address if @project.service_desk_enabled),
incoming_email: (@project.service_desk_incoming_address if @project.service_desk_enabled),
custom_email: (@project.service_desk_custom_address if @project.service_desk_enabled),
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
......
......@@ -3027,9 +3027,6 @@ msgstr ""
msgid "An error occurred while fetching terraform reports."
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
......
......@@ -28,6 +28,6 @@ RSpec.describe 'Service Desk Setting', :js do
project.reload
expect(project.service_desk_enabled).to be_truthy
expect(project.service_desk_address).to be_present
expect(find('.incoming-email').value).to eq(project.service_desk_address)
expect(find('[data-testid="incoming-email"]').value).to eq(project.service_desk_address)
end
end
import { shallowMount, mount } from '@vue/test-utils';
import { mount } 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';
......@@ -24,65 +25,6 @@ describe('ServiceDeskRoot', () => {
}
});
it('fetches incoming email when there is no incoming email provided', () => {
axiosMock.onGet(endpoint).replyOnce(httpStatusCodes.OK);
wrapper = shallowMount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: true,
initialIncomingEmail: '',
endpoint,
},
});
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(axiosMock.history.get).toHaveLength(1);
});
});
it('does not fetch incoming email when there is an incoming email provided', () => {
axiosMock.onGet(endpoint).replyOnce(httpStatusCodes.OK);
wrapper = shallowMount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: true,
initialIncomingEmail,
endpoint,
},
});
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(axiosMock.history.get).toHaveLength(0);
});
});
it('shows an error message when incoming email is not fetched correctly', () => {
axiosMock.onGet(endpoint).networkError();
wrapper = shallowMount(ServiceDeskRoot, {
propsData: {
initialIsEnabled: true,
initialIncomingEmail: '',
endpoint,
},
});
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(wrapper.html()).toContain(
'An error occurred while fetching the Service Desk address.',
);
});
});
it('sends a request to toggle service desk off when the toggle is clicked from the on state', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
......@@ -221,4 +163,18 @@ describe('ServiceDeskRoot', () => {
expect(wrapper.html()).toContain('An error occured while making the 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);
});
});
......@@ -13,6 +13,7 @@ describe('ServiceDeskSetting', () => {
});
const findTemplateDropdown = () => wrapper.find('#service-desk-template-select');
const findIncomingEmail = () => wrapper.find('[data-testid="incoming-email"]');
describe('when isEnabled=true', () => {
describe('only isEnabled', () => {
......@@ -35,7 +36,7 @@ describe('ServiceDeskSetting', () => {
it('should see loading spinner and not the incoming email', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
expect(wrapper.find('.incoming-email').exists()).toBe(false);
expect(findIncomingEmail().exists()).toBe(false);
});
});
});
......@@ -73,7 +74,7 @@ describe('ServiceDeskSetting', () => {
});
it('should see email and not the loading spinner', () => {
expect(wrapper.find('.incoming-email').element.value).toEqual(incomingEmail);
expect(findIncomingEmail().element.value).toEqual(incomingEmail);
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
......@@ -85,6 +86,45 @@ describe('ServiceDeskSetting', () => {
});
});
describe('with customEmail', () => {
describe('customEmail is different than incomingEmail', () => {
const incomingEmail = 'foo@bar.com';
const customEmail = 'custom@bar.com';
beforeEach(() => {
wrapper = mount(ServiceDeskSetting, {
propsData: {
isEnabled: true,
incomingEmail,
customEmail,
},
});
});
it('should see custom email', () => {
expect(findIncomingEmail().element.value).toEqual(customEmail);
});
});
describe('customEmail is the same as incomingEmail', () => {
const email = 'foo@bar.com';
beforeEach(() => {
wrapper = mount(ServiceDeskSetting, {
propsData: {
isEnabled: true,
incomingEmail: email,
customEmail: email,
},
});
});
it('should see custom email', () => {
expect(findIncomingEmail().element.value).toEqual(email);
});
});
});
describe('templates dropdown', () => {
it('renders a dropdown to choose a template', () => {
wrapper = shallowMount(ServiceDeskSetting, {
......
......@@ -19,24 +19,6 @@ describe('ServiceDeskService', () => {
axiosMock.restore();
});
describe('fetchIncomingEmail', () => {
it('makes a request to fetch incoming email', () => {
axiosMock.onGet(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
return service.fetchIncomingEmail().then(response => {
expect(response.data).toEqual(dummyResponse);
});
});
it('fails on error response', () => {
axiosMock.onGet(endpoint).networkError();
return service.fetchIncomingEmail().catch(error => {
expect(error.message).toBe(errorMessage);
});
});
});
describe('toggleServiceDesk', () => {
it('makes a request to set service desk', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
......
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