msmith1114
msmith1114

Reputation: 3231

Proper way of storing Playwright element for parent

Im trying to figure out the best way to store an element locator to eventually use that locator to find the parent.

For example, in this particular problem I have a table row (<tr>), which has a unique text on it Foo (as a <label>). This table row also has a checkbox. Looks basically like this:

Table Row

(Pretend there is an outline, but that's essentially the table row layout. The table has a lot of rows (Undetermined amount) so I cannot just say nth row. So the obvious unique element is to grab the element via it's text and store the "child" locator. Which i've done like this:

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

However now I need to grab the parent of it, that is a <tr> so I can then grab the checkbox to click on.

What is the best way about this? Playwright doesn't exactly have a "parent" selector, the closest I could find is the https://playwright.dev/docs/api/class-page#page-locator-option-has has option.

So from my understanding I would need to do something like:

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

Or is there a better way?

As a sidenote: When storing a locator, it says the await keyword is not needed (The 1st row of code above). Don't we need await when storing a locator?

jsfiddle: https://jsfiddle.net/mLb50jwp/ (Obviously the simplest version of it)

Upvotes: 6

Views: 14100

Answers (1)

Vishal Aggarwal
Vishal Aggarwal

Reputation: 4207

How about this direct flexible locator to checkbox as an simple answer:

const expectedName="Foo"    
const locator = `//tr[contains(.,${expectedName})]//input[@type="checkbox"]`

Playwright way to get parent locator:

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

The parent element could be selected with .., which is a short form for xpath=..

General Xpath way to get parent locator:

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

To get Parent with specific class:

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

-- returns parent element only of exact node type.

Why await keyword is required in general?

await is usually used to unwrap promises by passing a Promise as the expression. Using await pauses the execution of its surrounding async function until the promise is settled (that is, fulfilled or rejected). When execution resumes, the value of the await expression becomes that of the fulfilled promise.

Why await keyword is NOT required while declaring playwright locator?

At the time of declaring locator there is no promise to be resolved so await keyword not required however while performing an operation like 'click' promise is returned from playwright for which await keyword is required to pause the execution until promise is resolved.

Upvotes: 13

Related Questions