Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/playwright/impact-map.generated.json
Original file line number Diff line number Diff line change
Expand Up @@ -3328,6 +3328,7 @@
"playwright/e2e/Features/AdvancedSearch.spec.ts",
"playwright/e2e/Features/ContextCenterDashboard.spec.ts",
"playwright/e2e/Features/DataQuality/IncidentManagerSqlQuery.spec.ts",
"playwright/e2e/Features/DataQuality/ProfilerIngestionForm.spec.ts",
"playwright/e2e/Features/DataQuality/TableTestCaseExportFilters.spec.ts",
"playwright/e2e/Features/DomainFilterQueryFilter.spec.ts",
"playwright/e2e/Features/LandingPageWidgets/LandingPageContextCenter.spec.ts",
Expand Down Expand Up @@ -8668,6 +8669,7 @@
"openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/AddIngestion/AddIngestion.component.tsx"
],
"specs": [
"playwright/e2e/Features/DataQuality/ProfilerIngestionForm.spec.ts",
"playwright/e2e/Features/StorageMetadataAgentForm.spec.ts"
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,22 @@
Type,
type Destination,
} from '../../../generated/events/eventSubscription';
import {

Check warning on line 49 in openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here
ModifiedCreateEventSubscription,
ModifiedDestination,
} from '../../../pages/AddObservabilityPage/AddObservabilityPage.interface';
import { testAlertDestination } from '../../../rest/alertsAPI';
import { searchQuery } from '../../../rest/searchAPI';
import { AlertSourceSearch } from '../../../utils/Alerts/AlertSourceSearch';
import alertsClassBase from '../../../utils/AlertsClassBase';
import AlertAiDestinationConfigFields from './AlertAiDestinationConfigFields.component';
import AlertAiDestinationItem from './AlertAiDestinationItem.component';
import AlertAiDestinationSection from './AlertAiDestinationSection.component';
import AlertAiForm from './AlertAiForm.component';
import AlertAiFormFields from './AlertAiFormFields.component';
import AlertAiRuleSection from './AlertAiRuleSection.component';
import AlertAiRuleSection, {
RuleArgumentField,
} from './AlertAiRuleSection.component';
import AlertAiSection from './AlertAiSection.component';
import AlertDescriptionCard from './AlertDescriptionCard.component';

Expand Down Expand Up @@ -859,6 +862,60 @@
);
});

it('keeps a typed search when the source search is rebuilt during the debounce', async () => {
jest.useFakeTimers();
const getSourceSearch = () =>
({
byId: jest.fn(),
byName: jest.fn(),
containerEntities: [],
indexes: [],
} as unknown as AlertSourceSearch);
const value = {
...baseValue,
input: {
filters: [
{
arguments: [{ input: [], name: 'domainList' }],
effect: Effect.Include,
name: 'matchAnyDomain',
},
],
},
} as ModifiedCreateEventSubscription;
const renderField = (sourceSearch: AlertSourceSearch) => (
<RuleArgumentField
argument="domainList"
field="filters"
index={0}
name={0}
sourceSearch={sourceSearch}
value={value}
onChange={jest.fn()}
/>
);

const { rerender } = render(renderField(getSourceSearch()));
await act(async () => {
jest.advanceTimersByTime(0);
});
(searchQuery as jest.Mock).mockClear();

fireEvent.change(screen.getByTestId('domainList-autocomplete'), {
target: { value: 'dom' },
});
// Adding a filter re-asks the server what the selection supports, which hands the field
// a new source search while the typed text is still waiting on the debounce.
rerender(renderField(getSourceSearch()));
await act(async () => {
jest.advanceTimersByTime(500);
});

expect(searchQuery).toHaveBeenCalledWith(
expect.objectContaining({ query: 'dom' })
);
});

it('renders fixed runtime options with the fqn autocomplete contract', () => {
const onChange = jest.fn();
const selectedRule: ArgumentsInput = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,15 +316,30 @@
[hasNoResults, items, t]
);

// Read through a ref so a new source search (the server re-answers capabilities whenever the
// filters change) does not recreate, and so cancel, a search the user is still typing.
const searchParamsRef = useRef({
argument,
containerEntities: stableContainerEntities,
selectedSource,
sourceSearch,
});

useEffect(() => {
searchParamsRef.current = {
argument,
containerEntities: stableContainerEntities,
selectedSource,
sourceSearch,
};
}, [argument, selectedSource, sourceSearch, stableContainerEntities]);

const debouncedSearch = useMemo(
() =>
debounce(async (searchText: string) => {
const nextItems = await searchAlertAiArgumentOptions({
argument,
containerEntities: stableContainerEntities,
...searchParamsRef.current,
searchText,
selectedSource,
sourceSearch,
});

setHasNoResults(searchText.trim() !== '' && nextItems.length === 0);
Expand All @@ -336,7 +351,7 @@
)
);
}, 500),
[argument, selectedSource, sourceSearch, stableContainerEntities]
[]
);

useEffect(
Expand Down Expand Up @@ -519,7 +534,7 @@
value,
}: RuleSectionProps) => {
const { t } = useTranslation();
const selectedRules = value.input?.[field] ?? [];

Check warning on line 537 in openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiRuleSection.component.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

The 'selectedRules' logical expression could make the dependencies of useMemo Hook (at line 542) change on every render. To fix this, wrap the initialization of 'selectedRules' in its own useMemo() Hook
const ruleCopy = getRuleCopy(field, t);

const ruleItems = useMemo(
Expand Down
Loading