mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: Fix flaky saved search tests (#2079)
## Summary This PR fixes failing Saved-Search E2E tests by 1. Fixing a bug that caused the saved search's source to sometime not populate when navigating directly to the saved search 2. Updating the saved search modal to wait until the create saved search mutation completes and invalidates saved searches before attempting to navigate (also, added a loading state and error notifications to the modal) 3. Updated a few test assertions to be more explicit about waiting for the saved search to load ### Screenshots or video ### How to test locally or on Vercel ### References - Linear Issue: - Related PRs:
This commit is contained in:
parent
337ebff054
commit
6ef3b48e0c
5 changed files with 57 additions and 23 deletions
|
|
@ -409,7 +409,7 @@ function SaveSearchModalComponent({
|
|||
const onSubmit = (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
handleSubmit(({ name }) => {
|
||||
handleSubmit(async ({ name }) => {
|
||||
if (isUpdate) {
|
||||
if (savedSearchId == null) {
|
||||
throw new Error('savedSearchId is required for update');
|
||||
|
|
@ -432,11 +432,20 @@ function SaveSearchModalComponent({
|
|||
onSuccess: () => {
|
||||
onClose();
|
||||
},
|
||||
onError: error => {
|
||||
console.error('Error updating saved search:', error);
|
||||
notifications.show({
|
||||
color: 'red',
|
||||
title: 'Error',
|
||||
message:
|
||||
'An error occurred while updating your saved search. Please try again.',
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
} else {
|
||||
createSavedSearch.mutate(
|
||||
{
|
||||
try {
|
||||
const savedSearch = await createSavedSearch.mutateAsync({
|
||||
name,
|
||||
select: effectiveSelect,
|
||||
where: searchedConfig.where ?? '',
|
||||
|
|
@ -446,18 +455,25 @@ function SaveSearchModalComponent({
|
|||
orderBy: searchedConfig.orderBy ?? '',
|
||||
filters: searchedConfig.filters ?? [],
|
||||
tags: tags,
|
||||
},
|
||||
{
|
||||
onSuccess: savedSearch => {
|
||||
router.push(`/search/${savedSearch.id}${window.location.search}`);
|
||||
onClose();
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
router.push(`/search/${savedSearch.id}${window.location.search}`);
|
||||
onClose();
|
||||
} catch (error) {
|
||||
console.error('Error creating saved search:', error);
|
||||
notifications.show({
|
||||
color: 'red',
|
||||
title: 'Error',
|
||||
message:
|
||||
'An error occurred while saving your search. Please try again.',
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
const isPending = createSavedSearch.isPending || updateSavedSearch.isPending;
|
||||
|
||||
const { data: chartConfig } = useSearchedConfigToChartConfig(searchedConfig);
|
||||
|
||||
return (
|
||||
|
|
@ -572,6 +588,7 @@ function SaveSearchModalComponent({
|
|||
variant="primary"
|
||||
type="submit"
|
||||
disabled={!formState.isValid}
|
||||
loading={isPending}
|
||||
>
|
||||
{isUpdate ? 'Update' : 'Save'}
|
||||
</Button>
|
||||
|
|
@ -869,7 +886,7 @@ function DBSearchPage() {
|
|||
where: searchedConfig.where || '',
|
||||
whereLanguage:
|
||||
searchedConfig.whereLanguage ?? getStoredLanguage() ?? 'lucene',
|
||||
source: searchedConfig.source || defaultSourceId,
|
||||
source: searchedConfig.source || (savedSearchId ? '' : defaultSourceId),
|
||||
filters: searchedConfig.filters ?? [],
|
||||
orderBy: searchedConfig.orderBy ?? '',
|
||||
},
|
||||
|
|
@ -1619,16 +1636,18 @@ function DBSearchPage() {
|
|||
</Text>
|
||||
</Group>
|
||||
<Group justify="space-between" align="flex-end">
|
||||
<EditablePageName
|
||||
key={savedSearch.id}
|
||||
name={savedSearch?.name ?? 'Untitled Search'}
|
||||
onSave={editedName => {
|
||||
updateSavedSearch.mutate({
|
||||
id: savedSearch.id,
|
||||
name: editedName,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<div data-testid="saved-search-name">
|
||||
<EditablePageName
|
||||
key={savedSearch.id}
|
||||
name={savedSearch?.name ?? 'Untitled Search'}
|
||||
onSave={editedName => {
|
||||
updateSavedSearch.mutate({
|
||||
id: savedSearch.id,
|
||||
name: editedName,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Group gap="xs">
|
||||
<FavoriteButton
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export function useCreateSavedSearch() {
|
|||
}).json<SavedSearch>();
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['saved-search'] });
|
||||
return queryClient.invalidateQueries({ queryKey: ['saved-search'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ export class SavedSearchModalComponent {
|
|||
readonly page: Page;
|
||||
private readonly modal: Locator;
|
||||
private readonly nameInput: Locator;
|
||||
private readonly savedSearchNameTitle: Locator;
|
||||
private readonly submitButton: Locator;
|
||||
private readonly addTagButton: Locator;
|
||||
|
||||
|
|
@ -16,6 +17,9 @@ export class SavedSearchModalComponent {
|
|||
this.page = page;
|
||||
this.modal = page.locator('[data-testid="save-search-modal"]');
|
||||
this.nameInput = page.locator('[data-testid="save-search-name-input"]');
|
||||
this.savedSearchNameTitle = page.locator(
|
||||
'[data-testid="saved-search-name"]',
|
||||
);
|
||||
this.submitButton = page.locator(
|
||||
'[data-testid="save-search-submit-button"]',
|
||||
);
|
||||
|
|
@ -98,6 +102,9 @@ export class SavedSearchModalComponent {
|
|||
|
||||
// Wait for modal to fully close
|
||||
await expect(this.container).toBeHidden();
|
||||
|
||||
await expect(this.savedSearchNameTitle).toBeVisible({ timeout: 5000 });
|
||||
await expect(this.savedSearchNameTitle).toHaveText(name, { timeout: 5000 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -263,6 +263,10 @@ test.describe('Saved Search Functionality', () => {
|
|||
|
||||
// Wait for the search page to load
|
||||
await expect(page.getByTestId('search-page')).toBeVisible();
|
||||
await expect(searchPage.savedSearchNameTitle).toBeVisible();
|
||||
await expect(searchPage.savedSearchNameTitle).toHaveText(
|
||||
'Info Logs Navigation Test',
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Verify saved search loaded and executed automatically', async () => {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export class SearchPage {
|
|||
readonly infrastructure: InfrastructurePanelComponent;
|
||||
readonly filters: FilterComponent;
|
||||
readonly savedSearchModal: SavedSearchModalComponent;
|
||||
readonly savedSearchNameTitle: Locator;
|
||||
readonly alertModal: SearchPageAlertModalComponent;
|
||||
readonly defaultTimeout: number = 3000;
|
||||
private readonly alertsButtonLocator: Locator;
|
||||
|
|
@ -53,6 +54,9 @@ export class SearchPage {
|
|||
this.savedSearchModal = new SavedSearchModalComponent(page);
|
||||
this.alertModal = new SearchPageAlertModalComponent(page);
|
||||
this.alertsButtonLocator = page.getByTestId('alerts-button');
|
||||
this.savedSearchNameTitle = page.locator(
|
||||
'[data-testid="saved-search-name"]',
|
||||
);
|
||||
|
||||
// Define page-specific locators
|
||||
this.searchForm = page.getByTestId('search-form');
|
||||
|
|
|
|||
Loading…
Reference in a new issue