releaseActions.spec.tsx 5.3 KB

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