eventList.spec.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import {EventsStatsFixture} from 'sentry-fixture/events';
  2. import {GroupFixture} from 'sentry-fixture/group';
  3. import {LocationFixture} from 'sentry-fixture/locationFixture';
  4. import {OrganizationFixture} from 'sentry-fixture/organization';
  5. import {ProjectFixture} from 'sentry-fixture/project';
  6. import {RouterFixture} from 'sentry-fixture/routerFixture';
  7. import {TagsFixture} from 'sentry-fixture/tags';
  8. import {render, renderHook, screen, waitFor} from 'sentry-test/reactTestingLibrary';
  9. import {useEventColumns} from 'sentry/views/issueDetails/allEventsTable';
  10. import {MOCK_EVENTS_TABLE_DATA} from 'sentry/views/performance/transactionSummary/transactionEvents/testUtils';
  11. import {EventList} from './eventList';
  12. describe('EventList', () => {
  13. const organization = OrganizationFixture();
  14. const project = ProjectFixture({
  15. environments: ['production', 'staging', 'development'],
  16. });
  17. const group = GroupFixture();
  18. const persistantQuery = `issue:${group.shortId}`;
  19. const totalCount = 100;
  20. let mockEventList: jest.Mock;
  21. let mockEventListMeta: jest.Mock;
  22. beforeEach(() => {
  23. MockApiClient.clearMockResponses();
  24. MockApiClient.addMockResponse({
  25. url: `/organizations/${organization.slug}/issues/${group.id}/tags/`,
  26. body: TagsFixture(),
  27. method: 'GET',
  28. });
  29. MockApiClient.addMockResponse({
  30. url: `/organizations/${organization.slug}/events-stats/`,
  31. body: {'count()': EventsStatsFixture(), 'count_unique(user)': EventsStatsFixture()},
  32. method: 'GET',
  33. });
  34. mockEventList = MockApiClient.addMockResponse({
  35. url: '/organizations/org-slug/events/',
  36. headers: {
  37. Link:
  38. `<http://localhost/api/0/organizations/${organization.slug}/events/?cursor=2:0:0>; rel="next"; results="true"; cursor="2:0:0",` +
  39. `<http://localhost/api/0/organizations/${organization.slug}/events/?cursor=1:0:0>; rel="previous"; results="false"; cursor="1:0:0"`,
  40. },
  41. body: {
  42. data: MOCK_EVENTS_TABLE_DATA,
  43. },
  44. match: [
  45. (_url, options) => {
  46. return options.query?.field?.includes('user.display');
  47. },
  48. ],
  49. });
  50. mockEventListMeta = MockApiClient.addMockResponse({
  51. url: '/organizations/org-slug/events/',
  52. headers: {
  53. Link:
  54. `<http://localhost/api/0/organizations/${organization.slug}/events/?cursor=2:0:0>; rel="next"; results="true"; cursor="2:0:0",` +
  55. `<http://localhost/api/0/organizations/${organization.slug}/events/?cursor=1:0:0>; rel="previous"; results="false"; cursor="1:0:0"`,
  56. },
  57. body: {
  58. data: [{'count()': totalCount}],
  59. },
  60. match: [
  61. (_url, options) => {
  62. return options.query?.field?.includes('count()');
  63. },
  64. ],
  65. });
  66. });
  67. function renderAllEvents() {
  68. render(<EventList group={group} />, {
  69. organization,
  70. router: RouterFixture({
  71. location: LocationFixture({
  72. pathname: `/organizations/${organization.slug}/issues/${group.id}/events/`,
  73. }),
  74. routes: [{name: '', path: 'events/'}],
  75. }),
  76. });
  77. }
  78. it('renders the list using a discover event query', async function () {
  79. renderAllEvents();
  80. const {result} = renderHook(() => useEventColumns(group, organization));
  81. expect(await screen.findByText('All Events')).toBeInTheDocument();
  82. expect(mockEventList).toHaveBeenCalledWith(
  83. '/organizations/org-slug/events/',
  84. expect.objectContaining({
  85. query: {
  86. dataset: 'errors',
  87. environment: [],
  88. field: result.current.fields,
  89. per_page: 50,
  90. project: [project.id],
  91. query: persistantQuery,
  92. referrer: 'issue_details.streamline_list',
  93. statsPeriod: '14d',
  94. sort: '-timestamp',
  95. },
  96. })
  97. );
  98. expect(mockEventListMeta).toHaveBeenCalled();
  99. expect(screen.getByRole('button', {name: 'Previous Page'})).toBeInTheDocument();
  100. expect(screen.getByRole('button', {name: 'Next Page'})).toBeInTheDocument();
  101. expect(
  102. await screen.findByText(
  103. `Showing 1-${MOCK_EVENTS_TABLE_DATA.length} of ${totalCount} matching events`
  104. )
  105. ).toBeInTheDocument();
  106. // Returns minidump column, but we omit it as a custom column
  107. const columns = result.current.columnTitles.filter(t => t !== 'Minidump');
  108. for (const title of columns) {
  109. expect(screen.getByRole('columnheader', {name: title})).toBeInTheDocument();
  110. }
  111. });
  112. it('updates query from location param change', async function () {
  113. const [tagKey, tagValue] = ['user.email', 'leander.rodrigues@sentry.io'];
  114. const locationQuery = {
  115. query: {
  116. query: `${tagKey}:${tagValue}`,
  117. },
  118. };
  119. render(<EventList group={group} />, {
  120. organization,
  121. router: RouterFixture({
  122. location: LocationFixture({
  123. pathname: `/organizations/${organization.slug}/issues/${group.id}/events/`,
  124. query: locationQuery.query,
  125. }),
  126. routes: [{name: '', path: 'events/'}],
  127. }),
  128. });
  129. const expectedArgs = [
  130. '/organizations/org-slug/events/',
  131. expect.objectContaining({
  132. query: expect.objectContaining({
  133. query: [persistantQuery, locationQuery.query.query].join(' '),
  134. }),
  135. }),
  136. ];
  137. await waitFor(() => {
  138. expect(mockEventList).toHaveBeenCalledWith(...expectedArgs);
  139. });
  140. expect(mockEventListMeta).toHaveBeenCalledWith(...expectedArgs);
  141. });
  142. });