// Vitest, Testing Library e alternativas
Guia prático para implementar testes unitários no seu projeto: stack que usamos aqui (Vitest, Testing Library, Playwright para e2e) e outras opções como Jest e Cypress. Estrutura de pastas, exemplos copiáveis e checklist do que testar primeiro.
// testes unitários no dia a dia
Para testes unitários e de integração no front, uma combinação comum é: um runner (Vitest ou Jest), uma lib para testar componentes e hooks como o usuário usa (Testing Library) e ambiente de DOM (jsdom). Para e2e, Playwright ou Cypress. Aqui usamos Vitest + Testing Library + Playwright e mostramos alternativas.
Vitest é rápido, ESM nativo e API parecida com Jest. Jest é a opção mais conhecida; migração entre os dois é tranquila. Comando: pnpm test (ou test:watch).
Queries por papel e texto acessível (getByRole, getByText). Testa como o usuário usa a interface; evita detalhes de implementação. Funciona com Vitest e Jest.
Testes ao lado do código (ex.: src/lib/i18n/__tests__/config.test.ts). Padrão *.test.ts facilita watch e coverage em qualquer runner.
vi.mock() (Vitest) ou jest.mock() (Jest) para isolar módulos. pnpm test:coverage (ou equivalente) para relatório de cobertura.
// o que usar para unit e e2e
Stack que este projeto usa e outras opções consolidadas. Todas combinam bem com React e Next.js.
Runner (unit)
Rápido, ESM nativo, API estilo Jest. Watch e coverage integrados.
Componentes e hooks
render(), screen.getByRole/getByText, renderHook(). + @testing-library/jest-dom para matchers (toBeInTheDocument, etc.).
Testes e2e
Testes de ponta a ponta no navegador. Neste repo: pnpm test:e2e.
Runner (unit)
Padrão de mercado, muita documentação. Se já usa Jest, pode manter; para projetos novos Vitest costuma ser mais rápido.
Testes e2e
Alternativa popular ao Playwright. Boa DX e dashboard; Playwright tende a ser mais rápido e multi-browser.
// onde colocar os testes
Cada módulo pode ter uma pasta __tests__ com arquivos .test.ts ou .test.tsx. Em lib/ testamos config e utils; em scripts/ validadores e transformers. O mesmo padrão funciona com Vitest ou Jest.
Clique nos itens para explorar:
Código-fonte da aplicação
Scripts de build e validação
Você pode copiar a pasta __tests__ e o vitest.config (ou jest.config) para o seu projeto e adaptar. O padrão *.test.ts facilita o watch e o coverage.
// config, util, hook, componente e Jest
Cinco tipos de exemplo que você pode copiar: config e constantes (Vitest), função pura/util (Vitest ou Jest), hook com renderHook, componente com render + getByRole (Testing Library) e o mesmo teste de config com Jest. Cole no seu projeto, rode pnpm test (ou npm test com Jest) e adapte os nomes.
Dica: você pode colar o código abaixo direto; só ajuste o caminho do import e o nome do arquivo se precisar.
import { describe, expect, it } from "vitest";import { SUPPORTED_LOCALES, DEFAULT_LOCALE } from "../config";describe("i18n/config", () => {it("deve incluir pt-BR como locale suportado", () => {expect(SUPPORTED_LOCALES).toContain("pt-BR");});it("deve ter DEFAULT_LOCALE em SUPPORTED_LOCALES", () => {expect(SUPPORTED_LOCALES).toContain(DEFAULT_LOCALE);});});
import { describe, expect, it } from "vitest";import { formatSlug } from "../formatSlug";describe("formatSlug", () => {it("normaliza texto para slug", () => {expect(formatSlug("Hello World")).toBe("hello-world");});it("remove acentos", () => {expect(formatSlug("Ação")).toBe("acao");});});
import { describe, expect, it, vi } from "vitest";import { renderHook, waitFor } from "@testing-library/react";import { useMyHook } from "../useMyHook";describe("useMyHook", () => {it("retorna valor inicial e atualiza após ação", async () => {const { result } = renderHook(() => useMyHook());expect(result.current.value).toBe(0);result.current.increment();await waitFor(() => {expect(result.current.value).toBe(1);});});});
import { describe, expect, it, vi } from "vitest";import { render, screen, fireEvent } from "@testing-library/react";import { SubmitButton } from "../SubmitButton";describe("SubmitButton", () => {it("exibe label e chama onSubmit ao clicar", () => {const onSubmit = vi.fn();render(<SubmitButton label="Enviar" onSubmit={onSubmit} />);expect(screen.getByRole("button", { name: /enviar/i })).toBeInTheDocument();fireEvent.click(screen.getByRole("button", { name: /enviar/i }));expect(onSubmit).toHaveBeenCalledTimes(1);});});
import { SUPPORTED_LOCALES, DEFAULT_LOCALE } from "../config";describe("i18n/config", () => {it("deve incluir pt-BR como locale suportado", () => {expect(SUPPORTED_LOCALES).toContain("pt-BR");});it("deve ter DEFAULT_LOCALE em SUPPORTED_LOCALES", () => {expect(SUPPORTED_LOCALES).toContain(DEFAULT_LOCALE);});});
Para componentes use render() e screen.getByRole/getByText; para hooks use renderHook. Com Jest use jest.fn() no lugar de vi.fn() e jest.mock no lugar de vi.mock. Prefira queries por papel (getByRole).
// prioridade para júnior e pleno
Ordem sugerida para começar a cobrir o projeto sem se perder. Foque em utils e config, depois hooks e por último componentes com lógica importante.
i18n, SEO, AI Chatbot e Analytics: todas com código aberto e documentação passo a passo.