columnEditorModal.spec.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import {act, renderGlobalModal, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  2. import {openModal} from 'sentry/actionCreators/modal';
  3. import type {TagCollection} from 'sentry/types/group';
  4. import {ColumnEditorModal} from 'sentry/views/explore/tables/columnEditorModal';
  5. const stringTags: TagCollection = {
  6. id: {
  7. key: 'id',
  8. name: 'id',
  9. },
  10. project: {
  11. key: 'project',
  12. name: 'project',
  13. },
  14. 'span.op': {
  15. key: 'span.op',
  16. name: 'span.op',
  17. },
  18. };
  19. const numberTags: TagCollection = {
  20. 'span.duration': {
  21. key: 'span.duration',
  22. name: 'span.duration',
  23. },
  24. };
  25. describe('ColumnEditorModal', function () {
  26. beforeEach(function () {
  27. // without this the `CompactSelect` component errors with a bunch of async updates
  28. jest.spyOn(console, 'error').mockImplementation();
  29. });
  30. it('allows closes modal on apply', async function () {
  31. const onClose = jest.fn();
  32. renderGlobalModal();
  33. act(() => {
  34. openModal(
  35. modalProps => (
  36. <ColumnEditorModal
  37. {...modalProps}
  38. columns={['id', 'project']}
  39. onColumnsChange={() => {}}
  40. stringTags={stringTags}
  41. numberTags={numberTags}
  42. />
  43. ),
  44. {onClose}
  45. );
  46. });
  47. expect(onClose).not.toHaveBeenCalled();
  48. await userEvent.click(screen.getByRole('button', {name: 'Apply'}));
  49. expect(onClose).toHaveBeenCalled();
  50. });
  51. it('allows deleting a column', async function () {
  52. const onColumnsChange = jest.fn();
  53. renderGlobalModal();
  54. act(() => {
  55. openModal(
  56. modalProps => (
  57. <ColumnEditorModal
  58. {...modalProps}
  59. columns={['id', 'project']}
  60. onColumnsChange={onColumnsChange}
  61. stringTags={stringTags}
  62. numberTags={numberTags}
  63. />
  64. ),
  65. {onClose: jest.fn()}
  66. );
  67. });
  68. const columns1 = ['id', 'project'];
  69. screen.getAllByTestId('editor-column').forEach((column, i) => {
  70. expect(column).toHaveTextContent(columns1[i]);
  71. });
  72. await userEvent.click(screen.getAllByLabelText('Remove Column')[0]);
  73. const columns2 = ['project'];
  74. screen.getAllByTestId('editor-column').forEach((column, i) => {
  75. expect(column).toHaveTextContent(columns2[i]);
  76. });
  77. // only 1 column remaining, disable the delete option
  78. expect(screen.getByLabelText('Remove Column')).toBeDisabled();
  79. await userEvent.click(screen.getByRole('button', {name: 'Apply'}));
  80. expect(onColumnsChange).toHaveBeenCalledWith(['project']);
  81. });
  82. it('allows adding a column', async function () {
  83. const onColumnsChange = jest.fn();
  84. renderGlobalModal();
  85. act(() => {
  86. openModal(
  87. modalProps => (
  88. <ColumnEditorModal
  89. {...modalProps}
  90. columns={['id', 'project']}
  91. onColumnsChange={onColumnsChange}
  92. stringTags={stringTags}
  93. numberTags={numberTags}
  94. />
  95. ),
  96. {onClose: jest.fn()}
  97. );
  98. });
  99. const columns1 = ['id', 'project'];
  100. screen.getAllByTestId('editor-column').forEach((column, i) => {
  101. expect(column).toHaveTextContent(columns1[i]);
  102. });
  103. await userEvent.click(screen.getByRole('button', {name: 'Add a Column'}));
  104. const columns2 = ['id', 'project', 'None'];
  105. screen.getAllByTestId('editor-column').forEach((column, i) => {
  106. expect(column).toHaveTextContent(columns2[i]);
  107. });
  108. const options = ['id', 'project', 'span.duration', 'span.op'];
  109. await userEvent.click(screen.getByRole('button', {name: 'Column None'}));
  110. const columnOptions = await screen.findAllByRole('option');
  111. columnOptions.forEach((option, i) => {
  112. expect(option).toHaveTextContent(options[i]);
  113. });
  114. await userEvent.click(columnOptions[3]);
  115. const columns3 = ['id', 'project', 'span.op'];
  116. screen.getAllByTestId('editor-column').forEach((column, i) => {
  117. expect(column).toHaveTextContent(columns3[i]);
  118. });
  119. await userEvent.click(screen.getByRole('button', {name: 'Apply'}));
  120. expect(onColumnsChange).toHaveBeenCalledWith(['id', 'project', 'span.op']);
  121. });
  122. it('allows changing a column', async function () {
  123. const onColumnsChange = jest.fn();
  124. renderGlobalModal();
  125. act(() => {
  126. openModal(
  127. modalProps => (
  128. <ColumnEditorModal
  129. {...modalProps}
  130. columns={['id', 'project']}
  131. onColumnsChange={onColumnsChange}
  132. stringTags={stringTags}
  133. numberTags={numberTags}
  134. />
  135. ),
  136. {onClose: jest.fn()}
  137. );
  138. });
  139. const columns1 = ['id', 'project'];
  140. screen.getAllByTestId('editor-column').forEach((column, i) => {
  141. expect(column).toHaveTextContent(columns1[i]);
  142. });
  143. const options = ['id', 'project', 'span.duration', 'span.op'];
  144. await userEvent.click(screen.getByRole('button', {name: 'Column project'}));
  145. const columnOptions = await screen.findAllByRole('option');
  146. columnOptions.forEach((option, i) => {
  147. expect(option).toHaveTextContent(options[i]);
  148. });
  149. await userEvent.click(columnOptions[3]);
  150. const columns2 = ['id', 'span.op'];
  151. screen.getAllByTestId('editor-column').forEach((column, i) => {
  152. expect(column).toHaveTextContent(columns2[i]);
  153. });
  154. await userEvent.click(screen.getByRole('button', {name: 'Apply'}));
  155. expect(onColumnsChange).toHaveBeenCalledWith(['id', 'span.op']);
  156. });
  157. });