diff --git a/awx/ui_next/src/screens/Project/ProjectAdd/ProjectAdd.test.jsx b/awx/ui_next/src/screens/Project/ProjectAdd/ProjectAdd.test.jsx index 2b9857bc89..3bd0469dea 100644 --- a/awx/ui_next/src/screens/Project/ProjectAdd/ProjectAdd.test.jsx +++ b/awx/ui_next/src/screens/Project/ProjectAdd/ProjectAdd.test.jsx @@ -108,7 +108,11 @@ describe('', () => { ); }); await changeState; - wrapper.find('form').simulate('submit'); + await act(async () => { + wrapper.find('form').simulate('submit'); + }); + wrapper.update(); + expect(ProjectsAPI.create).toHaveBeenCalledTimes(1); }); test('handleSubmit should throw an error', async () => { diff --git a/awx/ui_next/src/screens/Project/ProjectEdit/ProjectEdit.test.jsx b/awx/ui_next/src/screens/Project/ProjectEdit/ProjectEdit.test.jsx new file mode 100644 index 0000000000..99975a807b --- /dev/null +++ b/awx/ui_next/src/screens/Project/ProjectEdit/ProjectEdit.test.jsx @@ -0,0 +1,153 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { createMemoryHistory } from 'history'; +import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers'; +import ProjectEdit from './ProjectEdit'; +import { ProjectsAPI, CredentialTypesAPI } from '@api'; + +jest.mock('@api'); + +describe('', () => { + let wrapper; + const projectData = { + id: 123, + name: 'foo', + description: 'bar', + scm_type: 'git', + scm_url: 'https://foo.bar', + scm_clean: true, + credential: 100, + organization: 2, + scm_update_on_launch: true, + scm_update_cache_timeout: 3, + allow_override: false, + custom_virtualenv: '/venv/custom-env', + summary_fields: { + credential: { + id: 100, + credential_type_id: 5, + kind: 'insights', + }, + }, + }; + + const projectOptionsResolve = { + data: { + actions: { + GET: { + scm_type: { + choices: [ + ['', 'Manual'], + ['git', 'Git'], + ['hg', 'Mercurial'], + ['svn', 'Subversion'], + ['insights', 'Red Hat Insights'], + ], + }, + }, + }, + }, + }; + + const scmCredentialResolve = { + data: { + results: [ + { + id: 4, + name: 'Source Control', + kind: 'scm', + }, + ], + }, + }; + + const insightsCredentialResolve = { + data: { + results: [ + { + id: 5, + name: 'Insights', + kind: 'insights', + }, + ], + }, + }; + + beforeEach(async () => { + await ProjectsAPI.readOptions.mockImplementation( + () => projectOptionsResolve + ); + await CredentialTypesAPI.read.mockImplementationOnce( + () => scmCredentialResolve + ); + await CredentialTypesAPI.read.mockImplementationOnce( + () => insightsCredentialResolve + ); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('initially renders successfully', async () => { + await act(async () => { + wrapper = mountWithContexts(); + }); + expect(wrapper.length).toBe(1); + }); + + test('handleSubmit should post to the api', async () => { + const history = createMemoryHistory(); + ProjectsAPI.update.mockResolvedValueOnce({ + data: { ...projectData }, + }); + await act(async () => { + wrapper = mountWithContexts(, { + context: { router: { history } }, + }); + }); + await waitForElement(wrapper, 'ContentLoading', el => el.length === 0); + await act(async () => { + wrapper.find('form').simulate('submit'); + }); + wrapper.update(); + expect(ProjectsAPI.update).toHaveBeenCalledTimes(1); + }); + + test('handleSubmit should throw an error', async () => { + ProjectsAPI.update.mockImplementation(() => Promise.reject(new Error())); + await act(async () => { + wrapper = mountWithContexts(); + }); + await waitForElement(wrapper, 'ContentLoading', el => el.length === 0); + await act(async () => { + wrapper.find('form').simulate('submit'); + }); + wrapper.update(); + expect(ProjectsAPI.update).toHaveBeenCalledTimes(1); + expect(wrapper.find('ProjectEdit .formSubmitError').length).toBe(1); + }); + + test('CardHeader close button should navigate to project details', async () => { + const history = createMemoryHistory(); + await act(async () => { + wrapper = mountWithContexts(, { + context: { router: { history } }, + }); + }); + wrapper.find('CardCloseButton').simulate('click'); + expect(history.location.pathname).toEqual('/projects/123/details'); + }); + + test('CardBody cancel button should navigate to project details', async () => { + const history = createMemoryHistory(); + await act(async () => { + wrapper = mountWithContexts(, { + context: { router: { history } }, + }); + }); + await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); + wrapper.find('ProjectEdit button[aria-label="Cancel"]').simulate('click'); + expect(history.location.pathname).toEqual('/projects/123/details'); + }); +}); diff --git a/awx/ui_next/src/screens/Project/shared/ProjectForm.jsx b/awx/ui_next/src/screens/Project/shared/ProjectForm.jsx index 94126eb1c7..046e90fa27 100644 --- a/awx/ui_next/src/screens/Project/shared/ProjectForm.jsx +++ b/awx/ui_next/src/screens/Project/shared/ProjectForm.jsx @@ -122,16 +122,23 @@ function ProjectForm({ project, ...props }) { scm_update_cache_timeout: 0, }; + /* Save current scm subform field values to state */ const saveSubFormState = form => { - const updatedScmFormFields = { ...scmFormFields }; + const currentScmFormFields = { ...scmFormFields }; - Object.keys(updatedScmFormFields).forEach(label => { - updatedScmFormFields[label] = form.values[label]; + Object.keys(currentScmFormFields).forEach(label => { + currentScmFormFields[label] = form.values[label]; }); - setScmSubFormState(updatedScmFormFields); + setScmSubFormState(currentScmFormFields); }; + /** + * If scm type is !== the initial scm type value, + * reset scm subform field values to defaults. + * If scm type is === the initial scm type value, + * reset scm subform field values to scmSubFormState. + */ const resetScmTypeFields = (value, form) => { if (form.values.scm_type === form.initialValues.scm_type) { saveSubFormState(form); diff --git a/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx b/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx index 18b4c5f680..550f60f7c4 100644 --- a/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx +++ b/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx @@ -21,6 +21,13 @@ describe('', () => { scm_update_cache_timeout: 3, allow_override: false, custom_virtualenv: '/venv/custom-env', + summary_fields: { + credential: { + id: 100, + credential_type_id: 4, + kind: 'scm', + }, + }, }; const projectOptionsResolve = {