index.spec.jsx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import React from 'react';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import IncidentDetails from 'app/views/incidents/details';
  5. import ProjectsStore from 'app/stores/projectsStore';
  6. describe('IncidentDetails', function() {
  7. const params = {orgId: 'org-slug', incidentId: '123'};
  8. const {organization, project, routerContext} = initializeOrg({
  9. router: {
  10. params,
  11. },
  12. });
  13. const mockIncident = TestStubs.Incident({projects: [project.slug]});
  14. let activitiesList;
  15. const createWrapper = props =>
  16. mountWithTheme(<IncidentDetails params={params} {...props} />, routerContext);
  17. beforeAll(function() {
  18. ProjectsStore.loadInitialData([project]);
  19. MockApiClient.addMockResponse({
  20. url: '/organizations/org-slug/incidents/123/',
  21. body: mockIncident,
  22. });
  23. // For @mentions
  24. MockApiClient.addMockResponse({
  25. url: '/organizations/org-slug/users/',
  26. body: [],
  27. });
  28. MockApiClient.addMockResponse({
  29. url: '/organizations/org-slug/incidents/123/suspects/',
  30. body: [TestStubs.IncidentSuspectCommit()],
  31. });
  32. MockApiClient.addMockResponse({
  33. url: '/organizations/org-slug/incidents/456/',
  34. statusCode: 404,
  35. });
  36. MockApiClient.addMockResponse({
  37. url: '/organizations/org-slug/incidents/456/suspects/',
  38. body: [],
  39. });
  40. activitiesList = MockApiClient.addMockResponse({
  41. url: `/organizations/${organization.slug}/incidents/${
  42. mockIncident.identifier
  43. }/activity/`,
  44. body: [TestStubs.IncidentActivity()],
  45. });
  46. });
  47. afterAll(function() {
  48. MockApiClient.clearMockResponses();
  49. });
  50. beforeEach(function() {
  51. activitiesList.mockClear();
  52. });
  53. it('loads incident', async function() {
  54. const wrapper = createWrapper();
  55. expect(wrapper.find('IncidentTitle').text()).toBe('Loading');
  56. expect(wrapper.find('SubscribeButton').prop('disabled')).toBe(true);
  57. await tick();
  58. wrapper.update();
  59. expect(wrapper.find('IncidentTitle').text()).toBe('Too many Chrome errors');
  60. expect(
  61. wrapper
  62. .find('ItemValue')
  63. .at(3)
  64. .text()
  65. ).toBe('100');
  66. expect(
  67. wrapper
  68. .find('ItemValue')
  69. .at(2)
  70. .text()
  71. ).toBe('20');
  72. expect(wrapper.find('SuspectItem')).toHaveLength(1);
  73. expect(
  74. wrapper
  75. .find('SuspectItem')
  76. .at(0)
  77. .find('MessageOverflow')
  78. .text()
  79. ).toBe('feat: Do something to raven/base.py');
  80. });
  81. it('handles invalid incident', async function() {
  82. const wrapper = createWrapper({params: {orgId: 'org-slug', incidentId: '456'}});
  83. await tick();
  84. wrapper.update();
  85. // Activity will also have a LoadingError
  86. expect(wrapper.find('LoadingError')).toHaveLength(2);
  87. });
  88. it('changes status to closed and fetches new activities', async function() {
  89. const updateStatus = MockApiClient.addMockResponse({
  90. url: '/organizations/org-slug/incidents/123/',
  91. method: 'PUT',
  92. body: TestStubs.Incident({
  93. status: 2,
  94. }),
  95. });
  96. const wrapper = createWrapper();
  97. await tick();
  98. wrapper.update();
  99. expect(activitiesList).toHaveBeenCalledTimes(1);
  100. expect(wrapper.find('Status').text()).toBe('Open');
  101. wrapper.find('[data-test-id="status-dropdown"] DropdownButton').simulate('click');
  102. wrapper
  103. .find('[data-test-id="status-dropdown"] MenuItem a')
  104. .at(0)
  105. .simulate('click');
  106. await tick();
  107. expect(updateStatus).toHaveBeenCalledWith(
  108. '/organizations/org-slug/incidents/123/',
  109. expect.objectContaining({
  110. data: {status: 2},
  111. })
  112. );
  113. // Refresh activities list since status changes also creates an activity
  114. expect(activitiesList).toHaveBeenCalledTimes(2);
  115. expect(wrapper.find('Status').text()).toBe('Closed');
  116. });
  117. it('toggles subscribe status with Subscribe button', async function() {
  118. const wrapper = createWrapper();
  119. await tick();
  120. wrapper.update();
  121. const subscribe = MockApiClient.addMockResponse({
  122. url: '/organizations/org-slug/incidents/123/subscriptions/',
  123. method: 'POST',
  124. });
  125. const unsubscribe = MockApiClient.addMockResponse({
  126. url: '/organizations/org-slug/incidents/123/subscriptions/',
  127. method: 'DELETE',
  128. });
  129. // Should be subscribed, so button should show "Unsubscribe"
  130. expect(wrapper.find('SubscribeButton Content').text()).toBe('Unsubscribe');
  131. // Click to unsubscribe
  132. wrapper.find('SubscribeButton').simulate('click');
  133. expect(unsubscribe).toHaveBeenCalled();
  134. expect(subscribe).not.toHaveBeenCalled();
  135. expect(wrapper.find('SubscribeButton Content').text()).toBe('Subscribe');
  136. // Click again to re-subscribe
  137. wrapper.find('SubscribeButton').simulate('click');
  138. expect(subscribe).toHaveBeenCalled();
  139. });
  140. it('loads related incidents', async function() {
  141. MockApiClient.addMockResponse({
  142. url: '/issues/1/',
  143. body: TestStubs.Group({
  144. id: '1',
  145. organization,
  146. }),
  147. });
  148. MockApiClient.addMockResponse({
  149. url: '/issues/2/',
  150. body: TestStubs.Group({
  151. id: '2',
  152. organization,
  153. }),
  154. });
  155. MockApiClient.addMockResponse({
  156. url: '/organizations/org-slug/incidents/123/',
  157. body: {
  158. ...mockIncident,
  159. groups: ['1', '2'],
  160. },
  161. });
  162. const wrapper = createWrapper();
  163. await tick();
  164. wrapper.update();
  165. expect(wrapper.find('RelatedItem')).toHaveLength(2);
  166. expect(
  167. wrapper
  168. .find('RelatedItem Title')
  169. .at(0)
  170. .text()
  171. ).toBe('RequestErrorfetchData(app/components/group/suggestedOwners)');
  172. expect(
  173. wrapper
  174. .find('RelatedItem GroupShortId')
  175. .at(0)
  176. .text()
  177. ).toBe('JAVASCRIPT-6QS');
  178. });
  179. it('renders incident without issues', async function() {
  180. MockApiClient.addMockResponse({
  181. url: '/organizations/org-slug/incidents/123/',
  182. body: {
  183. ...mockIncident,
  184. groups: [],
  185. },
  186. });
  187. const wrapper = createWrapper();
  188. expect(wrapper.find('RelatedIssues Placeholder')).toHaveLength(1);
  189. await tick();
  190. wrapper.update();
  191. expect(wrapper.find('RelatedItem')).toHaveLength(0);
  192. expect(wrapper.find('RelatedIssues Placeholder')).toHaveLength(0);
  193. });
  194. });