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.js413
1 files changed, 273 insertions, 140 deletions
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index 4c1394f3a87..8cf8a403e5d 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -1,9 +1,10 @@
+import { GlForm } from '@gitlab/ui';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import * as Sentry from '@sentry/browser';
import { setHTMLFixture } from 'helpers/fixtures';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { mockIntegrationProps } from 'jest/integrations/edit/mock_data';
+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';
@@ -13,7 +14,6 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field
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 waitForPromises from 'helpers/wait_for_promises';
import {
integrationLevels,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
@@ -23,9 +23,12 @@ import {
import { createStore } from '~/integrations/edit/store';
import eventHub from '~/integrations/edit/event_hub';
import httpStatus from '~/lib/utils/http_status';
+import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import { mockIntegrationProps } from '../mock_data';
jest.mock('~/integrations/edit/event_hub');
jest.mock('@sentry/browser');
+jest.mock('~/lib/utils/url_utility');
describe('IntegrationForm', () => {
const mockToastShow = jest.fn();
@@ -34,12 +37,18 @@ describe('IntegrationForm', () => {
let dispatch;
let mockAxios;
let mockForm;
+ let vueIntegrationFormFeatureFlag;
+
+ const createForm = () => {
+ mockForm = document.createElement('form');
+ jest.spyOn(document, 'querySelector').mockReturnValue(mockForm);
+ };
const createComponent = ({
customStateProps = {},
- featureFlags = {},
initialState = {},
props = {},
+ mountFn = shallowMountExtended,
} = {}) => {
const store = createStore({
customState: { ...mockIntegrationProps, ...customStateProps },
@@ -47,11 +56,12 @@ describe('IntegrationForm', () => {
});
dispatch = jest.spyOn(store, 'dispatch').mockImplementation();
- wrapper = shallowMountExtended(IntegrationForm, {
- propsData: { ...props, formSelector: '.test' },
- provide: {
- glFeatures: featureFlags,
- },
+ if (!vueIntegrationFormFeatureFlag) {
+ createForm();
+ }
+
+ wrapper = mountFn(IntegrationForm, {
+ propsData: { ...props },
store,
stubs: {
OverrideDropdown,
@@ -65,26 +75,33 @@ describe('IntegrationForm', () => {
show: mockToastShow,
},
},
+ provide: {
+ glFeatures: {
+ vueIntegrationForm: vueIntegrationFormFeatureFlag,
+ },
+ },
});
};
- const createForm = ({ isValid = true } = {}) => {
- mockForm = document.createElement('form');
- jest.spyOn(document, 'querySelector').mockReturnValue(mockForm);
- jest.spyOn(mockForm, 'checkValidity').mockReturnValue(isValid);
- jest.spyOn(mockForm, 'submit');
- };
-
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 findSaveButton = () => wrapper.findByTestId('save-button');
+ const findProjectSaveButton = () => wrapper.findByTestId('save-button');
+ const findInstanceOrGroupSaveButton = () => wrapper.findByTestId('save-button-instance-group');
const findTestButton = () => wrapper.findByTestId('test-button');
const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields);
const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields);
const findTriggerFields = () => wrapper.findComponent(TriggerFields);
+ const findGlForm = () => wrapper.findComponent(GlForm);
+ const findRedirectToField = () => wrapper.findByTestId('redirect-to-field');
+ const findFormElement = () => (vueIntegrationFormFeatureFlag ? findGlForm().element : mockForm);
+
+ const mockFormFunctions = ({ checkValidityReturn }) => {
+ jest.spyOn(findFormElement(), 'checkValidity').mockReturnValue(checkValidityReturn);
+ jest.spyOn(findFormElement(), 'submit');
+ };
beforeEach(() => {
mockAxios = new MockAdapter(axios);
@@ -220,6 +237,7 @@ describe('IntegrationForm', () => {
createComponent({
customStateProps: { type: 'jira', testPath: '/test' },
+ mountFn: mountExtended,
});
});
@@ -338,6 +356,19 @@ describe('IntegrationForm', () => {
});
});
});
+
+ describe('when `vueIntegrationForm` feature flag is $vueIntegrationFormEnabled', () => {
+ it('renders hidden fields', () => {
+ vueIntegrationFormFeatureFlag = true;
+ createComponent({
+ customStateProps: {
+ redirectTo: '/services',
+ },
+ });
+
+ expect(findRedirectToField().attributes('value')).toBe('/services');
+ });
+ });
});
describe('ActiveCheckbox', () => {
@@ -358,190 +389,292 @@ describe('IntegrationForm', () => {
});
describe.each`
- formActive | novalidate
- ${true} | ${null}
- ${false} | ${'true'}
+ formActive | vueIntegrationFormEnabled | novalidate
+ ${true} | ${true} | ${null}
+ ${false} | ${true} | ${'novalidate'}
+ ${true} | ${false} | ${null}
+ ${false} | ${false} | ${'true'}
`(
- 'when `toggle-integration-active` is emitted with $formActive',
- ({ formActive, novalidate }) => {
+ 'when `vueIntegrationForm` feature flag is $vueIntegrationFormEnabled and `toggle-integration-active` is emitted with $formActive',
+ ({ formActive, vueIntegrationFormEnabled, novalidate }) => {
beforeEach(async () => {
- createForm();
+ vueIntegrationFormFeatureFlag = vueIntegrationFormEnabled;
+
createComponent({
customStateProps: {
showActive: true,
initialActivated: false,
},
+ mountFn: mountExtended,
});
+ mockFormFunctions({ checkValidityReturn: false });
await findActiveCheckbox().vm.$emit('toggle-integration-active', formActive);
});
it(`sets noValidate to ${novalidate}`, () => {
- expect(mockForm.getAttribute('novalidate')).toBe(novalidate);
+ expect(findFormElement().getAttribute('novalidate')).toBe(novalidate);
});
},
);
});
- describe('when `save` button is clicked', () => {
- describe('buttons', () => {
- beforeEach(async () => {
- createForm();
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: true,
- },
+ describe.each`
+ vueIntegrationFormEnabled
+ ${true}
+ ${false}
+ `(
+ 'when `vueIntegrationForm` feature flag is $vueIntegrationFormEnabled',
+ ({ vueIntegrationFormEnabled }) => {
+ beforeEach(() => {
+ vueIntegrationFormFeatureFlag = vueIntegrationFormEnabled;
+ });
+
+ 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);
+ });
+
+ it('sets test button `disabled` prop to `true`', () => {
+ expect(findTestButton().props('disabled')).toBe(true);
+ });
});
- await findSaveButton().vm.$emit('click', new Event('click'));
- });
+ describe.each`
+ checkValidityReturn | integrationActive
+ ${true} | ${false}
+ ${true} | ${true}
+ ${false} | ${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,
+ });
+
+ mockFormFunctions({ checkValidityReturn });
+
+ await findProjectSaveButton().vm.$emit('click', new Event('click'));
+ });
+
+ it('submits form', () => {
+ expect(findFormElement().submit).toHaveBeenCalledTimes(1);
+ });
+ },
+ );
+
+ describe('when form is invalid (checkValidity returns false and integrationActive is true)', () => {
+ beforeEach(async () => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ initialActivated: true,
+ },
+ mountFn: mountExtended,
+ });
+ mockFormFunctions({ checkValidityReturn: false });
+
+ await findProjectSaveButton().vm.$emit('click', new Event('click'));
+ });
- it('sets save button `loading` prop to `true`', () => {
- expect(findSaveButton().props('loading')).toBe(true);
- });
+ it('does not submit form', () => {
+ expect(findFormElement().submit).not.toHaveBeenCalled();
+ });
- it('sets test button `disabled` prop to `true`', () => {
- expect(findTestButton().props('disabled')).toBe(true);
- });
- });
+ it('sets save button `loading` prop to `false`', () => {
+ expect(findProjectSaveButton().props('loading')).toBe(false);
+ });
- describe.each`
- checkValidityReturn | integrationActive
- ${true} | ${false}
- ${true} | ${true}
- ${false} | ${false}
- `(
- 'when form is valid (checkValidity returns $checkValidityReturn and integrationActive is $integrationActive)',
- ({ integrationActive, checkValidityReturn }) => {
- beforeEach(async () => {
- createForm({ isValid: checkValidityReturn });
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: integrationActive,
- },
+ it('sets test button `disabled` prop to `false`', () => {
+ expect(findTestButton().props('disabled')).toBe(false);
});
- await findSaveButton().vm.$emit('click', new Event('click'));
+ it('emits `VALIDATE_INTEGRATION_FORM_EVENT`', () => {
+ expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
+ });
});
+ });
- it('submit form', () => {
- expect(mockForm.submit).toHaveBeenCalledTimes(1);
- });
- },
- );
+ describe('when `test` button is clicked', () => {
+ describe('when form is invalid', () => {
+ it('emits `VALIDATE_INTEGRATION_FORM_EVENT` event to the event hub', () => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ },
+ mountFn: mountExtended,
+ });
+ mockFormFunctions({ checkValidityReturn: false });
- describe('when form is invalid (checkValidity returns false and integrationActive is true)', () => {
- beforeEach(async () => {
- createForm({ isValid: false });
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: true,
- },
+ findTestButton().vm.$emit('click', new Event('click'));
+
+ expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
+ });
});
- await findSaveButton().vm.$emit('click', new Event('click'));
- });
+ describe('when form is valid', () => {
+ const mockTestPath = '/test';
- it('does not submit form', () => {
- expect(mockForm.submit).not.toHaveBeenCalled();
- });
+ beforeEach(() => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ testPath: mockTestPath,
+ },
+ mountFn: mountExtended,
+ });
+ mockFormFunctions({ checkValidityReturn: true });
+ });
- it('sets save button `loading` prop to `false`', () => {
- expect(findSaveButton().props('loading')).toBe(false);
- });
+ describe('buttons', () => {
+ beforeEach(async () => {
+ await findTestButton().vm.$emit('click', new Event('click'));
+ });
- it('sets test button `disabled` prop to `false`', () => {
- expect(findTestButton().props('disabled')).toBe(false);
- });
+ it('sets test button `loading` prop to `true`', () => {
+ expect(findTestButton().props('loading')).toBe(true);
+ });
- it('emits `VALIDATE_INTEGRATION_FORM_EVENT`', () => {
- expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
+ it('sets save button `disabled` prop to `true`', () => {
+ expect(findProjectSaveButton().props('disabled')).toBe(true);
+ });
+ });
+
+ describe.each`
+ scenario | replyStatus | errorMessage | expectToast | expectSentry
+ ${'when "test settings" request fails'} | ${httpStatus.INTERNAL_SERVER_ERROR} | ${undefined} | ${I18N_DEFAULT_ERROR_MESSAGE} | ${true}
+ ${'when "test settings" returns an error'} | ${httpStatus.OK} | ${'an error'} | ${'an error'} | ${false}
+ ${'when "test settings" succeeds'} | ${httpStatus.OK} | ${undefined} | ${I18N_SUCCESSFUL_CONNECTION_MESSAGE} | ${false}
+ `('$scenario', ({ replyStatus, errorMessage, expectToast, expectSentry }) => {
+ beforeEach(async () => {
+ mockAxios.onPut(mockTestPath).replyOnce(replyStatus, {
+ error: Boolean(errorMessage),
+ message: errorMessage,
+ });
+
+ await findTestButton().vm.$emit('click', new Event('click'));
+ await waitForPromises();
+ });
+
+ it(`calls toast with '${expectToast}'`, () => {
+ 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);
+ });
+ });
+ });
});
- });
- });
+ },
+ );
+
+ describe('when `reset-confirmation-modal` emits `reset` event', () => {
+ const mockResetPath = '/reset';
- describe('when `test` button is clicked', () => {
- describe('when form is invalid', () => {
- it('emits `VALIDATE_INTEGRATION_FORM_EVENT` event to the event hub', () => {
- createForm({ isValid: false });
+ describe('buttons', () => {
+ beforeEach(async () => {
createComponent({
customStateProps: {
- showActive: true,
+ integrationLevel: integrationLevels.GROUP,
canTest: true,
+ resetPath: mockResetPath,
},
});
- findTestButton().vm.$emit('click', new Event('click'));
+ await findResetConfirmationModal().vm.$emit('reset');
+ });
- expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
+ it('sets reset button `loading` prop to `true`', () => {
+ expect(findResetButton().props('loading')).toBe(true);
});
- });
- describe('when form is valid', () => {
- const mockTestPath = '/test';
+ it('sets other button `disabled` props to `true`', () => {
+ expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(true);
+ expect(findTestButton().props('disabled')).toBe(true);
+ });
+ });
- beforeEach(() => {
- createForm({ isValid: true });
+ describe('when "reset settings" request fails', () => {
+ beforeEach(async () => {
+ mockAxios.onPost(mockResetPath).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
createComponent({
customStateProps: {
- showActive: true,
+ integrationLevel: integrationLevels.GROUP,
canTest: true,
- testPath: mockTestPath,
+ resetPath: mockResetPath,
},
});
- });
-
- 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);
- });
+ await findResetConfirmationModal().vm.$emit('reset');
+ await waitForPromises();
+ });
- it('sets save button `disabled` prop to `true`', () => {
- expect(findSaveButton().props('disabled')).toBe(true);
- });
+ it('displays a toast', () => {
+ expect(mockToastShow).toHaveBeenCalledWith(I18N_DEFAULT_ERROR_MESSAGE);
});
- describe.each`
- scenario | replyStatus | errorMessage | expectToast | expectSentry
- ${'when "test settings" request fails'} | ${httpStatus.INTERNAL_SERVER_ERROR} | ${undefined} | ${I18N_DEFAULT_ERROR_MESSAGE} | ${true}
- ${'when "test settings" returns an error'} | ${httpStatus.OK} | ${'an error'} | ${'an error'} | ${false}
- ${'when "test settings" succeeds'} | ${httpStatus.OK} | ${undefined} | ${I18N_SUCCESSFUL_CONNECTION_MESSAGE} | ${false}
- `('$scenario', ({ replyStatus, errorMessage, expectToast, expectSentry }) => {
- beforeEach(async () => {
- mockAxios.onPut(mockTestPath).replyOnce(replyStatus, {
- error: Boolean(errorMessage),
- message: errorMessage,
- });
+ it('captures exception in Sentry', () => {
+ expect(Sentry.captureException).toHaveBeenCalledTimes(1);
+ });
- await findTestButton().vm.$emit('click', new Event('click'));
- await waitForPromises();
- });
+ it('sets reset button `loading` prop to `false`', () => {
+ expect(findResetButton().props('loading')).toBe(false);
+ });
- it(`calls toast with '${expectToast}'`, () => {
- expect(mockToastShow).toHaveBeenCalledWith(expectToast);
- });
+ it('sets button `disabled` props to `false`', () => {
+ expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(false);
+ expect(findTestButton().props('disabled')).toBe(false);
+ });
+ });
- it('sets `loading` prop of test button to `false`', () => {
- expect(findTestButton().props('loading')).toBe(false);
+ describe('when "reset settings" succeeds', () => {
+ beforeEach(async () => {
+ mockAxios.onPost(mockResetPath).replyOnce(httpStatus.OK);
+ createComponent({
+ customStateProps: {
+ integrationLevel: integrationLevels.GROUP,
+ resetPath: mockResetPath,
+ },
});
- it('sets save button `disabled` prop to `false`', () => {
- expect(findSaveButton().props('disabled')).toBe(false);
- });
+ await findResetConfirmationModal().vm.$emit('reset');
+ await waitForPromises();
+ });
- it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => {
- expect(Sentry.captureException).toHaveBeenCalledTimes(expectSentry ? 1 : 0);
- });
+ it('calls `refreshCurrentPage`', () => {
+ expect(refreshCurrentPage).toHaveBeenCalledTimes(1);
});
});
});