DEV Community

Cover image for Jest Mock + Reactjs + SVGs
bragamat
bragamat

Posted on

Jest Mock + Reactjs + SVGs

Quando estamos construindo nossos testes de componentes react, muitas vezes queremos ver como está o nosso DOM e isso pode ficar um pouco desgastante dependendo de quantos elementos estão sendo renderizados! Por exemplo:

import React from "react";
import BirdsSvg from "./BirdsSvg";

function WelcomeMessage({ message }) {
  return (
    <>
      <h1 data-testid="welcome-message">{message}</h1>
      <BirdsSvg />
    </>
  );
}

export default WelcomeMessage;

onde o componente <BirdsSvg /> é um svg.

import React from "react";

export default function BirdsSvg() {
  return (
    <svg
      xmlnsrdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns="http://www.w3.org/2000/svg"
      xmlnscc="http://creativecommons.org/ns#"
      xmlnsdc="http://purl.org/dc/elements/1.1/"
      id="svg2"
      viewBox="0 0 332.59 228.16"
      version="1.1"
    >
      <g
        id="layer1"
        transform="translate(-95.351 -259.05)"
        groupmode="layer"
        label="Layer 1"
      >
        <g id="g3798" transform="matrix(3.0193 0 0 3.1136 -192.54 -1017.7)">
          <g
            id="g3954-5-2"
            strokeLinejoin="round"
            fillRule="evenodd"
            transform="matrix(.13195 0 0 .12599 133.41 389.13)"
            stroke="#000"
            strokeLinecap="round"
            strokeWidth="27.39"
          >
            <g
              id="g4720-2-9"
              transform="matrix(.99889 -.047095 .047095 .99889 -22.038 7.2067)"
            >
              <path
                id="path4363-1-21-1"
                rounded="0.56"
                arg1="1.5268686"
                arg2="2.5740661"
                randomized="0"
                cy="342.63394"
                cx="504.21341"
                flatsided="true"
                strokeWidth="46.328"
                fill="#e502b8"
                transform="matrix(-.45011 -.20108 -.24232 .66833 376.47 365.32)"
                transform-center-y="-14.31202"
                transform-center-x="0.79508119"
                type="star"
                sides="3"
                r1="116.27272"
                d="m509.32 458.79c-112.67 4.96-160.3-69.76-108.26-169.81 52.05-100.06 140.57-103.95 201.2-8.85 60.62 95.1 19.73 173.71-92.94 178.66z"
                r2="58.13636"
              />
.
.
.

(pode ver o svg inteiro aqui clicando aqui!)

e nosso teste pro componente <WelcomeMessage />:

import React from "react";
import { render } from "@testing-library/react";
import WelcomeMessage from "../components/WelcomeMessage";

describe("<WelcomeMessage />", () => {
  it("renders message as passed through props", () => {
    const message = "Sintam-se em casa 😁";
    const { getByTestId } = render(<WelcomeMessage message={message} />);

    expect(getByTestId("welcome-message").textContent).toBe(message);
  });
});

Agora supondo que queremos utilizar o helper debug retornado da função render (testing-library/react) pra gente entender como está nosso componente visualmente, esse seria o resultado:

  • o teste ficaria assim:
it("renders message as passed through props", () => {
    const message = "Sintam-se em casa 😁";
    const { debug, getByTestId } = render(<WelcomeMessage message={message} />);

    debug();
    expect(getByTestId("welcome-message").textContent).toBe(message);
  });

e quando rodassemos o comando yarn||npm test o resultado ira se parecer com isso:

Alt Text

Como podem ver, o debug() retorna o DOM naquele momento, incluindo o nosso SVG que ocupa quase toda a tela do terminal e deixa tuo muito bagunçado, o que pode resultar em muitos problemas pra depurar. Só pra vocês terem uma ideia melhor do quão difícil pode ficar pra visualizar tudo, esse é um printscreen do terminal (tirando bastante o zoom e tentando visualizar tudo):
Alt Text

e como vocês podem ver, mesmo assim não foi renderizado 100% do DOM no console.

Então, tendo isso em mente, hoje vou passar pra vocês uma dica bem simples e prática pra ajudar a gente a limpar esse console e a depurar nossos testes: o mock do jest.

o Mock é uma estratégia muito utilizada quando a gente quer testar algo que, dentro de um contexto, tem algum tipo de "contato" com API's externas à nossa aplicação. Porém no contexto de reactjs a gente consegue fazer um mock de um componente.

A estratégia que vamos tomar aqui é fazer um mock para representar nosso svg, ou seja: vamos transformar nosso componente svg em um componente h1 que vai ter um texto dentro... e com isso a gente resolve o problema da bagunça que ficou nosso terminal depois de utilizar a função debug.

Então basta que a gente passe o caminho relativo ao componente svg (que está sendo importado dentro do componente <WelcomeMessage />) e um callback "dizendo" o que a gente quer. Nosso teste vai ficar assim então:

import React from "react";
import { render } from "@testing-library/react";
import WelcomeMessage from "../components/WelcomeMessage";

jest.mock("../components/WelcomeMessage/BirdsSvg", () => () => <h1>Esse é o meu mock</h1>);

describe("<WelcomeMessage />", () => {
  it("renders message as passed through props", () => {
    const message = "Sintam-se em casa 😁";
    const {  debug, getByTestId } = render(<WelcomeMessage message={message} />);
    debug();
    expect(getByTestId("welcome-message").textContent).toBe(message);
  });
});

e agora nosso terminal vai ficar assim:
Alt Text

Como podemos perceber, existe agora um componente "novo" que não existe de verdade no fluxo da nossa aplicação. E podemos fazer ainda mais, retornar null e não renderizar nada relacioado ao componente <BirdsSvg />:

jest.mock("../components/WelcomeMessage/BirdsSvg", () => () => null);

Alt Text

Agora fica muito mais fácil de depurar e fazer alterações nos nossos testes! 😄

O Repositório ta disponível aqui 🚀

Top comments (0)