Home > other >  TypeError: Cannot read property 'startsWith' of undefined in router.pathname.startsWith()
TypeError: Cannot read property 'startsWith' of undefined in router.pathname.startsWith()

Time:10-22

I am using Jest and react testing library for TDD in NextJS, In the nav component I am using the code

<li className={router.pathname.startsWith('/settings/employeetypes') ? "active-link" : ""}>
 <a className="dropdown-item" href="#">Employee Type</a>
</li>

Nav component is being used in Home Component.

enter image description here

and test file is :

import React from 'react'
import { render, screen } from '@testing-library/react'
import * as nextRouter from 'next/router';
import '@testing-library/jest-dom'
nextRouter.useRouter = jest.fn();
nextRouter.useRouter.mockImplementation(() => ({ route: '/' }));
import Home from '../pages/index'

describe('Home', () => {
  it('Home Page renders a NavBar', () => {    
      render(<Home />)
      expect(screen.getByText(/live/i)).toBeInTheDocument();
  })

  it('Homepage should display app-wrapper class',() => {
    const { container } = render(<Home />)
    expect(container.getElementsByClassName('app-wrapper').length).toBe(1);
  })

  it('Homepage should display map',() => {
    const { container } = render(<Home  />)
    expect(container.firstChild).toMatchSnapshot();
  })
})

The code of Home Component is :

import axios from 'axios'
import NavBar from '@/components/NavBar'
import { useRef, useEffect } from 'react'
import { loadModules } from 'esri-loader'

export default function Home({...props}) {

  useEffect(() => {
     // some stuff there 
  })

  return (
    <div id="home-container"> 
        <NavBar />
        ....
        .... 
    </div>
}

export async function getServerSideProps(context) {
   ... // Call API for get data for Home Component
}

Code of NavBar Component:

import Link from "next/link";
import { useRouter } from "next/router";

const NavBar = ({...props}) => {
   const router = useRouter();

   return (
          <ul className="dropdown-menu" aria-labelledby="navbarDropdown">
               <li className={router.pathname == "/" ? "active-link nav-item" : "nav-item"}>
                        <Link href="/">
                            <a className="nav-link">
                                <span className="nav-icon">
                                    <img src="/icons/dashboard.png" />
                                </span>
                                <span className="nav-link-text">Live View</span>
                            </a>
                            </Link>
                 </li>

                  <li className={router.pathname.startsWith('/settings/locations') ? "active-link" : ""}>
                    <Link href="/settings/locations">
                       <a className="dropdown-item">Locations</a>
                     </Link>
                  </li>
            </ul>
   )
 }

CodePudding user response:

You can mock useRouter() to return an object like {pathname: "/settings/locations"}. Then router.pathname is no longer undefined and has a startsWith() method.

You just have to modify an existing line in your test file:

nextRouter.useRouter.mockImplementation(() => ({ route: '/', pathname: '/' })); // or which pathname you want to test
  • Related