eventContext.spec.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import type {Location} from 'history';
  2. import {render, screen} from 'sentry-test/reactTestingLibrary';
  3. import ConfigStore from 'sentry/stores/configStore';
  4. import {
  5. EntryType,
  6. Event,
  7. EventError,
  8. EventOrGroupType,
  9. ExceptionType,
  10. ExceptionValue,
  11. Frame,
  12. } from 'sentry/types/event';
  13. import EventView, {EventData} from 'sentry/utils/discover/eventView';
  14. import {QueryClient, QueryClientProvider} from 'sentry/utils/queryClient';
  15. import EventContext from './eventContext';
  16. const makeEvent = (event: Partial<Event> = {}): Event => {
  17. const evt: Event = {
  18. ...TestStubs.Event(),
  19. ...event,
  20. };
  21. return evt;
  22. };
  23. const mockedLocation = TestStubs.location({
  24. query: {
  25. field: ['issue', 'transaction.duration'],
  26. },
  27. });
  28. const dataRow: EventData = {
  29. id: '6b43e285de834ec5b5fe30d62d549b20',
  30. issue: 'SENTRY-VVY',
  31. release: 'backend@22.10.0+aaf33944f93dc8fa4234ca046a8d88fb1dccfb76',
  32. 'issue.id': 3512441874,
  33. 'project.name': 'sentry',
  34. };
  35. const queryClient = new QueryClient({
  36. defaultOptions: {
  37. queries: {
  38. retry: false,
  39. },
  40. },
  41. });
  42. const renderEventContext = (location?: Location, eventView?: EventView) => {
  43. const organization = TestStubs.Organization();
  44. render(
  45. <QueryClientProvider client={queryClient}>
  46. <EventContext
  47. dataRow={dataRow}
  48. organization={organization}
  49. location={location}
  50. eventView={eventView}
  51. />
  52. </QueryClientProvider>,
  53. {organization}
  54. );
  55. };
  56. describe('Quick Context Content: Event ID Column', function () {
  57. afterEach(() => {
  58. queryClient.clear();
  59. MockApiClient.clearMockResponses();
  60. });
  61. it('Renders transaction duration context', async () => {
  62. const currentTime = Date.now();
  63. MockApiClient.addMockResponse({
  64. url: '/organizations/org-slug/events/sentry:6b43e285de834ec5b5fe30d62d549b20/',
  65. body: makeEvent({
  66. type: EventOrGroupType.TRANSACTION,
  67. entries: [],
  68. endTimestamp: currentTime,
  69. startTimestamp: currentTime - 2,
  70. }),
  71. });
  72. renderEventContext(mockedLocation);
  73. expect(await screen.findByText(/Transaction Duration/i)).toBeInTheDocument();
  74. expect(screen.getByText(/2.00s/i)).toBeInTheDocument();
  75. });
  76. it('Renders transaction status context', async () => {
  77. const currentTime = Date.now();
  78. MockApiClient.addMockResponse({
  79. url: '/organizations/org-slug/events/sentry:6b43e285de834ec5b5fe30d62d549b20/',
  80. body: makeEvent({
  81. type: EventOrGroupType.TRANSACTION,
  82. entries: [],
  83. endTimestamp: currentTime,
  84. startTimestamp: currentTime - 2,
  85. contexts: {
  86. trace: {
  87. status: 'ok',
  88. },
  89. },
  90. tags: [
  91. {
  92. key: 'http.status_code',
  93. value: '200',
  94. },
  95. ],
  96. }),
  97. });
  98. renderEventContext(mockedLocation);
  99. expect(await screen.findByText(/Status/i)).toBeInTheDocument();
  100. expect(screen.getByText(/ok/i)).toBeInTheDocument();
  101. expect(screen.getByText(/HTTP 200/i)).toBeInTheDocument();
  102. });
  103. it('Renders NO stack trace message for error events without stackTraces', async () => {
  104. jest.spyOn(ConfigStore, 'get').mockImplementation(() => null);
  105. MockApiClient.addMockResponse({
  106. url: '/organizations/org-slug/events/sentry:6b43e285de834ec5b5fe30d62d549b20/',
  107. body: makeEvent({type: EventOrGroupType.ERROR, entries: []}),
  108. });
  109. renderEventContext();
  110. expect(
  111. await screen.findByText(/There is no stack trace available for this event./i)
  112. ).toBeInTheDocument();
  113. });
  114. it('Renders stack trace as context', async () => {
  115. const frame: Frame = {
  116. colNo: 0,
  117. filename: 'file.js',
  118. function: 'throwError',
  119. lineNo: 0,
  120. absPath: null,
  121. context: [],
  122. errors: null,
  123. inApp: false,
  124. instructionAddr: null,
  125. module: null,
  126. package: null,
  127. platform: null,
  128. rawFunction: null,
  129. symbol: null,
  130. symbolAddr: null,
  131. trust: undefined,
  132. vars: null,
  133. };
  134. const thread: ExceptionValue = {
  135. stacktrace: {
  136. hasSystemFrames: false,
  137. registers: {},
  138. framesOmitted: 0,
  139. frames: [frame],
  140. },
  141. mechanism: null,
  142. module: null,
  143. rawStacktrace: null,
  144. threadId: null,
  145. type: '',
  146. value: '',
  147. };
  148. const exceptionValue: ExceptionType = {
  149. values: [thread],
  150. excOmitted: undefined,
  151. hasSystemFrames: false,
  152. };
  153. const errorEvent: Event = {
  154. id: '6b43e285de834ec5b5fe30d62d549b20',
  155. type: EventOrGroupType.ERROR,
  156. entries: [
  157. {
  158. type: EntryType.EXCEPTION,
  159. data: exceptionValue,
  160. },
  161. ],
  162. } as EventError;
  163. MockApiClient.addMockResponse({
  164. url: '/organizations/org-slug/events/sentry:6b43e285de834ec5b5fe30d62d549b20/',
  165. body: makeEvent(errorEvent),
  166. });
  167. renderEventContext(mockedLocation);
  168. expect(await screen.findByTestId('stack-trace-content')).toBeInTheDocument();
  169. });
  170. });