diff --git a/awx/ui_next/src/screens/Organization/shared/OrganizationForm.jsx b/awx/ui_next/src/screens/Organization/shared/OrganizationForm.jsx
index 49b2f36d7c..360a195048 100644
--- a/awx/ui_next/src/screens/Organization/shared/OrganizationForm.jsx
+++ b/awx/ui_next/src/screens/Organization/shared/OrganizationForm.jsx
@@ -164,6 +164,7 @@ class OrganizationForm extends Component {
label={i18n._(t`Ansible Environment`)}
>
', () => {
).toEqual(true);
expect(wrapper.find('input#template-name').text()).toBe(defaultProps.name);
- expect(wrapper.find('input#template-playbook').text()).toBe(
- defaultProps.playbook
+ expect(wrapper.find('AnsibleSelect[name="playbook"]').text()).toBe(
+ 'Choose a playbook'
);
expect(wrapper.find('ProjectLookup').prop('value')).toBe(null);
done();
@@ -78,7 +79,18 @@ describe('', () => {
});
const wrapper = mountWithContexts();
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
- wrapper.find('JobTemplateForm').prop('handleSubmit')(jobTemplateData);
+ const formik = wrapper.find('Formik').instance();
+ const changeState = new Promise(resolve => {
+ formik.setState(
+ {
+ values: jobTemplateData,
+ },
+ () => resolve()
+ );
+ });
+ await changeState;
+ wrapper.find('form').simulate('submit');
+ await sleep(1);
expect(JobTemplatesAPI.create).toHaveBeenCalledWith(jobTemplateData);
done();
});
@@ -107,6 +119,7 @@ describe('', () => {
});
await wrapper.find('JobTemplateForm').prop('handleSubmit')(jobTemplateData);
+ await sleep(0);
expect(history.push).toHaveBeenCalledWith(
'/templates/job_template/1/details'
);
diff --git a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx
index 9f8f71c100..51e5a3ff65 100644
--- a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx
+++ b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx
@@ -106,13 +106,14 @@ class JobTemplateEdit extends Component {
template: { id },
history,
} = this.props;
+ const { newLabels, removedLabels } = values;
+ delete values.newLabels;
+ delete values.removedLabels;
this.setState({ formSubmitError: null });
try {
- await JobTemplatesAPI.update(id, { ...values });
- await Promise.all([
- this.submitLabels(values.newLabels, values.removedLabels),
- ]);
+ await JobTemplatesAPI.update(id, values);
+ await Promise.all([this.submitLabels(newLabels, removedLabels)]);
history.push(this.detailsUrl);
} catch (formSubmitError) {
this.setState({ formSubmitError });
diff --git a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx
index 0b9ce09b83..682d29b01a 100644
--- a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx
+++ b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx
@@ -1,6 +1,7 @@
import React from 'react';
-import { JobTemplatesAPI, LabelsAPI } from '@api';
+import { sleep } from '@testUtils/testUtils';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
+import { JobTemplatesAPI, LabelsAPI, ProjectsAPI } from '@api';
import JobTemplateEdit from './JobTemplateEdit';
jest.mock('@api');
@@ -74,9 +75,29 @@ const mockRelatedCredentials = {
],
};
+const mockRelatedProjectPlaybooks = [
+ 'check.yml',
+ 'debug-50.yml',
+ 'debug.yml',
+ 'debug2.yml',
+ 'debug_extra_vars.yml',
+ 'dynamic_inventory.yml',
+ 'environ_test.yml',
+ 'fail_unless.yml',
+ 'pass_unless.yml',
+ 'pause.yml',
+ 'ping-20.yml',
+ 'ping.yml',
+ 'setfact_50.yml',
+ 'vault.yml',
+];
+
JobTemplatesAPI.readCredentials.mockResolvedValue({
data: mockRelatedCredentials,
});
+ProjectsAPI.readPlaybooks.mockResolvedValue({
+ data: mockRelatedProjectPlaybooks,
+});
LabelsAPI.read.mockResolvedValue({ data: { results: [] } });
describe('', () => {
@@ -101,20 +122,38 @@ describe('', () => {
const newLabels = [
{ associate: true, id: 3 },
{ associate: true, id: 3 },
- { name: 'Mapel', organization: 1 },
+ { name: 'Maple', organization: 1 },
{ name: 'Tree', organization: 1 },
];
const removedLabels = [
{ disassociate: true, id: 1 },
{ disassociate: true, id: 2 },
];
+ JobTemplatesAPI.update.mockResolvedValue({
+ data: { ...updatedTemplateData },
+ });
+ const formik = wrapper.find('Formik').instance();
+ const changeState = new Promise(resolve => {
+ formik.setState(
+ {
+ values: {
+ ...mockJobTemplate,
+ ...updatedTemplateData,
+ newLabels,
+ removedLabels,
+ },
+ },
+ () => resolve()
+ );
+ });
+ await changeState;
+ wrapper.find('button[aria-label="Save"]').simulate('click');
+ await sleep(0);
- await wrapper.find('JobTemplateForm').prop('handleSubmit')(
- updatedTemplateData,
- newLabels,
- removedLabels
- );
- expect(JobTemplatesAPI.update).toHaveBeenCalledWith(1, updatedTemplateData);
+ expect(JobTemplatesAPI.update).toHaveBeenCalledWith(1, {
+ ...mockJobTemplate,
+ ...updatedTemplateData,
+ });
expect(JobTemplatesAPI.disassociateLabel).toHaveBeenCalledTimes(2);
expect(JobTemplatesAPI.associateLabel).toHaveBeenCalledTimes(2);
expect(JobTemplatesAPI.generateLabel).toHaveBeenCalledTimes(2);
diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
index 30479e3871..d7a699c387 100644
--- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
+++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
@@ -427,7 +427,7 @@ const FormikApp = withFormik({
const {
name = '',
description = '',
- job_type = '',
+ job_type = 'run',
inventory = '',
playbook = '',
project = '',
diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx
index 428bfc928f..d9be14e148 100644
--- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx
+++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx
@@ -1,7 +1,6 @@
import React from 'react';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
import { sleep } from '@testUtils/testUtils';
-import { shallow } from 'enzyme';
import JobTemplateForm, { _JobTemplateForm } from './JobTemplateForm';
import { LabelsAPI } from '@api';
@@ -42,13 +41,11 @@ describe('', () => {
test('initially renders successfully', async done => {
const wrapper = mountWithContexts(
- shallow(
-
- ).get(0)
+
);
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
@@ -64,14 +61,13 @@ describe('', () => {
test('should update form values on input changes', async done => {
const wrapper = mountWithContexts(
- shallow(
-
- ).get(0)
+
);
+
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
const form = wrapper.find('Formik');
wrapper.find('input#template-name').simulate('change', {
@@ -136,6 +132,27 @@ describe('', () => {
done();
});
+ test('should call loadRelatedProjectPlaybooks when project value changes', async done => {
+ const loadRelatedProjectPlaybooks = jest.spyOn(
+ _JobTemplateForm.prototype,
+ 'loadRelatedProjectPlaybooks'
+ );
+ const wrapper = mountWithContexts(
+
+ );
+ await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
+ wrapper.find('ProjectLookup').prop('onChange')({
+ id: 10,
+ name: 'project',
+ });
+ expect(loadRelatedProjectPlaybooks).toHaveBeenCalledWith(10);
+ done();
+ });
+
test('handleNewLabel should arrange new labels properly', async done => {
const handleNewLabel = jest.spyOn(
_JobTemplateForm.prototype,