stackTracePreview.spec.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  2. import {StackTracePreview} from 'sentry/components/stacktracePreview';
  3. import {EventError} from 'sentry/types';
  4. import {EntryType, Event, ExceptionType, ExceptionValue, Frame} from 'sentry/types/event';
  5. import useApi from 'sentry/utils/useApi';
  6. const makeEvent = (event: Partial<Event> = {}): Event => {
  7. const evt: Event = {
  8. ...TestStubs.Event(),
  9. ...event,
  10. };
  11. return evt;
  12. };
  13. jest.mock('sentry/utils/useApi');
  14. describe('StackTracePreview', () => {
  15. it('fetches from projects when eventId and projectSlug are provided', async () => {
  16. const api = new MockApiClient();
  17. const spy = jest
  18. .spyOn(api, 'requestPromise')
  19. .mockResolvedValue(makeEvent({id: 'event_id', entries: []}));
  20. // @ts-ignore useApi is mocked
  21. useApi.mockReturnValue(api);
  22. render(
  23. <StackTracePreview
  24. issueId="issue"
  25. eventId="event_id"
  26. projectSlug="project_slug"
  27. organization={TestStubs.Organization({slug: 'org_slug'})}
  28. >
  29. Preview Trigger
  30. </StackTracePreview>
  31. );
  32. userEvent.hover(screen.getByText(/Preview Trigger/));
  33. await waitFor(() => {
  34. expect(spy.mock.calls[0][0]).toBe(
  35. `/projects/org_slug/project_slug/events/event_id/`
  36. );
  37. });
  38. });
  39. it('fetches from issues when issueId when eventId and projectSlug are not provided', async () => {
  40. const api = new MockApiClient();
  41. const spy = jest
  42. .spyOn(api, 'requestPromise')
  43. .mockResolvedValue(makeEvent({id: 'event_id', entries: []}));
  44. // @ts-ignore useApi is mocked
  45. useApi.mockReturnValue(api);
  46. render(
  47. <StackTracePreview
  48. issueId="issue"
  49. organization={TestStubs.Organization({slug: 'org_slug'})}
  50. >
  51. Preview Trigger
  52. </StackTracePreview>
  53. );
  54. userEvent.hover(screen.getByText(/Preview Trigger/));
  55. await waitFor(() => {
  56. expect(spy.mock.calls[0][0]).toBe(
  57. `/issues/issue/events/latest/?collapse=stacktraceOnly`
  58. );
  59. });
  60. });
  61. it('renders error message', async () => {
  62. const api = new MockApiClient();
  63. jest
  64. .spyOn(api, 'requestPromise')
  65. .mockRejectedValue(makeEvent({id: 'event_id', entries: []}));
  66. // @ts-ignore useApi is mocked
  67. useApi.mockReturnValue(api);
  68. render(
  69. <StackTracePreview
  70. issueId="issue"
  71. organization={TestStubs.Organization({slug: 'org_slug'})}
  72. >
  73. Preview Trigger
  74. </StackTracePreview>
  75. );
  76. userEvent.hover(screen.getByText(/Preview Trigger/));
  77. expect(await screen.findByText(/Failed to load stack trace/)).toBeInTheDocument();
  78. });
  79. it('warns about no stacktrace', async () => {
  80. const api = new MockApiClient();
  81. jest
  82. .spyOn(api, 'requestPromise')
  83. .mockResolvedValue(makeEvent({id: 'event_id', entries: []}));
  84. // @ts-ignore useApi is mocked
  85. useApi.mockReturnValue(api);
  86. render(
  87. <StackTracePreview
  88. issueId="issue"
  89. organization={TestStubs.Organization({slug: 'org_slug'})}
  90. >
  91. Preview Trigger
  92. </StackTracePreview>
  93. );
  94. userEvent.hover(screen.getByText(/Preview Trigger/));
  95. expect(
  96. await screen.findByText(/There is no stack trace available for this issue./)
  97. ).toBeInTheDocument();
  98. });
  99. it.each([
  100. ['stack-trace-content', []],
  101. ['stack-trace-content-v2', ['grouping-stacktrace-ui']],
  102. ])('renders %s', async (component, features) => {
  103. const api = new MockApiClient();
  104. const frame: Frame = {
  105. colNo: 0,
  106. filename: 'file.js',
  107. function: 'throwError',
  108. lineNo: 0,
  109. absPath: null,
  110. context: [],
  111. errors: null,
  112. inApp: false,
  113. instructionAddr: null,
  114. module: null,
  115. package: null,
  116. platform: null,
  117. rawFunction: null,
  118. symbol: null,
  119. symbolAddr: null,
  120. trust: undefined,
  121. vars: null,
  122. };
  123. const thread: ExceptionValue = {
  124. stacktrace: {
  125. hasSystemFrames: false,
  126. registers: {},
  127. framesOmitted: 0,
  128. frames: [frame],
  129. },
  130. mechanism: null,
  131. module: null,
  132. rawStacktrace: null,
  133. threadId: null,
  134. type: '',
  135. value: '',
  136. };
  137. const exceptionValue: ExceptionType = {
  138. values: [thread],
  139. excOmitted: undefined,
  140. hasSystemFrames: false,
  141. };
  142. const errorEvent: EventError = {
  143. id: 'event_id',
  144. entries: [
  145. {
  146. type: EntryType.EXCEPTION,
  147. data: exceptionValue,
  148. },
  149. ],
  150. } as EventError;
  151. jest.spyOn(api, 'requestPromise').mockResolvedValue(makeEvent(errorEvent));
  152. // @ts-ignore useApi is mocked
  153. useApi.mockReturnValue(api);
  154. render(
  155. <StackTracePreview
  156. issueId="issue"
  157. organization={TestStubs.Organization({
  158. slug: 'org_slug',
  159. features,
  160. })}
  161. >
  162. Preview Trigger
  163. </StackTracePreview>
  164. );
  165. userEvent.hover(screen.getByText(/Preview Trigger/));
  166. expect(await screen.findByTestId(component)).toBeInTheDocument();
  167. });
  168. });