201 lines
5.2 KiB
TypeScript
201 lines
5.2 KiB
TypeScript
import { BackendSrv } from '@grafana/runtime';
|
|
|
|
import { GrafanaSearcher, SearchQuery } from './types';
|
|
import { toDashboardResults, SearchHit, SearchAPIResponse, UnifiedSearcher } from './unified';
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
const mockResults: SearchAPIResponse = {
|
|
hits: [],
|
|
totalHits: 0,
|
|
};
|
|
|
|
const mockFolders: SearchAPIResponse = {
|
|
hits: [],
|
|
totalHits: 0,
|
|
};
|
|
|
|
const mockFallbackSearcher = {
|
|
search: jest.fn(),
|
|
} as unknown as GrafanaSearcher;
|
|
|
|
const getResponse = (uri: string) => {
|
|
if (uri.endsWith('?type=folders')) {
|
|
return Promise.resolve(mockFolders);
|
|
}
|
|
return Promise.resolve(mockResults);
|
|
};
|
|
|
|
const mockSearcher = {
|
|
search: (uri: string) => getResponse(uri),
|
|
};
|
|
|
|
jest.mock('@grafana/runtime', () => {
|
|
const originalRuntime = jest.requireActual('@grafana/runtime');
|
|
return {
|
|
...originalRuntime,
|
|
getBackendSrv: () =>
|
|
({
|
|
get: (uri: string) => mockSearcher.search(uri),
|
|
}) as unknown as BackendSrv,
|
|
};
|
|
});
|
|
|
|
describe('Unified Storage Searcher', () => {
|
|
it('should perform search with basic query', async () => {
|
|
mockFolders.hits = [
|
|
{
|
|
name: 'folder1',
|
|
title: 'Folder 1',
|
|
resource: 'folders',
|
|
} as SearchHit,
|
|
];
|
|
mockResults.hits = [
|
|
{
|
|
name: 'dashboard1',
|
|
title: 'Dashboard 1',
|
|
resource: 'dashboards',
|
|
folder: 'folder1',
|
|
} as SearchHit,
|
|
];
|
|
|
|
const query: SearchQuery = {
|
|
query: 'test',
|
|
limit: 50,
|
|
};
|
|
|
|
const searcher = new UnifiedSearcher(mockFallbackSearcher);
|
|
|
|
const response = await searcher.search(query);
|
|
|
|
expect(response.view.length).toBe(1);
|
|
expect(response.view.get(0).title).toBe('Dashboard 1');
|
|
|
|
const df = response.view.dataFrame;
|
|
const locationInfo = df.meta?.custom?.locationInfo;
|
|
expect(locationInfo).toBeDefined();
|
|
expect(locationInfo?.folder1.name).toBe('Folder 1');
|
|
});
|
|
|
|
it('should perform search and sync folders with missing folder', async () => {
|
|
const mockFolders = {
|
|
hits: [
|
|
{
|
|
name: 'folder2',
|
|
title: 'Folder 2',
|
|
resource: 'folders',
|
|
} as SearchHit,
|
|
],
|
|
totalHits: 1,
|
|
};
|
|
|
|
const mockResults = {
|
|
hits: [
|
|
{
|
|
name: 'db1',
|
|
title: 'DB 1',
|
|
resource: 'dashboards',
|
|
folder: 'folder1',
|
|
} as SearchHit,
|
|
{
|
|
name: 'db2',
|
|
title: 'DB 2',
|
|
resource: 'dashboards',
|
|
folder: 'folder2',
|
|
} as SearchHit,
|
|
],
|
|
totalHits: 2,
|
|
};
|
|
|
|
jest
|
|
.spyOn(mockSearcher, 'search')
|
|
.mockResolvedValueOnce(mockFolders)
|
|
.mockResolvedValueOnce(mockResults)
|
|
.mockResolvedValueOnce(mockFolders);
|
|
|
|
const query: SearchQuery = {
|
|
query: 'test',
|
|
limit: 50,
|
|
};
|
|
|
|
const searcher = new UnifiedSearcher(mockFallbackSearcher);
|
|
|
|
const response = await searcher.search(query);
|
|
|
|
expect(response.view.length).toBe(2);
|
|
expect(response.view.get(0).title).toBe('DB 1');
|
|
expect(response.view.get(0).folder).toBe('sharedwithme');
|
|
expect(response.view.get(1).title).toBe('DB 2');
|
|
|
|
const df = response.view.dataFrame;
|
|
const locationInfo = df.meta?.custom?.locationInfo;
|
|
expect(locationInfo).toBeDefined();
|
|
expect(locationInfo?.folder2.name).toBe('Folder 2');
|
|
expect(mockSearcher.search).toHaveBeenCalledTimes(3);
|
|
});
|
|
|
|
it('can create dashboard search results and set meta sortBy so column is added for sprinkles sort field', () => {
|
|
const mockHits: SearchHit[] = [
|
|
{
|
|
resource: 'dashboard',
|
|
name: 'Main Dashboard',
|
|
title: 'Main Dashboard Title',
|
|
location: '/dashboards/1',
|
|
folder: 'General',
|
|
tags: ['monitoring', 'performance'],
|
|
field: { errors_today: 1 },
|
|
url: '/dashboards/1/main-dashboard-title',
|
|
},
|
|
{
|
|
resource: 'dashboard',
|
|
name: 'Main Dashboard',
|
|
title: 'Main Dashboard Title',
|
|
location: '/dashboards/1',
|
|
folder: 'General',
|
|
tags: ['monitoring', 'performance'],
|
|
field: { errors_today: 2 },
|
|
url: '/dashboards/1/main-dashboard-title',
|
|
},
|
|
];
|
|
|
|
const mockResponse: SearchAPIResponse = {
|
|
totalHits: 2,
|
|
hits: mockHits,
|
|
facets: {},
|
|
};
|
|
const results = toDashboardResults(mockResponse, 'errors_today');
|
|
|
|
expect(results.length).toBe(2);
|
|
const sprinklesField = results.fields[10];
|
|
expect(sprinklesField.name).toBe('errors_today');
|
|
expect(sprinklesField.values).toEqual([1, 2]); // this also tests the hits original order is preserved
|
|
expect(results.meta?.custom?.sortBy).toBe('errors_today');
|
|
});
|
|
|
|
it('will trim "-" from the sort field name', () => {
|
|
const mockHits: SearchHit[] = [
|
|
{
|
|
resource: 'dashboard',
|
|
name: 'Main Dashboard',
|
|
title: 'Main Dashboard Title',
|
|
location: '/dashboards/1',
|
|
folder: 'General',
|
|
tags: ['monitoring', 'performance'],
|
|
field: { errors_today: 1 },
|
|
url: '/dashboards/1/main-dashboard-title',
|
|
},
|
|
];
|
|
|
|
const mockResponse: SearchAPIResponse = {
|
|
totalHits: 0,
|
|
hits: mockHits,
|
|
facets: {},
|
|
};
|
|
const results = toDashboardResults(mockResponse, '-errors_today');
|
|
|
|
expect(results.meta?.custom?.sortBy).toBe('errors_today');
|
|
});
|
|
});
|