dashboardWidgetLibraryModal.spec.jsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  3. import {openAddDashboardWidgetModal} from 'sentry/actionCreators/modal';
  4. import DashboardWidgetLibraryModal from 'sentry/components/modals/dashboardWidgetLibraryModal';
  5. import * as types from 'sentry/views/dashboardsV2/types';
  6. const stubEl = props => <div>{props.children}</div>;
  7. const alertText =
  8. 'Please select at least one Widget from our Library. Alternatively, you can build a custom widget from scratch.';
  9. jest.mock('sentry/actionCreators/modal', () => ({
  10. openAddDashboardWidgetModal: jest.fn(),
  11. }));
  12. function mountModal({initialData}, onApply, closeModal, widgets = []) {
  13. const routerContext = TestStubs.routerContext();
  14. return mountWithTheme(
  15. <DashboardWidgetLibraryModal
  16. Header={stubEl}
  17. Footer={stubEl}
  18. Body={stubEl}
  19. organization={initialData.organization}
  20. dashboard={TestStubs.Dashboard(widgets, {
  21. id: '1',
  22. title: 'Dashboard 1',
  23. dateCreated: '2021-04-19T13:13:23.962105Z',
  24. createdBy: {id: '1'},
  25. widgetDisplay: [],
  26. })}
  27. onAddWidget={onApply}
  28. closeModal={closeModal}
  29. />,
  30. {context: routerContext}
  31. );
  32. }
  33. describe('Modals -> DashboardWidgetLibraryModal', function () {
  34. const initialData = initializeOrg({
  35. organization: {
  36. features: ['widget-library'],
  37. apdexThreshold: 400,
  38. },
  39. });
  40. let container;
  41. afterEach(() => {
  42. MockApiClient.clearMockResponses();
  43. if (container) {
  44. container.unmount();
  45. }
  46. });
  47. it('opens modal and renders correctly', async function () {
  48. // Checking initial modal states
  49. container = mountModal({initialData});
  50. expect(screen.queryByText('Duration Distribution')).toBeInTheDocument();
  51. expect(screen.queryByText('High Throughput Transactions')).toBeInTheDocument();
  52. expect(screen.queryByText('LCP by Country')).toBeInTheDocument();
  53. expect(screen.queryByText('Miserable Users')).toBeInTheDocument();
  54. expect(screen.queryByText('Slow vs Fast Transactions')).toBeInTheDocument();
  55. expect(screen.queryByText('Latest Unresolved Issues')).toBeInTheDocument();
  56. expect(screen.queryByText('Top Unhandled Error Types')).toBeInTheDocument();
  57. expect(screen.queryByText('Users Affected by Errors')).toBeInTheDocument();
  58. expect(
  59. screen.getByRole('button', {name: 'Widget Library beta', current: true})
  60. ).toBeInTheDocument();
  61. expect(
  62. screen.getByRole('button', {name: 'Custom Widget', current: false})
  63. ).toBeInTheDocument();
  64. const button = screen.getByRole('button', {name: 'Custom Widget'});
  65. userEvent.click(button);
  66. expect(openAddDashboardWidgetModal).toHaveBeenCalledTimes(1);
  67. });
  68. it('submits selected widgets', function () {
  69. // Checking initial modal states
  70. const mockApply = jest.fn();
  71. const closeModal = jest.fn();
  72. container = mountModal({initialData}, mockApply, closeModal, [
  73. TestStubs.Widget(
  74. [{name: '', orderby: '', conditions: 'event.type:error', fields: ['count()']}],
  75. {
  76. title: 'Errors',
  77. interval: '1d',
  78. id: '1',
  79. displayType: 'line',
  80. }
  81. ),
  82. ]);
  83. // Select some widgets
  84. const allEvents = screen.queryByText('High Throughput Transactions');
  85. userEvent.click(allEvents);
  86. expect(screen.getByTestId('confirm-widgets')).toBeEnabled();
  87. userEvent.click(screen.getByTestId('confirm-widgets'));
  88. expect(mockApply).toHaveBeenCalledTimes(1);
  89. expect(mockApply).toHaveBeenCalledWith([
  90. expect.objectContaining({
  91. displayType: 'line',
  92. id: '1',
  93. interval: '1d',
  94. queries: [
  95. {
  96. conditions: 'event.type:error',
  97. fields: ['count()'],
  98. name: '',
  99. orderby: '',
  100. },
  101. ],
  102. title: 'Errors',
  103. }),
  104. {
  105. displayType: 'top_n',
  106. id: undefined,
  107. interval: '5m',
  108. description: 'Top 5 transactions with the largest volume.',
  109. queries: [
  110. {
  111. conditions: '!event.type:error',
  112. fields: ['transaction', 'count()'],
  113. name: '',
  114. orderby: '-count',
  115. },
  116. ],
  117. title: 'High Throughput Transactions',
  118. widgetType: 'discover',
  119. },
  120. ]);
  121. expect(closeModal).toHaveBeenCalledTimes(1);
  122. });
  123. it('raises warning if widget not selected', function () {
  124. // Checking initial modal states
  125. const mockApply = jest.fn();
  126. const closeModal = jest.fn();
  127. container = mountModal({initialData}, mockApply, closeModal);
  128. expect(screen.queryByText(alertText)).not.toBeInTheDocument();
  129. userEvent.click(screen.getByTestId('confirm-widgets'));
  130. expect(mockApply).toHaveBeenCalledTimes(0);
  131. expect(closeModal).toHaveBeenCalledTimes(0);
  132. expect(screen.getByText(alertText)).toBeInTheDocument();
  133. });
  134. it('disables save button if widget limit is exceeded', function () {
  135. // Checking initial modal states
  136. const mockApply = jest.fn();
  137. const closeModal = jest.fn();
  138. types.MAX_WIDGETS = 1;
  139. container = mountModal({initialData}, mockApply, closeModal);
  140. // Select some widgets
  141. const allEvents = screen.queryByText('High Throughput Transactions');
  142. userEvent.click(allEvents);
  143. const totalErrors = screen.queryByText('Users Affected by Errors');
  144. userEvent.click(totalErrors);
  145. expect(screen.getByTestId('confirm-widgets')).toBeDisabled();
  146. });
  147. });