Explore: Unify spec setup (#73994)

* Simplify Explore spec setup

* Update public/app/features/explore/spec/helper/setup.tsx

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

---------

Co-authored-by: Giordano Ricci <me@giordanoricci.com>
This commit is contained in:
Piotr Jamróz
2023-09-05 13:05:11 +02:00
committed by GitHub
co-authored by Giordano Ricci
parent c8c9b6b767
commit 975edf14dc
6 changed files with 80 additions and 63 deletions
@@ -6,12 +6,6 @@ import { changeDatasource } from './helper/interactions';
import { makeLogsQueryResponse } from './helper/query';
import { setupExplore, tearDown, waitForExplore } from './helper/setup';
jest.mock('../../correlations/utils', () => {
return {
getCorrelationsBySourceUIDs: jest.fn().mockReturnValue({ correlations: [] }),
};
});
const testEventBus = new EventBusSrv();
jest.mock('@grafana/runtime', () => ({
@@ -6,6 +6,7 @@ import { stringify } from 'querystring';
import React from 'react';
import { Provider } from 'react-redux';
import { Route, Router } from 'react-router-dom';
import { of } from 'rxjs';
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
import {
@@ -18,10 +19,15 @@ import {
import {
setDataSourceSrv,
setEchoSrv,
setLocationService,
locationService,
HistoryWrapper,
LocationService,
setPluginExtensionGetter,
setBackendSrv,
getBackendSrv,
getDataSourceSrv,
getEchoSrv,
setLocationService,
} from '@grafana/runtime';
import { DataSourceRef } from '@grafana/schema';
import { GrafanaContext } from 'app/core/context/GrafanaContext';
@@ -31,6 +37,7 @@ import { setLastUsedDatasourceUID } from 'app/core/utils/explore';
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
import { configureStore } from 'app/store/configureStore';
import { RichHistoryRemoteStorageDTO } from '../../../../core/history/RichHistoryRemoteStorage';
import { LokiDatasource } from '../../../../plugins/datasource/loki/datasource';
import { LokiQuery } from '../../../../plugins/datasource/loki/types';
import { ExploreQueryParams } from '../../../../types';
@@ -42,10 +49,15 @@ type DatasourceSetup = { settings: DataSourceInstanceSettings; api: DataSourceAp
type SetupOptions = {
clearLocalStorage?: boolean;
datasources?: DatasourceSetup[];
queryHistory?: { queryHistory: Array<Partial<RichHistoryRemoteStorageDTO>>; totalCount: number };
urlParams?: ExploreQueryParams;
prevUsedDatasource?: { orgId: number; datasource: string };
};
type TearDownOptions = {
clearLocalStorage?: boolean;
};
export function setupExplore(options?: SetupOptions): {
datasources: { [uid: string]: DataSourceApi };
store: ReturnType<typeof configureStore>;
@@ -53,6 +65,27 @@ export function setupExplore(options?: SetupOptions): {
container: HTMLElement;
location: LocationService;
} {
const previousBackendSrv = getBackendSrv();
setBackendSrv({
datasourceRequest: jest.fn().mockRejectedValue(undefined),
delete: jest.fn().mockRejectedValue(undefined),
fetch: jest.fn().mockImplementation((req) => {
const data: Record<string, object | number> = {};
if (req.url.startsWith('/api/datasources/correlations') && req.method === 'GET') {
data.correlations = [];
data.totalCount = 0;
} else if (req.url.startsWith('/api/query-history') && req.method === 'GET') {
data.result = options?.queryHistory || {};
}
return of({ data });
}),
get: jest.fn(),
patch: jest.fn().mockRejectedValue(undefined),
post: jest.fn(),
put: jest.fn().mockRejectedValue(undefined),
request: jest.fn().mockRejectedValue(undefined),
});
setPluginExtensionGetter(() => ({ extensions: [] }));
// Clear this up otherwise it persists data source selection
@@ -74,6 +107,8 @@ export function setupExplore(options?: SetupOptions): {
const dsSettings = options?.datasources || defaultDatasources;
const previousDataSourceSrv = getDataSourceSrv();
setDataSourceSrv({
getList(): DataSourceInstanceSettings[] {
return dsSettings.map((d) => d.settings);
@@ -103,6 +138,7 @@ export function setupExplore(options?: SetupOptions): {
reload() {},
});
const previousEchoSrv = getEchoSrv();
setEchoSrv(new Echo());
const storeState = configureStore();
@@ -145,6 +181,16 @@ export function setupExplore(options?: SetupOptions): {
</Provider>
);
exploreTestsHelper.tearDownExplore = (options?: TearDownOptions) => {
setDataSourceSrv(previousDataSourceSrv);
setEchoSrv(previousEchoSrv);
setBackendSrv(previousBackendSrv);
setLocationService(locationService);
if (options?.clearLocalStorage !== false) {
window.localStorage.clear();
}
};
return {
datasources: fromPairs(dsSettings.map((d) => [d.api.name, d.api])),
store: storeState,
@@ -227,11 +273,17 @@ export const waitForExplore = (exploreId = 'left') => {
});
};
export const tearDown = () => {
window.localStorage.clear();
export const tearDown = (options?: TearDownOptions) => {
exploreTestsHelper.tearDownExplore?.(options);
};
export const withinExplore = (exploreId: string) => {
const container = screen.getAllByTestId('data-testid Explore');
return within(container[exploreId === 'left' ? 0 : 1]);
};
const exploreTestsHelper: { setupExplore: typeof setupExplore; tearDownExplore?: (options?: TearDownOptions) => void } =
{
setupExplore,
tearDownExplore: undefined,
};
@@ -6,14 +6,12 @@ import { getTemplateSrv } from '@grafana/runtime';
import { LokiQuery } from '../../../plugins/datasource/loki/types';
import { makeLogsQueryResponse } from './helper/query';
import { setupExplore, waitForExplore } from './helper/setup';
import { setupExplore, tearDown, waitForExplore } from './helper/setup';
const testEventBus = new EventBusSrv();
const fetch = jest.fn();
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getBackendSrv: () => ({ fetch }),
getAppEvents: () => testEventBus,
}));
@@ -33,13 +31,11 @@ jest.mock('react-virtualized-auto-sizer', () => {
};
});
jest.mock('../../correlations/utils', () => {
return {
getCorrelationsBySourceUIDs: jest.fn().mockReturnValue({ correlations: [] }),
};
});
describe('Explore: interpolation', () => {
afterEach(() => {
tearDown();
});
// support-escalations/issues/1459
it('Time is interpolated when explore is opened with a URL', async () => {
const urlParams = {
@@ -12,19 +12,6 @@ jest.mock('@grafana/runtime', () => ({
getAppEvents: () => testEventBus,
}));
jest.mock('../../correlations/utils', () => {
return {
getCorrelationsBySourceUIDs: jest.fn().mockReturnValue({ correlations: [] }),
};
});
jest.mock('app/core/core', () => ({
contextSrv: {
hasAccess: () => true,
getValidIntervals: (defaultIntervals: string[]) => defaultIntervals,
},
}));
describe('Explore: handle running/not running query', () => {
afterEach(() => {
tearDown();
@@ -1,7 +1,6 @@
import React from 'react';
import { of } from 'rxjs';
import { EventBusSrv, serializeStateToUrlParam } from '@grafana/data';
import { DataQuery, EventBusSrv, serializeStateToUrlParam } from '@grafana/data';
import { config } from '@grafana/runtime';
import { silenceConsoleOutput } from '../../../../test/core/utils/silenceConsoleOutput';
@@ -33,15 +32,15 @@ import {
import { makeLogsQueryResponse } from './helper/query';
import { setupExplore, tearDown, waitForExplore } from './helper/setup';
const fetchMock = jest.fn();
const postMock = jest.fn();
const getMock = jest.fn();
const reportInteractionMock = jest.fn();
const testEventBus = new EventBusSrv();
interface MockQuery extends DataQuery {
expr: string;
}
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getBackendSrv: () => ({ fetch: fetchMock, post: postMock, get: getMock }),
reportInteraction: (...args: object[]) => {
reportInteractionMock(...args);
},
@@ -79,12 +78,6 @@ jest.mock('react-virtualized-auto-sizer', () => {
};
});
jest.mock('../../correlations/utils', () => {
return {
getCorrelationsBySourceUIDs: jest.fn().mockReturnValue({ correlations: [] }),
};
});
describe('Explore: Query History', () => {
const USER_INPUT = 'my query';
const RAW_QUERY = `{"expr":"${USER_INPUT}"}`;
@@ -93,9 +86,6 @@ describe('Explore: Query History', () => {
afterEach(() => {
config.queryHistoryEnabled = false;
fetchMock.mockClear();
postMock.mockClear();
getMock.mockClear();
reportInteractionMock.mockClear();
tearDown();
});
@@ -116,6 +106,8 @@ describe('Explore: Query History', () => {
// when Explore is opened again
unmount();
tearDown({ clearLocalStorage: false });
setupExplore({ clearLocalStorage: false });
await waitForExplore();
@@ -265,13 +257,15 @@ describe('Explore: Query History', () => {
it('pagination', async () => {
config.queryHistoryEnabled = true;
const { datasources } = setupExplore();
const mockQuery: MockQuery = { refId: 'A', expr: 'query' };
const { datasources } = setupExplore({
queryHistory: {
queryHistory: [{ datasourceUid: 'loki', queries: [mockQuery] }],
totalCount: 2,
},
});
jest.mocked(datasources.loki.query).mockReturnValueOnce(makeLogsQueryResponse());
fetchMock.mockReturnValue(
of({
data: { result: { queryHistory: [{ datasourceUid: 'loki', queries: [{ expr: 'query' }] }], totalCount: 2 } },
})
);
await waitForExplore();
await openQueryHistory();
@@ -8,7 +8,7 @@ import { EventBusSrv, serializeStateToUrlParam } from '@grafana/data';
import * as mainState from '../state/main';
import { makeLogsQueryResponse } from './helper/query';
import { setupExplore, waitForExplore } from './helper/setup';
import { setupExplore, tearDown, waitForExplore } from './helper/setup';
const testEventBus = new EventBusSrv();
@@ -31,22 +31,16 @@ jest.mock('react-virtualized-auto-sizer', () => {
};
});
const fetch = jest.fn().mockResolvedValue({ correlations: [] });
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getBackendSrv: () => ({ fetch }),
getAppEvents: () => testEventBus,
}));
jest.mock('rxjs', () => ({
...jest.requireActual('rxjs'),
lastValueFrom: () =>
new Promise((resolve, reject) => {
resolve({ data: { correlations: [] } });
}),
}));
describe('Handles open/close splits and related events in UI and URL', () => {
afterEach(() => {
tearDown();
});
it('opens the split pane when split button is clicked', async () => {
const { location } = setupExplore();