playwright icon indicating copy to clipboard operation
playwright copied to clipboard

[BUG] Presence of >> selector corrupts independent evaluation of other selectors in list

Open Boeing787 opened this issue 2 years ago • 6 comments

Context:

  • Playwright Version: 1.24.2
  • Operating System: Mac
  • Node.js version: 18.5
  • Browser: All
  • Extra: N/A

Describe the bug

I'm using the >> selector in a broader statement made up of multiple selectors that is passed to a PlaywrightPage.locator, specifically, this:

fieldset:has-text('URL') >> input, button:has-text('Link Your Project')

Each of these independently (fieldset:has-text('URL') >> input and button:has-text('Link Your Project')) matches elements on the page, but when combined together, only the elements matching fieldset:has-text('URL') >> input are selected. This leads me to believe that the >> operator is corrupting the whole statement; Just like with CSS selectors, I'd expect the , to separate the individual statements so they can be evaluated independently, and their results combined.

Is there something I am misunderstanding about the >> operator, or is this a bug?

Boeing787 avatar Sep 19 '22 02:09 Boeing787

The below test passes for me. Can you share a self-contained example like I have below that illustrates the issue you are facing? I want to make sure we're debugging and solving the same issue. Thanks!

import { test, expect, Page } from '@playwright/test';

test('should work', async ({ page }) => {
  await page.setContent(`
    <form>
      <fieldset>
        <label for="url">URL</label><br/>
        <input type="text" id="url" name="url">
      </fieldset>
      <button>Link Your Project</button>
    </form>
  `);
  expect(page.locator("fieldset:has-text('URL') >> input")).toBeVisible();
  expect(page.locator("button:has-text('Link Your Project')")).toBeVisible();
  expect(page.locator("fieldset:has-text('URL') >> input, button:has-text('Link Your Project')')")).toHaveCount(2);
});

rwoll avatar Sep 19 '22 18:09 rwoll

hey @rwoll, I can repro what @Boeing787 is saying

the code

from lib.test_base import TestBase

issue_url = "https://github.com/microsoft/playwright/issues/17429"

url = "https://the-internet.herokuapp.com/"
TestBase.get_page().goto(url)

loc1 = TestBase.get_page().locator("xpath=//ul")
list1 = loc1.locator("a:has-text('Dropdown'), a:has-text('Checkboxes')")
list2 = loc1.locator("a:has-text('Dropdown') >> visible=true, a:has-text('Checkboxes') >> visible=true")
list3 = loc1.locator("a:has-text('Dropdown') >> visible=true, a:has-text('Checkboxes')")

print("Not using the >> operator, the count is : ", list1.count())
print("while using the >> operator, the count is : ", list2.count())
print("partially using the >> operator, the count is : ", list3.count())

image

GunjanSheth avatar Sep 20 '22 07:09 GunjanSheth

@GunjanSheth Thanks for your example! Looks like I forgot the awaits in my JS example leading me to the wrong conclusion. 🤦

Let me touch base with the team to sort out expected precedence of these operators so we can clarify in the docs as needed or apply fixes depending on the conclusion.

rwoll avatar Sep 20 '22 18:09 rwoll

I reviewed the following with @dgozman. It is working as expected and the last statement will fail:

import { test, expect } from '@playwright/test';

test('should work', async ({ page }) => {
  await page.setContent(`
    <form>
      <fieldset>
        <label for="url">URL</label><br/>
        <input type="text" id="url" name="url">
      </fieldset>
      <button>Link Your Project</button>
    </form>
  `);
  await expect(page.locator("fieldset:has-text('URL') >> input")).toBeVisible();
  await expect(page.locator("button:has-text('Link Your Project')")).toBeVisible();
  await expect(page.locator("fieldset:has-text('URL') >> input, button:has-text('Link Your Project')")).toHaveCount(2);
});

In this particular case, it can simply be fixed by dropping the use of >>:

  await expect(page.locator("fieldset:has-text('URL') input, button:has-text('Link Your Project')")).toHaveCount(2);

There's currently not a great way of expressing OR semantics when using the Playwright chaining (>>) locator.

rwoll avatar Sep 20 '22 18:09 rwoll

@Boeing787 Let me know if fieldset:has-text('URL') input, button:has-text('Link Your Project') works for your use case! If not, we'll convert this issue into a feature request for OR semantics with >> (through some yet-to-be determined API). (We've put some thought into the topic in the past, but have not introduced a solution yet.)

Thanks!

rwoll avatar Sep 20 '22 19:09 rwoll

There's currently not a great way of expressing OR semantics when using the Playwright chaining (>>) locator.

thanks @rwoll for looking into this and thanks @Boeing787 for bringing this out. Atleast for now we have a work around for the selector, but i guess we wont have the workaround while using >> visible=true, straightaway

GunjanSheth avatar Sep 21 '22 05:09 GunjanSheth

also please add OR semantics for getByTestId

for example with locator works perfectly. await page.locator('[data-testid=selector1], [data-testid=selector2').waitFor();

but with getByTestId await page.getByTestId('selector1, selector2').waitFor(); result is following: waiting for selector "internal:attr=[data-testid=selector1, selector2"]" to be visible

kodringer avatar Dec 27 '22 19:12 kodringer

This will be possible to achieve in the next version with Locator.or(), implemented in #21884.

dgozman avatar Mar 29 '23 15:03 dgozman