releaseActions.spec.tsx 5.4 KB

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