import {OrganizationFixture} from 'sentry-fixture/organization'; import {SecretFixture} from 'sentry-fixture/secret'; import {initializeOrg} from 'sentry-test/initializeOrg'; import { render, renderGlobalModal, screen, userEvent, waitForElementToBeRemoved, } from 'sentry-test/reactTestingLibrary'; import * as indicators from 'sentry/actionCreators/indicator'; import OrganizationsStore from 'sentry/stores/organizationsStore'; import { OrganizationFeatureFlagsIndex, type Secret, } from 'sentry/views/settings/featureFlags'; describe('OrganizationFeatureFlagsIndex', function () { const ENDPOINT = '/organizations/org-slug/flags/signing-secrets/'; const {organization} = initializeOrg(); beforeEach(function () { MockApiClient.addMockResponse({ url: '/organizations/org-slug/users/1234/', body: {}, }); OrganizationsStore.addOrReplace(organization); }); afterEach(function () { MockApiClient.clearMockResponses(); }); it('shows secrets', async function () { const secrets: Secret[] = [ SecretFixture(), SecretFixture({id: 2, provider: 'openfeature', secret: '456def****'}), ]; const mock = MockApiClient.addMockResponse({ url: ENDPOINT, method: 'GET', body: {data: secrets}, }); render(); await waitForElementToBeRemoved(() => screen.queryByTestId('loading-indicator')); expect(screen.getByText('launchdarkly')).toBeInTheDocument(); expect(screen.getByText('openfeature')).toBeInTheDocument(); expect(screen.queryByTestId('loading-error')).not.toBeInTheDocument(); expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument(); expect(screen.queryByTestId('empty-state')).not.toBeInTheDocument(); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith(ENDPOINT, expect.objectContaining({method: 'GET'})); }); it('handle error when loading secrets', async function () { const mock = MockApiClient.addMockResponse({ url: ENDPOINT, method: 'GET', statusCode: 400, }); render(); expect(await screen.findByTestId('loading-error')).toHaveTextContent( 'Failed to load secrets and providers for the organization.' ); expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument(); expect(screen.queryByTestId('empty-state')).not.toBeInTheDocument(); expect(mock).toHaveBeenCalledTimes(1); }); it('shows empty state', async function () { const secrets: Secret[] = []; MockApiClient.addMockResponse({ url: ENDPOINT, method: 'GET', body: {data: secrets}, }); render(); await waitForElementToBeRemoved(() => screen.queryByTestId('loading-indicator')); expect(screen.getByTestId('empty-state')).toBeInTheDocument(); expect(screen.queryByTestId('loading-error')).not.toBeInTheDocument(); expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument(); }); describe('removing', function () { it('allows to remove secrets', async function () { jest.spyOn(indicators, 'addSuccessMessage'); const secrets: Secret[] = [ SecretFixture(), SecretFixture({id: 2, provider: 'openfeature', secret: '456def****'}), ]; MockApiClient.addMockResponse({ url: ENDPOINT, method: 'GET', body: {data: secrets}, }); const deleteMock = MockApiClient.addMockResponse({ url: `${ENDPOINT}1/`, method: 'DELETE', }); render(); renderGlobalModal(); expect(await screen.findByText('openfeature')).toBeInTheDocument(); expect(screen.getByText('launchdarkly')).toBeInTheDocument(); expect( screen.getByLabelText('Remove secret for launchdarkly provider') ).toBeEnabled(); await userEvent.click( screen.getByLabelText('Remove secret for launchdarkly provider') ); // Confirm modal await userEvent.click(screen.getByRole('button', {name: 'Confirm'})); expect(screen.getByText('openfeature')).toBeInTheDocument(); expect(screen.queryByText('launchdarkly')).not.toBeInTheDocument(); expect(indicators.addSuccessMessage).toHaveBeenCalledWith( 'Removed the provider and signing secret for the organization.' ); expect(deleteMock).toHaveBeenCalledTimes(1); }); it('does not allow to remove without permission', async function () { const org = OrganizationFixture({ access: ['org:integrations'], }); const secrets: Secret[] = [ SecretFixture(), SecretFixture({ id: 2, provider: 'openfeature', secret: '456def**************************', }), ]; MockApiClient.addMockResponse({ url: ENDPOINT, method: 'GET', body: {data: secrets}, }); render(, {organization: org}); expect(await screen.findByText('launchdarkly')).toBeInTheDocument(); expect( screen.getByLabelText('Remove secret for launchdarkly provider') ).toBeDisabled(); }); }); });