schemaHintsList.spec.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  3. import type {TagCollection} from 'sentry/types/group';
  4. import {FieldKind} from 'sentry/utils/fields';
  5. import SchemaHintsList from 'sentry/views/explore/components/schemaHintsList';
  6. import {PageParamsProvider} from 'sentry/views/explore/contexts/pageParamsContext';
  7. const mockStringTags: TagCollection = {
  8. stringTag1: {key: 'stringTag1', kind: FieldKind.TAG, name: 'stringTag1'},
  9. stringTag2: {key: 'stringTag2', kind: FieldKind.TAG, name: 'stringTag2'},
  10. };
  11. const mockNumberTags: TagCollection = {
  12. numberTag1: {key: 'numberTag1', kind: FieldKind.MEASUREMENT, name: 'numberTag1'},
  13. numberTag2: {key: 'numberTag2', kind: FieldKind.MEASUREMENT, name: 'numberTag2'},
  14. };
  15. jest.mock('sentry/utils/useNavigate', () => ({useNavigate: jest.fn()}));
  16. const mockNavigate = jest.fn();
  17. jest.mock('sentry/utils/useNavigate', () => ({
  18. useNavigate: () => mockNavigate,
  19. }));
  20. // Mock getBoundingClientRect for container
  21. jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(function (
  22. this: HTMLElement
  23. ) {
  24. // Mock individual hint items
  25. if (this.hasAttribute('data-type')) {
  26. return {
  27. width: 200,
  28. right: 200,
  29. left: 0,
  30. top: 0,
  31. bottom: 100,
  32. height: 100,
  33. x: 0,
  34. y: 0,
  35. toJSON: () => {},
  36. };
  37. }
  38. return {
  39. width: 1000,
  40. right: 1000,
  41. left: 0,
  42. top: 0,
  43. bottom: 100,
  44. height: 100,
  45. x: 0,
  46. y: 0,
  47. toJSON: () => {},
  48. };
  49. });
  50. describe('SchemaHintsList', () => {
  51. const {organization, router} = initializeOrg({
  52. router: {
  53. location: {
  54. query: {
  55. query: '',
  56. },
  57. },
  58. },
  59. });
  60. beforeEach(() => {
  61. mockNavigate.mockClear();
  62. });
  63. it('should render', () => {
  64. render(
  65. <SchemaHintsList
  66. stringTags={mockStringTags}
  67. numberTags={mockNumberTags}
  68. supportedAggregates={[]}
  69. />
  70. );
  71. expect(screen.getByText('stringTag1 is ...')).toBeInTheDocument();
  72. expect(screen.getByText('stringTag2 is ...')).toBeInTheDocument();
  73. expect(screen.getByText('numberTag1 > ...')).toBeInTheDocument();
  74. expect(screen.getByText('numberTag2 > ...')).toBeInTheDocument();
  75. expect(screen.getByText('See full list')).toBeInTheDocument();
  76. });
  77. it('should add hint to query when clicked', async () => {
  78. render(
  79. <PageParamsProvider>
  80. <SchemaHintsList
  81. stringTags={mockStringTags}
  82. numberTags={mockNumberTags}
  83. supportedAggregates={[]}
  84. />
  85. </PageParamsProvider>
  86. );
  87. const stringTag1Hint = screen.getByText('stringTag1 is ...');
  88. await userEvent.click(stringTag1Hint);
  89. expect(mockNavigate).toHaveBeenCalledWith(
  90. expect.objectContaining({query: {query: 'stringTag1:""'}})
  91. );
  92. });
  93. it('should render loading indicator when isLoading is true', () => {
  94. render(
  95. <PageParamsProvider>
  96. <SchemaHintsList
  97. stringTags={{}}
  98. numberTags={{}}
  99. supportedAggregates={[]}
  100. isLoading
  101. />
  102. </PageParamsProvider>
  103. );
  104. expect(screen.getByTestId('loading-indicator')).toBeInTheDocument();
  105. });
  106. it('should open drawer when see full list is clicked', async () => {
  107. render(
  108. <PageParamsProvider>
  109. <SchemaHintsList
  110. stringTags={mockStringTags}
  111. numberTags={mockNumberTags}
  112. supportedAggregates={[]}
  113. />
  114. </PageParamsProvider>,
  115. {organization, router}
  116. );
  117. const seeFullList = screen.getByText('See full list');
  118. await userEvent.click(seeFullList);
  119. expect(screen.getByLabelText('Schema Hints Drawer')).toBeInTheDocument();
  120. expect(screen.getByText('Filter Attributes')).toBeInTheDocument();
  121. Object.values(mockStringTags).forEach(tag => {
  122. expect(screen.getByText(tag.key)).toBeInTheDocument();
  123. });
  124. Object.values(mockNumberTags).forEach(tag => {
  125. expect(screen.getByText(tag.key)).toBeInTheDocument();
  126. });
  127. });
  128. it('should add hint to query when clicked on drawer', async () => {
  129. render(
  130. <PageParamsProvider>
  131. <SchemaHintsList
  132. stringTags={mockStringTags}
  133. numberTags={mockNumberTags}
  134. supportedAggregates={[]}
  135. />
  136. </PageParamsProvider>,
  137. {organization, router}
  138. );
  139. const seeFullList = screen.getByText('See full list');
  140. await userEvent.click(seeFullList);
  141. expect(screen.getByLabelText('Schema Hints Drawer')).toBeInTheDocument();
  142. const stringTag1Checkbox = screen.getByText('stringTag1');
  143. await userEvent.click(stringTag1Checkbox);
  144. expect(mockNavigate).toHaveBeenCalledWith(
  145. expect.objectContaining({query: {query: 'stringTag1:""'}})
  146. );
  147. const numberTag1Checkbox = screen.getByText('numberTag1');
  148. await userEvent.click(numberTag1Checkbox);
  149. expect(mockNavigate).toHaveBeenCalledWith(
  150. expect.objectContaining({query: {query: 'numberTag1:>0'}})
  151. );
  152. });
  153. it('should remove hint from query when checkbox is unchecked on drawer', async () => {
  154. render(
  155. <PageParamsProvider>
  156. <SchemaHintsList
  157. stringTags={mockStringTags}
  158. numberTags={mockNumberTags}
  159. supportedAggregates={[]}
  160. />
  161. </PageParamsProvider>,
  162. {
  163. organization,
  164. router: {
  165. ...router,
  166. location: {...router.location, query: {query: 'stringTag1:"" numberTag1:>0'}},
  167. },
  168. }
  169. );
  170. const seeFullList = screen.getByText('See full list');
  171. await userEvent.click(seeFullList);
  172. const stringTag1Checkbox = screen.getByText('stringTag1');
  173. await userEvent.click(stringTag1Checkbox);
  174. expect(mockNavigate).toHaveBeenCalledWith(
  175. expect.objectContaining({query: {query: 'numberTag1:>0'}})
  176. );
  177. });
  178. it('should keep drawer open when query is updated', async () => {
  179. render(
  180. <PageParamsProvider>
  181. <SchemaHintsList
  182. stringTags={mockStringTags}
  183. numberTags={mockNumberTags}
  184. supportedAggregates={[]}
  185. />
  186. </PageParamsProvider>,
  187. {organization, router}
  188. );
  189. const seeFullList = screen.getByText('See full list');
  190. await userEvent.click(seeFullList);
  191. const stringTag1Checkbox = screen.getByText('stringTag1');
  192. await userEvent.click(stringTag1Checkbox);
  193. router.push({
  194. ...router.location,
  195. query: {query: 'stringTag1:""'},
  196. });
  197. expect(screen.getByLabelText('Schema Hints Drawer')).toBeInTheDocument();
  198. });
  199. });