Web-first assertions
Проверки в Playwright тоже умеют ждать — они повторяют попытку, пока условие не станет верным.
Web-first assertion — это проверка через
expect(locator), которая автоматически повторяется до тех пор, пока ожидаемое условие не выполнится или не выйдет таймаут.
Обычная проверка против web-first
Если бы проверка выполнялась мгновенно, она бы упала на асинхронном вебе: текст ещё не подгрузился. Рассмотрим неправильный и правильный варианты.
// ПЛОХО: получаем текст «прямо сейчас», без ожидания
const text = await page.getByRole('heading').textContent();
expect(text).toBe('Привет'); // упадёт, если текст ещё не появился
// ХОРОШО: web-first assertion ждёт нужный текст
await expect(page.getByRole('heading')).toHaveText('Привет');Во втором случае Playwright будет периодически перепроверять элемент, пока в нём не появится «Привет» (или не истечёт таймаут). Это убирает целый класс флаки-тестов, которые возникают из-за чтения ещё не готового состояния.
Важная деталь: await
Web-first assertions всегда с await, потому что они асинхронные (ждут). А вот проверки обычных значений (чисел, строк, которые уже у вас в руках) — без await. Перепутать легко, а ошибка коварная: без await проверка «как будто проходит», но на деле не дожидается результата.
await expect(locator).toBeVisible(); // ждёт → await
expect(2 + 2).toBe(4); // мгновенно → без awaitГлавные проверки
| Проверка | Что утверждает |
toBeVisible() | элемент виден на странице |
toBeHidden() | элемент скрыт или отсутствует |
toHaveText('...') | текст элемента точно равен |
toContainText('...') | текст содержит подстроку |
toHaveValue('...') | значение поля ввода |
toBeEnabled() / toBeDisabled() | элемент активен / неактивен |
toBeChecked() | чекбокс отмечен |
toHaveCount(n) | столько-то элементов в наборе |
toHaveURL('...') | адрес страницы |
Примеры из жизни
// после отправки формы видно сообщение об успехе
await page.getByRole('button', { name: 'Отправить' }).click();
await expect(page.getByText('Спасибо за заявку')).toBeVisible();
// поле email содержит введённое значение
await expect(page.getByLabel('Email')).toHaveValue('[email protected]');
// кнопка отправки заблокирована, пока форма не заполнена
await expect(page.getByRole('button', { name: 'Отправить' })).toBeDisabled();Отрицание через not
Любую проверку можно инвертировать через .not — например, убедиться, что баннер с ошибкой исчез:
await expect(page.getByText('Ошибка')).not.toBeVisible();Почему это снижает флаки
Web-first assertions — это второй (после авто-ожиданий действий) столп устойчивости Playwright. Вместо «считай состояние сейчас и сравни» они говорят «дождись, пока состояние станет таким». Большинство нестабильных тестов в других инструментах ломаются именно на мгновенных проверках текста, которого ещё нет. Правило простое: предпочитайте expect(locator).что-то() ручному чтению значений через textContent() и сравнению.
Итог
- Web-first assertion (
expect(locator)) повторяет проверку, пока условие не станет верным. - Такие проверки всегда с
await; проверки готовых значений — без. - Ключевые:
toBeVisible,toHaveText,toHaveValue,toBeEnabled,toHaveURL. - Они убирают флаки, возникающие из-за мгновенного чтения ещё не готового состояния.