Chore: Restrict imports of test files to avoid test pollution (#106057)

This commit is contained in:
Tom Ratcliffe 2025-05-28 09:37:15 +01:00 committed by GitHub
parent f6b72a9c96
commit ea0e49a6e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 279 additions and 271 deletions

View File

@ -130,6 +130,11 @@ module.exports = [
importNames: ['Trans'],
message: 'Please import from @grafana/i18n instead',
},
{
regex: '\\.test$',
message:
'Do not import test files. If you require reuse of constants/mocks across files, create a separate file with no tests',
},
],
paths: [
{

View File

@ -1,16 +1,8 @@
import { toDataFrame } from '../../dataframe/processDataFrame';
import { FieldType } from '../../types/dataFrame';
import { fieldMatchers } from '../matchers';
import { FieldMatcherID } from './ids';
export const simpleSeriesWithTypes = toDataFrame({
fields: [
{ name: 'A', type: FieldType.time },
{ name: 'B', type: FieldType.boolean },
{ name: 'C', type: FieldType.string },
],
});
import { simpleSeriesWithTypes } from './mocks';
describe('Field Type Matcher', () => {
const matcher = fieldMatchers.get(FieldMatcherID.byType);

View File

@ -0,0 +1,10 @@
import { toDataFrame } from '../../dataframe/processDataFrame';
import { FieldType } from '../../types/dataFrame';
export const simpleSeriesWithTypes = toDataFrame({
fields: [
{ name: 'A', type: FieldType.time },
{ name: 'B', type: FieldType.boolean },
{ name: 'C', type: FieldType.string },
],
});

View File

@ -2,8 +2,8 @@ import { FieldType } from '../../types/dataFrame';
import { MatcherConfig } from '../../types/transformations';
import { fieldMatchers } from '../matchers';
import { simpleSeriesWithTypes } from './fieldTypeMatcher.test';
import { FieldMatcherID, MatcherID } from './ids';
import { simpleSeriesWithTypes } from './mocks';
const matchesNumberConfig: MatcherConfig = {
id: FieldMatcherID.byType,

View File

@ -1,24 +1,9 @@
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { BackendSrvRequest } from '@grafana/runtime';
import { FetchQueue, FetchQueueUpdate, FetchStatus } from './FetchQueue';
type SubscribeTesterArgs<T> = {
observable: Observable<T>;
expectCallback: (data: T) => void;
doneCallback: jest.DoneCallback;
};
export const subscribeTester = <T>({ observable, expectCallback, doneCallback }: SubscribeTesterArgs<T>) => {
observable.subscribe({
next: (data) => expectCallback(data),
complete: () => {
doneCallback();
},
});
};
import { subscribeTester } from './__mocks__/subscribeTester';
describe('FetchQueue', () => {
describe('add', () => {

View File

@ -4,8 +4,8 @@ import { first } from 'rxjs/operators';
import { BackendSrvRequest } from '@grafana/runtime';
import { FetchQueue, FetchQueueUpdate } from './FetchQueue';
import { subscribeTester } from './FetchQueue.test';
import { ResponseQueue } from './ResponseQueue';
import { subscribeTester } from './__mocks__/subscribeTester';
const getTestContext = () => {
const id = 'id';

View File

@ -0,0 +1,16 @@
import { Observable } from 'rxjs';
type SubscribeTesterArgs<T> = {
observable: Observable<T>;
expectCallback: (data: T) => void;
doneCallback: jest.DoneCallback;
};
export const subscribeTester = <T>({ observable, expectCallback, doneCallback }: SubscribeTesterArgs<T>) => {
observable.subscribe({
next: (data) => expectCallback(data),
complete: () => {
doneCallback();
},
});
};

View File

@ -2,7 +2,7 @@ import { DataQuery } from '@grafana/data';
import { queryIsEmpty } from './query';
export interface TestQuery extends DataQuery {
interface TestQuery extends DataQuery {
name?: string;
}

View File

@ -27,7 +27,7 @@ import { makeExplorePaneState } from '../state/utils';
import { Logs } from './Logs';
import { visualisationTypeKey } from './utils/logs';
import { getMockElasticFrame, getMockLokiFrame } from './utils/testMocks.test';
import { getMockElasticFrame, getMockLokiFrame } from './utils/mocks';
const reportInteraction = jest.fn();
jest.mock('@grafana/runtime', () => ({

View File

@ -9,7 +9,7 @@ import { extractFieldsTransformer } from 'app/features/transformers/extractField
import { parseLogsFrame } from '../../logs/logsFrame';
import { LogsTable } from './LogsTable';
import { getMockElasticFrame, getMockLokiFrame, getMockLokiFrameDataPlane } from './utils/testMocks.test';
import { getMockElasticFrame, getMockLokiFrame, getMockLokiFrameDataPlane } from './utils/mocks';
jest.mock('@grafana/runtime', () => {
const actual = jest.requireActual('@grafana/runtime');

View File

@ -8,7 +8,7 @@ import { config } from '@grafana/runtime';
import { extractFieldsTransformer } from '../../transformers/extractFields/extractFields';
import { LogsTableWrap } from './LogsTableWrap';
import { getMockLokiFrame, getMockLokiFrameDataPlane } from './utils/testMocks.test';
import { getMockLokiFrame, getMockLokiFrameDataPlane } from './utils/mocks';
const getComponent = (partialProps?: Partial<ComponentProps<typeof LogsTableWrap>>) => {
return (

View File

@ -179,13 +179,3 @@ export const getMockElasticFrame = (override?: Partial<DataFrame>, timestamp = 1
};
return { ...testDataFrame, ...override };
};
it('should return a frame', () => {
expect(
getMockLokiFrame({
name: 'test',
})
).toMatchObject({
name: 'test',
});
});

View File

@ -6,6 +6,8 @@ import { TimeRange } from '@grafana/data';
import { configureStore } from '../../../store/configureStore';
// TODO: rebase after https://github.com/grafana/grafana/pull/105711, as this is already fixed
// eslint-disable-next-line no-restricted-imports
import { frameOld } from './TraceView.test';
import { TraceViewContainer } from './TraceViewContainer';

View File

@ -19,7 +19,7 @@ import { useState } from 'react';
import { createTheme } from '@grafana/data';
import { defaultFilters } from '../../../useSearch';
import { trace } from '../TracePageHeader.test';
import { trace } from '../mocks';
import NextPrevResult, { getStyles } from './NextPrevResult';

View File

@ -15,7 +15,7 @@
import { render, screen } from '@testing-library/react';
import { defaultFilters } from '../../../useSearch';
import { trace } from '../TracePageHeader.test';
import { trace } from '../mocks';
import TracePageSearchBar from './TracePageSearchBar';

View File

@ -19,6 +19,7 @@ import { MutableDataFrame } from '@grafana/data';
import { defaultFilters } from '../../useSearch';
import { TracePageHeader } from './TracePageHeader';
import { trace } from './mocks';
const setup = () => {
const defaultProps = {
@ -61,132 +62,3 @@ describe('TracePageHeader test', () => {
expect(timestampPart2).toBeInTheDocument();
});
});
export const trace = {
services: [{ name: 'serviceA', numberOfSpans: 1 }],
spans: [
{
traceID: '164afda25df92413',
spanID: '264afda25df92413',
operationName: 'HTTP Client',
serviceName: 'serviceA',
subsidiarilyReferencedBy: [],
startTime: 1675602037286989,
duration: 5685,
logs: [],
references: [],
tags: [],
processID: '264afda25df92413',
flags: 0,
process: {
serviceName: 'lb',
tags: [],
},
relativeStartTime: 0,
depth: 0,
hasChildren: false,
childSpanCount: 0,
warnings: [],
childSpanIds: [],
},
{
traceID: '164afda25df92413',
spanID: '364afda25df92413',
operationName: 'HTTP Client',
serviceName: 'serviceB',
subsidiarilyReferencedBy: [],
startTime: 1675602037286989,
duration: 5685,
logs: [],
references: [],
tags: [
{
key: 'http.url',
type: 'String',
value: `/v2/gamma/792edh2w897y2huehd2h89`,
},
{
key: 'http.method',
type: 'String',
value: `POST`,
},
{
key: 'http.status_code',
type: 'String',
value: `200`,
},
],
processID: '364afda25df92413',
flags: 0,
process: {
serviceName: 'lb',
tags: [],
},
relativeStartTime: 0,
depth: 0,
hasChildren: false,
childSpanCount: 0,
warnings: [],
childSpanIds: [],
},
{
traceID: '164afda25df92413',
spanID: '464afda25df92413',
operationName: 'HTTP Server',
serviceName: 'serviceC',
subsidiarilyReferencedBy: [],
startTime: 1675602037286989,
duration: 5685,
logs: [],
references: [],
tags: [
{
key: 'http.url',
type: 'String',
value: `/v2/gamma/792edh2w897y2huehd2h89`,
},
{
key: 'http.method',
type: 'String',
value: `POST`,
},
{
key: 'http.status_code',
type: 'String',
value: `200`,
},
],
processID: '464afda25df92413',
flags: 0,
process: {
serviceName: 'db',
tags: [],
},
relativeStartTime: 0,
depth: 0,
hasChildren: false,
childSpanCount: 0,
warnings: [],
childSpanIds: [],
},
],
traceID: '8bb35a31-eb64-512d-aaed-ddd61887bb2b',
traceName: 'serviceA: GET',
processes: {
'264afda25df92413': {
serviceName: 'serviceA',
tags: [],
},
'364afda25df92413': {
serviceName: 'serviceB',
tags: [],
},
'464afda25df92413': {
serviceName: 'serviceC',
tags: [],
},
},
duration: 2355515,
startTime: 1675605056289000,
endTime: 1675605058644515,
};

View File

@ -0,0 +1,128 @@
export const trace = {
services: [{ name: 'serviceA', numberOfSpans: 1 }],
spans: [
{
traceID: '164afda25df92413',
spanID: '264afda25df92413',
operationName: 'HTTP Client',
serviceName: 'serviceA',
subsidiarilyReferencedBy: [],
startTime: 1675602037286989,
duration: 5685,
logs: [],
references: [],
tags: [],
processID: '264afda25df92413',
flags: 0,
process: {
serviceName: 'lb',
tags: [],
},
relativeStartTime: 0,
depth: 0,
hasChildren: false,
childSpanCount: 0,
warnings: [],
childSpanIds: [],
},
{
traceID: '164afda25df92413',
spanID: '364afda25df92413',
operationName: 'HTTP Client',
serviceName: 'serviceB',
subsidiarilyReferencedBy: [],
startTime: 1675602037286989,
duration: 5685,
logs: [],
references: [],
tags: [
{
key: 'http.url',
type: 'String',
value: `/v2/gamma/792edh2w897y2huehd2h89`,
},
{
key: 'http.method',
type: 'String',
value: `POST`,
},
{
key: 'http.status_code',
type: 'String',
value: `200`,
},
],
processID: '364afda25df92413',
flags: 0,
process: {
serviceName: 'lb',
tags: [],
},
relativeStartTime: 0,
depth: 0,
hasChildren: false,
childSpanCount: 0,
warnings: [],
childSpanIds: [],
},
{
traceID: '164afda25df92413',
spanID: '464afda25df92413',
operationName: 'HTTP Server',
serviceName: 'serviceC',
subsidiarilyReferencedBy: [],
startTime: 1675602037286989,
duration: 5685,
logs: [],
references: [],
tags: [
{
key: 'http.url',
type: 'String',
value: `/v2/gamma/792edh2w897y2huehd2h89`,
},
{
key: 'http.method',
type: 'String',
value: `POST`,
},
{
key: 'http.status_code',
type: 'String',
value: `200`,
},
],
processID: '464afda25df92413',
flags: 0,
process: {
serviceName: 'db',
tags: [],
},
relativeStartTime: 0,
depth: 0,
hasChildren: false,
childSpanCount: 0,
warnings: [],
childSpanIds: [],
},
],
traceID: '8bb35a31-eb64-512d-aaed-ddd61887bb2b',
traceName: 'serviceA: GET',
processes: {
'264afda25df92413': {
serviceName: 'serviceA',
tags: [],
},
'364afda25df92413': {
serviceName: 'serviceB',
tags: [],
},
'464afda25df92413': {
serviceName: 'serviceC',
tags: [],
},
},
duration: 2355515,
startTime: 1675605056289000,
endTime: 1675605058644515,
};

View File

@ -1,11 +1,14 @@
import { DataSourceApi, DataSourceWithQueryExportSupport, DataSourceWithQueryImportSupport } from '@grafana/data';
import { ExpressionDatasourceRef } from '@grafana/runtime/internal';
import { DataQuery } from '@grafana/schema';
import { TestQuery } from 'app/core/utils/query.test';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { updateQueries } from './updateQueries';
interface TestQuery extends DataQuery {
name?: string;
}
const oldUidDS = {
uid: 'old-uid',
type: 'old-type',

View File

@ -6,9 +6,9 @@ import { dateTime, LoadingState } from '@grafana/data';
import createMockDatasource from '../../__mocks__/datasource';
import createMockQuery from '../../__mocks__/query';
import { ResultFormat } from '../../dataquery.gen';
import { createMockResourcePickerData } from '../MetricsQueryEditor/MetricsQueryEditor.test';
import LogsQueryEditor from './LogsQueryEditor';
import { createMockResourcePickerData } from './mocks';
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),

View File

@ -0,0 +1,26 @@
import createMockDatasource from '../../__mocks__/datasource';
import { createMockInstanceSetttings } from '../../__mocks__/instanceSettings';
import {
createMockSubscriptions,
createMockResourceGroupsBySubscription,
mockResourcesByResourceGroup,
} from '../../__mocks__/resourcePickerRows';
import ResourcePickerData from '../../resourcePicker/resourcePickerData';
export function createMockResourcePickerData() {
const mockDatasource = createMockDatasource();
const mockResourcePicker = new ResourcePickerData(
createMockInstanceSetttings(),
mockDatasource.azureMonitorDatasource,
mockDatasource.azureResourceGraphDatasource
);
mockResourcePicker.getSubscriptions = jest.fn().mockResolvedValue(createMockSubscriptions());
mockResourcePicker.getResourceGroupsBySubscriptionId = jest
.fn()
.mockResolvedValue(createMockResourceGroupsBySubscription());
mockResourcePicker.getResourcesForResourceGroup = jest.fn().mockResolvedValue(mockResourcesByResourceGroup());
mockResourcePicker.getResourceURIFromWorkspace = jest.fn().mockReturnValue('');
mockResourcePicker.getResourceURIDisplayProperties = jest.fn().mockResolvedValue({});
return mockResourcePicker;
}

View File

@ -2,17 +2,11 @@ import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import createMockDatasource from '../../__mocks__/datasource';
import { createMockInstanceSetttings } from '../../__mocks__/instanceSettings';
import createMockPanelData from '../../__mocks__/panelData';
import createMockQuery from '../../__mocks__/query';
import {
createMockResourceGroupsBySubscription,
createMockSubscriptions,
mockResourcesByResourceGroup,
} from '../../__mocks__/resourcePickerRows';
import { selectors } from '../../e2e/selectors';
import ResourcePickerData from '../../resourcePicker/resourcePickerData';
import { selectOptionInTest } from '../../utils/testUtils';
import { createMockResourcePickerData } from '../LogsQueryEditor/mocks';
import MetricsQueryEditor from './MetricsQueryEditor';
@ -30,24 +24,6 @@ const variableOptionGroup = {
options: [],
};
export function createMockResourcePickerData() {
const mockDatasource = createMockDatasource();
const mockResourcePicker = new ResourcePickerData(
createMockInstanceSetttings(),
mockDatasource.azureMonitorDatasource,
mockDatasource.azureResourceGraphDatasource
);
mockResourcePicker.getSubscriptions = jest.fn().mockResolvedValue(createMockSubscriptions());
mockResourcePicker.getResourceGroupsBySubscriptionId = jest
.fn()
.mockResolvedValue(createMockResourceGroupsBySubscription());
mockResourcePicker.getResourcesForResourceGroup = jest.fn().mockResolvedValue(mockResourcesByResourceGroup());
mockResourcePicker.getResourceURIFromWorkspace = jest.fn().mockReturnValue('');
mockResourcePicker.getResourceURIDisplayProperties = jest.fn().mockResolvedValue({});
return mockResourcePicker;
}
describe('MetricsQueryEditor', () => {
const originalScrollIntoView = window.HTMLElement.prototype.scrollIntoView;
const mockPanelData = createMockPanelData();

View File

@ -10,7 +10,7 @@ import createMockQuery from '../../__mocks__/query';
import { selectors } from '../../e2e/selectors';
import { AzureQueryType, ResultFormat } from '../../types';
import { selectOptionInTest } from '../../utils/testUtils';
import { createMockResourcePickerData } from '../MetricsQueryEditor/MetricsQueryEditor.test';
import { createMockResourcePickerData } from '../LogsQueryEditor/mocks';
import QueryEditor from './QueryEditor';

View File

@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';
import createMockDatasource from '../../__mocks__/datasource';
import createMockQuery from '../../__mocks__/query';
import { createMockResourcePickerData } from '../MetricsQueryEditor/MetricsQueryEditor.test';
import { createMockResourcePickerData } from '../LogsQueryEditor/mocks';
import TracesQueryEditor from './TracesQueryEditor';

View File

@ -4,7 +4,7 @@ import userEvent from '@testing-library/user-event';
import { CoreApp, PluginType } from '@grafana/data';
import { PyroscopeDataSource } from '../datasource';
import { mockFetchPyroscopeDatasourceSettings } from '../datasource.test';
import { mockFetchPyroscopeDatasourceSettings } from '../mocks';
import { ProfileTypeMessage } from '../types';
import { Props, QueryEditor } from './QueryEditor';

View File

@ -1,38 +1,11 @@
import {
AbstractLabelOperator,
CoreApp,
DataSourceInstanceSettings,
PluginMetaInfo,
PluginType,
DataSourceJsonData,
makeTimeRange,
} from '@grafana/data';
import { getBackendSrv, setBackendSrv, TemplateSrv } from '@grafana/runtime';
import { AbstractLabelOperator, CoreApp, makeTimeRange } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime';
import { defaultPyroscopeQueryType } from './dataquery.gen';
import { normalizeQuery, PyroscopeDataSource } from './datasource';
import { defaultSettings, mockFetchPyroscopeDatasourceSettings } from './mocks';
import { Query } from './types';
/** The datasource QueryEditor fetches datasource settings to send to the extension's `configure` method */
export function mockFetchPyroscopeDatasourceSettings(
datasourceSettings?: Partial<DataSourceInstanceSettings<DataSourceJsonData>>
) {
const settings = { ...defaultSettings, ...datasourceSettings };
const returnValues: Record<string, unknown> = {
[`/api/datasources/uid/${settings.uid}`]: settings,
};
setBackendSrv({
...getBackendSrv(),
get: function <T>(path: string) {
const value = returnValues[path];
if (value) {
return Promise.resolve(value as T);
}
return Promise.reject({ message: 'reject' });
},
});
}
function setupDatasource() {
mockFetchPyroscopeDatasourceSettings();
const templateSrv = {
@ -175,21 +148,3 @@ const defaultQuery = (query: Partial<Query>): Query => {
...query,
};
};
const defaultSettings: DataSourceInstanceSettings = {
id: 0,
uid: 'pyroscope',
type: 'profiling',
name: 'pyroscope',
access: 'proxy',
meta: {
id: 'pyroscope',
name: 'pyroscope',
type: PluginType.datasource,
info: {} as PluginMetaInfo,
module: '',
baseUrl: '',
},
jsonData: {},
readOnly: false,
};

View File

@ -0,0 +1,41 @@
import { DataSourceInstanceSettings, DataSourceJsonData, PluginMetaInfo, PluginType } from '@grafana/data';
import { setBackendSrv, getBackendSrv } from '@grafana/runtime';
export const defaultSettings: DataSourceInstanceSettings = {
id: 0,
uid: 'pyroscope',
type: 'profiling',
name: 'pyroscope',
access: 'proxy',
meta: {
id: 'pyroscope',
name: 'pyroscope',
type: PluginType.datasource,
info: {} as PluginMetaInfo,
module: '',
baseUrl: '',
},
jsonData: {},
readOnly: false,
};
/** The datasource QueryEditor fetches datasource settings to send to the extension's `configure` method */
export function mockFetchPyroscopeDatasourceSettings(
datasourceSettings?: Partial<DataSourceInstanceSettings<DataSourceJsonData>>
) {
const settings = { ...defaultSettings, ...datasourceSettings };
const returnValues: Record<string, unknown> = {
[`/api/datasources/uid/${settings.uid}`]: settings,
};
setBackendSrv({
...getBackendSrv(),
get: function <T>(path: string) {
const value = returnValues[path];
if (value) {
return Promise.resolve(value as T);
}
return Promise.reject({ message: 'reject' });
},
});
}

View File

@ -8,7 +8,7 @@ import { initTemplateSrv } from '../test/test_utils';
import { Scope } from '../types';
import TagsInput from './TagsInput';
import { v1Tags, v2Tags } from './utils.test';
import { v1Tags, v2Tags } from './mocks';
describe('TagsInput', () => {
let user: ReturnType<typeof userEvent.setup>;

View File

@ -0,0 +1,24 @@
import { uniq } from 'lodash';
import { intrinsics } from '../traceql/traceql';
export const testIntrinsics = uniq(['duration', 'kind', 'name', 'status'].concat(intrinsics));
export const v1Tags = ['bar', 'foo'];
export const v2Tags = [
{
name: 'resource',
tags: ['cluster', 'container'],
},
{
name: 'span',
tags: ['db'],
},
{
name: 'intrinsic',
tags: testIntrinsics,
},
];
export const emptyTags = [];

View File

@ -5,6 +5,7 @@ import { TempoDatasource } from '../datasource';
import TempoLanguageProvider from '../language_provider';
import { intrinsics } from '../traceql/traceql';
import { emptyTags, testIntrinsics, v1Tags, v2Tags } from './mocks';
import {
filterToQuerySection,
getAllTags,
@ -155,21 +156,3 @@ describe('filterToQuerySection returns the correct query section for a filter',
expect(result).toBe('span.foo=~"bar|baz"');
});
});
export const emptyTags = [];
export const testIntrinsics = uniq(['duration', 'kind', 'name', 'status'].concat(intrinsics));
export const v1Tags = ['bar', 'foo'];
export const v2Tags = [
{
name: 'resource',
tags: ['cluster', 'container'],
},
{
name: 'span',
tags: ['db'],
},
{
name: 'intrinsic',
tags: testIntrinsics,
},
];

View File

@ -1,6 +1,6 @@
import { uniq } from 'lodash';
import { v1Tags, v2Tags } from './SearchTraceQLEditor/utils.test';
import { v1Tags, v2Tags } from './SearchTraceQLEditor/mocks';
import { TraceqlSearchScope } from './dataquery.gen';
import { TempoDatasource } from './datasource';
import TempoLanguageProvider from './language_provider';

View File

@ -1,7 +1,7 @@
import { DataSourceInstanceSettings, PluginMetaInfo, PluginType } from '@grafana/data';
import { monacoTypes } from '@grafana/ui';
import { emptyTags, testIntrinsics, v1Tags, v2Tags } from '../SearchTraceQLEditor/utils.test';
import { v1Tags, v2Tags, emptyTags, testIntrinsics } from '../SearchTraceQLEditor/mocks';
import { TempoDatasource } from '../datasource';
import TempoLanguageProvider from '../language_provider';
import { Scope, TempoJsonData } from '../types';