En este tutorial aprenderemos a tetear un componente sencillo de React que nos permita hacer Testing.
¿Qué es Vitest?
vitest usa la misma confguracion de vite, esto asegura el entorno de desarrollo sea el mismo que el entorno de contruccion
creacion del proyecto
pnpm create vite react-vitest
npm create vite react-vitest
Opciones a escoger:
- Framework: React
- Language: Typescript
Instalación de dependencias
pnpm i
pnpm add vitest jsdom
npm i
Componente
creemos un componente en la carpeta components/Accordion.tsx
type AccordionProps = {
title: string;
children: React.ReactNode;
};
const Accordion = ({ title, children }: AccordionProps) => (
<div className="accordion">
<h3 className="accordion-title">{title}</h3>
<div className="accordion-content">{children}</div>
</div>
);
export default Accordion;
creano archivo de testing
en el mismo nivel crea un archivo Accordion.test.ts:
import {describe, test} from 'vitest';
describe("Accordion test", () => {
test("Should show title", () => {
})
})
Configurando Vitest
npm add vitest jsdom
Actualicemos la configuración en vite.config.js:
Actualizando Package.json
Añade este Script al package.json:
"test": "vitest"
npm test
pnpm test
Tambien es posible evitar tener que importar las funciones, usando globals. mejorando la configuracion:
/// <reference types="vitest" />
/// <reference types="vite/client" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
}
})
npm test
pnpm test
añadir tambien a tsconfig:
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}
Añadiendo React Testing Library
npm i -D jsdom @testing-library/react
pnpm add -D jsdom @testing-library/react
Primer Unit Test en React
import { render, screen } from "@testing-library/react";
import Accordion from "./Accordion";
describe("Accordion test", () => {
test("Should show title", () => {
render(
<Accordion title="hello">
<p>hello world</p>
</Accordion>
);
expect(screen.getByText("hello")).toBeDefined();
});
});
pnpm test
Testear funcionalidad
import Accordion from "./Accordion";
import { render, screen } from "@testing-library/react";
describe("Accordion", () => {
beforeEach(() => {
render(
<Accordion title="Testing">
<h4>Content</h4>
</Accordion>
);
});
test("should show title all the time", () => {
expect(screen.getByText(/Testing/i)).toBeDefined();
});
test("should not show the content at the start", () => {
expect(screen.queryByText(/Content/i)).toBeNull();
});
});
esto no pasar el test porque el content no esta presente.
psar el test
actualiza el codigo del componente a:
import { useState } from "react";
// import './Accordion.css'
type AccordionProps = {
title: string;
children: React.ReactNode;
};
const Accordion = ({ title, children }: AccordionProps) => {
const [open, setOpen] = useState(false);
return (
<div className="accordion">
<div>
<h3 className="accordion-title">{title}</h3>
<button onClick={() => setOpen(!open)}>
{open ? "Close" : "Open"}
</button>
</div>
{open && <div className="accordion-content">{children}</div>}
</div>
);
};
export default Accordion;
Crear CSS:
.accordion {
width: 80vw;
border-radius: 5px;
border: 1px solid gray;
}
.accordion-title {
padding: 0px 25px;
flex-direction: row;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid gray;
display: flex;
}
Luego puedes ejecutar el Test
pnpm test
Testeando Eventos
test('should show the content when the title is clicked', () => {
const button = screen.getByText(/Open/i);
fireEvent.click(button);
expect(screen.getByText(/Content/i)).toBeDefined();
});
test('should hide the content when the title is clicked twice', () => {
const button = screen.getByText(/Open/i);
fireEvent.click(button);
fireEvent.click(button);
expect(screen.queryByText(/Content/i)).toBeNull();
});