mirror of
https://github.com/grafana/grafana.git
synced 2025-09-28 18:54:25 +08:00

* refactor(plugins): use routes specific to the new plugins/admin * refactor(plugins): remove unused pages (PluginList, PluginItem) * refactor(plugins): remove PluginPage * refactor(plugins): remove UpdatePluginModal * refactor(plugins): move AppConfigWrapper under plugins/admin * refactor(plugins): move PluginDashboards under plugins/admin * refactor(plugins): rename the "specs" folder to "tests" * refactor(plugins): move test files to /tests folder * refactor(plugins): move AppRootPage into a /components folder * refactor(plugins): move PluginsErrorsInfo into a /plugins folder * refactor(plugins): move PluginSettingsCache into a /components folder * refactor(plugins): move PluginStateInfo into a /plugins folder * refactor(plugins): move AppRootPage.test.tsx next to the tested component * refactor(plugins): remove old snapshot tests * fix(plugins): fix tests * refactor(plugins/admin): move & rename PluginSettingsCache * fix(plugins): fix a few rebase issues * Plugins: remove deprecated code (state handling) (#41739) * refactor(plugins): use the plugins/admin reducer only * refactor(plugins): remove tests for the deprecated plugins reducer * refactor(plugins): remove tests for the deprecated plugins selectors * refactor(plugins/state): add a short comment note to selectors * feat(plugins/state): add a selector for selecting errors * feat(plugins/state): add a hook for getting plugin errors * refactor(plugins): udpate the PluginsErrorsInfo component to use the new state selectors * refactor(plugins/state): remove the old (deprecated) selectors * refactor(plugins/state): use the new actions under /admin * refactor(plugins/state): remove old (deprecated) reducers and actions * refactor(plugins): update component definition * fix(plugins): remove unnecessary {children} prop for PluginsErrorsInfo * Plugins: show / hide install controls based on the `pluginAdminEnabled` flag (#41749) * docs(plugins): update documentation for the `plugin_admin_enabled` flag * refactor(InstallControls): move the main component to a named module * feat(plugins): use the `pluginAdminEnable` flag to hide / show install controls in the UI * test(plugins): add tests for enabling/disabling install controls
142 lines
3.7 KiB
TypeScript
142 lines
3.7 KiB
TypeScript
import { act, render, screen } from '@testing-library/react';
|
|
import React, { Component } from 'react';
|
|
import AppRootPage from './AppRootPage';
|
|
import { getPluginSettings } from '../pluginSettings';
|
|
import { importAppPlugin } from '../plugin_loader';
|
|
import { getMockPlugin } from '../__mocks__/pluginMocks';
|
|
import { AppPlugin, PluginType, AppRootProps, NavModelItem } from '@grafana/data';
|
|
import { Route, Router } from 'react-router-dom';
|
|
import { locationService, setEchoSrv } from '@grafana/runtime';
|
|
import { GrafanaRoute } from 'app/core/navigation/GrafanaRoute';
|
|
import { Echo } from 'app/core/services/echo/Echo';
|
|
|
|
jest.mock('../pluginSettings', () => ({
|
|
getPluginSettings: jest.fn(),
|
|
}));
|
|
jest.mock('../plugin_loader', () => ({
|
|
importAppPlugin: jest.fn(),
|
|
}));
|
|
|
|
const importAppPluginMock = importAppPlugin as jest.Mock<
|
|
ReturnType<typeof importAppPlugin>,
|
|
Parameters<typeof importAppPlugin>
|
|
>;
|
|
|
|
const getPluginSettingsMock = getPluginSettings as jest.Mock<
|
|
ReturnType<typeof getPluginSettings>,
|
|
Parameters<typeof getPluginSettings>
|
|
>;
|
|
|
|
class RootComponent extends Component<AppRootProps> {
|
|
static timesMounted = 0;
|
|
componentDidMount() {
|
|
RootComponent.timesMounted += 1;
|
|
const node: NavModelItem = {
|
|
text: 'My Great plugin',
|
|
children: [
|
|
{
|
|
text: 'A page',
|
|
url: '/apage',
|
|
id: 'a',
|
|
},
|
|
{
|
|
text: 'Another page',
|
|
url: '/anotherpage',
|
|
id: 'b',
|
|
},
|
|
],
|
|
};
|
|
this.props.onNavChanged({
|
|
main: node,
|
|
node,
|
|
});
|
|
}
|
|
|
|
render() {
|
|
return <p>my great plugin</p>;
|
|
}
|
|
}
|
|
|
|
function renderUnderRouter() {
|
|
const route = { component: AppRootPage };
|
|
locationService.push('/a/my-awesome-plugin');
|
|
|
|
render(
|
|
<Router history={locationService.getHistory()}>
|
|
<Route path="/a/:pluginId" exact render={(props) => <GrafanaRoute {...props} route={route as any} />} />
|
|
</Router>
|
|
);
|
|
}
|
|
|
|
describe('AppRootPage', () => {
|
|
beforeEach(() => {
|
|
jest.resetAllMocks();
|
|
setEchoSrv(new Echo());
|
|
});
|
|
|
|
it('should not mount plugin twice if nav is changed', async () => {
|
|
// reproduces https://github.com/grafana/grafana/pull/28105
|
|
|
|
getPluginSettingsMock.mockResolvedValue(
|
|
getMockPlugin({
|
|
type: PluginType.app,
|
|
enabled: true,
|
|
})
|
|
);
|
|
|
|
const plugin = new AppPlugin();
|
|
plugin.root = RootComponent;
|
|
|
|
importAppPluginMock.mockResolvedValue(plugin);
|
|
|
|
renderUnderRouter();
|
|
|
|
// check that plugin and nav links were rendered, and plugin is mounted only once
|
|
expect(await screen.findByText('my great plugin')).toBeVisible();
|
|
expect(await screen.findByLabelText('Tab A page')).toBeVisible();
|
|
expect(await screen.findByLabelText('Tab Another page')).toBeVisible();
|
|
expect(RootComponent.timesMounted).toEqual(1);
|
|
});
|
|
|
|
it('should not render component if not at plugin path', async () => {
|
|
getPluginSettingsMock.mockResolvedValue(
|
|
getMockPlugin({
|
|
type: PluginType.app,
|
|
enabled: true,
|
|
})
|
|
);
|
|
|
|
class RootComponent extends Component<AppRootProps> {
|
|
static timesRendered = 0;
|
|
render() {
|
|
RootComponent.timesRendered += 1;
|
|
return <p>my great component</p>;
|
|
}
|
|
}
|
|
|
|
const plugin = new AppPlugin();
|
|
plugin.root = RootComponent;
|
|
|
|
importAppPluginMock.mockResolvedValue(plugin);
|
|
|
|
renderUnderRouter();
|
|
|
|
expect(await screen.findByText('my great component')).toBeVisible();
|
|
|
|
// renders the first time
|
|
expect(RootComponent.timesRendered).toEqual(1);
|
|
|
|
await act(async () => {
|
|
locationService.push('/foo');
|
|
});
|
|
|
|
expect(RootComponent.timesRendered).toEqual(1);
|
|
|
|
await act(async () => {
|
|
locationService.push('/a/my-awesome-plugin');
|
|
});
|
|
|
|
expect(RootComponent.timesRendered).toEqual(2);
|
|
});
|
|
});
|