createAlertButton.spec.jsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import React from 'react';
  2. import {mountWithTheme} from 'sentry-test/enzyme';
  3. import {DEFAULT_EVENT_VIEW, ALL_VIEWS} from 'app/views/eventsV2/data';
  4. import CreateAlertButton from 'app/components/createAlertButton';
  5. import EventView from 'app/utils/discover/eventView';
  6. const onIncompatibleQueryMock = jest.fn();
  7. const onCloseMock = jest.fn();
  8. const onSuccessMock = jest.fn();
  9. function generateWrappedComponent(organization, eventView) {
  10. return mountWithTheme(
  11. <CreateAlertButton
  12. location={location}
  13. organization={organization}
  14. eventView={eventView}
  15. projects={[]}
  16. onIncompatibleQuery={onIncompatibleQueryMock}
  17. onSuccess={onSuccessMock}
  18. />,
  19. TestStubs.routerContext()
  20. );
  21. }
  22. describe('CreateAlertButton', () => {
  23. const organization = TestStubs.Organization();
  24. afterEach(() => {
  25. jest.resetAllMocks();
  26. });
  27. it('renders', () => {
  28. const eventView = EventView.fromSavedQuery(DEFAULT_EVENT_VIEW);
  29. const wrapper = generateWrappedComponent(organization, eventView);
  30. expect(wrapper.text()).toBe('Create alert');
  31. });
  32. it('should warn when project is not selected', () => {
  33. const eventView = EventView.fromSavedQuery({
  34. ...DEFAULT_EVENT_VIEW,
  35. query: 'event.type:error',
  36. });
  37. const wrapper = generateWrappedComponent(organization, eventView);
  38. wrapper.simulate('click');
  39. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(1);
  40. const errorsAlert = mountWithTheme(
  41. onIncompatibleQueryMock.mock.calls[0][0](onCloseMock)
  42. );
  43. expect(errorsAlert.text()).toBe(
  44. 'An alert can use data from only one Project. Select one and try again.'
  45. );
  46. });
  47. it('should warn when all projects are selected (-1)', () => {
  48. const eventView = EventView.fromSavedQuery({
  49. ...DEFAULT_EVENT_VIEW,
  50. query: 'event.type:error',
  51. projects: [-1],
  52. });
  53. const wrapper = generateWrappedComponent(organization, eventView);
  54. wrapper.simulate('click');
  55. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(1);
  56. const errorsAlert = mountWithTheme(
  57. onIncompatibleQueryMock.mock.calls[0][0](onCloseMock)
  58. );
  59. expect(errorsAlert.text()).toBe(
  60. 'An alert can use data from only one Project. Select one and try again.'
  61. );
  62. });
  63. it('should warn when event.type is not specified', () => {
  64. const eventView = EventView.fromSavedQuery({
  65. ...DEFAULT_EVENT_VIEW,
  66. query: '',
  67. projects: [2],
  68. });
  69. const wrapper = generateWrappedComponent(organization, eventView);
  70. wrapper.simulate('click');
  71. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(1);
  72. const errorsAlert = mountWithTheme(
  73. onIncompatibleQueryMock.mock.calls[0][0](onCloseMock)
  74. );
  75. expect(errorsAlert.text()).toBe(
  76. 'An alert needs a filter of event.type:error or event.type:transaction. Use one of these and try again.'
  77. );
  78. });
  79. it('should warn when yAxis is not allowed', () => {
  80. const eventView = EventView.fromSavedQuery({
  81. ...ALL_VIEWS.find(view => view.name === 'Errors by URL'),
  82. query: 'event.type:error',
  83. yAxis: 'count_unique(issue)',
  84. projects: [2],
  85. });
  86. expect(eventView.getYAxis()).toBe('count_unique(issue)');
  87. const wrapper = generateWrappedComponent(organization, eventView);
  88. wrapper.simulate('click');
  89. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(1);
  90. const errorsAlert = mountWithTheme(
  91. onIncompatibleQueryMock.mock.calls[0][0](onCloseMock)
  92. );
  93. expect(errorsAlert.text()).toBe(
  94. 'An alert can’t use the metric count_unique(issue) just yet. Select another metric and try again.'
  95. );
  96. });
  97. it('should allow yAxis with a number as the parameter', () => {
  98. const eventView = EventView.fromSavedQuery({
  99. ...DEFAULT_EVENT_VIEW,
  100. query: 'event.type:transaction',
  101. yAxis: 'apdex(300)',
  102. fields: [...DEFAULT_EVENT_VIEW.fields, 'apdex(300)'],
  103. projects: [2],
  104. });
  105. expect(eventView.getYAxis()).toBe('apdex(300)');
  106. const wrapper = generateWrappedComponent(organization, eventView);
  107. wrapper.simulate('click');
  108. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(0);
  109. });
  110. it('should warn with multiple errors, missing event.type and project', () => {
  111. const eventView = EventView.fromSavedQuery({
  112. ...ALL_VIEWS.find(view => view.name === 'Errors by URL'),
  113. query: '',
  114. yAxis: 'count_unique(issue.id)',
  115. projects: [],
  116. });
  117. const wrapper = generateWrappedComponent(organization, eventView);
  118. wrapper.simulate('click');
  119. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(1);
  120. const errorsAlert = mountWithTheme(
  121. onIncompatibleQueryMock.mock.calls[0][0](onCloseMock)
  122. );
  123. expect(errorsAlert.text()).toContain('Yikes! That button didn’t work.');
  124. });
  125. it('should trigger success callback', () => {
  126. const eventView = EventView.fromSavedQuery({
  127. ...DEFAULT_EVENT_VIEW,
  128. query: 'event.type:error',
  129. projects: [2],
  130. });
  131. const wrapper = generateWrappedComponent(organization, eventView);
  132. wrapper.simulate('click');
  133. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(0);
  134. expect(onSuccessMock).toHaveBeenCalledTimes(1);
  135. });
  136. it('should allow alert to close', () => {
  137. const eventView = EventView.fromSavedQuery({
  138. ...DEFAULT_EVENT_VIEW,
  139. });
  140. const wrapper = generateWrappedComponent(organization, eventView);
  141. wrapper.simulate('click');
  142. expect(onIncompatibleQueryMock).toHaveBeenCalledTimes(1);
  143. const errorsAlert = mountWithTheme(
  144. onIncompatibleQueryMock.mock.calls[0][0](onCloseMock)
  145. );
  146. errorsAlert.find('[aria-label="Close"]').at(0).simulate('click');
  147. expect(onCloseMock).toHaveBeenCalledTimes(1);
  148. });
  149. it('disables the create alert button for members', async () => {
  150. const eventView = EventView.fromSavedQuery({
  151. ...DEFAULT_EVENT_VIEW,
  152. });
  153. const noAccessOrg = {
  154. ...organization,
  155. access: [],
  156. };
  157. const wrapper = generateWrappedComponent(noAccessOrg, eventView);
  158. const button = wrapper.find('button[aria-label="Create alert"]');
  159. expect(button.props()['aria-disabled']).toBe(true);
  160. });
  161. });