| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  | import { screen, render } from '@testing-library/react'; | 
					
						
							| 
									
										
										
										
											2025-06-25 22:02:35 +08:00
										 |  |  | import { useEffect } from 'react'; | 
					
						
							| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  | import { Provider } from 'react-redux'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-25 22:02:35 +08:00
										 |  |  | import { DataSourceJsonData, PluginExtensionDataSourceConfigContext, PluginState } from '@grafana/data'; | 
					
						
							| 
									
										
										
										
											2025-07-14 21:51:19 +08:00
										 |  |  | import { setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime'; | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  | import { createComponentWithMeta } from 'app/features/plugins/extensions/usePluginComponents'; | 
					
						
							| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  | import { configureStore } from 'app/store/configureStore'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-02 15:25:25 +08:00
										 |  |  | import { getMockDataSource, getMockDataSourceMeta, getMockDataSourceSettingsState } from '../mocks/dataSourcesMocks'; | 
					
						
							| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import { missingRightsMessage } from './DataSourceMissingRightsMessage'; | 
					
						
							|  |  |  | import { readOnlyMessage } from './DataSourceReadOnlyMessage'; | 
					
						
							|  |  |  | import { EditDataSourceView, ViewProps } from './EditDataSource'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-25 22:02:35 +08:00
										 |  |  | const onOptionsChange = jest.fn(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-02 23:57:57 +08:00
										 |  |  | jest.mock('@grafana/runtime', () => { | 
					
						
							|  |  |  |   return { | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |     ...jest.requireActual('@grafana/runtime'), | 
					
						
							| 
									
										
										
										
											2022-11-02 23:57:57 +08:00
										 |  |  |     getDataSourceSrv: jest.fn(() => ({ | 
					
						
							|  |  |  |       getInstanceSettings: (uid: string) => ({ | 
					
						
							|  |  |  |         uid, | 
					
						
							|  |  |  |         meta: getMockDataSourceMeta(), | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     })), | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-14 21:51:19 +08:00
										 |  |  | setPluginLinksHook(() => ({ links: [], isLoading: false })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  | const setup = (props?: Partial<ViewProps>) => { | 
					
						
							|  |  |  |   const store = configureStore(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return render( | 
					
						
							|  |  |  |     <Provider store={store}> | 
					
						
							|  |  |  |       <EditDataSourceView | 
					
						
							|  |  |  |         dataSource={getMockDataSource()} | 
					
						
							|  |  |  |         dataSourceMeta={getMockDataSourceMeta()} | 
					
						
							|  |  |  |         dataSourceSettings={getMockDataSourceSettingsState()} | 
					
						
							|  |  |  |         dataSourceRights={{ readOnly: false, hasWriteRights: true, hasDeleteRights: true }} | 
					
						
							|  |  |  |         exploreUrl={'/explore'} | 
					
						
							|  |  |  |         onDelete={jest.fn()} | 
					
						
							|  |  |  |         onDefaultChange={jest.fn()} | 
					
						
							|  |  |  |         onNameChange={jest.fn()} | 
					
						
							| 
									
										
										
										
											2025-06-25 22:02:35 +08:00
										 |  |  |         onOptionsChange={onOptionsChange} | 
					
						
							| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  |         onTest={jest.fn()} | 
					
						
							|  |  |  |         onUpdate={jest.fn()} | 
					
						
							|  |  |  |         {...props} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |     </Provider> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('<EditDataSource>', () => { | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |   beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  |     setPluginComponentsHook(jest.fn().mockReturnValue({ isLoading: false, components: [] })); | 
					
						
							| 
									
										
										
										
											2025-06-25 22:02:35 +08:00
										 |  |  |     onOptionsChange.mockClear(); | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  |   describe('On loading errors', () => { | 
					
						
							|  |  |  |     it('should render a Back button', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSource: getMockDataSource({ name: 'My Datasource' }), | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ loadError: 'Some weird error.' }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText('Loading ...')).not.toBeInTheDocument(); | 
					
						
							|  |  |  |       expect(screen.queryByText('My Datasource')).not.toBeInTheDocument(); | 
					
						
							|  |  |  |       expect(screen.queryByText('Back')).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render a Delete button if the user has rights delete the datasource', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ loadError: 'Some weird error.' }), | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: false, | 
					
						
							|  |  |  |           hasDeleteRights: true, | 
					
						
							|  |  |  |           hasWriteRights: true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText('Delete')).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not render a Delete button if the user has no rights to delete the datasource', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ loadError: 'Some weird error.' }), | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: false, | 
					
						
							|  |  |  |           hasDeleteRights: false, | 
					
						
							|  |  |  |           hasWriteRights: true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText('Delete')).not.toBeInTheDocument(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render a message if the datasource is read-only', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ loadError: 'Some weird error.' }), | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: true, | 
					
						
							|  |  |  |           hasDeleteRights: false, | 
					
						
							|  |  |  |           hasWriteRights: true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText(readOnlyMessage)).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('On loading', () => { | 
					
						
							|  |  |  |     it('should render a loading indicator while the data is being fetched', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSource: getMockDataSource({ name: 'My Datasource' }), | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ loading: true }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText('Loading ...')).toBeVisible(); | 
					
						
							|  |  |  |       expect(screen.queryByText('My Datasource')).not.toBeInTheDocument(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not render loading when data is already available', () => { | 
					
						
							|  |  |  |       setup(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText('Loading ...')).not.toBeInTheDocument(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('On editing', () => { | 
					
						
							|  |  |  |     it('should render no messages if the user has write access and if the data-source is not read-only', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: false, | 
					
						
							|  |  |  |           hasDeleteRights: true, | 
					
						
							|  |  |  |           hasWriteRights: true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText(readOnlyMessage)).not.toBeInTheDocument(); | 
					
						
							|  |  |  |       expect(screen.queryByText(missingRightsMessage)).not.toBeInTheDocument(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render a message if the user has no write access', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: false, | 
					
						
							|  |  |  |           hasDeleteRights: false, | 
					
						
							|  |  |  |           hasWriteRights: false, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText(missingRightsMessage)).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render a message if the data-source is read-only', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: true, | 
					
						
							|  |  |  |           hasDeleteRights: false, | 
					
						
							|  |  |  |           hasWriteRights: false, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText(readOnlyMessage)).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render a beta info message if the plugin is still in Beta state', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceMeta: getMockDataSourceMeta({ | 
					
						
							|  |  |  |           state: PluginState.beta, | 
					
						
							|  |  |  |         }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.getByTitle('This feature is close to complete but not fully tested')).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render an alpha info message if the plugin is still in Alpha state', () => { | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceMeta: getMockDataSourceMeta({ | 
					
						
							|  |  |  |           state: PluginState.alpha, | 
					
						
							|  |  |  |         }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect( | 
					
						
							|  |  |  |         screen.getByTitle('This feature is experimental and future updates might not be backward compatible') | 
					
						
							|  |  |  |       ).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render testing errors with a detailed error message', () => { | 
					
						
							|  |  |  |       const message = 'message'; | 
					
						
							|  |  |  |       const detailsMessage = 'detailed message'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ | 
					
						
							|  |  |  |           testingStatus: { | 
					
						
							|  |  |  |             message, | 
					
						
							|  |  |  |             status: 'error', | 
					
						
							|  |  |  |             details: { message: detailsMessage }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.getByText(message)).toBeVisible(); | 
					
						
							|  |  |  |       expect(screen.getByText(detailsMessage)).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render testing errors with empty details', () => { | 
					
						
							|  |  |  |       const message = 'message'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ | 
					
						
							|  |  |  |           testingStatus: { | 
					
						
							|  |  |  |             message, | 
					
						
							|  |  |  |             status: 'error', | 
					
						
							|  |  |  |             details: {}, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.getByText(message)).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should render testing errors with no details', () => { | 
					
						
							|  |  |  |       const message = 'message'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ | 
					
						
							|  |  |  |           testingStatus: { | 
					
						
							|  |  |  |             message, | 
					
						
							|  |  |  |             status: 'error', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.getByText(message)).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should use the verboseMessage property in the error details whenever it is available', () => { | 
					
						
							|  |  |  |       const message = 'message'; | 
					
						
							|  |  |  |       const detailsMessage = 'detailed message'; | 
					
						
							|  |  |  |       const detailsVerboseMessage = 'even more detailed...'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceSettings: getMockDataSourceSettingsState({ | 
					
						
							|  |  |  |           testingStatus: { | 
					
						
							|  |  |  |             message, | 
					
						
							|  |  |  |             status: 'error', | 
					
						
							|  |  |  |             details: { | 
					
						
							|  |  |  |               details: detailsMessage, | 
					
						
							|  |  |  |               verboseMessage: detailsVerboseMessage, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText(message)).toBeVisible(); | 
					
						
							|  |  |  |       expect(screen.queryByText(detailsMessage)).not.toBeInTheDocument(); | 
					
						
							|  |  |  |       expect(screen.queryByText(detailsVerboseMessage)).toBeInTheDocument(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('when extending the datasource config form', () => { | 
					
						
							|  |  |  |     it('should be possible to extend the form with a "component" extension in case the plugin ID is whitelisted', () => { | 
					
						
							|  |  |  |       const message = "I'm a UI extension component!"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  |       setPluginComponentsHook( | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |         jest.fn().mockReturnValue({ | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  |           isLoading: false, | 
					
						
							|  |  |  |           components: [ | 
					
						
							|  |  |  |             createComponentWithMeta( | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 pluginId: 'grafana-pdc-app', | 
					
						
							|  |  |  |                 title: 'Example component', | 
					
						
							|  |  |  |                 description: 'Example description', | 
					
						
							|  |  |  |                 component: () => <div>{message}</div>, | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               '1' | 
					
						
							|  |  |  |             ), | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |           ], | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: false, | 
					
						
							|  |  |  |           hasDeleteRights: true, | 
					
						
							|  |  |  |           hasWriteRights: true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText(message)).toBeVisible(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should NOT be possible to extend the form with a "component" extension in case the plugin ID is NOT whitelisted', () => { | 
					
						
							|  |  |  |       const message = "I'm a UI extension component!"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  |       setPluginComponentsHook( | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |         jest.fn().mockReturnValue({ | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  |           isLoading: false, | 
					
						
							|  |  |  |           components: [ | 
					
						
							|  |  |  |             createComponentWithMeta( | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 pluginId: 'myorg-basic-app', | 
					
						
							|  |  |  |                 title: 'Example component', | 
					
						
							|  |  |  |                 description: 'Example description', | 
					
						
							|  |  |  |                 component: () => <div>{message}</div>, | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               '1' | 
					
						
							|  |  |  |             ), | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |           ], | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: false, | 
					
						
							|  |  |  |           hasDeleteRights: true, | 
					
						
							|  |  |  |           hasWriteRights: true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(screen.queryByText(message)).not.toBeInTheDocument(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should pass a context prop to the rendered UI extension component', () => { | 
					
						
							|  |  |  |       const message = "I'm a UI extension component!"; | 
					
						
							|  |  |  |       const component = jest.fn().mockReturnValue(<div>{message}</div>); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  |       setPluginComponentsHook( | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |         jest.fn().mockReturnValue({ | 
					
						
							| 
									
										
										
										
											2025-02-25 16:17:17 +08:00
										 |  |  |           isLoading: false, | 
					
						
							|  |  |  |           components: [ | 
					
						
							|  |  |  |             createComponentWithMeta( | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 pluginId: 'grafana-pdc-app', | 
					
						
							|  |  |  |                 title: 'Example component', | 
					
						
							|  |  |  |                 description: 'Example description', | 
					
						
							|  |  |  |                 component, | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               '1' | 
					
						
							|  |  |  |             ), | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |           ], | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setup({ | 
					
						
							|  |  |  |         dataSourceRights: { | 
					
						
							|  |  |  |           readOnly: false, | 
					
						
							|  |  |  |           hasDeleteRights: true, | 
					
						
							|  |  |  |           hasWriteRights: true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(component).toHaveBeenCalled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const props = component.mock.calls[0][0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(props.context).toBeDefined(); | 
					
						
							|  |  |  |       expect(props.context.dataSource).toBeDefined(); | 
					
						
							|  |  |  |       expect(props.context.dataSourceMeta).toBeDefined(); | 
					
						
							|  |  |  |       expect(props.context.setJsonData).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2025-02-17 22:20:35 +08:00
										 |  |  |       expect(props.context.setSecureJsonData).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2023-06-14 19:18:24 +08:00
										 |  |  |       expect(props.context.testingStatus).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2023-06-02 17:01:36 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2025-06-25 22:02:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should be possible to update the `jsonData` first and `secureJsonData` directly afterwards from the extension component', () => { | 
					
						
							|  |  |  |     const message = "I'm a UI extension component!"; | 
					
						
							|  |  |  |     const component = ({ context }: { context: PluginExtensionDataSourceConfigContext }) => { | 
					
						
							|  |  |  |       useEffect(() => { | 
					
						
							|  |  |  |         context.setJsonData({ test: 'test' } as unknown as DataSourceJsonData); | 
					
						
							|  |  |  |         context.setSecureJsonData({ test: 'test' }); | 
					
						
							|  |  |  |         // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
					
						
							|  |  |  |       }, []); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return <div>{message}</div>; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setPluginComponentsHook( | 
					
						
							|  |  |  |       jest.fn().mockReturnValue({ | 
					
						
							|  |  |  |         isLoading: false, | 
					
						
							|  |  |  |         components: [ | 
					
						
							|  |  |  |           createComponentWithMeta( | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               pluginId: 'grafana-pdc-app', | 
					
						
							|  |  |  |               title: 'Example component', | 
					
						
							|  |  |  |               description: 'Example description', | 
					
						
							|  |  |  |               component: component as unknown as React.ComponentType<{}>, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             '1' | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setup({ | 
					
						
							|  |  |  |       dataSourceRights: { | 
					
						
							|  |  |  |         readOnly: false, | 
					
						
							|  |  |  |         hasDeleteRights: true, | 
					
						
							|  |  |  |         hasWriteRights: true, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(onOptionsChange).toHaveBeenCalledTimes(2); | 
					
						
							|  |  |  |     expect(onOptionsChange).toHaveBeenCalledWith({ | 
					
						
							|  |  |  |       ...getMockDataSource(), | 
					
						
							|  |  |  |       jsonData: { ...getMockDataSource().jsonData, test: 'test' }, | 
					
						
							|  |  |  |       secureJsonData: { test: 'test' }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be possible to update the `secureJsonData` first and `jsonData` directly afterwards from the extension component', () => { | 
					
						
							|  |  |  |     const message = "I'm a UI extension component!"; | 
					
						
							|  |  |  |     const component = ({ context }: { context: PluginExtensionDataSourceConfigContext }) => { | 
					
						
							|  |  |  |       useEffect(() => { | 
					
						
							|  |  |  |         context.setSecureJsonData({ test: 'test' }); | 
					
						
							|  |  |  |         context.setJsonData({ test: 'test' } as unknown as DataSourceJsonData); | 
					
						
							|  |  |  |         // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
					
						
							|  |  |  |       }, []); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return <div>{message}</div>; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setPluginComponentsHook( | 
					
						
							|  |  |  |       jest.fn().mockReturnValue({ | 
					
						
							|  |  |  |         isLoading: false, | 
					
						
							|  |  |  |         components: [ | 
					
						
							|  |  |  |           createComponentWithMeta( | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               pluginId: 'grafana-pdc-app', | 
					
						
							|  |  |  |               title: 'Example component', | 
					
						
							|  |  |  |               description: 'Example description', | 
					
						
							|  |  |  |               component: component as unknown as React.ComponentType<{}>, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             '1' | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setup({ | 
					
						
							|  |  |  |       dataSourceRights: { | 
					
						
							|  |  |  |         readOnly: false, | 
					
						
							|  |  |  |         hasDeleteRights: true, | 
					
						
							|  |  |  |         hasWriteRights: true, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(onOptionsChange).toHaveBeenCalledTimes(2); | 
					
						
							|  |  |  |     expect(onOptionsChange).toHaveBeenCalledWith({ | 
					
						
							|  |  |  |       ...getMockDataSource(), | 
					
						
							|  |  |  |       jsonData: { ...getMockDataSource().jsonData, test: 'test' }, | 
					
						
							|  |  |  |       secureJsonData: { test: 'test' }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-07-20 15:25:09 +08:00
										 |  |  | }); |