'How to get closest parent of element in Playwright?
I am quite new in playwright and i cannot find solution for how to get parent of element? Here is what i have so far:
const deliveryItems = await page.locator('.js-delivery-container'); //Items
const deliveryMethod = deliveryItems.locator('input[value="50"]'); //input in items selected by value
const example_parent = await deliveryMethod.closest('.js-delivery-name'); //name what i want to check
await expect(example_parent).toHaveText('Osobní odběr'); //check if selected right delivery
But when i run it.. there is a Error what popup in console:
TypeError: deliveryMethod.closest is not a function
33 |
34 | const deliveryMethod = deliveryItems.locator('input[value="50"]');
> 35 | const example_parent = await deliveryMethod.closest('.js-delivery-name');
Can anyone explain me this? Thanks
My structure looks like this:
<div class="select-content-box js-delivery-container">
<div class="select-content delivery-icon-factory">
<div class="extended-title transport-icon js-delivery-name">Osobní odběr</div>
<div class="extended-price js-delivery-price"></div>
<div class="select-btn">
<label class="label toggle">
<input type="radio" name="radio-delivery" value="50">
<div class="toggle-control"></div>
</label>
</div>
<div class="cleaner"></div>
<div class="select-address" style=""></div>
</div>
</div>
Solution 1:[1]
The ElementHandle.closest() method you are trying does not exist in the API at the moment (or is not yet available in the Playwright version you use, I only found it in this discussion #6015). That's the reason for the error.
The problem
You want to find a connection between the input field based on its value (input[value="50"]) and the .js-delivery-name element which is not possible, or at least any .parentElement?.parentElement?.nextSibling?.nextSibling... structure would be extremely fragile, same applies to XPath axes (they are not even in child-ancestor relation here but a kinda "second niece/nephew-second aunt/uncle" relation).
Possible solution
I suggest the following. "Playwright can select elements based on the page layout. These can be combined with regular CSS for better results."
1-2.) desired name within + delivery items: using the child combinator and universal selector you can compose patterns that can grab your desired elements within a container element, e.g.: .js-delivery-container > * .js-delivery-name
3.) above this input: when you have the exact selector then you can grab it by finding the closest element matches another CSS selector query in specific directions with :above(), :below(), :near(), :left-of() and :right-of() methods, e.g. :above(input[value="50"]). As the docs says: "Matches elements that are above any of the elements matching the inner selector".
// delivery items desired name within above this input
// ______________________ __ _______________ ________________________
// | || || || |
const parent = page.locator('.js-delivery-container > * .js-delivery-name:above(input[value="50"])')
await expect(parent).toHaveText(/Osobní odb?r/)
Note: Layout selectors use bounding client rect to compute the distance and relative position of the elements, so these above, below etc. directions are strictly meant for layout position and not for DOM ancestry.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | theDavidBarton |
