Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/integrations/edit/components/integration_form_spec.js')
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js420
1 files changed, 129 insertions, 291 deletions
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index 7e67379f5ab..4b49e492880 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -1,21 +1,20 @@
import { GlAlert, GlBadge, GlForm } from '@gitlab/ui';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import * as Sentry from '@sentry/browser';
import { setHTMLFixture } from 'helpers/fixtures';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
-import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
import IntegrationForm from '~/integrations/edit/components/integration_form.vue';
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
-import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
import IntegrationSectionConnection from '~/integrations/edit/components/sections/connection.vue';
+import IntegrationFormActions from '~/integrations/edit/components/integration_form_actions.vue';
import {
- integrationLevels,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
INTEGRATION_FORM_TYPE_SLACK,
@@ -60,7 +59,6 @@ describe('IntegrationForm', () => {
stubs: {
OverrideDropdown,
ActiveCheckbox,
- ConfirmationModal,
TriggerFields,
},
mocks: {
@@ -73,12 +71,6 @@ describe('IntegrationForm', () => {
const findOverrideDropdown = () => wrapper.findComponent(OverrideDropdown);
const findActiveCheckbox = () => wrapper.findComponent(ActiveCheckbox);
- const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal);
- const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal);
- const findResetButton = () => wrapper.findByTestId('reset-button');
- const findProjectSaveButton = () => wrapper.findByTestId('save-button');
- const findInstanceOrGroupSaveButton = () => wrapper.findByTestId('save-button-instance-group');
- const findTestButton = () => wrapper.findByTestId('test-button');
const findTriggerFields = () => wrapper.findComponent(TriggerFields);
const findAlert = () => wrapper.findComponent(GlAlert);
const findGlBadge = () => wrapper.findComponent(GlBadge);
@@ -91,6 +83,7 @@ describe('IntegrationForm', () => {
const findConnectionSectionComponent = () =>
findConnectionSection().findComponent(IntegrationSectionConnection);
const findHelpHtml = () => wrapper.findByTestId('help-html');
+ const findFormActions = () => wrapper.findComponent(IntegrationFormActions);
beforeEach(() => {
mockAxios = new MockAdapter(axios);
@@ -102,108 +95,6 @@ describe('IntegrationForm', () => {
});
describe('template', () => {
- describe('integrationLevel is instance', () => {
- it('renders ConfirmationModal', () => {
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.INSTANCE,
- },
- });
-
- expect(findConfirmationModal().exists()).toBe(true);
- });
-
- describe('resetPath is empty', () => {
- it('does not render ResetConfirmationModal and button', () => {
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.INSTANCE,
- },
- });
-
- expect(findResetButton().exists()).toBe(false);
- expect(findResetConfirmationModal().exists()).toBe(false);
- });
- });
-
- describe('resetPath is present', () => {
- it('renders ResetConfirmationModal and button', () => {
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.INSTANCE,
- resetPath: 'resetPath',
- },
- });
-
- expect(findResetButton().exists()).toBe(true);
- expect(findResetConfirmationModal().exists()).toBe(true);
- });
- });
- });
-
- describe('integrationLevel is group', () => {
- it('renders ConfirmationModal', () => {
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.GROUP,
- },
- });
-
- expect(findConfirmationModal().exists()).toBe(true);
- });
-
- describe('resetPath is empty', () => {
- it('does not render ResetConfirmationModal and button', () => {
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.GROUP,
- },
- });
-
- expect(findResetButton().exists()).toBe(false);
- expect(findResetConfirmationModal().exists()).toBe(false);
- });
- });
-
- describe('resetPath is present', () => {
- it('renders ResetConfirmationModal and button', () => {
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.GROUP,
- resetPath: 'resetPath',
- },
- });
-
- expect(findResetButton().exists()).toBe(true);
- expect(findResetConfirmationModal().exists()).toBe(true);
- });
- });
- });
-
- describe('integrationLevel is project', () => {
- it('does not render ConfirmationModal', () => {
- createComponent({
- customStateProps: {
- integrationLevel: 'project',
- },
- });
-
- expect(findConfirmationModal().exists()).toBe(false);
- });
-
- it('does not render ResetConfirmationModal and button', () => {
- createComponent({
- customStateProps: {
- integrationLevel: 'project',
- resetPath: 'resetPath',
- },
- });
-
- expect(findResetButton().exists()).toBe(false);
- expect(findResetConfirmationModal().exists()).toBe(false);
- });
- });
-
describe('triggerEvents is present', () => {
it('renders TriggerFields', () => {
const events = [{ title: 'push' }];
@@ -462,111 +353,85 @@ describe('IntegrationForm', () => {
);
});
- describe('when `save` button is clicked', () => {
- describe('buttons', () => {
- beforeEach(async () => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: true,
- },
- mountFn: mountExtended,
- });
-
- await findProjectSaveButton().vm.$emit('click', new Event('click'));
- });
-
- it('sets save button `loading` prop to `true`', () => {
- expect(findProjectSaveButton().props('loading')).toBe(true);
+ describe('Response to the "save" event (form submission)', () => {
+ const prepareComponentAndSave = async (initialActivated = true, checkValidityReturn) => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ initialActivated,
+ fields: [mockField],
+ },
+ mountFn: mountExtended,
});
+ jest.spyOn(findGlForm().element, 'submit');
+ jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(checkValidityReturn);
- it('sets test button `disabled` prop to `true`', () => {
- expect(findTestButton().props('disabled')).toBe(true);
- });
- });
+ findFormActions().vm.$emit('save');
+ await nextTick();
+ };
- describe.each`
- checkValidityReturn | integrationActive
- ${true} | ${false}
- ${true} | ${true}
- ${false} | ${false}
+ it.each`
+ desc | checkValidityReturn | integrationActive | shouldSubmit
+ ${'form is valid'} | ${true} | ${false} | ${true}
+ ${'form is valid'} | ${true} | ${true} | ${true}
+ ${'form is invalid'} | ${false} | ${false} | ${true}
+ ${'form is invalid'} | ${false} | ${true} | ${false}
`(
- 'when form is valid (checkValidity returns $checkValidityReturn and integrationActive is $integrationActive)',
- ({ integrationActive, checkValidityReturn }) => {
- beforeEach(async () => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: integrationActive,
- },
- mountFn: mountExtended,
- });
- jest.spyOn(findGlForm().element, 'submit');
- jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(checkValidityReturn);
-
- await findProjectSaveButton().vm.$emit('click', new Event('click'));
- });
+ 'when $desc (checkValidity returns $checkValidityReturn and integrationActive is $integrationActive)',
+ async ({ integrationActive, checkValidityReturn, shouldSubmit }) => {
+ await prepareComponentAndSave(integrationActive, checkValidityReturn);
- it('submit form', () => {
+ if (shouldSubmit) {
expect(findGlForm().element.submit).toHaveBeenCalledTimes(1);
- });
+ } else {
+ expect(findGlForm().element.submit).not.toHaveBeenCalled();
+ }
},
);
- describe('when form is invalid (checkValidity returns false and integrationActive is true)', () => {
- beforeEach(async () => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: true,
- fields: [mockField],
- },
- mountFn: mountExtended,
- });
- jest.spyOn(findGlForm().element, 'submit');
- jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(false);
-
- await findProjectSaveButton().vm.$emit('click', new Event('click'));
- });
-
- it('does not submit form', () => {
- expect(findGlForm().element.submit).not.toHaveBeenCalled();
- });
+ it('flips `isSaving` to `true`', async () => {
+ await prepareComponentAndSave(true, true);
+ expect(findFormActions().props('isSaving')).toBe(true);
+ });
- it('sets save button `loading` prop to `false`', () => {
- expect(findProjectSaveButton().props('loading')).toBe(false);
+ describe('when form is invalid', () => {
+ beforeEach(async () => {
+ await prepareComponentAndSave(true, false);
});
- it('sets test button `disabled` prop to `false`', () => {
- expect(findTestButton().props('disabled')).toBe(false);
+ it('when form is invalid, it sets `isValidated` props on form fields', () => {
+ expect(findDynamicField().props('isValidated')).toBe(true);
});
- it('sets `isValidated` props on form fields', () => {
- expect(findDynamicField().props('isValidated')).toBe(true);
+ it('resets `isSaving`', () => {
+ expect(findFormActions().props('isSaving')).toBe(false);
});
});
});
- describe('when `test` button is clicked', () => {
+ describe('Response to the "test" event from the actions', () => {
describe('when form is invalid', () => {
- it('sets `isValidated` props on form fields', async () => {
+ beforeEach(async () => {
createComponent({
customStateProps: {
showActive: true,
- canTest: true,
fields: [mockField],
},
mountFn: mountExtended,
});
jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(false);
- await findTestButton().vm.$emit('click', new Event('click'));
+ findFormActions().vm.$emit('test');
+ await nextTick();
+ });
+ it('sets `isValidated` props on form fields', () => {
expect(findDynamicField().props('isValidated')).toBe(true);
});
+
+ it('resets `isTesting`', () => {
+ expect(findFormActions().props('isTesting')).toBe(false);
+ });
});
describe('when form is valid', () => {
@@ -576,26 +441,18 @@ describe('IntegrationForm', () => {
createComponent({
customStateProps: {
showActive: true,
- canTest: true,
testPath: mockTestPath,
},
mountFn: mountExtended,
});
+
jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(true);
});
- describe('buttons', () => {
- beforeEach(async () => {
- await findTestButton().vm.$emit('click', new Event('click'));
- });
-
- it('sets test button `loading` prop to `true`', () => {
- expect(findTestButton().props('loading')).toBe(true);
- });
-
- it('sets save button `disabled` prop to `true`', () => {
- expect(findProjectSaveButton().props('disabled')).toBe(true);
- });
+ it('flips `isTesting` to `true`', async () => {
+ findFormActions().vm.$emit('test');
+ await nextTick();
+ expect(findFormActions().props('isTesting')).toBe(true);
});
describe.each`
@@ -614,7 +471,7 @@ describe('IntegrationForm', () => {
service_response: serviceResponse,
});
- await findTestButton().vm.$emit('click', new Event('click'));
+ findFormActions().vm.$emit('test');
await waitForPromises();
});
@@ -622,14 +479,6 @@ describe('IntegrationForm', () => {
expect(mockToastShow).toHaveBeenCalledWith(expectToast);
});
- it('sets `loading` prop of test button to `false`', () => {
- expect(findTestButton().props('loading')).toBe(false);
- });
-
- it('sets save button `disabled` prop to `false`', () => {
- expect(findProjectSaveButton().props('disabled')).toBe(false);
- });
-
it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => {
expect(Sentry.captureException).toHaveBeenCalledTimes(expectSentry ? 1 : 0);
});
@@ -638,44 +487,27 @@ describe('IntegrationForm', () => {
});
});
- describe('when `reset-confirmation-modal` emits `reset` event', () => {
+ describe('Response to the "reset" event from the actions', () => {
const mockResetPath = '/reset';
- describe('buttons', () => {
- beforeEach(async () => {
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.GROUP,
- canTest: true,
- resetPath: mockResetPath,
- },
- });
-
- await findResetConfirmationModal().vm.$emit('reset');
+ beforeEach(async () => {
+ mockAxios.onPost(mockResetPath).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
+ createComponent({
+ customStateProps: {
+ resetPath: mockResetPath,
+ },
});
- it('sets reset button `loading` prop to `true`', () => {
- expect(findResetButton().props('loading')).toBe(true);
- });
+ findFormActions().vm.$emit('reset');
+ await nextTick();
+ });
- it('sets other button `disabled` props to `true`', () => {
- expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(true);
- expect(findTestButton().props('disabled')).toBe(true);
- });
+ it('flips `isResetting` to `true`', () => {
+ expect(findFormActions().props('isResetting')).toBe(true);
});
describe('when "reset settings" request fails', () => {
beforeEach(async () => {
- mockAxios.onPost(mockResetPath).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
- createComponent({
- customStateProps: {
- integrationLevel: integrationLevels.GROUP,
- canTest: true,
- resetPath: mockResetPath,
- },
- });
-
- await findResetConfirmationModal().vm.$emit('reset');
await waitForPromises();
});
@@ -687,13 +519,8 @@ describe('IntegrationForm', () => {
expect(Sentry.captureException).toHaveBeenCalledTimes(1);
});
- it('sets reset button `loading` prop to `false`', () => {
- expect(findResetButton().props('loading')).toBe(false);
- });
-
- it('sets button `disabled` props to `false`', () => {
- expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(false);
- expect(findTestButton().props('disabled')).toBe(false);
+ it('resets `isResetting`', () => {
+ expect(findFormActions().props('isResetting')).toBe(false);
});
});
@@ -702,64 +529,74 @@ describe('IntegrationForm', () => {
mockAxios.onPost(mockResetPath).replyOnce(httpStatus.OK);
createComponent({
customStateProps: {
- integrationLevel: integrationLevels.GROUP,
resetPath: mockResetPath,
},
});
- await findResetConfirmationModal().vm.$emit('reset');
+ findFormActions().vm.$emit('reset');
await waitForPromises();
});
it('calls `refreshCurrentPage`', () => {
expect(refreshCurrentPage).toHaveBeenCalledTimes(1);
});
- });
- describe('Slack integration', () => {
- describe('Help and sections rendering', () => {
- const dummyHelp = 'Foo Help';
-
- it.each`
- integration | flagIsOn | helpHtml | sections | shouldShowSections | shouldShowHelp
- ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${''} | ${[]} | ${false} | ${false}
- ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
- ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${false} | ${false}
- ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${false} | ${true}
- ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${''} | ${[]} | ${false} | ${false}
- ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
- ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
- ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${true}
- ${'foo'} | ${false} | ${''} | ${[]} | ${false} | ${false}
- ${'foo'} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
- ${'foo'} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
- ${'foo'} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
- ${'foo'} | ${true} | ${''} | ${[]} | ${false} | ${false}
- ${'foo'} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
- ${'foo'} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
- ${'foo'} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
- `(
- '$sections sections, and "$helpHtml" helpHtml when the FF is "$flagIsOn" for "$integration" integration',
- ({ integration, flagIsOn, helpHtml, sections, shouldShowSections, shouldShowHelp }) => {
- createComponent({
- provide: {
- helpHtml,
- glFeatures: { integrationSlackAppNotifications: flagIsOn },
- },
- customStateProps: {
- sections,
- type: integration,
- },
- });
- expect(findAllSections().length > 0).toEqual(shouldShowSections);
- expect(findHelpHtml().exists()).toBe(shouldShowHelp);
- if (shouldShowHelp) {
- expect(findHelpHtml().html()).toContain(helpHtml);
- }
- },
- );
+ it('resets `isResetting`', async () => {
+ expect(findFormActions().props('isResetting')).toBe(false);
});
+ });
+ });
+
+ describe('Slack integration', () => {
+ describe('Help and sections rendering', () => {
+ const dummyHelp = 'Foo Help';
+
+ it.each`
+ integration | flagIsOn | helpHtml | sections | shouldShowSections | shouldShowHelp
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${''} | ${[]} | ${false} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${false} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${false} | ${true}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${''} | ${[]} | ${false} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${true}
+ ${'foo'} | ${false} | ${''} | ${[]} | ${false} | ${false}
+ ${'foo'} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${'foo'} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${'foo'} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${'foo'} | ${true} | ${''} | ${[]} | ${false} | ${false}
+ ${'foo'} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${'foo'} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${'foo'} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
+ `(
+ '$sections sections, and "$helpHtml" helpHtml when the FF is "$flagIsOn" for "$integration" integration',
+ ({ integration, flagIsOn, helpHtml, sections, shouldShowSections, shouldShowHelp }) => {
+ createComponent({
+ provide: {
+ helpHtml,
+ glFeatures: { integrationSlackAppNotifications: flagIsOn },
+ },
+ customStateProps: {
+ sections,
+ type: integration,
+ },
+ });
+ expect(findAllSections().length > 0).toEqual(shouldShowSections);
+ expect(findHelpHtml().exists()).toBe(shouldShowHelp);
+ if (shouldShowHelp) {
+ expect(findHelpHtml().html()).toContain(helpHtml);
+ }
+ },
+ );
+ });
+ describe.each`
+ hasSections | hasFieldsWithoutSections | description
+ ${true} | ${true} | ${'When having both: the sections and the fields without a section'}
+ ${true} | ${false} | ${'When having the sections only'}
+ ${false} | ${true} | ${'When having only the fields without a section'}
+ `('$description', ({ hasSections, hasFieldsWithoutSections }) => {
it.each`
prefix | integration | shouldUpgradeSlack | flagIsOn | shouldShowAlert
${'does'} | ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${true} | ${true}
@@ -769,7 +606,7 @@ describe('IntegrationForm', () => {
${'does not'} | ${'foo'} | ${false} | ${true} | ${false}
${'does not'} | ${'foo'} | ${true} | ${false} | ${false}
`(
- '$prefix render the upgrade warnning when we are in "$integration" integration with the flag "$flagIsOn" and Slack-needs-upgrade is "$shouldUpgradeSlack"',
+ '$prefix render the upgrade warning when we are in "$integration" integration with the flag "$flagIsOn" and Slack-needs-upgrade is "$shouldUpgradeSlack" and have sections',
({ integration, shouldUpgradeSlack, flagIsOn, shouldShowAlert }) => {
createComponent({
provide: {
@@ -778,7 +615,8 @@ describe('IntegrationForm', () => {
customStateProps: {
shouldUpgradeSlack,
type: integration,
- sections: [mockSectionConnection],
+ sections: hasSections ? [mockSectionConnection] : [],
+ fields: hasFieldsWithoutSections ? [mockField] : [],
},
});
expect(findAlert().exists()).toBe(shouldShowAlert);