В Playwright тесты строятся на взаимодействии с элементами страницы,
проверке их состояния и содержимого. Часто стандартных методов проверки
(toHaveText, toBeVisible,
toHaveAttribute) недостаточно для сложных сценариев. Для
таких случаев используются кастомные матчеры, которые
позволяют создавать гибкие, повторно используемые условия для
ассертов.
Кастомный матчер — это функция, которая определяет, соответствует ли
объект заданному условию. В Playwright для тестов на JavaScript (с
использованием Playwright Test) матчеры создаются через метод
expect.extend.
Пример базового кастомного матчера:
import { expect } from '@playwright/test';
expect.extend({
async toHaveCssClass(received, className) {
const element = await received;
const classList = await element.getAttribute('class') || '';
const pass = classList.split(' ').includes(className);
if (pass) {
return {
message: () => `Ожидание выполнено: элемент содержит класс "${className}"`,
pass: true,
};
} else {
return {
message: () => `Элемент не содержит класс "${className}". Существующие классы: ${classList}`,
pass: false,
};
}
},
});
Использование:
await expect(page.locator('#submit')).toHaveCssClass('active');
Здесь создается проверка на наличие CSS-класса у элемента. Ключевой
момент: кастомный матчер всегда возвращает объект с двумя полями:
pass (логическое значение) и message (функция
с описанием ошибки).
Большинство операций с элементами в Playwright асинхронные, поэтому
кастомные матчеры должны поддерживать async/await. Ошибки
синхронного выполнения могут привести к ложным результатам или
незавершенным промисам.
Пример проверки видимости нескольких элементов:
expect.extend({
async toAllBeVisible(received) {
const elements = await received.elementHandles();
const invisible = [];
for (const el of elements) {
if (!(await el.isVisible())) {
invisible.push(await el.textContent());
}
}
const pass = invisible.length === 0;
return {
pass,
message: () => pass
? 'Все элементы видимы'
: `Следующие элементы не видимы: ${invisible.join(', ')}`,
};
},
});
Использование:
await expect(page.locator('.item')).toAllBeVisible();
Этот пример демонстрирует работу с коллекциями элементов и обработку асинхронных состояний.
Кастомные матчеры становятся особенно полезными при проверках с различными условиями. Для повторного использования удобно принимать аргументы, например, диапазоны чисел, регулярные выражения или динамические строки.
Пример матчера для текста, соответствующего регулярному выражению:
expect.extend({
async toMatchTextRegex(received, regex) {
const element = await received;
const text = await element.textContent();
const pass = regex.test(text);
return {
pass,
message: () => pass
? `Текст "${text}" соответствует регулярному выражению ${regex}`
: `Текст "${text}" не соответствует регулярному выражению ${regex}`,
};
},
});
Использование:
await expect(page.locator('#price')).toMatchTextRegex(/^\$\d+\.\d{2}$/);
Такая конструкция обеспечивает гибкость: один матчинг-метод может работать с любыми элементами и условиями.
Чтобы отлаживать кастомные матчеры:
pass.message.elementHandles() для работы с коллекциями
элементов.Пример полезного логирования:
console.log('Содержимое элемента:', await element.textContent());
Лог помогает быстро понять, почему матчинг не проходит, особенно на динамических страницах с задержками загрузки контента.
Кастомные матчеры не заменяют стандартные методы Playwright, они их дополняют. Часто удобно использовать стандартные ожидания состояния элемента перед кастомной проверкой:
const button = page.locator('#submit');
await expect(button).toBeVisible(); // стандартный матчинг
await expect(button).toHaveCssClass('enabled'); // кастомный матчинг
Такой подход повышает стабильность тестов и упрощает диагностику ошибок.
message должен
максимально точно описывать причину провала.async/await при работе с элементами.Кастомные матчеры позволяют создавать читаемые, поддерживаемые и гибкие проверки, адаптированные под специфические требования веб-приложения, при этом органично интегрируясь в экосистему Playwright.