diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryEditor.tsx b/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryEditor.tsx index bcc03a1a913..c62defc81ce 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryEditor.tsx +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryEditor.tsx @@ -12,7 +12,6 @@ import { EditorRow } from './EditorRow'; import { EditorRows } from './EditorRows'; import { LabelsEditor } from './LabelsEditor'; import { ProfileTypesCascader, useProfileTypes } from './ProfileTypesCascader'; -import { PyroscopeQueryLinkExtensions } from './QueryLinkExtension'; import { QueryOptions } from './QueryOptions'; export type Props = QueryEditorProps; @@ -62,7 +61,6 @@ export function QueryEditor(props: Props) { labels={labels} getLabelValues={getLabelValues} /> - diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryLinkExtension.test.tsx b/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryLinkExtension.test.tsx deleted file mode 100644 index dd57142644a..00000000000 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryLinkExtension.test.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import React from 'react'; -import { act } from 'react-dom/test-utils'; - -import { PluginType, rangeUtil, PluginExtensionLink, PluginExtensionTypes } from '@grafana/data'; -import { usePluginLinkExtensions } from '@grafana/runtime'; - -import { PyroscopeDataSource } from '../datasource'; -import { mockFetchPyroscopeDatasourceSettings } from '../datasource.test'; - -import { Props, PyroscopeQueryLinkExtensions, resetPyroscopeQueryLinkExtensionsFetches } from './QueryLinkExtension'; - -// Constants copied from `QueryLinkExtension.tsx` -const EXTENSION_POINT_ID = 'plugins/grafana-pyroscope-datasource/query-links'; - -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - usePluginLinkExtensions: jest.fn(), - getTemplateSrv: () => { - return { - replace: (query: string): string => { - return query.replace(/\$var/g, 'interpolated'); - }, - }; - }, -})); - -const usePluginLinkExtensionsMock = jest.mocked(usePluginLinkExtensions); - -const defaultPyroscopeDataSourceSettings = { - uid: 'default-pyroscope', - url: 'http://pyroscope', - basicAuthUser: 'pyroscope_user', -}; - -describe('PyroscopeQueryLinkExtensions', () => { - const EXPECTED_BUTTON_LABEL = 'Profiles App'; - const DEFAULT_EXTENSION_PATH = 'a/mock-path-app/fake-path'; - - function createExtension(overrides?: Partial) { - return { - ...{ - description: 'unremarkable-description', - extensionPointId: EXTENSION_POINT_ID, - title: EXPECTED_BUTTON_LABEL, - path: DEFAULT_EXTENSION_PATH, - type: PluginExtensionTypes.link, - category: 'unremarkable-category', - icon: 'heart', - onClick() {}, - pluginId: 'mock-path-app', - id: `${Date.now()}}`, - }, - ...overrides, - } as PluginExtensionLink; - } - - beforeEach(() => { - resetPyroscopeQueryLinkExtensionsFetches(); - mockFetchPyroscopeDatasourceSettings(defaultPyroscopeDataSourceSettings); - - usePluginLinkExtensionsMock.mockRestore(); - usePluginLinkExtensionsMock.mockReturnValue({ extensions: [], isLoading: false }); // Unless stated otherwise, no extensions - }); - - it('should render if extension present', async () => { - usePluginLinkExtensionsMock.mockReturnValue({ extensions: [createExtension()], isLoading: false }); // Default extension - - await act(setup); - expect(await screen.findAllByText(EXPECTED_BUTTON_LABEL)).toBeDefined(); - }); - - it('Should not render if no extension present', async () => { - await act(setup); - expect(screen.queryByText(EXPECTED_BUTTON_LABEL)).toBeNull(); - }); -}); - -function setupDs() { - const ds = new PyroscopeDataSource({ - ...defaultPyroscopeDataSourceSettings, - name: 'test', - type: PluginType.datasource, - access: 'proxy', - id: 1, - jsonData: {}, - meta: { - name: '', - id: '', - type: PluginType.datasource, - baseUrl: '', - info: { - author: { - name: '', - }, - description: '', - links: [], - logos: { - large: '', - small: '', - }, - screenshots: [], - updated: '', - version: '', - }, - module: '', - }, - readOnly: false, - }); - - return ds; -} - -async function setup(options: { props: Partial } = { props: {} }) { - const utils = render( - - ); - return { ...utils }; -} diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryLinkExtension.tsx b/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryLinkExtension.tsx deleted file mode 100644 index 8a6761966df..00000000000 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryLinkExtension.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { css } from '@emotion/css'; -import React from 'react'; -import { useAsync } from 'react-use'; - -import { GrafanaTheme2, QueryEditorProps, TimeRange } from '@grafana/data'; -import { getBackendSrv, usePluginLinkExtensions } from '@grafana/runtime'; -import { LinkButton, useStyles2 } from '@grafana/ui'; - -import { PyroscopeDataSource } from '../datasource'; -import { PyroscopeDataSourceOptions, Query } from '../types'; - -const EXTENSION_POINT_ID = 'plugins/grafana-pyroscope-datasource/query-links'; - -/** A subset of the datasource settings that are relevant for this integration */ -type PyroscopeDatasourceSettings = { - uid: string; - url: string; - type: string; - basicAuthUser: string; -}; - -/** The context object that will be shared with the link extension's configure function */ -type ExtensionQueryLinksContext = { - datasourceUid: string; - query: Query; - range?: TimeRange | undefined; - datasourceSettings?: PyroscopeDatasourceSettings; -}; - -/* Global promises to fetch pyroscope datasource settings by uid as encountered */ -const pyroscopeDatasourceSettingsByUid: Record = {}; - -/* Reset promises for testing purposes */ -export function resetPyroscopeQueryLinkExtensionsFetches() { - Object.keys(pyroscopeDatasourceSettingsByUid).forEach((key) => delete pyroscopeDatasourceSettingsByUid[key]); -} - -/** A subset of the `PyroscopeDataSource` `QueryEditorProps` */ -export type Props = Pick< - QueryEditorProps, - 'datasource' | 'query' | 'range' ->; - -export function PyroscopeQueryLinkExtensions(props: Props) { - const { - datasource: { uid: datasourceUid }, - query, - range, - } = props; - - const { value: datasourceSettings } = useAsync(async () => { - if (pyroscopeDatasourceSettingsByUid[datasourceUid]) { - return pyroscopeDatasourceSettingsByUid[datasourceUid]; - } - const settings = await getBackendSrv().get(`/api/datasources/uid/${datasourceUid}`); - pyroscopeDatasourceSettingsByUid[datasourceUid] = settings; - return settings; - }, [datasourceUid]); - - const context: ExtensionQueryLinksContext = { - datasourceUid, - query, - range, - datasourceSettings, - }; - - const { extensions } = usePluginLinkExtensions({ - extensionPointId: EXTENSION_POINT_ID, - context, - }); - - const styles = useStyles2(getStyles); - - if (extensions.length === 0) { - return null; - } - - return ( - <> - {extensions.map((extension) => ( - - {extension.title} - - ))} - - ); -} - -function getStyles(theme: GrafanaTheme2) { - return { - linkButton: css({ - marginLeft: theme.spacing(1), - }), - }; -}