releaseActions.spec.tsx 5.2 KB

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