mirror of
https://github.com/ansible/awx.git
synced 2026-02-25 06:56:00 -03:30
Merge pull request #11090 from AlexSCorey/10952-AddHealthCheckOnInstancesList
Adds Health Check functionality to instance list
This commit is contained in:
@@ -6,10 +6,10 @@ class Instances extends Base {
|
|||||||
this.baseUrl = '/api/v2/instances/';
|
this.baseUrl = '/api/v2/instances/';
|
||||||
|
|
||||||
this.readHealthCheckDetail = this.readHealthCheckDetail.bind(this);
|
this.readHealthCheckDetail = this.readHealthCheckDetail.bind(this);
|
||||||
this.createHealthCheck = this.createHealthCheck.bind(this);
|
this.healthCheck = this.healthCheck.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
createHealthCheck(instanceId) {
|
healthCheck(instanceId) {
|
||||||
return this.http.post(`${this.baseUrl}${instanceId}/health_check/`);
|
return this.http.post(`${this.baseUrl}${instanceId}/health_check/`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ function InstanceToggle({ className, fetchInstances, instance, onToggle }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={t`Set the instance online or offline. If offline, jobs will not be assigned to this instance.`}
|
content={t`Set the instance enabled or disabled. If disabled, jobs will not be assigned to this instance.`}
|
||||||
position="top"
|
position="top"
|
||||||
>
|
>
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ function InstanceDetails({ setBreadcrumb, instanceGroup }) {
|
|||||||
|
|
||||||
const { error: healthCheckError, request: fetchHealthCheck } = useRequest(
|
const { error: healthCheckError, request: fetchHealthCheck } = useRequest(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const { data } = await InstancesAPI.createHealthCheck(instanceId);
|
const { data } = await InstancesAPI.healthCheck(instanceId);
|
||||||
setHealthCheck(data);
|
setHealthCheck(data);
|
||||||
}, [instanceId])
|
}, [instanceId])
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ describe('<InstanceDetails/>', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Should make request for Health Check', async () => {
|
test('Should make request for Health Check', async () => {
|
||||||
InstancesAPI.createHealthCheck.mockResolvedValue({
|
InstancesAPI.healthCheck.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
uuid: '00000000-0000-0000-0000-000000000000',
|
uuid: '00000000-0000-0000-0000-000000000000',
|
||||||
hostname: 'awx_1',
|
hostname: 'awx_1',
|
||||||
@@ -342,7 +342,7 @@ describe('<InstanceDetails/>', () => {
|
|||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find("Button[ouiaId='health-check-button']").prop('onClick')();
|
wrapper.find("Button[ouiaId='health-check-button']").prop('onClick')();
|
||||||
});
|
});
|
||||||
expect(InstancesAPI.createHealthCheck).toBeCalledWith(1);
|
expect(InstancesAPI.healthCheck).toBeCalledWith(1);
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find("Detail[label='Last Health Check']").prop('value')
|
wrapper.find("Detail[label='Last Health Check']").prop('value')
|
||||||
@@ -350,7 +350,7 @@ describe('<InstanceDetails/>', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Should handle api error for health check', async () => {
|
test('Should handle api error for health check', async () => {
|
||||||
InstancesAPI.createHealthCheck.mockRejectedValue(
|
InstancesAPI.healthCheck.mockRejectedValue(
|
||||||
new Error({
|
new Error({
|
||||||
response: {
|
response: {
|
||||||
config: {
|
config: {
|
||||||
@@ -392,7 +392,7 @@ describe('<InstanceDetails/>', () => {
|
|||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find("Button[ouiaId='health-check-button']").prop('onClick')();
|
wrapper.find("Button[ouiaId='health-check-button']").prop('onClick')();
|
||||||
});
|
});
|
||||||
expect(InstancesAPI.createHealthCheck).toBeCalledWith(1);
|
expect(InstancesAPI.healthCheck).toBeCalledWith(1);
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('AlertModal')).toHaveLength(1);
|
expect(wrapper.find('AlertModal')).toHaveLength(1);
|
||||||
expect(wrapper.find('ErrorDetail')).toHaveLength(1);
|
expect(wrapper.find('ErrorDetail')).toHaveLength(1);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { t } from '@lingui/macro';
|
import { Plural, t } from '@lingui/macro';
|
||||||
import { useLocation, useParams } from 'react-router-dom';
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
import 'styled-components/macro';
|
import 'styled-components/macro';
|
||||||
|
|
||||||
|
import useExpanded from 'hooks/useExpanded';
|
||||||
import DataListToolbar from 'components/DataListToolbar';
|
import DataListToolbar from 'components/DataListToolbar';
|
||||||
import PaginatedTable, {
|
import PaginatedTable, {
|
||||||
HeaderRow,
|
HeaderRow,
|
||||||
@@ -24,6 +25,7 @@ import useSelected from 'hooks/useSelected';
|
|||||||
import { InstanceGroupsAPI, InstancesAPI } from 'api';
|
import { InstanceGroupsAPI, InstancesAPI } from 'api';
|
||||||
import { getQSConfig, parseQueryString, mergeParams } from 'util/qs';
|
import { getQSConfig, parseQueryString, mergeParams } from 'util/qs';
|
||||||
|
|
||||||
|
import { Button, Tooltip } from '@patternfly/react-core';
|
||||||
import InstanceListItem from './InstanceListItem';
|
import InstanceListItem from './InstanceListItem';
|
||||||
|
|
||||||
const QS_CONFIG = getQSConfig('instance', {
|
const QS_CONFIG = getQSConfig('instance', {
|
||||||
@@ -81,6 +83,13 @@ function InstanceList() {
|
|||||||
fetchInstances();
|
fetchInstances();
|
||||||
}, [fetchInstances]);
|
}, [fetchInstances]);
|
||||||
|
|
||||||
|
const { error: healthCheckError, request: fetchHealthCheck } = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
|
await Promise.all(selected.map(({ id }) => InstancesAPI.healthCheck(id)));
|
||||||
|
fetchInstances();
|
||||||
|
}, [selected, fetchInstances])
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isLoading: isDisassociateLoading,
|
isLoading: isDisassociateLoading,
|
||||||
deleteItems: disassociateInstances,
|
deleteItems: disassociateInstances,
|
||||||
@@ -129,7 +138,7 @@ function InstanceList() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { error, dismissError } = useDismissableError(
|
const { error, dismissError } = useDismissableError(
|
||||||
associateError || disassociateError
|
associateError || disassociateError || healthCheckError
|
||||||
);
|
);
|
||||||
|
|
||||||
const canAdd =
|
const canAdd =
|
||||||
@@ -148,6 +157,9 @@ function InstanceList() {
|
|||||||
[instanceGroupId]
|
[instanceGroupId]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { expanded, isAllExpanded, handleExpand, expandAll } =
|
||||||
|
useExpanded(instances);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
@@ -178,6 +190,8 @@ function InstanceList() {
|
|||||||
{...props}
|
{...props}
|
||||||
isAllSelected={isAllSelected}
|
isAllSelected={isAllSelected}
|
||||||
onSelectAll={selectAll}
|
onSelectAll={selectAll}
|
||||||
|
isAllExpanded={isAllExpanded}
|
||||||
|
onExpandAll={expandAll}
|
||||||
qsConfig={QS_CONFIG}
|
qsConfig={QS_CONFIG}
|
||||||
additionalControls={[
|
additionalControls={[
|
||||||
...(canAdd
|
...(canAdd
|
||||||
@@ -198,6 +212,28 @@ function InstanceList() {
|
|||||||
)}
|
)}
|
||||||
modalTitle={t`Disassociate instance from instance group?`}
|
modalTitle={t`Disassociate instance from instance group?`}
|
||||||
/>,
|
/>,
|
||||||
|
<Tooltip
|
||||||
|
content={
|
||||||
|
selected.length ? (
|
||||||
|
<Plural
|
||||||
|
value={selected.length}
|
||||||
|
one="Click to run a health check on the selected instance."
|
||||||
|
other="Click to run a health check on the selected instances."
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
t`Select an instance to run a health check.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
isDisabled={!canAdd || !selected.length}
|
||||||
|
variant="secondary"
|
||||||
|
ouiaId="health-check"
|
||||||
|
onClick={fetchHealthCheck}
|
||||||
|
>{t`Health Check`}</Button>
|
||||||
|
</div>
|
||||||
|
</Tooltip>,
|
||||||
]}
|
]}
|
||||||
emptyStateControls={
|
emptyStateControls={
|
||||||
canAdd ? (
|
canAdd ? (
|
||||||
@@ -210,10 +246,9 @@ function InstanceList() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
headerRow={
|
headerRow={
|
||||||
<HeaderRow qsConfig={QS_CONFIG}>
|
<HeaderRow qsConfig={QS_CONFIG} isExpandable>
|
||||||
<HeaderCell sortKey="hostname">{t`Name`}</HeaderCell>
|
<HeaderCell sortKey="hostname">{t`Name`}</HeaderCell>
|
||||||
<HeaderCell>{t`Node Type`}</HeaderCell>
|
<HeaderCell sortKey="errors">{t`Status`}</HeaderCell>
|
||||||
<HeaderCell>{t`Policy Type`}</HeaderCell>
|
|
||||||
<HeaderCell>{t`Running Jobs`}</HeaderCell>
|
<HeaderCell>{t`Running Jobs`}</HeaderCell>
|
||||||
<HeaderCell>{t`Total Jobs`}</HeaderCell>
|
<HeaderCell>{t`Total Jobs`}</HeaderCell>
|
||||||
<HeaderCell>{t`Capacity Adjustment`}</HeaderCell>
|
<HeaderCell>{t`Capacity Adjustment`}</HeaderCell>
|
||||||
@@ -223,6 +258,8 @@ function InstanceList() {
|
|||||||
}
|
}
|
||||||
renderRow={(instance, index) => (
|
renderRow={(instance, index) => (
|
||||||
<InstanceListItem
|
<InstanceListItem
|
||||||
|
isExpanded={expanded.some((row) => row.id === instance.id)}
|
||||||
|
onExpand={() => handleExpand(instance)}
|
||||||
key={instance.id}
|
key={instance.id}
|
||||||
value={instance.hostname}
|
value={instance.hostname}
|
||||||
instance={instance}
|
instance={instance}
|
||||||
@@ -252,9 +289,11 @@ function InstanceList() {
|
|||||||
title={t`Error!`}
|
title={t`Error!`}
|
||||||
variant="error"
|
variant="error"
|
||||||
>
|
>
|
||||||
{associateError
|
{associateError && t`Failed to associate.`}
|
||||||
? t`Failed to associate.`
|
{disassociateError &&
|
||||||
: t`Failed to disassociate one or more instances.`}
|
t`Failed to disassociate one or more instances.`}
|
||||||
|
{healthCheckError &&
|
||||||
|
t`Failed to run a health check on one or more instances.`}
|
||||||
<ErrorDetail error={error} />
|
<ErrorDetail error={error} />
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { act } from 'react-dom/test-utils';
|
|||||||
import { Route } from 'react-router-dom';
|
import { Route } from 'react-router-dom';
|
||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
|
|
||||||
import { InstanceGroupsAPI } from 'api';
|
import { InstancesAPI, InstanceGroupsAPI } from 'api';
|
||||||
import {
|
import {
|
||||||
mountWithContexts,
|
mountWithContexts,
|
||||||
waitForElement,
|
waitForElement,
|
||||||
@@ -152,4 +152,49 @@ describe('<InstanceList/>', () => {
|
|||||||
wrapper.find('ModalBoxCloseButton').simulate('click');
|
wrapper.find('ModalBoxCloseButton').simulate('click');
|
||||||
expect(wrapper.find('AssociateModal').length).toBe(0);
|
expect(wrapper.find('AssociateModal').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
test('should run health check', async () => {
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[ouiaId="health-check"]').prop('isDisabled')
|
||||||
|
).toBe(true);
|
||||||
|
await act(async () =>
|
||||||
|
wrapper.find('DataListToolbar').prop('onSelectAll')(instances)
|
||||||
|
);
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[ouiaId="health-check"]').prop('isDisabled')
|
||||||
|
).toBe(false);
|
||||||
|
await act(async () =>
|
||||||
|
wrapper.find('Button[ouiaId="health-check"]').prop('onClick')()
|
||||||
|
);
|
||||||
|
expect(InstancesAPI.healthCheck).toBeCalledTimes(3);
|
||||||
|
});
|
||||||
|
test('should render health check error', async () => {
|
||||||
|
InstancesAPI.healthCheck.mockRejectedValue(
|
||||||
|
new Error({
|
||||||
|
response: {
|
||||||
|
config: {
|
||||||
|
method: 'create',
|
||||||
|
url: '/api/v2/instances',
|
||||||
|
},
|
||||||
|
data: 'An error occurred',
|
||||||
|
status: 403,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[ouiaId="health-check"]').prop('isDisabled')
|
||||||
|
).toBe(true);
|
||||||
|
await act(async () =>
|
||||||
|
wrapper.find('DataListToolbar').prop('onSelectAll')(instances)
|
||||||
|
);
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[ouiaId="health-check"]').prop('isDisabled')
|
||||||
|
).toBe(false);
|
||||||
|
await act(async () =>
|
||||||
|
wrapper.find('Button[ouiaId="health-check"]').prop('onClick')()
|
||||||
|
);
|
||||||
|
wrapper.update();
|
||||||
|
expect(wrapper.find('AlertModal')).toHaveLength(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ import {
|
|||||||
ProgressMeasureLocation,
|
ProgressMeasureLocation,
|
||||||
ProgressSize,
|
ProgressSize,
|
||||||
Slider,
|
Slider,
|
||||||
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { Tr, Td } from '@patternfly/react-table';
|
import { Tr, Td, ExpandableRowContent } from '@patternfly/react-table';
|
||||||
|
import { formatDateString } from 'util/dates';
|
||||||
import { ActionsTd, ActionItem } from 'components/PaginatedTable';
|
import { ActionsTd, ActionItem } from 'components/PaginatedTable';
|
||||||
import InstanceToggle from 'components/InstanceToggle';
|
import InstanceToggle from 'components/InstanceToggle';
|
||||||
|
import StatusLabel from 'components/StatusLabel';
|
||||||
import { Instance } from 'types';
|
import { Instance } from 'types';
|
||||||
import useRequest, { useDismissableError } from 'hooks/useRequest';
|
import useRequest, { useDismissableError } from 'hooks/useRequest';
|
||||||
import useDebounce from 'hooks/useDebounce';
|
import useDebounce from 'hooks/useDebounce';
|
||||||
@@ -21,6 +23,7 @@ import { InstancesAPI } from 'api';
|
|||||||
import { useConfig } from 'contexts/Config';
|
import { useConfig } from 'contexts/Config';
|
||||||
import AlertModal from 'components/AlertModal';
|
import AlertModal from 'components/AlertModal';
|
||||||
import ErrorDetail from 'components/ErrorDetail';
|
import ErrorDetail from 'components/ErrorDetail';
|
||||||
|
import { Detail, DetailList } from 'components/DetailList';
|
||||||
|
|
||||||
const Unavailable = styled.span`
|
const Unavailable = styled.span`
|
||||||
color: var(--pf-global--danger-color--200);
|
color: var(--pf-global--danger-color--200);
|
||||||
@@ -50,6 +53,8 @@ function computeForks(memCapacity, cpuCapacity, selectedCapacityAdjustment) {
|
|||||||
|
|
||||||
function InstanceListItem({
|
function InstanceListItem({
|
||||||
instance,
|
instance,
|
||||||
|
isExpanded,
|
||||||
|
onExpand,
|
||||||
isSelected,
|
isSelected,
|
||||||
onSelect,
|
onSelect,
|
||||||
fetchInstances,
|
fetchInstances,
|
||||||
@@ -106,6 +111,13 @@ function InstanceListItem({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tr id={`instance-row-${instance.id}`}>
|
<Tr id={`instance-row-${instance.id}`}>
|
||||||
|
<Td
|
||||||
|
expand={{
|
||||||
|
rowIndex,
|
||||||
|
isExpanded,
|
||||||
|
onToggle: onExpand,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Td
|
<Td
|
||||||
select={{
|
select={{
|
||||||
rowIndex,
|
rowIndex,
|
||||||
@@ -117,12 +129,17 @@ function InstanceListItem({
|
|||||||
/>
|
/>
|
||||||
<Td id={labelId} dataLabel={t`Name`}>
|
<Td id={labelId} dataLabel={t`Name`}>
|
||||||
<Link to={`/instance_groups/${id}/instances/${instance.id}/details`}>
|
<Link to={`/instance_groups/${id}/instances/${instance.id}/details`}>
|
||||||
{instance.hostname}
|
<b>{instance.hostname}</b>
|
||||||
</Link>
|
</Link>
|
||||||
</Td>
|
</Td>
|
||||||
<Td dataLabel={t`Node Type`}>{instance.node_type}</Td>
|
<Td dataLabel={t`Status`}>
|
||||||
<Td dataLabel={t`Policy Type`}>
|
<Tooltip
|
||||||
{instance.managed_by_policy ? t`Auto` : t`Manual`}
|
content={t`Last Health Check ${formatDateString(
|
||||||
|
instance.last_health_check
|
||||||
|
)}`}
|
||||||
|
>
|
||||||
|
<StatusLabel status={instance.errors ? 'error' : 'healthy'} />
|
||||||
|
</Tooltip>
|
||||||
</Td>
|
</Td>
|
||||||
<Td dataLabel={t`Running Jobs`}>{instance.jobs_running}</Td>
|
<Td dataLabel={t`Running Jobs`}>{instance.jobs_running}</Td>
|
||||||
<Td dataLabel={t`Total Jobs`}>{instance.jobs_total}</Td>
|
<Td dataLabel={t`Total Jobs`}>{instance.jobs_total}</Td>
|
||||||
@@ -166,6 +183,24 @@ function InstanceListItem({
|
|||||||
</ActionItem>
|
</ActionItem>
|
||||||
</ActionsTd>
|
</ActionsTd>
|
||||||
</Tr>
|
</Tr>
|
||||||
|
<Tr isExpanded={isExpanded}>
|
||||||
|
<Td colSpan={2} />
|
||||||
|
<Td colSpan={7}>
|
||||||
|
<ExpandableRowContent>
|
||||||
|
<DetailList>
|
||||||
|
<Detail label={t`Node Type`} value={instance.node_type} />
|
||||||
|
<Detail
|
||||||
|
label={t`Policy Type`}
|
||||||
|
value={instance.managed_by_policy ? t`Auto` : t`Manual`}
|
||||||
|
/>
|
||||||
|
<Detail
|
||||||
|
label={t`Last Health Check`}
|
||||||
|
value={formatDateString(instance.last_health_check)}
|
||||||
|
/>
|
||||||
|
</DetailList>
|
||||||
|
</ExpandableRowContent>
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
{updateError && (
|
{updateError && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
variant="error"
|
variant="error"
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const instance = [
|
|||||||
percent_capacity_remaining: 60.0,
|
percent_capacity_remaining: 60.0,
|
||||||
jobs_running: 0,
|
jobs_running: 0,
|
||||||
jobs_total: 68,
|
jobs_total: 68,
|
||||||
|
last_health_check: '2021-09-15T18:02:07.270664Z',
|
||||||
cpu: 6,
|
cpu: 6,
|
||||||
memory: 2087469056,
|
memory: 2087469056,
|
||||||
cpu_capacity: 24,
|
cpu_capacity: 24,
|
||||||
@@ -58,6 +59,7 @@ const instance = [
|
|||||||
modified: '2020-08-12T20:08:02.836748Z',
|
modified: '2020-08-12T20:08:02.836748Z',
|
||||||
capacity_adjustment: '0.40',
|
capacity_adjustment: '0.40',
|
||||||
version: '13.0.0',
|
version: '13.0.0',
|
||||||
|
last_health_check: '2021-09-15T18:02:07.270664Z',
|
||||||
capacity: 10,
|
capacity: 10,
|
||||||
consumed_capacity: 0,
|
consumed_capacity: 0,
|
||||||
percent_capacity_remaining: 60.0,
|
percent_capacity_remaining: 60.0,
|
||||||
@@ -162,10 +164,8 @@ describe('<InstanceListItem/>', () => {
|
|||||||
expect(wrapper.find('Td[dataLabel="Name"]').find('Link').prop('to')).toBe(
|
expect(wrapper.find('Td[dataLabel="Name"]').find('Link').prop('to')).toBe(
|
||||||
'/instance_groups/1/instances/1/details'
|
'/instance_groups/1/instances/1/details'
|
||||||
);
|
);
|
||||||
expect(wrapper.find('Td').at(1).text()).toBe('awx');
|
expect(wrapper.find('Td').at(2).text()).toBe('awx');
|
||||||
expect(wrapper.find('Progress').prop('value')).toBe(40);
|
expect(wrapper.find('Progress').prop('value')).toBe(40);
|
||||||
expect(wrapper.find('Td').at(2).text()).toBe('hybrid');
|
|
||||||
expect(wrapper.find('Td').at(3).text()).toBe('Auto');
|
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
wrapper
|
||||||
.find('Td')
|
.find('Td')
|
||||||
@@ -198,9 +198,7 @@ describe('<InstanceListItem/>', () => {
|
|||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
expect(wrapper.find('Td').first().prop('select').onSelect).toEqual(
|
expect(wrapper.find('Td').at(1).prop('select').onSelect).toEqual(onSelect);
|
||||||
onSelect
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should disable checkbox', async () => {
|
test('should disable checkbox', async () => {
|
||||||
@@ -218,7 +216,7 @@ describe('<InstanceListItem/>', () => {
|
|||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
expect(wrapper.find('Td').first().prop('select').disable).toEqual(true);
|
expect(wrapper.find('Td').at(1).prop('select').disable).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should display instance toggle', () => {
|
test('should display instance toggle', () => {
|
||||||
@@ -276,4 +274,32 @@ describe('<InstanceListItem/>', () => {
|
|||||||
});
|
});
|
||||||
expect(wrapper.find('ErrorDetail').length).toBe(1);
|
expect(wrapper.find('ErrorDetail').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Should render expanded row with the correct data points', async () => {
|
||||||
|
const onSelect = jest.fn();
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<InstanceListItem
|
||||||
|
instance={instance[0]}
|
||||||
|
onSelect={onSelect}
|
||||||
|
fetchInstances={() => {}}
|
||||||
|
isExpanded
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(wrapper.find('InstanceListItem').prop('isExpanded')).toBe(true);
|
||||||
|
expect(wrapper.find('Detail[label="Node Type"]').prop('value')).toBe(
|
||||||
|
'hybrid'
|
||||||
|
);
|
||||||
|
expect(wrapper.find('Detail[label="Policy Type"]').prop('value')).toBe(
|
||||||
|
'Auto'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
wrapper.find('Detail[label="Last Health Check"]').prop('value')
|
||||||
|
).toBe('9/15/2021, 6:02:07 PM');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user