Skip to content

Commit

Permalink
Add feature to edit instance group
Browse files Browse the repository at this point in the history
Add feature to edit instance group.

See: ansible#7767
  • Loading branch information
nixocio committed Aug 11, 2020
1 parent fbb9998 commit e3fe680
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
import React from 'react';
import { Card, PageSection } from '@patternfly/react-core';
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';

import { CardBody } from '../../../components/Card';
import { InstanceGroupsAPI } from '../../../api';
import InstanceGroupForm from '../shared/InstanceGroupForm';

function InstanceGroupEdit({ instanceGroup }) {
const history = useHistory();
const [submitError, setSubmitError] = useState(null);
const detailsUrl = `/instance_groups/${instanceGroup.id}/details`;

const handleSubmit = async values => {
try {
await InstanceGroupsAPI.update(instanceGroup.id, values);
history.push(detailsUrl);
} catch (error) {
setSubmitError(error);
}
};

const handleCancel = () => {
history.push(detailsUrl);
};

function InstanceGroupEdit() {
return (
<PageSection>
<Card>
<div>Edit instance group</div>
</Card>
</PageSection>
<CardBody>
<InstanceGroupForm
instanceGroup={instanceGroup}
onSubmit={handleSubmit}
submitError={submitError}
onCancel={handleCancel}
/>
</CardBody>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history';

import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import { InstanceGroupsAPI } from '../../../api';

import InstanceGroupEdit from './InstanceGroupEdit';

jest.mock('../../../api');

const instanceGroupData = {
id: 42,
type: 'instance_group',
url: '/api/v2/instance_groups/42/',
related: {
jobs: '/api/v2/instance_groups/42/jobs/',
instances: '/api/v2/instance_groups/7/instances/',
},
name: 'Foo',
created: '2020-07-21T18:41:02.818081Z',
modified: '2020-07-24T20:32:03.121079Z',
capacity: 24,
committed_capacity: 0,
consumed_capacity: 0,
percent_capacity_remaining: 100.0,
jobs_running: 0,
jobs_total: 0,
instances: 1,
controller: null,
is_controller: false,
is_isolated: false,
is_containerized: false,
credential: null,
policy_instance_percentage: 46,
policy_instance_minimum: 12,
policy_instance_list: [],
pod_spec_override: '',
summary_fields: {
user_capabilities: {
edit: true,
delete: true,
},
},
};

const updatedInstanceGroup = {
name: 'Bar',
policy_instance_percentage: 42,
};

describe('<InstanceGroupEdit>', () => {
let wrapper;
let history;

beforeAll(async () => {
history = createMemoryHistory();
await act(async () => {
wrapper = mountWithContexts(
<InstanceGroupEdit instanceGroup={instanceGroupData} />,
{
context: { router: { history } },
}
);
});
});

afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});

test('tower instance group name can not be updated', async () => {
let towerWrapper;
await act(async () => {
towerWrapper = mountWithContexts(
<InstanceGroupEdit
instanceGroup={{ ...instanceGroupData, name: 'tower' }}
/>,
{
context: { router: { history } },
}
);
});
expect(
towerWrapper.find('input#instance-group-name').prop('disabled')
).toBeTruthy();
expect(
towerWrapper.find('input#instance-group-name').prop('value')
).toEqual('tower');
});

test('handleSubmit should call the api and redirect to details page', async () => {
await act(async () => {
wrapper.find('InstanceGroupForm').invoke('onSubmit')(
updatedInstanceGroup
);
});
expect(InstanceGroupsAPI.update).toHaveBeenCalledWith(
42,
updatedInstanceGroup
);
});

test('should navigate to instance group details when cancel is clicked', async () => {
await act(async () => {
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
});
expect(history.location.pathname).toEqual('/instance_groups/42/details');
});

test('should navigate to instance group details after successful submission', async () => {
await act(async () => {
wrapper.find('InstanceGroupForm').invoke('onSubmit')(
updatedInstanceGroup
);
});
wrapper.update();
expect(wrapper.find('FormSubmitError').length).toBe(0);
expect(history.location.pathname).toEqual('/instance_groups/42/details');
});

test('failed form submission should show an error message', async () => {
const error = {
response: {
data: { detail: 'An error occurred' },
},
};
InstanceGroupsAPI.update.mockImplementationOnce(() =>
Promise.reject(error)
);
await act(async () => {
wrapper.find('InstanceGroupForm').invoke('onSubmit')(
updatedInstanceGroup
);
});
wrapper.update();
expect(wrapper.find('FormSubmitError').length).toBe(1);
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { func, shape } from 'prop-types';
import { Formik } from 'formik';
import { Formik, useField } from 'formik';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Form } from '@patternfly/react-core';
Expand All @@ -11,21 +11,24 @@ import { required, minMaxValue } from '../../../util/validators';
import { FormColumnLayout } from '../../../components/FormLayout';

function InstanceGroupFormFields({ i18n }) {
const [instanceGroupNameField, ,] = useField('name');
return (
<>
<FormField
name="name"
id="instance-group-name"
label={i18n._(t`Name`)}
name="name"
type="text"
validate={required(null, i18n)}
isRequired
isDisabled={instanceGroupNameField.value === 'tower'}
/>
<FormField
id="instance-group-policy-instance-minimum"
label={i18n._(t`Policy instance minimum`)}
name="policy_instance_minimum"
type="number"
min="0"
validate={minMaxValue(0, 2147483647, i18n)}
tooltip={i18n._(
t`Minimum number of instances that will be automatically
Expand All @@ -37,6 +40,8 @@ function InstanceGroupFormFields({ i18n }) {
label={i18n._(t`Policy instance percentage`)}
name="policy_instance_percentage"
type="number"
min="0"
max="100"
tooltip={i18n._(
t`Minimum percentage of all instances that will be automatically
assigned to this group when new instances come online.`
Expand Down

0 comments on commit e3fe680

Please sign in to comment.