On one hand I have a simple React component. When clicking on the button, the query string change and the useeffect hook with a dependency on router.next is triggered:
import React, {useEffect, useState} from 'react';
import { useRouter } from 'next/router';
export default function FirstPost() {
const router = useRouter();
const [data, setData] = useState("data");
useEffect(() => {
if(router.query.data) {
setData(router.query.data);
}
}, [router.query]);
const handleButtonClick = () => {
router.push({
pathname: router.pathname,
query: {
...router.query,
data: 'something'
},
},
undefined,
{
shallow: true
});
console.log('query data is ' + router.query.data);
}
return (
<div>
<h1 data-testid="firstPost">First Post {data}</h1>
<button onClick={handleButtonClick}>click me</button>
</div>
);
}
On the other hand I want to create a unit test to test this behavior. I create a mock on next/router and I mock the implementation of push
to force the query change:
/**
* @jest-environment jsdom
*/
import React, { FC } from 'react'
import {render, fireEvent } from '@testing-library/react'
import FirstPost from './first-post';
describe("FirstPost", () => {
it("Should display something when click", () => {
const useRouter = jest.spyOn(require("next/router"), "useRouter");
let query = {};
const push = jest.fn().mockImplementation((url) => {
expect(url.query.data).toBe('something');
query.data = 'something';
})
useRouter.mockImplementation(() => ({
route: '/',
pathname: '',
query: query,
asPath: '',
push: push,
}));
const wrapper = render(<FirstPost />);
let firstPostComponent = wrapper.getByTestId('firstPost');
expect(firstPostComponent).toBeDefined();
expect(firstPostComponent.textContent).toBe('First Post data');
const button = wrapper.getByRole('button');
fireEvent.click(button);
firstPostComponent = wrapper.getByTestId('firstPost');
expect(firstPostComponent).toBeDefined();
expect(firstPostComponent.textContent).toBe('First Post something');
});
});
Currently the test fail because firstPostComponent.textContent
is 'First Post data'.
With console.log I can see that router.query is correctly change to 'something' but useeffect isn't call.
I wonder how the dependency array passed as an second argument to useeffect works.