Правильный способ хранения элемента Playwright для родителя

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

Например, в этой конкретной задаче у меня есть строка таблицы (<tr>), в которой есть уникальный текст Foo (как <label>). Эта строка таблицы также имеет флажок. Выглядит в основном так:

(Представьте, что есть схема, но это, по сути, макет строки таблицы. В таблице много строк (неопределенное количество), поэтому я не могу просто сказать nth строка. Таким образом, очевидным уникальным элементом является захват элемента через его текст и сохранение "дочерний" локатор, который я сделал так:

const tableRow = page.locator('label:has-text("Foo")')

Однако теперь мне нужно захватить его родителя, то есть <tr>, чтобы затем я мог захватить флажок, чтобы щелкнуть по нему.

Каков наилучший способ по этому поводу? У Playwright точно нет «родительского» селектора, самый близкий, который я смог найти, это опция https://playwright.dev/docs/api/class-page#page-locator-option-hashas.

Итак, насколько я понимаю, мне нужно сделать что-то вроде:

  const tableRow = await page.locator('tr', { has: page.locator('label:has-text("Foo")') })
  await tableRow.locator('input[type = "checkbox"]').check()

Или есть лучший способ?

В качестве примечания: при сохранении локатора он говорит, что ключевое слово await не требуется (1-я строка кода выше). Разве нам не нужен await при хранении локатора?

jsfiddle: https://jsfiddle.net/mLb50jwp/ (очевидно, самая простая его версия)

Если вы поделитесь минимально воспроизводимым примером вашего веб-сайта/разметки и исполняемого кода, гораздо проще предоставить лучшее решение. Тем не менее, ваше второе решение выглядит разумным — получить строку с этой меткой, и у вас есть и родитель, и дочерний элемент. Начните с вершины дерева и работайте вниз, а не снизу вверх. Локаторы оцениваются лениво, поэтому вам нужно только await, когда вы выполняете действие, например .click() или .check().

ggorlen 11.04.2023 19:47

@ggorlen я добавил простой jsfiddle

msmith1114 11.04.2023 19:59

Спасибо, а не могли бы вы указать код в вопросе? Внешние ссылки со временем исчезают, и у нас есть фрагменты, которые запускают код.

ggorlen 11.04.2023 20:04

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

ggorlen 11.04.2023 20:12

В приведенном ниже ответе показано, как получить родителя («..»), но нужно ли вам получать его с помощью родителя? На самом деле я бы рекомендовал подход has, так как он не только более семантически получает строку на основе метки, как вы хотели, но и если туда добавляется дополнительный div или что-то в этом роде, он все равно будет работать. Относительные селекторы, такие как прямой родительский или дочерний (вместо предок/потомок), как правило, очень хрупкие и неустойчивы к изменениям разработчиков.

David R 12.04.2023 00:46

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

Vishal Aggarwal 12.04.2023 11:12

@VishalAggarwal Я так и сделал, и да, это правда, так что это хорошее решение. Одна потенциальная проблема заключается в том, что он найдет строки с этим текстом в любом месте, а не только метку, но это может не иметь значения для их случая, поскольку это все, что у них есть. И вообще, я бы порекомендовал, чтобы локаторы больше соответствовали тому, как пользователь будет находить, или другим практикам или семантической структуре, которую предоставляет Playwright, а не xpath, например has. Тем не менее, ваш лучший ответ определенно следует той же гибкой, а не абсолютной идее, как вы сказали, и представляет собой надежный селектор/подход xpath.

David R 12.04.2023 19:35

Кроме того, основываясь на их заявлении, что они хотели использовать локатор для ребенка, чтобы затем найти родителя, если это действительно / конкретно то, что они хотят сделать, has, как они просили, в этом случае показалось наиболее подходящим решением.

David R 12.04.2023 19:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
178
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как насчет этого прямого гибкого локатора для флажка в качестве простого ответа:

const expectedName = "Foo"    
    '//tr[contains(.,"'+expectedName+'")]//input[@type = "checkbox"]'

Драматургический способ получить родительский локатор:

parent_locator = page.get_by_role("button").locator('..')

Родительский элемент можно выбрать с помощью .., что является сокращением от xpath=..

Общий Xpath способ получить родительский локатор:

Xpath=//*[@id='rt-feature']//parent::div

Чтобы получить Parent с определенным классом:

//span/parent::div[@class = "parent"]

-- возвращает родительский элемент только точного типа узла.

Зачем вообще требуется ключевое слово await?

await обычно используется для развертывания обещаний путем передачи промиса в качестве выражения. Использование await приостанавливает выполнение окружающей его асинхронной функции до тех пор, пока обещание не будет выполнено (то есть выполнено или отклонено). Когда выполнение возобновляется, значение выражения ожидания становится значением выполненного обещания.

Почему ключевое слово await НЕ требуется при объявлении драматурга локатора?

Во время объявления локатора нет обещания для разрешения, поэтому ключевое слово await не требуется, однако при выполнении операции, такой как «щелчок», обещание возвращается от драматурга, для которого требуется ключевое слово await, чтобы приостановить выполнение до обещания разрешено.

Предоставление нескольких вариантов — это хорошо. Одно замечание заключается в том, что локатор — это не просто строка, это похоже на то, что он просто определяет, как найти, а не на самом деле определяет местоположение или выполняет какое-либо действие/что-либо асинхронное.

David R 12.04.2023 00:48

Другие вопросы по теме