Plugins: All plugins are up to date message if now new updates available (#109175)

* add message for no updates abailable

* add tests to PluginList
This commit is contained in:
Yulia Shanyrova
2025-08-11 14:45:21 +02:00
committed by GitHub
parent 7cde0dfaf5
commit 63237f0be8
3 changed files with 110 additions and 1 deletions
@@ -0,0 +1,97 @@
import { render, screen } from '@testing-library/react';
import { PluginSignatureStatus, PluginSignatureType, PluginType } from '@grafana/data';
import { config } from '@grafana/runtime';
import { CatalogPlugin } from '../types';
import { PluginList } from './PluginList';
jest.mock('react-router-dom-v5-compat', () => ({ useLocation: jest.fn(), useSearchParams: jest.fn() }));
const mockUseLocation = jest.requireMock('react-router-dom-v5-compat').useLocation;
const mockUseSearchParams = jest.requireMock('react-router-dom-v5-compat').useSearchParams;
const mockPlugin: CatalogPlugin = {
description: 'Test plugin description',
downloads: 1000,
hasUpdate: false,
id: 'test-plugin',
info: { logos: { small: 'small-logo-url', large: 'large-logo-url' }, keywords: ['test', 'plugin'] },
isDev: false,
isCore: false,
isEnterprise: false,
isInstalled: true,
isDisabled: false,
isDeprecated: false,
isManaged: false,
isPreinstalled: { found: false, withVersion: false },
isPublished: true,
name: 'Test Plugin',
orgName: 'Test Org',
signature: PluginSignatureStatus.valid,
signatureType: PluginSignatureType.grafana,
signatureOrg: 'Test Signature Org',
popularity: 4,
publishedAt: '2023-01-01',
type: PluginType.app,
updatedAt: '2023-12-01',
installedVersion: '1.0.0',
angularDetected: false,
isFullyInstalled: true,
accessControl: {},
};
const mockPlugin2: CatalogPlugin = {
...mockPlugin,
id: 'test-plugin-2',
name: 'Test Plugin 2',
type: PluginType.datasource,
};
describe('PluginList', () => {
beforeEach(() => {
jest.clearAllMocks();
mockUseLocation.mockReturnValue({ pathname: '/plugins' });
mockUseSearchParams.mockReturnValue([new URLSearchParams(), jest.fn()]);
config.appSubUrl = '';
});
afterEach(() => {
jest.clearAllMocks();
});
it('should render plugins when not loading and plugins exist', () => {
const plugins = [mockPlugin, mockPlugin2];
render(<PluginList plugins={plugins} isLoading={false} />);
expect(screen.getByTestId('plugin-list')).toBeInTheDocument();
expect(screen.getByText('Test Plugin')).toBeInTheDocument();
expect(screen.getByText('Test Plugin 2')).toBeInTheDocument();
});
it('should show "All plugins are up to date" message when filterBy=has-update and no plugins', () => {
mockUseSearchParams.mockReturnValue([new URLSearchParams('filterBy=has-update'), jest.fn()]);
render(<PluginList plugins={[]} isLoading={false} />);
expect(screen.getByText('All plugins are up to date')).toBeInTheDocument();
});
it('should show "No plugins found" message when filterBy=all and not loading', () => {
mockUseSearchParams.mockReturnValue([new URLSearchParams('filterBy=all'), jest.fn()]);
render(<PluginList plugins={[]} isLoading={false} />);
expect(screen.getByText('No plugins found')).toBeInTheDocument();
});
it('should not show empty state when filterBy=has-update but plugins exist', () => {
mockUseSearchParams.mockReturnValue([new URLSearchParams('filterBy=has-update'), jest.fn()]);
render(<PluginList plugins={[mockPlugin]} isLoading={false} />);
expect(screen.queryByText('All plugins are up to date')).not.toBeInTheDocument();
expect(screen.getByText('Test Plugin')).toBeInTheDocument();
});
});
@@ -1,4 +1,4 @@
import { useLocation } from 'react-router-dom-v5-compat';
import { useLocation, useSearchParams } from 'react-router-dom-v5-compat';
import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
@@ -15,9 +15,18 @@ interface Props {
export const PluginList = ({ plugins, isLoading }: Props) => {
const { pathname } = useLocation();
const [searchParams] = useSearchParams();
const pathName = config.appSubUrl + (pathname.endsWith('/') ? pathname.slice(0, -1) : pathname);
if (searchParams.get('filterBy') === 'has-update' && !isLoading && plugins.length === 0) {
return (
<EmptyState
variant="not-found"
message={t('plugins.no-updates-available.message', 'All plugins are up to date')}
/>
);
}
if (!isLoading && plugins.length === 0) {
return <EmptyState variant="not-found" message={t('plugins.empty-state.message', 'No plugins found')} />;
}
+3
View File
@@ -10941,6 +10941,9 @@
"label-plugin-id": "Plugin Id",
"label-severity": "Severity"
},
"no-updates-available": {
"message": "All plugins are up to date"
},
"not-found-plugin": {
"body-plugin-not-found": "That plugin cannot be found. Please check the url is correct or <1></1>go to the <3>plugin catalog</3>.",
"title-plugin-not-found": "Plugin not found"