2025-04-01 10:38:02 +09:00

226 lines
6.3 KiB
TypeScript

import { act, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { of } from 'rxjs';
import {
AnnotationQuery,
FieldType,
LoadingState,
PanelData,
VariableSupportType,
getDefaultTimeRange,
toDataFrame,
} from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { setRunRequest } from '@grafana/runtime';
import { mockDataSource } from 'app/features/alerting/unified/mocks';
import { LegacyVariableQueryEditor } from 'app/features/variables/editor/LegacyVariableQueryEditor';
import { AnnotationSettingsEdit } from './AnnotationSettingsEdit';
const defaultDatasource = mockDataSource({
name: 'Default Test Data Source',
type: 'test',
});
const promDatasource = mockDataSource({
name: 'Prometheus',
type: 'prometheus',
});
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getAngularLoader: () => ({
load: () => ({
destroy: jest.fn(),
digest: jest.fn(),
getScope: () => ({
$watch: jest.fn(),
}),
}),
}),
}));
jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => ({
...jest.requireActual('@grafana/runtime/src/services/dataSourceSrv'),
getDataSourceSrv: () => ({
get: async () => ({
...defaultDatasource,
variables: {
getType: () => VariableSupportType.Custom,
query: jest.fn(),
editor: jest.fn().mockImplementation(LegacyVariableQueryEditor),
},
}),
getList: () => [defaultDatasource, promDatasource],
getInstanceSettings: () => ({ ...defaultDatasource }),
}),
}));
jest.mock('./AngularEditorLoader', () => ({ AngularEditorLoader: () => 'mocked AngularEditorLoader' }));
const runRequestMock = jest.fn().mockReturnValue(
of<PanelData>({
state: LoadingState.Done,
series: [
toDataFrame({
fields: [{ name: 'text', type: FieldType.string, values: ['val1', 'val2', 'val11'] }],
}),
],
timeRange: getDefaultTimeRange(),
})
);
setRunRequest(runRequestMock);
describe('AnnotationSettingsEdit', () => {
const mockOnUpdate = jest.fn();
const mockGoBackToList = jest.fn();
const mockOnDelete = jest.fn();
async function setup() {
const annotationQuery: AnnotationQuery = {
name: 'test',
datasource: defaultDatasource,
enable: true,
hide: false,
iconColor: 'blue',
};
const props = {
annotation: annotationQuery,
onUpdate: mockOnUpdate,
editIndex: 1,
panels: [],
onBackToList: mockGoBackToList,
onDelete: mockOnDelete,
};
return {
anno: annotationQuery,
renderer: await act(async () => render(<AnnotationSettingsEdit {...props} />)),
user: userEvent.setup(),
};
}
afterEach(() => {
jest.clearAllMocks();
});
it('should render', async () => {
const {
renderer: { getByTestId },
} = await setup();
const nameInput = getByTestId(selectors.pages.Dashboard.Settings.Annotations.Settings.name);
const dataSourceSelect = getByTestId(selectors.components.DataSourcePicker.container);
const enableToggle = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.enable);
const hideToggle = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.hide);
const iconColorToggle = getByTestId(selectors.components.ColorSwatch.name);
const panelSelect = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.showInLabel);
const deleteAnno = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.delete);
const apply = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.apply);
expect(nameInput).toBeInTheDocument();
expect(dataSourceSelect).toBeInTheDocument();
expect(enableToggle).toBeInTheDocument();
expect(hideToggle).toBeInTheDocument();
expect(iconColorToggle).toBeInTheDocument();
expect(panelSelect).toBeInTheDocument();
expect(deleteAnno).toBeInTheDocument();
expect(apply).toBeInTheDocument();
});
it('should update annotation name on change', async () => {
const {
renderer: { getByTestId },
user,
} = await setup();
await user.type(getByTestId(selectors.pages.Dashboard.Settings.Annotations.Settings.name), 'new name');
expect(mockOnUpdate).toHaveBeenCalled();
});
it('should toggle annotation enabled on change', async () => {
const {
renderer: { getByTestId },
user,
anno,
} = await setup();
const annoArg = {
...anno,
enable: !anno.enable,
};
const enableToggle = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.enable);
await user.click(enableToggle);
expect(mockOnUpdate).toHaveBeenCalledTimes(1);
expect(mockOnUpdate).toHaveBeenCalledWith(annoArg, 1);
});
it('should toggle annotation hide on change', async () => {
const {
renderer: { getByTestId },
user,
anno,
} = await setup();
const annoArg = {
...anno,
hide: !anno.hide,
};
const hideToggle = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.hide);
await user.click(hideToggle);
expect(mockOnUpdate).toHaveBeenCalledTimes(1);
expect(mockOnUpdate).toHaveBeenCalledWith(annoArg, 1);
});
it('should set annotation filter', async () => {
const {
renderer: { getByTestId },
user,
} = await setup();
const panelSelect = getByTestId(selectors.components.Annotations.annotationsTypeInput);
await user.click(panelSelect);
await user.tab();
expect(mockOnUpdate).toHaveBeenCalledTimes(1);
expect(mockOnUpdate).toHaveBeenCalledWith(expect.objectContaining({ filter: undefined }), 1);
});
it('should delete annotation', async () => {
const {
renderer: { getByTestId },
user,
} = await setup();
const deleteAnno = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.delete);
await user.click(deleteAnno);
expect(mockOnDelete).toHaveBeenCalledTimes(1);
});
it('should go back to list annotation', async () => {
const {
renderer: { getByTestId },
user,
} = await setup();
const goBack = getByTestId(selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.apply);
await user.click(goBack);
expect(mockGoBackToList).toHaveBeenCalledTimes(1);
});
});