Boas-vindas! Sou Neilton Seguins e serei seu instrutor ao longo deste curso de React, em que aprenderemos sobre testes de integração e mocks.
Autodescrição: sou um homem negro com cabelos curtos, pretos e encaracolados. Tenho olhos castanhos e estou usando óculos de grau com armação retangular. Estou vestindo uma camiseta azul escura. Ao fundo, há uma parede com iluminação azul e rosa.
Este curso é para você que tem curiosidade de saber como testar:
Neste curso, vamos testar a aplicação do Bytebank. O time de desenvolvimento evoluiu nosso projeto, inserindo novas rotas e adicionando a conexão com uma API. A nível de código, há muitas novidades também!
Se você não tem familiaridade com o projeto do Bytebank, recomendamos que você assista ao curso de React JS: testes automatizados no front-end. Nele, você conhecerá o projeto Bytebank, enquanto aprende sobre os diferentes tipos de testes, bem como as vantagens de realizar testes!
Animado para estudar? Vamos lá!
A aplicação do Bytebank cresceu! O time de desenvolvimento utilizou a biblioteca React Router Dom e, agora, podemos acessar novas rotas. No menu da lateral esquerda da aplicação, temos os seguintes links:
Ao clicar em cada um deles, a página correspondente aparecerá na parte inferior central da tela.
Dado que temos novas funcionalidades, vamos desenvolver testes para garantir que elas estão funcionando como esperado. Primeiramente, vamos abrir nosso projeto no VS Code.
Na pasta "src", abriremos o arquivo routes.js
, em que temos as configurações de rotas da nossa aplicação:
import { Route, Routes } from 'react-router-dom';
import Cartoes from './componentes/Cartoes';
import Investimentos from './componentes/Investimentos';
import Servicos from './componentes/Servicos';
import Pagina404 from './paginas/Pagina404';
import App from './paginas/Principal/App';
export default function AppRoutes() {
return (
<Routes>
<Route path="/" element={<App />}>
<Route path="cartoes" element={<Cartoes />} />
<Route path="investimentos" element={<Investimentos />} />
<Route path="servicos" element={<Servicos />} />
</Route>
<Route path="*" element={<Pagina404 />} />
</Routes>
);
}
Assim, quando estamos na rota principal (apenas /
), o componente App
é renderizado. Quando estamos na rota cartoes
, renderizamos Cartoes
, e assim em diante. Caso estejamos em uma rota que não existe na aplicação, vamos renderizar uma página 404.
Então, nosso primeiro teste será responsável por verificar se o React Router Dom nos direciona para a rota principal quando usarmos o caminho /
.
Na pasta "src", vamos criar um arquivo chamado routes.test.js
. De início, importaremos o render
e o screen
de @testing-library/react
. Em seguida, importaremos nosso componente App
:
import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';
Na sequência, vamos usar a função describe()
. No primeiro parâmetro, a descrição será simplesmente "Rotas". No segundo parâmetro, passaremos uma função callback:
import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';
describe('Rotas', () => {
});
Dentro da função callback de describe()
, vamos desenvolver nosso teste com a função test()
. No primeiro parâmetro, a descrição do teste será "Deve renderizar a rota principal". No segundo parâmetro, passaremos outra função callback:
import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';
describe('Rotas', () => {
test('Deve renderizar a rota principal', () => {
});
});
Dentro dessa função callback, vamos renderizar o componente App
. Depois, faremos uma consulta. Declararemos uma constante chamada usuario
e utilizaremos o método getByText()
para encontrar a mensagem de boas-vindas que aparece na parte superior central da aplicação, isto é, o texto "Olá, Joana :)!":
import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';
describe('Rotas', () => {
test('Deve renderizar a rota principal', () => {
render(<App />);
const usuario = screen.getByText('Olá, Joana :)!');
});
});
Vale lembrar que usamos aspas simples, ao indicar o texto a ser encontrado com getByText()
.
Em seguida, utilizaremos o expect()
junto do toBeInTheDocument()
para indicar que esperamos a pessoa usuária esteja no documento:
import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';
describe('Rotas', () => {
test('Deve renderizar a rota principal', () => {
render(<App />);
const usuario = screen.getByText('Olá, Joana :)!');
expect(usuario).toBeInTheDocument();
});
});
Após salvar o arquivo, vamos abrir o terminal com o atalho "Ctrl + J" e executar nosso script de testes:
npm run test
Como resultado, descobrimos que um teste falhou. No terminal, temos uma mensagem de erro indicando que useLocation()
somente pode ser usado no contexto de um componente <Router>
:
useLocation() may be used only in the context of a component.
Em "src > paginas > Principal", no arquivo App.js
, utilizamos o useLocation()
na linha 18. Esse hook do React Router Dom só pode ser usado dentro de uma rota.
Voltando ao arquivo routes.js
, notamos que fizemos a configuração correta e o App
está dentro de um <Routes>
. Então, o que está acontecendo de errado?
O Jest não consegue acessar a pilha do histórico do navegador, de modo que não compreende que estamos em um contexto de rota. Como solução, podemos usar um componente do React Router Dom chamado Browser Router. Ele nos permitirá manipular o histórico de navegação.
Vamos voltar ao arquivo routes.test.js
para implementar essa alteração, passando um novo parâmetro para render()
. Vamos usar um wrapper
, que funciona como um envelope, um elemento que envolverá o componente App
. No caso, será um BrowserRouter
:
import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import App from './paginas/Principal/App';
describe('Rotas', () => {
test('Deve renderizar a rota principal', () => {
render(<App />, { wrapper: BrowserRouter });
const usuario = screen.getByText('Olá, Joana :)!');
expect(usuario).toBeInTheDocument();
});
});
Note que, ao adicionar o BrowserRouter
, o VS Code automaticamente adiciona a importação correspondente no início do arquivo, na linha 2.
Essa modificação deve ser o suficiente para resolver o problema que tivemos. Vamos salvar o arquivo e executar o testes novamente. Dessa vez, os testes passarão.
Será que precisaremos usar o Browser Router toda vez que quisermos acessar uma rota? Existem outras maneiras de resolver essa situação, vamos explorá-las a seguir.
Aprendemos como controlar a pilha do histórico de navegações, utilizando o Browser Router para testar a rota principal da nossa aplicação.
Contudo, o Browser Router não permite o acesso a outras rotas livremente, então não temos um controle maior da pilha do histórico de navegações. A boa notícia é que existe outro componente do React Router Dom que permite esse acesso. Trata-se do Memory Router.
Com o projeto aberto no VS Code, vamos acessar a pasta "src", abrir o arquivo routes.test.js
e começar a desenvolver um novo teste para testar a rota para a página de cartões.
Novamente usaremos a função test()
. No primeiro parâmetro, a descrição será "Deve renderizar a rota Cartões". No segundo parâmetro, passaremos uma arrow function:
import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import App from './paginas/Principal/App';
describe('Rotas', () => {
test('Deve renderizar a rota principal', () => {
render(<App />, { wrapper: BrowserRouter });
const usuario = screen.getByText('Olá, Joana :)!');
expect(usuario).toBeInTheDocument();
});
test('Deve renderizar a rota Cartões', () => {
});
});
Como pretendemos renderizar os componentes Cartoes
e MemoryRouter
, vamos importá-los no início do arquivo. Para auxiliar na criação dos testes, também será necessário importar Routes
e Route
de react-router-dom
:
import { render, screen } from '@testing-library/react';
import { BrowserRouter, MemoryRouter, Routes, Route } from 'react-router-dom';
import App from './paginas/Principal/App';
import Cartoes from './componentes/Cartoes';
describe('Rotas', () => {
test('Deve renderizar a rota principal', () => {
render(<App />, { wrapper: BrowserRouter });
const usuario = screen.getByText('Olá, Joana :)!');
expect(usuario).toBeInTheDocument();
});
test('Deve renderizar a rota Cartões', () => {
});
});
Dentro da função callback, em vez de simplesmente renderizar o componente Cartoes
, vamos renderizar o <MemoryRouter>
:
// código anterior omitido
test('Deve renderizar a rota Cartões', () => {
render(
<MemoryRouter>
</MemoryRouter>
);
});
});
Dentro do <MemoryRouter>
, usaremos uma sintaxe semelhante à definição de rotas da aplicação. Colocaremos o <Routes>
e, dentro dele, o <Route>
:
// ...
test('Deve renderizar a rota Cartões', () => {
render(
<MemoryRouter>
<Routes>
<Route></Route>
</Routes>
</MemoryRouter>
);
});
});
O <Route>
terá a propriedade path
com a rota principal /
e a propriedade element
com o componente App
:
// ...
test('Deve renderizar a rota Cartões', () => {
render(
<MemoryRouter>
<Routes>
<Route path="/" element={<App />}></Route>
</Routes>
</MemoryRouter>
);
});
});
Dentro do Route
do elemento App
, vamos definir uma rota-filha. O path dela será cartoes
e o elemento será o componente de cartões:
// ...
test('Deve renderizar a rota Cartões', () => {
render(
<MemoryRouter>
<Routes>
<Route path="/" element={<App />}>
<Route path="cartoes" element={<Cartoes />} />
</Route>
</Routes>
</MemoryRouter>
);
});
});
O MemoryRouter
precisa receber uma props chamada initialEntries
, que são as entradas principais, passadas em um formato parecido com um array.
Antes do método render()
, vamos definir a constante rota
, que receberá o caminho para a rota de cartões. Em seguida, passaremos essa constante na propriedade initialEntries
do MemoryRouter
:
// ...
test('Deve renderizar a rota Cartões', () => {
const rota = '/cartoes';
render(
<MemoryRouter initialEntries={[rota]}>
<Routes>
<Route path="/" element={<App />}>
<Route path="cartoes" element={<Cartoes />} />
</Route>
</Routes>
</MemoryRouter>
);
});
});
Após o render()
, definiremos uma variável chamada meusCartoes
, que armazenará o resultado da consulta. Usaremos o método getByText()
, passando como parâmetro a string "Meus cartões" — isto é, o título do componente:
// ...
test('Deve renderizar a rota Cartões', () => {
const rota = '/cartoes';
render(
<MemoryRouter initialEntries={[rota]}>
<Routes>
<Route path="/" element={<App />}>
<Route path="cartoes" element={<Cartoes />} />
</Route>
</Routes>
</MemoryRouter>
);
const meusCartoes = screen.getByText('Meus cartões');
});
});
Por fim, vamos indicar o resultado esperado. Nós esperamos que o conteúdo textual de meusCartoes
seja "Meus cartões", que é exatamente o título do componente:
// ...
test('Deve renderizar a rota Cartões', () => {
const rota = '/cartoes';
render(
<MemoryRouter initialEntries={[rota]}>
<Routes>
<Route path="/" element={<App />}>
<Route path="cartoes" element={<Cartoes />} />
</Route>
</Routes>
</MemoryRouter>
);
const meusCartoes = screen.getByText('Meus cartões');
expect(meusCartoes).toHaveTextContent('Meus cartões');
});
});
Após salvar o arquivo, abriremos o terminal ("Ctrl + J") e executaremos os testes. Podemos rodar tanto o comando npm run test
quanto o npm test
, pois o Node compreende ambos:
npm test
Os testes passarão, sem problemas.
Agora, sabemos que existem diferentes alternativas para controlar as rotas de uma aplicação. O Browser Router e o Memory Router são algumas opções. Assim, temos mais possibilidades para o desenvolvimento de testes melhores para rotas.
Na sequência, testaremos um componente que usa o useLocation()
, um hook do React Router Dom!
O curso React: testes de integração e mocks no Front-end possui 93 minutos de vídeos, em um total de 46 atividades. Gostou? Conheça nossos outros cursos de React em Front-end, ou leia nossos artigos de Front-end.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.