diff options
Diffstat (limited to 'spec/frontend/integrations/integration_settings_form_spec.js')
-rw-r--r-- | spec/frontend/integrations/integration_settings_form_spec.js | 303 |
1 files changed, 170 insertions, 133 deletions
diff --git a/spec/frontend/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js index f8f3f0fd318..c35d178e518 100644 --- a/spec/frontend/integrations/integration_settings_form_spec.js +++ b/spec/frontend/integrations/integration_settings_form_spec.js @@ -1,27 +1,38 @@ import MockAdaptor from 'axios-mock-adapter'; import IntegrationSettingsForm from '~/integrations/integration_settings_form'; +import eventHub from '~/integrations/edit/event_hub'; import axios from '~/lib/utils/axios_utils'; import toast from '~/vue_shared/plugins/global_toast'; +import { + I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE, + I18N_SUCCESSFUL_CONNECTION_MESSAGE, + I18N_DEFAULT_ERROR_MESSAGE, + GET_JIRA_ISSUE_TYPES_EVENT, + TOGGLE_INTEGRATION_EVENT, + TEST_INTEGRATION_EVENT, + SAVE_INTEGRATION_EVENT, +} from '~/integrations/constants'; +import waitForPromises from 'helpers/wait_for_promises'; jest.mock('~/vue_shared/plugins/global_toast'); +jest.mock('lodash/delay', () => (callback) => callback()); + +const FIXTURE = 'services/edit_service.html'; describe('IntegrationSettingsForm', () => { - const FIXTURE = 'services/edit_service.html'; + let integrationSettingsForm; + + const mockStoreDispatch = () => jest.spyOn(integrationSettingsForm.vue.$store, 'dispatch'); beforeEach(() => { loadFixtures(FIXTURE); + + integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form'); + integrationSettingsForm.init(); }); describe('constructor', () => { - let integrationSettingsForm; - - beforeEach(() => { - integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form'); - jest.spyOn(integrationSettingsForm, 'init').mockImplementation(() => {}); - }); - it('should initialize form element refs on class object', () => { - // Form Reference expect(integrationSettingsForm.$form).toBeDefined(); expect(integrationSettingsForm.$form.nodeName).toBe('FORM'); expect(integrationSettingsForm.formActive).toBeDefined(); @@ -32,180 +43,206 @@ describe('IntegrationSettingsForm', () => { }); }); - describe('toggleServiceState', () => { - let integrationSettingsForm; + describe('event handling', () => { + let mockAxios; beforeEach(() => { - integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form'); - }); - - it('should remove `novalidate` attribute to form when called with `true`', () => { - integrationSettingsForm.formActive = true; - integrationSettingsForm.toggleServiceState(); - - expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe(null); - }); - - it('should set `novalidate` attribute to form when called with `false`', () => { - integrationSettingsForm.formActive = false; - integrationSettingsForm.toggleServiceState(); - - expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBeDefined(); - }); - }); - - describe('testSettings', () => { - let integrationSettingsForm; - let formData; - let mock; - - beforeEach(() => { - mock = new MockAdaptor(axios); - + mockAxios = new MockAdaptor(axios); jest.spyOn(axios, 'put'); - - integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form'); - integrationSettingsForm.init(); - - formData = new FormData(integrationSettingsForm.$form); }); afterEach(() => { - mock.restore(); + mockAxios.restore(); + eventHub.dispose(); // clear event hub handlers }); - it('should make an ajax request with provided `formData`', async () => { - await integrationSettingsForm.testSettings(formData); + describe('when event hub receives `TOGGLE_INTEGRATION_EVENT`', () => { + it('should remove `novalidate` attribute to form when called with `true`', () => { + eventHub.$emit(TOGGLE_INTEGRATION_EVENT, true); - expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData); - }); + expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe(null); + }); - it('should show success message if test is successful', async () => { - jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {}); + it('should set `novalidate` attribute to form when called with `false`', () => { + eventHub.$emit(TOGGLE_INTEGRATION_EVENT, false); - mock.onPut(integrationSettingsForm.testEndPoint).reply(200, { - error: false, + expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe('novalidate'); }); + }); - await integrationSettingsForm.testSettings(formData); + describe('when event hub receives `TEST_INTEGRATION_EVENT`', () => { + describe('when form is valid', () => { + beforeEach(() => { + jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(true); + }); - expect(toast).toHaveBeenCalledWith('Connection successful.'); - }); + it('should make an ajax request with provided `formData`', async () => { + eventHub.$emit(TEST_INTEGRATION_EVENT); + await waitForPromises(); - it('should show error message if ajax request responds with test error', async () => { - const errorMessage = 'Test failed.'; - const serviceResponse = 'some error'; + expect(axios.put).toHaveBeenCalledWith( + integrationSettingsForm.testEndPoint, + new FormData(integrationSettingsForm.$form), + ); + }); - mock.onPut(integrationSettingsForm.testEndPoint).reply(200, { - error: true, - message: errorMessage, - service_response: serviceResponse, - test_failed: false, - }); + it('should show success message if test is successful', async () => { + jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {}); - await integrationSettingsForm.testSettings(formData); + mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, { + error: false, + }); - expect(toast).toHaveBeenCalledWith(`${errorMessage} ${serviceResponse}`); - }); + eventHub.$emit(TEST_INTEGRATION_EVENT); + await waitForPromises(); - it('should show error message if ajax request failed', async () => { - const errorMessage = 'Something went wrong on our end.'; + expect(toast).toHaveBeenCalledWith(I18N_SUCCESSFUL_CONNECTION_MESSAGE); + }); - mock.onPut(integrationSettingsForm.testEndPoint).networkError(); + it('should show error message if ajax request responds with test error', async () => { + const errorMessage = 'Test failed.'; + const serviceResponse = 'some error'; - await integrationSettingsForm.testSettings(formData); + mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, { + error: true, + message: errorMessage, + service_response: serviceResponse, + test_failed: false, + }); - expect(toast).toHaveBeenCalledWith(errorMessage); - }); + eventHub.$emit(TEST_INTEGRATION_EVENT); + await waitForPromises(); - it('should always dispatch `setIsTesting` with `false` once request is completed', async () => { - const dispatchSpy = jest.fn(); + expect(toast).toHaveBeenCalledWith(`${errorMessage} ${serviceResponse}`); + }); - mock.onPut(integrationSettingsForm.testEndPoint).networkError(); + it('should show error message if ajax request failed', async () => { + mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError(); - integrationSettingsForm.vue.$store = { dispatch: dispatchSpy }; + eventHub.$emit(TEST_INTEGRATION_EVENT); + await waitForPromises(); - await integrationSettingsForm.testSettings(formData); + expect(toast).toHaveBeenCalledWith(I18N_DEFAULT_ERROR_MESSAGE); + }); - expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false); - }); - }); + it('should always dispatch `setIsTesting` with `false` once request is completed', async () => { + const dispatchSpy = mockStoreDispatch(); + mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError(); - describe('getJiraIssueTypes', () => { - let integrationSettingsForm; - let formData; - let mock; + eventHub.$emit(TEST_INTEGRATION_EVENT); + await waitForPromises(); - beforeEach(() => { - mock = new MockAdaptor(axios); + expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false); + }); + }); - jest.spyOn(axios, 'put'); + describe('when form is invalid', () => { + beforeEach(() => { + jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(false); + jest.spyOn(integrationSettingsForm, 'testSettings'); + }); - integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form'); - integrationSettingsForm.init(); + it('should dispatch `setIsTesting` with `false` and not call `testSettings`', async () => { + const dispatchSpy = mockStoreDispatch(); - formData = new FormData(integrationSettingsForm.$form); - }); + eventHub.$emit(TEST_INTEGRATION_EVENT); + await waitForPromises(); - afterEach(() => { - mock.restore(); + expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false); + expect(integrationSettingsForm.testSettings).not.toHaveBeenCalled(); + }); + }); }); - it('should always dispatch `requestJiraIssueTypes`', async () => { - const dispatchSpy = jest.fn(); - - mock.onPut(integrationSettingsForm.testEndPoint).networkError(); + describe('when event hub receives `GET_JIRA_ISSUE_TYPES_EVENT`', () => { + it('should always dispatch `requestJiraIssueTypes`', () => { + const dispatchSpy = mockStoreDispatch(); + mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError(); - integrationSettingsForm.vue.$store = { dispatch: dispatchSpy }; + eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT); - await integrationSettingsForm.getJiraIssueTypes(); + expect(dispatchSpy).toHaveBeenCalledWith('requestJiraIssueTypes'); + }); - expect(dispatchSpy).toHaveBeenCalledWith('requestJiraIssueTypes'); - }); + it('should make an ajax request with provided `formData`', () => { + eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT); - it('should make an ajax request with provided `formData`', async () => { - await integrationSettingsForm.getJiraIssueTypes(formData); + expect(axios.put).toHaveBeenCalledWith( + integrationSettingsForm.testEndPoint, + new FormData(integrationSettingsForm.$form), + ); + }); - expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData); - }); + it('should dispatch `receiveJiraIssueTypesSuccess` with the correct payload if ajax request is successful', async () => { + const dispatchSpy = mockStoreDispatch(); + const mockData = ['ISSUE', 'EPIC']; + mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, { + error: false, + issuetypes: mockData, + }); - it('should dispatch `receiveJiraIssueTypesSuccess` with the correct payload if ajax request is successful', async () => { - const mockData = ['ISSUE', 'EPIC']; - const dispatchSpy = jest.fn(); + eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT); + await waitForPromises(); - mock.onPut(integrationSettingsForm.testEndPoint).reply(200, { - error: false, - issuetypes: mockData, + expect(dispatchSpy).toHaveBeenCalledWith('receiveJiraIssueTypesSuccess', mockData); }); - integrationSettingsForm.vue.$store = { dispatch: dispatchSpy }; - - await integrationSettingsForm.getJiraIssueTypes(formData); + it.each(['Custom error message here', undefined])( + 'should dispatch "receiveJiraIssueTypesError" with a message if the backend responds with error', + async (responseErrorMessage) => { + const dispatchSpy = mockStoreDispatch(); + + const expectedErrorMessage = + responseErrorMessage || I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE; + mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, { + error: true, + message: responseErrorMessage, + }); + + eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT); + await waitForPromises(); + + expect(dispatchSpy).toHaveBeenCalledWith( + 'receiveJiraIssueTypesError', + expectedErrorMessage, + ); + }, + ); + }); + + describe('when event hub receives `SAVE_INTEGRATION_EVENT`', () => { + describe('when form is valid', () => { + beforeEach(() => { + jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(true); + jest.spyOn(integrationSettingsForm.$form, 'submit'); + }); - expect(dispatchSpy).toHaveBeenCalledWith('receiveJiraIssueTypesSuccess', mockData); - }); + it('should submit the form', async () => { + eventHub.$emit(SAVE_INTEGRATION_EVENT); + await waitForPromises(); - it.each(['something went wrong', undefined])( - 'should dispatch "receiveJiraIssueTypesError" with a message if the backend responds with error', - async (responseErrorMessage) => { - const defaultErrorMessage = 'Connection failed. Please check your settings.'; - const expectedErrorMessage = responseErrorMessage || defaultErrorMessage; - const dispatchSpy = jest.fn(); + expect(integrationSettingsForm.$form.submit).toHaveBeenCalled(); + expect(integrationSettingsForm.$form.submit).toHaveBeenCalledTimes(1); + }); + }); - mock.onPut(integrationSettingsForm.testEndPoint).reply(200, { - error: true, - message: responseErrorMessage, + describe('when form is invalid', () => { + beforeEach(() => { + jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(false); + jest.spyOn(integrationSettingsForm.$form, 'submit'); }); - integrationSettingsForm.vue.$store = { dispatch: dispatchSpy }; + it('should dispatch `setIsSaving` with `false` and not submit form', async () => { + const dispatchSpy = mockStoreDispatch(); - await integrationSettingsForm.getJiraIssueTypes(formData); + eventHub.$emit(SAVE_INTEGRATION_EVENT); - expect(dispatchSpy).toHaveBeenCalledWith( - 'receiveJiraIssueTypesError', - expectedErrorMessage, - ); - }, - ); + await waitForPromises(); + + expect(dispatchSpy).toHaveBeenCalledWith('setIsSaving', false); + expect(integrationSettingsForm.$form.submit).not.toHaveBeenCalled(); + }); + }); + }); }); }); |