I have a search component that filters among fetched data. However, I see that it is always an empty string.
How can I test the updating and the display of the todos correctly?
here the code to be tested:
const [todos, setTodos] = useState<Todos>({ all: [], searched: null });
const [search, setSearch] = useState("");
useEffect(() => {
fetch("todos")
.then((response) => {
return response.json();
})
.then((response) => {
setTodos((todos) => ({ ...todos, all: response }));
})
.catch((e) => console.error(e));
}, []);
useEffect(()=>{ if (search) {
setTodos((todos) => ({
...todos,
searched: todos.all.filter((item) =>
item.title.toLowerCase().includes(search.toLowerCase())
),
}));
}
}, [search]);
const handleOnChangeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
};
<div className="search-container">
<input
className="search"
value={search}
onChange={handleOnChangeInput}
placeholder="Search todo..."
data-testid="search"
type="text"
/>
<button className="btn-delete" onClick={() => setSearch("")}>
Clear search
</button>
</div>
<div className="todos" data-testid="todos">
{(todos.searched && todos.searched.length > 0
? todos.searched
: todos.all
).map(({ id, title, completed }) => (
<div
data-testid="todo"
key={id}
className="todo"
onClick={() => handleOnClickTodo(id)}
>
{completed ? <p className="tick">✅</p> : null}
<p>{title}</p>
<button
className="btn-delete"
onClick={(event) => handleOnClickDelete(event, id)}
>
Delete
</button>
</div>
))}
</div>
Here is the test:
const mockResponse = [
{
userId: 1,
id: 1,
title: "Todo S",
completed: false,
},
{
userId: 1,
id: 2,
title: "Todo A",
completed: true,
},
];
beforeEach(() => {
jest.spyOn(global, "fetch" as any).mockResolvedValue({
json: () => mockResponse,
});
});
afterEach(() => {
jest.restoreAllMocks();
});
it("should filter todos based on search input", async () => {
render(
<MemoryRouter>
<Home />
</MemoryRouter>
);
const searchInput = screen.getByTestId("search");
fireEvent.change(searchInput, {
target: { value: "A" },
});
const todos = await screen.findAllByTestId("todo");
expect(todos).toHaveLength(1);
});