Executando verificação de segurança...
1

Primeiros passos com testes no NexJs13 + Jest + React Testing Library


  • Precisamos descrever o teste com a função describe
describe('<Home />', () => {})
  • Agora vamos usar a função it para realmente isolar o teste, é dentro dessa função que a lógica do teste é feita
describe('<Home />', () => {
	it('should have text in home page', () => {})
})

Render

  • A função render da lib React testing library, renderiza o componente na tela:
import { render } from "@testing-library/react";
import Home from "@/app/page";

describe("<Home />", () => {
  it("should have text in home page", () => {
    render(<Home />);
  });
});

Screen

  • É usada para procurar algo que exista em tela, como por exemplo, um texto. Vale ressaltar, que a função screen é usada após um função de render , para realmente simular a renderização do componente em tela, e depois fazer a consulta ao mesmo.
import {render, screen} from "@testing-library/react"
import Home from "path-component"

describe('<Home />', () => {
	it('should have text in home page', () => {
		render('<Home />');
		screen.getByText('Home page')
	})
})

Expect

  • Essa função espera que algo aconteça, e caso não aconteça gera um erro
import { render, screen } from "@testing-library/react";
import Home from "@/app/page";

describe("<Home />", () => {
  it("should have text in home page", () => {
    render(<Home />);
    expect(screen.getByText("Home")).toBeInTheDocument();
  });
});

Testes simulando o comportamento do usuário

  • Podemos baixar uma parte da lib react-testing-library que cuida do eventos:
npm i -D @testing-library/user-event
  • Com esse simples código podemos testar o click do usuário em um button, e sendo alterado um estado para true, sendo que, quando o estado está true é exibido um texto:
describe("<Home /> - Behavior", () => {
  it("should have a text after click button", async () => {
    expect(screen.queryByText("EXIST TEXT")).not.toBeInTheDocument();
    render(<Home />);
    const buttonAddText = screen.getByRole("button", { name: "Add text" });
    await userEvent.click(buttonAddText);
    expect(screen.getByText("EXIST TEXT")).toBeInTheDocument();
  });
});

Renderização baseada em promisses

  • Devemos lembrar que as vezes necessitamos renderizar um dado na tela que está vindo de uma API ou servidor externo, e que isso não é feito de forma síncrona. Para esses casos precisamos usar os métodos começados em find.., que trabalham de forma assíncrona.

//...
it("should have a text in screen after click in button - find", async () => {
    render(<Home />);
    expect(screen.queryByText("EXIST TEXT")).not.toBeInTheDocument();
    const button = screen.getByRole("button", { name: "Add text" });
    userEvent.click(button);
    expect(
      await screen.findByText("EXIST TEXT", {}, { timeout: 5000 })
    ).toBeInTheDocument();
  });

MSW

  • As vezes precisamos fazer uma request a uma API Rest, por exemplo, para enviar ou retornar dados para o usuario. Entretanto, testar essas requisições e como ela se comporta é algo fundamental, o MSW faz um “mock” em seu teste, sendo o interceptador da requisição no momento de teste, com isso, podemos simular uma requisição real e debugar nosso código para evitar futuros “bugs”.

Instalação

npm i -D msw whatwg-fetch

Configuração

  • Na raiz do projeto, crie uma pasta cujo nome é: mocks. Dentro desse pasta crie uma arquivo chamado server.ts ou server.js, e escreva a seguinte configuração:
import { setupServer } from "msw/node";
import { handlers } from "./handlers";
export const server = setupServer(...handlers);
  • A função setupServer recebe parâmetros, conhecidos como handlers, mas, podemos pensar nesses parâmetros como as rotas que serão usadas para consulta. Vamos então, criar um arquivo para colocar nossas handlers.
import { rest } from "msw";

export const handlers = [
  rest.get("https://randomuser.me/api/", (req, res, ctx) => {
    return res(
      ctx.json({
        results: [{ name: { first: "Henriik" } }],
      })
    );
  }),
];
  • Precisamos também configurar o nosso arquivo jest.setup.js, para que ele incie o “mock”:
import "@testing-library/jest-dom/extend-expect";

import "whatwg-fetch";
import { server } from "./mocks/server";

beforeAll(() => {
  server.listen();
});

afterAll(() => {
  server.close();
});
  • E logo em seguida criar meu componente que vai ser testado:
"use client";

import React, { useEffect, useState } from "react";

export default function UsersPage() {
  const [users, setUsers] = useState<string>("");

  useEffect(() => {
    (async () => {
      const request = await fetch("https://randomuser.me/api/");
      const { results } = await request.json();
      setUsers(results[0].name.first);
    })();
  }, []);

  return <div>{users ? <p>{users}</p> : <p>not users</p>}</div>;
}
  • E agora basta escrever o teste, é importante lembrar que o dado vai vim do nosso “mock”, ou seja, independente do que vim da api, o dado a ser validado no teste é aquele que colocamos no arquivo handlers:
import UsersPage from "@/app/users/page";
import { render, screen } from "@testing-library/react";

describe("<Users />", () => {
  it("request api for get name", async () => {
    render(<UsersPage />);
    expect(await screen.findByText("Henriik")).toBeInTheDocument();
  });
});

Funções importantes

NomeFuncionalidade
getByRole()Pega o elemento DOM pelo seu “papel”
getByLabelText()Pega o elemento do label que envolve o elemento input
getByText()Pega o elemento DOM pelo seu texto
getByTitle()Pega o elemento DOM pelo seu título
getByPlaceHolderText()Pega o elemento DOM pelo seu texto placeholder
getByAltText()Pega o elemento DOM por seu texto alt
getByDisplayValue()Pega o elemento de um input pelo seu valor atual
getAllByRole()Retorna uma lista de elementos DOM pelo seu “papel”
queryByRole()Retorna um elemento DOM pelo seu “papel”
queryByLabelText()Retorna um elemento do label que envolve o elemento input
queryByText()Retorna um elemento DOM pelo seu texto
queryByTitle()Retorna um elemento DOM pelo seu título
queryByPlaceHolderText()Retorna um elemento DOM pelo seu texto placeholder
queryByAltText()Retorna um elemento DOM por seu texto alt
queryByDisplayValue()Retorna um elemento de um input pelo seu valor atual
getAllByRole()Retorna uma lista de elementos DOM pelo seu “papel”
findByRole()Retorna um elemento DOM pelo seu “papel”
findByLabelText()Retorna um elemento do label que envolve o elemento input
findByText()Retorna um elemento DOM pelo seu texto
findByTitle()Retorna um elemento DOM pelo seu título
findByPlaceHolderText()Retorna um elemento DOM pelo seu texto placeholder
findByAltText()Retorna um elemento DOM por seu texto alt
findByDisplayValue()Retorna um elemento de um input pelo seu valor atual
getAllByRole()Retorna uma lista de elementos DOM pelo seu “papel”
queryAllByRole()Retorna uma lista de elementos DOM pelo seu “papel”
queryAllByLabelText()Retorna uma lista de elementos do label que envolve o elemento input
queryAllByText()Retorna uma lista de elementos DOM pelo seu texto
queryAllByTitle()Retorna uma lista de elementos DOM pelo seu título
queryAllByPlaceHolderText()Retorna uma lista de elementos DOM pelo seu texto placeholder
queryAllByAltText()Retorna uma lista de elementos DOM por seu texto alt
queryAllByDisplayValue()Retorna uma lista de elementos de um input pelo seu valor atual

Sou um desenvolvedor web fullstack com dois anos de experiência, apaixonado por tecnologia e por criar soluções eficientes. Mantenho-me atualizado com as novas tecnologias e estou sempre procurando aprender mais. Com uma alma jovem e sedenta por conhecimento, estou constantemente buscando expandir minhas habilidades. Tenho habilidades comprovadas em trabalhar em equipe e estou confiante em minhas habilidades para resolver problemas e entregar resultados de qualidade. Meu portfólio apresenta projetos que desenvolvi em várias tecnologias, incluindo React, NextJs, TypeScript, NodeJs, Jest, PHP, JavaScript, HTML, CSS, Python, Django e MySQL.

Carregando publicação patrocinada...
2
0