Testes unitários no Next com Jest
Testes unitários são muito úteis para garantir que nossos componentes continuem funcionando quando realizarmos manutenções no futuro.
Instalando dependências
Para configurar o Jest vamos instalar pacotes jest, @testing-library/react e @testing-library/jest-dom:
1yarn add -D jest @testing-library/react @testing-library/jest-dom
Configurando o testes
É necessário criar um arquivo de configuração para que o Jest entenda como realizar os testes.
Crie um arquivo jest.config.js na raíz do seu projeto:
1const nextJest = require('next/jest')
2
3const createJestConfig = nextJest({
4 // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
5 dir: './',
6})
7
8// Add any custom config to be passed to Jest
9const customJestConfig = {
10 // Add more setup options before each test is run
11 // setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
12 // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
13 moduleDirectories: ['node_modules', '<rootDir>/'],
14 testEnvironment: 'jest-environment-jsdom',
15}
16
17// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
18module.exports = createJestConfig(customJestConfig)
Agora, basta adicionar um script para executar os testes no package.json:
1{
2 ...
3 "scripts": {
4 ...
5 "test": "jest --watch"
6 },
7 ...
8}
Criando nossos testes
Para esse exemplo, vamos criar o primeiro teste do componente GetInTouch (da página principal aqui do blog).
O componente possui um título e alguns botões que redirecionam para meu perfil em outros sites. Vamos testar se o título aparece corretamente.
Primeiro é necessário realizar um mock do hook de internacionalização, responsável por traduzir os textos do blog.
1import { useIntl } from "../../hooks/useIntl";
2
3const TITLE = "GET IN TOUCH";
4jest.mock("../../hooks/useIntl");
5
6describe("Get In Touch Component", () => {
7 beforeAll(() => {
8 (useIntl as jest.Mock).mockImplementation(() => ({
9 getInTouch: { title: TITLE },
10 }));
11 });
12});
Para testar se a string da variável TITLE está sendo exibida corretamente, podemos utilizar a função queryByText e utilizar o expect para garantir que está tudo ok:
1 test("should render get-in-touch title", () => {
2 const { queryByText } = render(<GetInTouch />);
3
4 expect(queryByText(TITLE)).toBeTruthy();
5 });
Além do queryByText outros métodos estão disponíveis e é possível encontrar a descrição para eles na documentação da testing library
No fim, nosso arquivo de teste ficará da seguinte forma:
1import { render } from "@testing-library/react";
2import { useIntl } from "../../hooks/useIntl";
3import { GetInTouch } from ".";
4import { ThemeProvider } from "styled-components";
5import { darkTheme } from "../../styles/themes/dark-theme";
6
7const TITLE = "GET IN TOUCH";
8
9jest.mock("../../hooks/useIntl");
10
11describe("Get In Touch Component", () => {
12 beforeAll(() => {
13 (useIntl as jest.Mock).mockImplementation(() => ({
14 getInTouch: { title: TITLE },
15 }));
16 });
17
18 test("should render get-in-touch title", () => {
19 const { queryByText } = render(<GetInTouch />);
20
21 expect(queryByText(TITLE)).toBeTruthy();
22 });
23});
Rodando yarn test podemos ver que o teste passou:
Para ter certeza que está tudo ok, podemos substituir o expect(queryByText(TITLE)).toBeTruthy(); por expect(queryByText(TITLE)).toBeFalsy();