searchBar.spec.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  3. import TagStore from 'sentry/stores/tagStore';
  4. import IssueListSearchBar from 'sentry/views/issueList/searchBar';
  5. describe('IssueListSearchBar', function () {
  6. let recentSearchMock;
  7. let defaultProps;
  8. const {routerContext, organization} = initializeOrg();
  9. beforeEach(function () {
  10. TagStore.reset();
  11. TagStore.loadTagsSuccess(TestStubs.Tags());
  12. defaultProps = {
  13. organization,
  14. query: '',
  15. onSearch: jest.fn(),
  16. };
  17. recentSearchMock = MockApiClient.addMockResponse({
  18. url: '/organizations/org-slug/recent-searches/',
  19. method: 'GET',
  20. body: [],
  21. });
  22. });
  23. afterEach(function () {
  24. MockApiClient.clearMockResponses();
  25. });
  26. describe('updateAutoCompleteItems()', function () {
  27. it('sets state with complete tag', function () {
  28. const tagValuesMock = MockApiClient.addMockResponse({
  29. url: '/organizations/org-slug/tags/url/values/',
  30. method: 'GET',
  31. body: [],
  32. });
  33. render(<IssueListSearchBar {...defaultProps} />, {
  34. context: routerContext,
  35. });
  36. userEvent.type(screen.getByRole('textbox'), 'url:"fu"');
  37. expect(tagValuesMock).toHaveBeenLastCalledWith(
  38. expect.anything(),
  39. expect.objectContaining({
  40. query: expect.objectContaining({
  41. query: 'fu',
  42. }),
  43. })
  44. );
  45. expect(screen.getByTestId('smart-search-dropdown')).toBeInTheDocument();
  46. expect(screen.queryByRole('listitem')).not.toBeInTheDocument();
  47. });
  48. it('sets state when value has colon', function () {
  49. const tagValuesMock = MockApiClient.addMockResponse({
  50. url: '/organizations/org-slug/tags/url/values/',
  51. method: 'GET',
  52. body: [],
  53. });
  54. render(<IssueListSearchBar {...defaultProps} />, {
  55. context: routerContext,
  56. });
  57. userEvent.type(screen.getByRole('textbox'), 'url:');
  58. expect(tagValuesMock).toHaveBeenCalled();
  59. });
  60. it('does not request values when tag is `timesSeen`', function () {
  61. const tagValuesMock = MockApiClient.addMockResponse({
  62. url: '/organizations/org-slug/tags/url/values/',
  63. method: 'GET',
  64. body: [],
  65. });
  66. render(<IssueListSearchBar {...defaultProps} />, {
  67. context: routerContext,
  68. });
  69. userEvent.type(screen.getByRole('textbox'), 'timesSeen:');
  70. expect(tagValuesMock).not.toHaveBeenCalled();
  71. });
  72. });
  73. describe('Recent Searches', function () {
  74. it('saves search query as a recent search', function () {
  75. const tagValuesMock = MockApiClient.addMockResponse({
  76. url: '/organizations/org-slug/tags/url/values/',
  77. method: 'GET',
  78. body: [],
  79. });
  80. const saveRecentSearch = MockApiClient.addMockResponse({
  81. url: '/organizations/org-slug/recent-searches/',
  82. method: 'POST',
  83. body: {},
  84. });
  85. const onSearch = jest.fn();
  86. render(<IssueListSearchBar {...defaultProps} onSearch={onSearch} />, {
  87. context: routerContext,
  88. });
  89. userEvent.type(screen.getByRole('textbox'), 'url:"fu"');
  90. expect(tagValuesMock).toHaveBeenLastCalledWith(
  91. expect.anything(),
  92. expect.objectContaining({
  93. query: expect.objectContaining({
  94. query: 'fu',
  95. }),
  96. })
  97. );
  98. expect(screen.getByTestId('smart-search-dropdown')).toBeInTheDocument();
  99. expect(screen.queryByRole('listitem')).not.toBeInTheDocument();
  100. userEvent.keyboard('{Enter}');
  101. expect(onSearch).toHaveBeenCalledWith('url:"fu"');
  102. expect(saveRecentSearch).toHaveBeenCalledWith(
  103. expect.anything(),
  104. expect.objectContaining({
  105. data: {
  106. query: 'url:"fu"',
  107. type: 0,
  108. },
  109. })
  110. );
  111. });
  112. it('queries for recent searches', function () {
  113. MockApiClient.addMockResponse({
  114. url: '/organizations/org-slug/tags/url/values/',
  115. method: 'GET',
  116. body: [],
  117. });
  118. render(<IssueListSearchBar {...defaultProps} />, {context: routerContext});
  119. userEvent.type(screen.getByRole('textbox'), 'is:');
  120. expect(recentSearchMock).toHaveBeenCalledWith(
  121. expect.anything(),
  122. expect.objectContaining({
  123. query: {
  124. query: 'is:',
  125. limit: 3,
  126. type: 0,
  127. },
  128. })
  129. );
  130. });
  131. it('cycles through keyboard navigation for selection', async function () {
  132. MockApiClient.addMockResponse({
  133. url: '/organizations/org-slug/tags/device.orientation/values/',
  134. method: 'GET',
  135. body: [],
  136. });
  137. render(<IssueListSearchBar {...defaultProps} />, {context: routerContext});
  138. const textarea = screen.getByRole('textbox');
  139. // Keyboard navigate to first item and select
  140. userEvent.type(textarea, 't');
  141. await waitFor(() =>
  142. expect(screen.getAllByTestId('search-autocomplete-item')[0]).toBeInTheDocument()
  143. );
  144. userEvent.keyboard('{ArrowDown}{Tab}');
  145. expect(textarea).not.toHaveValue('t');
  146. const firstItemValue = textarea.textContent;
  147. // Keyboard navigate to second item and select
  148. userEvent.keyboard('{selectall}{backspace}t');
  149. await waitFor(() =>
  150. expect(screen.getAllByTestId('search-autocomplete-item')[0]).toBeInTheDocument()
  151. );
  152. userEvent.keyboard('{ArrowDown}{ArrowDown}{Tab}');
  153. expect(textarea).not.toHaveValue(firstItemValue);
  154. // Keyboard navigate to second item, then back to first item and select
  155. userEvent.keyboard('{selectall}{backspace}t');
  156. await waitFor(() =>
  157. expect(screen.getAllByTestId('search-autocomplete-item')[0]).toBeInTheDocument()
  158. );
  159. userEvent.keyboard('{ArrowDown}{ArrowDown}{ArrowUp}{Tab}');
  160. expect(textarea).toHaveValue(firstItemValue);
  161. });
  162. });
  163. });