From d811aa9e7bcba176a557792c6bf438f1549c953a Mon Sep 17 00:00:00 2001 From: Mihir Mavalankar Date: Tue, 25 Nov 2025 10:30:42 -0800 Subject: [PATCH] feat(triage signals): Auto Trigger default settings change [feature flagged] --- .../views/settings/projectSeer/index.spec.tsx | 71 +++++++++++++------ .../app/views/settings/projectSeer/index.tsx | 6 +- 2 files changed, 54 insertions(+), 23 deletions(-) diff --git a/static/app/views/settings/projectSeer/index.spec.tsx b/static/app/views/settings/projectSeer/index.spec.tsx index cd2efb3a047b73..516e8e33003f52 100644 --- a/static/app/views/settings/projectSeer/index.spec.tsx +++ b/static/app/views/settings/projectSeer/index.spec.tsx @@ -547,6 +547,7 @@ describe('ProjectSeer', () => { it('hides Scan Issues toggle when triage-signals-v0 feature flag is enabled', async () => { const projectWithFeatureFlag = ProjectFixture({ features: ['triage-signals-v0'], + autofixAutomationTuning: 'medium', // Already enabled, so no auto-enable PUT }); render(, { @@ -583,7 +584,7 @@ describe('ProjectSeer', () => { const projectWithFlag = ProjectFixture({ features: ['triage-signals-v0'], seerScannerAutomation: true, - autofixAutomationTuning: 'off', + autofixAutomationTuning: 'medium', // Already enabled, so no auto-enable PUT }); const {unmount} = render(, { @@ -620,30 +621,16 @@ describe('ProjectSeer', () => { ).not.toBeInTheDocument(); }); - it('maps values correctly: off=unchecked, others=checked', async () => { - const {unmount} = render(, { - organization, - outletContext: { - project: ProjectFixture({ - features: ['triage-signals-v0'], - seerScannerAutomation: true, - autofixAutomationTuning: 'off', - }), - }, - }); - - expect( - await screen.findByRole('checkbox', {name: /Auto-Trigger Fixes/i}) - ).not.toBeChecked(); - unmount(); - + it('toggle is always checked when triage-signals-v0 flag is enabled', async () => { + // When flag is on, the toggle is always checked regardless of stored value + // because we default to ON for triage signals users render(, { organization, outletContext: { project: ProjectFixture({ features: ['triage-signals-v0'], seerScannerAutomation: true, - autofixAutomationTuning: 'high', + autofixAutomationTuning: 'medium', }), }, }); @@ -666,30 +653,70 @@ describe('ProjectSeer', () => { project: ProjectFixture({ features: ['triage-signals-v0'], seerScannerAutomation: true, - autofixAutomationTuning: 'off', + autofixAutomationTuning: 'medium', // Start with enabled so no auto-enable }), }, }); const toggle = await screen.findByRole('checkbox', {name: /Auto-Trigger Fixes/i}); + expect(toggle).toBeChecked(); + + // Toggle OFF await userEvent.click(toggle); await waitFor(() => { expect(projectPutRequest).toHaveBeenCalledWith( expect.any(String), - expect.objectContaining({data: {autofixAutomationTuning: 'medium'}}) + expect.objectContaining({data: {autofixAutomationTuning: 'off'}}) ); }); + // Toggle back ON await userEvent.click(toggle); await waitFor(() => { expect(projectPutRequest).toHaveBeenCalledWith( expect.any(String), - expect.objectContaining({data: {autofixAutomationTuning: 'off'}}) + expect.objectContaining({data: {autofixAutomationTuning: 'medium'}}) ); }); }); + + it('respects existing off setting for orgs with flag enabled', async () => { + render(, { + organization, + outletContext: { + project: ProjectFixture({ + features: ['triage-signals-v0'], + seerScannerAutomation: true, + autofixAutomationTuning: 'off', // Existing org with it disabled + }), + }, + }); + + // Toggle should be unchecked, respecting the existing 'off' setting + expect( + await screen.findByRole('checkbox', {name: /Auto-Trigger Fixes/i}) + ).not.toBeChecked(); + }); + + it('defaults to ON for new orgs (undefined value)', async () => { + render(, { + organization, + outletContext: { + project: ProjectFixture({ + features: ['triage-signals-v0'], + seerScannerAutomation: true, + autofixAutomationTuning: undefined, // New org + }), + }, + }); + + // Toggle should be checked for new orgs + expect( + await screen.findByRole('checkbox', {name: /Auto-Trigger Fixes/i}) + ).toBeChecked(); + }); }); describe('Auto Create PR Setting', () => { diff --git a/static/app/views/settings/projectSeer/index.tsx b/static/app/views/settings/projectSeer/index.tsx index 40221ea3488fbb..275097270db65d 100644 --- a/static/app/views/settings/projectSeer/index.tsx +++ b/static/app/views/settings/projectSeer/index.tsx @@ -327,8 +327,11 @@ function ProjectSeerGeneralForm({project}: {project: Project}) { }, ]; + // When triage signals flag is on, toggle defaults to checked unless explicitly 'off' + // - New orgs (undefined): shows checked, persists on form interaction + // - Existing orgs with 'off': shows unchecked, preserves their choice const automationTuning = isTriageSignalsFeatureOn - ? (project.autofixAutomationTuning ?? 'off') !== 'off' + ? project.autofixAutomationTuning !== 'off' : (project.autofixAutomationTuning ?? 'off'); return ( @@ -346,6 +349,7 @@ function ProjectSeerGeneralForm({project}: {project: Project}) { initialData={{ seerScannerAutomation: project.seerScannerAutomation ?? false, // Same DB field, different UI: toggle (boolean) vs dropdown (string) + // When triage signals flag is on, default to true (ON) autofixAutomationTuning: automationTuning, automated_run_stopping_point: preference?.automation_handoff ? 'cursor_handoff'