diff --git a/static/app/views/detectors/components/details/common/automations.spec.tsx b/static/app/views/detectors/components/details/common/automations.spec.tsx index 1d15f8b45a0da5..459272cd329c2e 100644 --- a/static/app/views/detectors/components/details/common/automations.spec.tsx +++ b/static/app/views/detectors/components/details/common/automations.spec.tsx @@ -25,7 +25,7 @@ describe('DetectorDetailsAutomations', () => { const issueStreamDetector = IssueStreamDetectorFixture({id: 'issue-stream-1'}); beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); MockApiClient.clearMockResponses(); MockApiClient.addMockResponse({ @@ -98,6 +98,47 @@ describe('DetectorDetailsAutomations', () => { ); }); + it('can search connected alerts', async () => { + const automation2 = AutomationFixture({id: '2', name: 'Alert 2'}); + const detector = UptimeDetectorFixture({ + workflowIds: [automation1.id, automation2.id], + }); + + MockApiClient.addMockResponse({ + url: '/organizations/org-slug/workflows/', + method: 'GET', + body: [automation1, automation2], + match: [ + (_url, options) => + options.query?.detector !== undefined && options.query?.query === undefined, + ], + }); + + const searchRequest = MockApiClient.addMockResponse({ + url: '/organizations/org-slug/workflows/', + method: 'GET', + body: [automation2], + match: [ + (_url, options) => + options.query?.detector !== undefined && + typeof options.query?.query === 'string' && + options.query.query.includes('Alert 2'), + ], + }); + + render(, {organization}); + + expect(await screen.findByText(automation1.name)).toBeInTheDocument(); + + const searchInput = screen.getByRole('combobox', {name: 'Add a search term'}); + await userEvent.click(searchInput); + await userEvent.keyboard('Alert 2{Enter}'); + + await waitFor(() => expect(searchRequest).toHaveBeenCalled()); + expect(await screen.findByRole('link', {name: automation2.name})).toBeInTheDocument(); + expect(screen.queryByRole('link', {name: automation1.name})).not.toBeInTheDocument(); + }); + it('can connect a new automation from drawer', async () => { const detector = UptimeDetectorFixture({ id: 'detector-123', diff --git a/static/app/views/detectors/components/details/common/automations.tsx b/static/app/views/detectors/components/details/common/automations.tsx index a7053bec660bad..85d7c8ffdd2590 100644 --- a/static/app/views/detectors/components/details/common/automations.tsx +++ b/static/app/views/detectors/components/details/common/automations.tsx @@ -19,12 +19,12 @@ import AutomationTitleCell from 'sentry/components/workflowEngine/gridCell/autom import Section from 'sentry/components/workflowEngine/ui/section'; import {IconAdd} from 'sentry/icons'; import {t, tct} from 'sentry/locale'; -import {space} from 'sentry/styles/space'; import type {Detector} from 'sentry/types/workflowEngine/detectors'; import {defined} from 'sentry/utils'; import {parseCursor} from 'sentry/utils/cursor'; import useOrganization from 'sentry/utils/useOrganization'; import useProjectFromId from 'sentry/utils/useProjectFromId'; +import {AutomationSearch} from 'sentry/views/automations/components/automationListTable/search'; import {useAutomationsQuery} from 'sentry/views/automations/hooks'; import {getAutomationActions} from 'sentry/views/automations/hooks/utils'; import {makeAutomationCreatePathname} from 'sentry/views/automations/pathnames'; @@ -81,6 +81,11 @@ function DetectorAutomationsTable({ const issueStreamDetectorId = issueStreamDetectors?.[0]?.id; const detectorIds = [detectorId, issueStreamDetectorId]; const [cursor, setCursor] = useState(undefined); + const [searchQuery, setSearchQuery] = useState(''); + const onSearch = useCallback((query: string) => { + setSearchQuery(query); + setCursor(undefined); + }, []); const { data: automations, @@ -93,6 +98,7 @@ function DetectorAutomationsTable({ detector: detectorIds.filter(defined), limit: AUTOMATIONS_PER_PAGE, cursor, + query: searchQuery || undefined, }, {enabled: !issueStreamDetectorsPending} ); @@ -126,62 +132,67 @@ function DetectorAutomationsTable({ onRetry={refetchIssueStreamDetectors} /> )} - - - {t('Name')} - - {t('Actions')} - - - {t('Triggered By Issues')} - - - {isPending && } - {isError && } - {isSuccess && automations.length === 0 && ( - {emptyMessage} - )} - {isSuccess && - automations.map(automation => ( - - - - - - - - - {automation.detectorIds.includes(detectorId) ? ( - - {t('From Monitor')} - - ) : ( - {project.slug} - ) : ( - 'project' - ), - } - )} - showUnderline - > - {t('In Project')} - - )} - - - ))} - + + + + + {t('Name')} + + {t('Actions')} + + + {t('Triggered By Issues')} + + + {isPending && } + {isError && } + {isSuccess && automations.length === 0 && ( + {emptyMessage} + )} + {isSuccess && + automations.map(automation => ( + + + + + + + + + {automation.detectorIds.includes(detectorId) ? ( + + {t('From Monitor')} + + ) : ( + {project.slug} + ) : ( + 'project' + ), + } + )} + showUnderline + > + {t('In Project')} + + )} + + + ))} + + p.theme.breakpoints.sm}) { grid-template-columns: 1fr 180px;