В преддверии старта курсаАвтоматизация тестирования на JavaScriptпродолжаем публиковать перевод серии полезных статей.
Это третья часть из серии о тестировании с React. В прошлой части мы рассмотрели базовый формат моков React компонентов.
Еще одна вещь, которую вы можете сделать с помощью моков, - это проверить, правильные ли дочерние элементы были переданы. Вот собственно на это мы сейчас и посмотрим.
Все образцы кода для этой статьи доступны в этом репозитории.
Представьте, что мы хотим вставить форму подписки на рассылку
внутри PostContent
. Мы можем сделать это, передав ему
дочерние элементы.
Вот обновленный компонент BlogPage
:
export const BlogPage = ({ url }) => {const id = getPostIdFromUrl(url)const handleSignUp = () => {// }return (<PostContent id={id}><input type="email" placeholder="Sign up to my mailing list!" /><button onClick={handleSignUp}>Sign up</button></PostContent>)}
Важно то, что наши тесты BlogPage
не должно
волновать то, что PostContent
делает с
дочерними элементами. Они должны просто позаботиться о том, чтобы
они ему были переданы.
Мы могли бы проверить это, вытащив пропс children
из записи .mock.calls
и затем отрендерив его с помощью
render
. Другими словами, рассматривать его как пропс
для рендеринга.
Но есть более простой способ - заставить мок компонент
отрисовывать его children
:
jest.mock("../src/PostContent", () => ({PostContent: jest.fn(({ children }) => (<div data-testid="PostContent">{children}</div>))}))
Теперь мы можем написать тест, который проверяет, была ли
button
отрисована как дочерний элемент
PostContent
:
it("renders the mailing list sign up button as a child of PostContent", () => {render(<BlogPage url="http://personeltest.ru/away/example.com/blog/my-web-page" />)const postContentElement = screen.getByTestId("PostContent")const button = screen.queryByRole("button", { name: "Sign up" })expect(postContentElement).toContainElement(button)})
Тот же метод можно повторить и для поля input
.
Если вы запустите этот тест, вы заметите проблему. Наш предыдущий тест, проверяющий переданные пропсы, теперь не работает. Его ожидание выглядело так:
expect(PostContent).toHaveBeenCalledWith({ id: postId },expect.anything())
Он фейлится, потому что внезапно у нас оказывается еще и пропс
children
, который мы совсем не ожидали в рамках этого
теста.
Мы исправим это с помощью expect.objectContain
.
Используйте expect.objectContain для локализации ваших тестов
Часто бывает полезно иметь несколько модульных тестов для одного вызова мока компонента! Обычно я начинаю с одного теста со всеми указанными пропсами. Но для любых достаточно сложных значений пропсов может быть гораздо полезнее разбить их на отдельные тесты с хорошим описанием. Пропс
children
- как раз такой случай: наш тест, который проверяет, что мы передаем правильный ID, не зависит от чего-либо, связанного с отображаемым содержимым.
Мы можем избежать тестирования content
, используя
expect.objectContain
в нашем ожидании:
expect(PostContent).toHaveBeenCalledWith(expect.objectContaining({ id: postId }),expect.anything())
Подытожим
Итак, что мы узнали на данный момент?
-
Чтобы протестировать дочерние элементы, переданные в моки, измените мок компонент на `jest.fn (({children}) = {children})
-
Используйте
toContainElement
из пакета матчеровjest-dom
, чтобы проверить, отображаются ли компоненты как дочерние элементы вашего мок компонента.
-
Используйте
expect.objectContain
для написания модульных тестов, которые не будут ломаться при изменении ваших пропсов.
-
Используйте параметр конфигурации Jest
clearMocks
, чтобы убедиться, что ваши шпионы очищаются перед каждым тестом.
В четвертой части мы будем тестировать несколько отрисованных экземпляров одного и того же мок компонента.
Приглашаем вас записаться набесплатный демо-урок по теме: "Основы puppeteer".
Читать ещё: