createAlertButton.spec.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  2. import {navigateTo} from 'sentry/actionCreators/navigation';
  3. import CreateAlertButton, {
  4. CreateAlertFromViewButton,
  5. } from 'sentry/components/createAlertButton';
  6. import GuideStore from 'sentry/stores/guideStore';
  7. import EventView from 'sentry/utils/discover/eventView';
  8. import {DEFAULT_EVENT_VIEW} from 'sentry/views/discover/data';
  9. const onClickMock = jest.fn();
  10. jest.mock('sentry/actionCreators/navigation');
  11. describe('CreateAlertFromViewButton', () => {
  12. const organization = TestStubs.Organization();
  13. afterEach(() => {
  14. jest.resetAllMocks();
  15. });
  16. it('should trigger onClick callback', async () => {
  17. const context = TestStubs.routerContext();
  18. const eventView = EventView.fromSavedQuery({
  19. ...DEFAULT_EVENT_VIEW,
  20. query: 'event.type:error',
  21. projects: [2],
  22. });
  23. render(
  24. <CreateAlertFromViewButton
  25. organization={organization}
  26. eventView={eventView}
  27. projects={[TestStubs.Project()]}
  28. onClick={onClickMock}
  29. />,
  30. {context}
  31. );
  32. await userEvent.click(screen.getByRole('button', {name: 'Create Alert'}));
  33. expect(onClickMock).toHaveBeenCalledTimes(1);
  34. });
  35. it('disables the button for org-member', () => {
  36. const eventView = EventView.fromSavedQuery({
  37. ...DEFAULT_EVENT_VIEW,
  38. });
  39. const noAccessOrg = {
  40. ...organization,
  41. access: [],
  42. };
  43. const noAccessProj = {
  44. ...TestStubs.Project(),
  45. access: [],
  46. };
  47. render(
  48. <CreateAlertFromViewButton
  49. organization={noAccessOrg}
  50. eventView={eventView}
  51. projects={[noAccessProj]}
  52. onClick={onClickMock}
  53. />,
  54. {
  55. context: TestStubs.routerContext([{organization: noAccessOrg}]),
  56. organization: noAccessOrg,
  57. }
  58. );
  59. expect(screen.getByRole('button', {name: 'Create Alert'})).toBeDisabled();
  60. });
  61. it('enables the button for org-owner/manager', () => {
  62. const eventView = EventView.fromSavedQuery({
  63. ...DEFAULT_EVENT_VIEW,
  64. });
  65. const noAccessProj = {
  66. ...TestStubs.Project(),
  67. access: [],
  68. };
  69. render(
  70. <CreateAlertFromViewButton
  71. organization={organization}
  72. eventView={eventView}
  73. projects={[noAccessProj]}
  74. onClick={onClickMock}
  75. />,
  76. {
  77. context: TestStubs.routerContext([{organization}]),
  78. organization,
  79. }
  80. );
  81. expect(screen.getByRole('button', {name: 'Create Alert'})).toBeEnabled();
  82. });
  83. it('enables the button for team-admin', () => {
  84. const eventView = EventView.fromSavedQuery({
  85. ...DEFAULT_EVENT_VIEW,
  86. });
  87. const noAccessOrg = {
  88. ...organization,
  89. access: [],
  90. };
  91. const projects = [
  92. {
  93. ...TestStubs.Project(),
  94. id: 1,
  95. slug: 'admin-team',
  96. access: ['alerts:write'],
  97. },
  98. {
  99. ...TestStubs.Project(),
  100. id: 2,
  101. slug: 'contributor-team',
  102. access: ['alerts:read'],
  103. },
  104. ];
  105. render(
  106. <CreateAlertFromViewButton
  107. organization={noAccessOrg}
  108. eventView={eventView}
  109. projects={projects}
  110. onClick={onClickMock}
  111. />,
  112. {
  113. context: TestStubs.routerContext([{organization: noAccessOrg}]),
  114. organization: noAccessOrg,
  115. }
  116. );
  117. expect(screen.getByRole('button', {name: 'Create Alert'})).toBeEnabled();
  118. });
  119. it('shows a guide for org-member', () => {
  120. const noAccessOrg = {
  121. ...organization,
  122. access: [],
  123. };
  124. render(<CreateAlertButton organization={noAccessOrg} showPermissionGuide />, {
  125. organization: noAccessOrg,
  126. });
  127. expect(GuideStore.state.anchors).toEqual(new Set(['alerts_write_member']));
  128. });
  129. it('shows a guide for org-owner/manager', () => {
  130. const adminAccessOrg = {
  131. ...organization,
  132. access: ['org:write'],
  133. };
  134. render(<CreateAlertButton organization={adminAccessOrg} showPermissionGuide />, {
  135. organization: adminAccessOrg,
  136. });
  137. expect(GuideStore.state.anchors).toEqual(new Set(['alerts_write_owner']));
  138. });
  139. it('redirects to alert wizard with no project', async () => {
  140. render(<CreateAlertButton organization={organization} />, {
  141. organization,
  142. });
  143. await userEvent.click(screen.getByRole('button'));
  144. expect(navigateTo).toHaveBeenCalledWith(
  145. `/organizations/org-slug/alerts/wizard/?`,
  146. expect.objectContaining({
  147. params: expect.objectContaining({
  148. orgId: 'org-slug',
  149. }),
  150. })
  151. );
  152. });
  153. it('redirects to alert wizard with a project', () => {
  154. render(<CreateAlertButton organization={organization} projectSlug="proj-slug" />, {
  155. organization,
  156. });
  157. expect(screen.getByRole('button')).toHaveAttribute(
  158. 'href',
  159. '/organizations/org-slug/alerts/wizard/?project=proj-slug'
  160. );
  161. });
  162. it('removes a duplicate project filter', async () => {
  163. const context = TestStubs.routerContext();
  164. const eventView = EventView.fromSavedQuery({
  165. ...DEFAULT_EVENT_VIEW,
  166. query: 'event.type:error project:project-slug',
  167. projects: [2],
  168. });
  169. render(
  170. <CreateAlertFromViewButton
  171. organization={organization}
  172. eventView={eventView}
  173. projects={[TestStubs.Project()]}
  174. onClick={onClickMock}
  175. />,
  176. {context}
  177. );
  178. await userEvent.click(screen.getByRole('button'));
  179. expect(context.context.router.push).toHaveBeenCalledWith({
  180. pathname: `/organizations/org-slug/alerts/new/metric/`,
  181. query: expect.objectContaining({
  182. query: 'event.type:error ',
  183. project: 'project-slug',
  184. }),
  185. });
  186. });
  187. });