Plugin Details Page: Fix tabs not loading on hard refresh (#112915)
* don't show nav children while plugin config is loading * add tests
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
|
||||
import { PluginSignatureStatus, PluginSignatureType, PluginType } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import { CatalogPlugin } from '../types';
|
||||
|
||||
import { usePluginDetailsTabs } from './usePluginDetailsTabs';
|
||||
|
||||
jest.mock('react-router-dom-v5-compat', () => ({
|
||||
useLocation: () => ({ pathname: '/plugins/test-plugin' }),
|
||||
}));
|
||||
|
||||
jest.mock('./usePluginConfig');
|
||||
|
||||
jest.mock('app/core/core', () => ({
|
||||
contextSrv: {
|
||||
hasPermissionInMetadata: jest.fn(() => true),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockUsePluginConfig = jest.requireMock('./usePluginConfig').usePluginConfig;
|
||||
|
||||
const mockPlugin: CatalogPlugin = {
|
||||
id: 'test-plugin',
|
||||
name: 'Test Plugin',
|
||||
description: 'Test plugin description',
|
||||
type: PluginType.app,
|
||||
isPublished: true,
|
||||
isInstalled: true,
|
||||
isCore: false,
|
||||
isDev: false,
|
||||
isDisabled: false,
|
||||
isDeprecated: false,
|
||||
isEnterprise: false,
|
||||
isFullyInstalled: true,
|
||||
isManaged: false,
|
||||
isPreinstalled: { found: false, withVersion: false },
|
||||
hasUpdate: false,
|
||||
info: {
|
||||
logos: { small: '', large: '' },
|
||||
keywords: [],
|
||||
},
|
||||
orgName: 'Test',
|
||||
signature: PluginSignatureStatus.valid,
|
||||
signatureType: PluginSignatureType.grafana,
|
||||
signatureOrg: 'Grafana',
|
||||
popularity: 1,
|
||||
downloads: 100,
|
||||
updatedAt: '2023-01-01',
|
||||
publishedAt: '2023-01-01',
|
||||
angularDetected: false,
|
||||
accessControl: {},
|
||||
};
|
||||
|
||||
const mockPluginConfig = {
|
||||
meta: {
|
||||
id: 'test-plugin',
|
||||
name: 'Test Plugin',
|
||||
type: PluginType.app,
|
||||
module: 'test',
|
||||
baseUrl: '',
|
||||
info: {
|
||||
author: { name: 'Test' },
|
||||
description: 'Test plugin',
|
||||
logos: { small: '', large: '' },
|
||||
links: [],
|
||||
screenshots: [],
|
||||
updated: '2023-01-01',
|
||||
version: '1.0.0',
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
configPages: [
|
||||
{
|
||||
id: 'config-page-1',
|
||||
title: 'Configuration',
|
||||
icon: 'cog',
|
||||
body: () => null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe('usePluginDetailsTabs', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
config.featureToggles.externalServiceAccounts = false;
|
||||
});
|
||||
|
||||
it('should not include config-specific tabs while plugin config is loading', () => {
|
||||
// simulate the race condition: plugin is loaded but config is still loading
|
||||
mockUsePluginConfig.mockReturnValue({
|
||||
loading: true,
|
||||
error: undefined,
|
||||
value: null,
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => usePluginDetailsTabs(mockPlugin, undefined, false));
|
||||
|
||||
// should NOT include config page tabs while loading
|
||||
const configTab = result.current.navModel.children?.find((tab) => tab.id === 'config-page-1');
|
||||
expect(configTab).toBeUndefined();
|
||||
|
||||
// should include basic tabs
|
||||
const overviewTab = result.current.navModel.children?.find((tab) => tab.id === 'overview');
|
||||
expect(overviewTab).toBeDefined();
|
||||
});
|
||||
|
||||
it('should include config-specific tabs when plugin config is loaded', () => {
|
||||
// simulate config loaded successfully
|
||||
mockUsePluginConfig.mockReturnValue({
|
||||
loading: false,
|
||||
error: undefined,
|
||||
value: mockPluginConfig,
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => usePluginDetailsTabs(mockPlugin, undefined, false));
|
||||
|
||||
// should NOW include config page tabs
|
||||
const configTab = result.current.navModel.children?.find((tab) => tab.id === 'config-page-1');
|
||||
expect(configTab).toBeDefined();
|
||||
expect(configTab?.text).toBe('Configuration');
|
||||
});
|
||||
});
|
||||
@@ -85,7 +85,8 @@ export const usePluginDetailsTabs = (
|
||||
}
|
||||
|
||||
// Not extending the tabs with the config pages if the plugin is not installed
|
||||
if (!pluginConfig) {
|
||||
// also wait if the plugin config is still loading to avoid showing default tabs prematurely
|
||||
if (!pluginConfig || loading) {
|
||||
return navModelChildren;
|
||||
}
|
||||
|
||||
@@ -151,7 +152,7 @@ export const usePluginDetailsTabs = (
|
||||
}
|
||||
|
||||
return navModelChildren;
|
||||
}, [plugin, pluginConfig, pathname, isPublished, currentPageId, isNarrowScreen]);
|
||||
}, [plugin, pluginConfig, pathname, isPublished, currentPageId, isNarrowScreen, loading]);
|
||||
|
||||
const navModel: NavModelItem = {
|
||||
text: plugin?.name ?? '',
|
||||
|
||||
Reference in New Issue
Block a user