- 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
Nome | Funcionalidade |
---|
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. |