import {OrganizationFixture} from 'sentry-fixture/organization'; import {initializeOrg} from 'sentry-test/initializeOrg'; import {act, render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary'; import * as indicatorActions from 'sentry/actionCreators/indicator'; import Indicators from 'sentry/components/indicators'; import * as RegionUtils from 'sentry/utils/regions'; import OrganizationSettingsForm from 'sentry/views/settings/organizationGeneralSettings/organizationSettingsForm'; jest.mock('sentry/actionCreators/indicator'); jest.mock('sentry/utils/regions'); describe('OrganizationSettingsForm', function () { const {organization, routerProps} = initializeOrg(); let putMock: jest.Mock; const onSave = jest.fn(); beforeEach(function () { MockApiClient.clearMockResponses(); MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/auth-provider/`, method: 'GET', }); MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/integrations/?provider_key=github`, method: 'GET', body: { providers: [{canAdd: true}], }, }); onSave.mockReset(); }); it('can change a form field', async function () { putMock = MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/`, method: 'PUT', body: organization, }); render( ); render(); const input = screen.getByRole('textbox', {name: 'Display Name'}); const saveOnBlur = jest.spyOn(indicatorActions, 'saveOnBlurUndoMessage'); await userEvent.clear(input); await userEvent.type(input, 'New Name'); await userEvent.tab(); expect(putMock).toHaveBeenCalledWith( `/organizations/${organization.slug}/`, expect.objectContaining({ method: 'PUT', data: { name: 'New Name', }, }) ); expect(saveOnBlur).toHaveBeenCalledWith( { new: 'New Name', old: 'Organization Name', }, expect.anything(), 'name' ); const model = saveOnBlur.mock.calls[0][1]; // Test "undo" call undo directly expect(model.getValue('name')).toBe('New Name'); act(() => { model.undo(); }); expect(model.getValue('name')).toBe('Organization Name'); // `saveOnBlurUndoMessage` saves the new field, so reimplement this act(() => { model.saveField('name', 'Organization Name'); }); // Initial data should be updated to original name await waitFor(() => expect(model.initialData.name).toBe('Organization Name')); putMock.mockReset(); // Blurring the name field again should NOT trigger a save await userEvent.click(input); await userEvent.tab(); expect(putMock).not.toHaveBeenCalled(); }); it('can change slug', async function () { putMock = MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/`, method: 'PUT', body: organization, }); render( ); const input = screen.getByRole('textbox', {name: 'Organization Slug'}); await userEvent.clear(input); await userEvent.type(input, 'NEW SLUG'); await userEvent.tab(); expect(putMock).not.toHaveBeenCalled(); await userEvent.click(screen.getByRole('button', {name: 'Save'})); expect(putMock).toHaveBeenCalledWith( '/organizations/org-slug/', expect.objectContaining({ data: { slug: 'new-slug', }, }) ); }); it('can enable codecov', async function () { putMock = MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/`, method: 'PUT', body: {...organization, codecovAccess: true}, }); render( , { organization: { ...organization, features: ['codecov-integration'], }, } ); await userEvent.click( screen.getByRole('checkbox', {name: /Enable Code Coverage Insights/}) ); expect(putMock).toHaveBeenCalledWith( '/organizations/org-slug/', expect.objectContaining({ data: { codecovAccess: true, }, }) ); }); it('can toggle hideAiFeatures setting', async function () { putMock = MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/`, method: 'PUT', body: {...organization, hideAiFeatures: true}, }); render( , { organization: { ...organization, features: ['autofix'], }, } ); await userEvent.click(screen.getByRole('checkbox', {name: 'Hide AI Features'})); expect(putMock).toHaveBeenCalledWith( '/organizations/org-slug/', expect.objectContaining({ data: { hideAiFeatures: true, }, }) ); }); it('disables hideAiFeatures toggle and shows tooltip for DE region', function () { // Mock the region util to return DE region jest.mocked(RegionUtils.getRegionDataFromOrganization).mockImplementation(() => ({ name: 'de', displayName: 'Europe (Frankfurt)', url: 'https://sentry.de.example.com', })); render( , { organization: { ...organization, features: ['autofix'], }, } ); const toggle = screen.getByRole('checkbox', {name: 'Hide AI Features'}); expect(toggle).toBeDisabled(); }); });