mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Use PropsWithChildren
and allow router configuration in test utils render
This commit is contained in:
parent
045ec86984
commit
488c5b8396
@ -2,7 +2,7 @@ import { ToolkitStore } from '@reduxjs/toolkit/dist/configureStore';
|
|||||||
import { render, RenderOptions } from '@testing-library/react';
|
import { render, RenderOptions } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { KBarProvider } from 'kbar';
|
import { KBarProvider } from 'kbar';
|
||||||
import React from 'react';
|
import React, { ComponentProps, Fragment, PropsWithChildren } from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { PreloadedState } from 'redux';
|
import { PreloadedState } from 'redux';
|
||||||
@ -17,25 +17,27 @@ import { configureStore } from 'app/store/configureStore';
|
|||||||
import { StoreState } from 'app/types/store';
|
import { StoreState } from 'app/types/store';
|
||||||
|
|
||||||
interface ExtendedRenderOptions extends RenderOptions {
|
interface ExtendedRenderOptions extends RenderOptions {
|
||||||
|
/**
|
||||||
|
* Optional store to use for rendering. If not provided, a fresh store will be generated
|
||||||
|
* via `configureStore` method
|
||||||
|
*/
|
||||||
|
store?: ToolkitStore;
|
||||||
/**
|
/**
|
||||||
* Partial state to use for preloading store when rendering tests
|
* Partial state to use for preloading store when rendering tests
|
||||||
*/
|
*/
|
||||||
preloadedState?: PreloadedState<StoreState>;
|
preloadedState?: PreloadedState<StoreState>;
|
||||||
/**
|
/**
|
||||||
* Optional
|
* Should the wrapper be generated with a wrapping Router component?
|
||||||
|
* Useful if you're testing something that needs more nuanced routing behaviour
|
||||||
|
* and you want full control over it instead
|
||||||
*/
|
*/
|
||||||
store?: ToolkitStore;
|
|
||||||
renderWithRouter?: boolean;
|
renderWithRouter?: boolean;
|
||||||
|
/**
|
||||||
|
* Props to pass to `MemoryRouter`, if being used
|
||||||
|
*/
|
||||||
|
routerOptions?: ComponentProps<typeof MemoryRouter>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps children in empty fragment - used to conditionally render in a router or not,
|
|
||||||
* as needed by tests
|
|
||||||
*/
|
|
||||||
const FragmentWrapper = ({ children }: { children: React.ReactNode }) => {
|
|
||||||
return children;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a wrapper component that implements all of the providers that components
|
* Get a wrapper component that implements all of the providers that components
|
||||||
* within the app will need
|
* within the app will need
|
||||||
@ -43,22 +45,16 @@ const FragmentWrapper = ({ children }: { children: React.ReactNode }) => {
|
|||||||
const getWrapper = ({
|
const getWrapper = ({
|
||||||
store,
|
store,
|
||||||
renderWithRouter,
|
renderWithRouter,
|
||||||
|
routerOptions,
|
||||||
grafanaContext,
|
grafanaContext,
|
||||||
}: {
|
}: ExtendedRenderOptions & {
|
||||||
store?: ToolkitStore;
|
|
||||||
/**
|
|
||||||
* Should the wrapper be generated with a wrapping Router component?
|
|
||||||
* Useful if you're testing something that needs more nuanced routing behaviour
|
|
||||||
* and you want full control over it instead
|
|
||||||
*/
|
|
||||||
renderWithRouter?: boolean;
|
|
||||||
grafanaContext?: GrafanaContextType;
|
grafanaContext?: GrafanaContextType;
|
||||||
}): React.FC<{ children: React.ReactNode }> => {
|
}) => {
|
||||||
const reduxStore = store || configureStore();
|
const reduxStore = store || configureStore();
|
||||||
/**
|
/**
|
||||||
* Conditional router - either a MemoryRouter or just a Fragment
|
* Conditional router - either a MemoryRouter or just a Fragment
|
||||||
*/
|
*/
|
||||||
const PotentialRouter = renderWithRouter ? MemoryRouter : FragmentWrapper;
|
const PotentialRouter = renderWithRouter ? MemoryRouter : Fragment;
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
...getGrafanaContextMock(),
|
...getGrafanaContextMock(),
|
||||||
@ -69,14 +65,14 @@ const getWrapper = ({
|
|||||||
* Returns a wrapper that should (closely) match the main `AppWrapper`, so any tests are rendering
|
* Returns a wrapper that should (closely) match the main `AppWrapper`, so any tests are rendering
|
||||||
* in mostly the same providers as a "real" hierarchy
|
* in mostly the same providers as a "real" hierarchy
|
||||||
*/
|
*/
|
||||||
return function Wrapper({ children }: { children?: React.ReactNode }) {
|
return function Wrapper({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<Provider store={reduxStore}>
|
<Provider store={reduxStore}>
|
||||||
<ErrorBoundaryAlert style="page">
|
<ErrorBoundaryAlert style="page">
|
||||||
<GrafanaContext.Provider value={context}>
|
<GrafanaContext.Provider value={context}>
|
||||||
<ThemeProvider value={config.theme2}>
|
<ThemeProvider value={config.theme2}>
|
||||||
<KBarProvider>
|
<KBarProvider>
|
||||||
<PotentialRouter>
|
<PotentialRouter {...routerOptions}>
|
||||||
<ModalsContextProvider>{children}</ModalsContextProvider>
|
<ModalsContextProvider>{children}</ModalsContextProvider>
|
||||||
</PotentialRouter>
|
</PotentialRouter>
|
||||||
</KBarProvider>
|
</KBarProvider>
|
||||||
@ -99,7 +95,7 @@ const customRender = (
|
|||||||
) => {
|
) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const store = renderOptions.preloadedState ? configureStore(renderOptions?.preloadedState as any) : undefined;
|
const store = renderOptions.preloadedState ? configureStore(renderOptions?.preloadedState as any) : undefined;
|
||||||
const AllTheProviders = renderOptions.wrapper || getWrapper({ store, renderWithRouter });
|
const AllTheProviders = renderOptions.wrapper || getWrapper({ store, renderWithRouter, ...renderOptions });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...render(ui, { wrapper: AllTheProviders, ...renderOptions }),
|
...render(ui, { wrapper: AllTheProviders, ...renderOptions }),
|
||||||
|
Loading…
Reference in New Issue
Block a user