eventList.spec.tsx 6.1 KB

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