В преддверии старта курса «Автоматизация тестирования на 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://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".
Читать ещё: