mirror of
https://github.com/ansible/awx.git
synced 2026-03-06 11:11:07 -03:30
load related credentials when editing
This commit is contained in:
@@ -10,6 +10,7 @@ class JobTemplates extends InstanceGroupsMixin(Base) {
|
|||||||
this.readLaunch = this.readLaunch.bind(this);
|
this.readLaunch = this.readLaunch.bind(this);
|
||||||
this.associateLabel = this.associateLabel.bind(this);
|
this.associateLabel = this.associateLabel.bind(this);
|
||||||
this.disassociateLabel = this.disassociateLabel.bind(this);
|
this.disassociateLabel = this.disassociateLabel.bind(this);
|
||||||
|
this.readCredentials = this.readCredentials.bind(this);
|
||||||
this.generateLabel = this.generateLabel.bind(this);
|
this.generateLabel = this.generateLabel.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +33,10 @@ class JobTemplates extends InstanceGroupsMixin(Base) {
|
|||||||
generateLabel(orgId, label) {
|
generateLabel(orgId, label) {
|
||||||
return this.http.post(`${this.baseUrl}${orgId}/labels/`, label);
|
return this.http.post(`${this.baseUrl}${orgId}/labels/`, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readCredentials(id, params) {
|
||||||
|
return this.http.get(`${this.baseUrl}${id}/credentials/`, { params });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JobTemplates;
|
export default JobTemplates;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
import JobTemplateAdd from './JobTemplateAdd';
|
import JobTemplateAdd from './JobTemplateAdd';
|
||||||
import { JobTemplatesAPI } from '../../../api';
|
import { JobTemplatesAPI, LabelsAPI } from '@api';
|
||||||
|
|
||||||
jest.mock('@api');
|
jest.mock('@api');
|
||||||
|
|
||||||
@@ -20,6 +20,10 @@ describe('<JobTemplateAdd />', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
LabelsAPI.read.mockResolvedValue({ data: { results: [] } });
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
@@ -29,8 +33,9 @@ describe('<JobTemplateAdd />', () => {
|
|||||||
expect(wrapper.find('JobTemplateForm').length).toBe(1);
|
expect(wrapper.find('JobTemplateForm').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should render Job Template Form with default values', () => {
|
test('should render Job Template Form with default values', async done => {
|
||||||
const wrapper = mountWithContexts(<JobTemplateAdd />);
|
const wrapper = mountWithContexts(<JobTemplateAdd />);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
expect(wrapper.find('input#template-description').text()).toBe(
|
expect(wrapper.find('input#template-description').text()).toBe(
|
||||||
defaultProps.description
|
defaultProps.description
|
||||||
);
|
);
|
||||||
@@ -47,6 +52,7 @@ describe('<JobTemplateAdd />', () => {
|
|||||||
<option>Check</option>,
|
<option>Check</option>,
|
||||||
])
|
])
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
|
|
||||||
expect(wrapper.find('input#template-name').text()).toBe(defaultProps.name);
|
expect(wrapper.find('input#template-name').text()).toBe(defaultProps.name);
|
||||||
expect(wrapper.find('input#template-playbook').text()).toBe(
|
expect(wrapper.find('input#template-playbook').text()).toBe(
|
||||||
defaultProps.playbook
|
defaultProps.playbook
|
||||||
@@ -54,6 +60,7 @@ describe('<JobTemplateAdd />', () => {
|
|||||||
expect(wrapper.find('input#template-project').text()).toBe(
|
expect(wrapper.find('input#template-project').text()).toBe(
|
||||||
defaultProps.project
|
defaultProps.project
|
||||||
);
|
);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleSubmit should post to api', async done => {
|
test('handleSubmit should post to api', async done => {
|
||||||
@@ -72,7 +79,8 @@ describe('<JobTemplateAdd />', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const wrapper = mountWithContexts(<JobTemplateAdd />);
|
const wrapper = mountWithContexts(<JobTemplateAdd />);
|
||||||
await wrapper.find('JobTemplateForm').prop('handleSubmit')(jobTemplateData);
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
|
wrapper.find('JobTemplateForm').prop('handleSubmit')(jobTemplateData);
|
||||||
expect(JobTemplatesAPI.create).toHaveBeenCalledWith(jobTemplateData);
|
expect(JobTemplatesAPI.create).toHaveBeenCalledWith(jobTemplateData);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -107,15 +115,16 @@ describe('<JobTemplateAdd />', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should navigate to templates list when cancel is clicked', () => {
|
test('should navigate to templates list when cancel is clicked', async done => {
|
||||||
const history = {
|
const history = {
|
||||||
push: jest.fn(),
|
push: jest.fn(),
|
||||||
};
|
};
|
||||||
const wrapper = mountWithContexts(<JobTemplateAdd />, {
|
const wrapper = mountWithContexts(<JobTemplateAdd />, {
|
||||||
context: { router: { history } },
|
context: { router: { history } },
|
||||||
});
|
});
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
|
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
|
||||||
expect(history.push).toHaveBeenCalledWith('/templates');
|
expect(history.push).toHaveBeenCalledWith('/templates');
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
/* eslint react/no-unused-state: 0 */
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { withRouter, Redirect } from 'react-router-dom';
|
import { withRouter, Redirect } from 'react-router-dom';
|
||||||
import { CardBody } from '@patternfly/react-core';
|
import { CardBody } from '@patternfly/react-core';
|
||||||
import JobTemplateForm from '../shared/JobTemplateForm';
|
import ContentError from '@components/ContentError';
|
||||||
|
import ContentLoading from '@components/ContentLoading';
|
||||||
import { JobTemplatesAPI } from '@api';
|
import { JobTemplatesAPI } from '@api';
|
||||||
import { JobTemplate } from '@types';
|
import { JobTemplate } from '@types';
|
||||||
|
import JobTemplateForm from '../shared/JobTemplateForm';
|
||||||
|
|
||||||
class JobTemplateEdit extends Component {
|
class JobTemplateEdit extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -14,7 +17,10 @@ class JobTemplateEdit extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
error: '',
|
hasContentLoading: true,
|
||||||
|
contentError: null,
|
||||||
|
formSubmitError: null,
|
||||||
|
relatedCredentials: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -24,21 +30,75 @@ class JobTemplateEdit extends Component {
|
|||||||
|
|
||||||
this.handleCancel = this.handleCancel.bind(this);
|
this.handleCancel = this.handleCancel.bind(this);
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
this.loadRelatedCredentials = this.loadRelatedCredentials.bind(this);
|
||||||
this.submitLabels = this.submitLabels.bind(this);
|
this.submitLabels = this.submitLabels.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.loadRelated();
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadRelated() {
|
||||||
|
this.setState({ contentError: null, hasContentLoading: true });
|
||||||
|
try {
|
||||||
|
const [
|
||||||
|
relatedCredentials,
|
||||||
|
// relatedProjectPlaybooks,
|
||||||
|
] = await Promise.all([
|
||||||
|
this.loadRelatedCredentials(),
|
||||||
|
// this.loadRelatedProjectPlaybooks(),
|
||||||
|
]);
|
||||||
|
this.setState({
|
||||||
|
relatedCredentials,
|
||||||
|
});
|
||||||
|
} catch (contentError) {
|
||||||
|
this.setState({ contentError });
|
||||||
|
} finally {
|
||||||
|
this.setState({ hasContentLoading: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadRelatedCredentials() {
|
||||||
|
const {
|
||||||
|
template: { id },
|
||||||
|
} = this.props;
|
||||||
|
const params = {
|
||||||
|
page: 1,
|
||||||
|
page_size: 200,
|
||||||
|
order_by: 'name',
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
data: { results: credentials = [] },
|
||||||
|
} = await JobTemplatesAPI.readCredentials(id, params);
|
||||||
|
return credentials;
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status !== 403) throw err;
|
||||||
|
|
||||||
|
this.setState({ hasRelatedCredentialAccess: false });
|
||||||
|
const {
|
||||||
|
template: {
|
||||||
|
summary_fields: { credentials = [] },
|
||||||
|
},
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async handleSubmit(values, newLabels = [], removedLabels = []) {
|
async handleSubmit(values, newLabels = [], removedLabels = []) {
|
||||||
const {
|
const {
|
||||||
template: { id, type },
|
template: { id },
|
||||||
history,
|
history,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
this.setState({ formSubmitError: null });
|
||||||
try {
|
try {
|
||||||
await JobTemplatesAPI.update(id, { ...values });
|
await JobTemplatesAPI.update(id, { ...values });
|
||||||
await Promise.all([this.submitLabels(newLabels, removedLabels)]);
|
await Promise.all([this.submitLabels(newLabels, removedLabels)]);
|
||||||
history.push(this.detailsUrl);
|
history.push(this.detailsUrl);
|
||||||
} catch (error) {
|
} catch (formSubmitError) {
|
||||||
this.setState({ error });
|
this.setState({ formSubmitError });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +131,17 @@ class JobTemplateEdit extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { template } = this.props;
|
const { template } = this.props;
|
||||||
const { error } = this.state;
|
const { contentError, formSubmitError, hasContentLoading } = this.state;
|
||||||
const canEdit = template.summary_fields.user_capabilities.edit;
|
const canEdit = template.summary_fields.user_capabilities.edit;
|
||||||
|
|
||||||
|
if (hasContentLoading) {
|
||||||
|
return <ContentLoading />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentError) {
|
||||||
|
return <ContentError error={contentError} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (!canEdit) {
|
if (!canEdit) {
|
||||||
return <Redirect to={this.detailsUrl} />;
|
return <Redirect to={this.detailsUrl} />;
|
||||||
}
|
}
|
||||||
@@ -85,7 +153,7 @@ class JobTemplateEdit extends Component {
|
|||||||
handleCancel={this.handleCancel}
|
handleCancel={this.handleCancel}
|
||||||
handleSubmit={this.handleSubmit}
|
handleSubmit={this.handleSubmit}
|
||||||
/>
|
/>
|
||||||
{error ? <div> error </div> : null}
|
{formSubmitError ? <div> error </div> : null}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,98 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { JobTemplatesAPI } from '@api';
|
import { JobTemplatesAPI, LabelsAPI } from '@api';
|
||||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
import JobTemplateEdit from './JobTemplateEdit';
|
import JobTemplateEdit from './JobTemplateEdit';
|
||||||
|
|
||||||
jest.mock('@api');
|
jest.mock('@api');
|
||||||
|
|
||||||
describe('<JobTemplateEdit />', () => {
|
const mockJobTemplate = {
|
||||||
const mockData = {
|
id: 1,
|
||||||
id: 1,
|
name: 'Foo',
|
||||||
name: 'Foo',
|
description: 'Bar',
|
||||||
description: 'Bar',
|
job_type: 'run',
|
||||||
job_type: 'run',
|
inventory: 2,
|
||||||
inventory: 2,
|
project: 3,
|
||||||
project: 3,
|
playbook: 'Baz',
|
||||||
playbook: 'Baz',
|
type: 'job_template',
|
||||||
type: 'job_template',
|
summary_fields: {
|
||||||
summary_fields: {
|
user_capabilities: {
|
||||||
user_capabilities: {
|
edit: true,
|
||||||
edit: true,
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
results: [{ name: 'Sushi', id: 1 }, { name: 'Major', id: 2 }],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
labels: {
|
||||||
|
results: [{ name: 'Sushi', id: 1 }, { name: 'Major', id: 2 }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
test('initially renders successfully', () => {
|
const mockRelatedCredentials = {
|
||||||
mountWithContexts(<JobTemplateEdit template={mockData} />);
|
count: 2,
|
||||||
|
next: null,
|
||||||
|
previous: null,
|
||||||
|
results: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
type: 'credential',
|
||||||
|
url: '/api/v2/credentials/1/',
|
||||||
|
related: {},
|
||||||
|
summary_fields: {
|
||||||
|
user_capabilities: {
|
||||||
|
edit: true,
|
||||||
|
delete: true,
|
||||||
|
copy: true,
|
||||||
|
use: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created: '2016-08-24T20:20:44.411607Z',
|
||||||
|
modified: '2019-06-18T16:14:00.109434Z',
|
||||||
|
name: 'Test Vault Credential',
|
||||||
|
description: 'Credential with access to vaulted data.',
|
||||||
|
organization: 1,
|
||||||
|
credential_type: 3,
|
||||||
|
inputs: { vault_password: '$encrypted$' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
type: 'credential',
|
||||||
|
url: '/api/v2/credentials/2/',
|
||||||
|
related: {},
|
||||||
|
summary_fields: {
|
||||||
|
user_capabilities: {
|
||||||
|
edit: true,
|
||||||
|
delete: true,
|
||||||
|
copy: true,
|
||||||
|
use: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created: '2016-08-24T20:20:44.411607Z',
|
||||||
|
modified: '2017-07-11T15:58:39.103659Z',
|
||||||
|
name: 'Test Machine Credential',
|
||||||
|
description: 'Credential with access to internal machines.',
|
||||||
|
organization: 1,
|
||||||
|
credential_type: 1,
|
||||||
|
inputs: { ssh_key_data: '$encrypted$' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
JobTemplatesAPI.readCredentials.mockResolvedValue({
|
||||||
|
data: mockRelatedCredentials,
|
||||||
|
});
|
||||||
|
LabelsAPI.read.mockResolvedValue({ data: { results: [] } });
|
||||||
|
|
||||||
|
describe('<JobTemplateEdit />', () => {
|
||||||
|
test('initially renders successfully', async done => {
|
||||||
|
const wrapper = mountWithContexts(
|
||||||
|
<JobTemplateEdit template={mockJobTemplate} />
|
||||||
|
);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleSubmit should call api update', async (done) => {
|
test('handleSubmit should call api update', async done => {
|
||||||
const wrapper = mountWithContexts(<JobTemplateEdit template={mockData} />);
|
const wrapper = mountWithContexts(
|
||||||
|
<JobTemplateEdit template={mockJobTemplate} />
|
||||||
|
);
|
||||||
|
await waitForElement(wrapper, 'JobTemplateForm', e => e.length === 1);
|
||||||
const updatedTemplateData = {
|
const updatedTemplateData = {
|
||||||
name: 'new name',
|
name: 'new name',
|
||||||
description: 'new description',
|
description: 'new description',
|
||||||
@@ -59,18 +121,22 @@ describe('<JobTemplateEdit />', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should navigate to job template detail when cancel is clicked', () => {
|
test('should navigate to job template detail when cancel is clicked', async done => {
|
||||||
const history = {
|
const history = { push: jest.fn() };
|
||||||
push: jest.fn(),
|
const wrapper = mountWithContexts(
|
||||||
};
|
<JobTemplateEdit template={mockJobTemplate} />,
|
||||||
const wrapper = mountWithContexts(<JobTemplateEdit template={mockData} />, {
|
{ context: { router: { history } } }
|
||||||
context: { router: { history } },
|
);
|
||||||
});
|
const cancelButton = await waitForElement(
|
||||||
|
wrapper,
|
||||||
|
'button[aria-label="Cancel"]',
|
||||||
|
e => e.length === 1
|
||||||
|
);
|
||||||
expect(history.push).not.toHaveBeenCalled();
|
expect(history.push).not.toHaveBeenCalled();
|
||||||
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
|
cancelButton.prop('onClick')();
|
||||||
expect(history.push).toHaveBeenCalledWith(
|
expect(history.push).toHaveBeenCalledWith(
|
||||||
'/templates/job_template/1/details'
|
'/templates/job_template/1/details'
|
||||||
);
|
);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,15 +4,10 @@ import { withRouter } from 'react-router-dom';
|
|||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Formik, Field } from 'formik';
|
import { Formik, Field } from 'formik';
|
||||||
import {
|
import { Form, FormGroup, Tooltip, Card } from '@patternfly/react-core';
|
||||||
Form,
|
|
||||||
FormGroup,
|
|
||||||
Tooltip,
|
|
||||||
PageSection,
|
|
||||||
Card,
|
|
||||||
} from '@patternfly/react-core';
|
|
||||||
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
|
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
|
||||||
import ContentError from '@components/ContentError';
|
import ContentError from '@components/ContentError';
|
||||||
|
import ContentLoading from '@components/ContentLoading';
|
||||||
import AnsibleSelect from '@components/AnsibleSelect';
|
import AnsibleSelect from '@components/AnsibleSelect';
|
||||||
import MultiSelect from '@components/MultiSelect';
|
import MultiSelect from '@components/MultiSelect';
|
||||||
import FormActionGroup from '@components/FormActionGroup';
|
import FormActionGroup from '@components/FormActionGroup';
|
||||||
@@ -44,9 +39,7 @@ class JobTemplateForm extends Component {
|
|||||||
template: {
|
template: {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
inventory: '',
|
|
||||||
job_type: 'run',
|
job_type: 'run',
|
||||||
project: '',
|
|
||||||
playbook: '',
|
playbook: '',
|
||||||
summary_fields: {
|
summary_fields: {
|
||||||
inventory: null,
|
inventory: null,
|
||||||
@@ -180,23 +173,30 @@ class JobTemplateForm extends Component {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!hasContentLoading && contentError) {
|
if (hasContentLoading) {
|
||||||
return (
|
return (
|
||||||
<PageSection>
|
<Card className="awx-c-card">
|
||||||
<Card className="awx-c-card">
|
<ContentLoading />
|
||||||
<ContentError error={contentError} />
|
</Card>
|
||||||
</Card>
|
|
||||||
</PageSection>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (contentError) {
|
||||||
|
return (
|
||||||
|
<Card className="awx-c-card">
|
||||||
|
<ContentError error={contentError} />
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={{
|
||||||
name: template.name,
|
name: template.name,
|
||||||
description: template.description,
|
description: template.description,
|
||||||
job_type: template.job_type,
|
job_type: template.job_type,
|
||||||
inventory: template.inventory,
|
inventory: template.inventory || '',
|
||||||
project: template.project,
|
project: template.project || '',
|
||||||
playbook: template.playbook,
|
playbook: template.playbook,
|
||||||
labels: template.summary_fields.labels.results,
|
labels: template.summary_fields.labels.results,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
import { sleep } from '@testUtils/testUtils';
|
import { sleep } from '@testUtils/testUtils';
|
||||||
import JobTemplateForm, { _JobTemplateForm } from './JobTemplateForm';
|
import JobTemplateForm, { _JobTemplateForm } from './JobTemplateForm';
|
||||||
import { LabelsAPI } from '@api';
|
import { LabelsAPI } from '@api';
|
||||||
@@ -35,7 +35,7 @@ describe('<JobTemplateForm />', () => {
|
|||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('initially renders successfully', () => {
|
test('initially renders successfully', async done => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<JobTemplateForm
|
<JobTemplateForm
|
||||||
template={mockData}
|
template={mockData}
|
||||||
@@ -43,12 +43,14 @@ describe('<JobTemplateForm />', () => {
|
|||||||
handleCancel={jest.fn()}
|
handleCancel={jest.fn()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
const component = wrapper.find('ChipGroup');
|
const component = wrapper.find('ChipGroup');
|
||||||
expect(LabelsAPI.read).toHaveBeenCalled();
|
expect(LabelsAPI.read).toHaveBeenCalled();
|
||||||
expect(component.find('span#pf-random-id-1').text()).toEqual('Sushi');
|
expect(component.find('span#pf-random-id-1').text()).toEqual('Sushi');
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should update form values on input changes', async () => {
|
test('should update form values on input changes', async done => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<JobTemplateForm
|
<JobTemplateForm
|
||||||
template={mockData}
|
template={mockData}
|
||||||
@@ -56,7 +58,7 @@ describe('<JobTemplateForm />', () => {
|
|||||||
handleCancel={jest.fn()}
|
handleCancel={jest.fn()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
const form = wrapper.find('Formik');
|
const form = wrapper.find('Formik');
|
||||||
wrapper.find('input#template-name').simulate('change', {
|
wrapper.find('input#template-name').simulate('change', {
|
||||||
target: { value: 'new foo', name: 'name' },
|
target: { value: 'new foo', name: 'name' },
|
||||||
@@ -83,9 +85,10 @@ describe('<JobTemplateForm />', () => {
|
|||||||
target: { value: 'new baz type', name: 'playbook' },
|
target: { value: 'new baz type', name: 'playbook' },
|
||||||
});
|
});
|
||||||
expect(form.state('values').playbook).toEqual('new baz type');
|
expect(form.state('values').playbook).toEqual('new baz type');
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should call handleSubmit when Submit button is clicked', async () => {
|
test('should call handleSubmit when Submit button is clicked', async done => {
|
||||||
const handleSubmit = jest.fn();
|
const handleSubmit = jest.fn();
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<JobTemplateForm
|
<JobTemplateForm
|
||||||
@@ -94,14 +97,15 @@ describe('<JobTemplateForm />', () => {
|
|||||||
handleCancel={jest.fn()}
|
handleCancel={jest.fn()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
expect(handleSubmit).not.toHaveBeenCalled();
|
expect(handleSubmit).not.toHaveBeenCalled();
|
||||||
wrapper.find('button[aria-label="Save"]').simulate('click');
|
wrapper.find('button[aria-label="Save"]').simulate('click');
|
||||||
await sleep(1);
|
await sleep(1);
|
||||||
expect(handleSubmit).toBeCalled();
|
expect(handleSubmit).toBeCalled();
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should call handleCancel when Cancel button is clicked', () => {
|
test('should call handleCancel when Cancel button is clicked', async done => {
|
||||||
const handleCancel = jest.fn();
|
const handleCancel = jest.fn();
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<JobTemplateForm
|
<JobTemplateForm
|
||||||
@@ -110,12 +114,14 @@ describe('<JobTemplateForm />', () => {
|
|||||||
handleCancel={handleCancel}
|
handleCancel={handleCancel}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
expect(handleCancel).not.toHaveBeenCalled();
|
expect(handleCancel).not.toHaveBeenCalled();
|
||||||
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
|
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
|
||||||
expect(handleCancel).toBeCalled();
|
expect(handleCancel).toBeCalled();
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleNewLabel should arrange new labels properly', async () => {
|
test('handleNewLabel should arrange new labels properly', async done => {
|
||||||
const handleNewLabel = jest.spyOn(
|
const handleNewLabel = jest.spyOn(
|
||||||
_JobTemplateForm.prototype,
|
_JobTemplateForm.prototype,
|
||||||
'handleNewLabel'
|
'handleNewLabel'
|
||||||
@@ -128,6 +134,7 @@ describe('<JobTemplateForm />', () => {
|
|||||||
handleCancel={jest.fn()}
|
handleCancel={jest.fn()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
const multiSelect = wrapper.find('MultiSelect');
|
const multiSelect = wrapper.find('MultiSelect');
|
||||||
const component = wrapper.find('JobTemplateForm');
|
const component = wrapper.find('JobTemplateForm');
|
||||||
|
|
||||||
@@ -141,8 +148,9 @@ describe('<JobTemplateForm />', () => {
|
|||||||
{ name: 'Foo', organization: 1 },
|
{ name: 'Foo', organization: 1 },
|
||||||
{ associate: true, id: 2, name: 'Bar' },
|
{ associate: true, id: 2, name: 'Bar' },
|
||||||
]);
|
]);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
test('disassociateLabel should arrange new labels properly', async () => {
|
test('disassociateLabel should arrange new labels properly', async done => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<JobTemplateForm
|
<JobTemplateForm
|
||||||
template={mockData}
|
template={mockData}
|
||||||
@@ -150,6 +158,7 @@ describe('<JobTemplateForm />', () => {
|
|||||||
handleCancel={jest.fn()}
|
handleCancel={jest.fn()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||||
const component = wrapper.find('JobTemplateForm');
|
const component = wrapper.find('JobTemplateForm');
|
||||||
// This asserts that the user generated a label or clicked
|
// This asserts that the user generated a label or clicked
|
||||||
// on a label option, and then changed their mind and
|
// on a label option, and then changed their mind and
|
||||||
@@ -162,5 +171,6 @@ describe('<JobTemplateForm />', () => {
|
|||||||
component.instance().removeLabel({ name: 'Sushi', id: 1 });
|
component.instance().removeLabel({ name: 'Sushi', id: 1 });
|
||||||
expect(component.state().newLabels.length).toBe(0);
|
expect(component.state().newLabels.length).toBe(0);
|
||||||
expect(component.state().removedLabels.length).toBe(1);
|
expect(component.state().removedLabels.length).toBe(1);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user