Fix(ui): loading issue for react-awesome-query (#21424)

* fixed loading issue for react-awesome-query

* added tests

---------

Co-authored-by: Karan Hotchandani <33024356+karanh37@users.noreply.github.com>
(cherry picked from commit 40aba1d906e61a7e8061336b75e1979549d424ff)
This commit is contained in:
Dhruv Parmar 2025-06-10 04:38:56 +05:30 committed by OpenMetadata Release Bot
parent 82aca0cea5
commit bd250765cb
3 changed files with 69 additions and 11 deletions

View File

@ -22,6 +22,7 @@ import {
FIELDS,
OPERATOR,
runRuleGroupTests,
runRuleGroupTestsWithNonExistingValue,
verifyAllConditions,
} from '../../utils/advancedSearch';
import { createNewPage, redirectToHomePage } from '../../utils/common';
@ -287,4 +288,12 @@ test.describe('Advanced Search', { tag: '@advanced-search' }, () => {
});
});
});
test('Verify search with non existing value do not result in infinite search', async ({
page,
}) => {
test.slow(true);
await runRuleGroupTestsWithNonExistingValue(page);
});
});

View File

@ -581,3 +581,32 @@ export const runRuleGroupTests = async (
await page.getByTestId('clear-filters').click();
}
};
export const runRuleGroupTestsWithNonExistingValue = async (page: Page) => {
await showAdvancedSearchDialog(page);
const ruleLocator = page.locator('.rule').nth(0);
// Perform click on rule field
await selectOption(
page,
ruleLocator.locator('.rule--field .ant-select'),
'Database'
);
await selectOption(
page,
ruleLocator.locator('.rule--operator .ant-select'),
'=='
);
const inputElement = ruleLocator.locator(
'.rule--widget--SELECT .ant-select-selection-search-input'
);
await inputElement.fill('non-existing-value');
const dropdownText = page.locator('.ant-select-item-empty');
await expect(dropdownText).toContainText('Loading...');
await page.waitForTimeout(1000);
await expect(dropdownText).not.toContainText('Loading...');
};

View File

@ -137,8 +137,10 @@ class AdvancedSearchClassBase {
entityField,
isCaseInsensitive = false,
}) => {
// Wrapping the fetch function in a debounce of 300 ms
const debouncedFetch = debounce((search, callback) => {
let pendingResolve:
| ((result: { values: any[]; hasMore: boolean }) => void)
| null = null;
const debouncedFetch = debounce((search: string) => {
const sourceFields = isCaseInsensitive
? EntitySourceFields?.[entityField as EntityFields]?.join(',')
: undefined;
@ -149,22 +151,40 @@ class AdvancedSearchClassBase {
search ?? '',
JSON.stringify(getCombinedQueryFilterObject()),
sourceFields
).then((response) => {
const buckets =
response.data.aggregations[`sterms#${entityField}`].buckets;
)
.then((response) => {
const buckets =
response.data.aggregations[`sterms#${entityField}`].buckets;
const bucketsData = parseBucketsData(buckets, sourceFields);
const bucketsData = parseBucketsData(buckets, sourceFields);
callback({
values: bucketsData,
hasMore: false,
if (pendingResolve) {
pendingResolve({
values: bucketsData,
hasMore: false,
});
pendingResolve = null;
}
})
.catch(() => {
if (pendingResolve) {
pendingResolve({
values: [],
hasMore: false,
});
pendingResolve = null;
}
});
});
}, 300);
return (search) => {
return new Promise((resolve) => {
debouncedFetch(search, resolve);
// Resolve previous promise to prevent hanging
if (pendingResolve) {
pendingResolve({ values: [], hasMore: false });
}
pendingResolve = resolve;
debouncedFetch(search ?? '');
});
};
};