mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-02 19:48:17 +00:00
chore(ui): cache version response for any hour to avoid frequent calls (#21323)
* chore(ui): cache version response for any hour to avoid frequent calls * fix tests
This commit is contained in:
parent
2e251fccc3
commit
02235cdd9d
@ -10,13 +10,31 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ONE_HOUR_MS } from '../../constants/constants';
|
||||
import { HELP_ITEMS_ENUM } from '../../constants/Navbar.constants';
|
||||
|
||||
import { getVersion } from '../../rest/miscAPI';
|
||||
import { getHelpDropdownItems } from '../../utils/NavbarUtils';
|
||||
import NavBar from './NavBar';
|
||||
import NavBarComponent from './NavBar';
|
||||
|
||||
// Place these at the very top of your test file, before any imports!
|
||||
const mockGetItem = jest.fn();
|
||||
const mockSetItem = jest.fn();
|
||||
|
||||
jest.mock('cookie-storage', () => ({
|
||||
CookieStorage: class {
|
||||
getItem(...args: any[]) {
|
||||
return mockGetItem(...args);
|
||||
}
|
||||
setItem(...args: any[]) {
|
||||
return mockSetItem(...args);
|
||||
}
|
||||
constructor() {
|
||||
// Do nothing
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../hooks/useApplicationStore', () => ({
|
||||
useApplicationStore: jest.fn().mockImplementation(() => ({
|
||||
@ -99,15 +117,6 @@ jest.mock('react-router-dom', () => ({
|
||||
useHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../common/CmdKIcon/CmdKIcon.component', () => {
|
||||
return jest.fn().mockReturnValue(<div data-testid="cmd">CmdKIcon</div>);
|
||||
});
|
||||
jest.mock('../AppBar/SearchOptions', () => {
|
||||
return jest.fn().mockReturnValue(<div data-testid="cmd">SearchOptions</div>);
|
||||
});
|
||||
jest.mock('../AppBar/Suggestions', () => {
|
||||
return jest.fn().mockReturnValue(<div data-testid="cmd">Suggestions</div>);
|
||||
});
|
||||
jest.mock('antd', () => ({
|
||||
...jest.requireActual('antd'),
|
||||
|
||||
@ -120,16 +129,6 @@ jest.mock('antd', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../rest/miscAPI', () => ({
|
||||
getVersion: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
data: {
|
||||
version: '0.5.0-SNAPSHOT',
|
||||
},
|
||||
})
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('../../utils/NavbarUtils', () => ({
|
||||
getHelpDropdownItems: jest.fn().mockReturnValue([
|
||||
{
|
||||
@ -139,9 +138,15 @@ jest.mock('../../utils/NavbarUtils', () => ({
|
||||
]),
|
||||
}));
|
||||
|
||||
jest.mock('../../rest/miscAPI', () => ({
|
||||
getVersion: jest.fn().mockResolvedValue({
|
||||
version: '0.5.0-SNAPSHOT',
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('Test NavBar Component', () => {
|
||||
it('Should render NavBar component', async () => {
|
||||
render(<NavBar />);
|
||||
render(<NavBarComponent />);
|
||||
|
||||
expect(await screen.findByTestId('global-search-bar')).toBeInTheDocument();
|
||||
expect(await screen.findByTestId('user-profile-icon')).toBeInTheDocument();
|
||||
@ -160,14 +165,61 @@ describe('Test NavBar Component', () => {
|
||||
});
|
||||
|
||||
it('should call getVersion onMount', () => {
|
||||
render(<NavBar />);
|
||||
render(<NavBarComponent />);
|
||||
|
||||
expect(getVersion).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call getHelpDropdownItems function', async () => {
|
||||
render(<NavBar />);
|
||||
render(<NavBarComponent />);
|
||||
|
||||
expect(getHelpDropdownItems).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
// --- Additional tests for fetchOMVersion one hour threshold ---
|
||||
describe('fetchOMVersion one hour threshold', () => {
|
||||
const OLD_DATE_NOW = Date.now;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
||||
global.Date.now = jest.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
global.Date.now = OLD_DATE_NOW;
|
||||
});
|
||||
|
||||
it('should NOT call getVersion if less than one hour since last fetch', async () => {
|
||||
const now = 2000000;
|
||||
const lastFetch = now - (ONE_HOUR_MS - 1000); // less than 1 hour ago
|
||||
mockGetItem.mockReturnValue(String(lastFetch));
|
||||
jest.spyOn(global.Date, 'now').mockReturnValue(now);
|
||||
|
||||
render(<NavBarComponent />);
|
||||
await screen.findByTestId('global-search-bar');
|
||||
|
||||
expect(getVersion).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call getVersion and setItem if more than one hour since last fetch', async () => {
|
||||
const now = 3000000;
|
||||
const lastFetch = now - (ONE_HOUR_MS + 1000); // more than 1 hour ago
|
||||
mockGetItem.mockReturnValue(String(lastFetch));
|
||||
(global.Date.now as jest.Mock).mockReturnValue(now);
|
||||
|
||||
render(<NavBarComponent />);
|
||||
await Promise.resolve();
|
||||
|
||||
await act(async () => {
|
||||
expect(getVersion).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
expect(mockSetItem).toHaveBeenCalledWith(
|
||||
'versionFetchTime',
|
||||
'3000000',
|
||||
expect.objectContaining({ expires: expect.any(Date) })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -46,7 +46,9 @@ import { ReactComponent as SidebarExpandedIcon } from '../../assets/svg/ic-sideb
|
||||
import {
|
||||
DEFAULT_DOMAIN_VALUE,
|
||||
NOTIFICATION_READ_TIMER,
|
||||
ONE_HOUR_MS,
|
||||
SOCKET_EVENTS,
|
||||
VERSION_FETCH_TIME_KEY,
|
||||
} from '../../constants/constants';
|
||||
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
|
||||
import { HELP_ITEMS_ENUM } from '../../constants/Navbar.constants';
|
||||
@ -124,9 +126,22 @@ const NavBar = () => {
|
||||
} = useCurrentUserPreferences();
|
||||
|
||||
const fetchOMVersion = async () => {
|
||||
// If version fetch happens within an hour, skip fetching
|
||||
const lastFetchTime = cookieStorage.getItem(VERSION_FETCH_TIME_KEY);
|
||||
const now = Date.now();
|
||||
|
||||
if (lastFetchTime && now - Number(lastFetchTime) < ONE_HOUR_MS) {
|
||||
// Less than an hour since last fetch, skip fetching
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await getVersion();
|
||||
setVersion(res.version);
|
||||
// Set/update the cookie with current time, expires in 1 hour
|
||||
cookieStorage.setItem(VERSION_FETCH_TIME_KEY, String(now), {
|
||||
expires: new Date(now + ONE_HOUR_MS),
|
||||
});
|
||||
} catch (err) {
|
||||
showErrorToast(
|
||||
err as AxiosError,
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ReactComponent as CmdButton } from '../../../assets/svg/command-button.svg';
|
||||
import { ReactComponent as CtrlButton } from '../../../assets/svg/control-button.svg';
|
||||
import { ReactComponent as KButton } from '../../../assets/svg/k-button.svg';
|
||||
import { NavigatorHelper } from '../../../utils/NavigatorUtils';
|
||||
|
||||
const CmdKIcon = () => {
|
||||
return (
|
||||
<div className="d-flex items-center" data-testid="cmdicon-container">
|
||||
{NavigatorHelper.isMacOs() ? (
|
||||
<CmdButton
|
||||
data-testid="cmd-button"
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<CtrlButton
|
||||
data-testid="ctrl-button"
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<KButton
|
||||
data-testid="k-button"
|
||||
style={{
|
||||
marginLeft: '4px',
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CmdKIcon;
|
||||
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { NavigatorHelper } from '../../../utils/NavigatorUtils';
|
||||
import CmdKIcon from './CmdKIcon.component';
|
||||
|
||||
jest.mock('../../../utils/NavigatorUtils', () => ({
|
||||
NavigatorHelper: {
|
||||
isMacOs: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('CmdKIcon', () => {
|
||||
it('should render CmdKIcon', async () => {
|
||||
await act(async () => {
|
||||
render(<CmdKIcon />);
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('cmdicon-container')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render CmdButton when isMacOs is true', () => {
|
||||
(NavigatorHelper.isMacOs as jest.Mock).mockReturnValue(true);
|
||||
const { getByTestId, queryByTestId } = render(<CmdKIcon />);
|
||||
|
||||
expect(getByTestId('cmd-button')).toBeInTheDocument();
|
||||
expect(queryByTestId('ctrl-button')).toBeNull();
|
||||
});
|
||||
|
||||
it('should render CtrlButton when isMacOs is false', () => {
|
||||
(NavigatorHelper.isMacOs as jest.Mock).mockReturnValue(false);
|
||||
const { getByTestId, queryByTestId } = render(<CmdKIcon />);
|
||||
|
||||
expect(getByTestId('ctrl-button')).toBeInTheDocument();
|
||||
expect(queryByTestId('cmd-button')).toBeNull();
|
||||
});
|
||||
});
|
||||
@ -424,3 +424,6 @@ export const MAX_VISIBLE_OWNERS_FOR_FEED_TAB = 4;
|
||||
export const MAX_VISIBLE_OWNERS_FOR_FEED_CARD = 2;
|
||||
|
||||
export const BREADCRUMB_SEPARATOR = '/';
|
||||
|
||||
export const VERSION_FETCH_TIME_KEY = 'versionFetchTime';
|
||||
export const ONE_HOUR_MS = 60 * 60 * 1000;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user