UI for issues/243 and issues/244
This commit is contained in:
parent
4067880966
commit
08a3c5e225
5 changed files with 279 additions and 2 deletions
|
@ -12,6 +12,7 @@ import usePagination from 'lib/hooks/usePagination';
|
||||||
import ClusterContext from 'components/contexts/ClusterContext';
|
import ClusterContext from 'components/contexts/ClusterContext';
|
||||||
import PageLoader from 'components/common/PageLoader/PageLoader';
|
import PageLoader from 'components/common/PageLoader/PageLoader';
|
||||||
import Pagination from 'components/common/Pagination/Pagination';
|
import Pagination from 'components/common/Pagination/Pagination';
|
||||||
|
import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
|
||||||
import { GetTopicsRequest, TopicColumnsToSort } from 'generated-sources';
|
import { GetTopicsRequest, TopicColumnsToSort } from 'generated-sources';
|
||||||
import SortableColumnHeader from 'components/common/table/SortableCulumnHeader/SortableColumnHeader';
|
import SortableColumnHeader from 'components/common/table/SortableCulumnHeader/SortableColumnHeader';
|
||||||
import Search from 'components/common/Search/Search';
|
import Search from 'components/common/Search/Search';
|
||||||
|
@ -25,6 +26,8 @@ export interface TopicsListProps {
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
fetchTopicsList(props: GetTopicsRequest): void;
|
fetchTopicsList(props: GetTopicsRequest): void;
|
||||||
deleteTopic(topicName: TopicName, clusterName: ClusterName): void;
|
deleteTopic(topicName: TopicName, clusterName: ClusterName): void;
|
||||||
|
deleteTopics(topicName: TopicName, clusterNames: ClusterName[]): void;
|
||||||
|
clearTopicsMessages(topicName: TopicName, clusterNames: ClusterName[]): void;
|
||||||
clearTopicMessages(
|
clearTopicMessages(
|
||||||
topicName: TopicName,
|
topicName: TopicName,
|
||||||
clusterName: ClusterName,
|
clusterName: ClusterName,
|
||||||
|
@ -42,7 +45,9 @@ const List: React.FC<TopicsListProps> = ({
|
||||||
totalPages,
|
totalPages,
|
||||||
fetchTopicsList,
|
fetchTopicsList,
|
||||||
deleteTopic,
|
deleteTopic,
|
||||||
|
deleteTopics,
|
||||||
clearTopicMessages,
|
clearTopicMessages,
|
||||||
|
clearTopicsMessages,
|
||||||
search,
|
search,
|
||||||
orderBy,
|
orderBy,
|
||||||
setTopicsSearch,
|
setTopicsSearch,
|
||||||
|
@ -78,6 +83,45 @@ const List: React.FC<TopicsListProps> = ({
|
||||||
history.push(`${pathname}?page=1&perPage=${perPage || PER_PAGE}`);
|
history.push(`${pathname}?page=1&perPage=${perPage || PER_PAGE}`);
|
||||||
}, [showInternal]);
|
}, [showInternal]);
|
||||||
|
|
||||||
|
const [confirmationModal, setConfirmationModal] = React.useState<
|
||||||
|
'' | 'deleteTopics' | 'purgeMessages'
|
||||||
|
>('');
|
||||||
|
|
||||||
|
const closeConfirmationModal = () => {
|
||||||
|
setConfirmationModal('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const [selectedTopics, setSelectedTopics] = React.useState<Set<string>>(
|
||||||
|
new Set()
|
||||||
|
);
|
||||||
|
|
||||||
|
const clearSelectedTopics = () => {
|
||||||
|
setSelectedTopics(new Set());
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleTopicSelected = (topicName: string) => {
|
||||||
|
setSelectedTopics((prevState) => {
|
||||||
|
const newState = new Set(prevState);
|
||||||
|
if (newState.has(topicName)) {
|
||||||
|
newState.delete(topicName);
|
||||||
|
} else {
|
||||||
|
newState.add(topicName);
|
||||||
|
}
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteTopicsHandler = React.useCallback(() => {
|
||||||
|
deleteTopics(clusterName, Array.from(selectedTopics));
|
||||||
|
closeConfirmationModal();
|
||||||
|
clearSelectedTopics();
|
||||||
|
}, [clusterName, selectedTopics]);
|
||||||
|
const purgeMessagesHandler = React.useCallback(() => {
|
||||||
|
clearTopicsMessages(clusterName, Array.from(selectedTopics));
|
||||||
|
closeConfirmationModal();
|
||||||
|
clearSelectedTopics();
|
||||||
|
}, [clusterName, selectedTopics]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<Breadcrumb>{showInternal ? `All Topics` : `External Topics`}</Breadcrumb>
|
<Breadcrumb>{showInternal ? `All Topics` : `External Topics`}</Breadcrumb>
|
||||||
|
@ -119,9 +163,47 @@ const List: React.FC<TopicsListProps> = ({
|
||||||
<PageLoader />
|
<PageLoader />
|
||||||
) : (
|
) : (
|
||||||
<div className="box">
|
<div className="box">
|
||||||
|
{selectedTopics.size > 0 && (
|
||||||
|
<>
|
||||||
|
<div className="buttons">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="button is-danger"
|
||||||
|
onClick={() => {
|
||||||
|
setConfirmationModal('deleteTopics');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete selected topics
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="button is-danger"
|
||||||
|
onClick={() => {
|
||||||
|
setConfirmationModal('purgeMessages');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Purge messages of selected topics
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ConfirmationModal
|
||||||
|
isOpen={confirmationModal !== ''}
|
||||||
|
onCancel={closeConfirmationModal}
|
||||||
|
onConfirm={
|
||||||
|
confirmationModal === 'deleteTopics'
|
||||||
|
? deleteTopicsHandler
|
||||||
|
: purgeMessagesHandler
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{confirmationModal === 'deleteTopics'
|
||||||
|
? 'Are you sure want to remove selected topics?'
|
||||||
|
: 'Are you sure want to purge messages of selected topics?'}
|
||||||
|
</ConfirmationModal>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<table className="table is-fullwidth">
|
<table className="table is-fullwidth">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th> </th>
|
||||||
<SortableColumnHeader
|
<SortableColumnHeader
|
||||||
value={TopicColumnsToSort.NAME}
|
value={TopicColumnsToSort.NAME}
|
||||||
title="Topic Name"
|
title="Topic Name"
|
||||||
|
@ -154,6 +236,8 @@ const List: React.FC<TopicsListProps> = ({
|
||||||
clusterName={clusterName}
|
clusterName={clusterName}
|
||||||
key={topic.name}
|
key={topic.name}
|
||||||
topic={topic}
|
topic={topic}
|
||||||
|
selected={selectedTopics.has(topic.name)}
|
||||||
|
toggleTopicSelected={toggleTopicSelected}
|
||||||
deleteTopic={deleteTopic}
|
deleteTopic={deleteTopic}
|
||||||
clearTopicMessages={clearTopicMessages}
|
clearTopicMessages={clearTopicMessages}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,6 +14,8 @@ import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
|
||||||
|
|
||||||
export interface ListItemProps {
|
export interface ListItemProps {
|
||||||
topic: TopicWithDetailedInfo;
|
topic: TopicWithDetailedInfo;
|
||||||
|
selected: boolean;
|
||||||
|
toggleTopicSelected(topicName: TopicName): void;
|
||||||
deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void;
|
deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void;
|
||||||
clusterName: ClusterName;
|
clusterName: ClusterName;
|
||||||
clearTopicMessages(topicName: TopicName, clusterName: ClusterName): void;
|
clearTopicMessages(topicName: TopicName, clusterName: ClusterName): void;
|
||||||
|
@ -28,6 +30,8 @@ const ListItem: React.FC<ListItemProps> = ({
|
||||||
replicationFactor,
|
replicationFactor,
|
||||||
cleanUpPolicy,
|
cleanUpPolicy,
|
||||||
},
|
},
|
||||||
|
selected,
|
||||||
|
toggleTopicSelected,
|
||||||
deleteTopic,
|
deleteTopic,
|
||||||
clusterName,
|
clusterName,
|
||||||
clearTopicMessages,
|
clearTopicMessages,
|
||||||
|
@ -70,6 +74,17 @@ const ListItem: React.FC<ListItemProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
|
<td>
|
||||||
|
{!internal && (
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={selected}
|
||||||
|
onChange={() => {
|
||||||
|
toggleTopicSelected(name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
<td className="has-text-overflow-ellipsis">
|
<td className="has-text-overflow-ellipsis">
|
||||||
<NavLink
|
<NavLink
|
||||||
exact
|
exact
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount, ReactWrapper } from 'enzyme';
|
import { mount, ReactWrapper } from 'enzyme';
|
||||||
import { Router } from 'react-router-dom';
|
import { Route, Router } from 'react-router-dom';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import ClusterContext, {
|
import ClusterContext, {
|
||||||
ContextProps,
|
ContextProps,
|
||||||
} from 'components/contexts/ClusterContext';
|
} from 'components/contexts/ClusterContext';
|
||||||
|
@ -8,6 +9,13 @@ import List, { TopicsListProps } from 'components/Topics/List/List';
|
||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
import { StaticRouter } from 'react-router';
|
import { StaticRouter } from 'react-router';
|
||||||
import Search from 'components/common/Search/Search';
|
import Search from 'components/common/Search/Search';
|
||||||
|
import { externalTopicPayload } from 'redux/reducers/topics/__test__/fixtures';
|
||||||
|
import { ConfirmationModalProps } from 'components/common/ConfirmationModal/ConfirmationModal';
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'components/common/ConfirmationModal/ConfirmationModal',
|
||||||
|
() => 'mock-ConfirmationModal'
|
||||||
|
);
|
||||||
|
|
||||||
describe('List', () => {
|
describe('List', () => {
|
||||||
const setupComponent = (props: Partial<TopicsListProps> = {}) => (
|
const setupComponent = (props: Partial<TopicsListProps> = {}) => (
|
||||||
|
@ -17,6 +25,8 @@ describe('List', () => {
|
||||||
totalPages={1}
|
totalPages={1}
|
||||||
fetchTopicsList={jest.fn()}
|
fetchTopicsList={jest.fn()}
|
||||||
deleteTopic={jest.fn()}
|
deleteTopic={jest.fn()}
|
||||||
|
deleteTopics={jest.fn()}
|
||||||
|
clearTopicsMessages={jest.fn()}
|
||||||
clearTopicMessages={jest.fn()}
|
clearTopicMessages={jest.fn()}
|
||||||
search=""
|
search=""
|
||||||
orderBy={null}
|
orderBy={null}
|
||||||
|
@ -123,4 +133,130 @@ describe('List', () => {
|
||||||
expect(mockedHistory.push).toHaveBeenCalledWith('/?page=1&perPage=25');
|
expect(mockedHistory.push).toHaveBeenCalledWith('/?page=1&perPage=25');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when some list items are selected', () => {
|
||||||
|
const mockDeleteTopics = jest.fn();
|
||||||
|
const mockClearTopicsMessages = jest.fn();
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const pathname = '/ui/clusters/local/topics';
|
||||||
|
const component = mount(
|
||||||
|
<StaticRouter location={{ pathname }}>
|
||||||
|
<Route path="/ui/clusters/:clusterName">
|
||||||
|
<ClusterContext.Provider
|
||||||
|
value={{
|
||||||
|
isReadOnly: false,
|
||||||
|
hasKafkaConnectConfigured: true,
|
||||||
|
hasSchemaRegistryConfigured: true,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{setupComponent({
|
||||||
|
topics: [
|
||||||
|
externalTopicPayload,
|
||||||
|
{ ...externalTopicPayload, name: 'external.topic2' },
|
||||||
|
],
|
||||||
|
deleteTopics: mockDeleteTopics,
|
||||||
|
clearTopicsMessages: mockClearTopicsMessages,
|
||||||
|
})}
|
||||||
|
</ClusterContext.Provider>
|
||||||
|
</Route>
|
||||||
|
</StaticRouter>
|
||||||
|
);
|
||||||
|
const getCheckboxInput = (at: number) =>
|
||||||
|
component.find('ListItem').at(at).find('input[type="checkbox"]').at(0);
|
||||||
|
|
||||||
|
const getConfirmationModal = () =>
|
||||||
|
component.find('mock-ConfirmationModal').at(0);
|
||||||
|
|
||||||
|
it('renders delete/purge buttons', () => {
|
||||||
|
expect(getCheckboxInput(0).props().checked).toBeFalsy();
|
||||||
|
expect(getCheckboxInput(1).props().checked).toBeFalsy();
|
||||||
|
expect(component.find('.buttons').length).toEqual(0);
|
||||||
|
|
||||||
|
// check first item
|
||||||
|
getCheckboxInput(0).simulate('change');
|
||||||
|
expect(getCheckboxInput(0).props().checked).toBeTruthy();
|
||||||
|
expect(getCheckboxInput(1).props().checked).toBeFalsy();
|
||||||
|
expect(component.find('.buttons').length).toEqual(1);
|
||||||
|
|
||||||
|
// check second item
|
||||||
|
getCheckboxInput(1).simulate('change');
|
||||||
|
expect(getCheckboxInput(0).props().checked).toBeTruthy();
|
||||||
|
expect(getCheckboxInput(1).props().checked).toBeTruthy();
|
||||||
|
expect(component.find('.buttons').length).toEqual(1);
|
||||||
|
|
||||||
|
// uncheck second item
|
||||||
|
getCheckboxInput(1).simulate('change');
|
||||||
|
expect(getCheckboxInput(0).props().checked).toBeTruthy();
|
||||||
|
expect(getCheckboxInput(1).props().checked).toBeFalsy();
|
||||||
|
expect(component.find('.buttons').length).toEqual(1);
|
||||||
|
|
||||||
|
// uncheck first item
|
||||||
|
getCheckboxInput(0).simulate('change');
|
||||||
|
expect(getCheckboxInput(0).props().checked).toBeFalsy();
|
||||||
|
expect(getCheckboxInput(1).props().checked).toBeFalsy();
|
||||||
|
expect(component.find('.buttons').length).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const checkActionButtonClick = async (action: string) => {
|
||||||
|
const buttonIndex = action === 'deleteTopics' ? 0 : 1;
|
||||||
|
const confirmationText =
|
||||||
|
action === 'deleteTopics'
|
||||||
|
? 'Are you sure want to remove selected topics?'
|
||||||
|
: 'Are you sure want to purge messages of selected topics?';
|
||||||
|
const mockFn =
|
||||||
|
action === 'deleteTopics' ? mockDeleteTopics : mockClearTopicsMessages;
|
||||||
|
getCheckboxInput(0).simulate('change');
|
||||||
|
getCheckboxInput(1).simulate('change');
|
||||||
|
let modal = getConfirmationModal();
|
||||||
|
expect(modal.prop('isOpen')).toBeFalsy();
|
||||||
|
component
|
||||||
|
.find('.buttons')
|
||||||
|
.find('button')
|
||||||
|
.at(buttonIndex)
|
||||||
|
.simulate('click');
|
||||||
|
expect(modal.text()).toEqual(confirmationText);
|
||||||
|
modal = getConfirmationModal();
|
||||||
|
expect(modal.prop('isOpen')).toBeTruthy();
|
||||||
|
await act(async () => {
|
||||||
|
(modal.props() as ConfirmationModalProps).onConfirm();
|
||||||
|
});
|
||||||
|
component.update();
|
||||||
|
expect(getConfirmationModal().prop('isOpen')).toBeFalsy();
|
||||||
|
expect(getCheckboxInput(0).props().checked).toBeFalsy();
|
||||||
|
expect(getCheckboxInput(1).props().checked).toBeFalsy();
|
||||||
|
expect(component.find('.buttons').length).toEqual(0);
|
||||||
|
expect(mockFn).toBeCalledTimes(1);
|
||||||
|
expect(mockFn).toBeCalledWith('local', [
|
||||||
|
externalTopicPayload.name,
|
||||||
|
'external.topic2',
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
it('triggers the deleteTopics when clicked on the delete button', async () => {
|
||||||
|
await checkActionButtonClick('deleteTopics');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers the clearTopicsMessages when clicked on the clear button', async () => {
|
||||||
|
await checkActionButtonClick('clearTopicsMessages');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('closes ConfirmationModal when clicked on the cancel button', async () => {
|
||||||
|
getCheckboxInput(0).simulate('change');
|
||||||
|
getCheckboxInput(1).simulate('change');
|
||||||
|
let modal = getConfirmationModal();
|
||||||
|
expect(modal.prop('isOpen')).toBeFalsy();
|
||||||
|
component.find('.buttons').find('button').at(0).simulate('click');
|
||||||
|
modal = getConfirmationModal();
|
||||||
|
expect(modal.prop('isOpen')).toBeTruthy();
|
||||||
|
await act(async () => {
|
||||||
|
(modal.props() as ConfirmationModalProps).onCancel();
|
||||||
|
});
|
||||||
|
component.update();
|
||||||
|
expect(getConfirmationModal().prop('isOpen')).toBeFalsy();
|
||||||
|
expect(getCheckboxInput(0).props().checked).toBeTruthy();
|
||||||
|
expect(getCheckboxInput(1).props().checked).toBeTruthy();
|
||||||
|
expect(component.find('.buttons').length).toEqual(1);
|
||||||
|
expect(mockDeleteTopics).toBeCalledTimes(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@ import ListItem, { ListItemProps } from 'components/Topics/List/ListItem';
|
||||||
const mockDelete = jest.fn();
|
const mockDelete = jest.fn();
|
||||||
const clusterName = 'local';
|
const clusterName = 'local';
|
||||||
const mockDeleteMessages = jest.fn();
|
const mockDeleteMessages = jest.fn();
|
||||||
|
const mockToggleTopicSelected = jest.fn();
|
||||||
|
|
||||||
jest.mock(
|
jest.mock(
|
||||||
'components/common/ConfirmationModal/ConfirmationModal',
|
'components/common/ConfirmationModal/ConfirmationModal',
|
||||||
|
@ -23,6 +24,8 @@ describe('ListItem', () => {
|
||||||
deleteTopic={mockDelete}
|
deleteTopic={mockDelete}
|
||||||
clusterName={clusterName}
|
clusterName={clusterName}
|
||||||
clearTopicMessages={mockDeleteMessages}
|
clearTopicMessages={mockDeleteMessages}
|
||||||
|
selected={false}
|
||||||
|
toggleTopicSelected={mockToggleTopicSelected}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -73,6 +76,18 @@ describe('ListItem', () => {
|
||||||
expect(wrapper.find('.tag.is-light').text()).toEqual('Internal');
|
expect(wrapper.find('.tag.is-light').text()).toEqual('Internal');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders without checkbox for internal topic', () => {
|
||||||
|
const wrapper = mount(
|
||||||
|
<StaticRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>{setupComponent()}</tbody>
|
||||||
|
</table>
|
||||||
|
</StaticRouter>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(wrapper.find('td').at(0).html()).toEqual('<td></td>');
|
||||||
|
});
|
||||||
|
|
||||||
it('renders correct tags for external topic', () => {
|
it('renders correct tags for external topic', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<StaticRouter>
|
<StaticRouter>
|
||||||
|
@ -85,6 +100,28 @@ describe('ListItem', () => {
|
||||||
expect(wrapper.find('.tag.is-primary').text()).toEqual('External');
|
expect(wrapper.find('.tag.is-primary').text()).toEqual('External');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders with checkbox for external topic', () => {
|
||||||
|
const wrapper = mount(
|
||||||
|
<StaticRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>{setupComponent({ topic: externalTopicPayload })}</tbody>
|
||||||
|
</table>
|
||||||
|
</StaticRouter>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(wrapper.find('td').at(0).html()).toEqual(
|
||||||
|
'<td><input type="checkbox"></td>'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers the toggleTopicSelected when clicked on the checkbox input', () => {
|
||||||
|
const wrapper = shallow(setupComponent({ topic: externalTopicPayload }));
|
||||||
|
expect(wrapper.exists('input')).toBeTruthy();
|
||||||
|
wrapper.find('input[type="checkbox"]').at(0).simulate('change');
|
||||||
|
expect(mockToggleTopicSelected).toBeCalledTimes(1);
|
||||||
|
expect(mockToggleTopicSelected).toBeCalledWith(externalTopicPayload.name);
|
||||||
|
});
|
||||||
|
|
||||||
it('renders correct out of sync replicas number', () => {
|
it('renders correct out of sync replicas number', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<StaticRouter>
|
<StaticRouter>
|
||||||
|
@ -98,6 +135,6 @@ describe('ListItem', () => {
|
||||||
</StaticRouter>
|
</StaticRouter>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper.find('td').at(2).text()).toEqual('0');
|
expect(wrapper.find('td').at(3).text()).toEqual('0');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,7 +27,9 @@ exports[`List when it does not have readonly flag matches the snapshot 1`] = `
|
||||||
<List
|
<List
|
||||||
areTopicsFetching={false}
|
areTopicsFetching={false}
|
||||||
clearTopicMessages={[MockFunction]}
|
clearTopicMessages={[MockFunction]}
|
||||||
|
clearTopicsMessages={[MockFunction]}
|
||||||
deleteTopic={[MockFunction]}
|
deleteTopic={[MockFunction]}
|
||||||
|
deleteTopics={[MockFunction]}
|
||||||
fetchTopicsList={
|
fetchTopicsList={
|
||||||
[MockFunction] {
|
[MockFunction] {
|
||||||
"calls": Array [
|
"calls": Array [
|
||||||
|
@ -165,6 +167,9 @@ exports[`List when it does not have readonly flag matches the snapshot 1`] = `
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>
|
||||||
|
|
||||||
|
</th>
|
||||||
<ListHeaderCell
|
<ListHeaderCell
|
||||||
orderBy={null}
|
orderBy={null}
|
||||||
setOrderBy={[MockFunction]}
|
setOrderBy={[MockFunction]}
|
||||||
|
|
Loading…
Add table
Reference in a new issue