From 5b86f7cc4b99b395bea74766fd1193630970d6a8 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Mon, 16 May 2022 18:54:34 +0400 Subject: [PATCH 01/61] remove withRouter HOC from FiltersContainer --- .../Details/Messages/Filters/Filters.tsx | 16 ++++++----- .../Messages/Filters/FiltersContainer.ts | 27 +++---------------- .../Filters/__tests__/Filters.spec.tsx | 3 --- 3 files changed, 12 insertions(+), 34 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx index ad3aec6b815..3a59d15be24 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx @@ -12,7 +12,7 @@ import { } from 'generated-sources'; import React, { useContext } from 'react'; import { omitBy } from 'lodash'; -import { useHistory, useLocation } from 'react-router-dom'; +import { useHistory, useLocation, useParams } from 'react-router-dom'; import DatePicker from 'react-datepicker'; import MultiSelect from 'components/common/MultiSelect/MultiSelect.styled'; import { Option } from 'react-multi-select-component/dist/lib/interfaces'; @@ -29,6 +29,8 @@ import FilterModal, { import { SeekDirectionOptions } from 'components/Topics/Topic/Details/Messages/Messages'; import TopicMessagesContext from 'components/contexts/TopicMessagesContext'; import useModal from 'lib/hooks/useModal'; +import { getPartitionsByTopicName } from 'redux/reducers/topics/selectors'; +import { useAppSelector } from 'lib/hooks/redux'; import * as S from './Filters.styled'; import { @@ -41,10 +43,7 @@ import { type Query = Record; export interface FiltersProps { - clusterName: ClusterName; - topicName: TopicName; phaseMessage?: string; - partitions: Partition[]; meta: TopicMessageConsuming; isFetching: boolean; addMessage(content: { message: TopicMessage; prepend: boolean }): void; @@ -73,9 +72,6 @@ export const SeekTypeOptions = [ ]; const Filters: React.FC = ({ - clusterName, - topicName, - partitions, phaseMessage, meta: { elapsedMs, bytesConsumed, messagesConsumed }, isFetching, @@ -85,9 +81,15 @@ const Filters: React.FC = ({ updateMeta, setIsFetching, }) => { + const { clusterName, topicName } = + useParams<{ clusterName: ClusterName; topicName: TopicName }>(); const location = useLocation(); const history = useHistory(); + const partitions = useAppSelector((state) => + getPartitionsByTopicName(state, topicName) + ); + const { searchParams, seekDirection, isLive, changeSeekDirection } = useContext(TopicMessagesContext); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/FiltersContainer.ts b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/FiltersContainer.ts index 24c891111ae..144672ee603 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/FiltersContainer.ts +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/FiltersContainer.ts @@ -1,6 +1,5 @@ import { connect } from 'react-redux'; -import { ClusterName, RootState, TopicName } from 'redux/interfaces'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { RootState } from 'redux/interfaces'; import { addTopicMessage, resetTopicMessages, @@ -13,29 +12,11 @@ import { getTopicMessgesPhase, getIsTopicMessagesFetching, } from 'redux/reducers/topicMessages/selectors'; -import { getPartitionsByTopicName } from 'redux/reducers/topics/selectors'; import Filters from './Filters'; -interface RouteProps { - clusterName: ClusterName; - topicName: TopicName; -} - -type OwnProps = RouteComponentProps; - -const mapStateToProps = ( - state: RootState, - { - match: { - params: { topicName, clusterName }, - }, - }: OwnProps -) => ({ - clusterName, - topicName, +const mapStateToProps = (state: RootState) => ({ phaseMessage: getTopicMessgesPhase(state), - partitions: getPartitionsByTopicName(state, topicName), meta: getTopicMessgesMeta(state), isFetching: getIsTopicMessagesFetching(state), }); @@ -48,6 +29,4 @@ const mapDispatchToProps = { setIsFetching: setTopicMessagesFetchingStatus, }; -export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(Filters) -); +export default connect(mapStateToProps, mapDispatchToProps)(Filters); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/Filters.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/Filters.spec.tsx index 79cddac6d7e..7448b8c7789 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/Filters.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/Filters.spec.tsx @@ -26,9 +26,6 @@ const renderComponent = ( render( Date: Tue, 17 May 2022 14:20:57 +0400 Subject: [PATCH 02/61] remove withRouter HOC from Topics DetailsContainer --- .../Topics/Topic/Details/Details.tsx | 31 +++++++--- .../Topics/Topic/Details/DetailsContainer.ts | 33 ++-------- .../Topic/Details/__test__/Details.spec.tsx | 61 ++++++++++++------- 3 files changed, 66 insertions(+), 59 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx index 60307610fdd..467e4d9f91b 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx @@ -1,7 +1,13 @@ import React from 'react'; import { ClusterName, TopicName } from 'redux/interfaces'; import { Topic, TopicDetails } from 'generated-sources'; -import { NavLink, Switch, Route, useHistory } from 'react-router-dom'; +import { + NavLink, + Switch, + Route, + useHistory, + useParams, +} from 'react-router-dom'; import { clusterTopicSettingsPath, clusterTopicPath, @@ -22,6 +28,11 @@ import DropdownItem from 'components/common/Dropdown/DropdownItem'; import styled from 'styled-components'; import Navbar from 'components/common/Navigation/Navbar.styled'; import * as S from 'components/Topics/Topic/Details/Details.styled'; +import { useAppSelector } from 'lib/hooks/redux'; +import { + getIsTopicDeletePolicy, + getIsTopicInternal, +} from 'redux/reducers/topics/selectors'; import OverviewContainer from './Overview/OverviewContainer'; import TopicConsumerGroupsContainer from './ConsumerGroups/TopicConsumerGroupsContainer'; @@ -29,9 +40,6 @@ import SettingsContainer from './Settings/SettingsContainer'; import Messages from './Messages/Messages'; interface Props extends Topic, TopicDetails { - clusterName: ClusterName; - topicName: TopicName; - isInternal: boolean; isDeleted: boolean; isDeletePolicy: boolean; deleteTopic: (payload: { @@ -56,15 +64,22 @@ const HeaderControlsWrapper = styled.div` `; const Details: React.FC = ({ - clusterName, - topicName, - isInternal, isDeleted, - isDeletePolicy, deleteTopic, recreateTopic, clearTopicMessages, }) => { + const { clusterName, topicName } = + useParams<{ clusterName: ClusterName; topicName: TopicName }>(); + + const isInternal = useAppSelector((state) => + getIsTopicInternal(state, topicName) + ); + + const isDeletePolicy = useAppSelector((state) => + getIsTopicDeletePolicy(state, topicName) + ); + const history = useHistory(); const dispatch = useDispatch(); const { isReadOnly, isTopicDeletionAllowed } = diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/DetailsContainer.ts b/kafka-ui-react-app/src/components/Topics/Topic/Details/DetailsContainer.ts index e3fbd01f476..325d4d84e2b 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/DetailsContainer.ts +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/DetailsContainer.ts @@ -1,36 +1,13 @@ import { connect } from 'react-redux'; -import { ClusterName, RootState, TopicName } from 'redux/interfaces'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { RootState } from 'redux/interfaces'; import { deleteTopic, recreateTopic } from 'redux/reducers/topics/topicsSlice'; import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice'; -import { - getIsTopicDeleted, - getIsTopicDeletePolicy, - getIsTopicInternal, -} from 'redux/reducers/topics/selectors'; +import { getIsTopicDeleted } from 'redux/reducers/topics/selectors'; import Details from './Details'; -interface RouteProps { - clusterName: ClusterName; - topicName: TopicName; -} - -type OwnProps = RouteComponentProps; - -const mapStateToProps = ( - state: RootState, - { - match: { - params: { topicName, clusterName }, - }, - }: OwnProps -) => ({ - clusterName, - topicName, - isInternal: getIsTopicInternal(state, topicName), +const mapStateToProps = (state: RootState) => ({ isDeleted: getIsTopicDeleted(state), - isDeletePolicy: getIsTopicDeletePolicy(state, topicName), }); const mapDispatchToProps = { @@ -39,6 +16,4 @@ const mapDispatchToProps = { clearTopicMessages, }; -export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(Details) -); +export default connect(mapStateToProps, mapDispatchToProps)(Details); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx index 267fdd6c377..09ee9a6afaf 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx @@ -10,14 +10,14 @@ import { clusterTopicPath, clusterTopicsPath, } from 'lib/paths'; -import { Router } from 'react-router-dom'; +import { Route, Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; +import { CleanUpPolicy, SortOrder, Topic } from 'generated-sources'; describe('Details', () => { const mockDelete = jest.fn(); const mockClusterName = 'local'; const mockClearTopicMessages = jest.fn(); - const mockInternalTopicPayload = internalTopicPayload.internal; const mockRecreateTopic = jest.fn(); const defaultPathname = clusterTopicPath( mockClusterName, @@ -28,6 +28,25 @@ describe('Details', () => { }); jest.spyOn(mockHistory, 'push'); + const topic: Topic = { + ...internalTopicPayload, + cleanUpPolicy: CleanUpPolicy.DELETE, + internal: false, + }; + + const mockTopicsState = { + byName: { + [topic.name]: topic, + }, + allNames: [topic.name], + messages: [], + totalPages: 1, + search: '', + orderBy: null, + sortOrder: SortOrder.ASC, + consumerGroups: [], + }; + const setupComponent = ( pathname = defaultPathname, history = mockHistory, @@ -43,21 +62,24 @@ describe('Details', () => { }} > -
+ +
+ , - { pathname } + { + pathname, + preloadedState: { + topics: mockTopicsState, + }, + } ); describe('when it has readonly flag', () => { @@ -72,15 +94,11 @@ describe('Details', () => { }} >
); @@ -166,12 +184,11 @@ describe('Details', () => { it('shows a confirmation popup on deleting topic messages', () => { setupComponent(); - const { getByText } = screen; - const clearMessagesButton = getByText(/Clear messages/i); + const clearMessagesButton = screen.getAllByText(/Clear messages/i)[0]; userEvent.click(clearMessagesButton); expect( - getByText(/Are you sure want to clear topic messages?/i) + screen.getByText(/Are you sure want to clear topic messages?/i) ).toBeInTheDocument(); }); From a5b5aab1e09adf8de677f06947f28d386fd4cea0 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 17 May 2022 17:07:27 +0400 Subject: [PATCH 03/61] remove withRouter HOC from Topics TopicsConsumerGroupsContainer --- .../ConsumerGroups/TopicConsumerGroups.tsx | 16 +++--- .../TopicConsumerGroupsContainer.ts | 34 +++---------- .../__test__/TopicConsumerGroups.spec.tsx | 51 +++++++++++++++---- .../reducers/topics/__test__/fixtures.ts | 27 +++++++++- 4 files changed, 84 insertions(+), 44 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx index 518a18ced19..9293160d28e 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx @@ -6,13 +6,13 @@ import { Table } from 'components/common/table/Table/Table.styled'; import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell'; import { Tag } from 'components/common/Tag/Tag.styled'; import { TableKeyLink } from 'components/common/table/Table/TableKeyLink.styled'; -import { Link } from 'react-router-dom'; +import { Link, useParams } from 'react-router-dom'; import PageLoader from 'components/common/PageLoader/PageLoader'; import getTagColor from 'components/common/Tag/getTagColor'; +import { useAppSelector } from 'lib/hooks/redux'; +import { getTopicConsumerGroups } from 'redux/reducers/topics/selectors'; export interface Props extends Topic, TopicDetails { - clusterName: ClusterName; - topicName: TopicName; consumerGroups: ConsumerGroup[]; isFetched: boolean; fetchTopicConsumerGroups(payload: { @@ -22,12 +22,16 @@ export interface Props extends Topic, TopicDetails { } const TopicConsumerGroups: React.FC = ({ - consumerGroups, fetchTopicConsumerGroups, - clusterName, - topicName, isFetched, }) => { + const { clusterName, topicName } = + useParams<{ clusterName: ClusterName; topicName: TopicName }>(); + + const consumerGroups = useAppSelector((state) => + getTopicConsumerGroups(state, topicName) + ); + React.useEffect(() => { fetchTopicConsumerGroups({ clusterName, topicName }); }, [clusterName, fetchTopicConsumerGroups, topicName]); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroupsContainer.ts b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroupsContainer.ts index 17fad09a454..e60e0293df9 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroupsContainer.ts +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroupsContainer.ts @@ -1,31 +1,10 @@ import { connect } from 'react-redux'; -import { RootState, TopicName, ClusterName } from 'redux/interfaces'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { RootState } from 'redux/interfaces'; import { fetchTopicConsumerGroups } from 'redux/reducers/topics/topicsSlice'; import TopicConsumerGroups from 'components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups'; -import { - getTopicConsumerGroups, - getTopicsConsumerGroupsFetched, -} from 'redux/reducers/topics/selectors'; +import { getTopicsConsumerGroupsFetched } from 'redux/reducers/topics/selectors'; -interface RouteProps { - clusterName: ClusterName; - topicName: TopicName; -} - -type OwnProps = RouteComponentProps; - -const mapStateToProps = ( - state: RootState, - { - match: { - params: { topicName, clusterName }, - }, - }: OwnProps -) => ({ - consumerGroups: getTopicConsumerGroups(state, topicName), - topicName, - clusterName, +const mapStateToProps = (state: RootState) => ({ isFetched: getTopicsConsumerGroupsFetched(state), }); @@ -33,6 +12,7 @@ const mapDispatchToProps = { fetchTopicConsumerGroups, }; -export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(TopicConsumerGroups) -); +export default connect( + mapStateToProps, + mapDispatchToProps +)(TopicConsumerGroups); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx index a4675785db1..8051f6f5e68 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx @@ -5,6 +5,9 @@ import ConsumerGroups, { Props, } from 'components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups'; import { ConsumerGroupState } from 'generated-sources'; +import { Router, Route } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; +import { getTopicStateFixtures } from 'redux/reducers/topics/__test__/fixtures'; describe('TopicConsumerGroups', () => { const mockClusterName = 'localClusterName'; @@ -32,18 +35,46 @@ describe('TopicConsumerGroups', () => { }, ]; - const setUpComponent = (props: Partial = {}) => { - const { name, topicName, consumerGroups, isFetched } = props; + const topic = { + name: mockTopicName, + }; + + const topicsState = getTopicStateFixtures([topic], mockWithConsumerGroup); + + const defaultPathName = + '/ui/clusters/:clusterName/topics/:topicName/consumer-groups'; + + const defaultHistory = createMemoryHistory({ + initialEntries: [ + defaultPathName + .replace(':clusterName', mockClusterName) + .replace(':topicName', mockTopicName), + ], + }); + + const setUpComponent = ( + props: Partial = {}, + history = defaultHistory + ) => { + const { name, consumerGroups, isFetched } = props; return render( - + + + + + , + { + pathname: defaultPathName, + preloadedState: { + topics: topicsState, + }, + } ); }; diff --git a/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts b/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts index cec6cf350d9..a52ec9a7120 100644 --- a/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts +++ b/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts @@ -1,4 +1,5 @@ -import { Topic } from 'generated-sources'; +import { SortOrder, Topic, ConsumerGroup } from 'generated-sources'; +import { TopicsState } from 'redux/interfaces'; export const internalTopicPayload = { name: '__internal.topic', @@ -46,3 +47,27 @@ export const topicsPayload: Topic[] = [ internalTopicPayload, externalTopicPayload, ]; + +export const getTopicStateFixtures = ( + topics: Topic[], + consumerGroups?: ConsumerGroup[] +): TopicsState => { + const byName = topics.reduce((acc: { [i in string]: Topic }, curr) => { + const obj = { ...acc }; + obj[curr.name] = curr; + return obj; + }, {} as { [i in string]: Topic }); + + const allNames = Object.keys(byName); + + return { + byName, + allNames, + totalPages: 1, + search: '', + orderBy: null, + sortOrder: SortOrder.ASC, + consumerGroups: + consumerGroups && consumerGroups.length ? consumerGroups : [], + }; +}; From 43a7c162bfdab66b34f09131191408856f7b5fb9 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 17 May 2022 17:33:10 +0400 Subject: [PATCH 04/61] withRouter HOC from Topics TopicsConsumerGroupsContainer --- .../ConsumerGroups/TopicConsumerGroups.tsx | 3 +-- .../__test__/TopicConsumerGroups.spec.tsx | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx index 9293160d28e..c57cb2d84b7 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Topic, TopicDetails, ConsumerGroup } from 'generated-sources'; +import { Topic, TopicDetails } from 'generated-sources'; import { ClusterName, TopicName } from 'redux/interfaces'; import { clusterConsumerGroupsPath } from 'lib/paths'; import { Table } from 'components/common/table/Table/Table.styled'; @@ -13,7 +13,6 @@ import { useAppSelector } from 'lib/hooks/redux'; import { getTopicConsumerGroups } from 'redux/reducers/topics/selectors'; export interface Props extends Topic, TopicDetails { - consumerGroups: ConsumerGroup[]; isFetched: boolean; fetchTopicConsumerGroups(payload: { clusterName: ClusterName; diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx index 8051f6f5e68..e27467dfb8d 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx @@ -8,6 +8,7 @@ import { ConsumerGroupState } from 'generated-sources'; import { Router, Route } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { getTopicStateFixtures } from 'redux/reducers/topics/__test__/fixtures'; +import { TopicWithDetailedInfo } from 'redux/interfaces'; describe('TopicConsumerGroups', () => { const mockClusterName = 'localClusterName'; @@ -35,12 +36,10 @@ describe('TopicConsumerGroups', () => { }, ]; - const topic = { + const mockTopic: TopicWithDetailedInfo = { name: mockTopicName, }; - const topicsState = getTopicStateFixtures([topic], mockWithConsumerGroup); - const defaultPathName = '/ui/clusters/:clusterName/topics/:topicName/consumer-groups'; @@ -54,15 +53,16 @@ describe('TopicConsumerGroups', () => { const setUpComponent = ( props: Partial = {}, + topic = mockTopic, history = defaultHistory ) => { - const { name, consumerGroups, isFetched } = props; + const { name, isFetched } = props; + const topicsState = getTopicStateFixtures([topic]); return render( { }); it('render ConsumerGroups in Topic', () => { - setUpComponent({ - consumerGroups: mockWithConsumerGroup, - isFetched: true, - }); + setUpComponent( + { + isFetched: true, + }, + { ...mockTopic, consumerGroups: mockWithConsumerGroup } + ); expect(screen.getAllByRole('rowgroup')).toHaveLength(2); + expect( + screen.getByText(mockWithConsumerGroup[0].groupId) + ).toBeInTheDocument(); + expect( + screen.getByText(mockWithConsumerGroup[1].groupId) + ).toBeInTheDocument(); }); }); From c59dcc594fb1347fc9a2acbead7ef46ad7112fa8 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 17 May 2022 17:40:59 +0400 Subject: [PATCH 05/61] minor code refactor in the Details spec --- .../Topic/Details/__test__/Details.spec.tsx | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx index 09ee9a6afaf..c2432c5c5cd 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx @@ -3,7 +3,10 @@ import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import ClusterContext from 'components/contexts/ClusterContext'; import Details from 'components/Topics/Topic/Details/Details'; -import { internalTopicPayload } from 'redux/reducers/topics/__test__/fixtures'; +import { + getTopicStateFixtures, + internalTopicPayload, +} from 'redux/reducers/topics/__test__/fixtures'; import { render } from 'lib/testHelpers'; import { clusterTopicEditPath, @@ -12,7 +15,7 @@ import { } from 'lib/paths'; import { Route, Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; -import { CleanUpPolicy, SortOrder, Topic } from 'generated-sources'; +import { CleanUpPolicy, Topic } from 'generated-sources'; describe('Details', () => { const mockDelete = jest.fn(); @@ -34,18 +37,7 @@ describe('Details', () => { internal: false, }; - const mockTopicsState = { - byName: { - [topic.name]: topic, - }, - allNames: [topic.name], - messages: [], - totalPages: 1, - search: '', - orderBy: null, - sortOrder: SortOrder.ASC, - consumerGroups: [], - }; + const mockTopicsState = getTopicStateFixtures([topic]); const setupComponent = ( pathname = defaultPathname, From cd106350708879df1a9bdc61242853d6ceef40dd Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 17 May 2022 17:51:40 +0400 Subject: [PATCH 06/61] Routes code modifications to refactor strings representation to functions --- .../__test__/TopicConsumerGroups.spec.tsx | 11 ++++++----- .../src/components/Topics/Topic/Details/Details.tsx | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx index e27467dfb8d..a9cb8d28866 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx @@ -9,6 +9,7 @@ import { Router, Route } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { getTopicStateFixtures } from 'redux/reducers/topics/__test__/fixtures'; import { TopicWithDetailedInfo } from 'redux/interfaces'; +import { clusterTopicConsumerGroupsPath } from 'lib/paths'; describe('TopicConsumerGroups', () => { const mockClusterName = 'localClusterName'; @@ -40,14 +41,14 @@ describe('TopicConsumerGroups', () => { name: mockTopicName, }; - const defaultPathName = - '/ui/clusters/:clusterName/topics/:topicName/consumer-groups'; + const defaultPathName = clusterTopicConsumerGroupsPath( + ':clusterName', + ':topicName' + ); const defaultHistory = createMemoryHistory({ initialEntries: [ - defaultPathName - .replace(':clusterName', mockClusterName) - .replace(':topicName', mockTopicName), + clusterTopicConsumerGroupsPath(mockClusterName, mockTopicName), ], }); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx index 467e4d9f91b..ed45adc39b8 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx @@ -223,22 +223,22 @@ const Details: React.FC = ({ From a2f0485a339abcf8f6f164905421e8252256a98b Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 17 May 2022 18:25:14 +0400 Subject: [PATCH 07/61] Settings and TopicsConsumer removal of HOC with Router --- .../__test__/TopicConsumerGroups.spec.tsx | 23 +++-- .../Topic/Details/Settings/Settings.tsx | 24 +++-- .../Details/Settings/SettingsContainer.ts | 31 +------ .../Settings/__test__/Settings.spec.tsx | 90 +++++++++++-------- .../reducers/topics/__test__/fixtures.ts | 4 +- 5 files changed, 81 insertions(+), 91 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx index a9cb8d28866..8f194c149e5 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx @@ -4,7 +4,7 @@ import { screen } from '@testing-library/react'; import ConsumerGroups, { Props, } from 'components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups'; -import { ConsumerGroupState } from 'generated-sources'; +import { ConsumerGroup, ConsumerGroupState } from 'generated-sources'; import { Router, Route } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { getTopicStateFixtures } from 'redux/reducers/topics/__test__/fixtures'; @@ -37,10 +37,6 @@ describe('TopicConsumerGroups', () => { }, ]; - const mockTopic: TopicWithDetailedInfo = { - name: mockTopicName, - }; - const defaultPathName = clusterTopicConsumerGroupsPath( ':clusterName', ':topicName' @@ -54,19 +50,22 @@ describe('TopicConsumerGroups', () => { const setUpComponent = ( props: Partial = {}, - topic = mockTopic, - history = defaultHistory + consumerGroups?: ConsumerGroup[] ) => { - const { name, isFetched } = props; + const topic: TopicWithDetailedInfo = { + name: mockTopicName, + consumerGroups, + }; const topicsState = getTopicStateFixtures([topic]); return render( - + , @@ -98,7 +97,7 @@ describe('TopicConsumerGroups', () => { { isFetched: true, }, - { ...mockTopic, consumerGroups: mockWithConsumerGroup } + mockWithConsumerGroup ); expect(screen.getAllByRole('rowgroup')).toHaveLength(2); expect( diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/Settings.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/Settings.tsx index 3521e37bf44..90c08f84ded 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/Settings.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/Settings.tsx @@ -1,16 +1,15 @@ +import React from 'react'; import PageLoader from 'components/common/PageLoader/PageLoader'; import { Table } from 'components/common/table/Table/Table.styled'; import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell'; -import { TopicConfig } from 'generated-sources'; -import React from 'react'; import { ClusterName, TopicName } from 'redux/interfaces'; +import { useParams } from 'react-router-dom'; +import { useAppSelector } from 'lib/hooks/redux'; +import { getTopicConfig } from 'redux/reducers/topics/selectors'; import ConfigListItem from './ConfigListItem'; -interface Props { - clusterName: ClusterName; - topicName: TopicName; - config?: TopicConfig[]; +export interface Props { isFetched: boolean; fetchTopicConfig: (payload: { clusterName: ClusterName; @@ -18,13 +17,12 @@ interface Props { }) => void; } -const Settings: React.FC = ({ - clusterName, - topicName, - isFetched, - fetchTopicConfig, - config, -}) => { +const Settings: React.FC = ({ isFetched, fetchTopicConfig }) => { + const { clusterName, topicName } = + useParams<{ clusterName: ClusterName; topicName: TopicName }>(); + + const config = useAppSelector((state) => getTopicConfig(state, topicName)); + React.useEffect(() => { fetchTopicConfig({ clusterName, topicName }); }, [fetchTopicConfig, clusterName, topicName]); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/SettingsContainer.ts b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/SettingsContainer.ts index b38031a443c..c24895c080c 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/SettingsContainer.ts +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/SettingsContainer.ts @@ -1,32 +1,11 @@ import { connect } from 'react-redux'; -import { RootState, ClusterName, TopicName } from 'redux/interfaces'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { RootState } from 'redux/interfaces'; import { fetchTopicConfig } from 'redux/reducers/topics/topicsSlice'; -import { - getTopicConfig, - getTopicConfigFetched, -} from 'redux/reducers/topics/selectors'; +import { getTopicConfigFetched } from 'redux/reducers/topics/selectors'; import Settings from './Settings'; -interface RouteProps { - clusterName: ClusterName; - topicName: TopicName; -} - -type OwnProps = RouteComponentProps; - -const mapStateToProps = ( - state: RootState, - { - match: { - params: { topicName, clusterName }, - }, - }: OwnProps -) => ({ - clusterName, - topicName, - config: getTopicConfig(state, topicName), +const mapStateToProps = (state: RootState) => ({ isFetched: getTopicConfigFetched(state), }); @@ -34,6 +13,4 @@ const mapDispatchToProps = { fetchTopicConfig, }; -export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(Settings) -); +export default connect(mapStateToProps, mapDispatchToProps)(Settings); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx index 23a39b50c65..bf9349a0ccc 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx @@ -1,14 +1,31 @@ import React from 'react'; import { render } from 'lib/testHelpers'; import { screen } from '@testing-library/react'; -import Settings from 'components/Topics/Topic/Details/Settings/Settings'; +import Settings, { + Props, +} from 'components/Topics/Topic/Details/Settings/Settings'; import { TopicConfig } from 'generated-sources'; +import { clusterTopicSettingsPath } from 'lib/paths'; +import { createMemoryHistory } from 'history'; +import { Route, Router } from 'react-router-dom'; +import { getTopicStateFixtures } from 'redux/reducers/topics/__test__/fixtures'; describe('Settings', () => { + const mockClusterName = 'Cluster_Name'; + const mockTopicName = 'Topic_Name'; + + const defaultPathName = clusterTopicSettingsPath( + ':clusterName', + ':topicName' + ); + + const history = createMemoryHistory({ + initialEntries: [clusterTopicSettingsPath(mockClusterName, mockTopicName)], + }); + let expectedResult: number; const mockFn = jest.fn(); - const mockClusterName = 'Cluster Name'; - const mockTopicName = 'Topic Name'; + const mockConfig: TopicConfig[] = [ { name: 'first', @@ -20,43 +37,50 @@ describe('Settings', () => { }, ]; - it('should check it returns null if no config is passed', () => { - render( - + const setUpComponent = ( + props: Partial = {}, + config?: TopicConfig[] + ) => { + const topic = { + name: mockTopicName, + config, + }; + const topics = getTopicStateFixtures([topic]); + + return render( + + + + + , + { + pathname: defaultPathName, + preloadedState: { + topics, + }, + } ); + }; + + afterEach(() => { + mockFn.mockClear(); + }); + + it('should check it returns null if no config is passed', () => { + setUpComponent(); expect(screen.queryByRole('table')).not.toBeInTheDocument(); }); it('should show Page loader when it is in fetching state and config is given', () => { - render( - - ); + setUpComponent({ isFetched: false }, mockConfig); expect(screen.queryByRole('table')).not.toBeInTheDocument(); expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); it('should check and return null if it is not fetched and config is not given', () => { - render( - - ); + setUpComponent({ isFetched: false }); expect(screen.queryByRole('table')).not.toBeInTheDocument(); }); @@ -64,15 +88,7 @@ describe('Settings', () => { describe('Settings Component with Data', () => { beforeEach(() => { expectedResult = mockConfig.length + 1; // include the header table row as well - render( - - ); + setUpComponent({ isFetched: true }, mockConfig); }); it('should view the correct number of table row with header included elements after config fetching', () => { diff --git a/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts b/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts index a52ec9a7120..d7296d4b396 100644 --- a/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts +++ b/kafka-ui-react-app/src/redux/reducers/topics/__test__/fixtures.ts @@ -1,5 +1,5 @@ import { SortOrder, Topic, ConsumerGroup } from 'generated-sources'; -import { TopicsState } from 'redux/interfaces'; +import { TopicsState, TopicWithDetailedInfo } from 'redux/interfaces'; export const internalTopicPayload = { name: '__internal.topic', @@ -49,7 +49,7 @@ export const topicsPayload: Topic[] = [ ]; export const getTopicStateFixtures = ( - topics: Topic[], + topics: TopicWithDetailedInfo[], consumerGroups?: ConsumerGroup[] ): TopicsState => { const byName = topics.reduce((acc: { [i in string]: Topic }, curr) => { From 327d8541f5044bdceb79cb37bc5d1f80a3b1a122 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 17 May 2022 19:28:04 +0400 Subject: [PATCH 08/61] Remove withRouter HOC from Overview file --- .../Topic/Details/Overview/Overview.tsx | 41 +++-- .../Details/Overview/OverviewContainer.ts | 27 +-- .../Overview/__test__/Overview.spec.tsx | 170 ++++++++++-------- 3 files changed, 119 insertions(+), 119 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/Overview.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/Overview.tsx index 6e497b017e8..88a94b742d9 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/Overview.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/Overview.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Partition, Replica, Topic, TopicDetails } from 'generated-sources'; +import { Partition, Replica } from 'generated-sources'; import { ClusterName, TopicName } from 'redux/interfaces'; import Dropdown from 'components/common/Dropdown/Dropdown'; import DropdownItem from 'components/common/Dropdown/DropdownItem'; @@ -10,11 +10,12 @@ import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeader import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon'; import * as Metrics from 'components/common/Metrics'; import { Tag } from 'components/common/Tag/Tag.styled'; +import { useParams } from 'react-router-dom'; +import { useAppSelector } from 'lib/hooks/redux'; +import { getTopicByName } from 'redux/reducers/topics/selectors'; import { ReplicaCell } from 'components/Topics/Topic/Details/Details.styled'; -export interface Props extends Topic, TopicDetails { - clusterName: ClusterName; - topicName: TopicName; +export interface Props { clearTopicMessages(params: { clusterName: ClusterName; topicName: TopicName; @@ -22,21 +23,23 @@ export interface Props extends Topic, TopicDetails { }): void; } -const Overview: React.FC = ({ - partitions, - underReplicatedPartitions, - inSyncReplicas, - replicas, - partitionCount, - internal, - replicationFactor, - segmentSize, - segmentCount, - clusterName, - topicName, - cleanUpPolicy, - clearTopicMessages, -}) => { +const Overview: React.FC = ({ clearTopicMessages }) => { + const { clusterName, topicName } = + useParams<{ clusterName: ClusterName; topicName: TopicName }>(); + + const { + partitions, + underReplicatedPartitions, + inSyncReplicas, + replicas, + partitionCount, + internal, + replicationFactor, + segmentSize, + segmentCount, + cleanUpPolicy, + } = useAppSelector((state) => getTopicByName(state, topicName)); + const { isReadOnly } = React.useContext(ClusterContext); const messageCount = React.useMemo( diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/OverviewContainer.ts b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/OverviewContainer.ts index d5f90114844..f32a6028040 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/OverviewContainer.ts +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/OverviewContainer.ts @@ -1,34 +1,9 @@ import { connect } from 'react-redux'; -import { RootState, TopicName, ClusterName } from 'redux/interfaces'; -import { getTopicByName } from 'redux/reducers/topics/selectors'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice'; import Overview from 'components/Topics/Topic/Details/Overview/Overview'; -interface RouteProps { - clusterName: ClusterName; - topicName: TopicName; -} - -type OwnProps = RouteComponentProps; - -const mapStateToProps = ( - state: RootState, - { - match: { - params: { topicName, clusterName }, - }, - }: OwnProps -) => ({ - ...getTopicByName(state, topicName), - topicName, - clusterName, -}); - const mapDispatchToProps = { clearTopicMessages, }; -export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(Overview) -); +export default connect(null, mapDispatchToProps)(Overview); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx index 0d3fb363686..3851add7880 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx @@ -5,16 +5,27 @@ import Overview, { Props as OverviewProps, } from 'components/Topics/Topic/Details/Overview/Overview'; import theme from 'theme/theme'; -import { CleanUpPolicy } from 'generated-sources'; +import { CleanUpPolicy, Topic } from 'generated-sources'; import ClusterContext from 'components/contexts/ClusterContext'; import userEvent from '@testing-library/user-event'; +import { getTopicStateFixtures } from 'redux/reducers/topics/__test__/fixtures'; +import { clusterTopicPath } from 'lib/paths'; +import { createMemoryHistory } from 'history'; +import { Route, Router } from 'react-router-dom'; import { ReplicaCell } from 'components/Topics/Topic/Details/Details.styled'; describe('Overview', () => { const getReplicaCell = () => screen.getByLabelText('replica-info'); const mockClusterName = 'local'; const mockTopicName = 'topic'; - const mockClearTopicMessages = jest.fn(); + const mockTopic = { name: mockTopicName }; + + const defaultPathName = clusterTopicPath(':clusterName', ':topicName'); + + const defaultHistory = createMemoryHistory({ + initialEntries: [clusterTopicPath(mockClusterName, mockTopicName)], + }); + const mockPartitions = [ { partition: 1, @@ -36,44 +47,34 @@ describe('Overview', () => { hasSchemaRegistryConfigured: true, isTopicDeletionAllowed: true, }; - const defaultProps: OverviewProps = { - name: mockTopicName, - partitions: [], - internal: true, - clusterName: mockClusterName, - topicName: mockTopicName, - clearTopicMessages: mockClearTopicMessages, - }; const setupComponent = ( - props = defaultProps, - contextValues = defaultContextValues, - underReplicatedPartitions?: number, - inSyncReplicas?: number, - replicas?: number + props: Partial = {}, + topicState: Topic = mockTopic, + contextValues = defaultContextValues ) => { + const topics = getTopicStateFixtures([topicState]); + return render( - - - + + + + + + + , + { pathname: defaultPathName, preloadedState: { topics } } ); }; - afterEach(() => { - mockClearTopicMessages.mockClear(); - }); - it('at least one replica was rendered', () => { - setupComponent({ - ...defaultProps, - underReplicatedPartitions: 0, - inSyncReplicas: 1, - replicas: 1, + setupComponent( + {}, + { + ...mockTopic, + partitions: mockPartitions, + internal: false, + cleanUpPolicy: CleanUpPolicy.DELETE, }); expect(getReplicaCell()).toBeInTheDocument(); }); @@ -86,17 +87,20 @@ describe('Overview', () => { describe('when it has internal flag', () => { it('does not render the Action button a Topic', () => { - setupComponent({ - ...defaultProps, - partitions: mockPartitions, - internal: false, - cleanUpPolicy: CleanUpPolicy.DELETE, - }); + setupComponent( + {}, + { + ...mockTopic, + partitions: mockPartitions, + internal: false, + cleanUpPolicy: CleanUpPolicy.DELETE, + } + ); expect(screen.getAllByRole('menu')[0]).toBeInTheDocument(); }); it('does not render Partitions', () => { - setupComponent(); + setupComponent({}, { ...mockTopic, partitions: [] }); expect(screen.getByText('No Partitions found')).toBeInTheDocument(); }); @@ -110,12 +114,15 @@ describe('Overview', () => { }); it('should be the appropriate color', () => { - setupComponent({ - ...defaultProps, - underReplicatedPartitions: 0, - inSyncReplicas: 1, - replicas: 2, - }); + setupComponent( + {}, + { + ...mockTopic, + underReplicatedPartitions: 0, + inSyncReplicas: 1, + replicas: 2, + } + ); const circles = screen.getAllByRole('circle'); expect(circles[0]).toHaveStyle( `fill: ${theme.circularAlert.color.success}` @@ -127,24 +134,30 @@ describe('Overview', () => { }); describe('when Clear Messages is clicked', () => { - setupComponent({ - ...defaultProps, - partitions: mockPartitions, - internal: false, - cleanUpPolicy: CleanUpPolicy.DELETE, - }); - - const clearMessagesButton = screen.getByText('Clear Messages'); - userEvent.click(clearMessagesButton); + it('should when Clear Messages is clicked', () => { + const mockClearTopicMessages = jest.fn(); + setupComponent( + { clearTopicMessages: mockClearTopicMessages }, + { + ...mockTopic, + partitions: mockPartitions, + internal: false, + cleanUpPolicy: CleanUpPolicy.DELETE, + } + ); - expect(mockClearTopicMessages).toHaveBeenCalledTimes(1); + const clearMessagesButton = screen.getByText('Clear Messages'); + userEvent.click(clearMessagesButton); + expect(mockClearTopicMessages).toHaveBeenCalledTimes(1); + }); }); describe('when the table partition dropdown appearance', () => { it('should check if the dropdown is not present when it is readOnly', () => { setupComponent( + {}, { - ...defaultProps, + ...mockTopic, partitions: mockPartitions, internal: true, cleanUpPolicy: CleanUpPolicy.DELETE, @@ -155,32 +168,41 @@ describe('Overview', () => { }); it('should check if the dropdown is not present when it is internal', () => { - setupComponent({ - ...defaultProps, - partitions: mockPartitions, - internal: true, - cleanUpPolicy: CleanUpPolicy.DELETE, - }); + setupComponent( + {}, + { + ...mockTopic, + partitions: mockPartitions, + internal: true, + cleanUpPolicy: CleanUpPolicy.DELETE, + } + ); expect(screen.queryByText('Clear Messages')).not.toBeInTheDocument(); }); it('should check if the dropdown is not present when cleanUpPolicy is not DELETE', () => { - setupComponent({ - ...defaultProps, - partitions: mockPartitions, - internal: false, - cleanUpPolicy: CleanUpPolicy.COMPACT, - }); + setupComponent( + {}, + { + ...mockTopic, + partitions: mockPartitions, + internal: false, + cleanUpPolicy: CleanUpPolicy.COMPACT, + } + ); expect(screen.queryByText('Clear Messages')).not.toBeInTheDocument(); }); it('should check if the dropdown action to be in visible', () => { - setupComponent({ - ...defaultProps, - partitions: mockPartitions, - internal: false, - cleanUpPolicy: CleanUpPolicy.DELETE, - }); + setupComponent( + {}, + { + ...mockTopic, + partitions: mockPartitions, + internal: false, + cleanUpPolicy: CleanUpPolicy.DELETE, + } + ); expect(screen.getByText('Clear Messages')).toBeInTheDocument(); }); }); From 1ddf31c093e079ce58bb4689b2114792c30eb0e4 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 17 May 2022 20:34:48 +0400 Subject: [PATCH 09/61] Remove withRouter HOC from Edit file --- .../src/components/Topics/Topic/Edit/Edit.tsx | 16 ++-- .../Topics/Topic/Edit/EditContainer.ts | 21 ++++ .../Topics/Topic/Edit/EditContainer.tsx | 43 --------- .../Topics/Topic/Edit/__test__/Edit.spec.tsx | 95 ++++++++++++------- 4 files changed, 89 insertions(+), 86 deletions(-) create mode 100644 kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.ts diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx index 9bcf7b893d2..5d753bf0cb6 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx @@ -10,19 +10,18 @@ import { import { useForm, FormProvider } from 'react-hook-form'; import TopicForm from 'components/Topics/shared/Form/TopicForm'; import { clusterTopicPath } from 'lib/paths'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useParams } from 'react-router-dom'; import { yupResolver } from '@hookform/resolvers/yup'; import { topicFormValidationSchema } from 'lib/yupExtended'; import { TOPIC_CUSTOM_PARAMS_PREFIX, TOPIC_CUSTOM_PARAMS } from 'lib/constants'; import styled from 'styled-components'; import PageHeading from 'components/common/PageHeading/PageHeading'; +import { useAppSelector } from 'lib/hooks/redux'; +import { getFullTopic } from 'redux/reducers/topics/selectors'; import DangerZoneContainer from './DangerZone/DangerZoneContainer'; export interface Props { - clusterName: ClusterName; - topicName: TopicName; - topic?: TopicWithDetailedInfo; isFetched: boolean; isTopicUpdated: boolean; fetchTopicConfig: (payload: { @@ -83,15 +82,18 @@ const topicParams = (topic: TopicWithDetailedInfo | undefined) => { let formInit = false; const Edit: React.FC = ({ - clusterName, - topicName, - topic, isFetched, isTopicUpdated, fetchTopicConfig, updateTopic, }) => { + const { clusterName, topicName } = + useParams<{ clusterName: ClusterName; topicName: TopicName }>(); + + const topic = useAppSelector((state) => getFullTopic(state, topicName)); + const defaultValues = React.useMemo(() => topicParams(topic), [topic]); + const methods = useForm({ defaultValues, resolver: yupResolver(topicFormValidationSchema), diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.ts b/kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.ts new file mode 100644 index 00000000000..3ab8efead21 --- /dev/null +++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.ts @@ -0,0 +1,21 @@ +import { connect } from 'react-redux'; +import { RootState } from 'redux/interfaces'; +import { updateTopic, fetchTopicConfig } from 'redux/actions'; +import { + getTopicConfigFetched, + getTopicUpdated, +} from 'redux/reducers/topics/selectors'; + +import Edit from './Edit'; + +const mapStateToProps = (state: RootState) => ({ + isFetched: getTopicConfigFetched(state), + isTopicUpdated: getTopicUpdated(state), +}); + +const mapDispatchToProps = { + fetchTopicConfig, + updateTopic, +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Edit); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.tsx index b02f6d75483..e69de29bb2d 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/EditContainer.tsx @@ -1,43 +0,0 @@ -import { connect } from 'react-redux'; -import { RootState, ClusterName, TopicName } from 'redux/interfaces'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { - updateTopic, - fetchTopicConfig, -} from 'redux/reducers/topics/topicsSlice'; -import { - getTopicConfigFetched, - getTopicUpdated, - getFullTopic, -} from 'redux/reducers/topics/selectors'; - -import Edit from './Edit'; - -interface RouteProps { - clusterName: ClusterName; - topicName: TopicName; -} - -type OwnProps = RouteComponentProps; - -const mapStateToProps = ( - state: RootState, - { - match: { - params: { topicName, clusterName }, - }, - }: OwnProps -) => ({ - clusterName, - topicName, - topic: getFullTopic(state, topicName), - isFetched: getTopicConfigFetched(state), - isTopicUpdated: getTopicUpdated(state), -}); - -const mapDispatchToProps = { - fetchTopicConfig, - updateTopic, -}; - -export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Edit)); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/__test__/Edit.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Edit/__test__/Edit.spec.tsx index 676160ef4b5..01dbdaa092e 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Edit/__test__/Edit.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/__test__/Edit.spec.tsx @@ -3,34 +3,56 @@ import Edit, { DEFAULTS, Props } from 'components/Topics/Topic/Edit/Edit'; import { act, screen } from '@testing-library/react'; import { render } from 'lib/testHelpers'; import userEvent from '@testing-library/user-event'; -import { Router } from 'react-router-dom'; +import { Route, Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; -import { clusterTopicPath, clusterTopicsPath } from 'lib/paths'; +import { + clusterTopicEditPath, + clusterTopicPath, + clusterTopicsPath, +} from 'lib/paths'; +import { TopicsState, TopicWithDetailedInfo } from 'redux/interfaces'; +import { getTopicStateFixtures } from 'redux/reducers/topics/__test__/fixtures'; import { topicName, clusterName, topicWithInfo } from './fixtures'; -const historyMock = createMemoryHistory(); +const defaultPathName = clusterTopicEditPath(clusterName, topicName); -const renderComponent = (props: Partial = {}, history = historyMock) => - render( +const historyMock = createMemoryHistory({ + initialEntries: [defaultPathName], +}); + +const renderComponent = ( + props: Partial = {}, + topic: TopicWithDetailedInfo | null = topicWithInfo, + history = historyMock +) => { + let topics: TopicsState | undefined; + + if (topic === null) { + topics = undefined; + } else { + topics = getTopicStateFixtures([topic]); + } + + return render( - - + + + + , + { + pathname: defaultPathName, + preloadedState: { topics }, + } ); +}; describe('Edit Component', () => { it('renders the Edit Component', () => { @@ -45,7 +67,7 @@ describe('Edit Component', () => { }); it('should check Edit component renders null is not rendered when topic is not passed', () => { - renderComponent({ topic: undefined }); + renderComponent({}, { ...topicWithInfo, config: undefined }); expect( screen.queryByRole('heading', { name: `Edit ${topicName}` }) ).not.toBeInTheDocument(); @@ -67,7 +89,7 @@ describe('Edit Component', () => { it('should check Edit component renders null is not topic config is not passed is false', () => { const modifiedTopic = { ...topicWithInfo }; modifiedTopic.config = undefined; - renderComponent({ topic: modifiedTopic }); + renderComponent({}, modifiedTopic); expect( screen.queryByRole('heading', { name: `Edit ${topicName}` }) ).not.toBeInTheDocument(); @@ -77,19 +99,19 @@ describe('Edit Component', () => { }); describe('Edit Component with its topic default and modified values', () => { - it('should check the default partitions value in the DangerZone', () => { - renderComponent({ - topic: { ...topicWithInfo, partitionCount: undefined }, - }); - expect(screen.getByPlaceholderText('Number of partitions')).toHaveValue( - DEFAULTS.partitions - ); + it('should check the default partitions value in the DangerZone', async () => { + renderComponent({}, { ...topicWithInfo, partitionCount: 0 }); + // cause topic selector will return falsy + expect( + screen.queryByRole('heading', { name: `Edit ${topicName}` }) + ).not.toBeInTheDocument(); + expect( + screen.queryByRole('heading', { name: `Danger Zone` }) + ).not.toBeInTheDocument(); }); - it('should check the default partitions value in the DangerZone', () => { - renderComponent({ - topic: { ...topicWithInfo, replicationFactor: undefined }, - }); + it('should check the default partitions value in the DangerZone', async () => { + renderComponent({}, { ...topicWithInfo, replicationFactor: undefined }); expect(screen.getByPlaceholderText('Replication Factor')).toHaveValue( DEFAULTS.replicationFactor ); @@ -100,11 +122,11 @@ describe('Edit Component', () => { it('should check the submit functionality when topic updated is false', async () => { const updateTopicMock = jest.fn(); const mocked = createMemoryHistory({ - initialEntries: [`${clusterTopicsPath(clusterName)}/${topicName}/edit`], + initialEntries: [clusterTopicEditPath(clusterName, topicName)], }); jest.spyOn(mocked, 'push'); - renderComponent({ updateTopic: updateTopicMock }, mocked); + renderComponent({ updateTopic: updateTopicMock }, undefined, mocked); const btn = screen.getAllByText(/submit/i)[0]; expect(btn).toBeEnabled(); @@ -128,6 +150,7 @@ describe('Edit Component', () => { jest.spyOn(mocked, 'push'); renderComponent( { updateTopic: updateTopicMock, isTopicUpdated: true }, + undefined, mocked ); From 42772419ace3b94b2ba06c863ba60121fb9c7a17 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Wed, 18 May 2022 12:01:31 +0400 Subject: [PATCH 10/61] replace Router path with functions instead of strings --- .../src/components/Topics/Topic/Topic.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx index 88256a0f40b..38efdb2d75e 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx @@ -4,6 +4,11 @@ import { ClusterName, TopicName } from 'redux/interfaces'; import EditContainer from 'components/Topics/Topic/Edit/EditContainer'; import DetailsContainer from 'components/Topics/Topic/Details/DetailsContainer'; import PageLoader from 'components/common/PageLoader/PageLoader'; +import { + clusterTopicEditPath, + clusterTopicPath, + clusterTopicSendMessagePath, +} from 'lib/paths'; import SendMessage from './SendMessage/SendMessage'; @@ -46,16 +51,16 @@ const Topic: React.FC = ({ From 707bfa1232523a27e9f9a20db72b673a49912d9d Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Wed, 18 May 2022 12:10:57 +0400 Subject: [PATCH 11/61] delete CustomParamsContainer and use the simple component in the TopicForm --- .../CustomParams/CustomParamsContainer.tsx | 20 ------------------- .../Topics/shared/Form/TopicForm.tsx | 4 ++-- 2 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamsContainer.tsx diff --git a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamsContainer.tsx b/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamsContainer.tsx deleted file mode 100644 index 5806d11e928..00000000000 --- a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamsContainer.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { connect } from 'react-redux'; -import { RootState, TopicConfigByName } from 'redux/interfaces'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; - -import CustomParams from './CustomParams'; - -interface OwnProps extends RouteComponentProps { - isSubmitting: boolean; - config?: TopicConfigByName; -} - -const mapStateToProps = ( - _state: RootState, - { isSubmitting, config }: OwnProps -) => ({ - isSubmitting, - config, -}); - -export default withRouter(connect(mapStateToProps)(CustomParams)); diff --git a/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx b/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx index 9c747491089..bd0fb16beb6 100644 --- a/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx +++ b/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx @@ -10,7 +10,7 @@ import { InputLabel } from 'components/common/Input/InputLabel.styled'; import { FormError } from 'components/common/Input/Input.styled'; import { StyledForm } from 'components/common/Form/Form.styled'; -import CustomParamsContainer from './CustomParams/CustomParamsContainer'; +import CustomParams from './CustomParams/CustomParams'; import TimeToRetain from './TimeToRetain'; import * as S from './TopicForm.styled'; @@ -207,7 +207,7 @@ const TopicForm: React.FC = ({ Custom parameters - + {!isReadOnly && !isInternal && ( - + } right> From c962bcbd04c27a1e65526549a8941d5605fd1921 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Sun, 22 May 2022 20:57:47 +0400 Subject: [PATCH 31/61] Route Parameters code fix with functions and params with variables --- kafka-ui-react-app/src/components/App.tsx | 2 +- .../Brokers/__test__/Brokers.spec.tsx | 2 +- .../src/components/Cluster/Cluster.tsx | 14 +- .../src/components/Connect/Connect.tsx | 29 +--- .../Actions/__tests__/Actions.spec.tsx | 6 +- .../Details/Config/__test__/Config.spec.tsx | 6 +- .../components/Connect/Details/Details.tsx | 27 +--- .../ListItem/__tests__/ListItem.spec.tsx | 6 +- .../Details/Tasks/__tests__/Tasks.spec.tsx | 6 +- .../Details/__tests__/Details.spec.tsx | 6 +- .../Connect/Edit/__tests__/Edit.spec.tsx | 6 +- .../Connect/New/__tests__/New.spec.tsx | 2 +- .../ConsumerGroups/ConsumerGroups.tsx | 17 +-- .../__test__/ResetOffsets.spec.tsx | 7 +- .../__test__/TopicContents.spec.tsx | 4 +- .../Details/__tests__/Details.spec.tsx | 7 +- .../Details/__tests__/ListItem.spec.tsx | 4 +- .../__test__/ConsumerGroups.spec.tsx | 2 +- .../KsqlDb/List/__test__/List.spec.tsx | 2 +- .../KsqlDb/List/__test__/ListItem.spec.tsx | 2 +- .../KsqlDb/Query/__test__/Query.spec.tsx | 2 +- .../Schemas/Details/__test__/Details.spec.tsx | 2 +- .../Schemas/Diff/__test__/Diff.spec.tsx | 2 +- .../Schemas/Edit/__tests__/Edit.spec.tsx | 2 +- .../__test__/GlobalSchemaSelector.spec.tsx | 2 +- .../Schemas/List/__test__/List.spec.tsx | 2 +- .../Schemas/New/__test__/New.spec.tsx | 2 +- .../src/components/Schemas/Schemas.tsx | 19 +-- .../Schemas/__test__/Schemas.spec.tsx | 2 +- .../Topics/List/__tests__/List.spec.tsx | 2 +- .../Topics/New/__test__/New.spec.tsx | 8 +- .../__test__/TopicConsumerGroups.spec.tsx | 5 +- .../Topics/Topic/Details/Details.tsx | 24 +-- .../Overview/__test__/Overview.spec.tsx | 2 +- .../Settings/__test__/Settings.spec.tsx | 5 +- .../Topic/Details/__test__/Details.spec.tsx | 2 +- .../DangerZone/__test__/DangerZone.spec.tsx | 2 +- .../Topics/Topic/Edit/__test__/Edit.spec.tsx | 2 +- .../SendMessage/__test__/SendMessage.spec.tsx | 4 +- .../src/components/Topics/Topic/Topic.tsx | 9 +- .../Topics/Topic/__tests__/Topic.spec.tsx | 2 +- .../src/components/Topics/Topics.tsx | 8 +- .../common/Breadcrumb/Breadcrumb.tsx | 2 +- .../src/lib/__test__/paths.spec.ts | 108 +++++++++++++- kafka-ui-react-app/src/lib/paths.ts | 137 ++++++++++-------- 45 files changed, 255 insertions(+), 259 deletions(-) diff --git a/kafka-ui-react-app/src/components/App.tsx b/kafka-ui-react-app/src/components/App.tsx index 7211c4db1a0..ad479d40346 100644 --- a/kafka-ui-react-app/src/components/App.tsx +++ b/kafka-ui-react-app/src/components/App.tsx @@ -86,7 +86,7 @@ const App: React.FC = () => { - + diff --git a/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx b/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx index e8344246ff5..edf1f0b7183 100644 --- a/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx +++ b/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx @@ -18,7 +18,7 @@ describe('Brokers Component', () => { const renderComponent = () => render( - + , { diff --git a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx index 40cf3818086..0dc07ac51e9 100644 --- a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx +++ b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx @@ -62,32 +62,32 @@ const Cluster: React.FC = () => { - + - + - + {hasSchemaRegistryConfigured && ( - + )} {hasKafkaConnectConfigured && ( - + )} {hasKafkaConnectConfigured && ( - + )} {hasKsqlDbConfigured && ( - + )} diff --git a/kafka-ui-react-app/src/components/Connect/Connect.tsx b/kafka-ui-react-app/src/components/Connect/Connect.tsx index e63e4a4812f..eccfa34003b 100644 --- a/kafka-ui-react-app/src/components/Connect/Connect.tsx +++ b/kafka-ui-react-app/src/components/Connect/Connect.tsx @@ -18,38 +18,25 @@ import EditContainer from './Edit/EditContainer'; const Connect: React.FC = () => (
- + - + - + - +
diff --git a/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx index 4b998f420c3..2483fa64245 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx @@ -60,11 +60,7 @@ describe('Actions', () => { }); describe('view', () => { - const pathname = clusterConnectConnectorPath( - ':clusterName', - ':connectName', - ':connectorName' - ); + const pathname = clusterConnectConnectorPath(); const clusterName = 'my-cluster'; const connectName = 'my-connect'; const connectorName = 'my-connector'; diff --git a/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx index d12183338f6..6c043696590 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx @@ -9,11 +9,7 @@ import { screen } from '@testing-library/dom'; jest.mock('components/common/Editor/Editor', () => 'mock-Editor'); describe('Config', () => { - const pathname = clusterConnectConnectorConfigPath( - ':clusterName', - ':connectName', - ':connectorName' - ); + const pathname = clusterConnectConnectorConfigPath(); const clusterName = 'my-cluster'; const connectName = 'my-connect'; const connectorName = 'my-connector'; diff --git a/kafka-ui-react-app/src/components/Connect/Details/Details.tsx b/kafka-ui-react-app/src/components/Connect/Details/Details.tsx index fb24033b791..77e6f39d1f3 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Details.tsx @@ -99,34 +99,13 @@ const Details: React.FC = ({ - + - + - + diff --git a/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx index 647066e06fc..baaa58d6152 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx @@ -9,11 +9,7 @@ import { Route } from 'react-router-dom'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -const pathname = clusterConnectConnectorTasksPath( - ':clusterName', - ':connectName', - ':connectorName' -); +const pathname = clusterConnectConnectorTasksPath(); const clusterName = 'my-cluster'; const connectName = 'my-connect'; const connectorName = 'my-connector'; diff --git a/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx index 1ec12ecfcd7..dbacfc4a82f 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx @@ -19,11 +19,7 @@ describe('Tasks', () => { }); describe('view', () => { - const pathname = clusterConnectConnectorTasksPath( - ':clusterName', - ':connectName', - ':connectorName' - ); + const pathname = clusterConnectConnectorTasksPath(); const clusterName = 'my-cluster'; const connectName = 'my-connect'; const connectorName = 'my-connector'; diff --git a/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx index 3cda6c1a7c8..816e26af320 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx @@ -27,11 +27,7 @@ jest.mock( ); describe('Details', () => { - const pathname = clusterConnectConnectorPath( - ':clusterName', - ':connectName', - ':connectorName' - ); + const pathname = clusterConnectConnectorPath(); const clusterName = 'my-cluster'; const connectName = 'my-connect'; const connectorName = 'my-connector'; diff --git a/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx b/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx index 8e4f926f5ea..13f1d673186 100644 --- a/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx @@ -23,11 +23,7 @@ jest.mock('react-router-dom', () => ({ })); describe('Edit', () => { - const pathname = clusterConnectConnectorEditPath( - ':clusterName', - ':connectName', - ':connectorName' - ); + const pathname = clusterConnectConnectorEditPath(); const clusterName = 'my-cluster'; const connectName = 'my-connect'; const connectorName = 'my-connector'; diff --git a/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx b/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx index 649f566bc10..bba865e33bc 100644 --- a/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx @@ -51,7 +51,7 @@ describe('New', () => { const renderComponent = (props: Partial = {}) => render( - + { return ( - + - +
- + diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx index 5c034670c1e..6532fd946aa 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx @@ -13,12 +13,7 @@ const { groupId } = consumerGroupPayload; const renderComponent = () => render( - + , { diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx index 2d1a16d802c..7ce5b198d72 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx @@ -11,9 +11,7 @@ const clusterName = 'cluster1'; const renderComponent = (consumers: ConsumerGroupTopicPartition[] = []) => render( - + diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx index 16e15171ce1..1d1a97d2eeb 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx @@ -26,12 +26,7 @@ const renderComponent = () => { history.push(clusterConsumerGroupDetailsPath(clusterName, groupId)); render( - +
diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx index 5deab301c3c..86cd95e7346 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx @@ -12,9 +12,7 @@ const clusterName = 'cluster1'; const renderComponent = (consumers: ConsumerGroupTopicPartition[] = []) => render( - +
render( - + , diff --git a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx index 319cca0fa32..ce8f2a22fc7 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx @@ -14,7 +14,7 @@ const renderComponent = () => { history.push(clusterKsqlDbPath(clusterName)); render( - + diff --git a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx index 1b85d1403cd..cd9b1bd067b 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx @@ -19,7 +19,7 @@ const renderComponent = ({ history.push(clusterKsqlDbPath(clusterName)); render( - + diff --git a/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx b/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx index a261ad5b59c..2ee200d1a49 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx @@ -13,7 +13,7 @@ import { act } from '@testing-library/react'; const clusterName = 'testLocal'; const renderComponent = () => render( - + , { diff --git a/kafka-ui-react-app/src/components/Schemas/Details/__test__/Details.spec.tsx b/kafka-ui-react-app/src/components/Schemas/Details/__test__/Details.spec.tsx index 9021402a871..3134cf67111 100644 --- a/kafka-ui-react-app/src/components/Schemas/Details/__test__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/Schemas/Details/__test__/Details.spec.tsx @@ -27,7 +27,7 @@ const renderComponent = ( context: ContextProps = contextInitialValue ) => render( - +
diff --git a/kafka-ui-react-app/src/components/Schemas/Diff/__test__/Diff.spec.tsx b/kafka-ui-react-app/src/components/Schemas/Diff/__test__/Diff.spec.tsx index 74eeb7a7bef..9eb277537b8 100644 --- a/kafka-ui-react-app/src/components/Schemas/Diff/__test__/Diff.spec.tsx +++ b/kafka-ui-react-app/src/components/Schemas/Diff/__test__/Diff.spec.tsx @@ -37,7 +37,7 @@ describe('Diff', () => { return render( - + render( - + diff --git a/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/__test__/GlobalSchemaSelector.spec.tsx b/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/__test__/GlobalSchemaSelector.spec.tsx index 3d9a375bb52..5da302a3107 100644 --- a/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/__test__/GlobalSchemaSelector.spec.tsx +++ b/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/__test__/GlobalSchemaSelector.spec.tsx @@ -29,7 +29,7 @@ const expectOptionIsSelected = (option: string) => { describe('GlobalSchemaSelector', () => { const renderComponent = () => render( - + , { diff --git a/kafka-ui-react-app/src/components/Schemas/List/__test__/List.spec.tsx b/kafka-ui-react-app/src/components/Schemas/List/__test__/List.spec.tsx index da6ae2e434e..2e75d2cad8d 100644 --- a/kafka-ui-react-app/src/components/Schemas/List/__test__/List.spec.tsx +++ b/kafka-ui-react-app/src/components/Schemas/List/__test__/List.spec.tsx @@ -27,7 +27,7 @@ const renderComponent = ( context: ContextProps = contextInitialValue ) => render( - + diff --git a/kafka-ui-react-app/src/components/Schemas/New/__test__/New.spec.tsx b/kafka-ui-react-app/src/components/Schemas/New/__test__/New.spec.tsx index 3b4c545dabd..a6ecface9d7 100644 --- a/kafka-ui-react-app/src/components/Schemas/New/__test__/New.spec.tsx +++ b/kafka-ui-react-app/src/components/Schemas/New/__test__/New.spec.tsx @@ -10,7 +10,7 @@ const clusterName = 'local'; describe('New Component', () => { beforeEach(() => { render( - + , { diff --git a/kafka-ui-react-app/src/components/Schemas/Schemas.tsx b/kafka-ui-react-app/src/components/Schemas/Schemas.tsx index 89d87e44994..4818bb2d574 100644 --- a/kafka-ui-react-app/src/components/Schemas/Schemas.tsx +++ b/kafka-ui-react-app/src/components/Schemas/Schemas.tsx @@ -17,28 +17,19 @@ import { BreadcrumbRoute } from 'components/common/Breadcrumb/Breadcrumb.route'; const Schemas: React.FC = () => { return ( - + - + - +
- + - + diff --git a/kafka-ui-react-app/src/components/Schemas/__test__/Schemas.spec.tsx b/kafka-ui-react-app/src/components/Schemas/__test__/Schemas.spec.tsx index 5f8b4d122b2..99e145aeea0 100644 --- a/kafka-ui-react-app/src/components/Schemas/__test__/Schemas.spec.tsx +++ b/kafka-ui-react-app/src/components/Schemas/__test__/Schemas.spec.tsx @@ -15,7 +15,7 @@ import { schemaVersion } from 'redux/reducers/schemas/__test__/fixtures'; const renderComponent = (pathname: string) => render( - + , { pathname } diff --git a/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx b/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx index c66e622b5f2..7fdd9a48b2f 100644 --- a/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx @@ -179,7 +179,7 @@ describe('List', () => { beforeEach(() => { render( - + render( - + - + - - New topic path - + New topic path ); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx index 28ad6b99940..165bc18db29 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/__test__/TopicConsumerGroups.spec.tsx @@ -37,10 +37,7 @@ describe('TopicConsumerGroups', () => { }, ]; - const defaultPathName = clusterTopicConsumerGroupsPath( - ':clusterName', - ':topicName' - ); + const defaultPathName = clusterTopicConsumerGroupsPath(); const defaultHistory = createMemoryHistory({ initialEntries: [ diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx index 957073b5545..641ce6364b8 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx @@ -113,10 +113,7 @@ const Details: React.FC = ({
- + {!isReadOnly && !isInternal && ( - + } right> @@ -220,25 +217,16 @@ const Details: React.FC = ({ - + - + - + - + diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx index 8260886ae4e..95bdd2d339b 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx @@ -19,7 +19,7 @@ describe('Overview', () => { const mockTopicName = 'topic'; const mockTopic = { name: mockTopicName }; - const defaultPathName = clusterTopicPath(':clusterName', ':topicName'); + const defaultPathName = clusterTopicPath(); const defaultHistory = createMemoryHistory({ initialEntries: [clusterTopicPath(mockClusterName, mockTopicName)], diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx index bf9349a0ccc..5fcf7175dcf 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/Settings.spec.tsx @@ -14,10 +14,7 @@ describe('Settings', () => { const mockClusterName = 'Cluster_Name'; const mockTopicName = 'Topic_Name'; - const defaultPathName = clusterTopicSettingsPath( - ':clusterName', - ':topicName' - ); + const defaultPathName = clusterTopicSettingsPath(); const history = createMemoryHistory({ initialEntries: [clusterTopicSettingsPath(mockClusterName, mockTopicName)], diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx index df481bc4ca1..b0c4ce6cb36 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx @@ -54,7 +54,7 @@ describe('Details', () => { }} > - +
) => render( - + - + { render( <> - + diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx index 2241cfd7154..bf922800ca2 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx @@ -45,16 +45,13 @@ const Topic: React.FC = ({ return ( - + - + - + diff --git a/kafka-ui-react-app/src/components/Topics/Topic/__tests__/Topic.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/__tests__/Topic.spec.tsx index 97ff07b9f37..18465cee80a 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/__tests__/Topic.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/__tests__/Topic.spec.tsx @@ -35,7 +35,7 @@ describe('Topic Component', () => { const renderComponent = (pathname: string, topicFetching: boolean) => render( - + ( - + - + - + - + diff --git a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx index 7216c7c6145..d935db2fac6 100644 --- a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx +++ b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx @@ -7,7 +7,7 @@ import { BREADCRUMB_DEFINITIONS } from 'lib/constants'; import { BreadcrumbWrapper } from './Breadcrumb.styled'; import { BreadcrumbContext } from './Breadcrumb.context'; -const basePathEntriesLength = clusterPath(':clusterName').split('/').length; +const basePathEntriesLength = clusterPath().split('/').length; export interface BreadcrumbDefinitions { [key: string]: string; diff --git a/kafka-ui-react-app/src/lib/__test__/paths.spec.ts b/kafka-ui-react-app/src/lib/__test__/paths.spec.ts index abb136b331b..68f289fb67a 100644 --- a/kafka-ui-react-app/src/lib/__test__/paths.spec.ts +++ b/kafka-ui-react-app/src/lib/__test__/paths.spec.ts @@ -1,5 +1,13 @@ import { GIT_REPO_LINK } from 'lib/constants'; import * as paths from 'lib/paths'; +import { + clusterNameParam, + connectNameParam, + connectorNameParam, + consumerGroupIDParam, + schemaSubjectParams, + topicNameParam, +} from 'lib/paths'; const clusterName = 'test-cluster-name'; const groupId = 'test-group-id'; @@ -18,21 +26,34 @@ describe('Paths', () => { expect(paths.clusterPath(clusterName)).toEqual( `/ui/clusters/${clusterName}` ); + expect(paths.clusterPath()).toEqual(paths.clusterPath(clusterNameParam)); }); it('clusterBrokersPath', () => { expect(paths.clusterBrokersPath(clusterName)).toEqual( `${paths.clusterPath(clusterName)}/brokers` ); + expect(paths.clusterBrokersPath()).toEqual( + paths.clusterBrokersPath(clusterNameParam) + ); }); it('clusterConsumerGroupsPath', () => { expect(paths.clusterConsumerGroupsPath(clusterName)).toEqual( `${paths.clusterPath(clusterName)}/consumer-groups` ); + expect(paths.clusterConsumerGroupsPath()).toEqual( + paths.clusterConsumerGroupsPath(clusterNameParam) + ); }); it('clusterConsumerGroupDetailsPath', () => { expect(paths.clusterConsumerGroupDetailsPath(clusterName, groupId)).toEqual( `${paths.clusterConsumerGroupsPath(clusterName)}/${groupId}` ); + expect(paths.clusterConsumerGroupDetailsPath()).toEqual( + paths.clusterConsumerGroupDetailsPath( + clusterNameParam, + consumerGroupIDParam + ) + ); }); it('clusterConsumerGroupResetOffsetsPath', () => { expect( @@ -43,84 +64,135 @@ describe('Paths', () => { groupId )}/reset-offsets` ); + expect(paths.clusterConsumerGroupResetOffsetsPath()).toEqual( + paths.clusterConsumerGroupResetOffsetsPath( + clusterNameParam, + consumerGroupIDParam + ) + ); }); it('clusterSchemasPath', () => { expect(paths.clusterSchemasPath(clusterName)).toEqual( `${paths.clusterPath(clusterName)}/schemas` ); + expect(paths.clusterSchemasPath()).toEqual( + paths.clusterSchemasPath(clusterNameParam) + ); }); it('clusterSchemaNewPath', () => { expect(paths.clusterSchemaNewPath(clusterName)).toEqual( `${paths.clusterSchemasPath(clusterName)}/create-new` ); + expect(paths.clusterSchemaNewPath()).toEqual( + paths.clusterSchemaNewPath(clusterNameParam) + ); }); it('clusterSchemaPath', () => { expect(paths.clusterSchemaPath(clusterName, schemaId)).toEqual( `${paths.clusterSchemasPath(clusterName)}/${schemaId}` ); + expect(paths.clusterSchemaPath()).toEqual( + paths.clusterSchemaPath(clusterNameParam, schemaSubjectParams) + ); }); it('clusterSchemaEditPath', () => { expect(paths.clusterSchemaEditPath(clusterName, schemaId)).toEqual( `${paths.clusterSchemaPath(clusterName, schemaId)}/edit` ); + expect(paths.clusterSchemaEditPath()).toEqual( + paths.clusterSchemaEditPath(clusterNameParam, schemaSubjectParams) + ); }); it('clusterTopicsPath', () => { expect(paths.clusterTopicsPath(clusterName)).toEqual( `${paths.clusterPath(clusterName)}/topics` ); + expect(paths.clusterTopicsPath()).toEqual( + paths.clusterTopicsPath(clusterNameParam) + ); }); it('clusterTopicNewPath', () => { expect(paths.clusterTopicNewPath(clusterName)).toEqual( `${paths.clusterTopicsPath(clusterName)}/create-new` ); + expect(paths.clusterTopicNewPath()).toEqual( + paths.clusterTopicNewPath(clusterNameParam) + ); }); it('clusterTopicPath', () => { expect(paths.clusterTopicPath(clusterName, topicId)).toEqual( `${paths.clusterTopicsPath(clusterName)}/${topicId}` ); + expect(paths.clusterTopicPath()).toEqual( + paths.clusterTopicPath(clusterNameParam, topicNameParam) + ); }); it('clusterTopicSettingsPath', () => { expect(paths.clusterTopicSettingsPath(clusterName, topicId)).toEqual( `${paths.clusterTopicPath(clusterName, topicId)}/settings` ); + expect(paths.clusterTopicSettingsPath()).toEqual( + paths.clusterTopicSettingsPath(clusterNameParam, topicNameParam) + ); }); it('clusterTopicConsumerGroupsPath', () => { expect(paths.clusterTopicConsumerGroupsPath(clusterName, topicId)).toEqual( `${paths.clusterTopicPath(clusterName, topicId)}/consumer-groups` ); + expect(paths.clusterTopicConsumerGroupsPath()).toEqual( + paths.clusterTopicConsumerGroupsPath(clusterNameParam, topicNameParam) + ); }); it('clusterTopicMessagesPath', () => { expect(paths.clusterTopicMessagesPath(clusterName, topicId)).toEqual( `${paths.clusterTopicPath(clusterName, topicId)}/messages` ); + expect(paths.clusterTopicMessagesPath()).toEqual( + paths.clusterTopicMessagesPath(clusterNameParam, topicNameParam) + ); }); it('clusterTopicSendMessagePath', () => { expect(paths.clusterTopicSendMessagePath(clusterName, topicId)).toEqual( `${paths.clusterTopicPath(clusterName, topicId)}/message` ); + expect(paths.clusterTopicSendMessagePath()).toEqual( + paths.clusterTopicSendMessagePath(clusterNameParam, topicNameParam) + ); }); it('clusterTopicEditPath', () => { expect(paths.clusterTopicEditPath(clusterName, topicId)).toEqual( `${paths.clusterTopicPath(clusterName, topicId)}/edit` ); + expect(paths.clusterTopicEditPath()).toEqual( + paths.clusterTopicEditPath(clusterNameParam, topicNameParam) + ); }); it('clusterConnectsPath', () => { expect(paths.clusterConnectsPath(clusterName)).toEqual( `${paths.clusterPath(clusterName)}/connects` ); + expect(paths.clusterConnectsPath()).toEqual( + paths.clusterConnectsPath(clusterNameParam) + ); }); it('clusterConnectorsPath', () => { expect(paths.clusterConnectorsPath(clusterName)).toEqual( `${paths.clusterPath(clusterName)}/connectors` ); + expect(paths.clusterConnectorsPath()).toEqual( + paths.clusterConnectorsPath(clusterNameParam) + ); }); it('clusterConnectorNewPath', () => { expect(paths.clusterConnectorNewPath(clusterName)).toEqual( `${paths.clusterConnectorsPath(clusterName)}/create-new` ); + expect(paths.clusterConnectorNewPath()).toEqual( + paths.clusterConnectorNewPath(clusterNameParam) + ); }); it('clusterConnectConnectorPath', () => { expect( @@ -130,6 +202,13 @@ describe('Paths', () => { clusterName )}/${connectName}/connectors/${connectorName}` ); + expect(paths.clusterConnectConnectorPath()).toEqual( + paths.clusterConnectConnectorPath( + clusterNameParam, + connectNameParam, + connectorNameParam + ) + ); }); it('clusterConnectConnectorEditPath', () => { expect( @@ -145,6 +224,13 @@ describe('Paths', () => { connectorName )}/edit` ); + expect(paths.clusterConnectConnectorEditPath()).toEqual( + paths.clusterConnectConnectorEditPath( + clusterNameParam, + connectNameParam, + connectorNameParam + ) + ); }); it('clusterConnectConnectorTasksPath', () => { expect( @@ -160,6 +246,13 @@ describe('Paths', () => { connectorName )}/tasks` ); + expect(paths.clusterConnectConnectorTasksPath()).toEqual( + paths.clusterConnectConnectorTasksPath( + clusterNameParam, + connectNameParam, + connectorNameParam + ) + ); }); it('clusterConnectConnectorConfigPath', () => { expect( @@ -175,26 +268,29 @@ describe('Paths', () => { connectorName )}/config` ); + expect(paths.clusterConnectConnectorConfigPath()).toEqual( + paths.clusterConnectConnectorConfigPath( + clusterNameParam, + connectNameParam, + connectorNameParam + ) + ); }); it('clusterKsqlDbPath', () => { expect(paths.clusterKsqlDbPath(clusterName)).toEqual( `${paths.clusterPath(clusterName)}/ksqldb` ); - }); - it('clusterKsqlDbPath with default value', () => { expect(paths.clusterKsqlDbPath()).toEqual( - `${paths.clusterPath(':clusterName')}/ksqldb` + paths.clusterKsqlDbPath(clusterNameParam) ); }); it('clusterKsqlDbQueryPath', () => { expect(paths.clusterKsqlDbQueryPath(clusterName)).toEqual( `${paths.clusterKsqlDbPath(clusterName)}/query` ); - }); - it('clusterKsqlDbQueryPath with default value', () => { expect(paths.clusterKsqlDbQueryPath()).toEqual( - `${paths.clusterKsqlDbPath(':clusterName')}/query` + paths.clusterKsqlDbQueryPath(clusterNameParam) ); }); }); diff --git a/kafka-ui-react-app/src/lib/paths.ts b/kafka-ui-react-app/src/lib/paths.ts index 619ddd9e031..a878ad81e7b 100644 --- a/kafka-ui-react-app/src/lib/paths.ts +++ b/kafka-ui-react-app/src/lib/paths.ts @@ -11,73 +11,84 @@ import { GIT_REPO_LINK } from './constants'; export const gitCommitPath = (commit: string) => `${GIT_REPO_LINK}/commit/${commit}`; -export const clusterPath = (clusterName: ClusterName) => +export const clusterNameParam: ClusterName = ':clusterName'; +export const clusterPath = (clusterName: ClusterName = clusterNameParam) => `/ui/clusters/${clusterName}`; // Brokers -export const clusterBrokersPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/brokers`; +export const clusterBrokersPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/brokers`; // Consumer Groups -export const clusterConsumerGroupsPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/consumer-groups`; +export const consumerGroupIDParam = ':consumerGroupID'; +export const clusterConsumerGroupsPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/consumer-groups`; export const clusterConsumerGroupDetailsPath = ( - clusterName: ClusterName, - groupId: string + clusterName: ClusterName = clusterNameParam, + groupId: string = consumerGroupIDParam ) => `${clusterPath(clusterName)}/consumer-groups/${groupId}`; export const clusterConsumerGroupResetOffsetsPath = ( - clusterName: ClusterName, - groupId: string + clusterName: ClusterName = clusterNameParam, + groupId: string = consumerGroupIDParam ) => `${clusterPath(clusterName)}/consumer-groups/${groupId}/reset-offsets`; // Schemas -export const clusterSchemasPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/schemas`; -export const clusterSchemaNewPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/schemas/create-new`; +export const schemaSubjectParams = ':subject'; +export const clusterSchemasPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/schemas`; +export const clusterSchemaNewPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/schemas/create-new`; export const clusterSchemaPath = ( - clusterName: ClusterName, - subject: SchemaName + clusterName: ClusterName = clusterNameParam, + subject: SchemaName = schemaSubjectParams ) => `${clusterSchemasPath(clusterName)}/${subject}`; export const clusterSchemaEditPath = ( - clusterName: ClusterName, - subject: SchemaName + clusterName: ClusterName = clusterNameParam, + subject: SchemaName = schemaSubjectParams ) => `${clusterSchemasPath(clusterName)}/${subject}/edit`; export const clusterSchemaSchemaDiffPath = ( - clusterName: ClusterName, - subject: SchemaName + clusterName: ClusterName = clusterNameParam, + subject: SchemaName = schemaSubjectParams ) => `${clusterSchemaPath(clusterName, subject)}/diff`; // Topics -export const clusterTopicsPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/topics`; -export const clusterTopicNewPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/topics/create-new`; -export const clusterTopicCopyPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/topics/copy`; +export const topicNameParam = ':topicName'; +export const clusterTopicsPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/topics`; +export const clusterTopicNewPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/topics/create-new`; +export const clusterTopicCopyPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/topics/copy`; export const clusterTopicPath = ( - clusterName: ClusterName, - topicName: TopicName + clusterName: ClusterName = clusterNameParam, + topicName: TopicName = topicNameParam ) => `${clusterTopicsPath(clusterName)}/${topicName}`; export const clusterTopicSettingsPath = ( - clusterName: ClusterName, - topicName: TopicName + clusterName: ClusterName = clusterNameParam, + topicName: TopicName = topicNameParam ) => `${clusterTopicsPath(clusterName)}/${topicName}/settings`; export const clusterTopicMessagesPath = ( - clusterName: ClusterName, - topicName: TopicName + clusterName: ClusterName = clusterNameParam, + topicName: TopicName = topicNameParam ) => `${clusterTopicsPath(clusterName)}/${topicName}/messages`; export const clusterTopicEditPath = ( - clusterName: ClusterName, - topicName: TopicName + clusterName: ClusterName = clusterNameParam, + topicName: TopicName = topicNameParam ) => `${clusterTopicsPath(clusterName)}/${topicName}/edit`; export const clusterTopicConsumerGroupsPath = ( - clusterName: ClusterName, - topicName: TopicName + clusterName: ClusterName = clusterNameParam, + topicName: TopicName = topicNameParam ) => `${clusterTopicsPath(clusterName)}/${topicName}/consumer-groups`; export const clusterTopicSendMessagePath = ( - clusterName: ClusterName, - topicName: TopicName + clusterName: ClusterName = clusterNameParam, + topicName: TopicName = topicNameParam ) => `${clusterTopicsPath(clusterName)}/${topicName}/message`; export interface RouteParamsClusterTopic { clusterName: ClusterName; @@ -85,35 +96,40 @@ export interface RouteParamsClusterTopic { } // Kafka Connect -export const clusterConnectsPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/connects`; -export const clusterConnectorsPath = (clusterName: ClusterName) => - `${clusterPath(clusterName)}/connectors`; -export const clusterConnectorNewPath = (clusterName: ClusterName) => - `${clusterConnectorsPath(clusterName)}/create-new`; +export const connectNameParam = ':connectName'; +export const connectorNameParam = ':connectorName'; +export const clusterConnectsPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/connects`; +export const clusterConnectorsPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/connectors`; +export const clusterConnectorNewPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterConnectorsPath(clusterName)}/create-new`; export const clusterConnectConnectorsPath = ( - clusterName: ClusterName, - connectName: ConnectName + clusterName: ClusterName = clusterNameParam, + connectName: ConnectName = connectNameParam ) => `${clusterConnectsPath(clusterName)}/${connectName}/connectors`; export const clusterConnectConnectorPath = ( - clusterName: ClusterName, - connectName: ConnectName, - connectorName: ConnectorName + clusterName: ClusterName = clusterNameParam, + connectName: ConnectName = connectNameParam, + connectorName: ConnectorName = connectorNameParam ) => `${clusterConnectConnectorsPath(clusterName, connectName)}/${connectorName}`; export const clusterConnectConnectorEditPath = ( - clusterName: ClusterName, - connectName: ConnectName, - connectorName: ConnectorName + clusterName: ClusterName = clusterNameParam, + connectName: ConnectName = connectNameParam, + connectorName: ConnectorName = connectorNameParam ) => `${clusterConnectConnectorsPath( clusterName, connectName )}/${connectorName}/edit`; export const clusterConnectConnectorTasksPath = ( - clusterName: ClusterName, - connectName: ConnectName, - connectorName: ConnectorName + clusterName: ClusterName = clusterNameParam, + connectName: ConnectName = connectNameParam, + connectorName: ConnectorName = connectorNameParam ) => `${clusterConnectConnectorPath( clusterName, @@ -121,9 +137,9 @@ export const clusterConnectConnectorTasksPath = ( connectorName )}/tasks`; export const clusterConnectConnectorConfigPath = ( - clusterName: ClusterName, - connectName: ConnectName, - connectorName: ConnectorName + clusterName: ClusterName = clusterNameParam, + connectName: ConnectName = connectNameParam, + connectorName: ConnectorName = connectorNameParam ) => `${clusterConnectConnectorPath( clusterName, @@ -137,9 +153,10 @@ export interface RouterParamsClusterConnectConnector { } // KsqlDb -export const clusterKsqlDbPath = (clusterName: ClusterName = ':clusterName') => - `${clusterPath(clusterName)}/ksqldb`; +export const clusterKsqlDbPath = ( + clusterName: ClusterName = clusterNameParam +) => `${clusterPath(clusterName)}/ksqldb`; export const clusterKsqlDbQueryPath = ( - clusterName: ClusterName = ':clusterName' + clusterName: ClusterName = clusterNameParam ) => `${clusterPath(clusterName)}/ksqldb/query`; From 86aee4469a3cee4851e027112b5f2a4f3bf8fee9 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 24 May 2022 17:38:00 +0400 Subject: [PATCH 32/61] Updating BreadCrumb Route --- .../src/components/Cluster/Cluster.tsx | 58 ++++++++++++------- .../src/components/Connect/Connect.tsx | 34 ++++++----- .../ConsumerGroups/ConsumerGroups.tsx | 26 +++++---- .../src/components/KsqlDb/KsqlDb.tsx | 18 +++--- .../src/components/Schemas/Schemas.tsx | 42 +++++++++----- .../src/components/Topics/Topics.tsx | 34 ++++++----- .../common/Breadcrumb/Breadcrumb.route.tsx | 48 ++++----------- .../Breadcrumb/__tests__/Breadcrumb.spec.tsx | 20 +++++-- 8 files changed, 155 insertions(+), 125 deletions(-) diff --git a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx index 0dc07ac51e9..735258c75ce 100644 --- a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx +++ b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useSelector } from 'react-redux'; -import { Switch, Redirect, useParams } from 'react-router-dom'; +import { Switch, Redirect, useParams, Route } from 'react-router-dom'; import { ClusterFeaturesEnum } from 'generated-sources'; import { getClustersFeatures, @@ -62,34 +62,48 @@ const Cluster: React.FC = () => { - - - - - - - - - - {hasSchemaRegistryConfigured && ( - - + + + + + + + + + + + + + + + {hasSchemaRegistryConfigured && ( + + + + + )} {hasKafkaConnectConfigured && ( - - - + + + + + )} {hasKafkaConnectConfigured && ( - - - + + + + + )} {hasKsqlDbConfigured && ( - - - + + + + + )} (
- - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + { return ( - - - - -
- - - - + + + + + + + +
+ + + + + + + ); }; diff --git a/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx b/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx index 48d510ca264..c2c30a77b25 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Switch } from 'react-router-dom'; +import { Route, Switch } from 'react-router-dom'; import { clusterKsqlDbPath, clusterKsqlDbQueryPath } from 'lib/paths'; import List from 'components/KsqlDb/List/List'; import Query from 'components/KsqlDb/Query/Query'; @@ -8,12 +8,16 @@ import { BreadcrumbRoute } from 'components/common/Breadcrumb/Breadcrumb.route'; const KsqlDb: React.FC = () => { return ( - - - - - - + + + + + + + + + + ); }; diff --git a/kafka-ui-react-app/src/components/Schemas/Schemas.tsx b/kafka-ui-react-app/src/components/Schemas/Schemas.tsx index 4818bb2d574..c82f2335b99 100644 --- a/kafka-ui-react-app/src/components/Schemas/Schemas.tsx +++ b/kafka-ui-react-app/src/components/Schemas/Schemas.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Switch } from 'react-router-dom'; +import { Route, Switch } from 'react-router-dom'; import { clusterSchemaNewPath, clusterSchemaPath, @@ -17,21 +17,31 @@ import { BreadcrumbRoute } from 'components/common/Breadcrumb/Breadcrumb.route'; const Schemas: React.FC = () => { return ( - - - - - - - -
- - - - - - - + + + + + + + + + + + + +
+ + + + + + + + + + + + ); }; diff --git a/kafka-ui-react-app/src/components/Topics/Topics.tsx b/kafka-ui-react-app/src/components/Topics/Topics.tsx index c65a20af19b..5c220cd36b5 100644 --- a/kafka-ui-react-app/src/components/Topics/Topics.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topics.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Switch } from 'react-router-dom'; +import { Route, Switch } from 'react-router-dom'; import { clusterTopicCopyPath, clusterTopicNewPath, @@ -14,18 +14,26 @@ import New from './New/New'; const Topics: React.FC = () => ( - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + ); diff --git a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx index bbbac922a61..dd0c12e6579 100644 --- a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx +++ b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx @@ -1,10 +1,5 @@ import React, { useContext, useEffect } from 'react'; -import { - Route, - RouteProps, - useLocation, - useRouteMatch, -} from 'react-router-dom'; +import { useLocation, useRouteMatch } from 'react-router-dom'; import { BreadcrumbContext } from './Breadcrumb.context'; @@ -21,40 +16,17 @@ const BreadcrumbRouteInternal: React.FC = () => { return null; }; -export const BreadcrumbRoute: React.FC = ({ +interface BreadcrumbRoutProps { + children: React.ReactNode; +} + +export const BreadcrumbRoute: React.FC = ({ children, - render, - component, - ...props }) => { return ( - { - if (component) { - return ( - <> - {React.createElement(component)} - - - ); - } - if (render) { - return ( - <> - {render(routeParams)} - - - ); - } - - return ( - <> - {children} - - - ); - }} - /> + <> + {children} + + ); }; diff --git a/kafka-ui-react-app/src/components/common/Breadcrumb/__tests__/Breadcrumb.spec.tsx b/kafka-ui-react-app/src/components/common/Breadcrumb/__tests__/Breadcrumb.spec.tsx index 2012305ef06..a65ff085e51 100644 --- a/kafka-ui-react-app/src/components/common/Breadcrumb/__tests__/Breadcrumb.spec.tsx +++ b/kafka-ui-react-app/src/components/common/Breadcrumb/__tests__/Breadcrumb.spec.tsx @@ -3,19 +3,27 @@ import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb'; import { BreadcrumbProvider } from 'components/common/Breadcrumb/Breadcrumb.provider'; import { BreadcrumbRoute } from 'components/common/Breadcrumb/Breadcrumb.route'; import { render } from 'lib/testHelpers'; +import { Route } from 'react-router-dom'; +import { clusterTopicNewPath, clusterTopicPath } from 'lib/paths'; -const createTopicPath = '/ui/clusters/local/topics/create-new'; -const createTopicRoutePath = '/ui/clusters/:clusterName/topics/create-new'; +const createTopicPath = clusterTopicNewPath('local'); +const createTopicRoutePath = clusterTopicNewPath(); -const topicPath = '/ui/clusters/secondLocal/topics/topic-name'; -const topicRoutePath = '/ui/clusters/:clusterName/topics/:topicName'; +const topicName = 'topic-name'; + +const topicPath = clusterTopicPath('secondLocal', topicName); +const topicRoutePath = clusterTopicPath(); describe('Breadcrumb component', () => { const setupComponent = (pathname: string, routePath: string) => render( - + + +
+ + , { pathname } ); @@ -28,6 +36,6 @@ describe('Breadcrumb component', () => { it('renders the topic overview', async () => { const { getByText } = setupComponent(topicPath, topicRoutePath); expect(getByText('Topics')).toBeInTheDocument(); - expect(getByText('topic-name')).toBeInTheDocument(); + expect(getByText(topicName)).toBeInTheDocument(); }); }); From b4b3beacb07b1c1a420fad7401af422b7ba0bc44 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Tue, 24 May 2022 17:46:13 +0400 Subject: [PATCH 33/61] Refactor Redirects --- .../src/components/Cluster/Cluster.tsx | 8 ++++---- .../src/components/Connect/Connect.tsx | 14 ++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx index 735258c75ce..99a7740a63e 100644 --- a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx +++ b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx @@ -12,6 +12,7 @@ import { clusterConnectsPath, clusterConsumerGroupsPath, clusterKsqlDbPath, + clusterPath, clusterSchemasPath, clusterTopicsPath, } from 'lib/paths'; @@ -105,10 +106,9 @@ const Cluster: React.FC = () => { )} - + + + diff --git a/kafka-ui-react-app/src/components/Connect/Connect.tsx b/kafka-ui-react-app/src/components/Connect/Connect.tsx index 676ef782cdc..1076d9ead3c 100644 --- a/kafka-ui-react-app/src/components/Connect/Connect.tsx +++ b/kafka-ui-react-app/src/components/Connect/Connect.tsx @@ -38,14 +38,12 @@ const Connect: React.FC = () => ( - - + + + + + +
); From 746d53ee89f248a5769286d2bdd441aea288dcf6 Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Fri, 27 May 2022 14:23:12 +0400 Subject: [PATCH 34/61] WIP React Router v6 migration --- kafka-ui-react-app/package-lock.json | 117 ++++--------- kafka-ui-react-app/package.json | 2 +- kafka-ui-react-app/src/components/App.tsx | 35 ++-- .../src/components/Brokers/Brokers.tsx | 4 +- .../Brokers/__test__/Brokers.spec.tsx | 10 +- .../src/components/Cluster/Cluster.tsx | 122 +++++++------ .../Cluster/__tests__/Cluster.spec.tsx | 10 +- .../src/components/Connect/Connect.tsx | 50 ++++-- .../Connect/Details/Actions/Actions.tsx | 9 +- .../Actions/__tests__/Actions.spec.tsx | 111 +++++------- .../Connect/Details/Config/Config.tsx | 2 +- .../Details/Config/__test__/Config.spec.tsx | 43 +++-- .../components/Connect/Details/Details.tsx | 38 ++-- .../Details/Tasks/ListItem/ListItem.tsx | 2 +- .../ListItem/__tests__/ListItem.spec.tsx | 19 +- .../Details/Tasks/__tests__/Tasks.spec.tsx | 32 ++-- .../Details/__tests__/Details.spec.tsx | 47 ++--- .../src/components/Connect/Edit/Edit.tsx | 8 +- .../Connect/Edit/__tests__/Edit.spec.tsx | 22 +-- .../src/components/Connect/List/List.tsx | 4 +- .../src/components/Connect/List/ListItem.tsx | 5 +- .../src/components/Connect/New/New.tsx | 14 +- .../Connect/New/__tests__/New.spec.tsx | 13 +- .../Connect/__tests__/Connect.spec.tsx | 7 +- .../ConsumerGroups/ConsumerGroups.tsx | 45 +++-- .../ConsumerGroups/Details/Details.tsx | 15 +- .../Details/ResetOffsets/ResetOffsets.tsx | 15 +- .../__test__/ResetOffsets.spec.tsx | 17 +- .../__test__/TopicContents.spec.tsx | 17 +- .../Details/__tests__/Details.spec.tsx | 13 +- .../Details/__tests__/ListItem.spec.tsx | 17 +- .../components/ConsumerGroups/List/List.tsx | 4 +- .../__test__/ConsumerGroups.spec.tsx | 29 +--- .../src/components/KsqlDb/KsqlDb.tsx | 32 ++-- .../src/components/KsqlDb/List/List.tsx | 4 +- .../KsqlDb/List/__test__/List.spec.tsx | 15 +- .../KsqlDb/List/__test__/ListItem.spec.tsx | 15 +- .../src/components/KsqlDb/Query/Query.tsx | 3 +- .../KsqlDb/Query/__test__/Query.spec.tsx | 9 +- .../KsqlDb/__test__/KsqlDb.spec.tsx | 2 +- .../src/components/Nav/ClusterMenu.tsx | 4 - .../src/components/Nav/ClusterMenuItem.tsx | 11 +- .../src/components/Nav/Nav.styled.ts | 9 +- kafka-ui-react-app/src/components/Nav/Nav.tsx | 2 +- .../Nav/__tests__/ClusterMenu.spec.tsx | 6 +- .../components/Schemas/Details/Details.tsx | 9 +- .../Schemas/Details/__test__/Details.spec.tsx | 9 +- .../src/components/Schemas/Diff/Diff.tsx | 23 ++- .../Schemas/Diff/__test__/Diff.spec.tsx | 24 +-- .../src/components/Schemas/Edit/Edit.tsx | 10 +- .../Schemas/Edit/__tests__/Edit.spec.tsx | 13 +- .../GlobalSchemaSelector.tsx | 3 +- .../__test__/GlobalSchemaSelector.spec.tsx | 9 +- .../src/components/Schemas/List/List.tsx | 4 +- .../src/components/Schemas/List/ListItem.tsx | 2 +- .../Schemas/List/__test__/List.spec.tsx | 9 +- .../src/components/Schemas/New/New.tsx | 10 +- .../Schemas/New/__test__/New.spec.tsx | 9 +- .../src/components/Schemas/Schemas.tsx | 79 +++++---- .../Schemas/__test__/Schemas.spec.tsx | 9 +- .../src/components/Topics/List/List.tsx | 16 +- .../Topics/List/TopicsTableCells.tsx | 2 +- .../Topics/List/__tests__/List.spec.tsx | 77 ++++----- .../src/components/Topics/New/New.tsx | 17 +- .../Topics/New/__test__/New.spec.tsx | 70 ++++---- .../ConsumerGroups/TopicConsumerGroups.tsx | 3 +- .../__test__/TopicConsumerGroups.spec.tsx | 30 ++-- .../Topics/Topic/Details/Details.tsx | 161 ++++++++--------- .../Details/Messages/Filters/Filters.tsx | 11 +- .../Filters/__tests__/Filters.spec.tsx | 6 +- .../Messages/__test__/Messages.spec.tsx | 12 +- .../Messages/__test__/MessagesTable.spec.tsx | 17 +- .../Topic/Details/Overview/Overview.tsx | 3 +- .../Overview/__test__/Overview.spec.tsx | 27 ++- .../Topic/Details/Settings/Settings.tsx | 3 +- .../Settings/__test__/Settings.spec.tsx | 22 +-- .../Topic/Details/__test__/Details.spec.tsx | 35 ++-- .../Topic/Edit/DangerZone/DangerZone.tsx | 3 +- .../DangerZone/__test__/DangerZone.spec.tsx | 33 ++-- .../src/components/Topics/Topic/Edit/Edit.tsx | 11 +- .../Topics/Topic/Edit/__test__/Edit.spec.tsx | 39 ++--- .../Topics/Topic/SendMessage/SendMessage.tsx | 9 +- .../SendMessage/__test__/SendMessage.spec.tsx | 21 +-- .../src/components/Topics/Topic/Topic.tsx | 21 +-- .../Topics/Topic/__tests__/Topic.spec.tsx | 16 +- .../src/components/Topics/Topics.tsx | 58 ++++--- .../Topics/__tests__/Topics.spec.tsx | 9 +- .../src/components/__tests__/App.spec.tsx | 4 +- .../common/Breadcrumb/Breadcrumb.route.tsx | 9 +- .../Breadcrumb/__tests__/Breadcrumb.spec.tsx | 9 +- .../src/components/common/Button/Button.tsx | 2 +- .../Pagination/__tests__/Pagination.spec.tsx | 17 +- .../src/lib/__test__/paths.spec.ts | 95 +++++----- kafka-ui-react-app/src/lib/hooks/useSearch.ts | 18 +- kafka-ui-react-app/src/lib/paths.ts | 162 +++++++++++------- kafka-ui-react-app/src/lib/testHelpers.tsx | 26 ++- 96 files changed, 1129 insertions(+), 1177 deletions(-) diff --git a/kafka-ui-react-app/package-lock.json b/kafka-ui-react-app/package-lock.json index afff9bf5238..dccf512e7c8 100644 --- a/kafka-ui-react-app/package-lock.json +++ b/kafka-ui-react-app/package-lock.json @@ -36,7 +36,7 @@ "react-multi-select-component": "^4.0.6", "react-redux": "^7.2.6", "react-router": "^5.2.0", - "react-router-dom": "^5.3.1", + "react-router-dom": "^6.3.0", "redux": "^4.1.1", "redux-thunk": "^2.3.0", "sass": "^1.43.4", @@ -16158,7 +16158,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", - "dev": true, "dependencies": { "@babel/runtime": "^7.7.6" } @@ -24856,11 +24855,11 @@ } }, "node_modules/react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.3.tgz", + "integrity": "sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w==", "dependencies": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "hoist-non-react-statics": "^3.1.0", "loose-envify": "^1.3.1", @@ -24876,53 +24875,27 @@ } }, "node_modules/react-router-dom": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.1.tgz", - "integrity": "sha512-f0pj/gMAbv9e8gahTmCEY20oFhxhrmHwYeIwH5EO5xu0qme+wXtsdB8YfUOAZzUz4VaXmb58m3ceiLtjMhqYmQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.3.1", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "history": "^5.2.0", + "react-router": "6.3.0" }, "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/react-router-dom/node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" + "react": ">=16.8", + "react-dom": ">=16.8" } }, "node_modules/react-router-dom/node_modules/react-router": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.1.tgz", - "integrity": "sha512-v+zwjqb7bakqgF+wMVKlAPTca/cEmPOvQ9zt7gpSNyPXau1+0qvuYZ5BWzzNDP1y6s15zDwgb9rPN63+SIniRQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "history": "^5.2.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8" } }, "node_modules/react-router/node_modules/history": { @@ -40798,7 +40771,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", - "dev": true, "requires": { "@babel/runtime": "^7.7.6" } @@ -47310,11 +47282,11 @@ "dev": true }, "react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.3.tgz", + "integrity": "sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w==", "requires": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "hoist-non-react-statics": "^3.1.0", "loose-envify": "^1.3.1", @@ -47342,47 +47314,20 @@ } }, "react-router-dom": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.1.tgz", - "integrity": "sha512-f0pj/gMAbv9e8gahTmCEY20oFhxhrmHwYeIwH5EO5xu0qme+wXtsdB8YfUOAZzUz4VaXmb58m3ceiLtjMhqYmQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.3.1", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "history": "^5.2.0", + "react-router": "6.3.0" }, "dependencies": { - "history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "requires": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, "react-router": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.1.tgz", - "integrity": "sha512-v+zwjqb7bakqgF+wMVKlAPTca/cEmPOvQ9zt7gpSNyPXau1+0qvuYZ5BWzzNDP1y6s15zDwgb9rPN63+SIniRQ==", - "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", + "requires": { + "history": "^5.2.0" } } } diff --git a/kafka-ui-react-app/package.json b/kafka-ui-react-app/package.json index 9c7c6490329..7f01e4a5e01 100644 --- a/kafka-ui-react-app/package.json +++ b/kafka-ui-react-app/package.json @@ -32,7 +32,7 @@ "react-multi-select-component": "^4.0.6", "react-redux": "^7.2.6", "react-router": "^5.2.0", - "react-router-dom": "^5.3.1", + "react-router-dom": "^6.3.0", "redux": "^4.1.1", "redux-thunk": "^2.3.0", "sass": "^1.43.4", diff --git a/kafka-ui-react-app/src/components/App.tsx b/kafka-ui-react-app/src/components/App.tsx index ad479d40346..fd06b1534e6 100644 --- a/kafka-ui-react-app/src/components/App.tsx +++ b/kafka-ui-react-app/src/components/App.tsx @@ -1,7 +1,13 @@ import React from 'react'; -import { Switch, Route, useLocation } from 'react-router-dom'; +import { Routes, Route, useLocation } from 'react-router-dom'; import { GIT_TAG, GIT_COMMIT } from 'lib/constants'; -import { clusterPath } from 'lib/paths'; +import { + clusterBrokersPath, + clusterConsumerGroupsPath, + clusterPath, + clusterTopicsPath, + getNonExactPath, +} from 'lib/paths'; import Nav from 'components/Nav/Nav'; import PageLoader from 'components/common/PageLoader/PageLoader'; import Dashboard from 'components/Dashboard/Dashboard'; @@ -19,6 +25,10 @@ import { import * as S from './App.styled'; import Logo from './common/Logo/Logo'; +import { BreadcrumbRoute } from './common/Breadcrumb/Breadcrumb.route'; +import Brokers from './Brokers/Brokers'; +import Topics from './Topics/Topics'; +import ConsumersGroups from './ConsumerGroups/ConsumerGroups'; const App: React.FC = () => { const dispatch = useAppDispatch(); @@ -82,14 +92,19 @@ const App: React.FC = () => { aria-label="Overlay" /> {areClustersFulfilled ? ( - - - - - - - - + + {['/', '/ui', '/ui/clusters'].map((path) => ( + } + /> + ))} + } + /> + ) : ( )} diff --git a/kafka-ui-react-app/src/components/Brokers/Brokers.tsx b/kafka-ui-react-app/src/components/Brokers/Brokers.tsx index 75e3d3be6ae..d64f03da26a 100644 --- a/kafka-ui-react-app/src/components/Brokers/Brokers.tsx +++ b/kafka-ui-react-app/src/components/Brokers/Brokers.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { ClusterName } from 'redux/interfaces'; import useInterval from 'lib/hooks/useInterval'; import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted'; import { useParams } from 'react-router-dom'; @@ -8,6 +7,7 @@ import { Table } from 'components/common/table/Table/Table.styled'; import PageHeading from 'components/common/PageHeading/PageHeading'; import * as Metrics from 'components/common/Metrics'; import { useAppDispatch, useAppSelector } from 'lib/hooks/redux'; +import { ClusterNameRoute } from 'lib/paths'; import { fetchBrokers, fetchClusterStats, @@ -16,7 +16,7 @@ import { const Brokers: React.FC = () => { const dispatch = useAppDispatch(); - const { clusterName } = useParams<{ clusterName: ClusterName }>(); + const { clusterName } = useParams() as ClusterNameRoute; const { brokerCount, activeControllers, diff --git a/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx b/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx index edf1f0b7183..5d4f40e7b80 100644 --- a/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx +++ b/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx @@ -1,8 +1,8 @@ import React from 'react'; import Brokers from 'components/Brokers/Brokers'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { screen, waitFor } from '@testing-library/dom'; -import { Route } from 'react-router-dom'; +import { Route, Routes } from 'react-router-dom'; import { clusterBrokersPath } from 'lib/paths'; import fetchMock from 'fetch-mock'; import { clusterStatsPayload } from 'redux/reducers/brokers/__test__/fixtures'; @@ -18,11 +18,11 @@ describe('Brokers Component', () => { const renderComponent = () => render( - + - , + , { - pathname: clusterBrokersPath(clusterName), + initialEntries: [clusterBrokersPath(clusterName)], } ); diff --git a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx index 99a7740a63e..0409f8c9a08 100644 --- a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx +++ b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx @@ -1,20 +1,21 @@ import React from 'react'; import { useSelector } from 'react-redux'; -import { Switch, Redirect, useParams, Route } from 'react-router-dom'; +import { Routes, Navigate, useParams, Route, Outlet } from 'react-router-dom'; import { ClusterFeaturesEnum } from 'generated-sources'; import { getClustersFeatures, getClustersReadonlyStatus, } from 'redux/reducers/clusters/clustersSlice'; import { - clusterBrokersPath, - clusterConnectorsPath, - clusterConnectsPath, - clusterConsumerGroupsPath, - clusterKsqlDbPath, - clusterPath, - clusterSchemasPath, - clusterTopicsPath, + clusterBrokerRelativePath, + clusterConnectorsRelativePath, + clusterConnectsRelativePath, + clusterConsumerGroupsRelativePath, + clusterKsqlDbRelativePath, + ClusterNameRoute, + clusterSchemasRelativePath, + clusterTopicsRelativePath, + getNonExactPath, } from 'lib/paths'; import Topics from 'components/Topics/Topics'; import Schemas from 'components/Schemas/Schemas'; @@ -28,7 +29,7 @@ import { BreadcrumbRoute } from 'components/common/Breadcrumb/Breadcrumb.route'; import { BreadcrumbProvider } from 'components/common/Breadcrumb/Breadcrumb.provider'; const Cluster: React.FC = () => { - const { clusterName } = useParams<{ clusterName: string }>(); + const { clusterName } = useParams() as ClusterNameRoute; const isReadOnly = useSelector(getClustersReadonlyStatus(clusterName)); const features = useSelector(getClustersFeatures(clusterName)); @@ -62,54 +63,77 @@ const Cluster: React.FC = () => { - - - - - - - - - - - - - - - - - {hasSchemaRegistryConfigured && ( - + + - +
-
- )} - {hasKafkaConnectConfigured && ( - + } + /> + - +
-
- )} - {hasKafkaConnectConfigured && ( - + } + /> + - + - + } + /> + {hasSchemaRegistryConfigured && ( + + + + } + /> + )} + {hasKafkaConnectConfigured && ( + + + + } + /> + )} + {hasKafkaConnectConfigured && ( + + + + } + /> )} {hasKsqlDbConfigured && ( - - - - - + + + + } + /> )} - - - - + } + /> + + ); diff --git a/kafka-ui-react-app/src/components/Cluster/__tests__/Cluster.spec.tsx b/kafka-ui-react-app/src/components/Cluster/__tests__/Cluster.spec.tsx index cb26131eef7..3b3cb4bcfc8 100644 --- a/kafka-ui-react-app/src/components/Cluster/__tests__/Cluster.spec.tsx +++ b/kafka-ui-react-app/src/components/Cluster/__tests__/Cluster.spec.tsx @@ -1,17 +1,17 @@ import React from 'react'; -import { Route } from 'react-router-dom'; import { ClusterFeaturesEnum } from 'generated-sources'; import { store } from 'redux/store'; import { onlineClusterPayload } from 'redux/reducers/clusters/__test__/fixtures'; import Cluster from 'components/Cluster/Cluster'; import { fetchClusters } from 'redux/reducers/clusters/clustersSlice'; import { screen } from '@testing-library/react'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterBrokersPath, clusterConnectsPath, clusterConsumerGroupsPath, clusterKsqlDbPath, + clusterPath, clusterSchemasPath, clusterTopicsPath, } from 'lib/paths'; @@ -29,10 +29,10 @@ jest.mock('components/KsqlDb/KsqlDb', () => () =>
KsqlDb
); describe('Cluster', () => { const renderComponent = (pathname: string) => render( - + - , - { pathname, store } + , + { initialEntries: [pathname], store } ); it('renders Brokers', () => { diff --git a/kafka-ui-react-app/src/components/Connect/Connect.tsx b/kafka-ui-react-app/src/components/Connect/Connect.tsx index 1076d9ead3c..07813470e90 100644 --- a/kafka-ui-react-app/src/components/Connect/Connect.tsx +++ b/kafka-ui-react-app/src/components/Connect/Connect.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Switch, Redirect, Route } from 'react-router-dom'; +import { Navigate, Routes, Route } from 'react-router-dom'; import { clusterConnectorsPath, clusterConnectsPath, @@ -16,36 +16,48 @@ import DetailsContainer from './Details/DetailsContainer'; import EditContainer from './Edit/EditContainer'; const Connect: React.FC = () => ( -
- - + + - - + } + /> + - - + } + /> + - - + } + /> + - - - - - - - - -
+ } + /> + } + /> + } + /> + ); export default Connect; diff --git a/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx b/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx index 591876dd830..1381fa73e06 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useHistory, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import { ConnectorState, ConnectorAction } from 'generated-sources'; import { ClusterName, ConnectName, ConnectorName } from 'redux/interfaces'; import { @@ -59,9 +59,10 @@ const Actions: React.FC = ({ isConnectorActionRunning, }) => { const { clusterName, connectName, connectorName } = - useParams(); + useParams() as RouterParamsClusterConnectConnector; + + const navigate = useNavigate(); - const history = useHistory(); const [ isDeleteConnectorConfirmationVisible, setIsDeleteConnectorConfirmationVisible, @@ -70,7 +71,7 @@ const Actions: React.FC = ({ const deleteConnectorHandler = async () => { try { await deleteConnector({ clusterName, connectName, connectorName }); - history.push(clusterConnectorsPath(clusterName)); + navigate(clusterConnectorsPath(clusterName)); } catch { // do not redirect } diff --git a/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx index 2483fa64245..8533ffcc953 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { Route } from 'react-router-dom'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConnectConnectorPath, clusterConnectorsPath } from 'lib/paths'; import ActionsContainer from 'components/Connect/Details/Actions/ActionsContainer'; import Actions, { @@ -19,9 +18,7 @@ const cancelMock = jest.fn(); jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), - useHistory: () => ({ - push: mockHistoryPush, - }), + useNavigate: () => mockHistoryPush, })); jest.mock( @@ -66,7 +63,7 @@ describe('Actions', () => { const connectorName = 'my-connector'; const confirmationModal = (props: Partial = {}) => ( - + @@ -87,11 +84,11 @@ describe('Actions', () => { Confirm - + ); const component = (props: Partial = {}) => ( - + { isConnectorActionRunning={false} {...props} /> - + ); it('renders buttons when paused', () => { render(component({ connectorStatus: ConnectorState.PAUSED }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(screen.getAllByRole('button').length).toEqual(6); expect(screen.getByText('Resume')).toBeInTheDocument(); @@ -123,11 +118,9 @@ describe('Actions', () => { it('renders buttons when failed', () => { render(component({ connectorStatus: ConnectorState.FAILED }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(screen.getAllByRole('button').length).toEqual(5); @@ -139,11 +132,9 @@ describe('Actions', () => { it('renders buttons when unassigned', () => { render(component({ connectorStatus: ConnectorState.UNASSIGNED }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(screen.getAllByRole('button').length).toEqual(5); expect(screen.queryByText('Resume')).not.toBeInTheDocument(); @@ -153,11 +144,9 @@ describe('Actions', () => { it('renders buttons when running connector action', () => { render(component({ connectorStatus: ConnectorState.RUNNING }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(screen.getAllByRole('button').length).toEqual(6); expect(screen.queryByText('Resume')).not.toBeInTheDocument(); @@ -168,11 +157,9 @@ describe('Actions', () => { it('opens confirmation modal when delete button clicked', () => { render(component({ deleteConnector }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); userEvent.click(screen.getByRole('button', { name: 'Delete' })); @@ -183,11 +170,9 @@ describe('Actions', () => { it('closes when cancel button clicked', () => { render(confirmationModal({ isOpen: true }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); const cancelBtn = screen.getByRole('button', { name: 'Cancel' }); userEvent.click(cancelBtn); @@ -196,11 +181,9 @@ describe('Actions', () => { it('calls deleteConnector when confirm button clicked', () => { render(confirmationModal({ isOpen: true }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); const confirmBtn = screen.getByRole('button', { name: 'Confirm' }); userEvent.click(confirmBtn); @@ -214,11 +197,9 @@ describe('Actions', () => { it('redirects after delete', async () => { render(confirmationModal({ isOpen: true }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); const confirmBtn = screen.getByRole('button', { name: 'Confirm' }); userEvent.click(confirmBtn); @@ -231,11 +212,9 @@ describe('Actions', () => { it('calls restartConnector when restart button clicked', () => { const restartConnector = jest.fn(); render(component({ restartConnector }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); userEvent.click( screen.getByRole('button', { name: 'Restart Connector' }) @@ -256,11 +235,13 @@ describe('Actions', () => { pauseConnector, }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath( + clusterName, + connectName, + connectorName + ), + ], } ); userEvent.click(screen.getByRole('button', { name: 'Pause' })); @@ -280,11 +261,13 @@ describe('Actions', () => { resumeConnector, }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath( + clusterName, + connectName, + connectorName + ), + ], } ); userEvent.click(screen.getByRole('button', { name: 'Resume' })); diff --git a/kafka-ui-react-app/src/components/Connect/Details/Config/Config.tsx b/kafka-ui-react-app/src/components/Connect/Details/Config/Config.tsx index fa0bbdf6d2e..3313d5d27d1 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Config/Config.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Config/Config.tsx @@ -31,7 +31,7 @@ const Config: React.FC = ({ config, }) => { const { clusterName, connectName, connectorName } = - useParams(); + useParams() as RouterParamsClusterConnectConnector; React.useEffect(() => { fetchConfig({ clusterName, connectName, connectorName }); diff --git a/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx index 6c043696590..6f8fa909513 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { render } from 'lib/testHelpers'; -import { Route } from 'react-router-dom'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConnectConnectorConfigPath } from 'lib/paths'; import Config, { ConfigProps } from 'components/Connect/Details/Config/Config'; import { connector } from 'redux/reducers/connect/__test__/fixtures'; @@ -15,34 +14,38 @@ describe('Config', () => { const connectorName = 'my-connector'; const component = (props: Partial = {}) => ( - + - + ); it('to be in the document when fetching config', () => { render(component({ isConfigFetching: true }), { - pathname: clusterConnectConnectorConfigPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorConfigPath( + clusterName, + connectName, + connectorName + ), + ], }); expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); it('is empty when no config', () => { const { container } = render(component({ config: null }), { - pathname: clusterConnectConnectorConfigPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorConfigPath( + clusterName, + connectName, + connectorName + ), + ], }); expect(container).toBeEmptyDOMElement(); }); @@ -50,11 +53,13 @@ describe('Config', () => { it('fetches config on mount', () => { const fetchConfig = jest.fn(); render(component({ fetchConfig }), { - pathname: clusterConnectConnectorConfigPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorConfigPath( + clusterName, + connectName, + connectorName + ), + ], }); expect(fetchConfig).toHaveBeenCalledTimes(1); expect(fetchConfig).toHaveBeenCalledWith({ diff --git a/kafka-ui-react-app/src/components/Connect/Details/Details.tsx b/kafka-ui-react-app/src/components/Connect/Details/Details.tsx index 77e6f39d1f3..30bc9d61235 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Details.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { NavLink, Route, Switch, useParams } from 'react-router-dom'; +import { NavLink, Route, Routes, useParams } from 'react-router-dom'; import { Connector, Task } from 'generated-sources'; import { ClusterName, ConnectName, ConnectorName } from 'redux/interfaces'; import { @@ -42,7 +42,7 @@ const Details: React.FC = ({ connector, }) => { const { clusterName, connectName, connectorName } = - useParams(); + useParams() as RouterParamsClusterConnectConnector; React.useEffect(() => { fetchConnector({ clusterName, connectName, connectorName }); @@ -65,50 +65,50 @@ const Details: React.FC = ({ (isActive ? 'is-active' : '')} > Overview (isActive ? 'is-active' : '')} > Tasks (isActive ? 'is-active' : '')} > Config - - - - - - - - - - - + + } + /> + } + /> + } + /> +
); }; diff --git a/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/ListItem.tsx b/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/ListItem.tsx index 8d27222af2f..478e3dad112 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/ListItem.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/ListItem.tsx @@ -21,7 +21,7 @@ export interface ListItemProps { const ListItem: React.FC = ({ task, restartTask }) => { const { clusterName, connectName, connectorName } = - useParams(); + useParams() as RouterParamsClusterConnectConnector; const restartTaskHandler = async () => { await restartTask({ diff --git a/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx index baaa58d6152..8796281cc6e 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Tasks/ListItem/__tests__/ListItem.spec.tsx @@ -1,11 +1,10 @@ import React from 'react'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConnectConnectorTasksPath } from 'lib/paths'; import ListItem, { ListItemProps, } from 'components/Connect/Details/Tasks/ListItem/ListItem'; import { tasks } from 'redux/reducers/connect/__test__/fixtures'; -import { Route } from 'react-router-dom'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -18,19 +17,21 @@ const task = tasks[0]; const renderComponent = (props: ListItemProps = { task, restartTask }) => { return render( - +
-
, + , { - pathname: clusterConnectConnectorTasksPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorTasksPath( + clusterName, + connectName, + connectorName + ), + ], } ); }; diff --git a/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx index dbacfc4a82f..b3dfb82d293 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx @@ -1,10 +1,9 @@ import React from 'react'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConnectConnectorTasksPath } from 'lib/paths'; import TasksContainer from 'components/Connect/Details/Tasks/TasksContainer'; import Tasks, { TasksProps } from 'components/Connect/Details/Tasks/Tasks'; import { tasks } from 'redux/reducers/connect/__test__/fixtures'; -import { Route } from 'react-router-dom'; import { screen } from '@testing-library/dom'; jest.mock( @@ -19,24 +18,25 @@ describe('Tasks', () => { }); describe('view', () => { - const pathname = clusterConnectConnectorTasksPath(); const clusterName = 'my-cluster'; const connectName = 'my-connect'; const connectorName = 'my-connector'; const setupWrapper = (props: Partial = {}) => ( - + - + ); it('to be in the document when fetching tasks', () => { render(setupWrapper({ areTasksFetching: true }), { - pathname: clusterConnectConnectorTasksPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorTasksPath( + clusterName, + connectName, + connectorName + ), + ], }); expect(screen.getByRole('progressbar')).toBeInTheDocument(); expect(screen.queryByRole('table')).not.toBeInTheDocument(); @@ -44,11 +44,13 @@ describe('Tasks', () => { it('to be in the document when no tasks', () => { render(setupWrapper({ tasks: [] }), { - pathname: clusterConnectConnectorTasksPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorTasksPath( + clusterName, + connectName, + connectorName + ), + ], }); expect(screen.getByRole('table')).toBeInTheDocument(); expect(screen.getByText('No tasks found')).toBeInTheDocument(); diff --git a/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx b/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx index 816e26af320..a043bb370fc 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { Route } from 'react-router-dom'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConnectConnectorPath } from 'lib/paths'; import Details, { DetailsProps } from 'components/Connect/Details/Details'; import { connector, tasks } from 'redux/reducers/connect/__test__/fixtures'; @@ -33,7 +32,7 @@ describe('Details', () => { const connectorName = 'my-connector'; const setupWrapper = (props: Partial = {}) => ( - +
{ tasks={tasks} {...props} /> - + ); it('renders progressbar when fetching connector', () => { render(setupWrapper({ isConnectorFetching: true }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(screen.getByRole('progressbar')).toBeInTheDocument(); @@ -61,11 +58,9 @@ describe('Details', () => { it('renders progressbar when fetching tasks', () => { render(setupWrapper({ areTasksFetching: true }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(screen.getByRole('progressbar')).toBeInTheDocument(); expect(screen.queryByRole('navigation')).not.toBeInTheDocument(); @@ -73,11 +68,9 @@ describe('Details', () => { it('is empty when no connector', () => { const { container } = render(setupWrapper({ connector: null }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(container).toBeEmptyDOMElement(); }); @@ -85,11 +78,9 @@ describe('Details', () => { it('fetches connector on mount', () => { const fetchConnector = jest.fn(); render(setupWrapper({ fetchConnector }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(fetchConnector).toHaveBeenCalledTimes(1); expect(fetchConnector).toHaveBeenCalledWith({ @@ -102,11 +93,9 @@ describe('Details', () => { it('fetches tasks on mount', () => { const fetchTasks = jest.fn(); render(setupWrapper({ fetchTasks }), { - pathname: clusterConnectConnectorPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorPath(clusterName, connectName, connectorName), + ], }); expect(fetchTasks).toHaveBeenCalledTimes(1); expect(fetchTasks).toHaveBeenCalledWith({ diff --git a/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx b/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx index 6c25714e204..db5931a01d2 100644 --- a/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx +++ b/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useHistory, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import { Controller, useForm } from 'react-hook-form'; import { ErrorMessage } from '@hookform/error-message'; import { yupResolver } from '@hookform/resolvers/yup'; @@ -54,8 +54,8 @@ const Edit: React.FC = ({ updateConfig, }) => { const { clusterName, connectName, connectorName } = - useParams(); - const history = useHistory(); + useParams() as RouterParamsClusterConnectConnector; + const navigate = useNavigate(); const { handleSubmit, control, @@ -87,7 +87,7 @@ const Edit: React.FC = ({ connectorConfig: JSON.parse(values.config.trim()), }); if (connector) { - history.push( + navigate( clusterConnectConnectorConfigPath( clusterName, connectName, diff --git a/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx b/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx index 13f1d673186..6a4b7e723b9 100644 --- a/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConnectConnectorConfigPath, clusterConnectConnectorEditPath, @@ -17,9 +17,7 @@ jest.mock('components/common/Editor/Editor', () => 'mock-Editor'); const mockHistoryPush = jest.fn(); jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), - useHistory: () => ({ - push: mockHistoryPush, - }), + useNavigate: () => mockHistoryPush, })); describe('Edit', () => { @@ -30,7 +28,7 @@ describe('Edit', () => { const renderComponent = (props: Partial = {}) => render( - + { updateConfig={jest.fn()} {...props} /> - , + , { - pathname: clusterConnectConnectorEditPath( - clusterName, - connectName, - connectorName - ), + initialEntries: [ + clusterConnectConnectorEditPath( + clusterName, + connectName, + connectorName + ), + ], } ); diff --git a/kafka-ui-react-app/src/components/Connect/List/List.tsx b/kafka-ui-react-app/src/components/Connect/List/List.tsx index d7e911c1901..0f9cb1df722 100644 --- a/kafka-ui-react-app/src/components/Connect/List/List.tsx +++ b/kafka-ui-react-app/src/components/Connect/List/List.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useParams } from 'react-router-dom'; import { Connect, FullConnectorInfo } from 'generated-sources'; import { ClusterName, ConnectorSearch } from 'redux/interfaces'; -import { clusterConnectorNewPath } from 'lib/paths'; +import { clusterConnectorNewPath, ClusterNameRoute } from 'lib/paths'; import ClusterContext from 'components/contexts/ClusterContext'; import PageLoader from 'components/common/PageLoader/PageLoader'; import Search from 'components/common/Search/Search'; @@ -40,7 +40,7 @@ const List: React.FC = ({ setConnectorSearch, }) => { const { isReadOnly } = React.useContext(ClusterContext); - const { clusterName } = useParams<{ clusterName: string }>(); + const { clusterName } = useParams() as ClusterNameRoute; React.useEffect(() => { fetchConnects(clusterName); diff --git a/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx b/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx index ff0f3805f19..50f8242e23e 100644 --- a/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx +++ b/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx @@ -60,10 +60,7 @@ const ListItem: React.FC = ({ return ( - + {name} diff --git a/kafka-ui-react-app/src/components/Connect/New/New.tsx b/kafka-ui-react-app/src/components/Connect/New/New.tsx index 96b2a4f7e44..b90246c7afd 100644 --- a/kafka-ui-react-app/src/components/Connect/New/New.tsx +++ b/kafka-ui-react-app/src/components/Connect/New/New.tsx @@ -1,11 +1,11 @@ import React from 'react'; -import { useHistory, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import { Controller, FormProvider, useForm } from 'react-hook-form'; import { ErrorMessage } from '@hookform/error-message'; import { yupResolver } from '@hookform/resolvers/yup'; import { Connect, Connector, NewConnector } from 'generated-sources'; import { ClusterName, ConnectName } from 'redux/interfaces'; -import { clusterConnectConnectorPath } from 'lib/paths'; +import { clusterConnectConnectorPath, ClusterNameRoute } from 'lib/paths'; import yup from 'lib/yupExtended'; import Editor from 'components/common/Editor/Editor'; import PageLoader from 'components/common/PageLoader/PageLoader'; @@ -23,10 +23,6 @@ const validationSchema = yup.object().shape({ config: yup.string().required().isJsonObject(), }); -interface RouterParams { - clusterName: ClusterName; -} - export interface NewProps { fetchConnects(clusterName: ClusterName): unknown; areConnectsFetching: boolean; @@ -50,8 +46,8 @@ const New: React.FC = ({ connects, createConnector, }) => { - const { clusterName } = useParams(); - const history = useHistory(); + const { clusterName } = useParams() as ClusterNameRoute; + const navigate = useNavigate(); const methods = useForm({ mode: 'onTouched', @@ -96,7 +92,7 @@ const New: React.FC = ({ }); if (connector) { - history.push( + navigate( clusterConnectConnectorPath( clusterName, connector.connect, diff --git a/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx b/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx index bba865e33bc..94cba3f5a24 100644 --- a/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx @@ -1,12 +1,11 @@ import React from 'react'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConnectConnectorPath, clusterConnectorNewPath, } from 'lib/paths'; import New, { NewProps } from 'components/Connect/New/New'; import { connects, connector } from 'redux/reducers/connect/__test__/fixtures'; -import { Route } from 'react-router-dom'; import { fireEvent, screen, act } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ControllerRenderProps } from 'react-hook-form'; @@ -22,9 +21,7 @@ jest.mock( const mockHistoryPush = jest.fn(); jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), - useHistory: () => ({ - push: mockHistoryPush, - }), + useNavigate: () => mockHistoryPush, })); describe('New', () => { @@ -51,7 +48,7 @@ describe('New', () => { const renderComponent = (props: Partial = {}) => render( - + { createConnector={jest.fn()} {...props} /> - , - { pathname: clusterConnectorNewPath(clusterName) } + , + { initialEntries: [clusterConnectorNewPath(clusterName)] } ); it('fetches connects on mount', async () => { diff --git a/kafka-ui-react-app/src/components/Connect/__tests__/Connect.spec.tsx b/kafka-ui-react-app/src/components/Connect/__tests__/Connect.spec.tsx index 8708a2cea34..530b50e4e56 100644 --- a/kafka-ui-react-app/src/components/Connect/__tests__/Connect.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/__tests__/Connect.spec.tsx @@ -26,12 +26,7 @@ jest.mock('components/Connect/Edit/EditContainer', () => () => ( describe('Connect', () => { const renderComponent = (pathname: string) => - render( - - - , - { pathname, store } - ); + render(, { initialEntries: [pathname], store }); it('renders ListContainer', () => { renderComponent(clusterConnectorsPath('my-cluster')); diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx index 01637207796..023d0e57fc2 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Route, Switch } from 'react-router-dom'; +import { Route, Routes } from 'react-router-dom'; import Details from 'components/ConsumerGroups/Details/Details'; import ListContainer from 'components/ConsumerGroups/List/ListContainer'; import ResetOffsets from 'components/ConsumerGroups/Details/ResetOffsets/ResetOffsets'; @@ -12,23 +12,32 @@ import { const ConsumerGroups: React.FC = () => { return ( - - - - - - - - -
- - - - - - - - + + + + + } + /> + +
+ + } + /> + + + + } + /> + ); }; diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx index b298fa83137..f0d27047148 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx @@ -1,13 +1,12 @@ import React from 'react'; -import { ClusterName } from 'redux/interfaces'; import { clusterConsumerGroupResetOffsetsPath, clusterConsumerGroupsPath, + ClusterGroupParam, } from 'lib/paths'; -import { ConsumerGroupID } from 'redux/interfaces/consumerGroup'; import PageLoader from 'components/common/PageLoader/PageLoader'; import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal'; -import { useHistory, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import ClusterContext from 'components/contexts/ClusterContext'; import PageHeading from 'components/common/PageHeading/PageHeading'; import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon'; @@ -31,10 +30,10 @@ import getTagColor from 'components/common/Tag/getTagColor'; import ListItem from './ListItem'; const Details: React.FC = () => { - const history = useHistory(); + const navigate = useNavigate(); const { isReadOnly } = React.useContext(ClusterContext); const { consumerGroupID, clusterName } = - useParams<{ consumerGroupID: ConsumerGroupID; clusterName: ClusterName }>(); + useParams() as ClusterGroupParam; const dispatch = useAppDispatch(); const consumerGroup = useAppSelector((state) => selectById(state, consumerGroupID) @@ -55,12 +54,12 @@ const Details: React.FC = () => { }; React.useEffect(() => { if (isDeleted) { - history.push(clusterConsumerGroupsPath(clusterName)); + navigate(clusterConsumerGroupsPath(clusterName)); } - }, [clusterName, history, isDeleted]); + }, [clusterName, navigate, isDeleted]); const onResetOffsets = () => { - history.push( + navigate( clusterConsumerGroupResetOffsetsPath(clusterName, consumerGroupID) ); }; diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx index fecb1f57628..1283367e0c7 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx @@ -1,5 +1,5 @@ import { ConsumerGroupOffsetsResetType } from 'generated-sources'; -import { clusterConsumerGroupDetailsPath } from 'lib/paths'; +import { clusterConsumerGroupDetailsPath, ClusterGroupParam } from 'lib/paths'; import React from 'react'; import { Controller, @@ -7,7 +7,6 @@ import { useFieldArray, useForm, } from 'react-hook-form'; -import { ClusterName, ConsumerGroupID } from 'redux/interfaces'; import MultiSelect from 'react-multi-select-component'; import { Option } from 'react-multi-select-component/dist/lib/interfaces'; import DatePicker from 'react-datepicker'; @@ -15,7 +14,7 @@ import 'react-datepicker/dist/react-datepicker.css'; import { groupBy } from 'lodash'; import PageLoader from 'components/common/PageLoader/PageLoader'; import { ErrorMessage } from '@hookform/error-message'; -import { useHistory, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import Select from 'components/common/Select/Select'; import { InputLabel } from 'components/common/Input/InputLabel.styled'; import { Button } from 'components/common/Button/Button'; @@ -49,7 +48,7 @@ interface FormType { const ResetOffsets: React.FC = () => { const dispatch = useAppDispatch(); const { consumerGroupID, clusterName } = - useParams<{ consumerGroupID: ConsumerGroupID; clusterName: ClusterName }>(); + useParams() as ClusterGroupParam; const consumerGroup = useAppSelector((state) => selectById(state, consumerGroupID) ); @@ -162,15 +161,13 @@ const ResetOffsets: React.FC = () => { } }; - const history = useHistory(); + const navigate = useNavigate(); React.useEffect(() => { if (isOffsetReseted) { dispatch(resetLoaderById('consumerGroups/resetConsumerGroupOffsets')); - history.push( - clusterConsumerGroupDetailsPath(clusterName, consumerGroupID) - ); + navigate(clusterConsumerGroupDetailsPath(clusterName, consumerGroupID)); } - }, [clusterName, consumerGroupID, dispatch, history, isOffsetReseted]); + }, [clusterName, consumerGroupID, dispatch, navigate, isOffsetReseted]); if (!isFetched || !consumerGroup) { return ; diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx index 6532fd946aa..963600b7976 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/__test__/ResetOffsets.spec.tsx @@ -1,9 +1,8 @@ import React from 'react'; import fetchMock from 'fetch-mock'; -import { Route } from 'react-router-dom'; import { act, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConsumerGroupResetOffsetsPath } from 'lib/paths'; import { consumerGroupPayload } from 'redux/reducers/consumerGroups/__test__/fixtures'; import ResetOffsets from 'components/ConsumerGroups/Details/ResetOffsets/ResetOffsets'; @@ -13,14 +12,16 @@ const { groupId } = consumerGroupPayload; const renderComponent = () => render( - + - , + , { - pathname: clusterConsumerGroupResetOffsetsPath( - clusterName, - consumerGroupPayload.groupId - ), + initialEntries: [ + clusterConsumerGroupResetOffsetsPath( + clusterName, + consumerGroupPayload.groupId + ), + ], } ); diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx index 7ce5b198d72..e1a10b7cd57 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/TopicContents/__test__/TopicContents.spec.tsx @@ -3,26 +3,27 @@ import { clusterConsumerGroupDetailsPath } from 'lib/paths'; import { screen } from '@testing-library/react'; import TopicContents from 'components/ConsumerGroups/Details/TopicContents/TopicContents'; import { consumerGroupPayload } from 'redux/reducers/consumerGroups/__test__/fixtures'; -import { render } from 'lib/testHelpers'; -import { Route } from 'react-router-dom'; +import { render, WithRoute } from 'lib/testHelpers'; import { ConsumerGroupTopicPartition } from 'generated-sources'; const clusterName = 'cluster1'; const renderComponent = (consumers: ConsumerGroupTopicPartition[] = []) => render( - +
-
, + , { - pathname: clusterConsumerGroupDetailsPath( - clusterName, - consumerGroupPayload.groupId - ), + initialEntries: [ + clusterConsumerGroupDetailsPath( + clusterName, + consumerGroupPayload.groupId + ), + ], } ); diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx index 1d1a97d2eeb..76da20e308d 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx @@ -2,8 +2,7 @@ import Details from 'components/ConsumerGroups/Details/Details'; import React from 'react'; import fetchMock from 'fetch-mock'; import { createMemoryHistory } from 'history'; -import { render } from 'lib/testHelpers'; -import { Route, Router } from 'react-router-dom'; +import { render, WithRoute } from 'lib/testHelpers'; import { clusterConsumerGroupDetailsPath, clusterConsumerGroupResetOffsetsPath, @@ -23,13 +22,11 @@ const { groupId } = consumerGroupPayload; const history = createMemoryHistory(); const renderComponent = () => { - history.push(clusterConsumerGroupDetailsPath(clusterName, groupId)); render( - - -
- - + +
+ , + { initialEntries: [clusterConsumerGroupDetailsPath(clusterName, groupId)] } ); }; describe('Details component', () => { diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx index 86cd95e7346..5bbce7a9271 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx @@ -4,15 +4,14 @@ import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import ListItem from 'components/ConsumerGroups/Details/ListItem'; import { consumerGroupPayload } from 'redux/reducers/consumerGroups/__test__/fixtures'; -import { render } from 'lib/testHelpers'; -import { Route } from 'react-router-dom'; +import { render, WithRoute } from 'lib/testHelpers'; import { ConsumerGroupTopicPartition } from 'generated-sources'; const clusterName = 'cluster1'; const renderComponent = (consumers: ConsumerGroupTopicPartition[] = []) => render( - + />
-
, + , { - pathname: clusterConsumerGroupDetailsPath( - clusterName, - consumerGroupPayload.groupId - ), + initialEntries: [ + clusterConsumerGroupDetailsPath( + clusterName, + consumerGroupPayload.groupId + ), + ], } ); diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/List/List.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/List/List.tsx index 1286268d13d..3d04f9f61dc 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/List/List.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/List/List.tsx @@ -18,7 +18,7 @@ import { import usePagination from 'lib/hooks/usePagination'; import useSearch from 'lib/hooks/useSearch'; import { useAppDispatch } from 'lib/hooks/redux'; -import { ClusterName } from 'redux/interfaces'; +import { ClusterNameRoute } from 'lib/paths'; import { fetchConsumerGroupsPaged } from 'redux/reducers/consumerGroups/consumerGroupsSlice'; import PageLoader from 'components/common/PageLoader/PageLoader'; @@ -42,7 +42,7 @@ const List: React.FC = ({ const { page, perPage } = usePagination(); const [searchText, handleSearchText] = useSearch(); const dispatch = useAppDispatch(); - const { clusterName } = useParams<{ clusterName: ClusterName }>(); + const { clusterName } = useParams() as ClusterNameRoute; React.useEffect(() => { dispatch( diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/__test__/ConsumerGroups.spec.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/__test__/ConsumerGroups.spec.tsx index 33ab8f09c4c..22919aa7dfe 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/__test__/ConsumerGroups.spec.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/__test__/ConsumerGroups.spec.tsx @@ -11,27 +11,19 @@ import { consumerGroups, noConsumerGroupsResponse, } from 'redux/reducers/consumerGroups/__test__/fixtures'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import fetchMock from 'fetch-mock'; -import { Route, Router } from 'react-router-dom'; import { ConsumerGroupOrdering, SortOrder } from 'generated-sources'; -import { createMemoryHistory } from 'history'; const clusterName = 'cluster1'; -const historyMock = createMemoryHistory({ - initialEntries: [clusterConsumerGroupsPath(clusterName)], -}); - -const renderComponent = (history = historyMock) => +const renderComponent = (path?: string) => render( - - - - - , + + + , { - pathname: clusterConsumerGroupsPath(clusterName), + initialEntries: [path || clusterConsumerGroupsPath(clusterName)], } ); @@ -123,12 +115,9 @@ describe('ConsumerGroups', () => { } ); - const mockedHistory = createMemoryHistory({ - initialEntries: [ - `${clusterConsumerGroupsPath(clusterName)}?q=${searchText}`, - ], - }); - renderComponent(mockedHistory); + renderComponent( + `${clusterConsumerGroupsPath(clusterName)}?q=${searchText}` + ); await waitForElementToBeRemoved(() => screen.getByRole('progressbar')); await waitFor(() => expect(consumerGroupsMock.called()).toBeTruthy()); diff --git a/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx b/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx index c2c30a77b25..04149274d08 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/KsqlDb.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Route, Switch } from 'react-router-dom'; +import { Route, Routes } from 'react-router-dom'; import { clusterKsqlDbPath, clusterKsqlDbQueryPath } from 'lib/paths'; import List from 'components/KsqlDb/List/List'; import Query from 'components/KsqlDb/Query/Query'; @@ -7,18 +7,24 @@ import { BreadcrumbRoute } from 'components/common/Breadcrumb/Breadcrumb.route'; const KsqlDb: React.FC = () => { return ( - - - - - - - - - - - - + + + + + } + /> + + + + } + /> + ); }; diff --git a/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx b/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx index f2c85256304..b0200e373a2 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx @@ -6,7 +6,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; import { fetchKsqlDbTables } from 'redux/reducers/ksqlDb/ksqlDbSlice'; import { getKsqlDbTables } from 'redux/reducers/ksqlDb/selectors'; -import { clusterKsqlDbQueryPath } from 'lib/paths'; +import { clusterKsqlDbQueryPath, ClusterNameRoute } from 'lib/paths'; import PageHeading from 'components/common/PageHeading/PageHeading'; import { Table } from 'components/common/table/Table/Table.styled'; import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell'; @@ -25,7 +25,7 @@ const accessors = headers.map((header) => header.accessor); const List: FC = () => { const dispatch = useDispatch(); - const { clusterName } = useParams<{ clusterName: string }>(); + const { clusterName } = useParams() as ClusterNameRoute; const { rows, fetching, tablesCount, streamsCount } = useSelector(getKsqlDbTables); diff --git a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx index ce8f2a22fc7..b367a6117ce 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/List.spec.tsx @@ -1,23 +1,18 @@ import React from 'react'; import List from 'components/KsqlDb/List/List'; -import { Route, Router } from 'react-router-dom'; -import { createMemoryHistory } from 'history'; import { clusterKsqlDbPath } from 'lib/paths'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import fetchMock from 'fetch-mock'; import { screen, waitForElementToBeRemoved } from '@testing-library/dom'; -const history = createMemoryHistory(); const clusterName = 'local'; const renderComponent = () => { - history.push(clusterKsqlDbPath(clusterName)); render( - - - - - + + + , + { initialEntries: [clusterKsqlDbPath(clusterName)] } ); }; diff --git a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx index cd9b1bd067b..0942ee89185 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/List/__test__/ListItem.spec.tsx @@ -1,12 +1,9 @@ import React from 'react'; -import { Route, Router } from 'react-router-dom'; -import { createMemoryHistory } from 'history'; import { clusterKsqlDbPath } from 'lib/paths'; -import { render } from 'lib/testHelpers'; +import { render, WithRoute } from 'lib/testHelpers'; import { screen } from '@testing-library/dom'; import ListItem from 'components/KsqlDb/List/ListItem'; -const history = createMemoryHistory(); const clusterName = 'local'; const renderComponent = ({ @@ -16,13 +13,11 @@ const renderComponent = ({ accessors: string[]; data: Record; }) => { - history.push(clusterKsqlDbPath(clusterName)); render( - - - - - + + + , + { initialEntries: [clusterKsqlDbPath(clusterName)] } ); }; diff --git a/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx b/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx index 4b74ac4f3b3..83c6ae3a6b1 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx @@ -11,6 +11,7 @@ import { BASE_PARAMS } from 'lib/constants'; import { KsqlResponse, KsqlTableResponse } from 'generated-sources'; import { alertAdded, alertDissmissed } from 'redux/reducers/alerts/alertsSlice'; import { now } from 'lodash'; +import { ClusterNameRoute } from 'lib/paths'; import type { FormValues } from './QueryForm/QueryForm'; import * as S from './Query.styled'; @@ -61,7 +62,7 @@ export const getFormattedErrorFromTableData = ( }; const Query: FC = () => { - const { clusterName } = useParams<{ clusterName: string }>(); + const { clusterName } = useParams() as ClusterNameRoute; const sseRef = React.useRef<{ sse: EventSource | null; isOpen: boolean }>({ sse: null, diff --git a/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx b/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx index 2ee200d1a49..fd2cacfd7f1 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/Query/__test__/Query.spec.tsx @@ -1,4 +1,4 @@ -import { render, EventSourceMock } from 'lib/testHelpers'; +import { render, EventSourceMock, WithRoute } from 'lib/testHelpers'; import React from 'react'; import Query, { getFormattedErrorFromTableData, @@ -6,18 +6,17 @@ import Query, { import { screen, within } from '@testing-library/dom'; import fetchMock from 'fetch-mock'; import userEvent from '@testing-library/user-event'; -import { Route } from 'react-router-dom'; import { clusterKsqlDbQueryPath } from 'lib/paths'; import { act } from '@testing-library/react'; const clusterName = 'testLocal'; const renderComponent = () => render( - + - , + , { - pathname: clusterKsqlDbQueryPath(clusterName), + initialEntries: [clusterKsqlDbQueryPath(clusterName)], } ); diff --git a/kafka-ui-react-app/src/components/KsqlDb/__test__/KsqlDb.spec.tsx b/kafka-ui-react-app/src/components/KsqlDb/__test__/KsqlDb.spec.tsx index f9d8e89876c..d157316b8f5 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/__test__/KsqlDb.spec.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/__test__/KsqlDb.spec.tsx @@ -7,7 +7,7 @@ import { clusterKsqlDbPath } from 'lib/paths'; describe('KsqlDb Component', () => { describe('KsqlDb', () => { it('to be in the document', () => { - render(, { pathname: clusterKsqlDbPath() }); + render(, { initialEntries: [clusterKsqlDbPath()] }); expect(screen.getByText('KSQL DB')).toBeInTheDocument(); expect(screen.getByText('Execute KSQL Request')).toBeInTheDocument(); }); diff --git a/kafka-ui-react-app/src/components/Nav/ClusterMenu.tsx b/kafka-ui-react-app/src/components/Nav/ClusterMenu.tsx index 1f82571e9bc..5299a37cfba 100644 --- a/kafka-ui-react-app/src/components/Nav/ClusterMenu.tsx +++ b/kafka-ui-react-app/src/components/Nav/ClusterMenu.tsx @@ -54,10 +54,6 @@ const ClusterMenu: React.FC = ({ - location.pathname.startsWith(clusterConnectsPath(name)) || - location.pathname.startsWith(clusterConnectorsPath(name)) - } /> )} {hasFeatureConfigured(ClusterFeaturesEnum.KSQL_DB) && ( diff --git a/kafka-ui-react-app/src/components/Nav/ClusterMenuItem.tsx b/kafka-ui-react-app/src/components/Nav/ClusterMenuItem.tsx index 15b3e599ac4..a70c1108d25 100644 --- a/kafka-ui-react-app/src/components/Nav/ClusterMenuItem.tsx +++ b/kafka-ui-react-app/src/components/Nav/ClusterMenuItem.tsx @@ -1,25 +1,26 @@ import React, { PropsWithChildren } from 'react'; -import { NavLinkProps } from 'react-router-dom'; import * as S from './Nav.styled'; export interface ClusterMenuItemProps { to: string; title?: string; - exact?: boolean; isTopLevel?: boolean; - isActive?: NavLinkProps['isActive']; } const ClusterMenuItem: React.FC> = ( props ) => { - const { to, title, children, exact, isTopLevel, isActive } = props; + const { to, title, children, isTopLevel } = props; if (to) { return ( - + (isActive ? 'is-active' : '')} + > {title} {children} diff --git a/kafka-ui-react-app/src/components/Nav/Nav.styled.ts b/kafka-ui-react-app/src/components/Nav/Nav.styled.ts index be0f3353f57..f057b14823e 100644 --- a/kafka-ui-react-app/src/components/Nav/Nav.styled.ts +++ b/kafka-ui-react-app/src/components/Nav/Nav.styled.ts @@ -14,8 +14,8 @@ export const Divider = styled.hr` height: 1px; `; -export const Link = styled(NavLink).attrs({ activeClassName: 'is-active' })( - ({ theme, activeClassName }) => css` +export const Link = styled(NavLink)( + ({ theme }) => css` width: 100%; padding: 0.5em 0.75em; cursor: pointer; @@ -28,11 +28,6 @@ export const Link = styled(NavLink).attrs({ activeClassName: 'is-active' })( background-color: ${theme.menu.backgroundColor.hover}; color: ${theme.menu.color.hover}; } - - &.${activeClassName} { - background-color: ${theme.menu.backgroundColor.active}; - color: ${theme.menu.color.active}; - } ` ); diff --git a/kafka-ui-react-app/src/components/Nav/Nav.tsx b/kafka-ui-react-app/src/components/Nav/Nav.tsx index 12108fe435f..a21a104ae8d 100644 --- a/kafka-ui-react-app/src/components/Nav/Nav.tsx +++ b/kafka-ui-react-app/src/components/Nav/Nav.tsx @@ -13,7 +13,7 @@ interface Props { const Nav: React.FC = ({ areClustersFulfilled, clusters }) => (