Как проверить локаторы с помощью Playwright

от автора

В этой статье мы поговорим о том, что можно проверить у локатора (элемента) и какие вообще есть возможности проверок. Более того, в этой статье я описал упражнения, которые вы можете выполнить и отработать в качестве практики.

Обычно мои статьи были холиварными, а не техническими. Но в этот раз решила выложить что-то действительно техническое и полезное. Тестировщики, налетай! Очень хочу, чтобы опытные ребята, которые с playwright работают давно, поделиться своим мнением о примерах в тексте статьи. Достаточно ли они информативны.

Проверки локаторов

Это могут быть как интерактивные элементы (кнопки, поля ввода, чек-боксы, …), так и статика (картинки, текст, иконки и т.д.).

Каждый элемент на странице может давать пользователю обратную связь: поле ввода подсвечивается красным, если вы ввели невалидные данные, иконка «Сохранить» неактивна, потому что вы еще не внесли изменения в документ, цвет всплывающего уведомления должен быть красным, потому что случилась ошибка. Чаще всего, нам нужно получить какое-то свойство элемента только для того, чтобы сразу же проверить его значение. Мы хотим проверить, что отображается правильный текст или элементу присвоен нужный CSS-класс.

С другой стороны, иногда нам нужно, все же, уметь получать свойства элементов для промежуточных действий. Например, мы хотим посмотреть, сколько сейчас строк в таблице, удалить одну и проверить, что строк стало меньше на одну. Для того, чтобы организовать такую проверку, нам нужно вычислить, сколько всего строк было до того, как мы удалили последнюю строчку. Если в таблице было X строк, то, после нажатия, должно быть X-1. Найдите икс, получается? И вот тут нам нужна «ручка», которую мы дернем и получим число, без всяких assert’ов.

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

Текст элемента

Давайте начнем с простого примера — получение и проверка текста.

Задача для практики

Напишем скрипт, который открывает страницу и забирает текст у первого на странице элемента по локатору [field=descr].

const { test, expect } = require("@playwright/test"); test("get text", async ({ page }) => { await page.goto("<https://inzhenerka.tech/>"); const description = await page.locator("[field=descr]").first().textContent(); console.log(description); }); 

В консоль выведется текст «Помогаем инженерам повысить свою квалификацию на рынке труда и приобрести навыки международного уровня». Почему мы увидели его в консоли – потому что строка console.log(description);. А почему в переменной description оказалось значение – потому что мы использовали метод textContent(), который возвращает нам текст переданного локатора.

Что еще за first()?

Вы могли заметить, что мы используем у локатора какой-то метод first() перед тем, как запросить текст элемента. Нужно ли его использовать каждый раз, когда я хочу получить текст элемента? Или что будет, если этот метод не вызвать? Объясняем.

Дело в том, что, по нашему локатору [field=descr], на странице обнаруживается 4 элемента. Playwright, в таких случаях, выбрасывает ошибку Error: strict mode violation: locator('[field=descr]') resolved to 4 elements. Что переводится примерно как «разберись, че ты хочешь, потом приходи» «по такому локатору определяется 4 элемента». PW не выбирает за нас, с каким элементом работать, а просто останавливается. Хотите выполнения кода – давайте более точные инструкции. Ведь метод textContent() работает только с одним элементом, а тут их больше одного.

Итак, что же делать? Путя всего 2:

  • Путя 1й: напишите более точный локатор. И это — хорошая практика. Если у вас есть возомжность, посмотрите, что еще можно написать в локаторе, чтобы точно идентифицировать элемент.

  • Путя 2й и последний: объясните PW, какой из найденных элементов нужно выбрать. В нашем случае, мы просим взять первый — first. Кстати, угадайте, какой по порядку элемент мы получим, если напишем не .first(), а .last() ?

Раз уж мы умеем обращаться к первому подходящему и последнему подходящему элементу, возникает вопрос — а что, если я хочу обратиться к 4 из 10 элементов? Да или просто — к третьему и я не знаю, сколько их там будет всего? Здесь у нас есть метод .nth(number), который принимает на вход число — порядковый номер элемента. И да, индексация начинается с 0.

Получается, что nth(1) вернет мне второй по порядку элемент? Ага! А еще получается, что nth(0) – то же самое, что и first()? Ага! Просто «ферст» читается как-то проще, согласны?

Ссылочки на эти методы, если вы их читаете: nthfirst и last

Итак, мы умеем получать текст элемента. И тут, если вы работали с selenium’ом, например, вам уже все понятно: чтобы написать тест, нам нужно получить текст и сравнить его с ожидаемым. Ну как-то так, например:

`const { test, expect } = require("@playwright/test"); test("get text", async ({ page }) => { await page.goto("https://inzhenerka.tech/");

// сохранили текст элемента в переменную const description = await page.locator(«[field=descr]»).first().textContent(); // проверили, что текст в переменной равен тому, который мы указали expect(description).toEqual( «Помогаем инженерам повысить свою квалификацию на рынке труда и приобрести навыки международного уровня» ); });`

И это даже будет работать.

С другой стороны, если открыть документацию, можно увидеть вот такое предупреждение:

Untitled

Разработчики инструмента прямым текстом нам говорят, что, если хотите проверить текст, используйте лучше метод toHaveText(). Мы с вами в интернете давно и знаем, что в таких ситуациях нужно сразу спрашивать — а чем жто «лучше»?

Сначала давайте посмотрим, как будет выглядеть наш тест, если мы будем использовать рекомендуемый метод:

const { test, expect } = require("@playwright/test"); test("get text", async ({ page }) => { await page.goto("<https://inzhenerka.tech/>"); await expect(page.locator("[field=descr]").first()).toHaveText( "Помогаем инженерам повысить свою квалификацию на рынке труда и приобрести навыки международного уровня" ); }); 

Смотрите, обошлись без переменной description — сразу написали проверку, мол такой-то элемент должен содержать такой-то текст. В критерию «читаемость», один балл записываем в пользу второго подхода. Заметили, кстати, что теперь у expect() можно вызвать другой набор методов? Это все потому, что на вход мы передали не page, как раньше, а locator. Вот и методы подходящие появились.

У toHaveText() есть еще пара трюков в пороховницах.

Во-первых, этот метод умеет сравнивать, игнорируя регистр. Это пригодится вам, когда выяснится, что в HTML’е текст написан маленькими буквами, а на странице отображается КАПСОМ (спросите у своего фронтэнд разработчика, как такое можно организовать). И вот для того, чтобы не собирать шишки, подбирая правильный регистр у ожидаемого результата, мы можем просто передать правильную настройку:

await expect(page.locator("")).toHaveText("ожидаемый текст", {   ignoreCase: true, }); 

Вторая интересная фича метода toHaveText() — он умеет проверять текст у группы элементов. Как это работает: если ваш локатор определяет не один элемент на странице, а группу (например, список), то и для проверки текста у элементов мы должны передать группу (массив) значений. Метод соотнесет полученные и ожидаемые тексты 1-к-1. Если что-то не совпадет — ошибка. Примеры:

<!-- вот у нас есть вот такой список на странице  --> <ul>   <li>Билли</li>   <li>Вилли</li>   <li>Дилли</li> </ul> 
// ✓ Вот этот код проверит, что тексты у элементов соответственно равны переданным. await expect(page.locator("ul > li")).toHaveText(["Билли", "Вилли", "Дилли"]); // ✖ Вот такая проверка упадет, потому что текстовки идут в другом порядке await expect(page.locator("ul > li")).toHaveText(["Дилли", "Билли", "Вилли"]); // ✖ Такой тест тоже упадет, потому что текст одного из элементов не совпадем с ожидаемым await expect(page.locator("ul > li")).toHaveText([ "Билли", "Вилли", "Джонатан?", ]); // ✖ Вот тут сложнее. // Тест упадет, потому что локатор собирает не группу элементов (li), а только один (ul). // Нельзя сравнить текст одного элемента с группой текстов. await expect(page.locator("ul")).toHaveText(["Text 1", "Text 2", "Text 3"]); 

Ссылка на документацию В общем-то, действительно и удобнее, и код более читаемый. Давайте так и будем поступать: хотим получить данные — используем метод класса Locator. Хотим проверку — заносим локатор в метод expect и вызываем нам интересный метод.

Это бесплатная демо-часть урока тренажера по Playwright от INZHENERKA.TECH. Больше обсуждений по теме проходит в нашем сообществе по Playwright в телеграмме

Напомню о цели этой статьи: поделитесь своим мнением о примерах в тексте, как вам? Считаете ли вы их достаточно информативными?


ссылка на оригинал статьи https://habr.com/ru/articles/802767/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *