diff options
Diffstat (limited to 'spec/frontend/alerts_settings/alerts_settings_form_new_spec.js')
-rw-r--r-- | spec/frontend/alerts_settings/alerts_settings_form_new_spec.js | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js new file mode 100644 index 00000000000..fbd482b1906 --- /dev/null +++ b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js @@ -0,0 +1,364 @@ +import { mount } from '@vue/test-utils'; +import { + GlForm, + GlFormSelect, + GlCollapse, + GlFormInput, + GlToggle, + GlFormTextarea, +} from '@gitlab/ui'; +import waitForPromises from 'helpers/wait_for_promises'; +import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue'; +import { defaultAlertSettingsConfig } from './util'; +import { typeSet } from '~/alerts_settings/constants'; + +describe('AlertsSettingsFormNew', () => { + let wrapper; + const mockToastShow = jest.fn(); + + const createComponent = ({ + data = {}, + props = {}, + multipleHttpIntegrationsCustomMapping = false, + } = {}) => { + wrapper = mount(AlertsSettingsForm, { + data() { + return { ...data }; + }, + propsData: { + loading: false, + canAddIntegration: true, + canManageOpsgenie: true, + ...props, + }, + provide: { + glFeatures: { multipleHttpIntegrationsCustomMapping }, + ...defaultAlertSettingsConfig, + }, + mocks: { + $toast: { + show: mockToastShow, + }, + }, + }); + }; + + 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 findMappingBuilderSection = () => wrapper.find(`[id = "mapping-builder"]`); + 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 findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`); + const findActionBtn = () => wrapper.find(`[data-testid="payload-action-btn"]`); + + afterEach(() => { + if (wrapper) { + wrapper.destroy(); + wrapper = null; + } + }); + + describe('with default values', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders the initial template', () => { + expect(wrapper.html()).toMatchSnapshot(); + }); + + it('render the initial form with only an integration type dropdown', () => { + expect(findForm().exists()).toBe(true); + expect(findSelect().exists()).toBe(true); + expect(findMultiSupportText().exists()).toBe(false); + expect(findFormSteps().attributes('visible')).toBeUndefined(); + }); + + it('shows the rest of the form when the dropdown is used', async () => { + const options = findSelect().findAll('option'); + await options.at(1).setSelected(); + + await wrapper.vm.$nextTick(); + + expect( + findFormFields() + .at(0) + .isVisible(), + ).toBe(true); + }); + + it('disabled the dropdown and shows help text when multi integrations are not supported', async () => { + createComponent({ props: { canAddIntegration: false } }); + expect(findSelect().attributes('disabled')).toBe('disabled'); + expect(findMultiSupportText().exists()).toBe(true); + }); + }); + + describe('submitting integration form', () => { + it('allows for create-new-integration with the correct form values for HTTP', async () => { + createComponent({}); + + 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 update-integration with the correct form values for HTTP', async () => { + createComponent({ + data: { + selectedIntegration: typeSet.http, + currentIntegration: { id: '1', name: 'Test integration pre' }, + }, + props: { + loading: false, + }, + }); + + await findFormFields() + .at(0) + .setValue('Test integration post'); + 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('update-integration')).toBeTruthy(); + expect(wrapper.emitted('update-integration')[0]).toEqual([ + { type: typeSet.http, variables: { name: 'Test integration post', active: true } }, + ]); + }); + + it('allows for update-integration with the correct form values for PROMETHEUS', async () => { + createComponent({ + data: { + selectedIntegration: typeSet.prometheus, + currentIntegration: { id: '1', apiUrl: 'https://test-pre.com' }, + }, + props: { + loading: false, + }, + }); + + await findFormFields() + .at(0) + .setValue('Test integration'); + await findFormFields() + .at(1) + .setValue('https://test-post.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('update-integration')).toBeTruthy(); + expect(wrapper.emitted('update-integration')[0]).toEqual([ + { type: typeSet.prometheus, variables: { apiUrl: 'https://test-post.com', active: true } }, + ]); + }); + }); + + describe('submitting the integration with a JSON test payload', () => { + beforeEach(() => { + createComponent({ + data: { + selectedIntegration: typeSet.http, + currentIntegration: { id: '1', name: 'Test' }, + active: true, + }, + props: { + loading: false, + }, + }); + }); + + it('should not allow a user to test invalid JSON', async () => { + jest.useFakeTimers(); + await findJsonTextArea().setValue('Invalid JSON'); + + jest.runAllTimers(); + await wrapper.vm.$nextTick(); + + expect(findJsonTestSubmit().exists()).toBe(true); + expect(findJsonTestSubmit().text()).toBe('Save and test payload'); + expect(findJsonTestSubmit().props('disabled')).toBe(true); + }); + + it('should allow for the form to be automatically saved if the test payload is successfully submitted', async () => { + jest.useFakeTimers(); + await findJsonTextArea().setValue('{ "value": "value" }'); + + jest.runAllTimers(); + await wrapper.vm.$nextTick(); + expect(findJsonTestSubmit().props('disabled')).toBe(false); + }); + }); + + describe('Test payload section for HTTP integration', () => { + beforeEach(() => { + createComponent({ + multipleHttpIntegrationsCustomMapping: true, + props: { + currentIntegration: { + type: typeSet.http, + }, + }, + }); + }); + + describe.each` + active | resetSamplePayloadConfirmed | disabled + ${true} | ${true} | ${undefined} + ${false} | ${true} | ${'disabled'} + ${true} | ${false} | ${'disabled'} + ${false} | ${false} | ${'disabled'} + `('', ({ active, resetSamplePayloadConfirmed, disabled }) => { + const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed'; + const enabledState = disabled === 'disabled' ? 'disabled' : 'enabled'; + const activeState = active ? 'active' : 'not active'; + + it(`textarea should be ${enabledState} when payload reset ${payloadResetMsg} and current integration is ${activeState}`, async () => { + wrapper.setData({ + customMapping: { samplePayload: true }, + active, + resetSamplePayloadConfirmed, + }); + await wrapper.vm.$nextTick(); + expect( + findTestPayloadSection() + .find(GlFormTextarea) + .attributes('disabled'), + ).toBe(disabled); + }); + }); + + describe('action buttons for sample payload', () => { + describe.each` + resetSamplePayloadConfirmed | samplePayload | caption + ${false} | ${true} | ${'Edit payload'} + ${true} | ${false} | ${'Submit payload'} + ${true} | ${true} | ${'Submit payload'} + ${false} | ${false} | ${'Submit payload'} + `('', ({ resetSamplePayloadConfirmed, samplePayload, caption }) => { + const samplePayloadMsg = samplePayload ? 'was provided' : 'was not provided'; + const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed'; + + it(`shows ${caption} button when sample payload ${samplePayloadMsg} and payload reset ${payloadResetMsg}`, async () => { + wrapper.setData({ + selectedIntegration: typeSet.http, + customMapping: { samplePayload }, + resetSamplePayloadConfirmed, + }); + await wrapper.vm.$nextTick(); + expect(findActionBtn().text()).toBe(caption); + }); + }); + }); + + describe('Parsing payload', () => { + it('displays a toast message on successful parse', async () => { + jest.useFakeTimers(); + wrapper.setData({ + selectedIntegration: typeSet.http, + customMapping: { samplePayload: false }, + }); + await wrapper.vm.$nextTick(); + + findActionBtn().vm.$emit('click'); + jest.advanceTimersByTime(1000); + + await waitForPromises(); + + expect(mockToastShow).toHaveBeenCalledWith( + 'Sample payload has been parsed. You can now map the fields.', + ); + }); + }); + }); + + describe('Mapping builder section', () => { + describe.each` + featureFlag | integrationOption | visible + ${true} | ${1} | ${true} + ${true} | ${2} | ${false} + ${false} | ${1} | ${false} + ${false} | ${2} | ${false} + `('', ({ featureFlag, integrationOption, visible }) => { + const visibleMsg = visible ? 'is rendered' : 'is not rendered'; + const featureFlagMsg = featureFlag ? 'is enabled' : 'is disabled'; + const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus; + + it(`${visibleMsg} when multipleHttpIntegrationsCustomMapping feature flag ${featureFlagMsg} and integration type is ${integrationType}`, async () => { + createComponent({ multipleHttpIntegrationsCustomMapping: featureFlag }); + const options = findSelect().findAll('option'); + options.at(integrationOption).setSelected(); + await wrapper.vm.$nextTick(); + expect(findMappingBuilderSection().exists()).toBe(visible); + }); + }); + }); +}); |