2

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.

Bérenger
  • 66
  • 5

0 Answers0