dashboardWidgetLibraryModal.spec.jsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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.getByText('Duration Distribution')).toBeInTheDocument();
  51. expect(screen.getByText('High Throughput Transactions')).toBeInTheDocument();
  52. expect(screen.getByText('LCP by Country')).toBeInTheDocument();
  53. expect(screen.getByText('Miserable Users')).toBeInTheDocument();
  54. expect(screen.getByText('Slow vs. Fast Transactions')).toBeInTheDocument();
  55. expect(screen.getByText('Issues For Review')).toBeInTheDocument();
  56. expect(screen.getByText('Top Unhandled Error Types')).toBeInTheDocument();
  57. expect(screen.getByText('Users Affected by Errors')).toBeInTheDocument();
  58. expect(screen.getByRole('button', {name: 'Widget Library new'})).toBeInTheDocument();
  59. expect(screen.getByRole('button', {name: 'Custom Widget'})).toBeInTheDocument();
  60. const button = screen.getByRole('button', {name: 'Custom Widget'});
  61. userEvent.click(button);
  62. expect(openAddDashboardWidgetModal).toHaveBeenCalledTimes(1);
  63. });
  64. it('submits selected widgets', function () {
  65. // Checking initial modal states
  66. const mockApply = jest.fn();
  67. const closeModal = jest.fn();
  68. container = mountModal({initialData}, mockApply, closeModal, [
  69. TestStubs.Widget(
  70. [{name: '', orderby: '', conditions: 'event.type:error', fields: ['count()']}],
  71. {
  72. title: 'Errors',
  73. interval: '1d',
  74. id: '1',
  75. displayType: 'line',
  76. }
  77. ),
  78. ]);
  79. // Select some widgets
  80. const allEvents = screen.queryByText('High Throughput Transactions');
  81. userEvent.click(allEvents);
  82. expect(screen.getByTestId('confirm-widgets')).toBeEnabled();
  83. userEvent.click(screen.getByTestId('confirm-widgets'));
  84. expect(mockApply).toHaveBeenCalledTimes(1);
  85. expect(mockApply).toHaveBeenCalledWith([
  86. expect.objectContaining({
  87. displayType: 'line',
  88. id: '1',
  89. interval: '1d',
  90. queries: [
  91. {
  92. conditions: 'event.type:error',
  93. fields: ['count()'],
  94. name: '',
  95. orderby: '',
  96. },
  97. ],
  98. title: 'Errors',
  99. }),
  100. expect.objectContaining({
  101. displayType: 'top_n',
  102. id: undefined,
  103. interval: '5m',
  104. description: 'Top 5 transactions with the largest volume.',
  105. queries: [
  106. {
  107. conditions: 'event.type:transaction',
  108. fields: ['transaction', 'count()'],
  109. name: '',
  110. orderby: '-count',
  111. },
  112. ],
  113. title: 'High Throughput Transactions',
  114. widgetType: 'discover',
  115. }),
  116. ]);
  117. expect(closeModal).toHaveBeenCalledTimes(1);
  118. });
  119. it('raises warning if widget not selected', function () {
  120. // Checking initial modal states
  121. const mockApply = jest.fn();
  122. const closeModal = jest.fn();
  123. container = mountModal({initialData}, mockApply, closeModal);
  124. expect(screen.queryByText(alertText)).not.toBeInTheDocument();
  125. userEvent.click(screen.getByTestId('confirm-widgets'));
  126. expect(mockApply).toHaveBeenCalledTimes(0);
  127. expect(closeModal).toHaveBeenCalledTimes(0);
  128. expect(screen.getByText(alertText)).toBeInTheDocument();
  129. });
  130. it('disables save button if widget limit is exceeded', function () {
  131. // Checking initial modal states
  132. const mockApply = jest.fn();
  133. const closeModal = jest.fn();
  134. types.MAX_WIDGETS = 1;
  135. container = mountModal({initialData}, mockApply, closeModal);
  136. // Select some widgets
  137. const allEvents = screen.queryByText('High Throughput Transactions');
  138. userEvent.click(allEvents);
  139. const totalErrors = screen.queryByText('Users Affected by Errors');
  140. userEvent.click(totalErrors);
  141. expect(screen.getByTestId('confirm-widgets')).toBeDisabled();
  142. });
  143. });