projectLatestAlerts.spec.jsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import {initializeOrg} from 'sentry-test/initializeOrg';
  3. import ProjectLatestAlerts from 'sentry/views/projectDetail/projectLatestAlerts';
  4. describe('ProjectDetail > ProjectLatestAlerts', function () {
  5. let endpointMock, rulesEndpointMock;
  6. const {organization, project, router} = initializeOrg();
  7. beforeEach(function () {
  8. endpointMock = MockApiClient.addMockResponse({
  9. url: `/organizations/${organization.slug}/incidents/`,
  10. body: [
  11. TestStubs.Incident({id: 1, status: 20}), // critical
  12. TestStubs.Incident({id: 2, status: 10}), // warning
  13. TestStubs.Incident({id: 3, status: 2}), // closed
  14. ],
  15. });
  16. rulesEndpointMock = MockApiClient.addMockResponse({
  17. url: `/organizations/${organization.slug}/alert-rules/`,
  18. body: [TestStubs.MetricRule()],
  19. });
  20. });
  21. afterEach(function () {
  22. MockApiClient.clearMockResponses();
  23. });
  24. it('renders a list', function () {
  25. const wrapper = mountWithTheme(
  26. <ProjectLatestAlerts
  27. organization={organization}
  28. projectSlug={project.slug}
  29. location={router.location}
  30. isProjectStabilized
  31. />
  32. );
  33. expect(endpointMock).toHaveBeenCalledTimes(2); // one for closed, one for open
  34. expect(rulesEndpointMock).toHaveBeenCalledTimes(0);
  35. expect(endpointMock).toHaveBeenCalledWith(
  36. expect.anything(),
  37. expect.objectContaining({
  38. query: {per_page: 3, status: expect.anything()},
  39. })
  40. );
  41. expect(wrapper.find('SectionHeading').text()).toBe('Latest Alerts');
  42. expect(wrapper.find('AlertRowLink').length).toBe(3);
  43. expect(wrapper.find('AlertRowLink Link').at(0).prop('to')).toBe(
  44. '/organizations/org-slug/alerts/123/'
  45. );
  46. expect(wrapper.find('AlertRowLink AlertTitle').at(0).text()).toBe(
  47. 'Too many Chrome errors'
  48. );
  49. expect(wrapper.find('AlertRowLink AlertDate').at(0).text()).toBe(
  50. 'Triggered 2 years ago'
  51. );
  52. expect(wrapper.find('AlertRowLink AlertDate').at(2).text()).toBe(
  53. 'Resolved a year ago'
  54. );
  55. expect(wrapper.find('AlertRowLink').at(0).find('IconFire').exists()).toBeTruthy();
  56. expect(
  57. wrapper.find('AlertRowLink').at(0).find('IconExclamation').exists()
  58. ).toBeFalsy();
  59. expect(
  60. wrapper.find('AlertRowLink').at(1).find('IconExclamation').exists()
  61. ).toBeTruthy();
  62. expect(
  63. wrapper.find('AlertRowLink').at(2).find('IconCheckmark').exists()
  64. ).toBeTruthy();
  65. });
  66. it('shows the empty state', async function () {
  67. MockApiClient.addMockResponse({
  68. url: `/organizations/${organization.slug}/incidents/`,
  69. body: [],
  70. });
  71. const wrapper = mountWithTheme(
  72. <ProjectLatestAlerts
  73. organization={organization}
  74. projectSlug={project.slug}
  75. location={router.location}
  76. isProjectStabilized
  77. />
  78. );
  79. await tick();
  80. wrapper.update();
  81. expect(rulesEndpointMock).toHaveBeenCalledWith(
  82. expect.anything(),
  83. expect.objectContaining({
  84. query: {per_page: 1},
  85. })
  86. ); // if there are no alerts, we check if any rules are set
  87. expect(wrapper.text()).toContain('No alerts found');
  88. });
  89. it('shows configure alerts buttons', async function () {
  90. MockApiClient.addMockResponse({
  91. url: `/organizations/${organization.slug}/incidents/`,
  92. body: [],
  93. });
  94. MockApiClient.addMockResponse({
  95. url: `/organizations/${organization.slug}/alert-rules/`,
  96. body: [],
  97. });
  98. const wrapper = mountWithTheme(
  99. <ProjectLatestAlerts
  100. organization={organization}
  101. projectSlug={project.slug}
  102. location={router.location}
  103. isProjectStabilized
  104. />
  105. );
  106. await tick();
  107. wrapper.update();
  108. const createRuleButton = wrapper.find('Button').at(0);
  109. const learnMoreButton = wrapper.find('Button').at(1);
  110. expect(createRuleButton.text()).toBe('Create Alert');
  111. expect(createRuleButton.prop('to')).toBe(
  112. `/organizations/${organization.slug}/alerts/wizard/?referrer=project_detail&project=project-slug`
  113. );
  114. expect(learnMoreButton.text()).toBe('Learn More');
  115. expect(learnMoreButton.prop('href')).toBe(
  116. 'https://docs.sentry.io/product/alerts-notifications/metric-alerts/'
  117. );
  118. });
  119. it('calls API with the right params', function () {
  120. mountWithTheme(
  121. <ProjectLatestAlerts
  122. organization={organization}
  123. projectSlug={project.slug}
  124. location={{
  125. query: {statsPeriod: '7d', environment: 'staging', somethingBad: 'nope'},
  126. }}
  127. projectId={project.slug}
  128. isProjectStabilized
  129. />
  130. );
  131. expect(endpointMock).toHaveBeenCalledWith(
  132. expect.anything(),
  133. expect.objectContaining({
  134. query: {per_page: 3, statsPeriod: '7d', environment: 'staging', status: 'open'},
  135. })
  136. );
  137. });
  138. it('handles null dateClosed with resolved alerts', function () {
  139. MockApiClient.addMockResponse({
  140. url: `/organizations/${organization.slug}/incidents/`,
  141. body: [
  142. TestStubs.Incident({id: 1, status: 20}), // critical
  143. TestStubs.Incident({id: 2, status: 10}), // warning
  144. TestStubs.Incident({id: 3, status: 2, dateClosed: null}), // closed with null dateClosed
  145. ],
  146. });
  147. const wrapper = mountWithTheme(
  148. <ProjectLatestAlerts
  149. organization={organization}
  150. projectSlug={project.slug}
  151. location={router.location}
  152. isProjectStabilized
  153. />
  154. );
  155. expect(wrapper.find('AlertRowLink AlertDate').at(2).text()).toBe('Resolved ');
  156. });
  157. it('does not call API if project is not stabilized yet', function () {
  158. mountWithTheme(
  159. <ProjectLatestAlerts
  160. organization={organization}
  161. projectSlug={project.slug}
  162. location={router.location}
  163. isProjectStabilized={false}
  164. />
  165. );
  166. expect(endpointMock).toHaveBeenCalledTimes(0);
  167. });
  168. });