mirror of
				https://github.com/grafana/grafana.git
				synced 2025-02-25 18:55:37 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			217 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { thunkTester } from 'test/core/thunk/thunkTester';
 | |
| 
 | |
| import { dateTime, ExploreUrlState } from '@grafana/data';
 | |
| import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
 | |
| import { locationService } from '@grafana/runtime';
 | |
| import { PanelModel } from 'app/features/dashboard/state';
 | |
| 
 | |
| import { reducerTester } from '../../../../test/core/redux/reducerTester';
 | |
| import { MockDataSourceApi } from '../../../../test/mocks/datasource_srv';
 | |
| import { configureStore } from '../../../store/configureStore';
 | |
| import { ExploreItemState, ExploreState, StoreState, ThunkDispatch } from '../../../types';
 | |
| 
 | |
| import { exploreReducer, navigateToExplore, splitClose, splitOpen } from './main';
 | |
| 
 | |
| const getNavigateToExploreContext = async (openInNewWindow?: (url: string) => void) => {
 | |
|   const url = '/explore';
 | |
|   const panel: Partial<PanelModel> = {
 | |
|     datasource: { uid: 'mocked datasource' },
 | |
|     targets: [{ refId: 'A' }],
 | |
|   };
 | |
|   const datasource = new MockDataSourceApi(panel.datasource!.uid!);
 | |
|   const get = jest.fn().mockResolvedValue(datasource);
 | |
|   const getDataSourceSrv = jest.fn().mockReturnValue({ get });
 | |
|   const getExploreUrl = jest.fn().mockResolvedValue(url);
 | |
|   const timeRange = { from: dateTime(), to: dateTime() };
 | |
| 
 | |
|   const dispatchedActions = await thunkTester({})
 | |
|     .givenThunk(navigateToExplore)
 | |
|     .whenThunkIsDispatched(panel, { getDataSourceSrv, timeRange, getExploreUrl, openInNewWindow });
 | |
| 
 | |
|   return {
 | |
|     url,
 | |
|     panel,
 | |
|     get,
 | |
|     getDataSourceSrv,
 | |
|     timeRange,
 | |
|     getExploreUrl,
 | |
|     dispatchedActions,
 | |
|   };
 | |
| };
 | |
| 
 | |
| describe('navigateToExplore', () => {
 | |
|   describe('when navigateToExplore thunk is dispatched', () => {
 | |
|     describe('and openInNewWindow is undefined', () => {
 | |
|       it('then it should dispatch correct actions', async () => {
 | |
|         const { url } = await getNavigateToExploreContext();
 | |
|         expect(locationService.getLocation().pathname).toEqual(url);
 | |
|       });
 | |
| 
 | |
|       it('then getDataSourceSrv should have been once', async () => {
 | |
|         const { getDataSourceSrv } = await getNavigateToExploreContext();
 | |
| 
 | |
|         expect(getDataSourceSrv).toHaveBeenCalledTimes(1);
 | |
|       });
 | |
| 
 | |
|       it('then getExploreUrl should have been called with correct arguments', async () => {
 | |
|         const { getExploreUrl, panel, getDataSourceSrv, timeRange } = await getNavigateToExploreContext();
 | |
| 
 | |
|         expect(getExploreUrl).toHaveBeenCalledTimes(1);
 | |
|         expect(getExploreUrl).toHaveBeenCalledWith({
 | |
|           panel,
 | |
|           datasourceSrv: getDataSourceSrv(),
 | |
|           timeRange,
 | |
|         });
 | |
|       });
 | |
|     });
 | |
| 
 | |
|     describe('and openInNewWindow is defined', () => {
 | |
|       const openInNewWindow: (url: string) => void = jest.fn();
 | |
|       it('then it should dispatch no actions', async () => {
 | |
|         const { dispatchedActions } = await getNavigateToExploreContext(openInNewWindow);
 | |
| 
 | |
|         expect(dispatchedActions).toEqual([]);
 | |
|       });
 | |
| 
 | |
|       it('then getDataSourceSrv should have been once', async () => {
 | |
|         const { getDataSourceSrv } = await getNavigateToExploreContext(openInNewWindow);
 | |
| 
 | |
|         expect(getDataSourceSrv).toHaveBeenCalledTimes(1);
 | |
|       });
 | |
| 
 | |
|       it('then getExploreUrl should have been called with correct arguments', async () => {
 | |
|         const { getExploreUrl, panel, getDataSourceSrv, timeRange } = await getNavigateToExploreContext(
 | |
|           openInNewWindow
 | |
|         );
 | |
| 
 | |
|         expect(getExploreUrl).toHaveBeenCalledTimes(1);
 | |
|         expect(getExploreUrl).toHaveBeenCalledWith({
 | |
|           panel,
 | |
|           datasourceSrv: getDataSourceSrv(),
 | |
|           timeRange,
 | |
|         });
 | |
|       });
 | |
| 
 | |
|       it('then openInNewWindow should have been called with correct arguments', async () => {
 | |
|         const openInNewWindowFunc = jest.fn();
 | |
|         const { url } = await getNavigateToExploreContext(openInNewWindowFunc);
 | |
| 
 | |
|         expect(openInNewWindowFunc).toHaveBeenCalledTimes(1);
 | |
|         expect(openInNewWindowFunc).toHaveBeenCalledWith(url);
 | |
|       });
 | |
|     });
 | |
|   });
 | |
| });
 | |
| 
 | |
| describe('Explore reducer', () => {
 | |
|   describe('split view', () => {
 | |
|     describe('split open', () => {
 | |
|       it('it should create only ony new pane', async () => {
 | |
|         let dispatch: ThunkDispatch, getState: () => StoreState;
 | |
| 
 | |
|         const store: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({
 | |
|           explore: {
 | |
|             panes: {
 | |
|               one: { queries: [], range: {} },
 | |
|             },
 | |
|           },
 | |
|         } as unknown as Partial<StoreState>);
 | |
| 
 | |
|         dispatch = store.dispatch;
 | |
|         getState = store.getState;
 | |
| 
 | |
|         await dispatch(splitOpen());
 | |
|         let splitPanes = Object.keys(getState().explore.panes);
 | |
|         expect(splitPanes).toHaveLength(2);
 | |
|         let secondSplitPaneId = splitPanes[1];
 | |
| 
 | |
|         await dispatch(splitOpen());
 | |
|         splitPanes = Object.keys(getState().explore.panes);
 | |
|         // only 2 panes exist...
 | |
|         expect(splitPanes).toHaveLength(2);
 | |
|         // ...and the second pane is replaced
 | |
|         expect(splitPanes[0]).toBe('one');
 | |
|         expect(splitPanes[1]).not.toBe(secondSplitPaneId);
 | |
|       });
 | |
|     });
 | |
|     describe('split close', () => {
 | |
|       it('should reset right pane when it is closed', () => {
 | |
|         const leftItemMock = {
 | |
|           containerWidth: 100,
 | |
|         } as unknown as ExploreItemState;
 | |
| 
 | |
|         const rightItemMock = {
 | |
|           containerWidth: 200,
 | |
|         } as unknown as ExploreItemState;
 | |
| 
 | |
|         const initialState = {
 | |
|           panes: {
 | |
|             left: leftItemMock,
 | |
|             right: rightItemMock,
 | |
|           },
 | |
|         } as unknown as ExploreState;
 | |
| 
 | |
|         // closing left item
 | |
|         reducerTester<ExploreState>()
 | |
|           .givenReducer(exploreReducer, initialState)
 | |
|           .whenActionIsDispatched(splitClose('right'))
 | |
|           .thenStateShouldEqual({
 | |
|             evenSplitPanes: true,
 | |
|             largerExploreId: undefined,
 | |
|             panes: {
 | |
|               left: leftItemMock,
 | |
|             },
 | |
|             maxedExploreId: undefined,
 | |
|             syncedTimes: false,
 | |
|           } as unknown as ExploreState);
 | |
|       });
 | |
| 
 | |
|       it('should unsync time ranges', () => {
 | |
|         const itemMock = {
 | |
|           containerWidth: 100,
 | |
|         } as unknown as ExploreItemState;
 | |
| 
 | |
|         const initialState = {
 | |
|           panes: {
 | |
|             right: itemMock,
 | |
|             left: itemMock,
 | |
|           },
 | |
|           syncedTimes: true,
 | |
|         } as unknown as ExploreState;
 | |
| 
 | |
|         reducerTester<ExploreState>()
 | |
|           .givenReducer(exploreReducer, initialState)
 | |
|           .whenActionIsDispatched(splitClose('right'))
 | |
|           .thenStateShouldEqual({
 | |
|             evenSplitPanes: true,
 | |
|             panes: {
 | |
|               left: itemMock,
 | |
|             },
 | |
|             syncedTimes: false,
 | |
|           } as unknown as ExploreState);
 | |
|       });
 | |
|     });
 | |
|   });
 | |
| });
 | |
| 
 | |
| export const setup = (urlStateOverrides?: Partial<ExploreUrlState>) => {
 | |
|   const urlStateDefaults: ExploreUrlState = {
 | |
|     datasource: 'some-datasource',
 | |
|     queries: [],
 | |
|     range: {
 | |
|       from: '',
 | |
|       to: '',
 | |
|     },
 | |
|   };
 | |
|   const urlState: ExploreUrlState = { ...urlStateDefaults, ...urlStateOverrides };
 | |
|   const serializedUrlState = serializeStateToUrlParam(urlState);
 | |
|   const initialState = {
 | |
|     split: false,
 | |
|   } as unknown as ExploreState;
 | |
| 
 | |
|   return {
 | |
|     initialState,
 | |
|     serializedUrlState,
 | |
|   };
 | |
| };
 |