createAlertButton.spec.tsx 5.6 KB

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