Skip to content

Commit d48247c

Browse files
#RI-5156 - add internal link in recommendation
1 parent 4f75f17 commit d48247c

File tree

7 files changed

+99
-5
lines changed

7 files changed

+99
-5
lines changed

redisinsight/ui/src/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import FeatureFlagComponent from './feature-flag-component'
2929
import AutoRefresh from './auto-refresh'
3030
import { ModuleNotLoaded, FilterNotAvailable } from './messages'
3131
import RdiInstanceHeader from './rdi-instance-header'
32+
import InternalLink from './internal-link'
3233

3334
export { FullScreen } from './full-screen'
3435

@@ -71,4 +72,5 @@ export {
7172
FilterNotAvailable,
7273
AutoRefresh,
7374
RdiInstanceHeader,
75+
InternalLink,
7476
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react'
2+
import reactRouterDom from 'react-router-dom'
3+
import { instance, mock } from 'ts-mockito'
4+
import { render, screen, fireEvent } from 'uiSrc/utils/test-utils'
5+
6+
import InternalLink, { Props } from './InternalLink'
7+
8+
const mockedProps = mock<Props>()
9+
10+
jest.mock('react-router-dom', () => ({
11+
...jest.requireActual('react-router-dom'),
12+
useHistory: () => ({
13+
push: jest.fn,
14+
}),
15+
}))
16+
17+
describe('InternalLink', () => {
18+
it('should render', () => {
19+
expect(render(<InternalLink {...instance(mockedProps)} />)).toBeTruthy()
20+
})
21+
22+
it('should call history push with proper path', () => {
23+
const pushMock = jest.fn()
24+
reactRouterDom.useHistory = jest.fn().mockReturnValue({ push: pushMock })
25+
const onClickMock = jest.fn()
26+
27+
render(<InternalLink {...instance(mockedProps)} path="path" onClick={onClickMock} />)
28+
29+
fireEvent.click(screen.getByTestId('internal-link'))
30+
31+
expect(pushMock).toHaveBeenCalledTimes(1)
32+
expect(pushMock).toHaveBeenCalledWith('path')
33+
expect(onClickMock).toBeCalled()
34+
})
35+
})
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react'
2+
import { useHistory } from 'react-router-dom'
3+
import { EuiButton } from '@elastic/eui'
4+
5+
export interface Props {
6+
path: string
7+
text: string
8+
dataTestid?: string
9+
onClick?: () => void
10+
}
11+
12+
const InternalLink = (props: Props) => {
13+
const { path, text, onClick, dataTestid } = props
14+
15+
const history = useHistory()
16+
17+
const handleClick = () => {
18+
// can replace parameters here if needed (instanceId or rdiInstanceId)
19+
history.push(path)
20+
onClick?.()
21+
}
22+
return (
23+
<EuiButton
24+
fill
25+
color="secondary"
26+
size="s"
27+
onClick={handleClick}
28+
data-testid={dataTestid || 'internal-link'}
29+
>
30+
{text}
31+
</EuiButton>
32+
)
33+
}
34+
35+
export default InternalLink
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import InternalLink from './InternalLink'
2+
3+
export default InternalLink

redisinsight/ui/src/pages/rdi/pipeline-management/pages/job/Job.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ describe('Job', () => {
176176
event: TelemetryEvent.RDI_DEDICATED_EDITOR_CANCELLED,
177177
eventData: {
178178
rdiInstanceId: 'id',
179-
selectedLanguageSyntax: 'sql',
179+
selectedLanguageSyntax: 'sqliteFunctions',
180180
}
181181
});
182182
(sendEventTelemetry as jest.Mock).mockRestore()
@@ -197,7 +197,7 @@ describe('Job', () => {
197197
event: TelemetryEvent.RDI_DEDICATED_EDITOR_SAVED,
198198
eventData: {
199199
rdiInstanceId: 'id',
200-
selectedLanguageSyntax: 'sql',
200+
selectedLanguageSyntax: 'sqliteFunctions',
201201
}
202202
});
203203
(sendEventTelemetry as jest.Mock).mockRestore()

redisinsight/ui/src/utils/recommendation/utils.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
import { SpacerSize } from '@elastic/eui/src/components/spacer/spacer'
1212
import cx from 'classnames'
1313
import { IRecommendationsStatic, IRecommendationContent } from 'uiSrc/slices/interfaces/recommendations'
14-
import { OAuthConnectFreeDb, OAuthSsoHandlerDialog } from 'uiSrc/components'
14+
import { OAuthConnectFreeDb, OAuthSsoHandlerDialog, InternalLink } from 'uiSrc/components'
1515
import { OAuthSocialAction, OAuthSocialSource } from 'uiSrc/slices/interfaces'
1616
import CodeIcon from 'uiSrc/assets/img/code-changes.svg?react'
1717
import ConfigurationIcon from 'uiSrc/assets/img/configuration-changes.svg?react'
@@ -127,12 +127,21 @@ const renderContentElement = (
127127
external={false}
128128
data-testid={`link-${telemetry.telemetryName}-${idx}`}
129129
target="_blank"
130-
href={getUtmExternalLink(value.href, { medium: utmMedium, campaign: telemetry.telemetryName })}
130+
href={replaceVariables(value.href)}
131131
onClick={() => telemetry.onClickLink?.()}
132132
>
133133
{value.name}
134134
</EuiLink>
135135
)
136+
case 'internal-link':
137+
return (
138+
<InternalLink
139+
key={`${telemetry.telemetryName}-${idx}`}
140+
dataTestid={`internal-link-${telemetry.telemetryName}-${idx}`}
141+
path={value.path}
142+
text={value.name}
143+
/>
144+
)
136145
case 'link-sso':
137146
return (
138147
<OAuthSsoHandlerDialog>

redisinsight/ui/src/utils/tests/recommendation/utils.spec.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ const mockContent: IRecommendationContent[] = [
105105
type: 'link-sso',
106106
value: 'link-sso',
107107
},
108+
{
109+
type: 'internal-link',
110+
value: {
111+
path: '/some-path',
112+
name: 'name',
113+
},
114+
},
108115
]
109116

110117
describe('renderRecommendationBadgesLegend', () => {
@@ -183,6 +190,7 @@ describe('replaceVariables', () => {
183190
describe('renderRecommendationContent', () => {
184191
it('should render content', () => {
185192
const renderedContent = renderRecommendationContent(mockContent, undefined, { telemetryName: mockTelemetryName })
193+
// @ts-ignore
186194
render(renderedContent)
187195

188196
expect(screen.queryByTestId(`paragraph-${mockTelemetryName}-0`)).toBeInTheDocument()
@@ -192,6 +200,7 @@ describe('renderRecommendationContent', () => {
192200
expect(screen.queryByTestId(`list-${mockTelemetryName}-4`)).toBeInTheDocument()
193201
expect(screen.queryByTestId(`link-${mockTelemetryName}-6`)).toBeInTheDocument()
194202
expect(screen.queryByTestId(`code-link-${mockTelemetryName}-7`)).toBeInTheDocument()
203+
expect(screen.queryByTestId(`internal-link-${mockTelemetryName}-9`)).toBeInTheDocument()
195204
expect(screen.getByText('unknown')).toBeInTheDocument()
196205
})
197206

@@ -202,9 +211,10 @@ describe('renderRecommendationContent', () => {
202211
null,
203212
{ telemetryName: mockTelemetryName, onClickLink: onClickMock },
204213
)
214+
// @ts-ignore
205215
const { queryByTestId } = render(renderedContent)
206216

207-
fireEvent.click(queryByTestId(`link-${mockTelemetryName}-6`))
217+
fireEvent.click(queryByTestId(`link-${mockTelemetryName}-6`) as HTMLElement)
208218

209219
expect(onClickMock).toBeCalled()
210220
})

0 commit comments

Comments
 (0)