| 
									
										
										
										
											2024-05-10 21:28:51 +08:00
										 |  |  | import { Store } from '@reduxjs/toolkit'; | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  | import { render, RenderOptions } from '@testing-library/react'; | 
					
						
							|  |  |  | import userEvent from '@testing-library/user-event'; | 
					
						
							| 
									
										
										
										
											2024-04-26 22:45:48 +08:00
										 |  |  | import { createMemoryHistory, MemoryHistoryBuildOptions } from 'history'; | 
					
						
							| 
									
										
										
										
											2024-06-25 19:43:47 +08:00
										 |  |  | import { Fragment, PropsWithChildren } from 'react'; | 
					
						
							|  |  |  | import * as React from 'react'; | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  | import { Provider } from 'react-redux'; | 
					
						
							| 
									
										
										
										
											2024-10-28 23:18:49 +08:00
										 |  |  | // eslint-disable-next-line no-restricted-imports
 | 
					
						
							| 
									
										
										
										
											2024-04-26 22:45:48 +08:00
										 |  |  | import { Router } from 'react-router-dom'; | 
					
						
							| 
									
										
										
										
											2024-08-22 18:05:12 +08:00
										 |  |  | import { CompatRouter } from 'react-router-dom-v5-compat'; | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  | import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 17:58:58 +08:00
										 |  |  | import { HistoryWrapper, LocationServiceProvider, setLocationService } from '@grafana/runtime'; | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  | import { GrafanaContext, GrafanaContextType } from 'app/core/context/GrafanaContext'; | 
					
						
							|  |  |  | import { ModalsContextProvider } from 'app/core/context/ModalsContextProvider'; | 
					
						
							|  |  |  | import { configureStore } from 'app/store/configureStore'; | 
					
						
							|  |  |  | import { StoreState } from 'app/types/store'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface ExtendedRenderOptions extends RenderOptions { | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Optional store to use for rendering. If not provided, a fresh store will be generated | 
					
						
							|  |  |  |    * via `configureStore` method | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2024-05-10 21:28:51 +08:00
										 |  |  |   store?: Store<StoreState>; | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Partial state to use for preloading store when rendering tests | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2024-05-10 21:28:51 +08:00
										 |  |  |   preloadedState?: Partial<StoreState>; | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  |    * 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 | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |    */ | 
					
						
							|  |  |  |   renderWithRouter?: boolean; | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2024-04-26 22:45:48 +08:00
										 |  |  |    * Props to pass to `createMemoryHistory`, if being used | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2024-04-26 22:45:48 +08:00
										 |  |  |   historyOptions?: MemoryHistoryBuildOptions; | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Get a wrapper component that implements all of the providers that components | 
					
						
							|  |  |  |  * within the app will need | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const getWrapper = ({ | 
					
						
							|  |  |  |   store, | 
					
						
							|  |  |  |   renderWithRouter, | 
					
						
							| 
									
										
										
										
											2024-04-26 22:45:48 +08:00
										 |  |  |   historyOptions, | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |   grafanaContext, | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  | }: ExtendedRenderOptions & { | 
					
						
							| 
									
										
										
										
											2024-08-12 19:11:50 +08:00
										 |  |  |   grafanaContext?: Partial<GrafanaContextType>; | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  | }) => { | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |   const reduxStore = store || configureStore(); | 
					
						
							| 
									
										
										
										
											2024-04-26 22:45:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Create a fresh location service for each test - otherwise we run the risk
 | 
					
						
							|  |  |  |   // of it being stateful in between runs
 | 
					
						
							|  |  |  |   const history = createMemoryHistory(historyOptions); | 
					
						
							|  |  |  |   const locationService = new HistoryWrapper(history); | 
					
						
							|  |  |  |   setLocationService(locationService); | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 18:05:12 +08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Conditional router - either a MemoryRouter or just a Fragment | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   const PotentialRouter = renderWithRouter | 
					
						
							|  |  |  |     ? ({ children }: PropsWithChildren) => <Router history={history}>{children}</Router> | 
					
						
							|  |  |  |     : ({ children }: PropsWithChildren) => <Fragment>{children}</Fragment>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const PotentialCompatRouter = renderWithRouter ? CompatRouter : Fragment; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |   const context = { | 
					
						
							|  |  |  |     ...getGrafanaContextMock(), | 
					
						
							|  |  |  |     ...grafanaContext, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2024-04-15 23:45:05 +08:00
										 |  |  |    * Returns a wrapper that should (eventually?) match the main `AppWrapper`, so any tests are rendering | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |    * in mostly the same providers as a "real" hierarchy | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  |   return function Wrapper({ children }: PropsWithChildren) { | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |     return ( | 
					
						
							|  |  |  |       <Provider store={reduxStore}> | 
					
						
							| 
									
										
										
										
											2024-04-15 23:45:05 +08:00
										 |  |  |         <GrafanaContext.Provider value={context}> | 
					
						
							| 
									
										
										
										
											2024-08-22 18:05:12 +08:00
										 |  |  |           <PotentialRouter> | 
					
						
							| 
									
										
										
										
											2024-08-07 17:58:58 +08:00
										 |  |  |             <LocationServiceProvider service={locationService}> | 
					
						
							| 
									
										
										
										
											2024-08-22 18:05:12 +08:00
										 |  |  |               <PotentialCompatRouter> | 
					
						
							|  |  |  |                 <ModalsContextProvider>{children}</ModalsContextProvider> | 
					
						
							|  |  |  |               </PotentialCompatRouter> | 
					
						
							| 
									
										
										
										
											2024-08-07 17:58:58 +08:00
										 |  |  |             </LocationServiceProvider> | 
					
						
							| 
									
										
										
										
											2024-04-15 23:45:05 +08:00
										 |  |  |           </PotentialRouter> | 
					
						
							|  |  |  |         </GrafanaContext.Provider> | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |       </Provider> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Extended [@testing-library/react render](https://testing-library.com/docs/react-testing-library/api/#render)
 | 
					
						
							|  |  |  |  * method which wraps the passed element in all of the necessary Providers, | 
					
						
							|  |  |  |  * so it can render correctly in the context of the application | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const customRender = ( | 
					
						
							|  |  |  |   ui: React.ReactElement, | 
					
						
							|  |  |  |   { renderWithRouter = true, ...renderOptions }: ExtendedRenderOptions = {} | 
					
						
							|  |  |  | ) => { | 
					
						
							| 
									
										
										
										
											2024-08-07 17:58:58 +08:00
										 |  |  |   const user = userEvent.setup(); | 
					
						
							| 
									
										
										
										
											2024-05-10 21:28:51 +08:00
										 |  |  |   const store = renderOptions.preloadedState ? configureStore(renderOptions?.preloadedState) : undefined; | 
					
						
							| 
									
										
										
										
											2024-04-09 20:14:58 +08:00
										 |  |  |   const AllTheProviders = renderOptions.wrapper || getWrapper({ store, renderWithRouter, ...renderOptions }); | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     ...render(ui, { wrapper: AllTheProviders, ...renderOptions }), | 
					
						
							| 
									
										
										
										
											2024-08-07 17:58:58 +08:00
										 |  |  |     /** Instance of `userEvent.setup()` ready for use to interact with rendered component */ | 
					
						
							|  |  |  |     user, | 
					
						
							| 
									
										
										
										
											2024-04-06 00:32:16 +08:00
										 |  |  |     store, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export * from '@testing-library/react'; | 
					
						
							|  |  |  | export { customRender as render, getWrapper, userEvent }; |