Как сделать запрос по текстовой строке, содержащей HTML-теги, используя React Testing Library? - PullRequest
0 голосов
/ 04 апреля 2019

Текущее рабочее решение

Используя этот html:

<p data-testid="foo">Name: <strong>Bob</strong> <em>(special guest)</em></p>

Я могу использовать Библиотека React Testing getByTestId, чтобы найти textContent:

expect(getByTestId('foo').textContent).toEqual('Name: Bob (special guest)')

Это лучший способ?

Я хотел бы просто использовать этот html:

<p>Name: <strong>Bob</strong> <em>(special guest)</em></p>

И использовать React Testing Library 's getByText метод, подобный следующему:

expect(getByText('Name: Bob (special guest)')).toBeTruthy()

Но это не работает.

Итак, вопрос…

Существует ли более простой способ использования библиотеки React Testingнайти строки текстового содержимого с размеченными тегами?

Ответы [ 2 ]

0 голосов
/ 02 июля 2019

Вот твердый ответ от 4-го из Пять вещей, которые вы (вероятно) не знали о библиотеке тестирования из Блог Джорджо Полвары .


4. Запросы тоже принимают функции

Вы, вероятно, видели такую ​​ошибку:

Невозможно найти элемент с текстом: Hello world. Это может быть потому, что текст разбит на несколько элементов. В этом случае вы можете предоставить функцию для вашего текста matcher, чтобы сделать ваш matcher более гибким.

Обычно это происходит потому, что ваш HTML выглядит следующим образом:

<div>Hello <span>world</span></div>

Решение содержится в сообщении об ошибке: «[...] вы можете предоставить функцию для вашего сопоставителя текста [...]».

О чем это все? Оказывается, что сопоставители принимают строки, регулярные выражения или функции.

Функция вызывается для каждого рендеринга узла. Он получает два аргумента: содержимое узла и сам узел. Все, что вам нужно сделать, это вернуть true или false в зависимости от того, какой узел вам нужен.

Пример прояснит это:

import { render, within } from "@testing-library/react";
import "jest-dom/extend-expect";

test("pass functions to matchers", () => {
  const Hello = () => (
    <div>
      Hello <span>world</span>
    </div>
  );
  const { getByText } = render(<Hello />);

  // These won't match
  // getByText("Hello world");
  // getByText(/Hello world/);

  getByText((content, node) => {
    const hasText = node => node.textContent === "Hello world";
    const nodeHasText = hasText(node);
    const childrenDontHaveText = Array.from(node.children).every(
      child => !hasText(child)
    );

    return nodeHasText && childrenDontHaveText;
  });
});

Мы игнорируем аргумент content, потому что в этом случае это будет либо «Hello», «world», либо пустая строка.

Вместо этого мы проверяем, что текущий узел имеет право textContent . hasText - небольшая вспомогательная функция для этого. Я объявил это, чтобы держать вещи в чистоте.

Это еще не все. Наш div - не единственный узел с текстом, который мы ищем. Например, body в этом случае имеет тот же текст. Чтобы не возвращать больше узлов, чем необходимо, мы следим за тем, чтобы ни у одного из дочерних элементов не было того же текста, что и у его родителя. Таким образом, мы гарантируем, что возвращаемый нами узел является наименьшим, иными словами, он закрывается в нижней части нашего дерева DOM.


Прочитайте остальную часть Пять вещей, которые вы (вероятно) не знали о библиотеке тестирования

0 голосов
/ 04 апреля 2019

Вы можете передать метод в getbyText:

getByText((_, node) => node.textContent === 'Name: Bob (special guest)')

Вы можете поместить код в вспомогательную функцию, чтобы вам не приходилось вводить его все время.

...