es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Pruebas de elementos rotos en React

He leído algunos artículos que sugieren usar los emparejadores personalizados de getByText para probar texto en elementos fragmentados. Esto no funciona en mi caso. Tengo un componente donde renderizo una “etiqueta” y una cantidad, sin embargo, la etiqueta se divide en 2 elementos, los dos puntos y el texto, así como la cantidad. Esto hace que sea terrible para getByText encontrarlo.

Mi prueba se ve tan simple como esto:

it('displays amount and label', () => {
  render(<totalsummary amount="123" label="Total amount"></totalsummary>);
  expect(screen.getByText(/Total amount: 123/).toBeInTheDocument();
});

Esto resulta en una jerarquía que se renderiza en una prueba, con un error fallido de prueba:

<body>
  <div>
    <span style="margin-right: 16px;" id="sb12">
      Total amount
      :
    </span>
    <span aria-labelledby="sb12">
      123
    </span>
  </div>
</body>

> TestingLibraryElementError: Unable to find an element with the text: /Total amount: 123/. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

No estoy seguro de cómo superar esto sin probar la etiqueta y la cantidad por separado, lo que puede llevar a un éxito inesperado de la prueba cuando la cantidad o la etiqueta aparecen en cualquier otro lugar en la pantalla.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    En este caso, dado que la etiqueta y la cantidad están separadas en dos elementos diferentes, el matcher getByText no puede encontrarlos. Una forma de solucionar este problema es creando un matcher personalizado que pueda buscar el texto en ambos elementos. Aquí hay un ejemplo de cómo hacerlo usando React Testing Library:

    import { getByLabelText } from '@testing-library/dom';
    
    const getByTextWithMarkup = (container, targetText) => {
      const hasText = (node) => node => node.textContent === targetText;
    
      return Array.from(container.querySelectorAll('*')).find((node) => 
        hasText(node.firstChild) && hasText(node.lastChild)
      );
    };
    
    it('displays amount and label', () => {
      const { container } = render(<totalsummary amount="123" label="Total amount"></totalsummary>);
      expect(getByTextWithMarkup(container, 'Total amount: 123')).toBeInTheDocument();
    });
    

    Aquí hemos creado un matcher personalizado llamado getByTextWithMarkup que toma el contenedor (que es el componente renderizado) y el texto que queremos buscar como parámetros. Utilizamos querySelectorAll('*') para obtener todos los elementos dentro del contenedor, y luego iteramos sobre ellos para encontrar los elementos que contienen nuestro texto objetivo. Devolvemos el primer elemento que tiene tanto el texto de la etiqueta como el de la cantidad, y luego comprobamos si está en el documento con toBeInTheDocument().

    Usando este matcher personalizado, ahora podemos probar el componente TotalSummary, incluso cuando la etiqueta y la cantidad están separados en dos elementos diferentes.

Comments are closed.