releaseIssues.spec.jsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import ReleaseIssues from 'sentry/views/releases/detail/overview/releaseIssues';
  3. import {getReleaseBounds} from 'sentry/views/releases/utils';
  4. describe('ReleaseIssues', function () {
  5. let newIssuesEndpoint,
  6. resolvedIssuesEndpoint,
  7. unhandledIssuesEndpoint,
  8. allIssuesEndpoint;
  9. const props = {
  10. orgId: 'org',
  11. organization: TestStubs.Organization(),
  12. version: '1.0.0',
  13. selection: {projects: [], environments: [], datetime: {}},
  14. location: {href: '', query: {}},
  15. releaseBounds: getReleaseBounds(TestStubs.Release({version: '1.0.0'})),
  16. };
  17. beforeEach(function () {
  18. MockApiClient.clearMockResponses();
  19. MockApiClient.addMockResponse({
  20. url: `/organizations/${props.organization.slug}/users/`,
  21. body: [],
  22. });
  23. MockApiClient.addMockResponse({
  24. url: `/organizations/${props.organization.slug}/issues-count/?end=2020-03-24T02%3A04%3A59Z&query=first-release%3A%221.0.0%22%20is%3Aunresolved&query=release%3A%221.0.0%22%20is%3Aunresolved&query=error.handled%3A0%20release%3A%221.0.0%22%20is%3Aunresolved&query=regressed_in_release%3A%221.0.0%22&start=2020-03-23T01%3A02%3A00Z`,
  25. });
  26. MockApiClient.addMockResponse({
  27. url: `/organizations/${props.organization.slug}/issues-count/?query=first-release%3A%221.0.0%22%20is%3Aunresolved&query=release%3A%221.0.0%22%20is%3Aunresolved&query=error.handled%3A0%20release%3A%221.0.0%22%20is%3Aunresolved&query=regressed_in_release%3A%221.0.0%22&statsPeriod=24h`,
  28. });
  29. MockApiClient.addMockResponse({
  30. url: `/organizations/${props.organization.slug}/releases/1.0.0/resolved/`,
  31. });
  32. newIssuesEndpoint = MockApiClient.addMockResponse({
  33. url: `/organizations/${props.organization.slug}/issues/?end=2020-03-24T02%3A04%3A59Z&groupStatsPeriod=auto&limit=10&query=first-release%3A1.0.0%20is%3Aunresolved&sort=freq&start=2020-03-23T01%3A02%3A00Z`,
  34. body: [],
  35. });
  36. MockApiClient.addMockResponse({
  37. url: `/organizations/${props.organization.slug}/issues/?groupStatsPeriod=auto&limit=10&query=first-release%3A1.0.0%20is%3Aunresolved&sort=freq&statsPeriod=24h`,
  38. body: [],
  39. });
  40. resolvedIssuesEndpoint = MockApiClient.addMockResponse({
  41. url: `/organizations/${props.organization.slug}/releases/1.0.0/resolved/?end=2020-03-24T02%3A04%3A59Z&groupStatsPeriod=auto&limit=10&query=&sort=freq&start=2020-03-23T01%3A02%3A00Z`,
  42. body: [],
  43. });
  44. unhandledIssuesEndpoint = MockApiClient.addMockResponse({
  45. url: `/organizations/${props.organization.slug}/issues/?end=2020-03-24T02%3A04%3A59Z&groupStatsPeriod=auto&limit=10&query=release%3A1.0.0%20error.handled%3A0%20is%3Aunresolved&sort=freq&start=2020-03-23T01%3A02%3A00Z`,
  46. body: [],
  47. });
  48. MockApiClient.addMockResponse({
  49. url: `/organizations/${props.organization.slug}/issues/?groupStatsPeriod=auto&limit=10&query=release%3A1.0.0%20error.handled%3A0%20is%3Aunresolved&sort=freq&statsPeriod=24h`,
  50. body: [],
  51. });
  52. allIssuesEndpoint = MockApiClient.addMockResponse({
  53. url: `/organizations/${props.organization.slug}/issues/?end=2020-03-24T02%3A04%3A59Z&groupStatsPeriod=auto&limit=10&query=release%3A1.0.0%20is%3Aunresolved&sort=freq&start=2020-03-23T01%3A02%3A00Z`,
  54. body: [],
  55. });
  56. });
  57. const filterIssues = (wrapper, filter) => {
  58. wrapper.find(`ButtonBar Button[data-test-id="filter-${filter}"]`).simulate('click');
  59. };
  60. it('shows an empty state', async function () {
  61. const wrapper = mountWithTheme(<ReleaseIssues {...props} />);
  62. const wrapper2 = mountWithTheme(
  63. <ReleaseIssues {...props} location={{query: {pageStatsPeriod: '24h'}}} />
  64. );
  65. await tick();
  66. wrapper.update();
  67. expect(wrapper.find('EmptyStateWarning').text()).toBe(
  68. 'No new issues in this release.'
  69. );
  70. wrapper2.update();
  71. expect(wrapper2.find('EmptyStateWarning').text()).toBe(
  72. 'No new issues for the last 24 hours.'
  73. );
  74. filterIssues(wrapper, 'resolved');
  75. await tick();
  76. wrapper.update();
  77. expect(wrapper.find('EmptyStateWarning').text()).toBe(
  78. 'No resolved issues in this release.'
  79. );
  80. filterIssues(wrapper2, 'unhandled');
  81. await tick();
  82. wrapper2.update();
  83. expect(wrapper2.find('EmptyStateWarning').text()).toBe(
  84. 'No unhandled issues for the last 24 hours.'
  85. );
  86. });
  87. it('filters the issues', function () {
  88. const wrapper = mountWithTheme(<ReleaseIssues {...props} />);
  89. const filterOptions = wrapper.find('ButtonBar Button');
  90. expect(filterOptions).toHaveLength(6); // sixth one is "Open Issues" button
  91. expect(filterOptions.at(2).text()).toEqual('Unhandled');
  92. filterIssues(wrapper, 'new');
  93. expect(newIssuesEndpoint).toHaveBeenCalledTimes(1);
  94. filterIssues(wrapper, 'resolved');
  95. expect(resolvedIssuesEndpoint).toHaveBeenCalledTimes(1);
  96. filterIssues(wrapper, 'unhandled');
  97. expect(unhandledIssuesEndpoint).toHaveBeenCalledTimes(1);
  98. filterIssues(wrapper, 'all');
  99. expect(allIssuesEndpoint).toHaveBeenCalledTimes(1);
  100. });
  101. it('renders link to Issues', function () {
  102. const wrapper = mountWithTheme(<ReleaseIssues {...props} />);
  103. expect(wrapper.find('Link[data-test-id="issues-button"]').prop('to')).toEqual({
  104. pathname: `/organizations/${props.organization.slug}/issues/`,
  105. query: {
  106. sort: 'freq',
  107. query: 'firstRelease:1.0.0',
  108. cursor: undefined,
  109. limit: undefined,
  110. start: '2020-03-23T01:02:00Z',
  111. end: '2020-03-24T02:04:59Z',
  112. groupStatsPeriod: 'auto',
  113. },
  114. });
  115. filterIssues(wrapper, 'resolved');
  116. expect(wrapper.find('Link[data-test-id="issues-button"]').prop('to')).toEqual({
  117. pathname: `/organizations/${props.organization.slug}/issues/`,
  118. query: {
  119. sort: 'freq',
  120. query: 'release:1.0.0',
  121. cursor: undefined,
  122. limit: undefined,
  123. start: '2020-03-23T01:02:00Z',
  124. end: '2020-03-24T02:04:59Z',
  125. groupStatsPeriod: 'auto',
  126. },
  127. });
  128. filterIssues(wrapper, 'unhandled');
  129. expect(wrapper.find('Link[data-test-id="issues-button"]').prop('to')).toEqual({
  130. pathname: `/organizations/${props.organization.slug}/issues/`,
  131. query: {
  132. sort: 'freq',
  133. query: 'release:1.0.0 error.handled:0',
  134. cursor: undefined,
  135. limit: undefined,
  136. start: '2020-03-23T01:02:00Z',
  137. end: '2020-03-24T02:04:59Z',
  138. groupStatsPeriod: 'auto',
  139. },
  140. });
  141. filterIssues(wrapper, 'all');
  142. expect(wrapper.find('Link[data-test-id="issues-button"]').prop('to')).toEqual({
  143. pathname: `/organizations/${props.organization.slug}/issues/`,
  144. query: {
  145. sort: 'freq',
  146. query: 'release:1.0.0',
  147. cursor: undefined,
  148. limit: undefined,
  149. start: '2020-03-23T01:02:00Z',
  150. end: '2020-03-24T02:04:59Z',
  151. groupStatsPeriod: 'auto',
  152. },
  153. });
  154. });
  155. });