Routing: Import useLocation from compat package (#92071)

* Routing: Import useLocation from compat package

* Add ComparRouter

* Add CompatRouter

* Fix tests

* Add CompatRouter to TestProvider

* Use findBy

* Remove AppChromeService

* Remove historyOptions

* Routing: Fix alerting/test utils issues from react compat router usage (#92127)

* Use render from test-utils

* Use compat router

* Convert more tests

---------

Co-authored-by: Tom Ratcliffe <tom.ratcliffe@grafana.com>
This commit is contained in:
Alex Khomenko 2024-08-23 09:54:13 +03:00 committed by GitHub
parent d24b21d3ef
commit 0af4a20b58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 94 additions and 158 deletions

View File

@ -1,7 +1,7 @@
import { css } from '@emotion/css';
import { DOMAttributes } from '@react-types/shared';
import { memo, forwardRef, useCallback } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';

View File

@ -1,7 +1,7 @@
import { css, cx } from '@emotion/css';
import { useEffect, useRef } from 'react';
import * as React from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { useLocalStorage } from 'react-use';
import { GrafanaTheme2, NavModelItem, toIconName } from '@grafana/data';

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2, locationUtil, textUtil } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';

View File

@ -1,7 +1,7 @@
import { css } from '@emotion/css';
import { cloneDeep } from 'lodash';
import { memo } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2, locationUtil, textUtil } from '@grafana/data';
import { Dropdown, ToolbarButton, useStyles2 } from '@grafana/ui';

View File

@ -1,5 +1,5 @@
import { useCallback, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { UrlQueryMap } from '@grafana/data';
import { locationSearchToObject, locationService } from '@grafana/runtime';

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import { ErrorInfo, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2, locationUtil, PageLayoutType } from '@grafana/data';
import { Button, ErrorWithStack, useStyles2 } from '@grafana/ui';

View File

@ -1,4 +1,4 @@
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { locationService } from '@grafana/runtime';

View File

@ -2,6 +2,7 @@ import { render, renderHook, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { first, noop } from 'lodash';
import { Router } from 'react-router-dom';
import { CompatRouter } from 'react-router-dom-v5-compat';
import { config, locationService } from '@grafana/runtime';
import { contextSrv } from 'app/core/core';
@ -347,7 +348,9 @@ describe('Policy', () => {
const renderPolicy = (element: JSX.Element) =>
render(
<Router history={locationService.getHistory()}>
<CompatRouter>
<AlertmanagerProvider accessType="notification">{element}</AlertmanagerProvider>
</CompatRouter>
</Router>
);

View File

@ -1,5 +1,6 @@
import { render, screen } from '@testing-library/react';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render } from 'test/test-utils';
import { PanelModel } from 'app/features/dashboard/state';
import { createDashboardModelFixture } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures';
@ -16,12 +17,6 @@ jest.mock('app/types', () => {
};
});
jest.mock('react-router-dom', () => ({
useLocation: () => ({
pathname: 'localhost:3000/example/path',
}),
}));
jest.spyOn(analytics, 'logInfo');
jest.mock('react-use', () => ({

View File

@ -1,4 +1,4 @@
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { useAsync } from 'react-use';
import { urlUtil } from '@grafana/data';

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { useAsyncFn, useInterval } from 'react-use';
import { GrafanaTheme2, urlUtil } from '@grafana/data';

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { useAsyncFn, useInterval, useMeasure } from 'react-use';
import { GrafanaTheme2, urlUtil } from '@grafana/data';

View File

@ -1,7 +1,7 @@
import { css } from '@emotion/css';
import pluralize from 'pluralize';
import { useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2, urlUtil } from '@grafana/data';
import { LinkButton, LoadingPlaceholder, Pagination, Spinner, Text, useStyles2 } from '@grafana/ui';

View File

@ -1,6 +1,6 @@
import { css, cx } from '@emotion/css';
import { useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2 } from '@grafana/data';
import { LinkButton, Stack, useStyles2 } from '@grafana/ui';

View File

@ -1,11 +1,9 @@
import { render, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { waitFor } from '@testing-library/react';
import { render } from 'test/test-utils';
import { byRole } from 'testing-library-selector';
import { locationService, setPluginExtensionsHook } from '@grafana/runtime';
import { setPluginExtensionsHook } from '@grafana/runtime';
import { contextSrv } from 'app/core/services/context_srv';
import { configureStore } from 'app/store/configureStore';
import { AccessControlAction } from 'app/types';
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
@ -101,15 +99,7 @@ describe('RuleListGroupView', () => {
});
function renderRuleList(namespaces: CombinedRuleNamespace[]) {
const store = configureStore();
render(
<Provider store={store}>
<Router history={locationService.getHistory()}>
<RuleListGroupView namespaces={namespaces} expandAll />
</Router>
</Provider>
);
render(<RuleListGroupView namespaces={namespaces} expandAll />);
}
function getGrafanaNamespace(): CombinedRuleNamespace {

View File

@ -1,5 +1,5 @@
import { useCallback, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { locationService } from '@grafana/runtime';

View File

@ -2,6 +2,7 @@ import { renderHook } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import * as React from 'react';
import { MemoryRouter, Router } from 'react-router-dom';
import { CompatRouter } from 'react-router-dom-v5-compat';
import store from 'app/core/store';
import { AlertManagerImplementation } from 'app/plugins/datasource/alertmanager/types';
@ -34,7 +35,9 @@ describe('useAlertmanager', () => {
.mockReturnValueOnce({ availableExternalDataSources: [], availableInternalDataSources: [] });
const wrapper = ({ children }: React.PropsWithChildren) => (
<MemoryRouter>
<CompatRouter>
<AlertmanagerProvider accessType="instance">{children}</AlertmanagerProvider>
</CompatRouter>
</MemoryRouter>
);
@ -50,7 +53,9 @@ describe('useAlertmanager', () => {
const wrapper = ({ children }: React.PropsWithChildren) => (
<MemoryRouter>
<CompatRouter>
<AlertmanagerProvider accessType="instance">{children}</AlertmanagerProvider>
</CompatRouter>
</MemoryRouter>
);
@ -68,7 +73,9 @@ describe('useAlertmanager', () => {
const wrapper = ({ children }: React.PropsWithChildren) => (
<Router history={history}>
<CompatRouter>
<AlertmanagerProvider accessType="instance">{children}</AlertmanagerProvider>
</CompatRouter>
</Router>
);
@ -86,7 +93,9 @@ describe('useAlertmanager', () => {
const wrapper = ({ children }: React.PropsWithChildren) => (
<Router history={history}>
<CompatRouter>
<AlertmanagerProvider accessType="instance">{children}</AlertmanagerProvider>
</CompatRouter>
</Router>
);
@ -101,7 +110,9 @@ describe('useAlertmanager', () => {
const wrapper = ({ children }: React.PropsWithChildren) => (
<MemoryRouter>
<CompatRouter>
<AlertmanagerProvider accessType="instance">{children}</AlertmanagerProvider>
</CompatRouter>
</MemoryRouter>
);
@ -122,7 +133,9 @@ describe('useAlertmanager', () => {
const wrapper = ({ children }: React.PropsWithChildren) => (
<Router history={history}>
<CompatRouter>
<AlertmanagerProvider accessType="instance">{children}</AlertmanagerProvider>
</CompatRouter>
</Router>
);

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import { memo, useEffect, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import AutoSizer from 'react-virtualized-auto-sizer';
import { GrafanaTheme2 } from '@grafana/data';

View File

@ -1,5 +1,5 @@
import { useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { config, reportInteraction } from '@grafana/runtime';
import { Button, Drawer, Dropdown, Icon, Menu, MenuItem } from '@grafana/ui';

View File

@ -1,4 +1,4 @@
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { locationUtil } from '@grafana/data';
import { locationService } from '@grafana/runtime';

View File

@ -1,4 +1,4 @@
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { useAsync } from 'react-use';
import { urlUtil } from '@grafana/data';

View File

@ -1,5 +1,6 @@
import { act, fireEvent, render, screen } from '@testing-library/react';
import { act, fireEvent, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render } from 'test/test-utils';
import { standardEditorsRegistry, standardFieldConfigEditorRegistry } from '@grafana/data';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
@ -21,12 +22,6 @@ import { VizPanelManager } from './VizPanelManager';
const OptionsPaneSelector = selectors.components.PanelEditor.OptionsPane;
jest.mock('react-router-dom', () => ({
useLocation: () => ({
pathname: '',
}),
}));
standardEditorsRegistry.setInit(getAllOptionEditors);
standardFieldConfigEditorRegistry.setInit(getAllStandardFieldConfigs);

View File

@ -1,6 +1,6 @@
import { css, cx } from '@emotion/css';
import { useEffect, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2, PageLayoutType } from '@grafana/data';
import { useChromeHeaderHeight } from '@grafana/runtime';

View File

@ -1,4 +1,4 @@
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { locationUtil, NavModelItem } from '@grafana/data';
import { SceneObject, SceneObjectState } from '@grafana/scenes';

View File

@ -1,7 +1,7 @@
import { css } from '@emotion/css';
import { memo, ReactNode } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { textUtil } from '@grafana/data';
import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';

View File

@ -1,6 +1,6 @@
import * as H from 'history';
import { useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { locationUtil, NavModel, NavModelItem } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';

View File

@ -1,20 +1,13 @@
import { render, screen, within } from '@testing-library/react';
import { screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
import { render } from 'test/test-utils';
import { locationService } from '@grafana/runtime';
import { GrafanaContext } from 'app/core/context/GrafanaContext';
import { configureStore } from '../../../../store/configureStore';
import { DashboardModel } from '../../state';
import { createDashboardModelFixture } from '../../state/__fixtures__/dashboardFixtures';
import { DashboardSettings } from './DashboardSettings';
function setup(dashboard: DashboardModel) {
const store = configureStore();
const sectionNav = {
main: { text: 'Dashboard' },
node: {
@ -24,13 +17,7 @@ function setup(dashboard: DashboardModel) {
// Need to use DashboardSettings here as it's responsible for fetching the state back from location
return render(
<GrafanaContext.Provider value={getGrafanaContextMock()}>
<Provider store={store}>
<Router history={locationService.getHistory()}>
<DashboardSettings editview="links" dashboard={dashboard} sectionNav={sectionNav} pageNav={sectionNav.node} />
</Router>
</Provider>
</GrafanaContext.Provider>
);
}

View File

@ -1,6 +1,6 @@
import { useState } from 'react';
import { connect, MapStateToProps } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { PanelPlugin } from '@grafana/data';
import { locationService } from '@grafana/runtime';

View File

@ -1,6 +1,7 @@
import { fireEvent, render, screen, within } from '@testing-library/react';
import { fireEvent, screen, within } from '@testing-library/react';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import { render } from 'test/test-utils';
import {
FieldConfigSource,

View File

@ -1,26 +1,22 @@
import { render, screen, waitFor } from '@testing-library/react';
import { screen, waitFor } from '@testing-library/react';
import { KBarProvider } from 'kbar';
import { Component } from 'react';
import { Provider } from 'react-redux';
import { match, Router } from 'react-router-dom';
import { match } from 'react-router-dom';
import { useEffectOnce } from 'react-use';
import { mockToolkitActionCreator } from 'test/core/redux/mocks';
import { TestProvider } from 'test/helpers/TestProvider';
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
import { render } from 'test/test-utils';
import { createTheme } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config, locationService, setDataSourceSrv } from '@grafana/runtime';
import { config, setDataSourceSrv } from '@grafana/runtime';
import { Dashboard } from '@grafana/schema';
import { notifyApp } from 'app/core/actions';
import { AppChrome } from 'app/core/components/AppChrome/AppChrome';
import { GrafanaContext } from 'app/core/context/GrafanaContext';
import { getRouteComponentProps } from 'app/core/navigation/__mocks__/routeProps';
import { RouteDescriptor } from 'app/core/navigation/types';
import { HOME_NAV_ID } from 'app/core/reducers/navModel';
import { DashboardInitPhase, DashboardMeta, DashboardRoutes } from 'app/types';
import { configureStore } from '../../../store/configureStore';
import { Props as LazyLoaderProps } from '../dashgrid/LazyLoader';
import { DashboardSrv, setDashboardSrv } from '../services/DashboardSrv';
import { DashboardModel } from '../state';
@ -103,7 +99,6 @@ function setup(propOverrides?: Partial<Props>) {
},
];
const store = configureStore();
const props: Props = {
...getRouteComponentProps({
match: { params: { slug: 'my-dash', uid: '11' } } as unknown as match,
@ -130,29 +125,11 @@ function setup(propOverrides?: Partial<Props>) {
Object.assign(props, propOverrides);
const context = getGrafanaContextMock();
const { unmount, rerender } = render(
<GrafanaContext.Provider value={context}>
<Provider store={store}>
<Router history={locationService.getHistory()}>
<UnthemedDashboardPage {...props} />
</Router>
</Provider>
</GrafanaContext.Provider>
);
const { unmount, rerender } = render(<UnthemedDashboardPage {...props} />);
const wrappedRerender = (newProps: Partial<Props>) => {
Object.assign(props, newProps);
return rerender(
<GrafanaContext.Provider value={context}>
<Provider store={store}>
<Router history={locationService.getHistory()}>
<UnthemedDashboardPage {...props} />
</Router>
</Provider>
</GrafanaContext.Provider>
);
return rerender(<UnthemedDashboardPage {...props} />);
};
return { rerender: wrappedRerender, unmount };
@ -190,7 +167,7 @@ describe('DashboardPage', () => {
it('only calls initDashboard once when wrapped in AppChrome', async () => {
const props: Props = {
...getRouteComponentProps({
match: { params: { slug: 'my-dash', uid: '11' } } as unknown as match,
match: { params: { slug: 'my-dash', uid: '11' }, isExact: true, path: '', url: '' },
route: { routeName: DashboardRoutes.Normal } as RouteDescriptor,
}),
navIndex: {
@ -214,11 +191,9 @@ describe('DashboardPage', () => {
render(
<KBarProvider>
<TestProvider>
<AppChrome>
<UnthemedDashboardPage {...props} />
</AppChrome>
</TestProvider>
</KBarProvider>
);

View File

@ -1,16 +1,12 @@
import { act, render, screen, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { act, screen, waitFor } from '@testing-library/react';
import { Props } from 'react-virtualized-auto-sizer';
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
import { render } from 'test/test-utils';
import { config, locationService } from '@grafana/runtime';
import { GrafanaContext } from 'app/core/context/GrafanaContext';
import {
HOME_DASHBOARD_CACHE_KEY,
getDashboardScenePageStateManager,
} from 'app/features/dashboard-scene/pages/DashboardScenePageStateManager';
import { configureStore } from 'app/store/configureStore';
import { DashboardDTO, DashboardRoutes } from 'app/types';
import DashboardPageProxy, { DashboardPageProxyProps } from './DashboardPageProxy';
@ -84,13 +80,7 @@ jest.mock('app/features/dashboard/api/dashboard_api', () => ({
}));
function setup(props: Partial<DashboardPageProxyProps>) {
const context = getGrafanaContextMock();
const store = configureStore({});
return render(
<GrafanaContext.Provider value={context}>
<Provider store={store}>
<Router history={locationService.getHistory()}>
<DashboardPageProxy
location={locationService.getLocation()}
history={locationService.getHistory()}
@ -99,9 +89,6 @@ function setup(props: Partial<DashboardPageProxyProps>) {
match={{ params: {}, isExact: true, path: '/', url: '/' }}
{...props}
/>
</Router>
</Provider>
</GrafanaContext.Provider>
);
}

View File

@ -1,20 +1,12 @@
import { render, screen } from '@testing-library/react';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { locationService } from '@grafana/runtime';
import { configureStore } from 'app/store/configureStore';
import { screen } from '@testing-library/react';
import { render } from 'test/test-utils';
import { getMockDataSources } from '../__mocks__';
import { DataSourcesListView } from './DataSourcesList';
const setup = () => {
const store = configureStore();
return render(
<Provider store={store}>
<Router history={locationService.getHistory()}>
<DataSourcesListView
dataSources={getMockDataSources(3)}
dataSourcesCount={3}
@ -23,8 +15,6 @@ const setup = () => {
hasWriteRights={true}
hasExploreRights={true}
/>
</Router>
</Provider>
);
};

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { DataSourceSettings, GrafanaTheme2 } from '@grafana/data';
import { config } from '@grafana/runtime';

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { AppEvents } from '@grafana/data';
import { config, locationService } from '@grafana/runtime';

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import * as React from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { config } from '@grafana/runtime';

View File

@ -1,4 +1,4 @@
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { config } from '@grafana/runtime';
import { EmptyState, Grid } from '@grafana/ui';

View File

@ -1,5 +1,5 @@
import { useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { GrafanaPlugin, NavModelItem, PluginIncludeType, PluginType } from '@grafana/data';
import { config } from '@grafana/runtime';

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import { ReactElement } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { SelectableValue, GrafanaTheme2, PluginType } from '@grafana/data';
import { locationSearchToObject } from '@grafana/runtime';