Testing

Por defecto, al utilizar create-react-app, se ejecutaran los tests correspondientes a ficheros que terminen en .test.jsx.

Ejemplo del código de un test:

El siguiente test busca el botón de submit, lo pulsa y comprueba que aparece un mensaje de error (ya que no se ha rellenado el nombre ni la contraseña del usuario).

El comando test también hubiese funcionado si hubiesemos usado it en su lugar.

test('renders content', () => {
    // Arrange → Preparación del test. Si el test utiliza redux, context appi, etc... necesitamos ejecutar el test en el entorno correcto.
    render(<MemoryRouter><Login /></MemoryRouter>);
    const submitButton = screen.getByText(/submit/i);


    // Act → Las acciones que hagas
    userEvent.click(submitButton);

    // Assert → La comprobación de lo que ha ocurrido
    const error = screen.getByText(/error/i); // Username and email not filled
    expect(error).toBeInTheDocument();
});

Para no tener que cargar los providers necesarios constantemente, podemos definirlos en un fichero externo y utilizar ese wrapper.

import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';

const customRender = (ui) => {
    const Wrapper = ({ children }) => (
        <MemoryRouter>
            {children}
        </MemoryRouter>
    );
    return render(ui, { wrapper: Wrapper });
};

export * from '@testing-library/react';
export { customRender as render, userEvent };

Render

Recibe como parámetro el componente que queremos testear. Debemos añadir todos los providers que utilice el componente que queremos testear.

Screen

Se utiliza para buscar elementos en el dom renderizado.

Tipos de queries

  • get: accede a un elemento que debe existir en el momento de la invocación de este método. Si no lo encuentra, da error.
  • find: accede de forma asíncrona a un elemento que puede ser renderizado poco después de la invocación del método. Si no lo encuentra, da error.
  • query: accede a un elemento que debe existir en el momento de la invocación de este método. Si no lo encuentra, no da error.

Los tres aceptan expresiones regulares. La expresión regular /txt/i significa que buca cualquier texto que contenga la palabra txt sin tener en cuenta mayúsculas.

Priorities

Son la segunda parte del método. Indican el tipo de elemento al que queremos acceder. Algunos de los más típicos:

  • ByText → Acceden en función de un texto escrito en el dom.
  • ByTestId → Si puedes encontrar el elemento de otra manera, es posible añadirle un identificador: data-testid=»container», por ejemplo.

Expect

Recibe como parámetro el elemento que queremos evaluar y a partir de él ejecutamos el método de la evaluación.

  • toBeInTheDocument();
  • toBe(2);
  • .toHaveAttribute(‘href’, ‘/login’);

fireEvent

Nos permite evaluar si sucede el comportamiento deseado cuando se detona un evento.

import userEvent from "@testing-library/user-event";
    
userEvent.type(emailInput, 'test@test.com'); // Escribe 1234 en el input
userEvent.click(submitButton);

La diferencia entre usar userEvent y usar fireEvent es que userEvent simula el flujo completo que haría un usuario en una interacción. Por ejemplo, al hacer click, se ejecutan los eventos mousedown, mouseup, mouseclick, etc. firevent sólo simula un evento concreto. Es recomentable usar fireEvent siempre que se pueda.

describe

El comando describe nos permite establecer agrupaciones de varios tests.

describe('home page', () => {
  it('must display a title for loggin', () => {
    render(<Home />);
    expect(screen.queryByText(/Star Wars Ships Wik/i)).toBeInTheDocument();
  });
});

Ejecución de los tests

En el caso de que estemos usando create-react-app, ejecutaremos:

npm run test

Si no son muchos tests, seleccionaremos la opción de ejecutarlos todos. Si son muchos, filtraremos para ejecutar el deseado.

← Rutas privadas
Firebase (versión 9) →