diff --git a/static/app/views/settings/organizationGeneralSettings/aiFeatureSettings.tsx b/static/app/views/settings/organizationGeneralSettings/aiFeatureSettings.tsx index 0f7a8e4dc6ea2f..b243b4264d1a07 100644 --- a/static/app/views/settings/organizationGeneralSettings/aiFeatureSettings.tsx +++ b/static/app/views/settings/organizationGeneralSettings/aiFeatureSettings.tsx @@ -10,25 +10,29 @@ export const defaultEnableSeerFeaturesValue = (organization: Organization) => { export const makeHideAiFeaturesField = (organization: Organization): FieldObject => { const isBaa = false; // TODO: add a check here once we have a way to check if the org is a BAA customer. Leave it as false for now. + const hasFeatureFlag = organization.features.includes('gen-ai-features'); return { name: 'hideAiFeatures', type: 'boolean', label: t('Show Generative AI Features'), - help: tct( - 'Allows organization members to access [docs:features] powered by generative AI', - { - docs: ( - - ), - } - ), + help: tct('Allows organization members to access [link:generative AI features]', { + link: ( + + ), + }), defaultValue: defaultEnableSeerFeaturesValue(organization), - disabled: ({access}) => !access.has('org:write'), + disabled: ({access}) => !hasFeatureFlag || !access.has('org:write'), getValue: value => { // Reversing value because the field was previously called hideAiFeatures and we've inverted the behavior. return !value; }, + setValue: value => { + if (!hasFeatureFlag) { + return false; + } + return value; + }, disabledReason: isBaa ? t( 'To remain HIPAA compliant, Generative AI features are disabled for BAA customers' diff --git a/static/app/views/settings/organizationGeneralSettings/organizationSettingsForm.spec.tsx b/static/app/views/settings/organizationGeneralSettings/organizationSettingsForm.spec.tsx index 1bc8a85c6b84fd..f6f2c0d57d0817 100644 --- a/static/app/views/settings/organizationGeneralSettings/organizationSettingsForm.spec.tsx +++ b/static/app/views/settings/organizationGeneralSettings/organizationSettingsForm.spec.tsx @@ -178,7 +178,10 @@ describe('OrganizationSettingsForm', () => { it('can toggle "Show Generative AI Features"', async () => { // Default org fixture has hideAiFeatures: false, so Seer is enabled by default - const hiddenAiOrg = OrganizationFixture({hideAiFeatures: true}); + const hiddenAiOrg = OrganizationFixture({ + hideAiFeatures: true, + features: ['gen-ai-features'], + }); render( { { organization: { ...organization, - features: ['autofix'], + features: ['autofix', 'gen-ai-features'], }, } ); @@ -250,13 +253,42 @@ describe('OrganizationSettingsForm', () => { expect(toggle).toBeEnabled(); }); + it('disables "Show Generative AI Features" toggle when feature flag is off', () => { + render( + , + { + organization: { + ...organization, + features: [], // No gen-ai-features flag + }, + } + ); + + const checkbox = screen.getByRole('checkbox', { + name: 'Show Generative AI Features', + }); + + expect(checkbox).toBeDisabled(); + expect(checkbox).not.toBeChecked(); + }); + it('renders AI Code Review field', () => { render( + />, + { + organization: { + ...organization, + features: ['gen-ai-features'], + }, + } ); expect(screen.getByText('Enable AI Code Review')).toBeInTheDocument(); @@ -282,7 +314,13 @@ describe('OrganizationSettingsForm', () => { // This logic is inverted from the variable name initialData={OrganizationFixture({hideAiFeatures: false})} onSave={onSave} - /> + />, + { + organization: { + ...organization, + features: ['gen-ai-features'], + }, + } ); expect(screen.queryByText('Enable AI Code Review')).not.toBeInTheDocument(); @@ -299,7 +337,13 @@ describe('OrganizationSettingsForm', () => { {...routerProps} initialData={OrganizationFixture({hideAiFeatures: true})} onSave={onSave} - /> + />, + { + organization: { + ...organization, + features: ['gen-ai-features'], + }, + } ); expect(screen.getByText('Enable AI Code Review')).toBeInTheDocument(); @@ -314,7 +358,13 @@ describe('OrganizationSettingsForm', () => { {...routerProps} initialData={OrganizationFixture({hideAiFeatures: false})} onSave={onSave} - /> + />, + { + organization: { + ...organization, + features: ['gen-ai-features'], + }, + } ); MockApiClient.addMockResponse({ @@ -350,7 +400,13 @@ describe('OrganizationSettingsForm', () => { {...routerProps} initialData={OrganizationFixture({hideAiFeatures: true})} onSave={onSave} - /> + />, + { + organization: { + ...organization, + features: ['gen-ai-features'], + }, + } ); const preventAiField = screen.getByRole('checkbox', { @@ -361,6 +417,36 @@ describe('OrganizationSettingsForm', () => { expect(screen.queryByTestId('prevent-ai-disabled-tag')).not.toBeInTheDocument(); }); + it('is disabled when feature flag is off', () => { + jest.mocked(RegionUtils.getRegionDataFromOrganization).mockReturnValue({ + name: 'us', + displayName: 'United States of America (US)', + url: 'https://sentry.example.com', + }); + + render( + , + { + organization: { + ...organization, + features: ['gen-ai-features'], + }, + } + ); + + const preventAiField = screen.getByRole('checkbox', { + name: /Enable AI Code Review/i, + }); + expect(preventAiField).toBeInTheDocument(); + expect(preventAiField).toBeEnabled(); + + expect(screen.queryByTestId('prevent-ai-disabled-tag')).not.toBeInTheDocument(); + }); + it('is disabled when non US region', async () => { jest.mocked(RegionUtils.getRegionDataFromOrganization).mockReturnValue({ name: 'de', @@ -373,7 +459,13 @@ describe('OrganizationSettingsForm', () => { {...routerProps} initialData={OrganizationFixture({hideAiFeatures: true})} onSave={onSave} - /> + />, + { + organization: { + ...organization, + features: ['gen-ai-features'], + }, + } ); const preventAiField = screen.getByRole('checkbox', { @@ -410,6 +502,7 @@ describe('OrganizationSettingsForm', () => { organization: { ...organization, access: ['org:write'], + features: ['gen-ai-features'], }, } ); @@ -439,7 +532,9 @@ describe('OrganizationSettingsForm', () => { />, { organization: { + ...organization, access: ['org:read'], + features: ['gen-ai-features'], }, } ); @@ -465,7 +560,9 @@ describe('OrganizationSettingsForm', () => { />, { organization: { + ...organization, access: ['org:write'], + features: ['gen-ai-features'], }, } );