Skip to content

Conversation

@malwilley
Copy link
Member

@malwilley malwilley commented Dec 2, 2025

Adds a radio button to the "connect monitors" section. The default flow will be for users to select one or multiple projects that will alert on any issue. We need to fetch all the issue stream monitors in order to match them up with the projects from the dropdown.

The other option is to connect specific monitors, which works the same as it does today.

CleanShot 2025-12-01 at 16 49 10@2x CleanShot 2025-12-01 at 16 49 21@2x

@malwilley malwilley requested a review from a team as a code owner December 2, 2025 00:48
@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Dec 2, 2025
@codecov
Copy link

codecov bot commented Dec 2, 2025

❌ 3 Tests Failed:

Tests completed Failed Passed Skipped
12735 3 12732 10
View the top 3 failed test(s) by shortest run time
EditConnectedMonitors can connect an existing monitor via specific monitors mode
Stack Traces | 0.033s run time
TestingLibraryElementError: Unable to find an element with the text: Connected Monitors. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, script, style
...
    at Object.getElementError (.../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/config.js:37:19)
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:76:38
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:52:17
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:95:19
    at Object.getByText (.../automations/components/editConnectedMonitors.spec.tsx:83:19)
    at Promise.finally.completed (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1559:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1499:10)
    at _callCircusTest (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1009:40)
    at runNextTicks (node:internal/process/task_queues:65:5)
    at processTimers (node:internal/timers:520:9)
    at _runTest (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:949:3)
    at _runTestsForDescribeBlock (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:839:13)
    at _runTestsForDescribeBlock (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:829:11)
    at run (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:757:3)
    at runAndTransformResultsToJestFormat (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1920:21)
    at jestAdapter (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/runner.js:101:19)
    at runTestInternal (.../sentry/node_modules/.pnpm/jest-runner@30.0..../jest-runner/build/testWorker.js:272:16)
    at runTest (.../sentry/node_modules/.pnpm/jest-runner@30.0..../jest-runner/build/testWorker.js:340:7)
    at Object.worker (.../sentry/node_modules/.pnpm/jest-runner@30.0..../jest-runner/build/testWorker.js:494:12)
EditConnectedMonitors renders radio buttons for monitor selection mode
Stack Traces | 0.068s run time
TestingLibraryElementError: Unable to find an element with the text: Connected Monitors. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, script, style
...
    at Object.getElementError (.../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/config.js:37:19)
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:76:38
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:52:17
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:95:19
    at Object.getByText (.../automations/components/editConnectedMonitors.spec.tsx:54:19)
    at Promise.finally.completed (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1559:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1499:10)
    at _callCircusTest (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1009:40)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
    at _runTest (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:949:3)
    at _runTestsForDescribeBlock (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:839:13)
    at _runTestsForDescribeBlock (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:829:11)
    at run (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:757:3)
    at runAndTransformResultsToJestFormat (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/jestAdapterInit.js:1920:21)
    at jestAdapter (.../sentry/node_modules/.pnpm/jest-circus@30.0.4_babel-plugin-macros@3.1..../jest-circus/build/runner.js:101:19)
    at runTestInternal (.../sentry/node_modules/.pnpm/jest-runner@30.0..../jest-runner/build/testWorker.js:272:16)
    at runTest (.../sentry/node_modules/.pnpm/jest-runner@30.0..../jest-runner/build/testWorker.js:340:7)
    at Object.worker (.../sentry/node_modules/.pnpm/jest-runner@30.0..../jest-runner/build/testWorker.js:494:12)
EditConnectedMonitors can disconnect an existing monitor
Stack Traces | 0.141s run time
TestingLibraryElementError: Unable to find an element with the text: Connected Monitors. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, script, style
...
    at Object.getElementError (.../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/config.js:37:19)
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:76:38
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:52:17
    at .../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/query-helpers.js:95:19
    at Object.getByText (.../automations/components/editConnectedMonitors.spec.tsx:139:19)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

label={t('Connected monitors mode')}
value={monitorMode}
choices={[
['project', t('Alert on all issues in a project')],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be something like "Alert on all issues in selected project(s)" since it's multiselect?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept this wording because it is more simple/direct and the input is obviously multi-select, but I can see it going either way

const {data: issueStreamDetectors} = useIssueStreamDetectors();
const initialMode = getInitialMonitorMode(issueStreamDetectors, connectedIds);

if (!initialMode) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be checking if the issue stream detector query is loading here instead of checking initialMode, then if the query fails we use the specific mode?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah true, that's better - updated!

Comment on lines +204 to +213
// Sync the derived selectedProjectIds to the form model so the field can read from it
useEffect(() => {
const selectedProjectIds =
issueStreamDetectorsQuery.data
?.filter(detector => connectedIds.includes(detector.id))
.map(d => d.projectId) ?? [];
if (form && selectedProjectIds.length > 0) {
form.setValue('projectIds', selectedProjectIds);
}
}, [connectedIds, form, issueStreamDetectorsQuery.data]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: useEffect fails to clear projectIds in form model when selectedProjectIds is empty, causing stale data submission.
Severity: HIGH | Confidence: High

🔍 Detailed Analysis

When a user clears all project selections in SentryProjectSelectorField, the useEffect hook's condition selectedProjectIds.length > 0 prevents form.setValue('projectIds', selectedProjectIds) from being called. This leaves the form model's projectIds field with stale, previously selected values, even though connectedIds is correctly updated to []. Consequently, submitting the form sends incorrect, outdated projectIds, leading to incorrect automation connections.

💡 Suggested Fix

Remove the selectedProjectIds.length > 0 condition from the useEffect hook, ensuring form.setValue('projectIds', selectedProjectIds) is always called when form exists, even if selectedProjectIds is an empty array.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: static/app/views/automations/components/editConnectedMonitors.tsx#L204-L213

Potential issue: When a user clears all project selections in
`SentryProjectSelectorField`, the `useEffect` hook's condition
`selectedProjectIds.length > 0` prevents `form.setValue('projectIds',
selectedProjectIds)` from being called. This leaves the form model's `projectIds` field
with stale, previously selected values, even though `connectedIds` is correctly updated
to `[]`. Consequently, submitting the form sends incorrect, outdated `projectIds`,
leading to incorrect automation connections.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 5003126

return connectedIds.every(id => issueStreamDetectors.find(d => d.id === id))
? 'project'
: 'specific';
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Query error defaults to wrong mode with connected monitors

The getInitialMonitorMode function incorrectly returns 'project' when issueStreamDetectors is undefined due to a failed query, even when connectedIds exist. Per the PR discussion, when the query fails, it should fall back to 'specific' mode to preserve existing behavior and show the user's connected monitors. Currently, a user editing an automation with specific monitors connected would see the project selector instead of their monitors if the issue stream detectors API call fails, potentially leading to data loss on save.

Additional Locations (1)

Fix in Cursor Fix in Web

@malwilley malwilley merged commit b13a8e0 into master Dec 2, 2025
48 checks passed
@malwilley malwilley deleted the malwilley/feat/add-simpler-ux-for-connecting-alerts-to-a-project branch December 2, 2025 22:54
@github-actions github-actions bot locked and limited conversation to collaborators Dec 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants