Skip to content

Commit 9f096b7

Browse files
#RI-4472 - remove very useful vote (#2097)
* #RI-4472 - remove very useful vote
1 parent e26e765 commit 9f096b7

File tree

12 files changed

+361
-216
lines changed

12 files changed

+361
-216
lines changed

redisinsight/ui/src/assets/img/icons/double_like.svg

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 9 additions & 0 deletions
Loading
Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import React from 'react'
22
import { cloneDeep } from 'lodash'
33
import { instance, mock } from 'ts-mockito'
4-
import { setRecommendationVote } from 'uiSrc/slices/analytics/dbAnalysis'
54
import { userSettingsConfigSelector } from 'uiSrc/slices/user/user-settings'
6-
import { Vote } from 'uiSrc/constants/recommendations'
75

86
import {
97
act,
@@ -47,51 +45,18 @@ describe('RecommendationVoting', () => {
4745
expect(render(<RecommendationVoting {...instance(mockedProps)} />)).toBeTruthy()
4846
})
4947

50-
it('should call "setRecommendationVote" action be called after click "very-useful-vote-btn"', () => {
51-
render(<RecommendationVoting {...instance(mockedProps)} />)
52-
expect(screen.queryByTestId('very-useful-vote-btn')).toBeInTheDocument()
53-
fireEvent.click(screen.getByTestId('very-useful-vote-btn'))
54-
55-
const expectedActions = [setRecommendationVote()]
56-
expect(store.getActions()).toEqual(expectedActions)
57-
})
58-
59-
it('should call "setRecommendationVote" action be called after click "useful-vote-btn"', () => {
60-
render(<RecommendationVoting {...instance(mockedProps)} />)
61-
fireEvent.click(screen.getByTestId('useful-vote-btn'))
62-
63-
const expectedActions = [setRecommendationVote()]
64-
expect(store.getActions()).toEqual(expectedActions)
65-
})
66-
67-
it('should call "setRecommendationVote" action be called after click "not-useful-vote-btn"', () => {
68-
render(<RecommendationVoting {...instance(mockedProps)} />)
69-
fireEvent.click(screen.getByTestId('not-useful-vote-btn'))
70-
71-
const expectedActions = [setRecommendationVote()]
72-
expect(store.getActions()).toEqual(expectedActions)
73-
})
74-
7548
it('should render popover after click "not-useful-vote-btn"', async () => {
7649
render(<RecommendationVoting {...instance(mockedProps)} />)
7750

7851
expect(document.querySelector('[data-test-subj="github-repo-link"]')).not.toBeInTheDocument()
7952

80-
fireEvent.click(screen.getByTestId('not-useful-vote-btn'))
53+
fireEvent.click(screen.getByTestId('not useful-vote-btn'))
8154
await waitForEuiPopoverVisible()
8255

8356
expect(document.querySelector('[data-test-subj="github-repo-link"]')).toHaveAttribute('href', 'https://github.com/RedisInsight/RedisInsight/issues/new/choose')
8457
})
8558

86-
it('should render component where all buttons are disabled"', async () => {
87-
render(<RecommendationVoting {...instance(mockedProps)} vote={Vote.Like} />)
88-
89-
expect(screen.getByTestId('very-useful-vote-btn')).toBeDisabled()
90-
expect(screen.getByTestId('useful-vote-btn')).toBeDisabled()
91-
expect(screen.getByTestId('not-useful-vote-btn')).toBeDisabled()
92-
})
93-
94-
it('should render popover after click "not-useful-vote-btn"', async () => {
59+
it('should render proper popover and btn should be disabled"', async () => {
9560
userSettingsConfigSelector.mockImplementation(() => ({
9661
agreements: {
9762
analytics: false,
@@ -100,10 +65,11 @@ describe('RecommendationVoting', () => {
10065
render(<RecommendationVoting {...instance(mockedProps)} />)
10166

10267
await act(async () => {
103-
fireEvent.mouseOver(screen.getByTestId('not-useful-vote-btn'))
68+
fireEvent.mouseOver(screen.getByTestId('not useful-vote-btn'))
10469
})
10570
await waitForEuiToolTipVisible()
10671

107-
expect(screen.getByTestId('not-useful-vote-tooltip')).toHaveTextContent('Enable Analytics on the Settings page to vote for a recommendation')
72+
expect(screen.getByTestId('not useful-vote-tooltip')).toHaveTextContent('Enable Analytics on the Settings page to vote for a recommendation')
73+
expect(screen.getByTestId('not useful-vote-btn')).toBeDisabled()
10874
})
10975
})

redisinsight/ui/src/components/recommendation-voting/RecommendationVoting.tsx

Lines changed: 16 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,15 @@
11
import React, { useState } from 'react'
2-
import { useDispatch, useSelector } from 'react-redux'
2+
import { useSelector } from 'react-redux'
33
import cx from 'classnames'
44
import {
5-
EuiButton,
6-
EuiButtonIcon,
7-
EuiPopover,
85
EuiText,
9-
EuiToolTip,
106
EuiFlexGroup,
11-
EuiIcon,
12-
EuiLink,
137
} from '@elastic/eui'
148
import { userSettingsConfigSelector } from 'uiSrc/slices/user/user-settings'
15-
import { putRecommendationVote } from 'uiSrc/slices/analytics/dbAnalysis'
16-
import { IRecommendationsStatic } from 'uiSrc/slices/interfaces/recommendations'
17-
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
18-
import { EXTERNAL_LINKS } from 'uiSrc/constants/links'
199
import { Vote } from 'uiSrc/constants/recommendations'
20-
import _content from 'uiSrc/constants/dbAnalysisRecommendations.json'
21-
import { ReactComponent as LikeIcon } from 'uiSrc/assets/img/icons/like.svg'
22-
import { ReactComponent as DoubleLikeIcon } from 'uiSrc/assets/img/icons/double_like.svg'
23-
import { ReactComponent as DislikeIcon } from 'uiSrc/assets/img/icons/dislike.svg'
24-
import GithubSVG from 'uiSrc/assets/img/sidebar/github.svg'
25-
import { updateLiveRecommendation } from 'uiSrc/slices/recommendations/recommendations'
2610
import { Nullable } from 'uiSrc/utils'
2711

28-
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
12+
import VoteOption from './components/vote-option'
2913
import styles from './styles.module.scss'
3014

3115
export interface Props {
@@ -36,43 +20,9 @@ export interface Props {
3620
containerClass?: string
3721
}
3822

39-
const recommendationsContent = _content as IRecommendationsStatic
40-
4123
const RecommendationVoting = ({ vote, name, id = '', live = false, containerClass = '' }: Props) => {
4224
const config = useSelector(userSettingsConfigSelector)
43-
const { id: instanceId = '', provider } = useSelector(connectedInstanceSelector)
44-
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
45-
const dispatch = useDispatch()
46-
47-
const onSuccessVoted = ({ vote, name }: { name: string, vote: Nullable<Vote> }) => {
48-
sendEventTelemetry({
49-
event: live
50-
? TelemetryEvent.INSIGHTS_RECOMMENDATION_VOTED
51-
: TelemetryEvent.DATABASE_ANALYSIS_RECOMMENDATIONS_VOTED,
52-
eventData: {
53-
databaseId: instanceId,
54-
name: recommendationsContent[name]?.telemetryEvent ?? name,
55-
vote,
56-
provider
57-
}
58-
})
59-
}
60-
61-
const handleClick = (name: string, vote: Vote) => {
62-
if (vote === Vote.Dislike) {
63-
setIsPopoverOpen(true)
64-
}
65-
66-
if (live) {
67-
dispatch(updateLiveRecommendation(id, { vote }, onSuccessVoted))
68-
} else {
69-
dispatch(putRecommendationVote(name, vote, onSuccessVoted))
70-
}
71-
}
72-
73-
const getTooltipContent = (recommendationsContent: string) => (config?.agreements?.analytics
74-
? recommendationsContent
75-
: 'Enable Analytics on the Settings page to vote for a recommendation')
25+
const [popover, setPopover] = useState<string>('')
7626

7727
return (
7828
<EuiFlexGroup
@@ -81,97 +31,21 @@ const RecommendationVoting = ({ vote, name, id = '', live = false, containerClas
8131
gutterSize={live ? 'none' : 'l'}
8232
data-testid="recommendation-voting"
8333
>
84-
<EuiText size="m">Rate Recommendation</EuiText>
34+
<EuiText size="m">Is this useful?</EuiText>
8535
<div className="voteContent">
86-
<EuiToolTip
87-
content={getTooltipContent('Very Useful')}
88-
position="bottom"
89-
data-testid="very-useful-vote-tooltip"
90-
>
91-
<EuiButtonIcon
92-
disabled={!!vote || !config?.agreements?.analytics}
93-
iconType={DoubleLikeIcon}
94-
className={cx('vote__btn', { selected: vote === Vote.DoubleLike })}
95-
aria-label="vote very useful"
96-
data-testid="very-useful-vote-btn"
97-
onClick={() => handleClick(name, Vote.DoubleLike)}
98-
/>
99-
</EuiToolTip>
100-
<EuiToolTip
101-
content={getTooltipContent('Useful')}
102-
position="bottom"
103-
data-testid="useful-vote-tooltip"
104-
>
105-
<EuiButtonIcon
106-
disabled={!!vote || !config?.agreements?.analytics}
107-
iconType={LikeIcon}
108-
className={cx('vote__btn', { selected: vote === Vote.Like })}
109-
aria-label="vote useful"
110-
data-testid="useful-vote-btn"
111-
onClick={() => handleClick(name, Vote.Like)}
36+
{Object.values(Vote).map((option) => (
37+
<VoteOption
38+
key={option}
39+
voteOption={option}
40+
vote={vote}
41+
popover={popover}
42+
isAnalyticsEnable={config?.agreements?.analytics}
43+
setPopover={setPopover}
44+
name={name}
45+
id={id}
46+
live={live}
11247
/>
113-
</EuiToolTip>
114-
<EuiToolTip
115-
content={getTooltipContent('Not Useful')}
116-
position="bottom"
117-
data-testid="not-useful-vote-tooltip"
118-
>
119-
<EuiPopover
120-
initialFocus={false}
121-
anchorPosition="rightCenter"
122-
isOpen={isPopoverOpen}
123-
closePopover={() => setIsPopoverOpen(false)}
124-
anchorClassName={styles.popoverAnchor}
125-
panelClassName={cx('euiToolTip', 'popoverLikeTooltip', styles.popover)}
126-
button={(
127-
<EuiButtonIcon
128-
disabled={!!vote || !config?.agreements?.analytics}
129-
iconType={DislikeIcon}
130-
className={cx('vote__btn', { selected: vote === Vote.Dislike })}
131-
aria-label="vote not useful"
132-
data-testid="not-useful-vote-btn"
133-
onClick={() => handleClick(name, Vote.Dislike)}
134-
/>
135-
)}
136-
>
137-
<div>
138-
Thank you for your feedback, Tell us how we can improve
139-
<EuiButton
140-
aria-label="recommendation feedback"
141-
fill
142-
data-testid="recommendation-feedback-btn"
143-
className={styles.feedbackBtn}
144-
color="secondary"
145-
size="s"
146-
>
147-
<EuiLink
148-
external={false}
149-
className={styles.link}
150-
href={EXTERNAL_LINKS.recommendationFeedback}
151-
target="_blank"
152-
data-test-subj="github-repo-link"
153-
>
154-
<EuiIcon
155-
className={styles.githubIcon}
156-
aria-label="redis insight github issues"
157-
type={GithubSVG}
158-
data-testid="github-repo-icon"
159-
/>
160-
To Github
161-
</EuiLink>
162-
</EuiButton>
163-
<EuiButtonIcon
164-
iconType="cross"
165-
color="primary"
166-
id="close-monitor"
167-
aria-label="close popover"
168-
data-testid="close-popover"
169-
className={styles.icon}
170-
onClick={() => setIsPopoverOpen(false)}
171-
/>
172-
</div>
173-
</EuiPopover>
174-
</EuiToolTip>
48+
))}
17549
</div>
17650
</EuiFlexGroup>
17751
)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React from 'react'
2+
import { cloneDeep } from 'lodash'
3+
import { instance, mock } from 'ts-mockito'
4+
import { setRecommendationVote } from 'uiSrc/slices/analytics/dbAnalysis'
5+
import { Vote } from 'uiSrc/constants/recommendations'
6+
import {
7+
cleanup,
8+
mockedStore,
9+
fireEvent,
10+
render,
11+
screen,
12+
} from 'uiSrc/utils/test-utils'
13+
14+
import VoteOption, { Props } from './VoteOption'
15+
16+
const mockedProps = mock<Props>()
17+
18+
let store: typeof mockedStore
19+
20+
beforeEach(() => {
21+
cleanup()
22+
store = cloneDeep(mockedStore)
23+
store.clearActions()
24+
})
25+
26+
jest.mock('uiSrc/telemetry', () => ({
27+
...jest.requireActual('uiSrc/telemetry'),
28+
sendEventTelemetry: jest.fn(),
29+
}))
30+
31+
jest.mock('uiSrc/slices/user/user-settings', () => ({
32+
...jest.requireActual('uiSrc/slices/user/user-settings'),
33+
userSettingsConfigSelector: jest.fn().mockReturnValue({
34+
agreements: {
35+
analytics: true,
36+
}
37+
}),
38+
}))
39+
40+
describe('VoteOption', () => {
41+
it('should render', () => {
42+
expect(render(<VoteOption {...instance(mockedProps)} />)).toBeTruthy()
43+
})
44+
45+
it('should render proper text for Like vote', async () => {
46+
render(<VoteOption {...instance(mockedProps)} voteOption={Vote.Like} popover={Vote.Like} />)
47+
48+
expect(screen.getByTestId('common-text')).toHaveTextContent('Thank you for the feedback.')
49+
expect(screen.getByTestId('custom-text')).toHaveTextContent('Share your ideas with us.')
50+
})
51+
52+
it('should render proper text for Dislike vote', () => {
53+
render(<VoteOption {...instance(mockedProps)} vote={Vote.Dislike} />)
54+
expect(screen.getByTestId('common-text')).toHaveTextContent('Thank you for the feedback.')
55+
expect(screen.getByTestId('custom-text')).toHaveTextContent('Tell us how we can improve.')
56+
})
57+
58+
it('should call "setRecommendationVote" action be called after click "useful-vote-btn"', () => {
59+
render(
60+
<VoteOption
61+
{...instance(mockedProps)}
62+
isAnalyticsEnable
63+
voteOption={Vote.Like}
64+
vote={Vote.Like}
65+
setPopover={() => {}}
66+
/>
67+
)
68+
fireEvent.click(screen.getByTestId('useful-vote-btn'))
69+
70+
const expectedActions = [setRecommendationVote()]
71+
expect(store.getActions()).toEqual(expectedActions)
72+
})
73+
74+
it('should call "setRecommendationVote" action be called after click "not-useful-vote-btn"', () => {
75+
render(
76+
<VoteOption
77+
{...instance(mockedProps)}
78+
isAnalyticsEnable
79+
voteOption={Vote.Dislike}
80+
vote={Vote.Dislike}
81+
setPopover={() => {}}
82+
/>
83+
)
84+
fireEvent.click(screen.getByTestId('not useful-vote-btn'))
85+
86+
const expectedActions = [setRecommendationVote()]
87+
expect(store.getActions()).toEqual(expectedActions)
88+
})
89+
})

0 commit comments

Comments
 (0)