Commit 39347518 authored by David O'Regan's avatar David O'Regan Committed by Olena Horal-Koretska

Update alert setting form

We update the alert settings
form naming and actions to
support a missing mapping builder
parent 5933d4a8
......@@ -216,8 +216,12 @@ export default {
return {
name: this.currentIntegration?.name || '',
active: this.currentIntegration?.active || false,
token: this.currentIntegration?.token || this.selectedIntegrationType.token,
url: this.currentIntegration?.url || this.selectedIntegrationType.url,
token:
this.currentIntegration?.token ||
(this.selectedIntegrationType !== this.generic ? this.selectedIntegrationType.token : ''),
url:
this.currentIntegration?.url ||
(this.selectedIntegrationType !== this.generic ? this.selectedIntegrationType.url : ''),
apiUrl: this.currentIntegration?.apiUrl || '',
};
},
......@@ -246,8 +250,20 @@ export default {
canEditPayload() {
return this.hasSamplePayload && !this.resetSamplePayloadConfirmed;
},
isResetAuthKeyDisabled() {
return !this.active && !this.integrationForm.token !== '';
},
isPayloadEditDisabled() {
return !this.active || this.canEditPayload;
return this.glFeatures.multipleHttpIntegrationsCustomMapping
? !this.active || this.canEditPayload
: !this.active;
},
isSubmitTestPayloadDisabled() {
return (
!this.active ||
Boolean(this.integrationTestPayload.error) ||
this.integrationTestPayload.json === ''
);
},
},
watch: {
......@@ -257,7 +273,7 @@ export default {
}
this.selectedIntegration = val.type;
this.active = val.active;
if (val.type === typeSet.http) this.getIntegrationMapping(val.id);
if (val.type === typeSet.http && this.showMappingBuilder) this.getIntegrationMapping(val.id);
return this.integrationTypeSelect();
},
},
......@@ -297,14 +313,8 @@ export default {
});
},
submitWithTestPayload() {
return service
.updateTestAlert(this.testAlertPayload)
.then(() => {
this.$emit('set-test-alert-payload', this.testAlertPayload);
this.submit();
})
.catch(() => {
this.$emit('test-payload-failure');
});
},
submit() {
// TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
......@@ -323,6 +333,7 @@ export default {
return this.$emit('update-integration', integrationPayload);
}
this.reset();
return this.$emit('create-new-integration', integrationPayload);
},
reset() {
......@@ -539,7 +550,7 @@ export default {
</template>
</gl-form-input-group>
<gl-button v-gl-modal.authKeyModal :disabled="!active">
<gl-button v-gl-modal.authKeyModal :disabled="isResetAuthKeyDisabled">
{{ $options.i18n.integrationFormSteps.step3.reset }}
</gl-button>
<gl-modal
......@@ -642,7 +653,7 @@ export default {
<gl-button
v-if="!isManagingOpsgenie"
data-testid="integration-test-and-submit"
:disabled="Boolean(integrationTestPayload.error)"
:disabled="isSubmitTestPayloadDisabled"
category="secondary"
variant="success"
class="gl-mx-3 js-no-auto-disable"
......
......@@ -14,7 +14,8 @@ import resetHttpTokenMutation from '../graphql/mutations/reset_http_token.mutati
import resetPrometheusTokenMutation from '../graphql/mutations/reset_prometheus_token.mutation.graphql';
import updateCurrentIntergrationMutation from '../graphql/mutations/update_current_intergration.mutation.graphql';
import IntegrationsList from './alerts_integrations_list.vue';
import SettingsFormNew from './alerts_settings_form_new.vue';
import AlertSettingsForm from './alerts_settings_form.vue';
import service from '../services';
import { typeSet } from '../constants';
import {
updateStoreAfterIntegrationDelete,
......@@ -35,6 +36,9 @@ export default {
'AlertsIntegrations|The integration has been successfully saved. Alerts from this new integration should now appear on your alerts list.',
),
integrationRemoved: s__('AlertsIntegrations|The integration has been successfully removed.'),
alertSent: s__(
'AlertsIntegrations|The test alert has been successfully sent, and should now be visible on your alerts list.',
),
},
components: {
// TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
......@@ -42,7 +46,7 @@ export default {
GlLink,
GlSprintf,
IntegrationsList,
SettingsFormNew,
AlertSettingsForm,
},
inject: {
generic: {
......@@ -89,6 +93,7 @@ export default {
data() {
return {
isUpdating: false,
testAlertPayload: null,
integrations: {},
currentIntegration: null,
};
......@@ -131,6 +136,19 @@ export default {
if (error) {
return createFlash({ message: error });
}
if (this.testAlertPayload) {
const integration =
httpIntegrationCreate?.integration || prometheusIntegrationCreate?.integration;
const payload = {
...this.testAlertPayload,
endpoint: integration.url,
token: integration.token,
};
return this.validateAlertPayload(payload);
}
return createFlash({
message: this.$options.i18n.changesSaved,
type: FLASH_TYPES.SUCCESS,
......@@ -161,6 +179,13 @@ export default {
if (error) {
return createFlash({ message: error });
}
if (this.testAlertPayload) {
return this.validateAlertPayload();
}
this.clearCurrentIntegration();
return createFlash({
message: this.$options.i18n.changesSaved,
type: FLASH_TYPES.SUCCESS,
......@@ -171,6 +196,7 @@ export default {
})
.finally(() => {
this.isUpdating = false;
this.testAlertPayload = null;
});
},
resetToken({ type, variables }) {
......@@ -194,7 +220,13 @@ export default {
const integration =
httpIntegrationResetToken?.integration ||
prometheusIntegrationResetToken?.integration;
this.currentIntegration = integration;
this.$apollo.mutate({
mutation: updateCurrentIntergrationMutation,
variables: {
...integration,
},
});
return createFlash({
message: this.$options.i18n.changesSaved,
......@@ -262,8 +294,21 @@ export default {
variables: {},
});
},
testPayloadFailure() {
setTestAlertPayload(payload) {
this.testAlertPayload = payload;
},
validateAlertPayload(payload) {
return service
.updateTestAlert(payload ?? this.testAlertPayload)
.then(() => {
return createFlash({
message: this.$options.i18n.alertSent,
type: FLASH_TYPES.SUCCESS,
});
})
.catch(() => {
createFlash({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
});
},
},
};
......@@ -297,7 +342,7 @@ export default {
@edit-integration="editIntegration"
@delete-integration="deleteIntegration"
/>
<settings-form-new
<alert-settings-form
:loading="isUpdating"
:can-add-integration="canAddIntegration"
:can-manage-opsgenie="canManageOpsgenie"
......@@ -305,7 +350,7 @@ export default {
@update-integration="updateIntegration"
@reset-token="resetToken"
@clear-current-integration="clearCurrentIntegration"
@test-payload-failure="testPayloadFailure"
@set-test-alert-payload="setTestAlertPayload"
/>
</div>
</template>
---
title: Update alert setting form to handle JSON payload submit when mapping builder
is not enabled
merge_request: 48231
author:
type: fixed
......@@ -2730,6 +2730,9 @@ msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
msgstr ""
msgid "AlertsIntegrations|The test alert has been successfully sent, and should now be visible on your alerts list."
msgstr ""
msgid "AlertsIntegrations|You have opted to delete the %{integrationName} integration. Do you want to proceed? It means you will no longer receive alerts from this endpoint in your alert list, and this action cannot be undone."
msgstr ""
......
......@@ -87,7 +87,7 @@ exports[`AlertsSettingsFormNew with default values renders the initial template
<div class=\\"gl-display-flex gl-justify-content-start gl-py-3\\"><button data-testid=\\"integration-form-submit\\" type=\\"submit\\" class=\\"btn js-no-auto-disable btn-success btn-md gl-button\\">
<!---->
<!----> <span class=\\"gl-button-text\\">Save integration
</span></button> <button data-testid=\\"integration-test-and-submit\\" type=\\"button\\" class=\\"btn gl-mx-3 js-no-auto-disable btn-success btn-md gl-button btn-success-secondary\\">
</span></button> <button data-testid=\\"integration-test-and-submit\\" type=\\"button\\" disabled=\\"disabled\\" class=\\"btn gl-mx-3 js-no-auto-disable btn-success btn-md disabled gl-button btn-success-secondary\\">
<!---->
<!----> <span class=\\"gl-button-text\\">Save and test payload</span></button> <button type=\\"reset\\" class=\\"btn js-no-auto-disable btn-default btn-md gl-button\\">
<!---->
......
......@@ -8,7 +8,7 @@ import {
GlFormTextarea,
} from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
import { defaultAlertSettingsConfig } from './util';
import { typeSet } from '~/alerts_settings/constants';
......
import VueApollo from 'vue-apollo';
import { mount, createLocalVue } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_form_new.vue';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
import getIntegrationsQuery from '~/alerts_settings/graphql/queries/get_integrations.query.graphql';
import createHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
......@@ -113,17 +115,15 @@ describe('AlertsSettingsWrapper', () => {
}
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
describe('rendered via default permissions', () => {
it('renders the GraphQL alerts integrations list and new form', () => {
createComponent();
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(true);
expect(wrapper.find(AlertsSettingsForm).exists()).toBe(true);
});
it('uses a loading state inside the IntegrationsList table', () => {
......@@ -153,7 +153,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { createHttpIntegrationMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {
type: typeSet.http,
variables: createHttpVariables,
});
......@@ -175,7 +175,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { updateHttpIntegrationMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {
type: typeSet.http,
variables: updateHttpVariables,
});
......@@ -195,7 +195,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { resetHttpTokenMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {
type: typeSet.http,
variables: { id: ID },
});
......@@ -217,7 +217,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { createPrometheusIntegrationMutation: { integration: { id: '2' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {
type: typeSet.prometheus,
variables: createPrometheusVariables,
});
......@@ -239,7 +239,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { updatePrometheusIntegrationMutation: { integration: { id: '2' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {
type: typeSet.prometheus,
variables: updatePrometheusVariables,
});
......@@ -259,7 +259,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { resetPrometheusTokenMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {
type: typeSet.prometheus,
variables: { id: ID },
});
......@@ -279,7 +279,7 @@ describe('AlertsSettingsWrapper', () => {
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(ADD_INTEGRATION_ERROR);
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {});
wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {});
await waitForPromises();
......@@ -294,7 +294,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(RESET_INTEGRATION_TOKEN_ERROR);
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {});
wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {});
await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({ message: RESET_INTEGRATION_TOKEN_ERROR });
......@@ -308,23 +308,25 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {});
wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {});
await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR });
});
it('shows an error alert when integration test payload fails ', async () => {
const mock = new AxiosMockAdapter(axios);
mock.onPost(/(.*)/).replyOnce(403);
createComponent({
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
loading: false,
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('test-payload-failure');
await waitForPromises();
return wrapper.vm.validateAlertPayload({ endpoint: '', data: '', token: '' }).then(() => {
expect(createFlash).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
expect(createFlash).toHaveBeenCalledTimes(1);
mock.restore();
});
});
});
......
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