From 5db055604e46665f9ed3c75d306c60b2109c6ff1 Mon Sep 17 00:00:00 2001 From: ArtemHoruzhenko Date: Thu, 30 Oct 2025 12:39:09 +0200 Subject: [PATCH 1/4] RI-7687: use tabs for navigation in RDI (poc) --- .../app-navigation/AppNavigation.tsx | 12 +++++------ .../navigation-menu/hooks/useNavigation.ts | 20 +++++++++---------- .../src/pages/rdi/instance/InstancePage.tsx | 16 +++++++++++++-- .../InstancePageTemplate.tsx | 8 +++++++- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/redisinsight/ui/src/components/navigation-menu/app-navigation/AppNavigation.tsx b/redisinsight/ui/src/components/navigation-menu/app-navigation/AppNavigation.tsx index 5b9d6b3c4d..51167a3cc3 100644 --- a/redisinsight/ui/src/components/navigation-menu/app-navigation/AppNavigation.tsx +++ b/redisinsight/ui/src/components/navigation-menu/app-navigation/AppNavigation.tsx @@ -5,11 +5,11 @@ import { StyledAppNavigation, StyledAppNavigationContainer, } from './AppNavigation.styles' -import { useNavigation } from '../hooks/useNavigation' import FeatureFlagComponent from 'uiSrc/components/feature-flag-component/FeatureFlagComponent' import { FeatureFlags } from 'uiSrc/constants' import { OnboardingTourOptions } from 'uiSrc/components/onboarding-tour' import NavigationTabTrigger from './AppNavigationTabTrigger' +import { INavigations } from 'uiSrc/components/navigation-menu/navigation.types' type AppNavigationContainerProps = { children?: ReactNode @@ -41,18 +41,18 @@ const AppNavigationContainer = ({ ) export type AppNavigationProps = { + routes: INavigations[] actions?: ReactNode onChange?: (tabValue: string) => void } -const AppNavigation = ({ actions, onChange }: AppNavigationProps) => { - const { privateRoutes } = useNavigation() - const activeTab = privateRoutes.find((route) => route.isActivePage) +const AppNavigation = ({ actions, onChange, routes }: AppNavigationProps) => { + const activeTab = routes.find((route) => route.isActivePage) const navTabs: (TabInfo & { isActivePage: boolean featureFlag?: FeatureFlags onboard?: OnboardingTourOptions - })[] = privateRoutes.map((route) => ({ + })[] = routes.map((route) => ({ label: route.tooltipText, content: '', value: route.pageName, @@ -73,7 +73,7 @@ const AppNavigation = ({ actions, onChange }: AppNavigationProps) => { { - const tabNavItem = privateRoutes.find( + const tabNavItem = routes.find( (route) => route.pageName === tabValue, ) if (tabNavItem) { diff --git a/redisinsight/ui/src/components/navigation-menu/hooks/useNavigation.ts b/redisinsight/ui/src/components/navigation-menu/hooks/useNavigation.ts index 90cf1385f4..fb4dcdf776 100644 --- a/redisinsight/ui/src/components/navigation-menu/hooks/useNavigation.ts +++ b/redisinsight/ui/src/components/navigation-menu/hooks/useNavigation.ts @@ -147,16 +147,7 @@ export function useNavigation() { const privateRdiRoutes: INavigations[] = [ { - tooltipText: 'Pipeline Status', - pageName: PageNames.rdiStatistics, - ariaLabel: 'Pipeline Status page button', - onClick: () => handleGoPage(Pages.rdiStatistics(connectedRdiInstanceId)), - dataTestId: 'pipeline-status-page-btn', - isActivePage: activePage === `/${PageNames.rdiStatistics}`, - iconType: PipelineStatisticsIcon, - }, - { - tooltipText: 'Pipeline Management', + tooltipText: 'Pipeline', pageName: PageNames.rdiPipelineManagement, ariaLabel: 'Pipeline Management page button', onClick: () => @@ -165,6 +156,15 @@ export function useNavigation() { isActivePage: isPipelineManagementPath(), iconType: PipelineManagementIcon, }, + { + tooltipText: 'Analytics', + pageName: PageNames.rdiStatistics, + ariaLabel: 'Pipeline Status page button', + onClick: () => handleGoPage(Pages.rdiStatistics(connectedRdiInstanceId)), + dataTestId: 'pipeline-status-page-btn', + isActivePage: activePage === `/${PageNames.rdiStatistics}`, + iconType: PipelineStatisticsIcon, + }, ] const publicRoutes: INavigations[] = [ diff --git a/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx b/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx index 636179fe95..03437f6db8 100644 --- a/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react' +import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useHistory, useLocation, useParams } from 'react-router-dom' import { @@ -20,11 +20,13 @@ import { } from 'uiSrc/slices/instances/instances' import { RdiInstancePageTemplate } from 'uiSrc/templates' -import { RdiInstanceHeader } from 'uiSrc/components' +import { AppNavigation, RdiInstanceHeader } from 'uiSrc/components' import { Col, FlexItem } from 'uiSrc/components/base/layout/flex' import InstancePageRouter from './InstancePageRouter' import { RdiPipelineHeader } from './components' import styles from './styles.module.scss' +import { Nullable } from 'uiSrc/utils' +import { useNavigation } from 'uiSrc/components/navigation-menu/hooks/useNavigation' export interface Props { routes: IRoute[] @@ -39,6 +41,9 @@ const RdiInstancePage = ({ routes = [] }: Props) => { const { lastPage, contextRdiInstanceId } = useSelector(appContextSelector) const { data: rdiInstances } = useSelector(rdiInstancesSelector) const { data: dbInstances } = useSelector(dbInstancesSelector) + const { privateRdiRoutes } = useNavigation() + + const [actions, setActions] = useState>(null) useEffect(() => { if (!dbInstances?.length) { @@ -80,6 +85,13 @@ const RdiInstancePage = ({ routes = [] }: Props) => { + + setActions(null)} + routes={privateRdiRoutes} + /> + diff --git a/redisinsight/ui/src/templates/instance-page-template/InstancePageTemplate.tsx b/redisinsight/ui/src/templates/instance-page-template/InstancePageTemplate.tsx index 483f1cd97c..4761e14027 100644 --- a/redisinsight/ui/src/templates/instance-page-template/InstancePageTemplate.tsx +++ b/redisinsight/ui/src/templates/instance-page-template/InstancePageTemplate.tsx @@ -20,6 +20,7 @@ import { ImperativePanelGroupHandle } from 'uiSrc/components/base/layout/resize' import { AppNavigation } from 'uiSrc/components' import { AppNavigationActionsProvider } from 'uiSrc/contexts/AppNavigationActionsProvider' import { Nullable } from 'uiSrc/utils' +import { useNavigation } from 'uiSrc/components/navigation-menu/hooks/useNavigation' export const firstPanelId = 'main-component' export const secondPanelId = 'cli' @@ -51,6 +52,7 @@ const InstancePageTemplate = (props: Props) => { const { isShowCli, isShowHelper } = useSelector(cliSettingsSelector) const { isShowMonitor } = useSelector(monitorSelector) + const { privateRoutes } = useNavigation() const ref = useRef(null) @@ -92,7 +94,11 @@ const InstancePageTemplate = (props: Props) => { return ( <> - setActions(null)} /> + setActions(null)} + routes={privateRoutes} + /> Date: Thu, 30 Oct 2025 15:16:52 +0200 Subject: [PATCH 2/4] RI-7687: add tests and remove navigation from the left bar --- .../navigation-menu/NavigationMenu.spec.tsx | 12 ---- .../navigation-menu/NavigationMenu.tsx | 57 ---------------- .../pages/rdi/instance/InstancePage.spec.tsx | 68 ++++++++++++++++++- .../src/pages/rdi/instance/InstancePage.tsx | 2 +- 4 files changed, 68 insertions(+), 71 deletions(-) diff --git a/redisinsight/ui/src/components/navigation-menu/NavigationMenu.spec.tsx b/redisinsight/ui/src/components/navigation-menu/NavigationMenu.spec.tsx index a4ee8aa6bd..67e7d2cf25 100644 --- a/redisinsight/ui/src/components/navigation-menu/NavigationMenu.spec.tsx +++ b/redisinsight/ui/src/components/navigation-menu/NavigationMenu.spec.tsx @@ -186,18 +186,6 @@ describe('NavigationMenu', () => { }) }) - it('should render private routes with connectedRdiInstanceId', () => { - ;(appContextSelector as jest.Mock).mockImplementation(() => ({ - ...appContextSelector, - workspace: 'redisDataIntegration', - })) - - render() - - expect(screen.getByTestId('pipeline-status-page-btn')).toBeTruthy() - expect(screen.getByTestId('pipeline-management-page-btn')).toBeTruthy() - }) - describe('feature flags tests', () => { it('should show feature dependent items when feature flag is on', async () => { const initialStoreState = set( diff --git a/redisinsight/ui/src/components/navigation-menu/NavigationMenu.tsx b/redisinsight/ui/src/components/navigation-menu/NavigationMenu.tsx index bb65d3d227..266c9d950b 100644 --- a/redisinsight/ui/src/components/navigation-menu/NavigationMenu.tsx +++ b/redisinsight/ui/src/components/navigation-menu/NavigationMenu.tsx @@ -4,10 +4,8 @@ import React from 'react' import { FeatureFlags } from 'uiSrc/constants' import { EXTERNAL_LINKS } from 'uiSrc/constants/links' -import { renderOnboardingTourWithChild } from 'uiSrc/utils/onboarding' import { FeatureFlagComponent } from 'uiSrc/components' -import { RiBadge } from 'uiSrc/components/base/display/badge/RiBadge' import { SideBar, SideBarContainer, @@ -29,63 +27,11 @@ import styles from './styles.module.scss' const NavigationMenu = () => { const { - privateRdiRoutes, isRdiWorkspace, publicRoutes, - getAdditionPropsForHighlighting, highlightedPages, - connectedRdiInstanceId, } = useNavigation() - const renderNavItem = (nav: INavigations) => { - const fragment = ( - - {renderOnboardingTourWithChild( - -
- - - - {nav.isBeta && ( - - )} -
-
, - { options: nav.onboard }, - nav.isActivePage, - `ob-${nav.tooltipText}`, - )} -
- ) - - return nav.featureFlag ? ( - - {fragment} - - ) : ( - fragment - ) - } - const renderPublicNavItem = (nav: INavigations) => { const fragment = ( { > - {connectedRdiInstanceId && - isRdiWorkspace && - privateRdiRoutes.map(renderNavItem)} diff --git a/redisinsight/ui/src/pages/rdi/instance/InstancePage.spec.tsx b/redisinsight/ui/src/pages/rdi/instance/InstancePage.spec.tsx index 465a57e873..1655aaf148 100644 --- a/redisinsight/ui/src/pages/rdi/instance/InstancePage.spec.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/InstancePage.spec.tsx @@ -3,7 +3,13 @@ import React from 'react' import reactRouterDom, { BrowserRouter } from 'react-router-dom' import { instance, mock } from 'ts-mockito' -import { act, cleanup, mockedStore, render } from 'uiSrc/utils/test-utils' +import { + act, + cleanup, + mockedStore, + render, + userEvent, +} from 'uiSrc/utils/test-utils' import { resetKeys, resetPatternKeysData } from 'uiSrc/slices/browser/keys' import { setMonitorInitialState } from 'uiSrc/slices/cli/monitor' import { setInitialPubSubState } from 'uiSrc/slices/pubsub/pubsub' @@ -203,6 +209,35 @@ describe('InstancePage', () => { ) }) + it('should navigate to rdi pipeline management page via clicking on navigation', async () => { + const pushMock = jest.fn() + reactRouterDom.useHistory = jest.fn().mockReturnValue({ + push: pushMock, + block: jest.fn(() => jest.fn()), + }) + + reactRouterDom.useLocation = jest + .fn() + .mockReturnValue({ pathname: Pages.rdiStatistics(RDI_INSTANCE_ID_MOCK) }) + + const { getByRole } = render( + + + , + ) + expect(pushMock).not.toHaveBeenCalledWith( + Pages.rdiPipelineManagement(RDI_INSTANCE_ID_MOCK), + ) + const analyticsTab = getByRole('tab', { name: 'Analytics' }) + expect(analyticsTab).toBeInTheDocument() + + await userEvent.click(analyticsTab) + + expect(pushMock).not.toHaveBeenCalledWith( + Pages.rdiPipelineManagement(RDI_INSTANCE_ID_MOCK), + ) + }) + it('should redirect to rdi pipeline statistics page', async () => { ;(appContextSelector as jest.Mock).mockReturnValue({ contextRdiInstanceId: RDI_INSTANCE_ID_MOCK, @@ -230,4 +265,35 @@ describe('InstancePage', () => { Pages.rdiStatistics(RDI_INSTANCE_ID_MOCK), ) }) + + it('should navigate to rdi pipeline analytics page via clicking on navigation', async () => { + const pushMock = jest.fn() + reactRouterDom.useHistory = jest.fn().mockReturnValue({ + push: pushMock, + block: jest.fn(() => jest.fn()), + }) + + reactRouterDom.useLocation = jest + .fn() + .mockReturnValue({ + pathname: Pages.rdiPipelineManagement(RDI_INSTANCE_ID_MOCK), + }) + + const { getByRole } = render( + + + , + ) + expect(pushMock).not.toHaveBeenCalledWith( + Pages.rdiStatistics(RDI_INSTANCE_ID_MOCK), + ) + const pipelineTab = getByRole('tab', { name: 'Pipeline' }) + expect(pipelineTab).toBeInTheDocument() + + await userEvent.click(pipelineTab) + + expect(pushMock).not.toHaveBeenCalledWith( + Pages.rdiStatistics(RDI_INSTANCE_ID_MOCK), + ) + }) }) diff --git a/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx b/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx index 03437f6db8..9491ae710c 100644 --- a/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx @@ -36,12 +36,12 @@ const RdiInstancePage = ({ routes = [] }: Props) => { const dispatch = useDispatch() const history = useHistory() const { pathname } = useLocation() + const { privateRdiRoutes } = useNavigation() const { rdiInstanceId } = useParams<{ rdiInstanceId: string }>() const { lastPage, contextRdiInstanceId } = useSelector(appContextSelector) const { data: rdiInstances } = useSelector(rdiInstancesSelector) const { data: dbInstances } = useSelector(dbInstancesSelector) - const { privateRdiRoutes } = useNavigation() const [actions, setActions] = useState>(null) From ec0526153f907c4abb83ccbe3f1b8310f3dbae84 Mon Sep 17 00:00:00 2001 From: ArtemHoruzhenko Date: Thu, 30 Oct 2025 18:30:12 +0200 Subject: [PATCH 3/4] RI-7687: rework pipeline header --- .../components/header/RdiPipelineHeader.tsx | 19 +++++--- .../DeployPipelineButton.tsx | 3 +- .../ResetPipelineButton.tsx | 14 +++--- .../StartPipelineButton.tsx | 3 +- .../StopPipelineButton.tsx | 3 +- .../CurrentPipelineStatus.tsx | 43 +++++++++++-------- .../styles.module.scss | 27 ------------ .../pipeline-actions/PipelineActions.tsx | 13 +++++- .../components/header/styles.module.scss | 8 ---- 9 files changed, 58 insertions(+), 75 deletions(-) delete mode 100644 redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/styles.module.scss delete mode 100644 redisinsight/ui/src/pages/rdi/instance/components/header/styles.module.scss diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/RdiPipelineHeader.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/RdiPipelineHeader.tsx index 2507431a82..02720c0195 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/RdiPipelineHeader.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/RdiPipelineHeader.tsx @@ -11,7 +11,16 @@ import { FlexItem, Row } from 'uiSrc/components/base/layout/flex' import CurrentPipelineStatus from './components/current-pipeline-status' import PipelineActions from './components/pipeline-actions' -import styles from './styles.module.scss' +import styled from 'styled-components' +import { Theme } from 'uiSrc/components/base/theme/types' + +const StyledRdiPipelineHeader = styled(Row)` + padding: 0 16px; + border-bottom: 4px solid + ${({ theme }: { theme: Theme }) => + theme.components.tabs.variants.default.tabsLine.color}; + height: 58px; +` const RdiPipelineHeader = () => { const [headerLoading, setHeaderLoading] = useState(true) @@ -50,11 +59,7 @@ const RdiPipelineHeader = () => { : undefined return ( - + { collectorStatus={collectorStatus} pipelineStatus={pipelineStatus} /> - + ) } diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/deploy-pipeline-button/DeployPipelineButton.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/deploy-pipeline-button/DeployPipelineButton.tsx index 31a7b20ab4..23c088f72f 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/deploy-pipeline-button/DeployPipelineButton.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/deploy-pipeline-button/DeployPipelineButton.tsx @@ -117,14 +117,13 @@ const DeployPipelineButton = ({ loading, disabled, onReset }: Props) => { }} button={ - Deploy Pipeline + Deploy } > diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.tsx index 6d5cbe22ad..cdd5351bff 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.tsx @@ -1,10 +1,10 @@ import React from 'react' -import { RiResetIcon } from 'uiSrc/components/base/icons' import { Spacer } from 'uiSrc/components/base/layout/spacer' -import { SecondaryButton } from 'uiSrc/components/base/forms/buttons' import { RiTooltip } from 'uiSrc/components' import styles from '../styles.module.scss' +import { Button, TextButton } from '@redis-ui/components' +import { ResetIcon } from '@redis-ui/icons' export interface PipelineButtonProps { onClick: () => void @@ -35,17 +35,15 @@ const ResetPipelineButton = ({ } anchorClassName={disabled || loading ? styles.disabled : styles.tooltip} > - - Reset Pipeline - + + Reset + ) diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/start-pipeline-button/StartPipelineButton.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/start-pipeline-button/StartPipelineButton.tsx index f5039dbb4c..b9c2a8c2cb 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/start-pipeline-button/StartPipelineButton.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/start-pipeline-button/StartPipelineButton.tsx @@ -17,14 +17,13 @@ const StartPipelineButton = ({ > - Start Pipeline + Start ) diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/stop-pipeline-button/StopPipelineButton.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/stop-pipeline-button/StopPipelineButton.tsx index b12c023a1e..a24e55b5ba 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/stop-pipeline-button/StopPipelineButton.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/stop-pipeline-button/StopPipelineButton.tsx @@ -17,14 +17,13 @@ const StopPipelineButton = ({ > - Stop Pipeline + Stop ) diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/CurrentPipelineStatus.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/CurrentPipelineStatus.tsx index 015837eef7..0e51cf5b4f 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/CurrentPipelineStatus.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/CurrentPipelineStatus.tsx @@ -6,7 +6,8 @@ import { IconProps } from 'uiSrc/components/base/icons' import { Title } from 'uiSrc/components/base/text/Title' import { Loader } from 'uiSrc/components/base/display' import { RiTooltip } from 'uiSrc/components' -import styles from './styles.module.scss' +import { FlexItem, Row } from 'uiSrc/components/base/layout/flex' +import { Text } from 'uiSrc/components/base/text' export interface Props { pipelineState?: PipelineState @@ -57,22 +58,30 @@ const CurrentPipelineStatus = ({ const errorTooltipContent = statusError && formatLongName(statusError) return ( -
- Pipeline State: - {headerLoading ? ( - - ) : ( - -
- - {stateInfo.label} -
-
- )} -
+ + + Pipeline state: + + + {headerLoading ? ( + + ) : ( + + + + {stateInfo.label} + + + )} + + ) } diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/styles.module.scss b/redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/styles.module.scss deleted file mode 100644 index d762c0e75d..0000000000 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/current-pipeline-status/styles.module.scss +++ /dev/null @@ -1,27 +0,0 @@ -.stateBadge { - background-color: var(--euiColorEmptyShade); - padding: 2px 4px; - margin-left: 4px; - display: flex; - align-items: center; - gap: 4px; - border-radius: 4px; - - font-size: 12px; - font-weight: 500; - line-height: 14.4px; - - svg { - width: 20px; - height: 20px; - } -} - -.stateWrapper { - display: flex; - align-items: center; -} - -.tooltip { - cursor: pointer; -} diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.tsx index b4cf73b8df..55d698ce69 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.tsx @@ -28,6 +28,14 @@ import ResetPipelineButton from '../buttons/reset-pipeline-button' import RdiConfigFileActionMenu from '../rdi-config-file-action-menu' import StopPipelineButton from '../buttons/stop-pipeline-button' import StartPipelineButton from '../buttons/start-pipeline-button/StartPipelineButton' +import styled from 'styled-components' +import { Theme } from 'uiSrc/components/base/theme/types' + +const VerticalDelimiter = styled(FlexItem)` + border: ${({ theme }: { theme: Theme }) => + theme.components.appBar.separator}; + align-self: stretch; +` export interface Props { collectorStatus?: CollectorStatus @@ -149,7 +157,7 @@ const PipelineActions = ({ collectorStatus, pipelineStatus }: Props) => { const disabled = deployLoading || actionLoading return ( - + { loading={isLoadingBtn(PipelineAction.Reset)} /> + {collectorStatus === CollectorStatus.Ready ? ( { onReset={resetPipeline} /> - + diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/styles.module.scss b/redisinsight/ui/src/pages/rdi/instance/components/header/styles.module.scss deleted file mode 100644 index c750620c24..0000000000 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/styles.module.scss +++ /dev/null @@ -1,8 +0,0 @@ -:global(.euiPanel).popover { - max-width: 450px !important; - word-wrap: break-word; -} - -.wrapper { - padding: 0 16px 16px; -} From 6854970c0ad21611cf07b14733961e4d235c08af Mon Sep 17 00:00:00 2001 From: ArtemHoruzhenko Date: Fri, 31 Oct 2025 08:54:30 +0200 Subject: [PATCH 4/4] RI-7687: rework pipeline header - fix tests --- .../ResetPipelineButton.spec.tsx | 10 +++++-- .../pipeline-actions/PipelineActions.spec.tsx | 30 +++++++++++++------ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.spec.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.spec.tsx index 0db8b61a99..604854d27b 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.spec.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/buttons/reset-pipeline-button/ResetPipelineButton.spec.tsx @@ -1,6 +1,12 @@ import React from 'react' -import { fireEvent, render, screen, waitFor } from 'uiSrc/utils/test-utils' +import { + fireEvent, + render, + screen, + userEvent, + waitFor, +} from 'uiSrc/utils/test-utils' import ResetPipelineButton, { PipelineButtonProps } from './ResetPipelineButton' const mockedProps: PipelineButtonProps = { @@ -46,7 +52,7 @@ describe('ResetPipelineButton', () => { const onClick = jest.fn() render() - fireEvent.click(screen.getByTestId('reset-pipeline-btn')) + userEvent.click(screen.getByTestId('reset-pipeline-btn')) expect(onClick).not.toHaveBeenCalled() }) }) diff --git a/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.spec.tsx b/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.spec.tsx index c197c68c76..9cdcea2066 100644 --- a/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.spec.tsx +++ b/redisinsight/ui/src/pages/rdi/instance/components/header/components/pipeline-actions/PipelineActions.spec.tsx @@ -71,7 +71,7 @@ describe('PipelineActions', () => { collectorStatus={CollectorStatus.Ready} />, ) - expect(screen.getByText('Stop Pipeline')).toBeInTheDocument() + expect(screen.getByText('Stop')).toBeInTheDocument() }) it('should display startBtn if collectorStatus is not ready', () => { @@ -81,7 +81,7 @@ describe('PipelineActions', () => { collectorStatus={CollectorStatus.NotReady} />, ) - expect(screen.getByText('Start Pipeline')).toBeInTheDocument() + expect(screen.getByText('Start')).toBeInTheDocument() }) it('should display startBtn if collectorStatus is not ready', () => { @@ -91,7 +91,7 @@ describe('PipelineActions', () => { collectorStatus={CollectorStatus.NotReady} />, ) - expect(screen.getByText('Start Pipeline')).toBeInTheDocument() + expect(screen.getByText('Start')).toBeInTheDocument() }) it('should validate pipeline when schema, config, or jobs change', () => { @@ -211,9 +211,15 @@ describe('PipelineActions', () => { describe('validation with new schema parameters', () => { it('should pass monacoJobsSchema and jobNameSchema to validatePipeline when available', () => { - const mockMonacoJobsSchema = { type: 'object', properties: { task: { type: 'string' } } } - const mockJobNameSchema = { type: 'string', pattern: '^[a-zA-Z][a-zA-Z0-9_]*$' } - + const mockMonacoJobsSchema = { + type: 'object', + properties: { task: { type: 'string' } }, + } + const mockJobNameSchema = { + type: 'string', + pattern: '^[a-zA-Z][a-zA-Z0-9_]*$', + } + ;(validatePipeline as jest.Mock).mockReturnValue({ result: true, configValidationErrors: [], @@ -268,7 +274,7 @@ describe('PipelineActions', () => { it('should include monacoJobsSchema and jobNameSchema in dependency array for validation effect', () => { // This test verifies that the useEffect dependency array includes the new schema parameters // by checking that different schema values trigger different validatePipeline calls - + ;(validatePipeline as jest.Mock).mockReturnValue({ result: true, configValidationErrors: [], @@ -279,7 +285,10 @@ describe('PipelineActions', () => { ;(rdiPipelineSelector as jest.Mock).mockReturnValueOnce({ loading: false, schema: 'test-schema', - monacoJobsSchema: { type: 'object', properties: { task: { type: 'string' } } }, + monacoJobsSchema: { + type: 'object', + properties: { task: { type: 'string' } }, + }, jobNameSchema: { type: 'string', pattern: '^[a-zA-Z]+$' }, config: 'test-config', jobs: 'test-jobs', @@ -290,7 +299,10 @@ describe('PipelineActions', () => { // Verify that validatePipeline was called with all the correct parameters including schemas expect(validatePipeline).toHaveBeenCalledWith({ schema: 'test-schema', - monacoJobsSchema: { type: 'object', properties: { task: { type: 'string' } } }, + monacoJobsSchema: { + type: 'object', + properties: { task: { type: 'string' } }, + }, jobNameSchema: { type: 'string', pattern: '^[a-zA-Z]+$' }, config: 'test-config', jobs: 'test-jobs',