microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
66.82k stars 3.66k forks source link

[Feature] Ability to use layout selectors ('right-of', 'above', etc) if inner selector is Locator #12542

Open Shaddix opened 2 years ago

Shaddix commented 2 years ago

I have a Locator instance (DOM element located using page.locator()). I'd like to find the input that is 'near' to my Locator. Seems like currently it's not possible, or at least I haven't found it in docs. What I could use is page.locator('input:near(__repeat_whole_locator_xpath_here__') but it seems inconvenient.

My use case: we use a PageObject pattern, and each PageObject class has a Locator that refers to page area of the object. Let's say one of the smallest PageObjects is a drop-down element using e.g. FluentUI. I create a Locator for the DropDown, click on Locator, and would like to find the list of elements that are opened. Usually this drop-down-list appears somewhere far away in DOM, but close to the object visually, so using 'near' selector makes sense. So, I'd like to find this drop-down-list that is near to my Locator, and I don't see a convenient way to achieve that.

mskelton commented 2 years ago

This would make testing patterns like this possible:

const a = page.locator('"My element"')
const b = page.locator('"My other element"')

expect(a.above(b)).toBeVisible()

Could even be neat to have a matcher like this:

const a = page.locator('"My element"')
const b = page.locator('"My other element"')

expect(a).toBeAbove(b)

I'm doing some testing like this to test sorted lists of data. Using the layout selectors are pretty powerful for testing sorting.

Camo30 commented 2 years ago

@dgozman Too bad that these selectors were removed with 0e2855348cba314de3484364eb926626ca97fbd2 after adding them with commit 54dd6d01e5cf4847b40ded0663e8c3e6a60cd939. What was the reason for doing so? I definitely have a use case for that - it would be great to get that back.

dgozman commented 2 years ago

@Camo30 We were not satisfied with the API, so decided to remove for now. We'll probably bring them back in one of the future release. Let me reopen the issue.

Camo30 commented 2 years ago

@dgozman Thanks for reopening. In my opinion the api was a great improvement. I'm heavily using the page objects pattern for locators and because of this I often need to get from one locator to the next one without reusing the same selector twice.

For example:

<div class="form-group">
  <input type="text" class="form-control" id="username"></input>
  <div>
    <span class="validation-error"></span>
  </div>
</div>
class LoginPage {
    readonly page: Page;

    constructor(page: Page) {
        this.page = page;
    }

    get userTextBox(): Locator {
        return this.page.locator("id=username");
    }

    get userTextBoxValidationAlert(): Locator {
        // The line below works but here I have to reuse the selector which is error prone
        return this.page.locator('#username + div span.validation-error');

        // It would be great to be able to use it like that
        // return this.userTextBox.locatorBelow("div span.validation-error");
    }
Faithfinder commented 1 year ago

Would love to see this. Would allow removing a bunch of hacks.