fix(ui-components): remove test warnings (#5113)

This commit is contained in:
Marc Bernard
2025-03-02 11:39:04 +01:00
committed by GitHub
parent 8eb8975d66
commit 6260eae1e8
8 changed files with 155 additions and 44 deletions

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/ui-components': patch
---
fix(ui-components): remove test warnings

View File

@@ -34,13 +34,17 @@ describe('AppRoute', () => {
test('renders VersionPage component for PACKAGE path', async () => { test('renders VersionPage component for PACKAGE path', async () => {
act(() => appTest('/-/web/detail/jquery')); act(() => appTest('/-/web/detail/jquery'));
await waitFor(() => screen.getByTestId('readme-tab')); await waitFor(() => expect(screen.getByTestId('readme-tab')).toBeInTheDocument(), {
timeout: 3000,
});
expect(screen.getByTestId('sidebar')).toBeInTheDocument(); expect(screen.getByTestId('sidebar')).toBeInTheDocument();
}); });
test('renders VersionPage component for PACKAGE VERSION path', async () => { test('renders VersionPage component for PACKAGE VERSION path', async () => {
act(() => appTest('/-/web/detail/jquery/v/3.6.3')); act(() => appTest('/-/web/detail/jquery/v/3.6.3'));
await waitFor(() => screen.getByTestId('readme-tab')); await waitFor(() => expect(screen.getByTestId('readme-tab')).toBeInTheDocument(), {
timeout: 3000,
});
expect(screen.getByTestId('sidebar')).toBeInTheDocument(); expect(screen.getByTestId('sidebar')).toBeInTheDocument();
}); });

View File

@@ -1,7 +1,14 @@
import React from 'react'; import React from 'react';
import { cleanupDownloadMocks, setupDownloadMocks } from '../../../vitest/vitestHelpers';
import { store } from '../../store/store'; import { store } from '../../store/store';
import { cleanup, fireEvent, renderWithStore, screen } from '../../test/test-react-testing-library'; import {
cleanup,
fireEvent,
renderWithStore,
screen,
waitFor,
} from '../../test/test-react-testing-library';
import ActionBar from './ActionBar'; import ActionBar from './ActionBar';
const defaultPackageMeta = { const defaultPackageMeta = {
@@ -21,25 +28,37 @@ const defaultPackageMeta = {
}, },
}; };
beforeAll(() => {
setupDownloadMocks();
});
afterAll(() => {
cleanupDownloadMocks();
});
describe('<ActionBar /> component', () => { describe('<ActionBar /> component', () => {
afterEach(() => { afterEach(() => {
cleanup(); cleanup();
}); });
test('should render the component in default state', () => { test('should render the component in default state', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} />, store);
expect(screen.getByTestId('download-tarball-btn')).toBeInTheDocument(); await waitFor(() => {
expect(screen.getByTestId('BugReportIcon')).toBeInTheDocument(); expect(screen.getByTestId('download-tarball-btn')).toBeInTheDocument();
expect(screen.getByTestId('HomeIcon')).toBeInTheDocument(); expect(screen.getByTestId('BugReportIcon')).toBeInTheDocument();
expect(screen.getByTestId('HomeIcon')).toBeInTheDocument();
});
}); });
test('should not render if data is missing', () => { test('should not render if data is missing', async () => {
// @ts-ignore - testing with missing data // @ts-ignore - testing with missing data
renderWithStore(<ActionBar packageMeta={undefined} />, store); renderWithStore(<ActionBar packageMeta={undefined} />, store);
expect(screen.queryByTestId('HomeIcon')).toBeNull(); await waitFor(() => {
expect(screen.queryByTestId('HomeIcon')).toBeNull();
});
}); });
test('when there is no action bar data', () => { test('when there is no action bar data', async () => {
const packageMeta = { const packageMeta = {
...defaultPackageMeta, ...defaultPackageMeta,
latest: { latest: {
@@ -54,60 +73,80 @@ describe('<ActionBar /> component', () => {
}; };
renderWithStore(<ActionBar packageMeta={packageMeta} />, store); renderWithStore(<ActionBar packageMeta={packageMeta} />, store);
expect(screen.queryByTestId('download-tarball-btn')).not.toBeInTheDocument(); await waitFor(() => {
expect(screen.queryByTestId('BugReportIcon')).not.toBeInTheDocument(); expect(screen.queryByTestId('download-tarball-btn')).not.toBeInTheDocument();
expect(screen.queryByTestId('HomeIcon')).not.toBeInTheDocument(); expect(screen.queryByTestId('BugReportIcon')).not.toBeInTheDocument();
expect(screen.queryByTestId('HomeIcon')).not.toBeInTheDocument();
});
}); });
test('when there is a button to download a tarball', () => { test('when there is a button to download a tarball', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} />, store);
expect(screen.getByLabelText('action-bar-action.download-tarball')).toBeTruthy(); await waitFor(() => {
expect(screen.getByLabelText('action-bar-action.download-tarball')).toBeTruthy();
});
}); });
test('when button to download is disabled', () => { test('when button to download is disabled', async () => {
renderWithStore( renderWithStore(
<ActionBar packageMeta={defaultPackageMeta} showDownloadTarball={false} />, <ActionBar packageMeta={defaultPackageMeta} showDownloadTarball={false} />,
store store
); );
expect(screen.queryByTestId('download-tarball-btn')).not.toBeInTheDocument(); await waitFor(() => {
expect(screen.queryByTestId('download-tarball-btn')).not.toBeInTheDocument();
});
}); });
test('when there is a button to raw manifest', () => { test('when there is a button to raw manifest', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={true} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={true} />, store);
expect(screen.getByLabelText('action-bar-action.raw')).toBeTruthy(); await waitFor(() => {
expect(screen.getByLabelText('action-bar-action.raw')).toBeTruthy();
});
}); });
test('when click button to raw manifest open a dialog with viewer', async () => { test('when click button to raw manifest open a dialog with viewer', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={true} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={true} />, store);
expect(screen.queryByTestId('rawViewer--dialog')).toBeFalsy(); await waitFor(() => {
expect(screen.queryByTestId('rawViewer--dialog')).toBeFalsy();
});
fireEvent.click(screen.getByLabelText('action-bar-action.raw')); fireEvent.click(screen.getByLabelText('action-bar-action.raw'));
await screen.findByTestId('rawViewer--dialog'); await waitFor(() => {
expect(screen.getByTestId('rawViewer--dialog')).toBeInTheDocument();
});
fireEvent.click(screen.getByTestId('close-raw-viewer')); fireEvent.click(screen.getByTestId('close-raw-viewer'));
await screen.getByLabelText('action-bar-action.raw'); await waitFor(() => {
expect(screen.queryByTestId('rawViewer--dialog')).toBeFalsy();
expect(screen.queryByTestId('rawViewer--dialog')).toBeFalsy(); });
}); });
test('should not display download tarball button', () => { test('should not display download tarball button', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={false} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={false} />, store);
expect(screen.queryByLabelText('Download tarball')).toBeFalsy(); await waitFor(() => {
expect(screen.queryByLabelText('Download tarball')).toBeFalsy();
});
}); });
test('when click button to download ', async () => { test('when click button to download ', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={false} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={false} />, store);
fireEvent.click(screen.getByTestId('download-tarball-btn')); fireEvent.click(screen.getByTestId('download-tarball-btn'));
await store.getState().loading.models.download; await waitFor(() => {
expect(store.getState().loading.models.download).toBe(true);
});
}); });
test('should not display show raw button', () => { test('should not display show raw button', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={false} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} showRaw={false} />, store);
expect(screen.queryByLabelText('action-bar-action.raw')).toBeFalsy(); await waitFor(() => {
expect(screen.queryByLabelText('action-bar-action.raw')).toBeFalsy();
});
}); });
test('when there is a button to open an issue', () => { test('when there is a button to open an issue', async () => {
renderWithStore(<ActionBar packageMeta={defaultPackageMeta} />, store); renderWithStore(<ActionBar packageMeta={defaultPackageMeta} />, store);
expect(screen.getByTestId('BugReportIcon')).toBeInTheDocument(); await waitFor(() => {
expect(screen.getByTestId('BugReportIcon')).toBeInTheDocument();
});
}); });
}); });

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { MemoryRouter } from 'react-router'; import { MemoryRouter } from 'react-router';
import { store } from '../../'; import { store } from '../../';
import { cleanupDownloadMocks, setupDownloadMocks } from '../../../vitest/vitestHelpers';
import { import {
cleanup, cleanup,
fireEvent, fireEvent,
@@ -34,6 +35,14 @@ const props = {
keywords: ['verdaccio-core'], keywords: ['verdaccio-core'],
}; };
beforeAll(() => {
setupDownloadMocks();
});
afterAll(() => {
cleanupDownloadMocks();
});
describe('<Package /> component', () => { describe('<Package /> component', () => {
afterEach(() => { afterEach(() => {
cleanup(); cleanup();

View File

@@ -118,6 +118,8 @@ const Search: React.FC<RouteComponentProps> = ({ history }) => {
}; };
const renderOption = (props, option) => { const renderOption = (props, option) => {
const { key, ...otherProps } = props;
if (searchRemote) { if (searchRemote) {
const item: SearchResultWeb = option.package; const item: SearchResultWeb = option.package;
const isPrivate = option?.verdaccioPrivate; const isPrivate = option?.verdaccioPrivate;
@@ -125,7 +127,8 @@ const Search: React.FC<RouteComponentProps> = ({ history }) => {
const isRemote = !isCached && !isPrivate; const isRemote = !isCached && !isPrivate;
return ( return (
<SearchItem <SearchItem
{...props} key={key}
{...otherProps}
description={item?.description} description={item?.description}
isCached={isCached} isCached={isCached}
isPrivate={isPrivate} isPrivate={isPrivate}
@@ -137,7 +140,8 @@ const Search: React.FC<RouteComponentProps> = ({ history }) => {
} else { } else {
return ( return (
<SearchItem <SearchItem
{...props} key={key}
{...otherProps}
description={option?.description} description={option?.description}
name={option?.name} name={option?.name}
version={option?.version} version={option?.version}
@@ -161,4 +165,4 @@ const Search: React.FC<RouteComponentProps> = ({ history }) => {
); );
}; };
export default withRouter(Search); export default withRouter(Search as any);

View File

@@ -45,13 +45,29 @@ export function downloadFile(fileStream: Blob, fileName: string): void {
fileLink.href = objectURL; fileLink.href = objectURL;
fileLink.download = fileName; fileLink.download = fileName;
// Without appending to an HTML Element, download dialog does not show up on Firefox // Skip actual download in test environment to avoid JSDOM navigation error
// https://github.com/verdaccio/ui/issues/119 // Check if we're in a test environment (JSDOM)
document.documentElement.appendChild(fileLink); const isTestEnvironment =
fileLink.click(); (typeof window !== 'undefined' &&
// firefox requires remove the object url window.navigator &&
setTimeout(() => { window.navigator.userAgent &&
URL.revokeObjectURL(objectURL); window.navigator.userAgent.includes('Node.js')) ||
document.documentElement.removeChild(fileLink); window.navigator.userAgent.includes('jsdom');
}, 150);
if (!isTestEnvironment) {
// Without appending to an HTML Element, download dialog does not show up on Firefox
// https://github.com/verdaccio/ui/issues/119
document.documentElement.appendChild(fileLink);
fileLink.click();
// firefox requires remove the object url
setTimeout(() => {
URL.revokeObjectURL(objectURL);
document.documentElement.removeChild(fileLink);
}, 150);
} else {
// In test environment, just clean up without triggering navigation
setTimeout(() => {
URL.revokeObjectURL(objectURL);
}, 150);
}
} }

View File

@@ -13,7 +13,7 @@
"allowJs": true, "allowJs": true,
"types": ["node", "jest", "@testing-library/jest-dom"] "types": ["node", "jest", "@testing-library/jest-dom"]
}, },
"include": ["src/**/*", "vitest/**/*"], "include": ["src/**/*", "vitest/**/*", "src/test/**/*"],
"references": [ "references": [
{ {
"path": "../core/types" "path": "../core/types"

View File

@@ -0,0 +1,34 @@
import { vi } from 'vitest';
export const mockCreateObjectURL = vi.fn();
export const mockRevokeObjectURL = vi.fn();
let originalUserAgent: string;
/**
* Sets up mocks for URL and navigator.userAgent to handle download functionality in tests
*/
export function setupDownloadMocks(): void {
originalUserAgent = window.navigator.userAgent;
URL.createObjectURL = mockCreateObjectURL;
URL.revokeObjectURL = mockRevokeObjectURL;
Object.defineProperty(window.navigator, 'userAgent', {
value: 'jsdom',
configurable: true,
});
}
/**
* Cleans up mocks for URL and navigator.userAgent
*/
export function cleanupDownloadMocks(): void {
mockCreateObjectURL.mockReset();
mockRevokeObjectURL.mockReset();
Object.defineProperty(window.navigator, 'userAgent', {
value: originalUserAgent,
configurable: true,
});
}