import {browserHistory} from 'react-router'; import {initializeOrg} from 'sentry-test/initializeOrg'; import { render, screen, userEvent, waitForElementToBeRemoved, } from 'sentry-test/reactTestingLibrary'; import {GroupEvents} from 'sentry/views/organizationGroupDetails/groupEvents'; describe('groupEvents', function () { let request; let discoverRequest; let attachmentsRequest; const {organization, routerContext} = initializeOrg(); beforeEach(function () { request = MockApiClient.addMockResponse({ url: '/issues/1/events/', body: [ TestStubs.Event({ eventID: '12345', id: '1', message: 'ApiException', groupID: '1', }), TestStubs.Event({ crashFile: { sha1: 'sha1', name: 'name.dmp', dateCreated: '2019-05-21T18:01:48.762Z', headers: {'Content-Type': 'application/octet-stream'}, id: '12345', size: 123456, type: 'event.minidump', }, culprit: '', dateCreated: '2019-05-21T18:00:23Z', 'event.type': 'error', eventID: '123456', groupID: '1', id: '98654', location: 'main.js', message: 'TestException', platform: 'native', projectID: '123', tags: [{value: 'production', key: 'production'}], title: 'TestException', }), ], }); browserHistory.push = jest.fn(); discoverRequest = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events/', headers: { Link: `; rel="previous"; results="true"; cursor="0:0:1", ; rel="next"; results="true"; cursor="0:200:0"`, }, body: { data: [ { timestamp: '2022-09-11T15:01:10+00:00', transaction: '/api', release: 'backend@1.2.3', 'transaction.duration': 1803, environment: 'prod', 'user.display': 'sentry@sentry.sentry', id: 'id123', trace: 'trace123', 'project.name': 'project123', }, ], meta: { fields: { timestamp: 'date', transaction: 'string', release: 'string', 'transaction.duration': 'duration', environment: 'string', 'user.display': 'string', id: 'string', trace: 'string', 'project.name': 'string', }, units: { timestamp: null, transaction: null, release: null, 'transaction.duration': 'millisecond', environment: null, 'user.display': null, id: null, trace: null, 'project.name': null, }, isMetricsData: false, tips: {query: null, columns: null}, }, }, }); attachmentsRequest = MockApiClient.addMockResponse({ url: '/api/0/issues/1/attachments/?per_page=50&types=event.minidump&event_id=id123', body: [], }); }); afterEach(() => { MockApiClient.clearMockResponses(); jest.clearAllMocks(); }); it('renders', function () { const wrapper = render( , {context: routerContext, organization} ); expect(wrapper.container).toSnapshot(); }); it('handles search', function () { render( , {context: routerContext, organization} ); const list = [ {searchTerm: '', expectedQuery: ''}, {searchTerm: 'test', expectedQuery: 'test'}, {searchTerm: 'environment:production test', expectedQuery: 'test'}, ]; const input = screen.getByPlaceholderText('Search events by id, message, or tags'); for (const item of list) { userEvent.clear(input); userEvent.type(input, `${item.searchTerm}{enter}`); expect(browserHistory.push).toHaveBeenCalledWith( expect.objectContaining({ query: {query: item.expectedQuery}, }) ); } }); it('handles environment filtering', function () { render( , {context: routerContext, organization} ); expect(request).toHaveBeenCalledWith( '/issues/1/events/', expect.objectContaining({ query: {limit: 50, query: '', environment: ['prod', 'staging']}, }) ); }); describe('When the performance flag is enabled', () => { let org; let group; beforeEach(() => { org = initializeOrg({ organization: {features: ['performance-issues-all-events-tab']}, }); group = TestStubs.Group(); }); it('renders new events table for performance', function () { group.issueCategory = 'performance'; render( , {context: routerContext, organization} ); expect(discoverRequest).toHaveBeenCalledWith( '/organizations/org-slug/events/', expect.objectContaining({ query: expect.objectContaining({ query: 'performance.issue_ids:1 event.type:transaction ', }), }) ); const perfEventsColumn = screen.getByText('transaction'); expect(perfEventsColumn).toBeInTheDocument(); expect(request).not.toHaveBeenCalled(); }); it('renders event and trace link correctly', async () => { group.issueCategory = 'performance'; render( , {context: routerContext, organization} ); await waitForElementToBeRemoved(document.querySelector('div.loading-indicator')); const eventIdATag = screen.getByText('id123').closest('a'); const traceIdATag = screen.getByText('trace123').closest('a'); expect(eventIdATag).toHaveAttribute( 'href', '/organizations/org-slug/issues/1/events/id123/' ); expect(traceIdATag).toHaveAttribute( 'href', '/organizations/org-slug/performance/trace/trace123/?' ); }); it('does not display attachments column with no attachments', async () => { render( , {context: routerContext, organization} ); await waitForElementToBeRemoved(document.querySelector('div.loading-indicator')); const attachmentsColumn = screen.queryByText('attachments'); expect(attachmentsColumn).not.toBeInTheDocument(); expect(attachmentsRequest).toHaveBeenCalled(); }); it('does not display minidump column with no minidumps', async () => { render( , {context: routerContext, organization} ); await waitForElementToBeRemoved(document.querySelector('div.loading-indicator')); const minidumpColumn = screen.queryByText('minidump'); expect(minidumpColumn).not.toBeInTheDocument(); }); it('displays minidumps', async () => { attachmentsRequest = MockApiClient.addMockResponse({ url: '/api/0/issues/1/attachments/?per_page=50&types=event.minidump&event_id=id123', body: [ { id: 'id123', name: 'dc42a8b9-fc22-4de1-8a29-45b3006496d8.dmp', headers: { 'Content-Type': 'application/octet-stream', }, mimetype: 'application/octet-stream', size: 1294340, sha1: '742127552a1191f71fcf6ba7bc5afa0a837350e2', dateCreated: '2022-09-28T09:04:38.659307Z', type: 'event.minidump', event_id: 'd54cb9246ee241ffbdb39bf7a9fafbb7', }, ], }); render( , {context: routerContext, organization} ); await waitForElementToBeRemoved(document.querySelector('div.loading-indicator')); const minidumpColumn = screen.queryByText('minidump'); expect(minidumpColumn).toBeInTheDocument(); }); it('does not display attachments but displays minidump', async () => { attachmentsRequest = MockApiClient.addMockResponse({ url: '/api/0/issues/1/attachments/?per_page=50&types=event.minidump&event_id=id123', body: [ { id: 'id123', name: 'dc42a8b9-fc22-4de1-8a29-45b3006496d8.dmp', headers: { 'Content-Type': 'application/octet-stream', }, mimetype: 'application/octet-stream', size: 1294340, sha1: '742127552a1191f71fcf6ba7bc5afa0a837350e2', dateCreated: '2022-09-28T09:04:38.659307Z', type: 'event.minidump', event_id: 'd54cb9246ee241ffbdb39bf7a9fafbb7', }, ], }); render( , {context: routerContext, organization} ); await waitForElementToBeRemoved(document.querySelector('div.loading-indicator')); const attachmentsColumn = screen.queryByText('attachments'); const minidumpColumn = screen.queryByText('minidump'); expect(attachmentsColumn).not.toBeInTheDocument(); expect(minidumpColumn).toBeInTheDocument(); expect(attachmentsRequest).toHaveBeenCalled(); }); it('renders new events table if error', function () { render( , {context: routerContext, organization} ); expect(discoverRequest).toHaveBeenCalledWith( '/organizations/org-slug/events/', expect.objectContaining({ query: expect.objectContaining({ query: 'issue.id:1 ', field: expect.not.arrayContaining(['attachments', 'minidump']), }), }) ); const perfEventsColumn = screen.getByText('transaction'); expect(perfEventsColumn).toBeInTheDocument(); }); it('removes sort if unsupported by the events table', function () { render( , {context: routerContext, organization} ); expect(discoverRequest).toHaveBeenCalledWith( '/organizations/org-slug/events/', expect.objectContaining({query: expect.not.objectContaining({sort: 'user'})}) ); }); it('shows discover query error message', async () => { discoverRequest = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events/', statusCode: 500, body: { detail: 'Internal Error', errorId: '69ab396e73704cdba9342ff8dcd59795', }, }); render( , {context: routerContext, organization} ); await waitForElementToBeRemoved(document.querySelector('div.loading-indicator')); expect(screen.getByTestId('loading-error')).toHaveTextContent('Internal Error'); }); }); it('does not renders new events table if error', function () { const org = initializeOrg(); const group = TestStubs.Group(); render( , {context: routerContext, organization} ); const perfEventsColumn = screen.queryByText('transaction'); expect(perfEventsColumn).not.toBeInTheDocument(); }); });