Skip to content

Commit 6c0265d

Browse files
committed
implement this
1 parent 7078d80 commit 6c0265d

File tree

2 files changed

+149
-1
lines changed

2 files changed

+149
-1
lines changed

redisinsight/ui/src/pages/rdi/pipeline-management/components/navigation/cards/ConfigurationCard.spec.tsx

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,20 @@ import ConfigurationCard, { ConfigurationCardProps } from './ConfigurationCard'
77

88
const mockedProps = mock<ConfigurationCardProps>()
99

10+
const mockUseSelector = jest.fn()
11+
jest.mock('react-redux', () => ({
12+
...jest.requireActual('react-redux'),
13+
useSelector: () => mockUseSelector(),
14+
}))
15+
1016
describe('ConfigurationCard', () => {
17+
beforeEach(() => {
18+
mockUseSelector.mockReturnValue({
19+
changes: {},
20+
configValidationErrors: [],
21+
})
22+
})
23+
1124
it('should render with correct title', () => {
1225
render(<ConfigurationCard {...instance(mockedProps)} />)
1326

@@ -49,4 +62,92 @@ describe('ConfigurationCard', () => {
4962
expect(card).toHaveAttribute('tabIndex', '0')
5063
expect(card).toHaveAttribute('role', 'button')
5164
})
65+
66+
describe('Changes indicator', () => {
67+
it('should not show changes indicator when no changes', () => {
68+
mockUseSelector.mockReturnValue({
69+
changes: {},
70+
configValidationErrors: [],
71+
})
72+
73+
render(<ConfigurationCard {...instance(mockedProps)} />)
74+
75+
expect(
76+
screen.queryByTestId('updated-configuration-highlight'),
77+
).not.toBeInTheDocument()
78+
})
79+
80+
it('should show changes indicator when config has changes', () => {
81+
mockUseSelector.mockReturnValue({
82+
changes: { config: 'modified' },
83+
configValidationErrors: [],
84+
})
85+
86+
render(<ConfigurationCard {...instance(mockedProps)} />)
87+
88+
expect(
89+
screen.getByTestId('updated-configuration-highlight'),
90+
).toBeInTheDocument()
91+
})
92+
})
93+
94+
describe('Validation errors', () => {
95+
it('should not show error icon when config is valid', () => {
96+
mockUseSelector.mockReturnValue({
97+
changes: {},
98+
configValidationErrors: [],
99+
})
100+
101+
render(<ConfigurationCard {...instance(mockedProps)} />)
102+
103+
expect(
104+
screen.queryByTestId('rdi-pipeline-nav__error-configuration'),
105+
).not.toBeInTheDocument()
106+
})
107+
108+
it('should show error icon when config has validation errors', () => {
109+
mockUseSelector.mockReturnValue({
110+
changes: {},
111+
configValidationErrors: [
112+
'Invalid configuration',
113+
'Missing required field',
114+
],
115+
})
116+
117+
render(<ConfigurationCard {...instance(mockedProps)} />)
118+
119+
expect(
120+
screen.getByTestId('rdi-pipeline-nav__error-configuration'),
121+
).toBeInTheDocument()
122+
})
123+
124+
it('should handle single validation error', () => {
125+
mockUseSelector.mockReturnValue({
126+
changes: {},
127+
configValidationErrors: ['Single error'],
128+
})
129+
130+
render(<ConfigurationCard {...instance(mockedProps)} />)
131+
132+
expect(
133+
screen.getByTestId('rdi-pipeline-nav__error-configuration'),
134+
).toBeInTheDocument()
135+
})
136+
})
137+
138+
it('should show both changes indicator and error icon when config has changes and errors', () => {
139+
mockUseSelector.mockReturnValue({
140+
changes: { config: 'modified' },
141+
configValidationErrors: ['Invalid configuration'],
142+
})
143+
144+
render(<ConfigurationCard {...instance(mockedProps)} />)
145+
146+
expect(
147+
screen.getByTestId('updated-configuration-highlight'),
148+
).toBeInTheDocument()
149+
expect(
150+
screen.getByTestId('rdi-pipeline-nav__error-configuration'),
151+
).toBeInTheDocument()
152+
})
52153
})

redisinsight/ui/src/pages/rdi/pipeline-management/components/navigation/cards/ConfigurationCard.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import React from 'react'
22
import { RdiPipelineTabs } from 'uiSrc/slices/interfaces'
3+
import { useSelector } from 'react-redux'
4+
5+
import { rdiPipelineSelector } from 'uiSrc/slices/rdi/pipeline'
6+
import { RiTooltip } from 'uiSrc/components'
7+
import { Indicator } from 'uiSrc/components/base/text/text.styles'
8+
import { Row } from 'uiSrc/components/base/layout/flex'
9+
import { Text } from 'uiSrc/components/base/text'
10+
import { Icon, ToastNotificationIcon } from 'uiSrc/components/base/icons'
11+
312
import BaseCard, { BaseCardProps } from './BaseCard'
13+
import ValidationErrorsList from '../../validation-errors-list/ValidationErrorsList'
414

515
export type ConfigurationCardProps = Omit<
616
BaseCardProps,
@@ -13,10 +23,15 @@ const ConfigurationCard = ({
1323
onSelect,
1424
isSelected,
1525
}: ConfigurationCardProps) => {
26+
const { changes, configValidationErrors } = useSelector(rdiPipelineSelector)
27+
1628
const handleClick = () => {
1729
onSelect(RdiPipelineTabs.Config)
1830
}
1931

32+
const hasChanges = !!changes.config
33+
const isValid = configValidationErrors.length === 0
34+
2035
return (
2136
<BaseCard
2237
title="Configuration"
@@ -25,7 +40,39 @@ const ConfigurationCard = ({
2540
onClick={handleClick}
2641
data-testid={`rdi-nav-btn-${RdiPipelineTabs.Config}`}
2742
>
28-
Configuration file
43+
<Row gap="s" align="center">
44+
{!hasChanges && <Indicator $color="transparent" />}
45+
46+
{hasChanges && (
47+
<RiTooltip
48+
content="This file contains undeployed changes."
49+
position="top"
50+
>
51+
<Indicator
52+
$color="informative"
53+
data-testid={`updated-configuration-highlight`}
54+
/>
55+
</RiTooltip>
56+
)}
57+
58+
<Text>Configuration file</Text>
59+
60+
{!isValid && (
61+
<RiTooltip
62+
position="right"
63+
content={
64+
<ValidationErrorsList validationErrors={configValidationErrors} />
65+
}
66+
>
67+
<Icon
68+
icon={ToastNotificationIcon}
69+
color="danger500"
70+
size="M"
71+
data-testid={`rdi-pipeline-nav__error-configuration`}
72+
/>
73+
</RiTooltip>
74+
)}
75+
</Row>
2976
</BaseCard>
3077
)
3178
}

0 commit comments

Comments
 (0)