测试去抖函数 React - React-testing-library
Testing debounced function React - React-testing-library
我有以下组件
import React, { useState, useEffect } from 'react';
import { FiSearch } from 'react-icons/fi';
import { useProducts } from '../../hooks';
export default function SearchBar() {
const [query, setQuery] = useState('');
const [debounced, setDebounced] = useState('');
useEffect(() => {
const timeout = setTimeout(() => {
setDebounced(query);
}, 300);
return () => {
clearTimeout(timeout);
};
}, [query]);
const handleChange = (e) => {
e.preventDefault();
setQuery(e.target.value);
};
useProducts(debounced);
return (
<div className="search-form">
<FiSearch className="search-form__icon" />
<input
type="text"
className="search-form__input"
placeholder="Search for brands or shoes..."
onChange={handleChange}
value={query}
/>
</div>
);
}
我想测试输入后 300 毫秒后是否真的调用了 useProducts(debounced);
。遗憾的是,我不知道从哪里开始,希望有人能提供帮助。
我建议使用 @testing-library/user-event
在 <input>
元素上输入,因为它更接近于模拟用户的触发事件。
至于测试,您应该模拟 useProducts
实现以断言它被正确调用。
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import SearchBar from '<path-to-search-bar-component>'; // Update this accordingly
import * as hooks from '<path-to-hooks-file>'; // Update this accordingly
describe('Test <SearchBar />', () => {
it('should call useProducts after 300ms after typing', async () => {
const mockHook = jest.fn();
jest.spyOn(hooks, 'useProducts').mockImplementation(mockHook);
render(<SearchBar />);
const input = screen.getByPlaceholderText('Search for brands or shoes...');
userEvent.type(input, 'A');
expect(mockHook).not.toHaveBeenCalledWith('A'); // It won't be called immediately
await waitFor(() => expect(mockHook).toHaveBeenCalledWith('A'), { timeout: 350 }); // But will get called within 350ms
jest.clearAllMocks();
});
});
我有以下组件
import React, { useState, useEffect } from 'react';
import { FiSearch } from 'react-icons/fi';
import { useProducts } from '../../hooks';
export default function SearchBar() {
const [query, setQuery] = useState('');
const [debounced, setDebounced] = useState('');
useEffect(() => {
const timeout = setTimeout(() => {
setDebounced(query);
}, 300);
return () => {
clearTimeout(timeout);
};
}, [query]);
const handleChange = (e) => {
e.preventDefault();
setQuery(e.target.value);
};
useProducts(debounced);
return (
<div className="search-form">
<FiSearch className="search-form__icon" />
<input
type="text"
className="search-form__input"
placeholder="Search for brands or shoes..."
onChange={handleChange}
value={query}
/>
</div>
);
}
我想测试输入后 300 毫秒后是否真的调用了 useProducts(debounced);
。遗憾的是,我不知道从哪里开始,希望有人能提供帮助。
我建议使用 @testing-library/user-event
在 <input>
元素上输入,因为它更接近于模拟用户的触发事件。
至于测试,您应该模拟 useProducts
实现以断言它被正确调用。
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import SearchBar from '<path-to-search-bar-component>'; // Update this accordingly
import * as hooks from '<path-to-hooks-file>'; // Update this accordingly
describe('Test <SearchBar />', () => {
it('should call useProducts after 300ms after typing', async () => {
const mockHook = jest.fn();
jest.spyOn(hooks, 'useProducts').mockImplementation(mockHook);
render(<SearchBar />);
const input = screen.getByPlaceholderText('Search for brands or shoes...');
userEvent.type(input, 'A');
expect(mockHook).not.toHaveBeenCalledWith('A'); // It won't be called immediately
await waitFor(() => expect(mockHook).toHaveBeenCalledWith('A'), { timeout: 350 }); // But will get called within 350ms
jest.clearAllMocks();
});
});