updating job template tests

This commit is contained in:
Keith Grant
2019-07-22 16:21:11 -07:00
parent 5edc6deeae
commit bb5b255c28
6 changed files with 73 additions and 43 deletions

View File

@@ -176,15 +176,21 @@ class Lookup extends React.Component {
columns, columns,
multiple, multiple,
name, name,
required,
i18n, i18n,
} = this.props; } = this.props;
const header = lookupHeader || i18n._(t`items`); const header = lookupHeader || i18n._(t`items`);
const canDelete = !required || (multiple && value.length > 1);
const chips = value ? ( const chips = value ? (
<ChipGroup> <ChipGroup>
{(multiple ? value : [value]).map(chip => ( {(multiple ? value : [value]).map(chip => (
<Chip key={chip.id} onClick={() => this.toggleSelected(chip)}> <Chip
key={chip.id}
onClick={() => this.toggleSelected(chip)}
isReadOnly={!canDelete}
>
{chip.name} {chip.name}
</Chip> </Chip>
))} ))}
@@ -253,6 +259,7 @@ class Lookup extends React.Component {
selected={lookupSelectedItems} selected={lookupSelectedItems}
showOverflowAfter={5} showOverflowAfter={5}
onRemove={this.toggleSelected} onRemove={this.toggleSelected}
isReadOnly={!canDelete}
/> />
)} )}
{error ? <div>error</div> : ''} {error ? <div>error</div> : ''}
@@ -272,16 +279,19 @@ Lookup.propTypes = {
lookupHeader: string, lookupHeader: string,
name: string, name: string,
onLookupSave: func.isRequired, onLookupSave: func.isRequired,
value: oneOfType([Item, arrayOf(Item)]).isRequired, value: oneOfType([Item, arrayOf(Item)]),
sortedColumnKey: string.isRequired, sortedColumnKey: string.isRequired,
multiple: bool, multiple: bool,
required: bool,
}; };
Lookup.defaultProps = { Lookup.defaultProps = {
id: 'lookup-search', id: 'lookup-search',
lookupHeader: null, lookupHeader: null,
name: null, name: null,
value: null,
multiple: false, multiple: false,
required: false,
}; };
export { Lookup as _Lookup }; export { Lookup as _Lookup };

View File

@@ -17,6 +17,7 @@ describe('<Lookup />', () => {
getItems={() => {}} getItems={() => {}}
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
); );
}); });
@@ -33,6 +34,7 @@ describe('<Lookup />', () => {
})} })}
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
).find('Lookup'); ).find('Lookup');
@@ -57,6 +59,7 @@ describe('<Lookup />', () => {
getItems={() => {}} getItems={() => {}}
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
).find('Lookup'); ).find('Lookup');
expect(spy).not.toHaveBeenCalled(); expect(spy).not.toHaveBeenCalled();
@@ -90,6 +93,7 @@ describe('<Lookup />', () => {
getItems={() => ({ data })} getItems={() => ({ data })}
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
); );
setImmediate(() => { setImmediate(() => {
@@ -118,6 +122,7 @@ describe('<Lookup />', () => {
getItems={() => ({ data })} getItems={() => ({ data })}
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
); );
const removeIcon = wrapper.find('button[aria-label="close"]').first(); const removeIcon = wrapper.find('button[aria-label="close"]').first();
@@ -136,6 +141,7 @@ describe('<Lookup />', () => {
getItems={() => {}} getItems={() => {}}
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
).find('Lookup'); ).find('Lookup');
const chip = wrapper.find('.pf-c-chip'); const chip = wrapper.find('.pf-c-chip');
@@ -152,6 +158,7 @@ describe('<Lookup />', () => {
getItems={() => {}} getItems={() => {}}
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
).find('Lookup'); ).find('Lookup');
wrapper.instance().toggleSelected({ wrapper.instance().toggleSelected({
@@ -182,6 +189,7 @@ describe('<Lookup />', () => {
onLookupSave={onLookupSaveFn} onLookupSave={onLookupSaveFn}
getItems={() => {}} getItems={() => {}}
sortedColumnKey="name" sortedColumnKey="name"
multiple
/> />
).find('Lookup'); ).find('Lookup');
wrapper.instance().toggleSelected({ wrapper.instance().toggleSelected({
@@ -206,7 +214,40 @@ describe('<Lookup />', () => {
); );
}); });
test('should call callback with selected single item', () => {
mockData = { name: 'foo', id: 1, isChecked: false, url: 'https://foo' };
const onLookupSaveFn = jest.fn();
const wrapper = mountWithContexts(
<Lookup
lookupHeader="Foo Bar"
name="fooBar"
value={mockData}
onLookupSave={onLookupSaveFn}
getItems={() => ({
data: {
results: [ mockData ],
count: 1,
}
})}
sortedColumnKey="name"
/>
);
wrapper.find('Lookup').instance().toggleSelected({
id: 1,
name: 'foo',
});
wrapper.find('Lookup').instance().saveModal();
expect(onLookupSaveFn).toHaveBeenCalledWith(
{
id: 1,
name: 'foo',
},
'fooBar'
);
});
test('should re-fetch data when URL params change', async () => { test('should re-fetch data when URL params change', async () => {
mockData = [{ name: 'foo', id: 1, isChecked: false }];
const history = createMemoryHistory({ const history = createMemoryHistory({
initialEntries: ['/organizations/add'], initialEntries: ['/organizations/add'],
}); });
@@ -220,6 +261,7 @@ describe('<Lookup />', () => {
columns={mockColumns} columns={mockColumns}
sortedColumnKey="name" sortedColumnKey="name"
getItems={getItems} getItems={getItems}
multiple
handleHttpError={() => {}} handleHttpError={() => {}}
location={{ history }} location={{ history }}
i18n={{ _: val => val.toString() }} i18n={{ _: val => val.toString() }}

View File

@@ -29,7 +29,7 @@ describe('<JobTemplateAdd />', () => {
expect(wrapper.find('input#template-description').text()).toBe( expect(wrapper.find('input#template-description').text()).toBe(
defaultProps.description defaultProps.description
); );
expect(wrapper.find('input#template-inventory').text()).toBe( expect(wrapper.find('InventoriesLookup').prop('value')).toBe(
defaultProps.inventory defaultProps.inventory
); );
expect(wrapper.find('AnsibleSelect[name="job_type"]').props().value).toBe( expect(wrapper.find('AnsibleSelect[name="job_type"]').props().value).toBe(

View File

@@ -1,5 +1,5 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { string, func } from 'prop-types'; import { string, func, bool } from 'prop-types';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { FormGroup, Tooltip } from '@patternfly/react-core'; import { FormGroup, Tooltip } from '@patternfly/react-core';
@@ -13,7 +13,7 @@ const getInventories = async params => InventoriesAPI.read(params);
class InventoriesLookup extends React.Component { class InventoriesLookup extends React.Component {
render() { render() {
const { value, tooltip, onChange, i18n } = this.props; const { value, tooltip, onChange, required, i18n } = this.props;
return ( return (
<FormGroup <FormGroup
@@ -36,6 +36,7 @@ class InventoriesLookup extends React.Component {
value={value} value={value}
onLookupSave={onChange} onLookupSave={onChange}
getItems={getInventories} getItems={getInventories}
required={required}
columns={[ columns={[
{ name: i18n._(t`Name`), key: 'name', isSortable: true }, { name: i18n._(t`Name`), key: 'name', isSortable: true },
{ {
@@ -59,13 +60,16 @@ class InventoriesLookup extends React.Component {
} }
InventoriesLookup.propTypes = { InventoriesLookup.propTypes = {
value: Inventory.isRequired, value: Inventory,
tooltip: string, tooltip: string,
onChange: func.isRequired, onChange: func.isRequired,
required: bool,
}; };
InventoriesLookup.defaultProps = { InventoriesLookup.defaultProps = {
value: null,
tooltip: '', tooltip: '',
required: false,
}; };
export default withI18n()(InventoriesLookup); export default withI18n()(InventoriesLookup);

View File

@@ -128,43 +128,10 @@ class JobTemplateForm extends Component {
form.setFieldValue('inventory', value.id); form.setFieldValue('inventory', value.id);
this.setState({ inventory: value }); this.setState({ inventory: value });
}} }}
required
/> />
)} )}
/> />
{/* <FormGroup
fieldId="template-inventory"
helperTextInvalid={form.errors.inventory}
isRequired
label={i18n._(t`Inventory`)}
>
<Lookup
id="template-inventory"
lookupHeader={i18n._(t`Inventory`)}
name="inventory"
value={[field.value]}
onLookupSave={(value) => {console.log(value)}}
getItems={() => ({
data: {
results: [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}],
count: 2
}
})}
columns={[
{ name: i18n._(t`Name`), key: 'name', isSortable: true},
]}
sortedColumnsKey="name"
/>
</FormGroup> */}
{/* <FormField
id="template-inventory"
name="inventory"
type="number"
label={i18n._(t`Inventory`)}
tooltip={i18n._(t`Select the inventory containing the hosts
you want this job to manage.`)}
isRequired
validate={required(null, i18n)}
/> */}
<FormField <FormField
id="template-project" id="template-project"
name="project" name="project"

View File

@@ -15,6 +15,12 @@ describe('<JobTemplateForm />', () => {
project: 3, project: 3,
playbook: 'Baz', playbook: 'Baz',
type: 'job_template', type: 'job_template',
summary_fields: {
inventory: {
id: 2,
name: 'foo',
},
},
}; };
afterEach(() => { afterEach(() => {
@@ -31,7 +37,7 @@ describe('<JobTemplateForm />', () => {
); );
}); });
test('should update form values on input changes', () => { test('should update form values on input changes', async () => {
const wrapper = mountWithContexts( const wrapper = mountWithContexts(
<JobTemplateForm <JobTemplateForm
template={mockData} template={mockData}
@@ -53,8 +59,9 @@ describe('<JobTemplateForm />', () => {
target: { value: 'new job type', name: 'job_type' }, target: { value: 'new job type', name: 'job_type' },
}); });
expect(form.state('values').job_type).toEqual('new job type'); expect(form.state('values').job_type).toEqual('new job type');
wrapper.find('input#template-inventory').simulate('change', { wrapper.find('InventoriesLookup').prop('onChange')({
target: { value: 3, name: 'inventory' }, id: 3,
name: 'inventory'
}); });
expect(form.state('values').inventory).toEqual(3); expect(form.state('values').inventory).toEqual(3);
wrapper.find('input#template-project').simulate('change', { wrapper.find('input#template-project').simulate('change', {