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

Add support for HTTP Create

Add support for alert HTTP
create supported via GraphQL
parent a7537882
<script>
import { GlTable, GlIcon, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import {
GlButtonGroup,
GlButton,
GlIcon,
GlLoadingIcon,
GlTable,
GlTooltipDirective,
} from '@gitlab/ui';
import { s__, __ } from '~/locale';
import Tracking from '~/tracking';
import { trackAlertIntegrationsViewsOptions } from '../constants';
......@@ -25,9 +32,11 @@ const bodyTrClass =
export default {
i18n,
components: {
GlTable,
GlButtonGroup,
GlButton,
GlIcon,
GlLoadingIcon,
GlTable,
},
directives: {
GlTooltip: GlTooltipDirective,
......@@ -57,6 +66,10 @@ export default {
key: 'type',
label: __('Type'),
},
{
key: 'actions',
label: __('Actions'),
},
],
computed: {
tbodyTrClass() {
......@@ -111,6 +124,13 @@ export default {
</span>
</template>
<template #cell(actions)="{ item }">
<gl-button-group>
<gl-button icon="pencil" @click="$emit('edit-integration', { id: item.id })" />
<gl-button icon="remove" @click="$emit('delete-integration', { id: item.id })" />
</gl-button-group>
</template>
<template #table-busy>
<gl-loading-icon size="lg" color="dark" class="mt-3" />
</template>
......
......@@ -21,12 +21,14 @@ import {
JSON_VALIDATE_DELAY,
targetPrometheusUrlPlaceholder,
typeSet,
defaultFormState,
} from '../constants';
export default {
targetPrometheusUrlPlaceholder,
JSON_VALIDATE_DELAY,
typeSet,
defaultFormState,
i18n: {
integrationFormSteps: {
step1: {
......@@ -62,6 +64,11 @@ export default {
label: s__('AlertSettings|Prometheus API base URL'),
help: s__('AlertSettings|URL cannot be blank and must start with http or https'),
},
restKeyInfo: {
label: s__(
'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
),
},
},
},
components: {
......@@ -95,23 +102,18 @@ export default {
type: Boolean,
required: true,
},
currentIntegration: {
type: Object,
required: false,
default: null,
},
},
data() {
return {
selectedIntegration: integrationTypesNew[0].value,
active: false,
options: integrationTypesNew,
formVisible: false,
integrationForm: {
name: '',
integrationTestPayload: {
json: null,
error: null,
},
active: false,
authKey: '',
url: '',
apiUrl: '',
},
};
},
computed: {
......@@ -125,9 +127,29 @@ export default {
case this.$options.typeSet.prometheus:
return this.prometheus;
default:
return {};
return this.defaultFormState;
}
},
integrationForm() {
return {
name: this.currentIntegration?.name || '',
integrationTestPayload: {
json: null,
error: null,
},
active: this.currentIntegration?.active || false,
token: this.currentIntegration?.token || '',
url: this.currentIntegration?.url || '',
apiUrl: this.currentIntegration?.apiUrl || '',
};
},
},
watch: {
currentIntegration(val) {
this.selectedIntegration = val.type;
this.active = val.active;
this.onIntegrationTypeSelect();
},
},
methods: {
onIntegrationTypeSelect() {
......@@ -142,18 +164,29 @@ export default {
this.onSubmit();
},
onSubmit() {
const { name, apiUrl, active } = this.integrationForm;
const { name, apiUrl } = this.integrationForm;
const variables =
this.selectedIntegration === this.$options.typeSet.http
? { name, active }
: { apiUrl, active };
this.$emit('on-create-new-integration', { type: this.selectedIntegration, variables });
? { name, active: this.active }
: { apiUrl, active: this.active };
const integrationPayload = { type: this.selectedIntegration, variables };
if (this.currentIntegration) {
return this.$emit('update-integration', integrationPayload);
}
return this.$emit('create-new-integration', integrationPayload);
},
onReset() {
// TODO: Reset form values
this.integrationForm = this.defaultFormState;
this.selectedIntegration = integrationTypesNew[0].value;
this.onIntegrationTypeSelect();
},
onResetAuthKey() {
// TODO: Handle reset auth key via GraphQL
this.$emit('reset-token', {
type: this.selectedIntegration,
variables: { id: this.currentIntegration.id },
});
},
validateJson() {
this.integrationForm.integrationTestPayload.error = null;
......@@ -214,7 +247,7 @@ export default {
/>
<gl-toggle
v-model="integrationForm.active"
v-model="active"
:is-loading="loading"
:label="__('Active')"
class="gl-my-4 gl-font-weight-normal"
......@@ -242,13 +275,9 @@ export default {
{{ s__('AlertSettings|Webhook URL') }}
</span>
<gl-form-input-group id="url" readonly :value="selectedIntegrationType.url">
<gl-form-input-group id="url" readonly :value="integrationForm.url">
<template #append>
<clipboard-button
:text="selectedIntegrationType.url || ''"
:title="__('Copy')"
class="gl-m-0!"
/>
<clipboard-button :text="integrationForm.url" :title="__('Copy')" class="gl-m-0!" />
</template>
</gl-form-input-group>
</div>
......@@ -262,14 +291,10 @@ export default {
id="authorization-key"
class="gl-mb-2"
readonly
:value="selectedIntegrationType.authKey"
:value="integrationForm.token"
>
<template #append>
<clipboard-button
:text="selectedIntegrationType.authKey || ''"
:title="__('Copy')"
class="gl-m-0!"
/>
<clipboard-button :text="integrationForm.token" :title="__('Copy')" class="gl-m-0!" />
</template>
</gl-form-input-group>
......@@ -281,9 +306,9 @@ export default {
:title="$options.i18n.integrationFormSteps.step3.reset"
:ok-title="$options.i18n.integrationFormSteps.step3.reset"
ok-variant="danger"
@ok="() => {}"
@ok="onResetAuthKey"
>
{{ $options.i18n.integrationFormSteps.step3.reset }}
{{ $options.i18n.integrationFormSteps.restKeyInfo.label }}
</gl-modal>
</div>
</gl-form-group>
......
......@@ -59,7 +59,7 @@ export default {
selectedIntegration: integrationTypes[0].value,
options: integrationTypes,
active: false,
authKey: '',
token: '',
targetUrl: '',
feedback: {
variant: 'danger',
......@@ -98,7 +98,7 @@ export default {
case 'HTTP': {
return {
url: this.generic.url,
authKey: this.generic.authKey,
token: this.generic.token,
active: this.generic.active,
resetKey: this.resetKey.bind(this),
};
......@@ -106,7 +106,7 @@ export default {
case 'PROMETHEUS': {
return {
url: this.prometheus.url,
authKey: this.prometheus.authKey,
token: this.prometheus.token,
active: this.prometheus.active,
resetKey: this.resetKey.bind(this, 'PROMETHEUS'),
targetUrl: this.prometheus.prometheusApiUrl,
......@@ -167,7 +167,7 @@ export default {
this.setOpsgenieAsDefault();
}
this.active = this.selectedIntegrationType.active;
this.authKey = this.selectedIntegrationType.authKey ?? '';
this.token = this.selectedIntegrationType.token ?? '';
},
methods: {
createUserErrorMessage(errors = {}) {
......@@ -212,8 +212,8 @@ export default {
return fn
.then(({ data: { token } }) => {
this.authKey = token;
this.setFeedback({ feedbackMessage: this.$options.i18n.authKeyRest, variant: 'success' });
this.token = token;
this.setFeedback({ feedbackMessage: this.$options.i18n.tokenRest, variant: 'success' });
})
.catch(() => {
this.setFeedback({ feedbackMessage: this.$options.i18n.errorKeyMsg, variant: 'danger' });
......@@ -313,7 +313,7 @@ export default {
.updateTestAlert({
endpoint: this.selectedIntegrationType.url,
data: this.testAlert.json,
authKey: this.selectedIntegrationType.authKey,
token: this.selectedIntegrationType.token,
})
.then(() => {
this.setFeedback({
......@@ -439,21 +439,21 @@ export default {
{{ prometheusInfo }}
</span>
</gl-form-group>
<gl-form-group :label="$options.i18n.authKeyLabel" label-for="authorization-key">
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="authKey">
<gl-form-group :label="$options.i18n.tokenLabel" label-for="authorization-key">
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="token">
<template #append>
<clipboard-button
:text="authKey"
:text="token"
:title="$options.i18n.copyToClipboard"
class="gl-m-0!"
/>
</template>
</gl-form-input-group>
<gl-button v-gl-modal.authKeyModal :disabled="!active" class="gl-mt-3">{{
<gl-button v-gl-modal.tokenModal :disabled="!active" class="gl-mt-3">{{
$options.i18n.resetKey
}}</gl-button>
<gl-modal
modal-id="authKeyModal"
modal-id="tokenModal"
:title="$options.i18n.resetKey"
:ok-title="$options.i18n.resetKey"
ok-variant="danger"
......
......@@ -7,6 +7,10 @@ import createFlash, { FLASH_TYPES } from '~/flash';
import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
import createHttpIntegrationMutation from '../graphql/mutations/create_http_integration.mutation.graphql';
import createPrometheusIntegrationMutation from '../graphql/mutations/create_prometheus_integration.mutation.graphql';
import updateHttpIntegrationMutation from '../graphql/mutations/update_http_integration.mutation.graphql';
import updatePrometheusIntegrationMutation from '../graphql/mutations/update_prometheus_integration.mutation.graphql';
import resetHttpTokenMutation from '../graphql/mutations/reset_http_token.mutation.graphql';
import resetPrometheusTokenMutation from '../graphql/mutations/reset_prometheus_token.mutation.graphql';
import IntegrationsList from './alerts_integrations_list.vue';
import SettingsFormOld from './alerts_settings_form_old.vue';
import SettingsFormNew from './alerts_settings_form_new.vue';
......@@ -52,16 +56,16 @@ export default {
list,
};
},
error() {
this.errored = true;
error(err) {
createFlash({ message: err });
},
},
},
data() {
return {
errored: false,
isUpdating: false,
integrations: {},
currentIntegration: null,
};
},
computed: {
......@@ -84,7 +88,7 @@ export default {
},
},
methods: {
onCreateNewIntegration({ type, variables }) {
createNewIntegration({ type, variables }) {
this.isUpdating = true;
this.$apollo
.mutate({
......@@ -109,7 +113,6 @@ export default {
});
})
.catch(err => {
this.errored = true;
createFlash({ message: err });
})
.finally(() => {
......@@ -151,6 +154,72 @@ export default {
data,
});
},
updateIntegration({ type, variables }) {
this.isUpdating = true;
this.$apollo
.mutate({
mutation:
type === this.$options.typeSet.http
? updateHttpIntegrationMutation
: updatePrometheusIntegrationMutation,
variables: {
...variables,
id: this.currentIntegration.id,
},
})
.then(({ data: { httpIntegrationUpdate, prometheusIntegrationUpdate } = {} } = {}) => {
const error = httpIntegrationUpdate?.errors[0] || prometheusIntegrationUpdate?.errors[0];
if (error) {
return createFlash({ message: error });
}
return createFlash({
message: this.$options.i18n.changesSaved,
type: FLASH_TYPES.SUCCESS,
});
})
.catch(err => {
createFlash({ message: err });
})
.finally(() => {
this.isUpdating = false;
});
},
resetToken({ type, variables }) {
this.isUpdating = true;
this.$apollo
.mutate({
mutation:
type === this.$options.typeSet.http
? resetHttpTokenMutation
: resetPrometheusTokenMutation,
variables,
})
.then(
({ data: { httpIntegrationResetToken, prometheusIntegrationResetToken } = {} } = {}) => {
const error =
httpIntegrationResetToken?.errors[0] || prometheusIntegrationResetToken?.errors[0];
if (error) {
return createFlash({ message: error });
}
return createFlash({
message: this.$options.i18n.changesSaved,
type: FLASH_TYPES.SUCCESS,
});
},
)
.catch(err => {
createFlash({ message: err });
})
.finally(() => {
this.isUpdating = false;
});
},
editIntegration({ id }) {
this.currentIntegration = this.integrations.list.find(integration => integration.id === id);
},
deleteIntegration() {
// TODO, handle delete via GraphQL
},
},
};
</script>
......@@ -160,11 +229,16 @@ export default {
<integrations-list
:integrations="glFeatures.httpIntegrationsList ? integrations.list : intergrationsOptionsOld"
:loading="loading"
@edit-integration="editIntegration"
@delete-integration="deleteIntegration"
/>
<settings-form-new
v-if="glFeatures.httpIntegrationsList"
:loading="loading"
@on-create-new-integration="onCreateNewIntegration"
:loading="isUpdating"
:current-integration="currentIntegration"
@create-new-integration="createNewIntegration"
@update-integration="updateIntegration"
@reset-token="resetToken"
/>
<settings-form-old v-else />
</div>
......
......@@ -57,6 +57,15 @@ export const typeSet = {
prometheus: 'PROMETHEUS',
};
export const defaultFormState = {
name: '',
active: false,
token: '',
url: '',
apiUrl: '',
integrationTestPayload: { json: null, error: null },
};
export const JSON_VALIDATE_DELAY = 250;
export const targetPrometheusUrlPlaceholder = 'http://prometheus.example.com/';
......
#import "../fragments/integration_item.fragment.graphql"
mutation resetHttpIntegrationToken($id: ID!) {
httpIntegrationResetToken(input: { id: $id }) {
errors
integration {
...IntegrationItem
}
}
}
#import "../fragments/integration_item.fragment.graphql"
mutation resetPrometheusIntegrationToken($id: ID!) {
prometheusIntegrationResetToken(input: { id: $id }) {
errors
integration {
...IntegrationItem
}
}
}
#import "../fragments/integration_item.fragment.graphql"
mutation updateHttpIntegration($id: ID!, $name: String!, $active: Boolean!) {
httpIntegrationUpdate(input: { id: $id, name: $name, active: $active }) {
errors
integration {
...IntegrationItem
}
}
}
#import "../fragments/integration_item.fragment.graphql"
mutation updatePrometheusIntegration($id: ID!, $apiUrl: String!, $active: Boolean!) {
prometheusIntegrationUpdate(input: { id: $id, apiUrl: $apiUrl, active: $active }) {
errors
integration {
...IntegrationItem
}
}
}
......@@ -50,7 +50,7 @@ export default el => {
prometheus: {
active: parseBoolean(prometheusActivated),
url: prometheusUrl,
authKey: prometheusAuthorizationKey,
token: prometheusAuthorizationKey,
prometheusFormPath,
prometheusResetKeyPath,
prometheusApiUrl,
......@@ -60,7 +60,7 @@ export default el => {
alertsUsageUrl,
active: parseBoolean(activatedStr),
formPath,
authKey: authorizationKey,
token: authorizationKey,
url,
},
opsgenie: {
......
......@@ -24,10 +24,10 @@ exports[`AlertsSettingsFormOld with default values renders the initial template
</span>
</gl-form-group-stub>
<gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\">
<gl-form-group-stub label-for=\\"authorization-key\\">
<gl-form-input-group-stub value=\\"\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
<gl-modal-stub modalid=\\"authKeyModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
<gl-modal-stub modalid=\\"tokenModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
</gl-modal-stub>
</gl-form-group-stub>
......
......@@ -70,16 +70,70 @@ describe('AlertsSettingsFormNew', () => {
});
});
describe('when form is invalid', () => {
// TODO, implement specs for when form is invalid
});
describe('submitting integration form', () => {
it('allows for create-new-integration with the correct form values for HTTP', async () => {
createComponent({});
describe('when form is valid', () => {
beforeEach(() => {
const options = findSelect().findAll('option');
await options.at(1).setSelected();
await findFormFields()
.at(0)
.setValue('Test integration');
await findFormToggle().trigger('click');
await wrapper.vm.$nextTick();
expect(findSubmitButton().exists()).toBe(true);
expect(findSubmitButton().text()).toBe('Save integration');
findForm().trigger('submit');
await wrapper.vm.$nextTick();
expect(wrapper.emitted('create-new-integration')).toBeTruthy();
expect(wrapper.emitted('create-new-integration')[0]).toEqual([
{ type: typeSet.http, variables: { name: 'Test integration', active: true } },
]);
});
it('allows for create-new-integration with the correct form values for PROMETHEUS', async () => {
createComponent({});
const options = findSelect().findAll('option');
await options.at(2).setSelected();
await findFormFields()
.at(0)
.setValue('Test integration');
await findFormFields()
.at(1)
.setValue('https://test.com');
await findFormToggle().trigger('click');
await wrapper.vm.$nextTick();
expect(findSubmitButton().exists()).toBe(true);
expect(findSubmitButton().text()).toBe('Save integration');
findForm().trigger('submit');
await wrapper.vm.$nextTick();
expect(wrapper.emitted('create-new-integration')).toBeTruthy();
expect(wrapper.emitted('create-new-integration')[0]).toEqual([
{ type: typeSet.prometheus, variables: { apiUrl: 'https://test.com', active: true } },
]);
});
it('allows for on-create-new-integration with the correct form values for HTTP', async () => {
it('allows for update-integration with the correct form values for HTTP', async () => {
createComponent({
props: {
currentIntegration: { id: '1' },
loading: false,
},
});
const options = findSelect().findAll('option');
await options.at(1).setSelected();
......@@ -97,13 +151,20 @@ describe('AlertsSettingsFormNew', () => {
await wrapper.vm.$nextTick();
expect(wrapper.emitted('on-create-new-integration')).toBeTruthy();
expect(wrapper.emitted('on-create-new-integration')[0]).toEqual([
expect(wrapper.emitted('update-integration')).toBeTruthy();
expect(wrapper.emitted('update-integration')[0]).toEqual([
{ type: typeSet.http, variables: { name: 'Test integration', active: true } },
]);
});
it('allows for on-create-new-integration with the correct form values for PROMETHEUS', async () => {
it('allows for update-integration with the correct form values for PROMETHEUS', async () => {
createComponent({
props: {
currentIntegration: { id: '1' },
loading: false,
},
});
const options = findSelect().findAll('option');
await options.at(2).setSelected();
......@@ -124,8 +185,8 @@ describe('AlertsSettingsFormNew', () => {
await wrapper.vm.$nextTick();
expect(wrapper.emitted('on-create-new-integration')).toBeTruthy();
expect(wrapper.emitted('on-create-new-integration')[0]).toEqual([
expect(wrapper.emitted('update-integration')).toBeTruthy();
expect(wrapper.emitted('update-integration')[0]).toEqual([
{ type: typeSet.prometheus, variables: { apiUrl: 'https://test.com', active: true } },
]);
});
......
......@@ -69,7 +69,7 @@ describe('AlertsSettingsFormOld', () => {
createComponent(
{},
{
authKey: 'newToken',
token: 'newToken',
},
);
......
......@@ -6,14 +6,24 @@ import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
import createHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
import createPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql';
import updateHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
import updatePrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql';
import resetHttpTokenMutation from '~/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql';
import resetPrometheusTokenMutation from '~/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql';
import { typeSet } from '~/alerts_settings/constants';
import createFlash from '~/flash';
import { defaultAlertSettingsConfig } from './util';
import mockIntegrations from './mocks/integrations.json';
import {
createHttpVariables,
updateHttpVariables,
createPrometheusVariables,
updatePrometheusVariables,
ID,
} from './mocks/apollo_mock';
jest.mock('~/flash');
const projectPath = '';
describe('AlertsSettingsWrapper', () => {
let wrapper;
......@@ -80,7 +90,7 @@ describe('AlertsSettingsWrapper', () => {
it('renders the IntegrationsList table using the API data', () => {
createComponent({
data: { integrations: { list: mockIntegrations } },
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
......@@ -100,7 +110,7 @@ describe('AlertsSettingsWrapper', () => {
it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
createComponent({
data: { integrations: { list: mockIntegrations } },
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
......@@ -108,26 +118,66 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { createHttpIntegrationMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('on-create-new-integration', {
type: 'HTTP',
variables: { name: 'Test 1', active: true },
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
type: typeSet.http,
variables: createHttpVariables,
});
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: createHttpIntegrationMutation,
update: expect.anything(),
variables: createHttpVariables,
});
});
it('calls `$apollo.mutate` with `updateHttpIntegrationMutation`', () => {
createComponent({
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { updateHttpIntegrationMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
type: typeSet.http,
variables: updateHttpVariables,
});
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: updateHttpIntegrationMutation,
variables: updateHttpVariables,
});
});
it('calls `$apollo.mutate` with `resetHttpTokenMutation`', () => {
createComponent({
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { resetHttpTokenMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
type: typeSet.http,
variables: { id: ID },
});
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: resetHttpTokenMutation,
variables: {
name: 'Test 1',
active: true,
projectPath,
id: ID,
},
});
});
it('calls `$apollo.mutate` with `createPrometheusIntegrationMutation`', () => {
createComponent({
data: { integrations: { list: mockIntegrations } },
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
......@@ -135,33 +185,107 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { createPrometheusIntegrationMutation: { integration: { id: '2' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('on-create-new-integration', {
type: 'PROMETHEUS',
variables: { apiUrl: 'https://test.com', active: true },
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
type: typeSet.prometheus,
variables: createPrometheusVariables,
});
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: createPrometheusIntegrationMutation,
update: expect.anything(),
variables: createPrometheusVariables,
});
});
it('calls `$apollo.mutate` with `updatePrometheusIntegrationMutation`', () => {
createComponent({
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { updatePrometheusIntegrationMutation: { integration: { id: '2' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
type: typeSet.prometheus,
variables: updatePrometheusVariables,
});
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: updatePrometheusIntegrationMutation,
variables: updatePrometheusVariables,
});
});
it('calls `$apollo.mutate` with `resetPrometheusTokenMutation`', () => {
createComponent({
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
data: { resetPrometheusTokenMutation: { integration: { id: '1' } } },
});
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
type: typeSet.prometheus,
variables: { id: ID },
});
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: resetPrometheusTokenMutation,
variables: {
apiUrl: 'https://test.com',
active: true,
projectPath,
id: ID,
},
});
});
it('shows error alert when integration creation fails ', () => {
it('shows error alert when integration creation fails ', async () => {
const errorMsg = 'Something went wrong';
createComponent({
data: { integrations: { list: mockIntegrations } },
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {});
setImmediate(() => {
expect(createFlash).toHaveBeenCalledWith({ message: errorMsg });
});
});
it('shows error alert when integration token reset fails ', () => {
const errorMsg = 'Something went wrong';
createComponent({
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
wrapper.find(AlertsSettingsFormNew).vm.$emit('on-create-new-integration', {});
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {});
setImmediate(() => {
expect(createFlash).toHaveBeenCalledWith({ message: errorMsg });
});
});
it('shows error alert when integration update fails ', () => {
const errorMsg = 'Something went wrong';
createComponent({
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
provide: { glFeatures: { httpIntegrationsList: true } },
loading: false,
});
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {});
setImmediate(() => {
expect(createFlash).toHaveBeenCalledWith({ message: errorMsg });
......
const projectPath = '';
export const ID = 'gid://gitlab/AlertManagement::HttpIntegration/7';
export const createHttpVariables = {
name: 'Test Pre',
active: true,
projectPath,
};
export const updateHttpVariables = {
name: 'Test Pre',
active: true,
id: ID,
};
export const createPrometheusVariables = {
apiUrl: 'https://test-pre.com',
active: true,
projectPath,
};
export const updatePrometheusVariables = {
apiUrl: 'https://test-pre.com',
active: true,
id: ID,
};
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