Context API React: o que é, como funciona e como criar testes unitários

Olá! Tudo certo por aí?
Neste artigo, vamos abordar como utilizar a Context API em conjunto com testes unitários para garantir o correto funcionamento de aplicações em React. Para facilitar, utilizaremos como exemplo prático uma lista de tarefas (ToDo list).
Antes de começarmos, é importante lembrar que a Context API é uma solução criada para resolver o prop drilling no React, problema comum quando precisamos passar muitos dados entre componentes aninhados.
Se você está se perguntando "Context API no React: o que é?", trata-se de um recurso nativo do React para compartilhamento de estado global entre componentes, sem a necessidade de passar props manualmente.
Primeiro, vamos criar o nosso Provider de contexto. O Provider irá fornecer os dados para os componentes que estiverem "subscritos" a ele. Veja um exemplo básico:
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 anterior, criamos um Provider que armazena uma lista de tarefas (todos) e disponibiliza duas funções: uma para adicionar e outra para remover tarefas da lista.
Agora que temos o nosso Provider, vamos criar os nossos testes unitários. Para isso, vamos usar o pacote @testing-library/react.
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, renderizamos o Provider e o Consumer em um wrapper e clicamos no botão "Remover". Em seguida, utilizamos a função de espera, "wait", da biblioteca de testes para garantir que o elemento com o texto "tarefa 1" tenha sido removido.
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 Context API React usando React Testing Library, vale reforçar os principais benefícios de aplicar testes unitários em sua aplicação React.
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, escrever testes unitários contribui para um código mais limpo e fácil de manter, porque incentiva a divisão do código em partes menores e mais fáceis de testar. Isso evita 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.
Se você deseja se aprofundar em Context API React, aprender mais sobre testes unitários React com React Testing Library, praticar contexto React ou resolver de vez o prop drilling React em seus projetos, confira as sugestões abaixo da Alura:
Esperamos que este artigo tenha esclarecido como utilizar e testar a Context API em uma aplicação React. Lembre-se de sempre testar o código para garantir seu correto funcionamento e facilitar a manutenção futura.
Até a próxima 🖖!









