En este post, se explica cómo utilizar screen, render y expect para realizar pruebas a un formulario en React.
Render:
Como su nombre indica, lo que va a hacer esto es renderizar el componente que nosotros le pidamos y nos va a retornar el contenedor del DOM donde se está ejecutando la prueba. Para
simplificar la explicación, imagínate un vacío (navegador) y dentro de este aparece el componente que renderizaste y eso es lo unico que hay. A partir de ahí, vamos a poder empezar a trabajar.
Screen:
screen es una utilidad que nos permite actuar sobre el contenedor renderizado. Proporciona métodos para buscar elementos en el DOM, como getByRole, getByTestId, etc. Esto facilita la interacción y
la búsqueda de elementos específicos para las pruebas.
Expect:
La función expect se utiliza para hacer afirmaciones sobre los elementos del DOM. En la primera parte de la afirmación, se indica qué elemento se va a observar, y en la segunda parte se especifica
qué se espera que suceda. Por ejemplo, expect(elemento).toBeInTheDocument() verifica si el elemento está presente en el documento.
Mocks:
Los mocks son datos controlados que se proporcionan a los componentes para obtener respuestas predecibles durante las pruebas.
import { render } from '@testing-library/react'
// describe(nombreComponente, logica)
describe('LoginForm', () => {
// Vamos a tomar "it" como cada parte individual del test.
it('should render correctly', () => {
const container = render(<LoginForm />) // renderiza <LoginForm/>
expect(container).toBeInTheDocument() // Si container esta en el documento pasa el test
})
})
Ya sabiendo la base de cómo vamos a realizar los tests, podemos comenzar a complejizarlos.
// Esta va a ser la información "buena"
export const LoginFormMock = {
username: 'username',
password: 'pass123@',
}
// Esta va a ser la información erronea
export const LoginFormMockError = {
username: 'usernameeeeeeeeeeeeeee',
password: 'pass123',
}
import { screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { LoginFormMock } from '@/__mocks__/LoginForm.mock.ts'
describe('LoginForm', () => {
// se ejecuta despues del test y resetea los mocks
afterEach(cleanup)
afterEach(jest.clearAllMocks)
// Este beforeEach es para que se ejecute siempre antes de cualquier test y no tener que repetir constantemente el render
beforeEach(() => {
render(<LoginForm />)
})
it('should two input and button exists at the screen', () => {
// Obtenemos los elementos por su rol y name, aunque hay otras formas como el data-testid
const usernameInput = screen.getByRole('textbox', { name: /Iniciar sesion/i, })
const passwordInput = screen.getByRole('textbox', { name: /Contraseña/i })
const buttonSubmit = screen.getByRole('button', { name: /Iniciar sesion/i })
expect(usernameInput).toBeInTheDocument()
expect(passwordInput).toBeInTheDocument()
expect(buttonSubmit).toBeInTheDocument()
// Aca verifica si el botón está deshabilitado cuando el form no tiene información.
expect(buttonSubmit).toBeDisabled()
})
it('should enable the submit button if the form values are valid', async () => {
const usernameInput = screen.getByRole('textbox', { name: /Iniciar sesion/i })
const passwordInput = screen.getByRole('textbox', { name: /Contraseña/i })
const submitButton = screen.getByRole('button', { name: /Iniciar sesion/i })
expect(submitButton).tobeDisabled()
// Ahora simulamos que el usuario escribe en el form con la información del mock
await userEvent.type(usernameInput, LoginFormMock.username)
await userEvent.type(usernameInput, LoginFormMock.password)
// El waitFor es una función que espera a que todo lo que está dentro termine; aquí no se utiliza de la mejor manera
// pero es para el ejemplo
await waitFor(() => {
// Vemos si el valor del form conincide con el mock
expect(usernameInput).toHaveValue(LoginFormMock.username)
expect(passwordInput).toHaveValue(LoginFormMock.password)
})
// y vemos que se habilite el boton
expect(submitButton).toBeEnabled()
})