Skip to content

Commit 007a027

Browse files
srest2021claude
andcommitted
test(seer): Add tests for set_default_project_auto_open_prs
Cover all org-default-to-project mapping cases: Seer agent with default and custom stopping points, auto_open_prs forcing open_pr, external agents (Cursor/Claude) with handoff config, missing integration ID edge case, API error handling, and dual-write feature flag gating. Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com> Made-with: Cursor
1 parent 42b9053 commit 007a027

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

tests/sentry/seer/similarity/test_utils.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
filter_null_from_string,
1616
get_stacktrace_string,
1717
get_token_count,
18+
set_default_project_auto_open_prs,
1819
stacktrace_exceeds_limits,
1920
)
2021
from sentry.services.eventstore.models import Event
@@ -1220,3 +1221,140 @@ def test_generates_stacktrace_string_from_variants(self) -> None:
12201221
assert token_count > 0
12211222
# Verify we get the expected token count for this specific stacktrace
12221223
assert token_count == 33
1224+
1225+
1226+
class TestSetDefaultProjectAutoOpenPrs(TestCase):
1227+
"""Tests for set_default_project_auto_open_prs which wires org-level Seer
1228+
defaults (stopping point, coding agent, auto_open_prs) into project-level
1229+
preferences at project creation time.
1230+
"""
1231+
1232+
def setUp(self):
1233+
super().setUp()
1234+
self.project = self.create_project(organization=self.organization)
1235+
1236+
@patch("sentry.seer.similarity.utils.write_preference_to_sentry_db")
1237+
@patch("sentry.seer.similarity.utils.set_project_seer_preference")
1238+
@patch("sentry.seer.similarity.utils.is_seer_seat_based_tier_enabled", return_value=False)
1239+
def test_skips_when_tier_not_enabled(
1240+
self, mock_tier: MagicMock, mock_set_pref: MagicMock, mock_dual_write: MagicMock
1241+
):
1242+
set_default_project_auto_open_prs(self.organization, self.project)
1243+
mock_set_pref.assert_not_called()
1244+
mock_dual_write.assert_not_called()
1245+
1246+
@patch("sentry.seer.similarity.utils.write_preference_to_sentry_db")
1247+
@patch("sentry.seer.similarity.utils.set_project_seer_preference")
1248+
@patch("sentry.seer.similarity.utils.is_seer_seat_based_tier_enabled", return_value=True)
1249+
def test_seer_agent_default_stopping_point(
1250+
self, mock_tier: MagicMock, mock_set_pref: MagicMock, mock_dual_write: MagicMock
1251+
):
1252+
"""Seer agent, no auto_open_prs, default stopping point (code_changes)."""
1253+
set_default_project_auto_open_prs(self.organization, self.project)
1254+
1255+
pref = mock_set_pref.call_args[0][0]
1256+
assert pref.automated_run_stopping_point == "code_changes"
1257+
assert pref.automation_handoff is None
1258+
1259+
@patch("sentry.seer.similarity.utils.write_preference_to_sentry_db")
1260+
@patch("sentry.seer.similarity.utils.set_project_seer_preference")
1261+
@patch("sentry.seer.similarity.utils.is_seer_seat_based_tier_enabled", return_value=True)
1262+
def test_seer_agent_custom_stopping_point(
1263+
self, mock_tier: MagicMock, mock_set_pref: MagicMock, mock_dual_write: MagicMock
1264+
):
1265+
"""Seer agent, no auto_open_prs, custom stopping point (root_cause)."""
1266+
self.organization.update_option("sentry:default_stopping_point", "root_cause")
1267+
1268+
set_default_project_auto_open_prs(self.organization, self.project)
1269+
1270+
pref = mock_set_pref.call_args[0][0]
1271+
assert pref.automated_run_stopping_point == "root_cause"
1272+
assert pref.automation_handoff is None
1273+
1274+
@patch("sentry.seer.similarity.utils.write_preference_to_sentry_db")
1275+
@patch("sentry.seer.similarity.utils.set_project_seer_preference")
1276+
@patch("sentry.seer.similarity.utils.is_seer_seat_based_tier_enabled", return_value=True)
1277+
def test_seer_agent_with_auto_open_prs(
1278+
self, mock_tier: MagicMock, mock_set_pref: MagicMock, mock_dual_write: MagicMock
1279+
):
1280+
"""auto_open_prs=True forces stopping point to open_pr regardless of default."""
1281+
self.organization.update_option("sentry:auto_open_prs", True)
1282+
self.organization.update_option("sentry:default_stopping_point", "root_cause")
1283+
1284+
set_default_project_auto_open_prs(self.organization, self.project)
1285+
1286+
pref = mock_set_pref.call_args[0][0]
1287+
assert pref.automated_run_stopping_point == "open_pr"
1288+
assert pref.automation_handoff is None
1289+
1290+
@patch("sentry.seer.similarity.utils.write_preference_to_sentry_db")
1291+
@patch("sentry.seer.similarity.utils.set_project_seer_preference")
1292+
@patch("sentry.seer.similarity.utils.is_seer_seat_based_tier_enabled", return_value=True)
1293+
def test_external_agent_no_auto_open_prs(
1294+
self, mock_tier: MagicMock, mock_set_pref: MagicMock, mock_dual_write: MagicMock
1295+
):
1296+
agents = [
1297+
("cursor_background_agent", 1234),
1298+
("claude_code_agent", 5678),
1299+
]
1300+
for agent, integration_id in agents:
1301+
with self.subTest(agent=agent):
1302+
mock_set_pref.reset_mock()
1303+
self.organization.update_option("sentry:seer_default_coding_agent", agent)
1304+
self.organization.update_option(
1305+
"sentry:seer_default_coding_agent_integration_id", integration_id
1306+
)
1307+
1308+
set_default_project_auto_open_prs(self.organization, self.project)
1309+
1310+
pref = mock_set_pref.call_args[0][0]
1311+
assert pref.automated_run_stopping_point == "code_changes"
1312+
assert pref.automation_handoff is not None
1313+
assert pref.automation_handoff.handoff_point == "root_cause"
1314+
assert pref.automation_handoff.target == agent
1315+
assert pref.automation_handoff.integration_id == integration_id
1316+
assert pref.automation_handoff.auto_create_pr is False
1317+
1318+
@patch("sentry.seer.similarity.utils.write_preference_to_sentry_db")
1319+
@patch("sentry.seer.similarity.utils.set_project_seer_preference")
1320+
@patch("sentry.seer.similarity.utils.is_seer_seat_based_tier_enabled", return_value=True)
1321+
def test_external_agent_with_auto_open_prs(
1322+
self, mock_tier: MagicMock, mock_set_pref: MagicMock, mock_dual_write: MagicMock
1323+
):
1324+
"""auto_open_prs=True forces open_pr and sets auto_create_pr on handoff."""
1325+
self.organization.update_option("sentry:auto_open_prs", True)
1326+
agents = [
1327+
("cursor_background_agent", 1234),
1328+
("claude_code_agent", 5678),
1329+
]
1330+
for agent, integration_id in agents:
1331+
with self.subTest(agent=agent):
1332+
mock_set_pref.reset_mock()
1333+
self.organization.update_option("sentry:seer_default_coding_agent", agent)
1334+
self.organization.update_option(
1335+
"sentry:seer_default_coding_agent_integration_id", integration_id
1336+
)
1337+
1338+
set_default_project_auto_open_prs(self.organization, self.project)
1339+
1340+
pref = mock_set_pref.call_args[0][0]
1341+
assert pref.automated_run_stopping_point == "open_pr"
1342+
assert pref.automation_handoff is not None
1343+
assert pref.automation_handoff.target == agent
1344+
assert pref.automation_handoff.integration_id == integration_id
1345+
assert pref.automation_handoff.auto_create_pr is True
1346+
1347+
@patch("sentry.seer.similarity.utils.write_preference_to_sentry_db")
1348+
@patch("sentry.seer.similarity.utils.set_project_seer_preference")
1349+
@patch("sentry.seer.similarity.utils.is_seer_seat_based_tier_enabled", return_value=True)
1350+
def test_external_agent_without_integration_id_skips_handoff(
1351+
self, mock_tier: MagicMock, mock_set_pref: MagicMock, mock_dual_write: MagicMock
1352+
):
1353+
self.organization.update_option(
1354+
"sentry:seer_default_coding_agent", "cursor_background_agent"
1355+
)
1356+
1357+
set_default_project_auto_open_prs(self.organization, self.project)
1358+
1359+
pref = mock_set_pref.call_args[0][0]
1360+
assert pref.automation_handoff is None

0 commit comments

Comments
 (0)