diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-02 21:11:20 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-02 21:11:20 +0300 |
commit | bf2439c21308c74e437b872180046b39a61734b5 (patch) | |
tree | d6f1fe33eb4b726e4e9f11350b8838dae2fc53f4 /spec/frontend/alerts_settings/components | |
parent | 426384d091a0c229ff849ed6ba481bfbe700fb6a (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/alerts_settings/components')
3 files changed, 535 insertions, 380 deletions
diff --git a/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap b/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap index eb2b82a0211..ef6a7621b51 100644 --- a/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap +++ b/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap @@ -4,113 +4,152 @@ exports[`AlertsSettingsForm with default values renders the initial template 1`] <form class="gl-mt-6" > - <h5 - class="gl-font-lg gl-my-5" - > - Add new integrations - </h5> - <div - class="form-group gl-form-group" - id="integration-type" - role="group" + class="tabs gl-tabs" + id="__BVID__6" > - <label - class="d-block col-form-label" - for="integration-type" - id="integration-type__BV_label_" - > - 1. Select integration type - </label> + <!----> <div - class="bv-no-focus-ring" + class="" > - <select - class="gl-form-select mw-100 custom-select" - id="__BVID__8" + <ul + class="nav gl-tabs-nav" + id="__BVID__6__BV_tab_controls_" + role="tablist" > - <option - value="" + <!----> + <li + class="nav-item" + role="presentation" > - Select integration type - </option> - <option - value="HTTP" + <a + aria-controls="__BVID__8" + aria-posinset="1" + aria-selected="true" + aria-setsize="3" + class="nav-link active gl-tab-nav-item gl-tab-nav-item-active gl-tab-nav-item-active-indigo" + href="#" + id="__BVID__8___BV_tab_button__" + role="tab" + target="_self" + > + Configure details + </a> + </li> + <li + class="nav-item" + role="presentation" > - HTTP Endpoint - </option> - <option - value="PROMETHEUS" + <a + aria-controls="__BVID__22" + aria-disabled="true" + aria-posinset="2" + aria-selected="false" + aria-setsize="3" + class="nav-link disabled disabled gl-tab-nav-item" + href="#" + id="__BVID__22___BV_tab_button__" + role="tab" + tabindex="-1" + target="_self" + > + View credentials + </a> + </li> + <li + class="nav-item" + role="presentation" > - External Prometheus - </option> - </select> - - <!----> - <!----> - <!----> - <!----> + <a + aria-controls="__BVID__41" + aria-disabled="true" + aria-posinset="3" + aria-selected="false" + aria-setsize="3" + class="nav-link disabled disabled gl-tab-nav-item" + href="#" + id="__BVID__41___BV_tab_button__" + role="tab" + tabindex="-1" + target="_self" + > + Send test alert + </a> + </li> + <!----> + </ul> </div> - </div> - - <transition-stub - class="gl-mt-3" - css="true" - enteractiveclass="collapsing" - enterclass="" - entertoclass="collapse show" - leaveactiveclass="collapsing" - leaveclass="collapse show" - leavetoclass="collapse" - > <div - class="collapse" - id="__BVID__10" - style="display: none;" + class="tab-content gl-tab-content" + id="__BVID__6__BV_tab_container_" > - <div> + <transition-stub + css="true" + enteractiveclass="" + enterclass="" + entertoclass="show" + leaveactiveclass="" + leaveclass="show" + leavetoclass="" + mode="out-in" + name="" + > <div - class="form-group gl-form-group" - id="name-integration" - role="group" + aria-hidden="false" + aria-labelledby="__BVID__8___BV_tab_button__" + class="tab-pane active" + id="__BVID__8" + role="tabpanel" + style="" > - <label - class="d-block col-form-label" - for="name-integration" - id="name-integration__BV_label_" - > - 2. Name integration - </label> <div - class="bv-no-focus-ring" + class="form-group gl-form-group" + id="integration-type" + role="group" > - <input - class="gl-form-input form-control" - id="__BVID__15" - placeholder="Enter integration name" - type="text" - /> - <!----> - <!----> - <!----> + <label + class="d-block col-form-label" + for="integration-type" + id="integration-type__BV_label_" + > + Select integration type + </label> + <div + class="bv-no-focus-ring" + > + <select + class="gl-form-select gl-max-w-full custom-select" + id="__BVID__13" + > + <option + value="" + > + Select integration type + </option> + <option + value="HTTP" + > + HTTP Endpoint + </option> + <option + value="PROMETHEUS" + > + External Prometheus + </option> + </select> + + <!----> + <!----> + <!----> + <!----> + </div> </div> - </div> - - <div - class="form-group gl-form-group" - id="integration-webhook" - role="group" - > - <label - class="d-block col-form-label" - for="integration-webhook" - id="integration-webhook__BV_label_" - > - 3. Set up webhook - </label> + <div - class="bv-no-focus-ring" + class="gl-mt-3" > + <!----> + <span> Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the <a @@ -166,241 +205,324 @@ exports[`AlertsSettingsForm with default values renders the initial template 1`] <!----> - <div - class="gl-my-4" + <!----> + + <!----> + + <!----> + </div> + + <div + class="gl-display-flex gl-justify-content-start gl-py-3" + > + <button + class="btn js-no-auto-disable btn-confirm btn-md gl-button" + data-testid="integration-form-submit" + type="submit" > + <!----> + + <!----> + <span - class="gl-font-weight-bold" + class="gl-button-text" > - Webhook URL - + Save integration + </span> + </button> + + <button + class="btn gl-ml-3 js-no-auto-disable btn-default btn-md gl-button" + type="reset" + > + <!----> + <!----> + + <span + class="gl-button-text" + > + Cancel and close + </span> + </button> + </div> + </div> + </transition-stub> + + <transition-stub + css="true" + enteractiveclass="" + enterclass="" + entertoclass="show" + leaveactiveclass="" + leaveclass="show" + leavetoclass="" + mode="out-in" + name="" + > + <div + aria-hidden="true" + aria-labelledby="__BVID__22___BV_tab_button__" + class="tab-pane disabled" + id="__BVID__22" + role="tabpanel" + style="display: none;" + > + <fieldset + class="form-group gl-form-group" + id="integration-webhook" + > + <!----> + <div + class="bv-no-focus-ring" + role="group" + tabindex="-1" + > <div - id="url" - readonly="readonly" + class="gl-my-4" > + <span + class="gl-font-weight-bold" + > + + Webhook URL + + </span> + <div - class="input-group" - role="group" + id="url" + readonly="readonly" > - <!----> - <!----> - - <input - class="gl-form-input form-control" - id="url" - readonly="readonly" - type="text" - /> - <div - class="input-group-append" + class="input-group" + role="group" > - <button - aria-label="Copy this value" - class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon" - data-clipboard-text="" - title="Copy" - type="button" + <!----> + <!----> + + <input + class="gl-form-input form-control" + id="url" + readonly="readonly" + type="text" + /> + + <div + class="input-group-append" > - <!----> - - <svg - aria-hidden="true" - class="gl-button-icon gl-icon s16" - data-testid="copy-to-clipboard-icon" + <button + aria-label="Copy this value" + class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon" + data-clipboard-text="" + title="Copy" + type="button" > - <use - href="#copy-to-clipboard" - /> - </svg> - - <!----> - </button> + <!----> + + <svg + aria-hidden="true" + class="gl-button-icon gl-icon s16" + data-testid="copy-to-clipboard-icon" + > + <use + href="#copy-to-clipboard" + /> + </svg> + + <!----> + </button> + </div> + <!----> </div> - <!----> </div> </div> - </div> - - <div - class="gl-my-4" - > - <span - class="gl-font-weight-bold" - > - - Authorization key - - </span> <div - class="gl-mb-3" - id="authorization-key" - readonly="readonly" + class="gl-my-4" > + <span + class="gl-font-weight-bold" + > + + Authorization key + + </span> + <div - class="input-group" - role="group" + class="gl-mb-3" + id="authorization-key" + readonly="readonly" > - <!----> - <!----> - - <input - class="gl-form-input form-control" - id="authorization-key" - readonly="readonly" - type="text" - /> - <div - class="input-group-append" + class="input-group" + role="group" > - <button - aria-label="Copy this value" - class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon" - data-clipboard-text="" - title="Copy" - type="button" + <!----> + <!----> + + <input + class="gl-form-input form-control" + id="authorization-key" + readonly="readonly" + type="text" + /> + + <div + class="input-group-append" > - <!----> - - <svg - aria-hidden="true" - class="gl-button-icon gl-icon s16" - data-testid="copy-to-clipboard-icon" + <button + aria-label="Copy this value" + class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon" + data-clipboard-text="" + title="Copy" + type="button" > - <use - href="#copy-to-clipboard" - /> - </svg> - - <!----> - </button> + <!----> + + <svg + aria-hidden="true" + class="gl-button-icon gl-icon s16" + data-testid="copy-to-clipboard-icon" + > + <use + href="#copy-to-clipboard" + /> + </svg> + + <!----> + </button> + </div> + <!----> </div> - <!----> </div> </div> - - <button - class="btn btn-default btn-md disabled gl-button" - disabled="disabled" - type="button" - > - <!----> - - <!----> - - <span - class="gl-button-text" - > - - Reset Key - - </span> - </button> - + <!----> + <!----> <!----> </div> - <!----> - <!----> - <!----> - </div> - </div> - - <div - class="form-group gl-form-group" - id="test-integration" - role="group" - > - <label - class="d-block col-form-label" - for="test-integration" - id="test-integration__BV_label_" - > - 4. Sample alert payload (optional) - </label> - <div - class="bv-no-focus-ring" + </fieldset> + + <button + class="btn btn-danger btn-md disabled gl-button" + disabled="disabled" + type="button" > - <span> - Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional). - </span> + <!----> - <textarea - class="gl-form-input gl-form-textarea gl-my-3 form-control is-valid" - disabled="disabled" - id="test-payload" - placeholder="{ \\"events\\": [{ \\"application\\": \\"Name of application\\" }] }" - style="resize: none; overflow-y: scroll;" - wrap="soft" - /> <!----> + + <span + class="gl-button-text" + > + + Reset Key + + </span> + </button> + + <button + class="btn gl-ml-3 js-no-auto-disable btn-default btn-md gl-button" + type="reset" + > <!----> + <!----> - </div> + + <span + class="gl-button-text" + > + Cancel and close + </span> + </button> + + <!----> </div> - - <!----> - - <!----> - </div> + </transition-stub> - <div - class="gl-display-flex gl-justify-content-start gl-py-3" + <transition-stub + css="true" + enteractiveclass="" + enterclass="" + entertoclass="show" + leaveactiveclass="" + leaveclass="show" + leavetoclass="" + mode="out-in" + name="" > - <button - class="btn js-no-auto-disable btn-success btn-md gl-button" - data-testid="integration-form-submit" - type="submit" + <div + aria-hidden="true" + aria-labelledby="__BVID__41___BV_tab_button__" + class="tab-pane disabled" + id="__BVID__41" + role="tabpanel" + style="display: none;" > - <!----> - - <!----> - - <span - class="gl-button-text" + <fieldset + class="form-group gl-form-group" + id="test-integration" > - Save integration - - </span> - </button> - - <button - class="btn gl-mx-3 js-no-auto-disable btn-success btn-md disabled gl-button btn-success-secondary" - data-testid="integration-test-and-submit" - disabled="disabled" - type="button" - > - <!----> + <!----> + <div + class="bv-no-focus-ring" + role="group" + tabindex="-1" + > + <span> + Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point. + </span> + + <textarea + class="gl-form-input gl-form-textarea gl-my-3 form-control is-valid" + id="test-payload" + placeholder="{ \\"events\\": [{ \\"application\\": \\"Name of application\\" }] }" + style="resize: none; overflow-y: scroll;" + wrap="soft" + /> + <!----> + <!----> + <!----> + </div> + </fieldset> - <!----> - - <span - class="gl-button-text" + <button + class="btn js-no-auto-disable btn-confirm btn-md gl-button" + data-testid="send-test-alert" + type="button" > - Save and test payload - </span> - </button> - - <button - class="btn js-no-auto-disable btn-default btn-md gl-button" - type="reset" - > - <!----> + <!----> + + <!----> + + <span + class="gl-button-text" + > + + Send + + </span> + </button> - <!----> - - <span - class="gl-button-text" + <button + class="btn gl-ml-3 js-no-auto-disable btn-default btn-md gl-button" + type="reset" > - Cancel - </span> - </button> - </div> + <!----> + + <!----> + + <span + class="gl-button-text" + > + Cancel and close + </span> + </button> + </div> + </transition-stub> + <!----> </div> - </transition-stub> + </div> </form> `; diff --git a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js index 511b3d2a059..f8e192dfae9 100644 --- a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js +++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js @@ -1,11 +1,4 @@ -import { - GlForm, - GlFormSelect, - GlCollapse, - GlFormInput, - GlToggle, - GlFormTextarea, -} from '@gitlab/ui'; +import { GlForm, GlFormSelect, GlFormInput, GlToggle, GlFormTextarea, GlTab } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; import MappingBuilder from '~/alerts_settings/components/alert_mapping_builder.vue'; @@ -52,18 +45,18 @@ describe('AlertsSettingsForm', () => { const findForm = () => wrapper.find(GlForm); const findSelect = () => wrapper.find(GlFormSelect); - const findFormSteps = () => wrapper.find(GlCollapse); const findFormFields = () => wrapper.findAll(GlFormInput); const findFormToggle = () => wrapper.find(GlToggle); - const findTestPayloadSection = () => wrapper.find(`[id = "test-integration"]`); + const findSamplePayloadSection = () => wrapper.find('[data-testid="sample-payload-section"]'); const findMappingBuilderSection = () => wrapper.find(`[id = "mapping-builder"]`); const findMappingBuilder = () => wrapper.findComponent(MappingBuilder); const findSubmitButton = () => wrapper.find(`[type = "submit"]`); const findMultiSupportText = () => wrapper.find(`[data-testid="multi-integrations-not-supported"]`); - const findJsonTestSubmit = () => wrapper.find(`[data-testid="integration-test-and-submit"]`); + const findJsonTestSubmit = () => wrapper.find(`[data-testid="send-test-alert"]`); const findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`); const findActionBtn = () => wrapper.find(`[data-testid="payload-action-btn"]`); + const findTabs = () => wrapper.findAll(GlTab); afterEach(() => { if (wrapper) { @@ -95,7 +88,7 @@ describe('AlertsSettingsForm', () => { expect(findForm().exists()).toBe(true); expect(findSelect().exists()).toBe(true); expect(findMultiSupportText().exists()).toBe(false); - expect(findFormSteps().attributes('visible')).toBeUndefined(); + expect(findFormFields()).toHaveLength(0); }); it('shows the rest of the form when the dropdown is used', async () => { @@ -110,11 +103,40 @@ describe('AlertsSettingsForm', () => { expect(findMultiSupportText().exists()).toBe(true); }); - it('disabled the name input when the selected value is prometheus', async () => { + it('hides the name input when the selected value is prometheus', async () => { createComponent(); await selectOptionAtIndex(2); + expect(findFormFields().at(0).attributes('id')).not.toBe('name-integration'); + }); + + describe('form tabs', () => { + it('renders 3 tabs', () => { + expect(findTabs()).toHaveLength(3); + }); - expect(findFormFields().at(0).attributes('disabled')).toBe('disabled'); + it('only first tab is enabled on integration create', () => { + createComponent({ + data: { + currentIntegration: null, + }, + }); + const tabs = findTabs(); + expect(tabs.at(0).find('[role="tabpanel"]').classes('disabled')).toBe(false); + expect(tabs.at(1).find('[role="tabpanel"]').classes('disabled')).toBe(true); + expect(tabs.at(2).find('[role="tabpanel"]').classes('disabled')).toBe(true); + }); + + it('all tabs are enabled on integration edit', () => { + createComponent({ + data: { + currentIntegration: { id: 1 }, + }, + }); + const tabs = findTabs(); + expect(tabs.at(0).find('[role="tabpanel"]').classes('disabled')).toBe(false); + expect(tabs.at(1).find('[role="tabpanel"]').classes('disabled')).toBe(false); + expect(tabs.at(2).find('[role="tabpanel"]').classes('disabled')).toBe(false); + }); }); }); @@ -195,14 +217,9 @@ describe('AlertsSettingsForm', () => { describe('PROMETHEUS', () => { it('create', async () => { createComponent(); - await selectOptionAtIndex(2); - const apiUrl = 'https://test.com'; - enableIntegration(1, apiUrl); - - findFormToggle().trigger('click'); - + enableIntegration(0, apiUrl); const submitBtn = findSubmitButton(); expect(submitBtn.exists()).toBe(true); expect(submitBtn.text()).toBe('Save integration'); @@ -226,7 +243,7 @@ describe('AlertsSettingsForm', () => { }); const apiUrl = 'https://test-post.com'; - enableIntegration(1, apiUrl); + enableIntegration(0, apiUrl); const submitBtn = findSubmitButton(); expect(submitBtn.exists()).toBe(true); @@ -264,7 +281,7 @@ describe('AlertsSettingsForm', () => { const jsonTestSubmit = findJsonTestSubmit(); expect(jsonTestSubmit.exists()).toBe(true); - expect(jsonTestSubmit.text()).toBe('Save and test payload'); + expect(jsonTestSubmit.text()).toBe('Send'); expect(jsonTestSubmit.props('disabled')).toBe(true); }); @@ -313,16 +330,14 @@ describe('AlertsSettingsForm', () => { it(`textarea should be ${enabledState} when payload reset ${payloadResetMsg} and current integration is ${activeState}`, async () => { wrapper.setData({ - currentIntegration: { - type: typeSet.http, - payloadExample: validSamplePayload, - payloadAttributeMappings: [], - }, + selectedIntegration: typeSet.http, active, resetPayloadAndMappingConfirmed, }); await wrapper.vm.$nextTick(); - expect(findTestPayloadSection().find(GlFormTextarea).attributes('disabled')).toBe(disabled); + expect(findSamplePayloadSection().find(GlFormTextarea).attributes('disabled')).toBe( + disabled, + ); }); }); @@ -330,9 +345,9 @@ describe('AlertsSettingsForm', () => { describe.each` resetPayloadAndMappingConfirmed | payloadExample | caption ${false} | ${validSamplePayload} | ${'Edit payload'} - ${true} | ${emptySamplePayload} | ${'Submit payload'} - ${true} | ${validSamplePayload} | ${'Submit payload'} - ${false} | ${emptySamplePayload} | ${'Submit payload'} + ${true} | ${emptySamplePayload} | ${'Parse payload for custom mapping'} + ${true} | ${validSamplePayload} | ${'Parse payload for custom mapping'} + ${false} | ${emptySamplePayload} | ${'Parse payload for custom mapping'} `('', ({ resetPayloadAndMappingConfirmed, payloadExample, caption }) => { const samplePayloadMsg = payloadExample ? 'was provided' : 'was not provided'; const payloadResetMsg = resetPayloadAndMappingConfirmed @@ -386,7 +401,7 @@ describe('AlertsSettingsForm', () => { await waitForPromises(); - expect(findTestPayloadSection().find('.invalid-feedback').text()).toBe(errorMessage); + expect(findSamplePayloadSection().find('.invalid-feedback').text()).toBe(errorMessage); }); }); }); diff --git a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js index 8e63b24284b..77fac6dd022 100644 --- a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js +++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js @@ -9,7 +9,9 @@ import { useMockIntersectionObserver } from 'helpers/mock_dom_observer'; import waitForPromises from 'helpers/wait_for_promises'; import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue'; import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue'; -import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue'; +import AlertsSettingsWrapper, { + i18n, +} from '~/alerts_settings/components/alerts_settings_wrapper.vue'; import { typeSet } from '~/alerts_settings/constants'; import createPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql'; import destroyHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql'; @@ -19,6 +21,7 @@ import updateCurrentHttpIntegrationMutation from '~/alerts_settings/graphql/muta import updateCurrentPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/update_current_prometheus_integration.mutation.graphql'; import updatePrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql'; import getIntegrationsQuery from '~/alerts_settings/graphql/queries/get_integrations.query.graphql'; +import alertsUpdateService from '~/alerts_settings/services'; import { ADD_INTEGRATION_ERROR, RESET_INTEGRATION_TOKEN_ERROR, @@ -26,7 +29,7 @@ import { INTEGRATION_PAYLOAD_TEST_ERROR, DELETE_INTEGRATION_ERROR, } from '~/alerts_settings/utils/error_messages'; -import createFlash from '~/flash'; +import createFlash, { FLASH_TYPES } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { createHttpVariables, @@ -78,6 +81,8 @@ describe('AlertsSettingsWrapper', () => { const findLoader = () => wrapper.findComponent(IntegrationsList).findComponent(GlLoadingIcon); const findIntegrationsList = () => wrapper.findComponent(IntegrationsList); const findIntegrations = () => wrapper.find(IntegrationsList).findAll('table tbody tr'); + const findAddIntegrationBtn = () => wrapper.find('[data-testid="add-integration-btn"]'); + const findAlertsSettingsForm = () => wrapper.findComponent(AlertsSettingsForm); async function destroyHttpIntegration(localWrapper) { await jest.runOnlyPendingTimers(); @@ -144,14 +149,37 @@ describe('AlertsSettingsWrapper', () => { 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(AlertsSettingsForm).exists()).toBe(true); + describe('template', () => { + beforeEach(() => { + createComponent({ + data: { + integrations: { list: mockIntegrations }, + httpIntegrations: { list: [] }, + currentIntegration: mockIntegrations[0], + }, + loading: false, + }); }); - it('uses a loading state inside the IntegrationsList table', () => { + it('renders alerts integrations list and add new integration button by default', () => { + expect(findLoader().exists()).toBe(false); + expect(findIntegrations()).toHaveLength(mockIntegrations.length); + expect(findAddIntegrationBtn().exists()).toBe(true); + }); + + it('does NOT render settings form by default', () => { + expect(findAlertsSettingsForm().exists()).toBe(false); + }); + + it('hides `add new integration` button and displays setting form on btn click', async () => { + const addNewIntegrationBtn = findAddIntegrationBtn(); + expect(addNewIntegrationBtn.exists()).toBe(true); + await addNewIntegrationBtn.trigger('click'); + expect(findAlertsSettingsForm().exists()).toBe(true); + expect(addNewIntegrationBtn.exists()).toBe(false); + }); + + it('shows loading indicator inside the IntegrationsList table', () => { createComponent({ data: { integrations: {} }, loading: true, @@ -159,26 +187,24 @@ describe('AlertsSettingsWrapper', () => { expect(wrapper.find(IntegrationsList).exists()).toBe(true); expect(findLoader().exists()).toBe(true); }); + }); - it('renders the IntegrationsList table using the API data', () => { + describe('Integration updates', () => { + beforeEach(() => { createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, + data: { + integrations: { list: mockIntegrations }, + currentIntegration: mockIntegrations[0], + formVisible: true, + }, loading: false, }); - expect(findLoader().exists()).toBe(false); - expect(findIntegrations()).toHaveLength(mockIntegrations.length); }); - it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({ data: { createHttpIntegrationMutation: { integration: { id: '1' } } }, }); - wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', { + findAlertsSettingsForm().vm.$emit('create-new-integration', { type: typeSet.http, variables: createHttpVariables, }); @@ -192,15 +218,10 @@ describe('AlertsSettingsWrapper', () => { }); it('calls `$apollo.mutate` with `updateHttpIntegrationMutation`', () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({ data: { updateHttpIntegrationMutation: { integration: { id: '1' } } }, }); - wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', { + findAlertsSettingsForm().vm.$emit('update-integration', { type: typeSet.http, variables: updateHttpVariables, }); @@ -212,15 +233,10 @@ describe('AlertsSettingsWrapper', () => { }); it('calls `$apollo.mutate` with `resetHttpTokenMutation`', () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({ data: { resetHttpTokenMutation: { integration: { id: '1' } } }, }); - wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', { + findAlertsSettingsForm().vm.$emit('reset-token', { type: typeSet.http, variables: { id: HTTP_ID }, }); @@ -234,15 +250,10 @@ describe('AlertsSettingsWrapper', () => { }); it('calls `$apollo.mutate` with `createPrometheusIntegrationMutation`', () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({ data: { createPrometheusIntegrationMutation: { integration: { id: '2' } } }, }); - wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', { + findAlertsSettingsForm().vm.$emit('create-new-integration', { type: typeSet.prometheus, variables: createPrometheusVariables, }); @@ -257,14 +268,18 @@ describe('AlertsSettingsWrapper', () => { it('calls `$apollo.mutate` with `updatePrometheusIntegrationMutation`', () => { createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[3] }, + data: { + integrations: { list: mockIntegrations }, + currentIntegration: mockIntegrations[3], + formVisible: true, + }, loading: false, }); jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({ data: { updatePrometheusIntegrationMutation: { integration: { id: '2' } } }, }); - wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', { + findAlertsSettingsForm().vm.$emit('update-integration', { type: typeSet.prometheus, variables: updatePrometheusVariables, }); @@ -276,15 +291,10 @@ describe('AlertsSettingsWrapper', () => { }); it('calls `$apollo.mutate` with `resetPrometheusTokenMutation`', () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({ data: { resetPrometheusTokenMutation: { integration: { id: '1' } } }, }); - wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', { + findAlertsSettingsForm().vm.$emit('reset-token', { type: typeSet.prometheus, variables: { id: PROMETHEUS_ID }, }); @@ -298,13 +308,8 @@ describe('AlertsSettingsWrapper', () => { }); it('shows an error alert when integration creation fails ', async () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(ADD_INTEGRATION_ERROR); - wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {}); + findAlertsSettingsForm().vm.$emit('create-new-integration', {}); await waitForPromises(); @@ -312,28 +317,18 @@ describe('AlertsSettingsWrapper', () => { }); it('shows an error alert when integration token reset fails ', async () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(RESET_INTEGRATION_TOKEN_ERROR); - wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {}); + findAlertsSettingsForm().vm.$emit('reset-token', {}); await waitForPromises(); expect(createFlash).toHaveBeenCalledWith({ message: RESET_INTEGRATION_TOKEN_ERROR }); }); it('shows an error alert when integration update fails ', async () => { - createComponent({ - data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] }, - loading: false, - }); - jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg); - wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {}); + findAlertsSettingsForm().vm.$emit('update-integration', {}); await waitForPromises(); expect(createFlash).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR }); @@ -342,12 +337,7 @@ describe('AlertsSettingsWrapper', () => { 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, - }); - - return wrapper.vm.validateAlertPayload({ endpoint: '', data: '', token: '' }).then(() => { + return wrapper.vm.testAlertPayload({ endpoint: '', data: '', token: '' }).then(() => { expect(createFlash).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR }); expect(createFlash).toHaveBeenCalledTimes(1); mock.restore(); @@ -389,6 +379,34 @@ describe('AlertsSettingsWrapper', () => { variables: mockIntegrations[3], }); }); + + describe('Test alert', () => { + it('makes `updateTestAlert` service call', async () => { + jest.spyOn(alertsUpdateService, 'updateTestAlert').mockResolvedValueOnce(); + const testPayload = '{"title":"test"}'; + findAlertsSettingsForm().vm.$emit('test-alert-payload', testPayload); + expect(alertsUpdateService.updateTestAlert).toHaveBeenCalledWith(testPayload); + }); + + it('shows success message on successful test', async () => { + jest.spyOn(alertsUpdateService, 'updateTestAlert').mockResolvedValueOnce({}); + findAlertsSettingsForm().vm.$emit('test-alert-payload', ''); + await waitForPromises(); + expect(createFlash).toHaveBeenCalledWith({ + message: i18n.alertSent, + type: FLASH_TYPES.SUCCESS, + }); + }); + + it('shows error message when test alert fails', async () => { + jest.spyOn(alertsUpdateService, 'updateTestAlert').mockRejectedValueOnce({}); + findAlertsSettingsForm().vm.$emit('test-alert-payload', ''); + await waitForPromises(); + expect(createFlash).toHaveBeenCalledWith({ + message: INTEGRATION_PAYLOAD_TEST_ERROR, + }); + }); + }); }); describe('with mocked Apollo client', () => { |