message: Use fake timers to test search filter hooks debounce
diff: import React from 'react';
  import { ApiProvider } from '@backstage/core-app-api';
  import { TestApiRegistry } from '@backstage/test-utils';
  -import { act, renderHook } from '@testing-library/react-hooks';
  +import { renderHook } from '@testing-library/react-hooks';
  import { SearchContextProvider, useSearch } from '../SearchContext';
  import { useDefaultFilterValue, useAsyncFilterValues } from './hooks';
  import { searchApiRef } from '../../apis';
  +jest.useFakeTimers();
  +
  describe('SearchFilter.hooks', () => {
  describe('useDefaultFilterValue', () => {
  const query = jest.fn().mockResolvedValue({});
  @@ -225,11 +227,12 @@ describe('SearchFilter.hooks', () => {
  const expectedValues = ['value1', 'value2'];
  const asyncFn = () => Promise.resolve(expectedValues);
  const { result, waitForNextUpdate } = renderHook(() =>
  - useAsyncFilterValues(asyncFn, '', undefined, 1),
  + useAsyncFilterValues(asyncFn, '', undefined, 1000),
  );
  expect(result.current.loading).toEqual(true);
  + jest.runAllTimers();
  await waitForNextUpdate();
  expect(result.current.loading).toEqual(false);
  @@ -239,16 +242,16 @@ describe('SearchFilter.hooks', () => {
  it('should debounce method invocation', async () => {
  const expectedValues = ['value1', 'value2'];
  const asyncFn = jest.fn().mockResolvedValue(expectedValues);
  - renderHook(() => useAsyncFilterValues(asyncFn, '', undefined, 10));
  + renderHook(() => useAsyncFilterValues(asyncFn, '', undefined, 1000));
  expect(asyncFn).not.toHaveBeenCalled();
  - // Allow 6 milliseconds to pass.
  - await act(() => new Promise(resolve => setTimeout(resolve, 6)));
  + // Advance timers by 600ms
  + jest.advanceTimersByTime(600);
  expect(asyncFn).not.toHaveBeenCalled();
  - // Allow an additional 6 milliseconds to pass.
  - await act(() => new Promise(resolve => setTimeout(resolve, 6)));
  + // Another 600ms to exceed the 1000ms debounce
  + jest.advanceTimersByTime(600);
  expect(asyncFn).toHaveBeenCalled();
  });
  @@ -258,16 +261,18 @@ describe('SearchFilter.hooks', () => {
  .mockImplementation((x: string) => Promise.resolve([x]));
  const { rerender, waitForNextUpdate } = renderHook(
  (props: { inputValue: string } = { inputValue: '' }) =>
  - useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1),
  + useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1000),
  );
  expect(asyncFn).not.toHaveBeenCalled();
  + jest.runAllTimers();
  await waitForNextUpdate();
  expect(asyncFn).toHaveBeenCalledTimes(1);
  expect(asyncFn).toHaveBeenCalledWith('');
  // Re-render with different input value.
  rerender({ inputValue: 'somethingElse' });
  + jest.runAllTimers();
  await waitForNextUpdate();
  expect(asyncFn).toHaveBeenCalledTimes(2);
  expect(asyncFn).toHaveBeenLastCalledWith('somethingElse');
  @@ -278,10 +283,12 @@ describe('SearchFilter.hooks', () => {
  const asyncFn = jest.fn().mockResolvedValue(expectedValues);
  const { rerender, waitForNextUpdate } = renderHook(
  (props: { inputValue: string } = { inputValue: '' }) =>
  - useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1),
  + useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1000),
  );
  expect(asyncFn).not.toHaveBeenCalled();
  +
  + jest.runAllTimers();
  await waitForNextUpdate();
  expect(asyncFn).toHaveBeenCalledTimes(1);
  