Files
grafana/public/app/features/plugins/hooks/tests/useImportAppPlugin.test.tsx
Levente Balogh 9a85a2e441 Data Connections: Create a new top-level page (#50018)
* Feature Flags: introduce a flag for enabling the Data Connections page

* Feature Flags: generate schemas

* Navigation: add navigation weight for the Data Connections page

* NavLink: add a comment pointing out where icon names can be looked up

* NavTree: add a new page called Data Connections

* fix(Api): prefix the navigation IDs with the parent ("data-connections")

* feat(Frontend): add a basic page with four tabs

* feat(Plugins): add a hook for importing an app plugin

* feat(Plugins): add a component for loading app plugins anywhere

* feat(Data Connections): load the cloud-onboarding app under the "Cloud onboarding" tab

* feat(Data Connections): generate a proper nav model to highlight active tabs

* test(Data Connections): add tests

* refactor(Data Connections): update temporary text content

This is only used as a placeholder until the tabs are under development.

* refactor(Data Cnnnections): move /pages to /tabs

* refactor(Data Connections): remove the `types.ts` file as it is not referenced by any module

* feat(Data Connections): only register routes if feature is enabled
2022-06-10 12:13:31 +02:00

151 lines
4.7 KiB
TypeScript

import { render, act, waitFor } from '@testing-library/react';
import React from 'react';
import { AppPlugin, PluginType } from '@grafana/data';
import { getMockPlugin } from '../../__mocks__/pluginMocks';
import { getPluginSettings } from '../../pluginSettings';
import { importAppPlugin } from '../../plugin_loader';
import { useImportAppPlugin } from '../useImportAppPlugin';
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>
>;
const PLUGIN_ID = 'sample-plugin';
describe('useImportAppPlugin()', () => {
beforeEach(() => {
jest.resetAllMocks();
});
test('returns the imported plugin in case it exists', async () => {
let response: any;
getPluginSettingsMock.mockResolvedValue(getAppPluginMeta());
importAppPluginMock.mockResolvedValue(getAppPluginMock());
act(() => {
response = runHook(PLUGIN_ID);
});
await waitFor(() => expect(response.value).not.toBeUndefined());
await waitFor(() => expect(response.error).toBeUndefined());
await waitFor(() => expect(response.loading).toBe(false));
});
test('returns an error if the plugin does not exist', async () => {
let response: any;
act(() => {
response = runHook(PLUGIN_ID);
});
await waitFor(() => expect(response.value).toBeUndefined());
await waitFor(() => expect(response.error).not.toBeUndefined());
await waitFor(() => expect(response.error.message).toMatch(/unknown plugin/i));
await waitFor(() => expect(response.loading).toBe(false));
});
test('returns an error if the plugin is not an app', async () => {
let response: any;
getPluginSettingsMock.mockResolvedValue(getAppPluginMeta({ type: PluginType.panel }));
importAppPluginMock.mockResolvedValue(getAppPluginMock());
act(() => {
response = runHook(PLUGIN_ID);
});
await waitFor(() => expect(response.value).toBeUndefined());
await waitFor(() => expect(response.error).not.toBeUndefined());
await waitFor(() => expect(response.error.message).toMatch(/plugin must be an app/i));
await waitFor(() => expect(response.loading).toBe(false));
});
test('returns an error if the plugin is not enabled', async () => {
let response: any;
getPluginSettingsMock.mockResolvedValue(getAppPluginMeta({ enabled: false }));
importAppPluginMock.mockResolvedValue(getAppPluginMock());
act(() => {
response = runHook(PLUGIN_ID);
});
await waitFor(() => expect(response.value).toBeUndefined());
await waitFor(() => expect(response.error).not.toBeUndefined());
await waitFor(() => expect(response.error.message).toMatch(/is not enabled/i));
await waitFor(() => expect(response.loading).toBe(false));
});
test('returns errors that happen during fetching plugin settings', async () => {
let response: any;
const errorMsg = 'Error while fetching plugin data';
getPluginSettingsMock.mockRejectedValue(new Error(errorMsg));
importAppPluginMock.mockResolvedValue(getAppPluginMock());
act(() => {
response = runHook(PLUGIN_ID);
});
await waitFor(() => expect(response.value).toBeUndefined());
await waitFor(() => expect(response.error).not.toBeUndefined());
await waitFor(() => expect(response.error.message).toBe(errorMsg));
await waitFor(() => expect(response.loading).toBe(false));
});
test('returns errors that happen during importing a plugin', async () => {
let response: any;
const errorMsg = 'Error while importing the plugin';
getPluginSettingsMock.mockResolvedValue(getAppPluginMeta());
importAppPluginMock.mockRejectedValue(new Error(errorMsg));
act(() => {
response = runHook(PLUGIN_ID);
});
await waitFor(() => expect(response.value).toBeUndefined());
await waitFor(() => expect(response.error).not.toBeUndefined());
await waitFor(() => expect(response.error.message).toBe(errorMsg));
await waitFor(() => expect(response.loading).toBe(false));
});
});
function runHook(id: string): any {
const returnVal = {};
function TestComponent() {
Object.assign(returnVal, useImportAppPlugin(id));
return null;
}
render(<TestComponent />);
return returnVal;
}
function getAppPluginMeta(overrides?: Record<string, any>) {
return getMockPlugin({
id: PLUGIN_ID,
type: PluginType.app,
enabled: true,
...overrides,
});
}
function getAppPluginMock() {
const plugin = new AppPlugin();
plugin.init(getAppPluginMeta());
return plugin;
}