mirror of
https://github.com/ansible/awx.git
synced 2026-01-17 04:31:21 -03:30
Add feature to Add/Edit Execution Environments (#8165)
* Add feature to Add/Edit Execution Environments Add feature to Add/Edit Execution Environments. Also, add key for `ExecutionEnvironmentsList`. See: https://github.com/ansible/awx/issues/7887 * Update registry credential label
This commit is contained in:
parent
9530c6ca50
commit
684b9bd47a
@ -140,7 +140,7 @@ function getRouteConfig(i18n) {
|
||||
screen: Applications,
|
||||
},
|
||||
{
|
||||
title: i18n._(t`Execution environments`),
|
||||
title: i18n._(t`Execution Environments`),
|
||||
path: '/execution_environments',
|
||||
screen: ExecutionEnvironments,
|
||||
},
|
||||
|
||||
@ -1,25 +1,124 @@
|
||||
import React from 'react';
|
||||
import { Route, Redirect, Switch } from 'react-router-dom';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import {
|
||||
Link,
|
||||
Redirect,
|
||||
Route,
|
||||
Switch,
|
||||
useLocation,
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
|
||||
import useRequest from '../../util/useRequest';
|
||||
import { ExecutionEnvironmentsAPI } from '../../api';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import ContentLoading from '../../components/ContentLoading';
|
||||
|
||||
import ExecutionEnvironmentDetails from './ExecutionEnvironmentDetails';
|
||||
import ExecutionEnvironmentEdit from './ExecutionEnvironmentEdit';
|
||||
|
||||
function ExecutionEnvironment() {
|
||||
function ExecutionEnvironment({ i18n, setBreadcrumb }) {
|
||||
const { id } = useParams();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const {
|
||||
isLoading,
|
||||
error: contentError,
|
||||
request: fetchExecutionEnvironments,
|
||||
result: executionEnvironment,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const { data } = await ExecutionEnvironmentsAPI.readDetail(id);
|
||||
return data;
|
||||
}, [id]),
|
||||
null
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fetchExecutionEnvironments();
|
||||
}, [fetchExecutionEnvironments, pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
if (executionEnvironment) {
|
||||
setBreadcrumb(executionEnvironment);
|
||||
}
|
||||
}, [executionEnvironment, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to execution environments`)}
|
||||
</>
|
||||
),
|
||||
link: '/execution_environments',
|
||||
id: 99,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Details`),
|
||||
link: `/execution_environments/${id}/details`,
|
||||
id: 0,
|
||||
},
|
||||
];
|
||||
|
||||
if (!isLoading && contentError) {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
<ContentError error={contentError}>
|
||||
{contentError.response?.status === 404 && (
|
||||
<span>
|
||||
{i18n._(t`Execution environment not found.`)}{' '}
|
||||
<Link to="/execution_environments">
|
||||
{i18n._(t`View all execution environments`)}
|
||||
</Link>
|
||||
</span>
|
||||
)}
|
||||
</ContentError>
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
}
|
||||
|
||||
let cardHeader = <RoutedTabs tabsArray={tabsArray} />;
|
||||
if (pathname.endsWith('edit')) {
|
||||
cardHeader = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/execution_environments/:id"
|
||||
to="/execution_environments/:id/details"
|
||||
exact
|
||||
/>
|
||||
<Route path="/execution_environments/:id/edit">
|
||||
<ExecutionEnvironmentEdit />
|
||||
</Route>
|
||||
<Route path="/execution_environments/:id/details">
|
||||
<ExecutionEnvironmentDetails />
|
||||
</Route>
|
||||
</Switch>
|
||||
<PageSection>
|
||||
<Card>
|
||||
{cardHeader}
|
||||
{isLoading && <ContentLoading />}
|
||||
{!isLoading && executionEnvironment && (
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/execution_environments/:id"
|
||||
to="/execution_environments/:id/details"
|
||||
exact
|
||||
/>
|
||||
{executionEnvironment && (
|
||||
<>
|
||||
<Route path="/execution_environments/:id/edit">
|
||||
<ExecutionEnvironmentEdit
|
||||
executionEnvironment={executionEnvironment}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/execution_environments/:id/details">
|
||||
<ExecutionEnvironmentDetails />
|
||||
</Route>
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
)}
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExecutionEnvironment;
|
||||
export default withI18n()(ExecutionEnvironment);
|
||||
|
||||
@ -1,11 +1,40 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import ExecutionEnvironmentForm from '../shared/ExecutionEnvironmentForm';
|
||||
import { CardBody } from '../../../components/Card';
|
||||
import { ExecutionEnvironmentsAPI } from '../../../api';
|
||||
|
||||
function ExecutionEnvironmentAdd() {
|
||||
const history = useHistory();
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
|
||||
const handleSubmit = async values => {
|
||||
try {
|
||||
const { data: response } = await ExecutionEnvironmentsAPI.create({
|
||||
...values,
|
||||
credential: values?.credential?.id,
|
||||
});
|
||||
history.push(`/execution_environments/${response.id}/details`);
|
||||
} catch (error) {
|
||||
setSubmitError(error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
history.push(`/execution_environments`);
|
||||
};
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
<div>Add Execution Environments</div>
|
||||
<CardBody>
|
||||
<ExecutionEnvironmentForm
|
||||
onSubmit={handleSubmit}
|
||||
submitError={submitError}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { createMemoryHistory } from 'history';
|
||||
|
||||
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||
import { ExecutionEnvironmentsAPI } from '../../../api';
|
||||
import ExecutionEnvironmentAdd from './ExecutionEnvironmentAdd';
|
||||
|
||||
jest.mock('../../../api');
|
||||
|
||||
const executionEnvironmentData = {
|
||||
credential: 4,
|
||||
description: 'A simple EE',
|
||||
image: 'https://registry.com/image/container',
|
||||
};
|
||||
|
||||
ExecutionEnvironmentsAPI.create.mockResolvedValue({
|
||||
data: {
|
||||
id: 42,
|
||||
},
|
||||
});
|
||||
|
||||
describe('<ExecutionEnvironmentAdd/>', () => {
|
||||
let wrapper;
|
||||
let history;
|
||||
|
||||
beforeEach(async () => {
|
||||
history = createMemoryHistory({
|
||||
initialEntries: ['/execution_environments'],
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<ExecutionEnvironmentAdd />, {
|
||||
context: { router: { history } },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('handleSubmit should call the api and redirect to details page', async () => {
|
||||
await act(async () => {
|
||||
wrapper.find('ExecutionEnvironmentForm').prop('onSubmit')({
|
||||
executionEnvironmentData,
|
||||
});
|
||||
});
|
||||
wrapper.update();
|
||||
expect(ExecutionEnvironmentsAPI.create).toHaveBeenCalledWith({
|
||||
executionEnvironmentData,
|
||||
});
|
||||
expect(history.location.pathname).toBe(
|
||||
'/execution_environments/42/details'
|
||||
);
|
||||
});
|
||||
|
||||
test('handleCancel should return the user back to the execution environments list', async () => {
|
||||
wrapper.find('Button[aria-label="Cancel"]').simulate('click');
|
||||
expect(history.location.pathname).toEqual('/execution_environments');
|
||||
});
|
||||
|
||||
test('failed form submission should show an error message', async () => {
|
||||
const error = {
|
||||
response: {
|
||||
data: { detail: 'An error occurred' },
|
||||
},
|
||||
};
|
||||
ExecutionEnvironmentsAPI.create.mockImplementationOnce(() =>
|
||||
Promise.reject(error)
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper.find('ExecutionEnvironmentForm').invoke('onSubmit')(
|
||||
executionEnvironmentData
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('FormSubmitError').length).toBe(1);
|
||||
});
|
||||
});
|
||||
@ -1,13 +1,39 @@
|
||||
import React from 'react';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import React, { useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
function ExecutionEnvironmentEdit() {
|
||||
import { CardBody } from '../../../components/Card';
|
||||
import { ExecutionEnvironmentsAPI } from '../../../api';
|
||||
import ExecutionEnvironmentForm from '../shared/ExecutionEnvironmentForm';
|
||||
|
||||
function ExecutionEnvironmentEdit({ executionEnvironment }) {
|
||||
const history = useHistory();
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
const detailsUrl = `/execution_environments/${executionEnvironment.id}/details`;
|
||||
|
||||
const handleSubmit = async values => {
|
||||
try {
|
||||
await ExecutionEnvironmentsAPI.update(executionEnvironment.id, {
|
||||
...values,
|
||||
credential: values.credential ? values.credential.id : null,
|
||||
});
|
||||
history.push(detailsUrl);
|
||||
} catch (error) {
|
||||
setSubmitError(error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
history.push(detailsUrl);
|
||||
};
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
<div>Edit Execution environments</div>
|
||||
</Card>
|
||||
</PageSection>
|
||||
<CardBody>
|
||||
<ExecutionEnvironmentForm
|
||||
executionEnvironment={executionEnvironment}
|
||||
onSubmit={handleSubmit}
|
||||
submitError={submitError}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { createMemoryHistory } from 'history';
|
||||
|
||||
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||
import { ExecutionEnvironmentsAPI } from '../../../api';
|
||||
|
||||
import ExecutionEnvironmentEdit from './ExecutionEnvironmentEdit';
|
||||
|
||||
jest.mock('../../../api');
|
||||
|
||||
const executionEnvironmentData = {
|
||||
id: 42,
|
||||
credential: { id: 4 },
|
||||
description: 'A simple EE',
|
||||
image: 'https://registry.com/image/container',
|
||||
};
|
||||
|
||||
const updateExecutionEnvironmentData = {
|
||||
image: 'https://registry.com/image/container2',
|
||||
description: 'Updated new description',
|
||||
};
|
||||
|
||||
describe('<ExecutionEnvironmentEdit/>', () => {
|
||||
let wrapper;
|
||||
let history;
|
||||
|
||||
beforeAll(async () => {
|
||||
history = createMemoryHistory();
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ExecutionEnvironmentEdit
|
||||
executionEnvironment={executionEnvironmentData}
|
||||
/>,
|
||||
{
|
||||
context: { router: { history } },
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('handleSubmit should call the api and redirect to details page', async () => {
|
||||
await act(async () => {
|
||||
wrapper.find('ExecutionEnvironmentForm').invoke('onSubmit')(
|
||||
updateExecutionEnvironmentData
|
||||
);
|
||||
wrapper.update();
|
||||
expect(ExecutionEnvironmentsAPI.update).toHaveBeenCalledWith(42, {
|
||||
...updateExecutionEnvironmentData,
|
||||
credential: null,
|
||||
});
|
||||
});
|
||||
|
||||
expect(history.location.pathname).toEqual(
|
||||
'/execution_environments/42/details'
|
||||
);
|
||||
});
|
||||
|
||||
test('should navigate to execution environments details when cancel is clicked', async () => {
|
||||
await act(async () => {
|
||||
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
|
||||
});
|
||||
expect(history.location.pathname).toEqual(
|
||||
'/execution_environments/42/details'
|
||||
);
|
||||
});
|
||||
|
||||
test('should navigate to execution environments detail after successful submission', async () => {
|
||||
await act(async () => {
|
||||
wrapper.find('ExecutionEnvironmentForm').invoke('onSubmit')({
|
||||
updateExecutionEnvironmentData,
|
||||
});
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('FormSubmitError').length).toBe(0);
|
||||
expect(history.location.pathname).toEqual(
|
||||
'/execution_environments/42/details'
|
||||
);
|
||||
});
|
||||
|
||||
test('failed form submission should show an error message', async () => {
|
||||
const error = {
|
||||
response: {
|
||||
data: { detail: 'An error occurred' },
|
||||
},
|
||||
};
|
||||
ExecutionEnvironmentsAPI.update.mockImplementationOnce(() =>
|
||||
Promise.reject(error)
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper.find('ExecutionEnvironmentForm').invoke('onSubmit')(
|
||||
updateExecutionEnvironmentData
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('FormSubmitError').length).toBe(1);
|
||||
});
|
||||
});
|
||||
@ -19,12 +19,14 @@ const executionEnvironments = {
|
||||
image: 'https://registry.com/r/image/manifest',
|
||||
organization: null,
|
||||
credential: null,
|
||||
url: '/api/v2/execution_environments/1/',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
image: 'https://registry.com/r/image2/manifest',
|
||||
organization: null,
|
||||
credential: null,
|
||||
url: '/api/v2/execution_environments/2/',
|
||||
},
|
||||
],
|
||||
count: 2,
|
||||
|
||||
@ -171,6 +171,7 @@ function ExecutionEnvironmentList({ i18n }) {
|
||||
)}
|
||||
renderItem={executionEnvironment => (
|
||||
<ExecutionEnvironmentsListItem
|
||||
key={executionEnvironment.id}
|
||||
executionEnvironment={executionEnvironment}
|
||||
detailUrl={`${match.url}/${executionEnvironment.id}/details`}
|
||||
onSelect={() => handleSelect(executionEnvironment)}
|
||||
|
||||
@ -22,7 +22,7 @@ function ExecutionEnvironments({ i18n }) {
|
||||
setBreadcrumbConfig({
|
||||
'/execution_environments': i18n._(t`Execution environments`),
|
||||
'/execution_environments/add': i18n._(t`Create Execution environments`),
|
||||
[`/execution_environments/${executionEnvironments.id}`]: `${executionEnvironments.name}`,
|
||||
[`/execution_environments/${executionEnvironments.id}`]: `${executionEnvironments.image}`,
|
||||
[`/execution_environments/${executionEnvironments.id}/edit`]: i18n._(
|
||||
t`Edit details`
|
||||
),
|
||||
|
||||
@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { func, shape } from 'prop-types';
|
||||
import { Formik, useField } from 'formik';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
import { Form } from '@patternfly/react-core';
|
||||
import FormField, { FormSubmitError } from '../../../components/FormField';
|
||||
import FormActionGroup from '../../../components/FormActionGroup';
|
||||
import CredentialLookup from '../../../components/Lookup/CredentialLookup';
|
||||
import { url } from '../../../util/validators';
|
||||
import { FormColumnLayout } from '../../../components/FormLayout';
|
||||
|
||||
function ExecutionEnvironmentFormFields({ i18n }) {
|
||||
const [credentialField, , credentialHelpers] = useField('credential');
|
||||
return (
|
||||
<>
|
||||
<FormField
|
||||
id="execution-environment-image"
|
||||
label={i18n._(t`Image`)}
|
||||
name="image"
|
||||
type="text"
|
||||
validate={url(i18n)}
|
||||
isRequired
|
||||
tooltip={i18n._(
|
||||
t`The registry location where the container is stored.`
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
id="execution-environment-description"
|
||||
label={i18n._(t`Description`)}
|
||||
name="description"
|
||||
type="text"
|
||||
/>
|
||||
<CredentialLookup
|
||||
label={i18n._(t`Registry Credential`)}
|
||||
onChange={value => credentialHelpers.setValue(value)}
|
||||
value={credentialField.value || null}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ExecutionEnvironmentForm({
|
||||
executionEnvironment = {},
|
||||
onSubmit,
|
||||
onCancel,
|
||||
submitError,
|
||||
...rest
|
||||
}) {
|
||||
const initialValues = {
|
||||
image: executionEnvironment.image || '',
|
||||
description: executionEnvironment.description || '',
|
||||
credential: executionEnvironment?.summary_fields?.credential || null,
|
||||
};
|
||||
return (
|
||||
<Formik initialValues={initialValues} onSubmit={values => onSubmit(values)}>
|
||||
{formik => (
|
||||
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
||||
<FormColumnLayout>
|
||||
<ExecutionEnvironmentFormFields {...rest} />
|
||||
{submitError && <FormSubmitError error={submitError} />}
|
||||
<FormActionGroup
|
||||
onCancel={onCancel}
|
||||
onSubmit={formik.handleSubmit}
|
||||
/>
|
||||
</FormColumnLayout>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
ExecutionEnvironmentForm.propTypes = {
|
||||
executionEnvironment: shape({}),
|
||||
onCancel: func.isRequired,
|
||||
onSubmit: func.isRequired,
|
||||
submitError: shape({}),
|
||||
};
|
||||
|
||||
ExecutionEnvironmentForm.defaultProps = {
|
||||
executionEnvironment: {},
|
||||
submitError: null,
|
||||
};
|
||||
|
||||
export default withI18n()(ExecutionEnvironmentForm);
|
||||
@ -0,0 +1,115 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||
|
||||
import ExecutionEnvironmentForm from './ExecutionEnvironmentForm';
|
||||
|
||||
jest.mock('../../../api');
|
||||
|
||||
const executionEnvironment = {
|
||||
id: 16,
|
||||
type: 'execution_environment',
|
||||
url: '/api/v2/execution_environments/16/',
|
||||
related: {
|
||||
created_by: '/api/v2/users/1/',
|
||||
modified_by: '/api/v2/users/1/',
|
||||
activity_stream: '/api/v2/execution_environments/16/activity_stream/',
|
||||
unified_job_templates:
|
||||
'/api/v2/execution_environments/16/unified_job_templates/',
|
||||
credential: '/api/v2/credentials/4/',
|
||||
},
|
||||
summary_fields: {
|
||||
credential: {
|
||||
id: 4,
|
||||
name: 'Container Registry',
|
||||
},
|
||||
},
|
||||
created: '2020-09-17T16:06:57.346128Z',
|
||||
modified: '2020-09-17T16:06:57.346147Z',
|
||||
description: 'A simple EE',
|
||||
organization: null,
|
||||
image: 'https://registry.com/image/container',
|
||||
managed_by_tower: false,
|
||||
credential: 4,
|
||||
};
|
||||
|
||||
describe('<ExecutionEnvironmentForm/>', () => {
|
||||
let wrapper;
|
||||
let onCancel;
|
||||
let onSubmit;
|
||||
|
||||
beforeEach(async () => {
|
||||
onCancel = jest.fn();
|
||||
onSubmit = jest.fn();
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ExecutionEnvironmentForm
|
||||
onCancel={onCancel}
|
||||
onSubmit={onSubmit}
|
||||
executionEnvironment={executionEnvironment}
|
||||
/>
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('Initially renders successfully', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
});
|
||||
|
||||
test('should display form fields properly', () => {
|
||||
expect(wrapper.find('FormGroup[label="Image"]').length).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="Description"]').length).toBe(1);
|
||||
expect(wrapper.find('CredentialLookup').length).toBe(1);
|
||||
});
|
||||
|
||||
test('should call onSubmit when form submitted', async () => {
|
||||
expect(onSubmit).not.toHaveBeenCalled();
|
||||
await act(async () => {
|
||||
wrapper.find('button[aria-label="Save"]').simulate('click');
|
||||
});
|
||||
expect(onSubmit).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should update form values', () => {
|
||||
act(() => {
|
||||
wrapper.find('input#execution-environment-image').simulate('change', {
|
||||
target: {
|
||||
value: 'https://registry.com/image/container2',
|
||||
name: 'image',
|
||||
},
|
||||
});
|
||||
wrapper
|
||||
.find('input#execution-environment-description')
|
||||
.simulate('change', {
|
||||
target: { value: 'New description', name: 'description' },
|
||||
});
|
||||
wrapper.find('CredentialLookup').invoke('onBlur')();
|
||||
wrapper.find('CredentialLookup').invoke('onChange')({
|
||||
id: 99,
|
||||
name: 'credential',
|
||||
});
|
||||
});
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('input#execution-environment-image').prop('value')
|
||||
).toEqual('https://registry.com/image/container2');
|
||||
expect(
|
||||
wrapper.find('input#execution-environment-description').prop('value')
|
||||
).toEqual('New description');
|
||||
expect(wrapper.find('CredentialLookup').prop('value')).toEqual({
|
||||
id: 99,
|
||||
name: 'credential',
|
||||
});
|
||||
});
|
||||
|
||||
test('should call handleCancel when Cancel button is clicked', async () => {
|
||||
expect(onCancel).not.toHaveBeenCalled();
|
||||
wrapper.find('button[aria-label="Cancel"]').invoke('onClick')();
|
||||
expect(onCancel).toBeCalled();
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user