React e Context API: testes de unidade
Salve, salve! Tudo bem com você?
Hoje estou aqui pra falar sobre a Context API e como podemos criar testes unitários, para garantir que tudo funcione corretamente em uma aplicação React. Para ilustrar, vamos usar como exemplo uma lista de tarefas (ToDo list).
Antes de começarmos, é importante lembrar que a Context API é uma opção mais avançada do que o padrão de passagem de props em React, então é recomendado só usá-la se você precisar compartilhar dados em uma escala mais ampla ou se passar props manualmente estiver ficando muito complexo. Normalmente precisamos pensar em soluções desse tipo quando enfrentamos o já conhecido e famoso prop drilling.
Primeiro, vamos criar o nosso Provider de contexto. O Provider irá fornecer os dados para os componentes que estiverem "subscritos" a ele. Alguma coisa nessa linha:
import React, { useState } from "react";
export const TodoContext = React.createContext();
export function TodoProvider(props) {
const [todos, setTodos] = useState([]);
function addTodo(todo) {
setTodos([...todos, todo]);
}
function deleteTodo(index) {
setTodos(todos.filter((todo, i) => i !== index));
}
return (
<TodoContext.Provider
value={{
todos,
addTodo,
deleteTodo,
}}
>
{props.children}
</TodoContext.Provider>
);
}
No exemplo acima, criamos um Provider que armazena uma lista de tarefas (todos) e duas funções para adicionar e remover tarefas da lista.
Agora que temos o nosso Provider, vamos criar os nossos testes unitários. Para isso, vamos usar o pacote "react-testing-library".
O primeiro teste será para verificar se a função "addTodo" está adicionando corretamente uma tarefa à lista. Tipo assim:
import { render, fireEvent, wait } from "react-testing-library";
import { TodoProvider, TodoContext } from "./TodoProvider";
test("adiciona uma tarefa à lista", async () => {
const { getByTestId, getByText } = render(
<TodoProvider>
<TodoContext.Consumer>
{({ addTodo }) => (
<button data-testid="add-button" onClick={() => addTodo("nova tarefa")}>
Adicionar tarefa
</button>
)}
</TodoContext.Consumer>
</TodoProvider>
);
fireEvent.click(getByTestId("add-button"));
await wait(() => expect(getByText("nova tarefa")).toBeInTheDocument());
});
No exemplo acima, estamos renderizando o Provider e o Consumer dentro de um wrapper e, em seguida, clicando no botão "Adicionar tarefa". Depois, estamos usando a função "wait" do "react-testing-library" para garantir que o elemento com o texto "nova tarefa" esteja sendo exibido antes de verificarmos se ele está no documento.
O segundo teste será para verificar se a função "deleteTodo" está removendo corretamente uma tarefa da lista. Aqui está como podemos fazer isso:
import { render, fireEvent, wait } from "react-testing-library";
import { TodoProvider, TodoContext } from "./TodoProvider";
test("remove uma tarefa da lista", async () => {
const { getByTestId, queryByText } = render(
<TodoProvider>
<TodoContext.Consumer>
{({ todos, deleteTodo }) =>
todos.map((todo, index) => (
<div key={todo}>
<span>{todo}</span>
<button data-testid="delete-button" onClick={() => deleteTodo(index)}>
Remover
</button>
</div>
))
}
</TodoContext.Consumer>
</TodoProvider>
);
fireEvent.click(getByTestId("delete-button"));
await wait(() => expect(queryByText("tarefa 1")).toBeNull());
});
No exemplo acima, estamos renderizando o Provider e o Consumer dentro de um wrapper e, em seguida, clicando no botão "Remover". Depois, estamos usando a função "wait" do "react-testing-library" para garantir que o elemento com o texto "tarefa 1" não esteja sendo exibido antes de verificarmos se ele é nulo.
Agora que já vimos como criar testes unitários para a Context API, vamos falar sobre os benefícios de fazer testes unitários em uma aplicação.
Testes unitários nos ajudam a garantir que o código da nossa aplicação esteja funcionando corretamente, mesmo quando fazemos alterações futuras. Isso nos permite ter mais confiança no código que estamos escrevendo e nos dá a segurança de saber que as alterações que estamos fazendo não estão quebrando o funcionamento de outras partes da aplicação.
Além disso, testes unitários nos ajudam a escrever código mais limpo e mais fácil de manter. Isso porque, ao escrever testes, somos forçados a pensar em como dividir nosso código em partes menores e mais fáceis de testar, o que nos ajuda a evitar a criação de funções muito longas e complexas.
O pacote "react-testing-library" é uma ótima opção para fazer testes em aplicações React, pois ele nos permite testar o comportamento do usuário, como clicar em botões e preencher formulários, de maneira mais fácil e intuitiva. Além disso, ele nos ajuda a escrever testes mais robustos, pois não se prende a detalhes de implementação, o que nos permite alterar o código sem precisar alterar os testes.
Quer saber mais sobre como a Context API funciona? Ou é no mundo dos testes que você quer mergulhar? Aqui na Alura temos algumas opções, dá uma olhada:
Espero que este post tenha ajudado a entender como usar e testar a Context API em uma aplicação React. Não esqueça de sempre testar o seu código para garantir que ele esteja funcionando corretamente e para torná-lo mais fácil de manter no futuro.
Até a próxima 🖖!