mirror of
https://github.com/ansible/awx.git
synced 2026-05-07 17:37:37 -02:30
update tests for PaginatedTable lists
This commit is contained in:
@@ -147,13 +147,14 @@ ListHeader.propTypes = {
|
|||||||
searchColumns: SearchColumns.isRequired,
|
searchColumns: SearchColumns.isRequired,
|
||||||
searchableKeys: PropTypes.arrayOf(PropTypes.string),
|
searchableKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
relatedSearchableKeys: PropTypes.arrayOf(PropTypes.string),
|
relatedSearchableKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
sortColumns: SortColumns.isRequired,
|
sortColumns: SortColumns,
|
||||||
renderToolbar: PropTypes.func,
|
renderToolbar: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
ListHeader.defaultProps = {
|
ListHeader.defaultProps = {
|
||||||
renderToolbar: props => <DataListToolbar {...props} />,
|
renderToolbar: props => <DataListToolbar {...props} />,
|
||||||
searchableKeys: [],
|
searchableKeys: [],
|
||||||
|
sortColumns: null,
|
||||||
relatedSearchableKeys: [],
|
relatedSearchableKeys: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const ActionsGrid = styled.div`
|
|||||||
}}
|
}}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default function ActionsTd({ children }) {
|
export default function ActionsTd({ children, ...props }) {
|
||||||
const numActions = children.length || 1;
|
const numActions = children.length || 1;
|
||||||
const width = numActions * 40;
|
const width = numActions * 40;
|
||||||
return (
|
return (
|
||||||
@@ -25,6 +25,7 @@ export default function ActionsTd({ children }) {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
--pf-c-table--cell--Width: ${width}px;
|
--pf-c-table--cell--Width: ${width}px;
|
||||||
`}
|
`}
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
<ActionsGrid numActions={numActions}>
|
<ActionsGrid numActions={numActions}>
|
||||||
{React.Children.map(children, (child, i) =>
|
{React.Children.map(children, (child, i) =>
|
||||||
|
|||||||
@@ -36,15 +36,9 @@ function PaginatedTable({
|
|||||||
showPageSizeOptions,
|
showPageSizeOptions,
|
||||||
i18n,
|
i18n,
|
||||||
renderToolbar,
|
renderToolbar,
|
||||||
// onRowClick,
|
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
// const handleListItemSelect = (id = 0) => {
|
|
||||||
// const match = items.find(item => item.id === Number(id));
|
|
||||||
// onRowClick(match);
|
|
||||||
// };
|
|
||||||
|
|
||||||
const pushHistoryState = params => {
|
const pushHistoryState = params => {
|
||||||
const { pathname } = history.location;
|
const { pathname } = history.location;
|
||||||
const encodedParams = encodeNonDefaultQueryString(qsConfig, params);
|
const encodedParams = encodeNonDefaultQueryString(qsConfig, params);
|
||||||
@@ -174,7 +168,6 @@ PaginatedTable.propTypes = {
|
|||||||
renderToolbar: PropTypes.func,
|
renderToolbar: PropTypes.func,
|
||||||
hasContentLoading: PropTypes.bool,
|
hasContentLoading: PropTypes.bool,
|
||||||
contentError: PropTypes.shape(),
|
contentError: PropTypes.shape(),
|
||||||
// onRowClick: PropTypes.func,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PaginatedTable.defaultProps = {
|
PaginatedTable.defaultProps = {
|
||||||
@@ -187,7 +180,6 @@ PaginatedTable.defaultProps = {
|
|||||||
showPageSizeOptions: true,
|
showPageSizeOptions: true,
|
||||||
renderRow: item => <PaginatedTableRow key={item.id} item={item} />,
|
renderRow: item => <PaginatedTableRow key={item.id} item={item} />,
|
||||||
renderToolbar: props => <DataListToolbar {...props} />,
|
renderToolbar: props => <DataListToolbar {...props} />,
|
||||||
// onRowClick: () => null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { PaginatedTable as _PaginatedTable };
|
export { PaginatedTable as _PaginatedTable };
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
SyncAltIcon,
|
SyncAltIcon,
|
||||||
ExclamationTriangleIcon,
|
ExclamationTriangleIcon,
|
||||||
ClockIcon,
|
ClockIcon,
|
||||||
|
MinusCircleIcon,
|
||||||
} from '@patternfly/react-icons';
|
} from '@patternfly/react-icons';
|
||||||
import styled, { keyframes } from 'styled-components';
|
import styled, { keyframes } from 'styled-components';
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ const colors = {
|
|||||||
running: 'blue',
|
running: 'blue',
|
||||||
pending: 'blue',
|
pending: 'blue',
|
||||||
waiting: 'grey',
|
waiting: 'grey',
|
||||||
|
disabled: 'grey',
|
||||||
canceled: 'orange',
|
canceled: 'orange',
|
||||||
};
|
};
|
||||||
const icons = {
|
const icons = {
|
||||||
@@ -42,6 +44,7 @@ const icons = {
|
|||||||
running: RunningIcon,
|
running: RunningIcon,
|
||||||
pending: ClockIcon,
|
pending: ClockIcon,
|
||||||
waiting: ClockIcon,
|
waiting: ClockIcon,
|
||||||
|
disabled: MinusCircleIcon,
|
||||||
canceled: ExclamationTriangleIcon,
|
canceled: ExclamationTriangleIcon,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +69,7 @@ StatusLabel.propTypes = {
|
|||||||
'running',
|
'running',
|
||||||
'pending',
|
'pending',
|
||||||
'waiting',
|
'waiting',
|
||||||
|
'disabled',
|
||||||
'canceled',
|
'canceled',
|
||||||
]).isRequired,
|
]).isRequired,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ function InventoryList({ i18n }) {
|
|||||||
itemCount={itemCount}
|
itemCount={itemCount}
|
||||||
pluralizedItemName={i18n._(t`Inventories`)}
|
pluralizedItemName={i18n._(t`Inventories`)}
|
||||||
qsConfig={QS_CONFIG}
|
qsConfig={QS_CONFIG}
|
||||||
onRowClick={handleSelect}
|
|
||||||
toolbarSearchColumns={[
|
toolbarSearchColumns={[
|
||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
|
|||||||
@@ -56,15 +56,16 @@ function InventoryListItem({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tr id={inventory.id}>
|
<Tr id={inventory.id} aria-labelledby={labelId}>
|
||||||
<Td
|
<Td
|
||||||
select={{
|
select={{
|
||||||
rowIndex,
|
rowIndex,
|
||||||
isSelected,
|
isSelected,
|
||||||
onSelect,
|
onSelect,
|
||||||
}}
|
}}
|
||||||
|
dataLabel={i18n._(t`Selected`)}
|
||||||
/>
|
/>
|
||||||
<Td id={labelId}>
|
<Td id={labelId} dataLabel={i18n._(t`Name`)}>
|
||||||
{inventory.pending_deletion ? (
|
{inventory.pending_deletion ? (
|
||||||
<b>{inventory.name}</b>
|
<b>{inventory.name}</b>
|
||||||
) : (
|
) : (
|
||||||
@@ -73,30 +74,32 @@ function InventoryListItem({
|
|||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td dataLabel={i18n._(t`Status`)}>
|
||||||
{inventory.kind !== 'smart' && <StatusLabel status={syncStatus} />}
|
{inventory.kind !== 'smart' && <StatusLabel status={syncStatus} />}
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td dataLabel={i18n._(t`Type`)}>
|
||||||
{inventory.kind === 'smart'
|
{inventory.kind === 'smart'
|
||||||
? i18n._(t`Smart Inventory`)
|
? i18n._(t`Smart Inventory`)
|
||||||
: i18n._(t`Inventory`)}
|
: i18n._(t`Inventory`)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td key="organization">
|
<Td key="organization" dataLabel={i18n._(t`Organization`)}>
|
||||||
<Link
|
<Link
|
||||||
to={`/organizations/${inventory.summary_fields.organization.id}/details`}
|
to={`/organizations/${inventory.summary_fields.organization.id}/details`}
|
||||||
>
|
>
|
||||||
{inventory.summary_fields.organization.name}
|
{inventory.summary_fields.organization.name}
|
||||||
</Link>
|
</Link>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>{inventory.total_groups}</Td>
|
<Td dataLabel={i18n._(t`Groups`)}>{inventory.total_groups}</Td>
|
||||||
<Td>{inventory.total_hosts}</Td>
|
<Td dataLabel={i18n._(t`Hosts`)}>{inventory.total_hosts}</Td>
|
||||||
<Td>{inventory.total_inventory_sources}</Td>
|
<Td dataLabel={i18n._(t`Sources`)}>
|
||||||
|
{inventory.total_inventory_sources}
|
||||||
|
</Td>
|
||||||
{inventory.pending_deletion ? (
|
{inventory.pending_deletion ? (
|
||||||
<Td>
|
<Td dataLabel={i18n._(t`Groups`)}>
|
||||||
<Label color="red">{i18n._(t`Pending delete`)}</Label>
|
<Label color="red">{i18n._(t`Pending delete`)}</Label>
|
||||||
</Td>
|
</Td>
|
||||||
) : (
|
) : (
|
||||||
<ActionsTd>
|
<ActionsTd dataLabel={i18n._(t`Actions`)}>
|
||||||
<ActionItem
|
<ActionItem
|
||||||
visible={inventory.summary_fields.user_capabilities.edit}
|
visible={inventory.summary_fields.user_capabilities.edit}
|
||||||
tooltip={i18n._(t`Edit Inventory`)}
|
tooltip={i18n._(t`Edit Inventory`)}
|
||||||
|
|||||||
@@ -9,145 +9,167 @@ jest.mock('../../../api/models/Inventories');
|
|||||||
describe('<InventoryListItem />', () => {
|
describe('<InventoryListItem />', () => {
|
||||||
test('initially renders succesfully', () => {
|
test('initially renders succesfully', () => {
|
||||||
mountWithContexts(
|
mountWithContexts(
|
||||||
<InventoryListItem
|
<table>
|
||||||
inventory={{
|
<tbody>
|
||||||
id: 1,
|
<InventoryListItem
|
||||||
name: 'Inventory',
|
inventory={{
|
||||||
summary_fields: {
|
|
||||||
organization: {
|
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Default',
|
name: 'Inventory',
|
||||||
},
|
summary_fields: {
|
||||||
user_capabilities: {
|
organization: {
|
||||||
edit: true,
|
id: 1,
|
||||||
},
|
name: 'Default',
|
||||||
},
|
},
|
||||||
}}
|
user_capabilities: {
|
||||||
detailUrl="/inventories/inventory/1"
|
edit: true,
|
||||||
isSelected
|
},
|
||||||
onSelect={() => {}}
|
},
|
||||||
/>
|
}}
|
||||||
|
detailUrl="/inventories/inventory/1"
|
||||||
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should render prompt list item data', () => {
|
test('should render prompt list item data', () => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<InventoryListItem
|
<table>
|
||||||
inventory={{
|
<tbody>
|
||||||
id: 1,
|
<InventoryListItem
|
||||||
name: 'Inventory',
|
inventory={{
|
||||||
kind: '',
|
|
||||||
summary_fields: {
|
|
||||||
organization: {
|
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Default',
|
name: 'Inventory',
|
||||||
},
|
kind: '',
|
||||||
user_capabilities: {
|
summary_fields: {
|
||||||
edit: true,
|
organization: {
|
||||||
},
|
id: 1,
|
||||||
},
|
name: 'Default',
|
||||||
}}
|
},
|
||||||
detailUrl="/inventories/inventory/1"
|
user_capabilities: {
|
||||||
isSelected
|
edit: true,
|
||||||
onSelect={() => {}}
|
},
|
||||||
/>
|
},
|
||||||
|
}}
|
||||||
|
detailUrl="/inventories/inventory/1"
|
||||||
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
expect(wrapper.find('SyncStatusIndicator').length).toBe(1);
|
expect(wrapper.find('StatusLabel').length).toBe(1);
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
wrapper
|
||||||
.find('DataListCell')
|
.find('Td')
|
||||||
.at(1)
|
.at(1)
|
||||||
.text()
|
.text()
|
||||||
).toBe('Inventory');
|
).toBe('Inventory');
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
wrapper
|
||||||
.find('DataListCell')
|
.find('Td')
|
||||||
.at(2)
|
.at(2)
|
||||||
.text()
|
.text()
|
||||||
|
).toBe('Disabled');
|
||||||
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('Td')
|
||||||
|
.at(3)
|
||||||
|
.text()
|
||||||
).toBe('Inventory');
|
).toBe('Inventory');
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
wrapper
|
||||||
.find('DataListCell')
|
.find('Td')
|
||||||
.at(3)
|
|
||||||
.text()
|
|
||||||
).toBe('OrganizationDefault');
|
|
||||||
expect(
|
|
||||||
wrapper
|
|
||||||
.find('DataListCell')
|
|
||||||
.at(4)
|
.at(4)
|
||||||
.text()
|
.text()
|
||||||
).toBe('GroupsHostsSources');
|
).toBe('Default');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('edit button shown to users with edit capabilities', () => {
|
test('edit button shown to users with edit capabilities', () => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<InventoryListItem
|
<table>
|
||||||
inventory={{
|
<tbody>
|
||||||
id: 1,
|
<InventoryListItem
|
||||||
name: 'Inventory',
|
inventory={{
|
||||||
summary_fields: {
|
|
||||||
organization: {
|
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Default',
|
name: 'Inventory',
|
||||||
},
|
summary_fields: {
|
||||||
user_capabilities: {
|
organization: {
|
||||||
edit: true,
|
id: 1,
|
||||||
},
|
name: 'Default',
|
||||||
},
|
},
|
||||||
}}
|
user_capabilities: {
|
||||||
detailUrl="/inventories/inventory/1"
|
edit: true,
|
||||||
isSelected
|
},
|
||||||
onSelect={() => {}}
|
},
|
||||||
/>
|
}}
|
||||||
|
detailUrl="/inventories/inventory/1"
|
||||||
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
expect(wrapper.find('PencilAltIcon').exists()).toBeTruthy();
|
expect(wrapper.find('PencilAltIcon').exists()).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('edit button hidden from users without edit capabilities', () => {
|
test('edit button hidden from users without edit capabilities', () => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<InventoryListItem
|
<table>
|
||||||
inventory={{
|
<tbody>
|
||||||
id: 1,
|
<InventoryListItem
|
||||||
name: 'Inventory',
|
inventory={{
|
||||||
summary_fields: {
|
|
||||||
organization: {
|
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Default',
|
name: 'Inventory',
|
||||||
},
|
summary_fields: {
|
||||||
user_capabilities: {
|
organization: {
|
||||||
edit: false,
|
id: 1,
|
||||||
},
|
name: 'Default',
|
||||||
},
|
},
|
||||||
}}
|
user_capabilities: {
|
||||||
detailUrl="/inventories/inventory/1"
|
edit: false,
|
||||||
isSelected
|
},
|
||||||
onSelect={() => {}}
|
},
|
||||||
/>
|
}}
|
||||||
|
detailUrl="/inventories/inventory/1"
|
||||||
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy();
|
expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should call api to copy inventory', async () => {
|
test('should call api to copy inventory', async () => {
|
||||||
InventoriesAPI.copy.mockResolvedValue();
|
InventoriesAPI.copy.mockResolvedValue();
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<InventoryListItem
|
<table>
|
||||||
inventory={{
|
<tbody>
|
||||||
id: 1,
|
<InventoryListItem
|
||||||
name: 'Inventory',
|
inventory={{
|
||||||
summary_fields: {
|
|
||||||
organization: {
|
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Default',
|
name: 'Inventory',
|
||||||
},
|
summary_fields: {
|
||||||
user_capabilities: {
|
organization: {
|
||||||
edit: false,
|
id: 1,
|
||||||
copy: true,
|
name: 'Default',
|
||||||
},
|
},
|
||||||
},
|
user_capabilities: {
|
||||||
}}
|
edit: false,
|
||||||
detailUrl="/inventories/inventory/1"
|
copy: true,
|
||||||
isSelected
|
},
|
||||||
onSelect={() => {}}
|
},
|
||||||
/>
|
}}
|
||||||
|
detailUrl="/inventories/inventory/1"
|
||||||
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
|
|
||||||
await act(async () =>
|
await act(async () =>
|
||||||
@@ -161,25 +183,29 @@ describe('<InventoryListItem />', () => {
|
|||||||
InventoriesAPI.copy.mockRejectedValue(new Error());
|
InventoriesAPI.copy.mockRejectedValue(new Error());
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<InventoryListItem
|
<table>
|
||||||
inventory={{
|
<tbody>
|
||||||
id: 1,
|
<InventoryListItem
|
||||||
name: 'Inventory',
|
inventory={{
|
||||||
summary_fields: {
|
|
||||||
organization: {
|
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Default',
|
name: 'Inventory',
|
||||||
},
|
summary_fields: {
|
||||||
user_capabilities: {
|
organization: {
|
||||||
edit: false,
|
id: 1,
|
||||||
copy: true,
|
name: 'Default',
|
||||||
},
|
},
|
||||||
},
|
user_capabilities: {
|
||||||
}}
|
edit: false,
|
||||||
detailUrl="/inventories/inventory/1"
|
copy: true,
|
||||||
isSelected
|
},
|
||||||
onSelect={() => {}}
|
},
|
||||||
/>
|
}}
|
||||||
|
detailUrl="/inventories/inventory/1"
|
||||||
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
await act(async () =>
|
await act(async () =>
|
||||||
wrapper.find('Button[aria-label="Copy"]').prop('onClick')()
|
wrapper.find('Button[aria-label="Copy"]').prop('onClick')()
|
||||||
@@ -191,25 +217,29 @@ describe('<InventoryListItem />', () => {
|
|||||||
|
|
||||||
test('should not render copy button', async () => {
|
test('should not render copy button', async () => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<InventoryListItem
|
<table>
|
||||||
inventory={{
|
<tbody>
|
||||||
id: 1,
|
<InventoryListItem
|
||||||
name: 'Inventory',
|
inventory={{
|
||||||
summary_fields: {
|
|
||||||
organization: {
|
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Default',
|
name: 'Inventory',
|
||||||
},
|
summary_fields: {
|
||||||
user_capabilities: {
|
organization: {
|
||||||
edit: false,
|
id: 1,
|
||||||
copy: false,
|
name: 'Default',
|
||||||
},
|
},
|
||||||
},
|
user_capabilities: {
|
||||||
}}
|
edit: false,
|
||||||
detailUrl="/inventories/inventory/1"
|
copy: false,
|
||||||
isSelected
|
},
|
||||||
onSelect={() => {}}
|
},
|
||||||
/>
|
}}
|
||||||
|
detailUrl="/inventories/inventory/1"
|
||||||
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
expect(wrapper.find('CopyButton').length).toBe(0);
|
expect(wrapper.find('CopyButton').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -122,14 +122,12 @@ function OrganizationsList({ i18n }) {
|
|||||||
<PageSection>
|
<PageSection>
|
||||||
<Card>
|
<Card>
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
// TODO: audit if any of these props are no longer in use
|
|
||||||
contentError={contentError}
|
contentError={contentError}
|
||||||
hasContentLoading={hasContentLoading}
|
hasContentLoading={hasContentLoading}
|
||||||
items={organizations}
|
items={organizations}
|
||||||
itemCount={organizationCount}
|
itemCount={organizationCount}
|
||||||
pluralizedItemName={i18n._(t`Organizations`)}
|
pluralizedItemName={i18n._(t`Organizations`)}
|
||||||
qsConfig={QS_CONFIG}
|
qsConfig={QS_CONFIG}
|
||||||
onRowClick={handleSelect}
|
|
||||||
toolbarSearchColumns={[
|
toolbarSearchColumns={[
|
||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ describe('<OrganizationsList />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Item appears selected after selecting it', async () => {
|
test('Item appears selected after selecting it', async () => {
|
||||||
const itemCheckboxInput = 'input#select-organization-1';
|
const itemCheckboxInput = 'tr#org-row-1 input[type="checkbox"]';
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(<OrganizationsList />);
|
wrapper = mountWithContexts(<OrganizationsList />);
|
||||||
});
|
});
|
||||||
@@ -115,7 +115,6 @@ describe('<OrganizationsList />', () => {
|
|||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper
|
wrapper
|
||||||
.find(itemCheckboxInput)
|
.find(itemCheckboxInput)
|
||||||
.closest('DataListCheck')
|
|
||||||
.props()
|
.props()
|
||||||
.onChange();
|
.onChange();
|
||||||
});
|
});
|
||||||
@@ -128,9 +127,9 @@ describe('<OrganizationsList />', () => {
|
|||||||
|
|
||||||
test('All items appear selected after select-all and unselected after unselect-all', async () => {
|
test('All items appear selected after select-all and unselected after unselect-all', async () => {
|
||||||
const itemCheckboxInputs = [
|
const itemCheckboxInputs = [
|
||||||
'input#select-organization-1',
|
'tr#org-row-1 input[type="checkbox"]',
|
||||||
'input#select-organization-2',
|
'tr#org-row-2 input[type="checkbox"]',
|
||||||
'input#select-organization-3',
|
'tr#org-row-3 input[type="checkbox"]',
|
||||||
];
|
];
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(<OrganizationsList />);
|
wrapper = mountWithContexts(<OrganizationsList />);
|
||||||
@@ -227,7 +226,7 @@ describe('<OrganizationsList />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Error dialog shown for failed deletion', async () => {
|
test('Error dialog shown for failed deletion', async () => {
|
||||||
const itemCheckboxInput = 'input#select-organization-1';
|
const itemCheckboxInput = 'tr#org-row-1 input[type="checkbox"]';
|
||||||
OrganizationsAPI.destroy.mockRejectedValue(
|
OrganizationsAPI.destroy.mockRejectedValue(
|
||||||
new Error({
|
new Error({
|
||||||
response: {
|
response: {
|
||||||
@@ -250,7 +249,6 @@ describe('<OrganizationsList />', () => {
|
|||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper
|
wrapper
|
||||||
.find(itemCheckboxInput)
|
.find(itemCheckboxInput)
|
||||||
.closest('DataListCheck')
|
|
||||||
.props()
|
.props()
|
||||||
.onChange();
|
.onChange();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function OrganizationListItem({
|
|||||||
}) {
|
}) {
|
||||||
const labelId = `check-action-${organization.id}`;
|
const labelId = `check-action-${organization.id}`;
|
||||||
return (
|
return (
|
||||||
<Tr id={`${organization.id}`}>
|
<Tr id={`org-row-${organization.id}`}>
|
||||||
<Td
|
<Td
|
||||||
select={{
|
select={{
|
||||||
rowIndex,
|
rowIndex,
|
||||||
|
|||||||
@@ -11,77 +11,91 @@ describe('<OrganizationListItem />', () => {
|
|||||||
mountWithContexts(
|
mountWithContexts(
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<MemoryRouter initialEntries={['/organizations']} initialIndex={0}>
|
<MemoryRouter initialEntries={['/organizations']} initialIndex={0}>
|
||||||
<OrganizationListItem
|
<table>
|
||||||
organization={{
|
<tbody>
|
||||||
id: 1,
|
<OrganizationListItem
|
||||||
name: 'Org',
|
organization={{
|
||||||
summary_fields: {
|
id: 1,
|
||||||
related_field_counts: {
|
name: 'Org',
|
||||||
users: 1,
|
summary_fields: {
|
||||||
teams: 1,
|
related_field_counts: {
|
||||||
},
|
users: 1,
|
||||||
user_capabilities: {
|
teams: 1,
|
||||||
edit: true,
|
},
|
||||||
},
|
user_capabilities: {
|
||||||
},
|
edit: true,
|
||||||
}}
|
},
|
||||||
detailUrl="/organization/1"
|
},
|
||||||
isSelected
|
}}
|
||||||
onSelect={() => {}}
|
detailUrl="/organization/1"
|
||||||
/>
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('edit button shown to users with edit capabilities', () => {
|
test('edit button shown to users with edit capabilities', () => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<MemoryRouter initialEntries={['/organizations']} initialIndex={0}>
|
<MemoryRouter initialEntries={['/organizations']} initialIndex={0}>
|
||||||
<OrganizationListItem
|
<table>
|
||||||
organization={{
|
<tbody>
|
||||||
id: 1,
|
<OrganizationListItem
|
||||||
name: 'Org',
|
organization={{
|
||||||
summary_fields: {
|
id: 1,
|
||||||
related_field_counts: {
|
name: 'Org',
|
||||||
users: 1,
|
summary_fields: {
|
||||||
teams: 1,
|
related_field_counts: {
|
||||||
},
|
users: 1,
|
||||||
user_capabilities: {
|
teams: 1,
|
||||||
edit: true,
|
},
|
||||||
},
|
user_capabilities: {
|
||||||
},
|
edit: true,
|
||||||
}}
|
},
|
||||||
detailUrl="/organization/1"
|
},
|
||||||
isSelected
|
}}
|
||||||
onSelect={() => {}}
|
detailUrl="/organization/1"
|
||||||
/>
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
);
|
);
|
||||||
expect(wrapper.find('PencilAltIcon').exists()).toBeTruthy();
|
expect(wrapper.find('PencilAltIcon').exists()).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('edit button hidden from users without edit capabilities', () => {
|
test('edit button hidden from users without edit capabilities', () => {
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<MemoryRouter initialEntries={['/organizations']} initialIndex={0}>
|
<MemoryRouter initialEntries={['/organizations']} initialIndex={0}>
|
||||||
<OrganizationListItem
|
<table>
|
||||||
organization={{
|
<tbody>
|
||||||
id: 1,
|
<OrganizationListItem
|
||||||
name: 'Org',
|
organization={{
|
||||||
summary_fields: {
|
id: 1,
|
||||||
related_field_counts: {
|
name: 'Org',
|
||||||
users: 1,
|
summary_fields: {
|
||||||
teams: 1,
|
related_field_counts: {
|
||||||
},
|
users: 1,
|
||||||
user_capabilities: {
|
teams: 1,
|
||||||
edit: false,
|
},
|
||||||
},
|
user_capabilities: {
|
||||||
},
|
edit: false,
|
||||||
}}
|
},
|
||||||
detailUrl="/organization/1"
|
},
|
||||||
isSelected
|
}}
|
||||||
onSelect={() => {}}
|
detailUrl="/organization/1"
|
||||||
/>
|
isSelected
|
||||||
|
onSelect={() => {}}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user