Merge pull request #9164 from backstage/search/filter-timers

Use fake timers to test search filter hooks debounce
This commit is contained in:
Otto Sichert
2022-01-25 16:59:17 +01:00
committed by GitHub
@@ -16,11 +16,13 @@
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);