index.spec.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {act, render, screen} from 'sentry-test/reactTestingLibrary';
  3. import ProjectsStore from 'sentry/stores/projectsStore';
  4. import EventView from 'sentry/utils/discover/eventView';
  5. import {ALL_VIEWS, DEFAULT_EVENT_VIEW} from 'sentry/views/discover/data';
  6. import EventDetails from 'sentry/views/discover/eventDetails';
  7. describe('Discover > EventDetails', function () {
  8. const allEventsView = EventView.fromSavedQuery(DEFAULT_EVENT_VIEW);
  9. const errorsView = EventView.fromSavedQuery(
  10. ALL_VIEWS.find(view => view.name === 'Errors by Title')!
  11. );
  12. beforeEach(function () {
  13. act(() => ProjectsStore.loadInitialData([TestStubs.Project()]));
  14. MockApiClient.addMockResponse({
  15. url: '/organizations/org-slug/projects/',
  16. body: [],
  17. });
  18. MockApiClient.addMockResponse({
  19. url: '/organizations/org-slug/discover/',
  20. body: {
  21. meta: {
  22. id: 'string',
  23. title: 'string',
  24. 'project.name': 'string',
  25. timestamp: 'date',
  26. },
  27. data: [
  28. {
  29. id: 'deadbeef',
  30. title: 'Oh no something bad',
  31. 'project.name': 'project-slug',
  32. timestamp: '2019-05-23T22:12:48+00:00',
  33. },
  34. ],
  35. },
  36. });
  37. MockApiClient.addMockResponse({
  38. url: '/organizations/org-slug/events/project-slug:deadbeef/',
  39. method: 'GET',
  40. body: {
  41. id: '1234',
  42. size: 1200,
  43. projectSlug: 'project-slug',
  44. eventID: 'deadbeef',
  45. groupID: '123',
  46. title: 'Oh no something bad',
  47. location: '/users/login',
  48. message: 'It was not good',
  49. dateCreated: '2019-05-23T22:12:48+00:00',
  50. entries: [
  51. {
  52. type: 'message',
  53. message: 'bad stuff',
  54. data: {},
  55. },
  56. ],
  57. tags: [
  58. {key: 'browser', value: 'Firefox'},
  59. {key: 'device.uuid', value: 'test-uuid'},
  60. {key: 'release', value: '82ebf297206a'},
  61. ],
  62. },
  63. });
  64. MockApiClient.addMockResponse({
  65. url: '/issues/123/',
  66. method: 'GET',
  67. body: TestStubs.Group({id: '123'}),
  68. });
  69. MockApiClient.addMockResponse({
  70. url: '/organizations/org-slug/events-stats/',
  71. method: 'GET',
  72. body: {
  73. data: [
  74. [1234561700, [1]],
  75. [1234561800, [1]],
  76. ],
  77. },
  78. });
  79. MockApiClient.addMockResponse({
  80. url: '/projects/org-slug/project-slug/events/1234/committers/',
  81. method: 'GET',
  82. statusCode: 404,
  83. body: {},
  84. });
  85. MockApiClient.addMockResponse({
  86. url: '/projects/org-slug/project-slug/events/1234/grouping-info/',
  87. body: {},
  88. });
  89. // Missing event
  90. MockApiClient.addMockResponse({
  91. url: '/organizations/org-slug/events/project-slug:abad1/',
  92. method: 'GET',
  93. statusCode: 404,
  94. body: {},
  95. });
  96. });
  97. it('renders', async function () {
  98. render(
  99. <EventDetails
  100. {...TestStubs.routeComponentProps()}
  101. organization={TestStubs.Organization()}
  102. params={{eventSlug: 'project-slug:deadbeef'}}
  103. location={{
  104. ...TestStubs.location(),
  105. query: allEventsView.generateQueryStringObject(),
  106. }}
  107. />
  108. );
  109. expect(await screen.findByText('Oh no something bad')).toBeInTheDocument();
  110. });
  111. it('renders a 404', async function () {
  112. render(
  113. <EventDetails
  114. {...TestStubs.routeComponentProps()}
  115. organization={TestStubs.Organization()}
  116. params={{eventSlug: 'project-slug:abad1'}}
  117. location={{
  118. ...TestStubs.location(),
  119. query: allEventsView.generateQueryStringObject(),
  120. }}
  121. />
  122. );
  123. expect(await screen.findByText('Page Not Found')).toBeInTheDocument();
  124. });
  125. it('renders a chart in grouped view', async function () {
  126. render(
  127. <EventDetails
  128. {...TestStubs.routeComponentProps()}
  129. organization={TestStubs.Organization()}
  130. params={{eventSlug: 'project-slug:deadbeef'}}
  131. location={{
  132. ...TestStubs.location(),
  133. query: errorsView.generateQueryStringObject(),
  134. }}
  135. />
  136. );
  137. expect(await screen.findByText('Oh no something bad')).toBeInTheDocument();
  138. });
  139. it('renders an alert when linked issues are missing', async function () {
  140. MockApiClient.addMockResponse({
  141. url: '/issues/123/',
  142. statusCode: 404,
  143. method: 'GET',
  144. body: {},
  145. });
  146. render(
  147. <EventDetails
  148. {...TestStubs.routeComponentProps()}
  149. organization={TestStubs.Organization()}
  150. params={{eventSlug: 'project-slug:deadbeef'}}
  151. location={{
  152. ...TestStubs.location(),
  153. query: allEventsView.generateQueryStringObject(),
  154. }}
  155. />
  156. );
  157. expect(
  158. await screen.findByText(
  159. 'The linked issue cannot be found. It may have been deleted, or merged.'
  160. )
  161. ).toBeInTheDocument();
  162. });
  163. it('navigates when tag values are clicked', async function () {
  164. const {organization, routerContext} = initializeOrg({
  165. organization: TestStubs.Organization(),
  166. router: {
  167. location: {
  168. pathname: '/organizations/org-slug/discover/project-slug:deadbeef',
  169. query: {},
  170. },
  171. },
  172. });
  173. render(
  174. <EventDetails
  175. {...TestStubs.routeComponentProps()}
  176. organization={organization}
  177. params={{eventSlug: 'project-slug:deadbeef'}}
  178. location={{
  179. ...TestStubs.location(),
  180. query: allEventsView.generateQueryStringObject(),
  181. }}
  182. />,
  183. {context: routerContext}
  184. );
  185. // Get the first link as we wrap react-router's link
  186. expect(await screen.findByText('Firefox')).toBeInTheDocument();
  187. expect(screen.getByRole('link', {name: 'Firefox'})).toHaveAttribute(
  188. 'href',
  189. '/organizations/org-slug/discover/results/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=browser%3AFirefox%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  190. );
  191. // Get the second link
  192. expect(screen.getByRole('link', {name: 'test-uuid'})).toHaveAttribute(
  193. 'href',
  194. '/organizations/org-slug/discover/results/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=tags%5Bdevice.uuid%5D%3Atest-uuid%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  195. );
  196. // Get the third link
  197. expect(screen.getByRole('link', {name: '82ebf297206a'})).toHaveAttribute(
  198. 'href',
  199. '/organizations/org-slug/discover/results/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=release%3A82ebf297206a%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  200. );
  201. });
  202. it('navigates to homepage when tag values are clicked', async function () {
  203. const {organization, routerContext, router} = initializeOrg({
  204. organization: TestStubs.Organization(),
  205. router: {
  206. location: {
  207. pathname: '/organizations/org-slug/discover/project-slug:deadbeef',
  208. query: {...allEventsView.generateQueryStringObject(), homepage: 'true'},
  209. },
  210. },
  211. });
  212. render(
  213. <EventDetails
  214. {...TestStubs.routeComponentProps()}
  215. organization={organization}
  216. params={{eventSlug: 'project-slug:deadbeef'}}
  217. location={router.location}
  218. />,
  219. {context: routerContext}
  220. );
  221. // Get the first link as we wrap react-router's link
  222. expect(await screen.findByText('Firefox')).toBeInTheDocument();
  223. expect(screen.getByRole('link', {name: 'Firefox'})).toHaveAttribute(
  224. 'href',
  225. '/organizations/org-slug/discover/homepage/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=browser%3AFirefox%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  226. );
  227. // Get the second link
  228. expect(screen.getByRole('link', {name: 'test-uuid'})).toHaveAttribute(
  229. 'href',
  230. '/organizations/org-slug/discover/homepage/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=tags%5Bdevice.uuid%5D%3Atest-uuid%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  231. );
  232. // Get the third link
  233. expect(screen.getByRole('link', {name: '82ebf297206a'})).toHaveAttribute(
  234. 'href',
  235. '/organizations/org-slug/discover/homepage/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=release%3A82ebf297206a%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  236. );
  237. });
  238. it('appends tag value to existing query when clicked', async function () {
  239. const {organization, routerContext} = initializeOrg({
  240. organization: TestStubs.Organization(),
  241. router: {
  242. location: {
  243. pathname: '/organizations/org-slug/discover/project-slug:deadbeef',
  244. query: {},
  245. },
  246. },
  247. });
  248. render(
  249. <EventDetails
  250. {...TestStubs.routeComponentProps()}
  251. organization={organization}
  252. params={{eventSlug: 'project-slug:deadbeef'}}
  253. location={{
  254. ...TestStubs.location(),
  255. query: {...allEventsView.generateQueryStringObject(), query: 'Dumpster'},
  256. }}
  257. />,
  258. {context: routerContext}
  259. );
  260. // Get the first link as we wrap react-router's link
  261. expect(await screen.findByText('Firefox')).toBeInTheDocument();
  262. expect(screen.getByRole('link', {name: 'Firefox'})).toHaveAttribute(
  263. 'href',
  264. '/organizations/org-slug/discover/results/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=Dumpster%20browser%3AFirefox%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  265. );
  266. // Get the second link
  267. expect(screen.getByRole('link', {name: 'test-uuid'})).toHaveAttribute(
  268. 'href',
  269. '/organizations/org-slug/discover/results/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=Dumpster%20tags%5Bdevice.uuid%5D%3Atest-uuid%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  270. );
  271. // Get the third link
  272. expect(screen.getByRole('link', {name: '82ebf297206a'})).toHaveAttribute(
  273. 'href',
  274. '/organizations/org-slug/discover/results/?field=title&field=event.type&field=project&field=user.display&field=timestamp&name=All%20Events&query=Dumpster%20release%3A82ebf297206a%20title%3A%22Oh%20no%20something%20bad%22&sort=-timestamp&statsPeriod=24h&yAxis=count%28%29'
  275. );
  276. });
  277. it('links back to the homepage if the query param contains homepage flag', async () => {
  278. const {organization, router, routerContext} = initializeOrg({
  279. organization: TestStubs.Organization(),
  280. router: {
  281. location: {
  282. pathname: '/organizations/org-slug/discover/project-slug:deadbeef',
  283. query: {...allEventsView.generateQueryStringObject(), homepage: '1'},
  284. },
  285. },
  286. });
  287. render(
  288. <EventDetails
  289. {...TestStubs.routeComponentProps()}
  290. organization={organization}
  291. params={{eventSlug: 'project-slug:deadbeef'}}
  292. location={router.location}
  293. />,
  294. {context: routerContext, organization}
  295. );
  296. const breadcrumb = await screen.findByTestId('breadcrumb-link');
  297. expect(breadcrumb).toHaveTextContent('Discover');
  298. expect(breadcrumb).toHaveAttribute(
  299. 'href',
  300. expect.stringMatching(new RegExp('^/organizations/org-slug/discover/homepage/?'))
  301. );
  302. });
  303. });