Reputation: 462
I have to test a component which renders based on the country and language in the url path params. So I want to the if the components are rendered properly based on the change in params.
I am mocking the useParams and setting some required value which works for most of the tests. Now for a specific case, I need to change the param.
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({
language: 'IT'
})
}));
How do I override the language in test ?
Thank you
Upvotes: 5
Views: 6394
Reputation: 63
this solution worked well for me
let mockUseParams = {
language: 'IT',
};
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => mockUseParams,
}));
it('test with different param', () => {
mockUseParams.language: 'EN'
// test implementation
});
Upvotes: 0
Reputation: 41
You can use it like this :
const mockUseParams = jest.fn().mockResolvedValue({
slug: 'param1',
id: '123',
});
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => mockUseParams(),
}));
And to update the params :
mockUseParams.mockReturnValueOnce({
slug: 'param2',
id: '123',
});
Upvotes: 0
Reputation: 2191
Based on this page on the Jest docs, try the following
// create a separate mock function that you can access from tests
// NOTE: the name must start with `mock` and is case sensitive
const mockUseParams = jest.fn().mockReturnValue({
language: 'IT',
});
// mock the module using the mock function created above
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => mockUseParams(),
}));
it('should behave differently when the params change', () => {
mockUseParams.mockReturnValueOnce({
language: 'EN',
});
// test implementation
});
Upvotes: 1
Reputation: 13
yes Include the Router in your App component; Always render the App component in your tests (never child components like Locations); Navigate to your pages in tests by finding and clicking links on the page The positives of this approach: you don’t need to read the rest of this post 🙃 (and your test setup will be less complicated). The negatives: you can’t immediately load a routing history (the current page and previous pages) in test setup; you need to go through all the user interactions to build the history.
Upvotes: 0
Reputation: 12984
Instead of mocking useParams
you can use <MemoryRouter initialEntries>
, for example:
MyComponent.js
import { useParams } from "react-router-dom";
function MyComponent() {
const { language } = useParams();
return (
<div>
<h2>My Component page</h2>
<p>language: {language}</p>
</div>
);
}
MyComponent.test.js
import { MemoryRouter } from "react-router-dom";
import { render, screen, fireEvent } from "@testing-library/react";
import "@testing-library/jest-dom";
import App from "./App";
test("Home: Go to `MyComponent: en`", async () => {
render(
<MemoryRouter initialEntries={["/"]}>
<App />
</MemoryRouter>
);
expect(screen.getByText("Home page")).toBeInTheDocument();
fireEvent.click(screen.getByText("My Component: en"));
expect(screen.getByText("language: en")).toBeInTheDocument();
expect(screen.queryByText("language: fr")).not.toBeInTheDocument();
});
test("MyComponent: en", async () => {
render(
<MemoryRouter initialEntries={["/myComponent/en"]}>
<App />
</MemoryRouter>
);
expect(screen.getByText("language: en")).toBeInTheDocument();
});
test("MyComponent: fr", async () => {
render(
<MemoryRouter initialEntries={["/myComponent/fr"]}>
<App />
</MemoryRouter>
);
expect(screen.getByText("language: fr")).toBeInTheDocument();
});
Online demo
Upvotes: 2