mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Search: Fix Search returning results out of order (#68370)
* Search: Fix Search returning results out of order * test
This commit is contained in:
parent
c8fd3c20cd
commit
78afddebbf
@ -7,6 +7,15 @@ import * as utils from '../utils';
|
|||||||
|
|
||||||
import { getSearchStateManager } from './SearchStateManager';
|
import { getSearchStateManager } from './SearchStateManager';
|
||||||
|
|
||||||
|
jest.mock('lodash', () => {
|
||||||
|
const orig = jest.requireActual('lodash');
|
||||||
|
|
||||||
|
return {
|
||||||
|
...orig,
|
||||||
|
debounce: (d: Function) => d,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
jest.mock('@grafana/runtime', () => {
|
jest.mock('@grafana/runtime', () => {
|
||||||
const originalModule = jest.requireActual('@grafana/runtime');
|
const originalModule = jest.requireActual('@grafana/runtime');
|
||||||
return {
|
return {
|
||||||
@ -15,7 +24,8 @@ jest.mock('@grafana/runtime', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('SearchStateManager', () => {
|
describe('SearchStateManager', () => {
|
||||||
jest.spyOn(getGrafanaSearcher(), 'search').mockResolvedValue({
|
const searcher = getGrafanaSearcher();
|
||||||
|
jest.spyOn(searcher, 'search').mockResolvedValue({
|
||||||
isItemLoaded: jest.fn(),
|
isItemLoaded: jest.fn(),
|
||||||
loadMoreItems: jest.fn(),
|
loadMoreItems: jest.fn(),
|
||||||
totalRows: 0,
|
totalRows: 0,
|
||||||
@ -69,5 +79,44 @@ describe('SearchStateManager', () => {
|
|||||||
expect(stm.state.sort).toBe(undefined);
|
expect(stm.state.sort).toBe(undefined);
|
||||||
expect(stm.state.folderUid).toBe('abc');
|
expect(stm.state.folderUid).toBe('abc');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('updates search results in order', async () => {
|
||||||
|
const stm = getSearchStateManager();
|
||||||
|
|
||||||
|
jest.spyOn(searcher, 'search').mockReturnValueOnce(
|
||||||
|
new Promise(async (resolve) => {
|
||||||
|
await wait(100);
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
isItemLoaded: jest.fn(),
|
||||||
|
loadMoreItems: jest.fn(),
|
||||||
|
totalRows: 100,
|
||||||
|
view: new DataFrameView<DashboardQueryResult>({ fields: [], length: 0 }),
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
stm.onQueryChange('d');
|
||||||
|
|
||||||
|
jest.spyOn(searcher, 'search').mockReturnValueOnce(
|
||||||
|
new Promise(async (resolve) => {
|
||||||
|
await wait(50);
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
isItemLoaded: jest.fn(),
|
||||||
|
loadMoreItems: jest.fn(),
|
||||||
|
totalRows: 10,
|
||||||
|
view: new DataFrameView<DashboardQueryResult>({ fields: [], length: 0 }),
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
stm.onQueryChange('debugging');
|
||||||
|
|
||||||
|
await wait(150);
|
||||||
|
|
||||||
|
expect(stm.state.result?.totalRows).toEqual(10);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
@ -39,6 +39,7 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
updateLocation = debounce((query) => locationService.partial(query, true), 300);
|
updateLocation = debounce((query) => locationService.partial(query, true), 300);
|
||||||
doSearchWithDebounce = debounce(() => this.doSearch(), 300);
|
doSearchWithDebounce = debounce(() => this.doSearch(), 300);
|
||||||
lastQuery?: SearchQuery;
|
lastQuery?: SearchQuery;
|
||||||
|
lastSearchPromise: Promise<void> = Promise.resolve();
|
||||||
|
|
||||||
initStateFromUrl(folderUid?: string, doInitialSearch = true) {
|
initStateFromUrl(folderUid?: string, doInitialSearch = true) {
|
||||||
const stateFromUrl = parseRouteParams(locationService.getSearchObject());
|
const stateFromUrl = parseRouteParams(locationService.getSearchObject());
|
||||||
@ -224,9 +225,13 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
|
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
|
||||||
if (this.state.starred) {
|
const searcher = getGrafanaSearcher();
|
||||||
getGrafanaSearcher()
|
|
||||||
.starred(this.lastQuery)
|
// Issue this search now, but wait until previous searches have resolved to update it in the state
|
||||||
|
const searchPromise = this.state.starred ? searcher.starred(this.lastQuery) : searcher.search(this.lastQuery);
|
||||||
|
|
||||||
|
this.lastSearchPromise = this.lastSearchPromise
|
||||||
|
.then(() => searchPromise)
|
||||||
.then((result) => this.setState({ result, loading: false }))
|
.then((result) => this.setState({ result, loading: false }))
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
reportSearchFailedQueryInteraction(this.state.eventTrackingNamespace, {
|
reportSearchFailedQueryInteraction(this.state.eventTrackingNamespace, {
|
||||||
@ -234,19 +239,9 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
error: error?.message,
|
error: error?.message,
|
||||||
});
|
});
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
|
||||||
|
return Promise.resolve(); // make sure this.lastSearchPromise is always resolved
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
getGrafanaSearcher()
|
|
||||||
.search(this.lastQuery)
|
|
||||||
.then((result) => this.setState({ result, loading: false }))
|
|
||||||
.catch((error) => {
|
|
||||||
reportSearchFailedQueryInteraction(this.state.eventTrackingNamespace, {
|
|
||||||
...trackingInfo,
|
|
||||||
error: error?.message,
|
|
||||||
});
|
|
||||||
this.setState({ loading: false });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This gets the possible tags from within the query results
|
// This gets the possible tags from within the query results
|
||||||
|
Loading…
Reference in New Issue
Block a user