Search code examples
javascriptreactjsunit-testingreact-router-domenzyme

Error with the tag Link, react-router-dom


I am doing a React challenge, it just asks me to put a Link tag from react router and it should have a text, it works perfectly in the browser but I can't pass the test, it keeps showing me an error, and I have tried literally everything.

Here is my code:

import React, { Component } from 'react'
import { Link } from 'react-router-dom';

class Nav extends Component {

    render() {
        return (
            <div>
                <li>
                    <Link to="/"></Link>
                </li>
                <li>
                    <Link to="/house/create"></Link>
                </li>
                <li>
                    <Link to="/">Home</Link>
                </li>
                <li>
                    <Link to="/house/create">Create House</Link>
                </li>
            </div>
        );
    };
};

export default Nav;

Here is the test code, the first one is passing, the other two are the ones that I can not pass.

import React from "react";
import { Link } from "react-router-dom";
import { configure, shallow } from "enzyme";
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
import isReact from "is-react";


import Nav from "../src/components/Nav/Nav";

configure({ adapter: new Adapter() });

describe("<Nav />", () => {
    let nav;
    // Si o si vas a tener que usar class component! No van a correr ninguno de los tests si no lo haces. <3
    beforeEach(() => {
        nav = shallow(<Nav />);
        expect(isReact.classComponent(Nav)).toBeTruthy();
    });

    it('Debería renderizar dos <Link to="" />. El primero que vaya a "/", y el segundo a "/house/create"', () => {
        // Podes importar el componente Link de react-router-dom.
        expect(nav.find(Link).length).toBeGreaterThanOrEqual(2);
        expect(nav.find(Link).length).toBeGreaterThanOrEqual(2);
        expect(nav.find(Link).at(0).prop('to')).toEqual('/');
        expect(nav.find(Link).at(1).prop('to')).toEqual('/house/create');
    });

    it('Debería tener un Link con el texto "Home" que cambie la ruta hacia "/"', () => {
        // El orden en el que se declaran los Links es importante!
        expect(nav.find(Link).at(0).prop("to")).toEqual("/");
        expect(nav.find(Link).at(0).text()).toEqual("Home");
    });

    it('Debería tener un segundo Link, con texto "Create House" y que cambie la ruta hacia "/house/create"', () => {
        expect(nav.find(Link).at(1).prop("to")).toEqual("/house/create");
        expect(nav.find(Link).at(1).text()).toEqual("Create House");
    });
});

when I run the test, it says it is receiving an empty string instead of "Home" or "Create House". I can not find a solution. Thank you.


Solution

  • Without being able to run your tests I think the issue is that you added 2 more Link components and edited those instead of the initial two Link components.

    You can read from the unit tests that it's expecting to see at least 2 link components, but then only explicitly checks the first two. nav.find(Link) returns an array of the found/matched element/component and only elements/components at indices 0 and 1 are tested.

    describe("<Nav />", () => {
      let nav;
      beforeEach(() => {
        nav = shallow(<Nav />);
        expect(isReact.classComponent(Nav)).toBeTruthy();
      });
    
      it('Debería renderizar dos <Link to="" />. El primero que vaya a "/", y el segundo a "/house/create"', () => {
        expect(nav.find(Link).length).toBeGreaterThanOrEqual(2);
    
        // Test the first found link
        expect(nav.find(Link).at(0).prop('to')).toEqual('/');
    
        // Test the second found link
        expect(nav.find(Link).at(1).prop('to')).toEqual('/house/create');
      });
    
      // Tests the first found link
      it('Debería tener un Link con el texto "Home" que cambie la ruta hacia "/"', () => {
        expect(nav.find(Link).at(0).prop("to")).toEqual("/");
        expect(nav.find(Link).at(0).text()).toEqual("Home");
      });
    
      // Tests the second found link
      it('Debería tener un segundo Link, con texto "Create House" y que cambie la ruta hacia "/house/create"', () => {
        expect(nav.find(Link).at(1).prop("to")).toEqual("/house/create");
        expect(nav.find(Link).at(1).text()).toEqual("Create House");
      });
    });
    

    The Nav component is rendering four Link components.

    class Nav extends Component {
      render() {
        return (
          <div>
            <li>
              <Link to="/"></Link> // index 0
            </li>
            <li>
              <Link to="/house/create"></Link> // index 1
            </li>
            <li>
              <Link to="/">Home</Link> // index 2
            </li>
            <li>
              <Link to="/house/create">Create House</Link> // index 3
            </li>
          </div>
        );
      };
    };
    

    The first test passes because it's only testing the to prop, but the next two tests fail because they are missing the link text.

    I think the solution is to remove the first two links so the second two with text values are what get tested.

    class Nav extends Component {
      render() {
        return (
          <div>
            <li>
              <Link to="/">Home</Link> // index 0
            </li>
            <li>
              <Link to="/house/create">Create House</Link> // index 1
            </li>
          </div>
        );
      };
    };
    

    Because the second two tests both test the to prop, the first test testing only the to prop is completely redundant and could/should be removed.