diff --git a/static/app/views/detectors/components/forms/cron/cronIssuePreview.tsx b/static/app/views/detectors/components/forms/cron/cronIssuePreview.tsx new file mode 100644 index 000000000000..6269b074e045 --- /dev/null +++ b/static/app/views/detectors/components/forms/cron/cronIssuePreview.tsx @@ -0,0 +1,37 @@ +import {t} from 'sentry/locale'; +import {DetectorIssuePreview} from 'sentry/views/detectors/components/forms/common/detectorIssuePreview'; +import {IssuePreviewSection} from 'sentry/views/detectors/components/forms/common/issuePreviewSection'; +import {ownerToActor} from 'sentry/views/detectors/components/forms/common/ownerToActor'; +import {useDetectorFormContext} from 'sentry/views/detectors/components/forms/context'; +import {useCronDetectorFormField} from 'sentry/views/detectors/components/forms/cron/fields'; + +const FALLBACK_ISSUE_TITLE = t('Cron failure: …'); +const SUBTITLE = t('Your monitor is failing: A missed check-in was detected'); + +function useCronIssueTitle() { + const name = useCronDetectorFormField('name'); + + if (!name) { + return FALLBACK_ISSUE_TITLE; + } + + return t('Cron failure: %s', name); +} + +export function CronIssuePreview({step}: {step?: number}) { + const owner = useCronDetectorFormField('owner'); + const issueTitle = useCronIssueTitle(); + const assignee = ownerToActor(owner); + const {project} = useDetectorFormContext(); + + return ( + + + + ); +} diff --git a/static/app/views/detectors/components/forms/cron/index.spec.tsx b/static/app/views/detectors/components/forms/cron/index.spec.tsx index 3e6f53dd7767..15a8d409979b 100644 --- a/static/app/views/detectors/components/forms/cron/index.spec.tsx +++ b/static/app/views/detectors/components/forms/cron/index.spec.tsx @@ -1,7 +1,7 @@ import {OrganizationFixture} from 'sentry-fixture/organization'; import {ProjectFixture} from 'sentry-fixture/project'; -import {render, screen} from 'sentry-test/reactTestingLibrary'; +import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; import {OrganizationStore} from 'sentry/stores/organizationStore'; import {ProjectsStore} from 'sentry/stores/projectsStore'; @@ -58,7 +58,7 @@ describe('NewCronDetectorForm', () => { // Form sections should be visible expect(await screen.findByText(/Detect/)).toBeInTheDocument(); - expect(screen.getByText(/Assign/)).toBeInTheDocument(); + expect(screen.getByText(/\d\. Assign/)).toBeInTheDocument(); expect(screen.getByText(/Description/)).toBeInTheDocument(); // Create Monitor button should be present and enabled @@ -80,8 +80,6 @@ describe('NewCronDetectorForm', () => { // Form sections should be hidden expect(screen.queryByText(/Detect/)).not.toBeInTheDocument(); - expect(screen.queryByText(/Assign/)).not.toBeInTheDocument(); - expect(screen.queryByText(/Description/)).not.toBeInTheDocument(); // Create Monitor button should be present but disabled const createButton = screen.getByRole('button', {name: 'Create Monitor'}); @@ -89,6 +87,27 @@ describe('NewCronDetectorForm', () => { expect(createButton).toBeDisabled(); }); + it('renders issue preview and updates title when name changes', async () => { + renderForm(); + + // Issue preview section should render with fallback title + expect(await screen.findByTestId('issue-preview-section')).toBeInTheDocument(); + expect(screen.getByText('Cron failure: …')).toBeInTheDocument(); + expect( + screen.getByText('Your monitor is failing: A missed check-in was detected') + ).toBeInTheDocument(); + + // Edit the monitor name + const title = screen.getByText('New Monitor'); + await userEvent.click(title); + const nameInput = screen.getByRole('textbox', {name: 'Monitor Name'}); + await userEvent.clear(nameInput); + await userEvent.type(nameInput, 'My Cron Job{Enter}'); + + // Issue preview updates with the new name + expect(await screen.findByText('Cron failure: My Cron Job')).toBeInTheDocument(); + }); + it('shows form sections and enabled button when guide is set to "manual"', async () => { renderForm({ location: { @@ -99,7 +118,7 @@ describe('NewCronDetectorForm', () => { // Form sections should be visible even with platform set, because guide is "manual" expect(await screen.findByText(/Detect/)).toBeInTheDocument(); - expect(screen.getByText(/Assign/)).toBeInTheDocument(); + expect(screen.getByText(/\d\. Assign/)).toBeInTheDocument(); expect(screen.getByText(/Description/)).toBeInTheDocument(); // Create Monitor button should be present and enabled diff --git a/static/app/views/detectors/components/forms/cron/index.tsx b/static/app/views/detectors/components/forms/cron/index.tsx index 2d53658f1eec..8cdf7c7ffd85 100644 --- a/static/app/views/detectors/components/forms/cron/index.tsx +++ b/static/app/views/detectors/components/forms/cron/index.tsx @@ -22,6 +22,7 @@ import {EditDetectorLayout} from 'sentry/views/detectors/components/forms/editDe import {NewDetectorLayout} from 'sentry/views/detectors/components/forms/newDetectorLayout'; import {useCronsUpsertGuideState} from 'sentry/views/insights/crons/components/useCronsUpsertGuideState'; +import {CronIssuePreview} from './cronIssuePreview'; import {PreviewSection} from './previewSection'; function useIsShowingPlatformGuide() { @@ -35,6 +36,7 @@ const FORM_SECTIONS = [ CronDetectorFormResolveSection, AssignSection, DescribeSection, + CronIssuePreview, AutomateSection, ];