mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 20:59:35 +08:00
239 lines
7.7 KiB
TypeScript
239 lines
7.7 KiB
TypeScript
import { queryByTestId, render, screen } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
|
|
import {
|
|
DataSourceInstanceSettings,
|
|
DataSourcePluginMeta,
|
|
GrafanaConfig,
|
|
PluginMetaInfo,
|
|
PluginType,
|
|
locationUtil,
|
|
} from '@grafana/data';
|
|
import { config } from '@grafana/runtime';
|
|
|
|
import { DataSourceModal, DataSourceModalProps } from './DataSourceModal';
|
|
|
|
const pluginMetaInfo: PluginMetaInfo = {
|
|
author: { name: '' },
|
|
description: '',
|
|
screenshots: [],
|
|
version: '',
|
|
updated: '',
|
|
links: [],
|
|
logos: { small: '', large: '' },
|
|
};
|
|
|
|
function createPluginMeta(name: string, builtIn: boolean): DataSourcePluginMeta {
|
|
return { builtIn, name, id: name, type: PluginType.datasource, baseUrl: '', info: pluginMetaInfo, module: '' };
|
|
}
|
|
|
|
function createDS(name: string, id: number, builtIn: boolean): DataSourceInstanceSettings {
|
|
return {
|
|
name: name,
|
|
uid: name + 'uid',
|
|
meta: createPluginMeta(name, builtIn),
|
|
id,
|
|
access: 'direct',
|
|
jsonData: {},
|
|
type: '',
|
|
readOnly: true,
|
|
};
|
|
}
|
|
|
|
const mockDS1 = createDS('mock.datasource.1', 1, false);
|
|
const mockDS2 = createDS('mock.datasource.2', 2, false);
|
|
const mockDSBuiltIn = createDS('mock.datasource.builtin', 3, true);
|
|
|
|
const mockDSList = [mockDS1, mockDS2, mockDSBuiltIn];
|
|
|
|
const setup = (partialProps: Partial<DataSourceModalProps> = {}) => {
|
|
window.HTMLElement.prototype.scrollIntoView = function () {};
|
|
|
|
const props: DataSourceModalProps = {
|
|
...partialProps,
|
|
onChange: partialProps.onChange || jest.fn(),
|
|
onDismiss: partialProps.onDismiss || jest.fn(),
|
|
current: partialProps.current || mockDS1,
|
|
};
|
|
|
|
return render(<DataSourceModal {...props} />);
|
|
};
|
|
|
|
jest.mock('@grafana/runtime', () => {
|
|
const actual = jest.requireActual('@grafana/runtime');
|
|
return {
|
|
...actual,
|
|
getTemplateSrv: () => {
|
|
return {
|
|
getVariables: () => [],
|
|
};
|
|
},
|
|
};
|
|
});
|
|
|
|
jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => {
|
|
return {
|
|
getDataSourceSrv: () => ({
|
|
getList: getListMock,
|
|
getInstanceSettings: getInstanceSettingsMock,
|
|
}),
|
|
};
|
|
});
|
|
|
|
locationUtil.initialize({
|
|
config: { appSubUrl: '/my-sub-path' } as GrafanaConfig,
|
|
getTimeRangeForUrl: jest.fn(),
|
|
getVariablesUrlParams: jest.fn(),
|
|
});
|
|
|
|
const getListMock = jest.fn();
|
|
const getInstanceSettingsMock = jest.fn();
|
|
beforeEach(() => {
|
|
getListMock.mockReturnValue(mockDSList);
|
|
getInstanceSettingsMock.mockReturnValue(mockDS1);
|
|
});
|
|
|
|
describe('DataSourceDropdown', () => {
|
|
it('should render', () => {
|
|
expect(() => setup()).not.toThrow();
|
|
});
|
|
|
|
describe('configuration', () => {
|
|
it('displays the configure new datasource when the list is empty', async () => {
|
|
const user = userEvent.setup();
|
|
setup();
|
|
const searchBox = await screen.findByRole('searchbox');
|
|
expect(searchBox).toBeInTheDocument();
|
|
await user.click(searchBox!);
|
|
await user.keyboard('foobarbaz'); //Search for a DS that should not exist
|
|
|
|
expect(screen.queryAllByText('Configure a new data source')).toHaveLength(2);
|
|
screen.queryAllByRole('link').forEach((link) => {
|
|
// It should point to the new data source page including any sub url configured
|
|
expect(link).toHaveAttribute('href', '/my-sub-path/connections/datasources/new');
|
|
});
|
|
});
|
|
|
|
it('only displays the file drop area when the ff is enabled', async () => {
|
|
const defaultValue = config.featureToggles.editPanelCSVDragAndDrop;
|
|
config.featureToggles.editPanelCSVDragAndDrop = true;
|
|
setup({ uploadFile: true });
|
|
|
|
expect(await screen.queryByTestId('file-drop-zone-default-children')).toBeInTheDocument();
|
|
config.featureToggles.editPanelCSVDragAndDrop = defaultValue;
|
|
});
|
|
|
|
it('does not show the file drop area when the ff is disabled', async () => {
|
|
const defaultValue = config.featureToggles.editPanelCSVDragAndDrop;
|
|
config.featureToggles.editPanelCSVDragAndDrop = false;
|
|
|
|
setup({ uploadFile: true });
|
|
expect(await screen.queryByTestId('file-drop-zone-default-children')).toBeNull();
|
|
|
|
config.featureToggles.editPanelCSVDragAndDrop = defaultValue;
|
|
});
|
|
|
|
it('should not display the drop zone by default', async () => {
|
|
const defaultValue = config.featureToggles.editPanelCSVDragAndDrop;
|
|
config.featureToggles.editPanelCSVDragAndDrop = true;
|
|
|
|
const component = setup();
|
|
|
|
expect(queryByTestId(component.container, 'file-drop-zone-default-children')).toBeNull();
|
|
config.featureToggles.editPanelCSVDragAndDrop = defaultValue;
|
|
});
|
|
|
|
it('should display the drop zone when uploadFile is enabled', async () => {
|
|
const defaultValue = config.featureToggles.editPanelCSVDragAndDrop;
|
|
config.featureToggles.editPanelCSVDragAndDrop = true;
|
|
setup({ uploadFile: true });
|
|
|
|
expect(await screen.queryByTestId('file-drop-zone-default-children')).toBeInTheDocument();
|
|
config.featureToggles.editPanelCSVDragAndDrop = defaultValue;
|
|
});
|
|
|
|
it('should fetch the DS applying the correct filters consistently across lists', async () => {
|
|
const filters = {
|
|
mixed: true,
|
|
tracing: true,
|
|
dashboard: true,
|
|
metrics: true,
|
|
type: 'foo',
|
|
annotations: true,
|
|
variables: true,
|
|
alerting: true,
|
|
pluginId: 'pluginid',
|
|
logs: true,
|
|
};
|
|
|
|
const props = {
|
|
onChange: () => {},
|
|
onDismiss: () => {},
|
|
current: mockDS1.name,
|
|
...filters,
|
|
};
|
|
|
|
getListMock.mockClear();
|
|
render(<DataSourceModal {...props}></DataSourceModal>);
|
|
|
|
// Every call to the service must contain same filters
|
|
expect(getListMock).toHaveBeenCalled();
|
|
getListMock.mock.calls.forEach((call) =>
|
|
expect(call[0]).toMatchObject({
|
|
...filters,
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('interactions', () => {
|
|
it('should be searchable', async () => {
|
|
const user = userEvent.setup();
|
|
setup();
|
|
const searchBox = await screen.findByRole('searchbox');
|
|
expect(searchBox).toBeInTheDocument();
|
|
await user.click(searchBox!);
|
|
|
|
await user.keyboard(mockDS2.name); //Search for xMockDS
|
|
|
|
expect(screen.queryByText(mockDS1.name, { selector: 'span' })).toBeNull();
|
|
expect(await screen.findByText(mockDS2.name, { selector: 'span' })).toBeInTheDocument();
|
|
|
|
await user.keyboard('foobarbaz'); //Search for a DS that should not exist
|
|
|
|
expect(await screen.findByText('No data sources found')).toBeInTheDocument();
|
|
});
|
|
|
|
//Skipping this test as it's flaky on drone
|
|
it.skip('calls the onChange with the default query containing the file', async () => {
|
|
const user = userEvent.setup();
|
|
config.featureToggles.editPanelCSVDragAndDrop = true;
|
|
const onChange = jest.fn();
|
|
setup({ onChange, uploadFile: true });
|
|
|
|
const fileInput = (
|
|
await screen.queryByTestId('file-drop-zone-default-children')!
|
|
).parentElement!.parentElement!.querySelector('input');
|
|
const file = new File([''], 'test.csv', { type: 'text/plain' });
|
|
expect(fileInput).toBeInTheDocument();
|
|
await user.upload(fileInput!, file);
|
|
const defaultQuery = onChange.mock.lastCall[1][0];
|
|
expect(defaultQuery).toMatchObject({
|
|
refId: 'A',
|
|
datasource: { type: 'grafana', uid: 'grafana' },
|
|
queryType: 'snapshot',
|
|
file: { path: 'test.csv' },
|
|
});
|
|
config.featureToggles.editPanelCSVDragAndDrop = false;
|
|
});
|
|
|
|
it('should call the onChange handler with the correct datasource', async () => {
|
|
const user = userEvent.setup();
|
|
const onChange = jest.fn();
|
|
setup({ onChange });
|
|
await user.click(await screen.findByText(mockDS2.name, { selector: 'span' }));
|
|
expect(onChange.mock.lastCall[0].name).toEqual(mockDS2.name);
|
|
});
|
|
});
|
|
});
|