mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			181 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
| import { openai } from '@grafana/llm';
 | |
| 
 | |
| import { DASHBOARD_SCHEMA_VERSION } from '../../state/DashboardMigrator';
 | |
| import { createDashboardModelFixture, createPanelSaveModel } from '../../state/__fixtures__/dashboardFixtures';
 | |
| import { NEW_PANEL_TITLE } from '../../utils/dashboard';
 | |
| 
 | |
| import { getDashboardChanges, getPanelStrings, isLLMPluginEnabled, sanitizeReply } from './utils';
 | |
| 
 | |
| // Mock the openai module
 | |
| jest.mock('@grafana/llm', () => ({
 | |
|   ...jest.requireActual('@grafana/llm'),
 | |
|   openai: {
 | |
|     streamChatCompletions: jest.fn(),
 | |
|     accumulateContent: jest.fn(),
 | |
|     health: jest.fn(),
 | |
|   },
 | |
| }));
 | |
| 
 | |
| jest.mock('@grafana/runtime', () => ({
 | |
|   ...jest.requireActual('@grafana/runtime'),
 | |
|   config: {
 | |
|     ...jest.requireActual('@grafana/runtime').config,
 | |
|     apps: {
 | |
|       'grafana-llm-app': true,
 | |
|     },
 | |
|   },
 | |
| }));
 | |
| 
 | |
| describe('getDashboardChanges', () => {
 | |
|   it('should correctly split user changes and migration changes', () => {
 | |
|     // Mock data for testing
 | |
|     const deprecatedOptions = {
 | |
|       legend: { displayMode: 'hidden', showLegend: false },
 | |
|     };
 | |
|     const deprecatedVersion = DASHBOARD_SCHEMA_VERSION - 1;
 | |
|     const dashboard = createDashboardModelFixture({
 | |
|       schemaVersion: deprecatedVersion,
 | |
|       panels: [createPanelSaveModel({ title: 'Panel 1', options: deprecatedOptions })],
 | |
|     });
 | |
| 
 | |
|     // Update title for the first panel
 | |
|     dashboard.updatePanels([
 | |
|       {
 | |
|         ...dashboard.panels[0],
 | |
|         title: 'New title',
 | |
|       },
 | |
|       ...dashboard.panels.slice(1),
 | |
|     ]);
 | |
| 
 | |
|     // Call the function to test
 | |
|     const result = getDashboardChanges(dashboard);
 | |
| 
 | |
|     // Assertions
 | |
|     expect(result.migrationChanges).toContain(
 | |
|       `-  "schemaVersion": ${deprecatedVersion},\n+  "schemaVersion": ${DASHBOARD_SCHEMA_VERSION},\n`
 | |
|     );
 | |
| 
 | |
|     expect(result.migrationChanges).not.toContain(
 | |
|       '   "panels": [\n' +
 | |
|         '     {\n' +
 | |
|         '-      "type": "timeseries",\n' +
 | |
|         '-      "title": "Panel 1",\n' +
 | |
|         '+      "id": 1,\n'
 | |
|     );
 | |
| 
 | |
|     expect(result.migrationChanges).not.toContain(
 | |
|       '-      }\n' +
 | |
|         '+      },\n' +
 | |
|         '+      "title": "New title",\n' +
 | |
|         '+      "type": "timeseries"\n' +
 | |
|         '     }\n' +
 | |
|         '   ]\n' +
 | |
|         ' }\n'
 | |
|     );
 | |
| 
 | |
|     expect(result.userChanges).not.toContain('-  "schemaVersion": 37,\n' + '+  "schemaVersion": 38,\n');
 | |
| 
 | |
|     expect(result.userChanges).toContain(
 | |
|       '   "panels": [\n' +
 | |
|         '     {\n' +
 | |
|         '-      "type": "timeseries",\n' +
 | |
|         '-      "title": "Panel 1",\n' +
 | |
|         '+      "id": 1,\n'
 | |
|     );
 | |
| 
 | |
|     expect(result.userChanges).toContain(
 | |
|       '-      }\n' +
 | |
|         '+      },\n' +
 | |
|         '+      "title": "New title",\n' +
 | |
|         '+      "type": "timeseries"\n' +
 | |
|         '     }\n' +
 | |
|         '   ]\n' +
 | |
|         ' }\n'
 | |
|     );
 | |
| 
 | |
|     expect(result.migrationChanges).toBeDefined();
 | |
|   });
 | |
| });
 | |
| 
 | |
| describe('isLLMPluginEnabled', () => {
 | |
|   it('should return false if LLM plugin is not enabled', async () => {
 | |
|     // Mock openai.health to return false
 | |
|     jest.mocked(openai.health).mockResolvedValue({ ok: false, configured: false });
 | |
| 
 | |
|     const enabled = await isLLMPluginEnabled();
 | |
| 
 | |
|     expect(enabled).toBe(false);
 | |
|   });
 | |
| 
 | |
|   it('should return true if LLM plugin is enabled', async () => {
 | |
|     // Mock openai.health to return true
 | |
|     jest.mocked(openai.health).mockResolvedValue({ ok: true, configured: false });
 | |
| 
 | |
|     const enabled = await isLLMPluginEnabled();
 | |
| 
 | |
|     expect(enabled).toBe(true);
 | |
|   });
 | |
| });
 | |
| 
 | |
| describe('sanitizeReply', () => {
 | |
|   it('should remove quotes from the beginning and end of a string', () => {
 | |
|     expect(sanitizeReply('"Hello, world!"')).toBe('Hello, world!');
 | |
|   });
 | |
| 
 | |
|   it('should not remove quotes from the middle of a string', () => {
 | |
|     expect(sanitizeReply('Hello, "world"!')).toBe('Hello, "world"!');
 | |
|   });
 | |
| 
 | |
|   it('should only remove quotes if they are at the beginning or end of a string, and not in the middle', () => {
 | |
|     expect(sanitizeReply('"Hello", world!')).toBe('Hello", world!');
 | |
|   });
 | |
| 
 | |
|   it('should return an empty string if given an empty string', () => {
 | |
|     expect(sanitizeReply('')).toBe('');
 | |
|   });
 | |
| });
 | |
| 
 | |
| describe('getPanelStrings', () => {
 | |
|   function dashboardSetup(items: Array<{ title: string; description: string }>) {
 | |
|     return createDashboardModelFixture({
 | |
|       panels: items.map((item) => createPanelSaveModel(item)),
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   it('should return an empty array if all panels dont have title or descriptions', () => {
 | |
|     const dashboard = dashboardSetup([{ title: '', description: '' }]);
 | |
| 
 | |
|     expect(getPanelStrings(dashboard)).toEqual([]);
 | |
|   });
 | |
| 
 | |
|   it('should return an empty array if all panels have no description and panels that have title are titled "Panel title', () => {
 | |
|     const dashboard = dashboardSetup([{ title: NEW_PANEL_TITLE, description: '' }]);
 | |
| 
 | |
|     expect(getPanelStrings(dashboard)).toEqual([]);
 | |
|   });
 | |
| 
 | |
|   it('should return an array of panels if a panel has a title or description', () => {
 | |
|     const dashboard = dashboardSetup([
 | |
|       { title: 'Graph panel', description: '' },
 | |
|       { title: '', description: 'Logs' },
 | |
|     ]);
 | |
| 
 | |
|     expect(getPanelStrings(dashboard)).toEqual([
 | |
|       '- Panel 0\n- Title: Graph panel',
 | |
|       '- Panel 1\n- Title: \n- Description: Logs',
 | |
|     ]);
 | |
|   });
 | |
| 
 | |
|   it('returns an array with title and description if both are present', () => {
 | |
|     const dashboard = dashboardSetup([
 | |
|       { title: 'Graph panel', description: 'Logs' },
 | |
|       { title: 'Table panel', description: 'Metrics' },
 | |
|     ]);
 | |
| 
 | |
|     expect(getPanelStrings(dashboard)).toEqual([
 | |
|       '- Panel 0\n- Title: Graph panel\n- Description: Logs',
 | |
|       '- Panel 1\n- Title: Table panel\n- Description: Metrics',
 | |
|     ]);
 | |
|   });
 | |
| });
 |