РЕДАКТИРОВАТЬ: Я нашел решение, исходя из этого видео от Кента С. Доддса.
Просто оберните вызовы jest.advanceTimersByTime в функцию акта.
Итак, это:
jest.advanceTimersByTime(510);
становится:
act(()=>jest.advanceTimersByTime(510));
Я реализовал простой пользовательский хук, чтобы отменить обновление значения.
Вот код:
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
Клиент этого хука выглядит примерно так (очень упрощенно):
function Search(props) {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);
// doing something useful with debouncedSearchTerm....
// ...
// ...
}
Итак, я пытаюсь проверить ловушку с кодом ниже:
import { renderHook, act } from 'react-hooks-testing-library';
import useDebounce from '../useDebounce';
jest.useFakeTimers();
it.only('should update value after specified delay', () => {
const { result, rerender } = renderHook(
({ value, delay }) => useDebounce(value, delay),
{ initialProps: { value: '', delay: 500 } }
);
expect(result.current).toBe('');
jest.advanceTimersByTime(510);
expect(result.current).toBe('');
rerender({ value: 'Hello World', delay: 500 });
expect(result.current).toBe('');
jest.advanceTimersByTime(498);
expect(result.current).toBe('');
jest.advanceTimersByTime(3);
expect(result.current).toBe('Hello World');
});
Хотя, тест пройден, я получаю следующее предупреждение:
console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:102
Warning: An update to TestHook inside a test was not wrapped in act(...). When testing, code that causes React state updates should be wrapped into act(...): act(() => { /* fire events that update state */ }); /* assert on the output */ This ensures that you're testing the behavior the user would see in the browser. Learn more at..... in TestHook in Suspense
Я понимаю, что если я собираюсь вызвать функцию для обновления внутреннего состояния ловушки (например, increment () ловушки useCounter), я должен сделать это в act функции, как указано в документации.
Но хук useDebounce, который я реализовал, изменяет состояние с помощью внутреннего useEffect, которое запускается всякий раз, когда изменяется значение или задержка.
Как мне избавиться от этого предупреждения? Что-то не так с моим кодом? Я забыл добавить что-нибудь в тестовый код?
Пожалуйста, помогите!