releaseActions.spec.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import type {Location} from 'history';
  2. import {HealthFixture} from 'sentry-fixture/health';
  3. import {LocationFixture} from 'sentry-fixture/locationFixture';
  4. import {OrganizationFixture} from 'sentry-fixture/organization';
  5. import {ReleaseFixture} from 'sentry-fixture/release';
  6. import {ReleaseMetaFixture} from 'sentry-fixture/releaseMeta';
  7. import {ReleaseProjectFixture} from 'sentry-fixture/releaseProject';
  8. import {RouteComponentPropsFixture} from 'sentry-fixture/routeComponentPropsFixture';
  9. import {
  10. render,
  11. renderGlobalModal,
  12. screen,
  13. userEvent,
  14. waitFor,
  15. } from 'sentry-test/reactTestingLibrary';
  16. import type {ReleaseProject} from 'sentry/types';
  17. import {ReleaseStatus} from 'sentry/types/release';
  18. import {browserHistory} from 'sentry/utils/browserHistory';
  19. import ReleaseActions from 'sentry/views/releases/detail/header/releaseActions';
  20. describe('ReleaseActions', function () {
  21. const organization = OrganizationFixture();
  22. const project1 = ReleaseProjectFixture({
  23. slug: 'project1',
  24. hasHealthData: true,
  25. healthData: HealthFixture(),
  26. }) as Required<ReleaseProject>;
  27. const project2 = ReleaseProjectFixture({
  28. slug: 'project2',
  29. hasHealthData: true,
  30. healthData: HealthFixture(),
  31. }) as Required<ReleaseProject>;
  32. const release = ReleaseFixture({
  33. projects: [project1, project2],
  34. });
  35. const location: Location = {
  36. ...LocationFixture(),
  37. pathname: `/organizations/sentry/releases/${release.version}/`,
  38. query: {
  39. project: '1',
  40. statsPeriod: '24h',
  41. yAxis: 'events',
  42. },
  43. };
  44. let mockUpdate: ReturnType<typeof MockApiClient.addMockResponse>;
  45. beforeEach(function () {
  46. mockUpdate = MockApiClient.addMockResponse({
  47. url: `/organizations/${organization.slug}/releases/`,
  48. method: 'POST',
  49. });
  50. });
  51. afterEach(function () {
  52. MockApiClient.clearMockResponses();
  53. });
  54. it('archives a release', async function () {
  55. render(
  56. <ReleaseActions
  57. organization={organization}
  58. projectSlug={release.projects[0].slug}
  59. release={release}
  60. refetchData={jest.fn()}
  61. releaseMeta={{...ReleaseMetaFixture(), projects: release.projects}}
  62. location={location}
  63. />
  64. );
  65. renderGlobalModal();
  66. await userEvent.click(screen.getByLabelText('Actions'));
  67. const archiveAction = screen.getByTestId('archive');
  68. expect(archiveAction).toBeInTheDocument();
  69. expect(archiveAction).toHaveTextContent('Archive');
  70. await userEvent.click(archiveAction);
  71. expect(await screen.findByText('Archive Release 1.2.0')).toBeInTheDocument();
  72. const affectedProjects = screen.getAllByTestId('badge-display-name');
  73. expect(affectedProjects.length).toBe(2);
  74. // confirm modal
  75. await userEvent.click(screen.getByTestId('confirm-button'));
  76. expect(mockUpdate).toHaveBeenCalledWith(
  77. expect.anything(),
  78. expect.objectContaining({
  79. data: {
  80. projects: [],
  81. status: 'archived',
  82. version: release.version,
  83. },
  84. })
  85. );
  86. await waitFor(() =>
  87. expect(browserHistory.push).toHaveBeenCalledWith(
  88. `/organizations/${organization.slug}/releases/`
  89. )
  90. );
  91. });
  92. it('restores a release', async function () {
  93. const refetchDataMock = jest.fn();
  94. render(
  95. <ReleaseActions
  96. {...RouteComponentPropsFixture()}
  97. organization={organization}
  98. projectSlug={release.projects[0].slug}
  99. release={{...release, status: ReleaseStatus.ARCHIVED}}
  100. refetchData={refetchDataMock}
  101. releaseMeta={{...ReleaseMetaFixture(), projects: release.projects}}
  102. location={location}
  103. />
  104. );
  105. renderGlobalModal();
  106. await userEvent.click(screen.getByLabelText('Actions'));
  107. const restoreAction = screen.getByTestId('restore');
  108. expect(restoreAction).toBeInTheDocument();
  109. expect(restoreAction).toHaveTextContent('Restore');
  110. await userEvent.click(restoreAction);
  111. expect(await screen.findByText('Restore Release 1.2.0')).toBeInTheDocument();
  112. const affectedProjects = screen.getAllByTestId('badge-display-name');
  113. expect(affectedProjects.length).toBe(2);
  114. // confirm modal
  115. await userEvent.click(screen.getByTestId('confirm-button'));
  116. expect(mockUpdate).toHaveBeenCalledWith(
  117. expect.anything(),
  118. expect.objectContaining({
  119. data: {
  120. projects: [],
  121. status: 'open',
  122. version: release.version,
  123. },
  124. })
  125. );
  126. await waitFor(() => expect(refetchDataMock).toHaveBeenCalledTimes(1));
  127. });
  128. it('navigates to a next/prev release', function () {
  129. const {rerender} = render(
  130. <ReleaseActions
  131. organization={organization}
  132. projectSlug={release.projects[0].slug}
  133. release={release}
  134. refetchData={jest.fn()}
  135. releaseMeta={{...ReleaseMetaFixture(), projects: release.projects}}
  136. location={location}
  137. />
  138. );
  139. expect(screen.getByLabelText('Oldest')).toHaveAttribute(
  140. 'href',
  141. '/organizations/sentry/releases/0/?project=1&statsPeriod=24h&yAxis=events'
  142. );
  143. expect(screen.getByLabelText('Older')).toHaveAttribute(
  144. 'href',
  145. '/organizations/sentry/releases/123/?project=1&statsPeriod=24h&yAxis=events'
  146. );
  147. expect(screen.getByLabelText('Newer')).toHaveAttribute(
  148. 'href',
  149. '/organizations/sentry/releases/456/?project=1&statsPeriod=24h&yAxis=events'
  150. );
  151. expect(screen.getByLabelText('Newest')).toHaveAttribute(
  152. 'href',
  153. '/organizations/sentry/releases/999/?project=1&statsPeriod=24h&yAxis=events'
  154. );
  155. rerender(
  156. <ReleaseActions
  157. organization={organization}
  158. projectSlug={release.projects[0].slug}
  159. release={release}
  160. refetchData={jest.fn()}
  161. releaseMeta={{...ReleaseMetaFixture(), projects: release.projects}}
  162. location={{
  163. ...location,
  164. pathname: `/organizations/sentry/releases/${release.version}/files-changed/`,
  165. }}
  166. />
  167. );
  168. expect(screen.getByLabelText('Newer')).toHaveAttribute(
  169. 'href',
  170. '/organizations/sentry/releases/456/files-changed/?project=1&statsPeriod=24h&yAxis=events'
  171. );
  172. });
  173. });