Reputation: 600
I am trying to mock useSearchParams
using vitest
. I have tried a couple of methods but couldn't find a solution.
The sample code can be found here: https://codesandbox.io/p/sandbox/laughing-bas-m7ygo8
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
function App() {
const [searchParams, setSearchParams] = useSearchParams();
const [search, setSearch] = useState("");
const [direction, setDirection] = useState("");
const sortParams = searchParams.get("sortBy");
useEffect(() => {
setDirection(sortParams || "");
}, [sortParams]);
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const val = event.target.value;
setSearch(val);
setSearchParams((prev) => {
prev.set("search", val);
return prev;
});
};
const handleSortChange = (val: string) => {
setDirection(val);
setSearchParams((prev) => {
prev.set("sortBy", val);
return prev;
});
};
return (
<div>
<p>Hello</p>
<input type="search" value={search} onChange={handleSearchChange} />
<button onClick={() => handleSortChange("asc")}>Sort</button>
{direction}
</div>
);
}
export default App;
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { useSearchParams } from "react-router-dom";
import App from "./App";
vi.mock("react-router-dom", () => ({
useSearchParams: vi.fn(),
}));
describe("Simple working test", () => {
it("url should update when user clicks sort button", () => {
render(<App />);
const button = screen.getByRole("button");
userEvent.click(button);
expect(screen.getByText(/Hello/i)).toBeInTheDocument();
});
});
Can anyone please help me here? Thanks :)
Upvotes: 1
Views: 5595
Reputation: 77
If you know what you doing and there is no other way for you to test it, try to mock it like this:
const mockUseSearchParams = vi.fn();
vi.mock('react-router-dom', async () => {
const actual = await vi.importActual('react-router-dom') as any;
return {
...actual,
useSearchParams: () => mockUseSearchParams
};
});
And then you can test against mockUseSearchParams
.
For example:
expect(mockUseSearchParams).toHaveBeenCalledWith('some_value_you_want_to_test');
Upvotes: 1
Reputation: 600
Remove the mock :
vi.mock("react-router-dom", () => ({
useSearchParams: vi.fn(),
}));
Instead use: render(<App />, { wrapper: BrowserRouter });
Upvotes: -1
Reputation: 6073
You should not mock useSearchParams
. Instead, wrap your component in a MemoryRouter
for testing:
render(<MemoryRouter initialEntries={['blogs/1']}>
<Route path='blogs/:blogId'>
<App />
</Route>
</MemoryRouter>)
Upvotes: 0