index.spec.tsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import {EventsStatsFixture} from 'sentry-fixture/events';
  2. import {GroupFixture} from 'sentry-fixture/group';
  3. import {IncidentFixture} from 'sentry-fixture/incident';
  4. import {MetricRuleFixture} from 'sentry-fixture/metricRule';
  5. import {ProjectFixture} from 'sentry-fixture/project';
  6. import {initializeOrg} from 'sentry-test/initializeOrg';
  7. import {act, render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  8. import ProjectsStore from 'sentry/stores/projectsStore';
  9. import {trackAnalytics} from 'sentry/utils/analytics';
  10. import MetricAlertDetails from 'sentry/views/alerts/rules/metric/details';
  11. import {Dataset} from 'sentry/views/alerts/rules/metric/types';
  12. jest.mock('sentry/utils/analytics');
  13. describe('MetricAlertDetails', () => {
  14. const project = ProjectFixture({slug: 'earth', platform: 'javascript'});
  15. beforeEach(() => {
  16. act(() => ProjectsStore.loadInitialData([project]));
  17. MockApiClient.addMockResponse({
  18. url: '/organizations/org-slug/projects/',
  19. body: [project],
  20. });
  21. MockApiClient.addMockResponse({
  22. url: '/organizations/org-slug/users/',
  23. body: [],
  24. });
  25. MockApiClient.addMockResponse({
  26. url: '/organizations/org-slug/events-stats/',
  27. body: EventsStatsFixture(),
  28. });
  29. MockApiClient.addMockResponse({
  30. url: '/organizations/org-slug/issues/?end=2017-10-17T02%3A41%3A20&groupStatsPeriod=auto&limit=5&project=2&query=event.type%3Aerror&sort=freq&start=2017-10-10T02%3A41%3A20',
  31. body: [GroupFixture()],
  32. });
  33. });
  34. afterEach(() => {
  35. act(() => ProjectsStore.reset());
  36. jest.resetAllMocks();
  37. MockApiClient.clearMockResponses();
  38. });
  39. it('renders', async () => {
  40. const {organization, routerProps, router} = initializeOrg();
  41. const incident = IncidentFixture();
  42. const rule = MetricRuleFixture({
  43. projects: [project.slug],
  44. latestIncident: incident,
  45. });
  46. const promptResponse = {
  47. dismissed_ts: undefined,
  48. snoozed_ts: undefined,
  49. };
  50. MockApiClient.addMockResponse({
  51. url: `/organizations/${organization.slug}/prompts-activity/`,
  52. body: promptResponse,
  53. });
  54. MockApiClient.addMockResponse({
  55. url: `/organizations/org-slug/alert-rules/${rule.id}/`,
  56. body: rule,
  57. });
  58. MockApiClient.addMockResponse({
  59. url: `/organizations/org-slug/incidents/`,
  60. body: [incident],
  61. });
  62. render(
  63. <MetricAlertDetails
  64. organization={organization}
  65. {...routerProps}
  66. params={{ruleId: rule.id}}
  67. />,
  68. {router, organization}
  69. );
  70. expect(await screen.findAllByText(rule.name)).toHaveLength(2);
  71. expect(screen.getByText('Change alert status to Resolved')).toBeInTheDocument();
  72. expect(screen.getByText(`#${incident.identifier}`)).toBeInTheDocument();
  73. // Related issues
  74. expect(screen.getByTestId('group')).toBeInTheDocument();
  75. expect(trackAnalytics).toHaveBeenCalledWith(
  76. 'alert_rule_details.viewed',
  77. expect.objectContaining({
  78. rule_id: Number(rule.id),
  79. alert: '',
  80. })
  81. );
  82. });
  83. it('renders selected incident', async () => {
  84. const {organization, router, routerProps} = initializeOrg();
  85. const rule = MetricRuleFixture({projects: [project.slug]});
  86. const incident = IncidentFixture();
  87. const promptResponse = {
  88. dismissed_ts: undefined,
  89. snoozed_ts: undefined,
  90. };
  91. MockApiClient.addMockResponse({
  92. url: `/organizations/${organization.slug}/prompts-activity/`,
  93. body: promptResponse,
  94. });
  95. MockApiClient.addMockResponse({
  96. url: `/organizations/org-slug/alert-rules/${rule.id}/`,
  97. body: rule,
  98. });
  99. const incidentMock = MockApiClient.addMockResponse({
  100. url: `/organizations/org-slug/incidents/${incident.id}/`,
  101. body: incident,
  102. });
  103. MockApiClient.addMockResponse({
  104. url: `/organizations/org-slug/incidents/`,
  105. body: [incident],
  106. });
  107. // Related issues to the selected incident
  108. const issuesRequest = MockApiClient.addMockResponse({
  109. url: '/organizations/org-slug/issues/?end=2016-04-26T19%3A44%3A05&groupStatsPeriod=auto&limit=5&project=2&query=event.type%3Aerror&sort=freq&start=2016-03-29T19%3A44%3A05',
  110. body: [GroupFixture()],
  111. });
  112. render(
  113. <MetricAlertDetails
  114. organization={organization}
  115. {...routerProps}
  116. location={{...router.location, query: {alert: incident.id}}}
  117. params={{ruleId: rule.id}}
  118. />,
  119. {router, organization}
  120. );
  121. expect(await screen.findAllByText(rule.name)).toHaveLength(2);
  122. // Related issues
  123. expect(screen.getByTestId('group')).toBeInTheDocument();
  124. expect(trackAnalytics).toHaveBeenCalledWith(
  125. 'alert_rule_details.viewed',
  126. expect.objectContaining({
  127. rule_id: Number(rule.id),
  128. alert: '321',
  129. })
  130. );
  131. expect(incidentMock).toHaveBeenCalled();
  132. expect(issuesRequest).toHaveBeenCalled();
  133. });
  134. it('renders mute button for metric alert', async () => {
  135. const {organization, routerProps, router} = initializeOrg();
  136. const incident = IncidentFixture();
  137. const rule = MetricRuleFixture({
  138. projects: [project.slug],
  139. latestIncident: incident,
  140. });
  141. MockApiClient.addMockResponse({
  142. url: `/organizations/org-slug/alert-rules/${rule.id}/`,
  143. body: rule,
  144. });
  145. MockApiClient.addMockResponse({
  146. url: `/organizations/org-slug/incidents/`,
  147. body: [incident],
  148. });
  149. const promptResponse = {
  150. dismissed_ts: undefined,
  151. snoozed_ts: undefined,
  152. };
  153. MockApiClient.addMockResponse({
  154. url: `/organizations/${organization.slug}/prompts-activity/`,
  155. body: promptResponse,
  156. });
  157. const postRequest = MockApiClient.addMockResponse({
  158. url: `/projects/${organization.slug}/${project.slug}/alert-rules/${rule.id}/snooze/`,
  159. method: 'POST',
  160. });
  161. const deleteRequest = MockApiClient.addMockResponse({
  162. url: `/projects/${organization.slug}/${project.slug}/alert-rules/${rule.id}/snooze/`,
  163. method: 'DELETE',
  164. });
  165. render(
  166. <MetricAlertDetails
  167. {...routerProps}
  168. organization={organization}
  169. params={{ruleId: rule.id}}
  170. />,
  171. {router, organization}
  172. );
  173. expect(await screen.findByText('Mute for me')).toBeInTheDocument();
  174. await userEvent.click(screen.getByRole('button', {name: 'Mute for me'}));
  175. expect(postRequest).toHaveBeenCalledTimes(1);
  176. expect(await screen.findByText('Unmute')).toBeInTheDocument();
  177. await userEvent.click(screen.getByRole('button', {name: 'Unmute'}));
  178. expect(deleteRequest).toHaveBeenCalledTimes(1);
  179. });
  180. it('renders open in discover button with dataset=errors for is:unresolved query', async () => {
  181. const {organization, routerProps, router} = initializeOrg({
  182. organization: {features: ['discover-basic']},
  183. });
  184. const rule = MetricRuleFixture({
  185. projects: [project.slug],
  186. dataset: Dataset.ERRORS,
  187. query: 'is:unresolved',
  188. });
  189. MockApiClient.addMockResponse({
  190. url: `/organizations/org-slug/alert-rules/${rule.id}/`,
  191. body: rule,
  192. });
  193. MockApiClient.addMockResponse({
  194. url: `/organizations/org-slug/incidents/`,
  195. body: [],
  196. });
  197. MockApiClient.addMockResponse({
  198. url: '/organizations/org-slug/issues/?end=2017-10-17T02%3A41%3A20&groupStatsPeriod=auto&limit=5&project=2&query=event.type%3Aerror%20is%3Aunresolved&sort=freq&start=2017-10-10T02%3A41%3A20',
  199. body: [],
  200. });
  201. render(
  202. <MetricAlertDetails
  203. organization={organization}
  204. {...routerProps}
  205. params={{ruleId: rule.id}}
  206. />,
  207. {router, organization}
  208. );
  209. expect(await screen.findAllByText(rule.name)).toHaveLength(2);
  210. expect(screen.getByRole('button', {name: 'Open in Discover'})).toHaveAttribute(
  211. 'href',
  212. expect.stringContaining('dataset=errors')
  213. );
  214. });
  215. });