import {initializeOrg} from 'sentry-test/initializeOrg'; import {render, screen} from 'sentry-test/reactTestingLibrary'; import {textWithMarkupMatcher} from 'sentry-test/utils'; import ProjectLatestAlerts from './projectLatestAlerts'; describe('ProjectDetail > ProjectLatestAlerts', function () { let endpointMock: jest.Mock; let rulesEndpointMock: jest.Mock; const {organization, project, router, routerContext} = initializeOrg(); beforeEach(function () { endpointMock = MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/incidents/`, body: [ TestStubs.Incident({id: 1, status: 20}), // critical TestStubs.Incident({id: 2, status: 10}), // warning TestStubs.Incident({id: 3, status: 2}), // closed ], }); rulesEndpointMock = MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/alert-rules/`, body: [TestStubs.MetricRule()], }); }); afterEach(function () { MockApiClient.clearMockResponses(); }); it('renders a list', async function () { render( , {context: routerContext} ); expect(endpointMock).toHaveBeenCalledTimes(2); // one for closed, one for open expect(rulesEndpointMock).toHaveBeenCalledTimes(0); expect(endpointMock).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ query: {per_page: 3, status: expect.anything()}, }) ); expect(screen.getByText('Latest Alerts')).toBeInTheDocument(); expect(await screen.findAllByText('Too many Chrome errors')).toHaveLength(3); expect( screen.getAllByRole('link', {name: 'Too many Chrome errors'})[0] ).toHaveAttribute( 'href', '/organizations/org-slug/alerts/123/' ); expect( screen.getAllByText(textWithMarkupMatcher('Triggered 2 years ago')) ).toHaveLength(2); expect( screen.getByText(textWithMarkupMatcher('Resolved a year ago')) ).toBeInTheDocument(); expect(screen.getByLabelText('Critical')).toBeInTheDocument(); expect(screen.getByLabelText('Warning')).toBeInTheDocument(); expect(screen.getByLabelText('Resolved')).toBeInTheDocument(); }); it('shows the empty state', async function () { MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/incidents/`, body: [], }); render( ); expect(await screen.findByText('No alerts found')).toBeInTheDocument(); expect(rulesEndpointMock).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ query: {per_page: 1, asc: 1}, }) ); }); it('shows configure alerts buttons', async function () { MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/incidents/`, body: [], }); MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/alert-rules/`, body: [], }); render( , {context: routerContext} ); expect(await screen.findByRole('button', {name: 'Create Alert'})).toHaveAttribute( 'href', `/organizations/${organization.slug}/alerts/wizard/?referrer=project_detail&project=project-slug` ); expect(screen.getByRole('button', {name: 'Learn More'})).toHaveAttribute( 'href', 'https://docs.sentry.io/product/alerts-notifications/metric-alerts/' ); }); it('calls API with the right params', function () { render( ); expect(endpointMock).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ query: {per_page: 3, statsPeriod: '7d', environment: 'staging', status: 'open'}, }) ); }); it('handles null dateClosed with resolved alerts', async function () { MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/incidents/`, body: [ TestStubs.Incident({id: 1, status: 20}), // critical TestStubs.Incident({id: 2, status: 10}), // warning TestStubs.Incident({id: 3, status: 2, dateClosed: null}), // closed with null dateClosed ], }); render( ); expect(await screen.findByText('Resolved')).toBeInTheDocument(); }); it('does not call API if project is not stabilized yet', function () { render( ); expect(endpointMock).toHaveBeenCalledTimes(0); }); it('renders error state', async function () { MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/incidents/`, body: [], statusCode: 500, }); render( ); expect(await screen.findByText('Unable to load latest alerts')).toBeInTheDocument(); }); });