DashboardSearch.test.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
  2. import React from 'react';
  3. import { selectOptionInTest } from 'test/helpers/selectOptionInTest';
  4. import { selectors } from '@grafana/e2e-selectors';
  5. import { locationService, setEchoSrv } from '@grafana/runtime';
  6. import * as MockSearchSrv from 'app/core/services/__mocks__/search_srv';
  7. import { Echo } from 'app/core/services/echo/Echo';
  8. import * as SearchSrv from 'app/core/services/search_srv';
  9. import { searchResults } from '../testData';
  10. import { SearchLayout } from '../types';
  11. import { DashboardSearchOLD as DashboardSearch, Props } from './DashboardSearch';
  12. jest.mock('app/core/services/search_srv');
  13. // Typecast the mock search so the mock import is correctly recognised by TS
  14. // https://stackoverflow.com/a/53222290
  15. const { mockSearch } = SearchSrv as typeof MockSearchSrv;
  16. beforeEach(() => {
  17. jest.useFakeTimers('modern');
  18. mockSearch.mockClear();
  19. });
  20. afterEach(() => {
  21. jest.useRealTimers();
  22. });
  23. const setup = (testProps?: Partial<Props>) => {
  24. const props: any = {
  25. onCloseSearch: () => {},
  26. ...testProps,
  27. };
  28. render(<DashboardSearch {...props} />);
  29. jest.runOnlyPendingTimers();
  30. };
  31. /**
  32. * Need to wrap component render in async act and use jest.runAllTimers to test
  33. * calls inside useDebounce hook
  34. */
  35. describe('DashboardSearch', () => {
  36. beforeAll(() => {
  37. setEchoSrv(new Echo());
  38. });
  39. it('should call search api with default query when initialised', async () => {
  40. locationService.push('/');
  41. setup();
  42. await waitFor(() => screen.getByPlaceholderText('Search dashboards by name'));
  43. expect(mockSearch).toHaveBeenCalledTimes(1);
  44. expect(mockSearch).toHaveBeenCalledWith({
  45. query: '',
  46. tag: [],
  47. skipRecent: false,
  48. skipStarred: false,
  49. starred: false,
  50. folderIds: [],
  51. layout: SearchLayout.Folders,
  52. sort: undefined,
  53. prevSort: null,
  54. });
  55. });
  56. it('should call api with updated query on query change', async () => {
  57. locationService.push('/');
  58. setup();
  59. const input = await screen.findByPlaceholderText('Search dashboards by name');
  60. await act((async () => {
  61. await fireEvent.input(input, { target: { value: 'Test' } });
  62. jest.runOnlyPendingTimers();
  63. }) as any);
  64. expect(mockSearch).toHaveBeenCalledWith({
  65. query: 'Test',
  66. skipRecent: false,
  67. skipStarred: false,
  68. tag: [],
  69. starred: false,
  70. folderIds: [],
  71. layout: SearchLayout.Folders,
  72. sort: undefined,
  73. prevSort: null,
  74. });
  75. });
  76. it("should render 'No results' message when there are no dashboards", async () => {
  77. locationService.push('/');
  78. setup();
  79. const message = await screen.findByText('No dashboards matching your query were found.');
  80. expect(message).toBeInTheDocument();
  81. });
  82. it('should render search results', async () => {
  83. mockSearch.mockResolvedValueOnce(searchResults);
  84. locationService.push('/');
  85. setup();
  86. const section = await screen.findAllByTestId(selectors.components.Search.sectionV2);
  87. expect(section).toHaveLength(2);
  88. expect(screen.getAllByTestId(selectors.components.Search.itemsV2)).toHaveLength(1);
  89. });
  90. it('should call search with selected tags', async () => {
  91. locationService.push('/');
  92. setup();
  93. await waitFor(() => screen.getByLabelText('Tag filter'));
  94. const tagComponent = screen.getByLabelText('Tag filter');
  95. expect(tagComponent).toBeInTheDocument();
  96. tagComponent.focus();
  97. await waitFor(() => selectOptionInTest(tagComponent, 'tag1'));
  98. await waitFor(() =>
  99. expect(mockSearch).toHaveBeenCalledWith({
  100. query: '',
  101. skipRecent: false,
  102. skipStarred: false,
  103. tag: ['tag1'],
  104. starred: false,
  105. folderIds: [],
  106. layout: SearchLayout.Folders,
  107. sort: undefined,
  108. prevSort: null,
  109. })
  110. );
  111. });
  112. it('should call search api with provided search params', async () => {
  113. locationService.partial({ query: 'test query', tag: ['tag1'], sort: 'asc' });
  114. setup({});
  115. await waitFor(() => {
  116. expect(mockSearch).toHaveBeenCalledTimes(1);
  117. expect(mockSearch).toHaveBeenCalledWith(
  118. expect.objectContaining({
  119. query: 'test query',
  120. tag: ['tag1'],
  121. sort: 'asc',
  122. })
  123. );
  124. });
  125. });
  126. });