summaryrefslogtreecommitdiff
path: root/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/alerts_settings/components/alerts_settings_form_spec.js')
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_form_spec.js227
1 files changed, 130 insertions, 97 deletions
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 02229b3d3da..d2dcff14432 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
@@ -1,29 +1,18 @@
-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';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
import { typeSet } from '~/alerts_settings/constants';
-import alertFields from '../mocks/alertFields.json';
+import alertFields from '../mocks/alert_fields.json';
+import parsedMapping from '../mocks/parsed_mapping.json';
import { defaultAlertSettingsConfig } from './util';
describe('AlertsSettingsForm', () => {
let wrapper;
const mockToastShow = jest.fn();
- const createComponent = ({
- data = {},
- props = {},
- multipleHttpIntegrationsCustomMapping = false,
- multiIntegrations = true,
- } = {}) => {
+ const createComponent = ({ data = {}, props = {}, multiIntegrations = true } = {}) => {
wrapper = mount(AlertsSettingsForm, {
data() {
return { ...data };
@@ -35,10 +24,12 @@ describe('AlertsSettingsForm', () => {
},
provide: {
...defaultAlertSettingsConfig,
- glFeatures: { multipleHttpIntegrationsCustomMapping },
multiIntegrations,
},
mocks: {
+ $apollo: {
+ query: jest.fn(),
+ },
$toast: {
show: mockToastShow,
},
@@ -46,20 +37,20 @@ 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 findForm = () => wrapper.findComponent(GlForm);
+ const findSelect = () => wrapper.findComponent(GlFormSelect);
+ const findFormFields = () => wrapper.findAllComponents(GlFormInput);
+ const findFormToggle = () => wrapper.findComponent(GlToggle);
+ 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.findAllComponents(GlTab);
afterEach(() => {
if (wrapper) {
@@ -91,7 +82,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 () => {
@@ -106,37 +97,47 @@ 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('disabled')).toBe('disabled');
+ expect(findFormFields().at(0).attributes('id')).not.toBe('name-integration');
});
- });
-
- describe('submitting integration form', () => {
- describe('HTTP', () => {
- it('create', async () => {
- createComponent();
- const integrationName = 'Test integration';
- await selectOptionAtIndex(1);
- enableIntegration(0, integrationName);
-
- const submitBtn = findSubmitButton();
- expect(submitBtn.exists()).toBe(true);
- expect(submitBtn.text()).toBe('Save integration');
+ describe('form tabs', () => {
+ it('renders 3 tabs', () => {
+ expect(findTabs()).toHaveLength(3);
+ });
- findForm().trigger('submit');
+ 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);
+ });
- expect(wrapper.emitted('create-new-integration')[0]).toEqual([
- { type: typeSet.http, variables: { name: integrationName, active: 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);
});
+ });
+ });
+ describe('submitting integration form', () => {
+ describe('HTTP', () => {
it('create with custom mapping', async () => {
createComponent({
- multipleHttpIntegrationsCustomMapping: true,
multiIntegrations: true,
props: { alertFields },
});
@@ -146,7 +147,7 @@ describe('AlertsSettingsForm', () => {
enableIntegration(0, integrationName);
- const sampleMapping = { field: 'test' };
+ const sampleMapping = parsedMapping.payloadAttributeMappings;
findMappingBuilder().vm.$emit('onMappingUpdate', sampleMapping);
findForm().trigger('submit');
@@ -157,7 +158,7 @@ describe('AlertsSettingsForm', () => {
name: integrationName,
active: true,
payloadAttributeMappings: sampleMapping,
- payloadExample: null,
+ payloadExample: '{}',
},
},
]);
@@ -182,23 +183,28 @@ describe('AlertsSettingsForm', () => {
findForm().trigger('submit');
- expect(wrapper.emitted('update-integration')[0]).toEqual([
- { type: typeSet.http, variables: { name: updatedIntegrationName, active: true } },
- ]);
+ expect(wrapper.emitted('update-integration')[0]).toEqual(
+ expect.arrayContaining([
+ {
+ type: typeSet.http,
+ variables: {
+ name: updatedIntegrationName,
+ active: true,
+ payloadAttributeMappings: [],
+ payloadExample: '{}',
+ },
+ },
+ ]),
+ );
});
});
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');
@@ -222,7 +228,7 @@ describe('AlertsSettingsForm', () => {
});
const apiUrl = 'https://test-post.com';
- enableIntegration(1, apiUrl);
+ enableIntegration(0, apiUrl);
const submitBtn = findSubmitButton();
expect(submitBtn.exists()).toBe(true);
@@ -260,7 +266,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);
});
@@ -275,56 +281,73 @@ describe('AlertsSettingsForm', () => {
});
describe('Test payload section for HTTP integration', () => {
+ const validSamplePayload = JSON.stringify(alertFields);
+ const emptySamplePayload = '{}';
+
beforeEach(() => {
createComponent({
- multipleHttpIntegrationsCustomMapping: true,
- props: {
+ data: {
currentIntegration: {
type: typeSet.http,
+ payloadExample: validSamplePayload,
+ payloadAttributeMappings: [],
},
- alertFields,
+ active: false,
+ resetPayloadAndMappingConfirmed: false,
},
+ props: { alertFields },
});
});
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';
+ active | resetPayloadAndMappingConfirmed | disabled
+ ${true} | ${true} | ${undefined}
+ ${false} | ${true} | ${'disabled'}
+ ${true} | ${false} | ${'disabled'}
+ ${false} | ${false} | ${'disabled'}
+ `('', ({ active, resetPayloadAndMappingConfirmed, disabled }) => {
+ const payloadResetMsg = resetPayloadAndMappingConfirmed
+ ? '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 },
+ selectedIntegration: typeSet.http,
active,
- resetSamplePayloadConfirmed,
+ resetPayloadAndMappingConfirmed,
});
await wrapper.vm.$nextTick();
- expect(findTestPayloadSection().find(GlFormTextarea).attributes('disabled')).toBe(disabled);
+ expect(findSamplePayloadSection().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';
+ resetPayloadAndMappingConfirmed | payloadExample | caption
+ ${false} | ${validSamplePayload} | ${'Edit 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
+ ? '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,
+ currentIntegration: {
+ payloadExample,
+ type: typeSet.http,
+ active: true,
+ payloadAttributeMappings: [],
+ },
+ resetPayloadAndMappingConfirmed,
});
await wrapper.vm.$nextTick();
expect(findActionBtn().text()).toBe(caption);
@@ -333,16 +356,20 @@ describe('AlertsSettingsForm', () => {
});
describe('Parsing payload', () => {
- it('displays a toast message on successful parse', async () => {
- jest.useFakeTimers();
+ beforeEach(() => {
wrapper.setData({
selectedIntegration: typeSet.http,
- customMapping: { samplePayload: false },
+ resetPayloadAndMappingConfirmed: true,
});
- await wrapper.vm.$nextTick();
+ });
+ it('displays a toast message on successful parse', async () => {
+ jest.spyOn(wrapper.vm.$apollo, 'query').mockResolvedValue({
+ data: {
+ project: { alertManagementPayloadFields: [] },
+ },
+ });
findActionBtn().vm.$emit('click');
- jest.advanceTimersByTime(1000);
await waitForPromises();
@@ -350,27 +377,33 @@ describe('AlertsSettingsForm', () => {
'Sample payload has been parsed. You can now map the fields.',
);
});
+
+ it('displays an error message under payload field on unsuccessful parse', async () => {
+ const errorMessage = 'Error parsing paylod';
+ jest.spyOn(wrapper.vm.$apollo, 'query').mockRejectedValue({ message: errorMessage });
+ findActionBtn().vm.$emit('click');
+
+ await waitForPromises();
+
+ expect(findSamplePayloadSection().find('.invalid-feedback').text()).toBe(errorMessage);
+ });
});
});
describe('Mapping builder section', () => {
describe.each`
- alertFieldsProvided | multiIntegrations | featureFlag | integrationOption | visible
- ${true} | ${true} | ${true} | ${1} | ${true}
- ${true} | ${true} | ${true} | ${2} | ${false}
- ${true} | ${true} | ${false} | ${1} | ${false}
- ${true} | ${true} | ${false} | ${2} | ${false}
- ${true} | ${false} | ${true} | ${1} | ${false}
- ${false} | ${true} | ${true} | ${1} | ${false}
- `('', ({ alertFieldsProvided, multiIntegrations, featureFlag, integrationOption, visible }) => {
+ alertFieldsProvided | multiIntegrations | integrationOption | visible
+ ${true} | ${true} | ${1} | ${true}
+ ${true} | ${true} | ${2} | ${false}
+ ${true} | ${false} | ${1} | ${false}
+ ${false} | ${true} | ${1} | ${false}
+ `('', ({ alertFieldsProvided, multiIntegrations, integrationOption, visible }) => {
const visibleMsg = visible ? 'is rendered' : 'is not rendered';
- const featureFlagMsg = featureFlag ? 'is enabled' : 'is disabled';
const alertFieldsMsg = alertFieldsProvided ? 'are provided' : 'are not provided';
const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus;
- it(`${visibleMsg} when multipleHttpIntegrationsCustomMapping feature flag ${featureFlagMsg} and integration type is ${integrationType} and alert fields ${alertFieldsMsg}`, async () => {
+ it(`${visibleMsg} when integration type is ${integrationType} and alert fields ${alertFieldsMsg}`, async () => {
createComponent({
- multipleHttpIntegrationsCustomMapping: featureFlag,
multiIntegrations,
props: {
alertFields: alertFieldsProvided ? alertFields : [],