* #2325 Make connectors table rows clickable and #2076 Implement connectors sorting * #2325 fix status sorting * fix ConnectorsTests * #2325 code review * #2325 add test coverage * #2325 code review fix * #2325 fix redirects for topics Co-authored-by: Roman Zabaluev <rzabaluev@provectus.com> Co-authored-by: VladSenyuta <vlad.senyuta@gmail.com>
This commit is contained in:
parent
80eb2dccfe
commit
7d5b7de992
9 changed files with 251 additions and 217 deletions
|
@ -28,14 +28,14 @@ public class KafkaConnectList {
|
||||||
|
|
||||||
@Step
|
@Step
|
||||||
public KafkaConnectList openConnector(String connectorName) {
|
public KafkaConnectList openConnector(String connectorName) {
|
||||||
$(By.linkText(connectorName)).click();
|
$x("//tbody//td[1][text()='" + connectorName + "']").shouldBe(Condition.enabled).click();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Step
|
@Step
|
||||||
public boolean isConnectorVisible(String connectorName) {
|
public boolean isConnectorVisible(String connectorName) {
|
||||||
$(By.xpath("//table")).shouldBe(Condition.visible);
|
$(By.xpath("//table")).shouldBe(Condition.visible);
|
||||||
return isVisible($x("//tbody//td[1]//a[text()='" + connectorName + "']"));
|
return isVisible($x("//tbody//td[1][text()='" + connectorName + "']"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Step
|
@Step
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { FullConnectorInfo } from 'generated-sources';
|
||||||
|
import { CellContext } from '@tanstack/react-table';
|
||||||
|
import { ClusterNameRoute } from 'lib/paths';
|
||||||
|
import useAppParams from 'lib/hooks/useAppParams';
|
||||||
|
import { Dropdown, DropdownItem } from 'components/common/Dropdown';
|
||||||
|
import { useDeleteConnector } from 'lib/hooks/api/kafkaConnect';
|
||||||
|
import { useConfirm } from 'lib/hooks/useConfirm';
|
||||||
|
|
||||||
|
const ActionsCell: React.FC<CellContext<FullConnectorInfo, unknown>> = ({
|
||||||
|
row,
|
||||||
|
}) => {
|
||||||
|
const { connect, name } = row.original;
|
||||||
|
|
||||||
|
const { clusterName } = useAppParams<ClusterNameRoute>();
|
||||||
|
|
||||||
|
const confirm = useConfirm();
|
||||||
|
const deleteMutation = useDeleteConnector({
|
||||||
|
clusterName,
|
||||||
|
connectName: connect,
|
||||||
|
connectorName: name,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
confirm(
|
||||||
|
<>
|
||||||
|
Are you sure want to remove <b>{name}</b> connector?
|
||||||
|
</>,
|
||||||
|
async () => {
|
||||||
|
await deleteMutation.mutateAsync();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Dropdown>
|
||||||
|
<DropdownItem onClick={handleDelete} danger>
|
||||||
|
Remove Connector
|
||||||
|
</DropdownItem>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ActionsCell;
|
|
@ -3,4 +3,10 @@ import styled from 'styled-components';
|
||||||
export const TagsWrapper = styled.div`
|
export const TagsWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
span {
|
||||||
|
color: rgb(76, 76, 255) !important;
|
||||||
|
&:hover {
|
||||||
|
color: rgb(23, 23, 207) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import useAppParams from 'lib/hooks/useAppParams';
|
import useAppParams from 'lib/hooks/useAppParams';
|
||||||
import { ClusterNameRoute } from 'lib/paths';
|
import { clusterConnectConnectorPath, ClusterNameRoute } from 'lib/paths';
|
||||||
import { Table } from 'components/common/table/Table/Table.styled';
|
import Table, { TagCell } from 'components/common/NewTable';
|
||||||
import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
|
import { FullConnectorInfo } from 'generated-sources';
|
||||||
import { useConnectors } from 'lib/hooks/api/kafkaConnect';
|
import { useConnectors } from 'lib/hooks/api/kafkaConnect';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
|
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
|
|
||||||
import ListItem from './ListItem';
|
import ActionsCell from './ActionsCell';
|
||||||
|
import TopicsCell from './TopicsCell';
|
||||||
|
import RunningTasksCell from './RunningTasksCell';
|
||||||
|
|
||||||
const List: React.FC = () => {
|
const List: React.FC = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const { clusterName } = useAppParams<ClusterNameRoute>();
|
const { clusterName } = useAppParams<ClusterNameRoute>();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const { data: connectors } = useConnectors(
|
const { data: connectors } = useConnectors(
|
||||||
|
@ -16,35 +20,30 @@ const List: React.FC = () => {
|
||||||
searchParams.get('q') || ''
|
searchParams.get('q') || ''
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const columns = React.useMemo<ColumnDef<FullConnectorInfo>[]>(
|
||||||
|
() => [
|
||||||
|
{ header: 'Name', accessorKey: 'name' },
|
||||||
|
{ header: 'Connect', accessorKey: 'connect' },
|
||||||
|
{ header: 'Type', accessorKey: 'type' },
|
||||||
|
{ header: 'Plugin', accessorKey: 'connectorClass' },
|
||||||
|
{ header: 'Topics', cell: TopicsCell },
|
||||||
|
{ header: 'Status', accessorKey: 'status.state', cell: TagCell },
|
||||||
|
{ header: 'Running Tasks', cell: RunningTasksCell },
|
||||||
|
{ header: '', id: 'action', cell: ActionsCell },
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table isFullwidth>
|
<Table
|
||||||
<thead>
|
data={connectors || []}
|
||||||
<tr>
|
columns={columns}
|
||||||
<TableHeaderCell title="Name" />
|
enableSorting
|
||||||
<TableHeaderCell title="Connect" />
|
onRowClick={({ original: { connect, name } }) =>
|
||||||
<TableHeaderCell title="Type" />
|
navigate(clusterConnectConnectorPath(clusterName, connect, name))
|
||||||
<TableHeaderCell title="Plugin" />
|
}
|
||||||
<TableHeaderCell title="Topics" />
|
emptyMessage="No connectors found"
|
||||||
<TableHeaderCell title="Status" />
|
|
||||||
<TableHeaderCell title="Running Tasks" />
|
|
||||||
<TableHeaderCell> </TableHeaderCell>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{(!connectors || connectors.length) === 0 && (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={10}>No connectors found</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
{connectors?.map((connector) => (
|
|
||||||
<ListItem
|
|
||||||
key={connector.name}
|
|
||||||
connector={connector}
|
|
||||||
clusterName={clusterName}
|
|
||||||
/>
|
/>
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { FullConnectorInfo } from 'generated-sources';
|
|
||||||
import { clusterConnectConnectorPath, clusterTopicPath } from 'lib/paths';
|
|
||||||
import { ClusterName } from 'redux/interfaces';
|
|
||||||
import { Link, NavLink } from 'react-router-dom';
|
|
||||||
import { Tag } from 'components/common/Tag/Tag.styled';
|
|
||||||
import { TableKeyLink } from 'components/common/table/Table/TableKeyLink.styled';
|
|
||||||
import getTagColor from 'components/common/Tag/getTagColor';
|
|
||||||
import { useDeleteConnector } from 'lib/hooks/api/kafkaConnect';
|
|
||||||
import { Dropdown, DropdownItem } from 'components/common/Dropdown';
|
|
||||||
import { useConfirm } from 'lib/hooks/useConfirm';
|
|
||||||
|
|
||||||
import * as S from './List.styled';
|
|
||||||
|
|
||||||
export interface ListItemProps {
|
|
||||||
clusterName: ClusterName;
|
|
||||||
connector: FullConnectorInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ListItem: React.FC<ListItemProps> = ({
|
|
||||||
clusterName,
|
|
||||||
connector: {
|
|
||||||
name,
|
|
||||||
connect,
|
|
||||||
type,
|
|
||||||
connectorClass,
|
|
||||||
topics,
|
|
||||||
status,
|
|
||||||
tasksCount,
|
|
||||||
failedTasksCount,
|
|
||||||
},
|
|
||||||
}) => {
|
|
||||||
const confirm = useConfirm();
|
|
||||||
const deleteMutation = useDeleteConnector({
|
|
||||||
clusterName,
|
|
||||||
connectName: connect,
|
|
||||||
connectorName: name,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleDelete = () => {
|
|
||||||
confirm(
|
|
||||||
<>
|
|
||||||
Are you sure want to remove <b>{name}</b> connector?
|
|
||||||
</>,
|
|
||||||
async () => {
|
|
||||||
await deleteMutation.mutateAsync();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const runningTasks = React.useMemo(() => {
|
|
||||||
if (!tasksCount) return null;
|
|
||||||
return tasksCount - (failedTasksCount || 0);
|
|
||||||
}, [tasksCount, failedTasksCount]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<tr>
|
|
||||||
<TableKeyLink>
|
|
||||||
<NavLink to={clusterConnectConnectorPath(clusterName, connect, name)}>
|
|
||||||
{name}
|
|
||||||
</NavLink>
|
|
||||||
</TableKeyLink>
|
|
||||||
<td>{connect}</td>
|
|
||||||
<td>{type}</td>
|
|
||||||
<td>{connectorClass}</td>
|
|
||||||
<td>
|
|
||||||
<S.TagsWrapper>
|
|
||||||
{topics?.map((t) => (
|
|
||||||
<Tag key={t} color="gray">
|
|
||||||
<Link to={clusterTopicPath(clusterName, t)}>{t}</Link>
|
|
||||||
</Tag>
|
|
||||||
))}
|
|
||||||
</S.TagsWrapper>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{status && <Tag color={getTagColor(status.state)}>{status.state}</Tag>}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{runningTasks && (
|
|
||||||
<span>
|
|
||||||
{runningTasks} of {tasksCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>
|
|
||||||
<Dropdown>
|
|
||||||
<DropdownItem onClick={handleDelete} danger>
|
|
||||||
Remove Connector
|
|
||||||
</DropdownItem>
|
|
||||||
</Dropdown>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ListItem;
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { FullConnectorInfo } from 'generated-sources';
|
||||||
|
import { CellContext } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
const RunningTasksCell: React.FC<CellContext<FullConnectorInfo, unknown>> = ({
|
||||||
|
row,
|
||||||
|
}) => {
|
||||||
|
const { tasksCount, failedTasksCount } = row.original;
|
||||||
|
|
||||||
|
if (!tasksCount) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{tasksCount - (failedTasksCount || 0)} of {tasksCount}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RunningTasksCell;
|
|
@ -0,0 +1,45 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { FullConnectorInfo } from 'generated-sources';
|
||||||
|
import { CellContext } from '@tanstack/react-table';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { Tag } from 'components/common/Tag/Tag.styled';
|
||||||
|
import { ClusterNameRoute, clusterTopicPath } from 'lib/paths';
|
||||||
|
import useAppParams from 'lib/hooks/useAppParams';
|
||||||
|
|
||||||
|
import * as S from './List.styled';
|
||||||
|
|
||||||
|
const TopicsCell: React.FC<CellContext<FullConnectorInfo, unknown>> = ({
|
||||||
|
row,
|
||||||
|
}) => {
|
||||||
|
const { topics } = row.original;
|
||||||
|
const { clusterName } = useAppParams<ClusterNameRoute>();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const navigateToTopic = (
|
||||||
|
e: React.KeyboardEvent | React.MouseEvent,
|
||||||
|
topic: string
|
||||||
|
) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
navigate(clusterTopicPath(clusterName, topic));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.TagsWrapper>
|
||||||
|
{topics?.map((t) => (
|
||||||
|
<Tag key={t} color="gray">
|
||||||
|
<span
|
||||||
|
role="link"
|
||||||
|
onClick={(e) => navigateToTopic(e, t)}
|
||||||
|
onKeyDown={(e) => navigateToTopic(e, t)}
|
||||||
|
tabIndex={0}
|
||||||
|
>
|
||||||
|
{t}
|
||||||
|
</span>
|
||||||
|
</Tag>
|
||||||
|
))}
|
||||||
|
</S.TagsWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TopicsCell;
|
|
@ -5,24 +5,28 @@ import ClusterContext, {
|
||||||
initialValue,
|
initialValue,
|
||||||
} from 'components/contexts/ClusterContext';
|
} from 'components/contexts/ClusterContext';
|
||||||
import List from 'components/Connect/List/List';
|
import List from 'components/Connect/List/List';
|
||||||
import { screen } from '@testing-library/react';
|
import { act, screen, waitFor } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import { render, WithRoute } from 'lib/testHelpers';
|
import { render, WithRoute } from 'lib/testHelpers';
|
||||||
import { clusterConnectorsPath } from 'lib/paths';
|
import { clusterConnectConnectorPath, clusterConnectorsPath } from 'lib/paths';
|
||||||
import { useConnectors } from 'lib/hooks/api/kafkaConnect';
|
import { useConnectors, useDeleteConnector } from 'lib/hooks/api/kafkaConnect';
|
||||||
|
|
||||||
|
const mockedUsedNavigate = jest.fn();
|
||||||
|
const mockDelete = jest.fn();
|
||||||
|
|
||||||
|
jest.mock('react-router-dom', () => ({
|
||||||
|
...jest.requireActual('react-router-dom'),
|
||||||
|
useNavigate: () => mockedUsedNavigate,
|
||||||
|
}));
|
||||||
|
|
||||||
jest.mock('components/Connect/List/ListItem', () => () => (
|
|
||||||
<tr>
|
|
||||||
<td>List Item</td>
|
|
||||||
</tr>
|
|
||||||
));
|
|
||||||
jest.mock('lib/hooks/api/kafkaConnect', () => ({
|
jest.mock('lib/hooks/api/kafkaConnect', () => ({
|
||||||
useConnectors: jest.fn(),
|
useConnectors: jest.fn(),
|
||||||
|
useDeleteConnector: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const clusterName = 'local';
|
const clusterName = 'local';
|
||||||
|
|
||||||
describe('Connectors List', () => {
|
const renderComponent = (contextValue: ContextProps = initialValue) =>
|
||||||
const renderComponent = (contextValue: ContextProps = initialValue) =>
|
|
||||||
render(
|
render(
|
||||||
<ClusterContext.Provider value={contextValue}>
|
<ClusterContext.Provider value={contextValue}>
|
||||||
<WithRoute path={clusterConnectorsPath()}>
|
<WithRoute path={clusterConnectorsPath()}>
|
||||||
|
@ -32,22 +36,89 @@ describe('Connectors List', () => {
|
||||||
{ initialEntries: [clusterConnectorsPath(clusterName)] }
|
{ initialEntries: [clusterConnectorsPath(clusterName)] }
|
||||||
);
|
);
|
||||||
|
|
||||||
it('renders empty connectors Table', async () => {
|
describe('Connectors List', () => {
|
||||||
(useConnectors as jest.Mock).mockImplementation(() => ({
|
describe('when the connectors are loaded', () => {
|
||||||
data: [],
|
beforeEach(() => {
|
||||||
}));
|
|
||||||
|
|
||||||
await renderComponent();
|
|
||||||
expect(screen.getByRole('table')).toBeInTheDocument();
|
|
||||||
expect(screen.getByText('No connectors found')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders connectors Table', async () => {
|
|
||||||
(useConnectors as jest.Mock).mockImplementation(() => ({
|
(useConnectors as jest.Mock).mockImplementation(() => ({
|
||||||
data: connectors,
|
data: connectors,
|
||||||
}));
|
}));
|
||||||
await renderComponent();
|
});
|
||||||
|
|
||||||
|
it('renders', async () => {
|
||||||
|
renderComponent();
|
||||||
expect(screen.getByRole('table')).toBeInTheDocument();
|
expect(screen.getByRole('table')).toBeInTheDocument();
|
||||||
expect(screen.getAllByText('List Item').length).toEqual(2);
|
expect(screen.getAllByRole('row').length).toEqual(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('opens broker when row clicked', async () => {
|
||||||
|
renderComponent();
|
||||||
|
await act(() => {
|
||||||
|
userEvent.click(
|
||||||
|
screen.getByRole('row', {
|
||||||
|
name: 'hdfs-source-connector first SOURCE FileStreamSource a b c RUNNING 2 of 2',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockedUsedNavigate).toBeCalledWith(
|
||||||
|
clusterConnectConnectorPath(
|
||||||
|
clusterName,
|
||||||
|
'first',
|
||||||
|
'hdfs-source-connector'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when table is empty', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
(useConnectors as jest.Mock).mockImplementation(() => ({
|
||||||
|
data: [],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders empty table', async () => {
|
||||||
|
renderComponent();
|
||||||
|
expect(screen.getByRole('table')).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByRole('row', { name: 'No connectors found' })
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when remove connector modal is open', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
(useConnectors as jest.Mock).mockImplementation(() => ({
|
||||||
|
data: connectors,
|
||||||
|
}));
|
||||||
|
(useDeleteConnector as jest.Mock).mockImplementation(() => ({
|
||||||
|
mutateAsync: mockDelete,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls removeConnector on confirm', async () => {
|
||||||
|
renderComponent();
|
||||||
|
const removeButton = screen.getAllByText('Remove Connector')[0];
|
||||||
|
await waitFor(() => userEvent.click(removeButton));
|
||||||
|
|
||||||
|
const submitButton = screen.getAllByRole('button', {
|
||||||
|
name: 'Confirm',
|
||||||
|
})[0];
|
||||||
|
await act(() => userEvent.click(submitButton));
|
||||||
|
expect(mockDelete).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('closes the modal when cancel button is clicked', async () => {
|
||||||
|
renderComponent();
|
||||||
|
const removeButton = screen.getAllByText('Remove Connector')[0];
|
||||||
|
await waitFor(() => userEvent.click(removeButton));
|
||||||
|
|
||||||
|
const cancelButton = screen.getAllByRole('button', {
|
||||||
|
name: 'Cancel',
|
||||||
|
})[0];
|
||||||
|
await waitFor(() => userEvent.click(cancelButton));
|
||||||
|
expect(cancelButton).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connectors } from 'lib/fixtures/kafkaConnect';
|
|
||||||
import ListItem, { ListItemProps } from 'components/Connect/List/ListItem';
|
|
||||||
import { screen } from '@testing-library/react';
|
|
||||||
import { render } from 'lib/testHelpers';
|
|
||||||
|
|
||||||
describe('Connectors ListItem', () => {
|
|
||||||
const connector = connectors[0];
|
|
||||||
const setupWrapper = (props: Partial<ListItemProps> = {}) => (
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<ListItem clusterName="local" connector={connector} {...props} />
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
);
|
|
||||||
|
|
||||||
it('renders item', () => {
|
|
||||||
render(setupWrapper());
|
|
||||||
expect(screen.getAllByRole('cell')[6]).toHaveTextContent('2 of 2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('topics tags are sorted', () => {
|
|
||||||
render(setupWrapper());
|
|
||||||
const getLink = screen.getAllByRole('link');
|
|
||||||
expect(getLink[1]).toHaveTextContent('a');
|
|
||||||
expect(getLink[2]).toHaveTextContent('b');
|
|
||||||
expect(getLink[3]).toHaveTextContent('c');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders item with failed tasks', () => {
|
|
||||||
render(
|
|
||||||
setupWrapper({
|
|
||||||
connector: {
|
|
||||||
...connector,
|
|
||||||
failedTasksCount: 1,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
expect(screen.getAllByRole('cell')[6]).toHaveTextContent('1 of 2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('does not render info about tasks if taksCount is undefined', () => {
|
|
||||||
render(
|
|
||||||
setupWrapper({
|
|
||||||
connector: {
|
|
||||||
...connector,
|
|
||||||
tasksCount: undefined,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
expect(screen.getAllByRole('cell')[6]).toHaveTextContent('');
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Add table
Reference in a new issue