Fix(ui) : Release dialog flash (#22776)

* fixed release dialog flash

* optimized approach to remove release dialog flash

* fixed sonar

* fixed github redirect

* updated tests
This commit is contained in:
Dhruv Parmar 2025-08-06 21:33:01 +05:30 committed by GitHub
parent 51b826b06b
commit 58dbb98205
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 46 deletions

View File

@ -18,7 +18,6 @@ import { useTranslation } from 'react-i18next';
import { ReactComponent as CloseIcon } from '../../../../assets/svg/close.svg'; import { ReactComponent as CloseIcon } from '../../../../assets/svg/close.svg';
import { ReactComponent as RocketIcon } from '../../../../assets/svg/rocket.svg'; import { ReactComponent as RocketIcon } from '../../../../assets/svg/rocket.svg';
import { ROUTES, VERSION } from '../../../../constants/constants'; import { ROUTES, VERSION } from '../../../../constants/constants';
import { useAuth } from '../../../../hooks/authHooks';
import { useApplicationStore } from '../../../../hooks/useApplicationStore'; import { useApplicationStore } from '../../../../hooks/useApplicationStore';
import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation'; import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation';
import brandClassBase from '../../../../utils/BrandData/BrandClassBase'; import brandClassBase from '../../../../utils/BrandData/BrandClassBase';
@ -31,13 +30,14 @@ const cookieStorage = new CookieStorage();
const WhatsNewAlert = () => { const WhatsNewAlert = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const location = useCustomLocation(); const location = useCustomLocation();
const { isFirstTimeUser } = useAuth();
const { appVersion } = useApplicationStore(); const { appVersion } = useApplicationStore();
const [showWhatsNew, setShowWhatsNew] = useState({ const [showWhatsNew, setShowWhatsNew] = useState({
alert: false, alert: false,
modal: false, modal: false,
}); });
const cookieKey = getVersionedStorageKey(VERSION, appVersion); const cookieKey = useMemo(() => {
return appVersion ? getVersionedStorageKey(VERSION, appVersion) : null;
}, [appVersion]);
const { releaseLink, blogLink, isMajorRelease } = useMemo(() => { const { releaseLink, blogLink, isMajorRelease } = useMemo(() => {
return { return {
@ -63,18 +63,22 @@ const WhatsNewAlert = () => {
); );
const handleCancel = useCallback(() => { const handleCancel = useCallback(() => {
cookieStorage.setItem(cookieKey, 'true', { if (cookieKey) {
expires: getReleaseVersionExpiry(), cookieStorage.setItem(cookieKey, 'true', {
}); expires: getReleaseVersionExpiry(),
});
}
onModalCancel(); onModalCancel();
}, [cookieStorage, onModalCancel, getReleaseVersionExpiry, cookieKey]); }, [cookieStorage, onModalCancel, getReleaseVersionExpiry, cookieKey]);
useEffect(() => { useEffect(() => {
setShowWhatsNew({ if (cookieKey) {
alert: cookieStorage.getItem(cookieKey) !== 'true', setShowWhatsNew((prev) => ({
modal: false, ...prev,
}); alert: cookieStorage.getItem(cookieKey) !== 'true',
}, [isFirstTimeUser, cookieKey]); }));
}
}, [cookieKey]);
return ( return (
<> <>

View File

@ -209,9 +209,10 @@ describe('WhatsNewAlert', () => {
appVersion: undefined, appVersion: undefined,
})); }));
const { findByText } = render(<WhatsNewAlert />); const { queryByTestId } = render(<WhatsNewAlert />);
expect(await findByText('Version')).toBeInTheDocument(); // Should not render the alert when appVersion is undefined
expect(queryByTestId('whats-new-alert-card')).not.toBeInTheDocument();
}); });
it('should call brandClassBase methods with correct version', () => { it('should call brandClassBase methods with correct version', () => {

View File

@ -16,7 +16,6 @@ import ButtonGroup from 'antd/lib/button/button-group';
import { CookieStorage } from 'cookie-storage'; import { CookieStorage } from 'cookie-storage';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { ReactComponent as CloseIcon } from '../../../assets/svg/close.svg'; import { ReactComponent as CloseIcon } from '../../../assets/svg/close.svg';
import { ReactComponent as StarGithubIcon } from '../../../assets/svg/ic-star-github.svg'; import { ReactComponent as StarGithubIcon } from '../../../assets/svg/ic-star-github.svg';
import { ReactComponent as StarIcon } from '../../../assets/svg/ic-start-filled-github.svg'; import { ReactComponent as StarIcon } from '../../../assets/svg/ic-start-filled-github.svg';
@ -150,23 +149,15 @@ const GithubStarCard = () => {
</Typography.Paragraph> </Typography.Paragraph>
<ButtonGroup className="github-action-button-group"> <ButtonGroup className="github-action-button-group">
<Link <Typography.Link href={OMD_REPOSITORY_LINK} target="_blank">
target="_blank"
to={{
pathname: OMD_REPOSITORY_LINK,
}}>
<Button <Button
className="github-star-button github-modal-action-button" className="github-star-button github-modal-action-button"
icon={<Icon component={StarGithubIcon} size={12} />}> icon={<Icon component={StarGithubIcon} size={12} />}>
{t('label.star')} {t('label.star')}
</Button> </Button>
</Link> </Typography.Link>
<Link <Typography.Link href={OMD_REPOSITORY_LINK} target="_blank">
target="_blank"
to={{
pathname: OMD_REPOSITORY_LINK,
}}>
<Button className="github-modal-action-button"> <Button className="github-modal-action-button">
{isLoading ? ( {isLoading ? (
<div data-testid="skeleton-loader"> <div data-testid="skeleton-loader">
@ -176,7 +167,7 @@ const GithubStarCard = () => {
starredCount starredCount
)} )}
</Button> </Button>
</Link> </Typography.Link>
</ButtonGroup> </ButtonGroup>
</Card> </Card>
</Affix> </Affix>

View File

@ -16,20 +16,10 @@ import { TWO_MINUTE_IN_MILLISECOND } from '../../../constants/constants';
import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocation'; import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocation';
import GithubStarCard from './GithubStarCard.component'; import GithubStarCard from './GithubStarCard.component';
const mockLinkButton = jest.fn();
jest.mock('../../../hooks/useCustomLocation/useCustomLocation', () => { jest.mock('../../../hooks/useCustomLocation/useCustomLocation', () => {
return jest.fn().mockImplementation(() => ({ pathname: '/my-data' })); return jest.fn().mockImplementation(() => ({ pathname: '/my-data' }));
}); });
jest.mock('react-router-dom', () => ({
Link: jest.fn().mockImplementation(({ children, ...rest }) => (
<a {...rest} onClick={mockLinkButton}>
{children}
</a>
)),
}));
jest.mock('../../../utils/WhatsNewModal.util', () => ({ jest.mock('../../../utils/WhatsNewModal.util', () => ({
getReleaseVersionExpiry: jest.fn().mockImplementation(() => new Date()), getReleaseVersionExpiry: jest.fn().mockImplementation(() => new Date()),
})); }));
@ -72,21 +62,26 @@ describe('GithubStarCard', () => {
expect(screen.getByRole('button', { name: '10' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: '10' })).toBeInTheDocument();
}); });
it('check redirect buttons', async () => { it('check redirect buttons have correct links', async () => {
render(<GithubStarCard />); render(<GithubStarCard />);
jest.advanceTimersByTime(TWO_MINUTE_IN_MILLISECOND); jest.advanceTimersByTime(TWO_MINUTE_IN_MILLISECOND);
const starTextButton = await screen.findByRole('button', { await screen.findByTestId('github-star-popup-card');
name: 'label.star',
});
fireEvent.click(starTextButton); // Check that both links point to the correct GitHub repository
const links = screen.getAllByRole('link');
const countButton = screen.getByRole('button', { name: '10' }); expect(links).toHaveLength(2);
expect(links[0]).toHaveAttribute(
fireEvent.click(countButton); 'href',
'https://star-us.open-metadata.org/'
expect(mockLinkButton).toHaveBeenCalledTimes(2); );
expect(links[0]).toHaveAttribute('target', '_blank');
expect(links[1]).toHaveAttribute(
'href',
'https://star-us.open-metadata.org/'
);
expect(links[1]).toHaveAttribute('target', '_blank');
}); });
it('should close the alert when the close button is clicked', async () => { it('should close the alert when the close button is clicked', async () => {