Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REGRESSION]: Text selector changed behavior #5634

Closed
niranjan-borawake opened this issue Feb 26, 2021 · 9 comments
Closed

[REGRESSION]: Text selector changed behavior #5634

niranjan-borawake opened this issue Feb 26, 2021 · 9 comments
Assignees

Comments

@niranjan-borawake
Copy link

niranjan-borawake commented Feb 26, 2021

Context:

  • GOOD Playwright Version: 1.8.0
  • BAD Playwright Version: 1.9.1
  • Operating System: Windows, Linux or Mac
  • Extra: N/A

Describe the bug

As per the fix #5603 and the comment - #5603 (comment)

For
<div>text1<span>child node</span>text2</div>
In v1.8.0 - text="child" did not select <span>child node</span>
But it does select it in v1.9.1.

@ychaudhari
Copy link

I have noticed that text selectors have been broken in 1.9.0 and 1.9.1
e.g.
I have an element like this:

<h2>
	<span>Title:</span>
	&nbsp;
	<span>text</span>
</h2>

My selector await expect(page).toHaveSelector('"text"'); was working in 1.8.1 but breaks in 1.9.1

I can't seem to downgrade to 1.8.1 as my ci pipeline uses mcr.microsoft.com/playwright:bionic which downloads playwright 1.9.1

@ychaudhari
Copy link

Is there a workaround for this?

@niranjan-borawake
Copy link
Author

Use a regex selector instead - /^text$/.

@dgozman
Copy link
Contributor

dgozman commented Mar 1, 2021

@ychaudhari Do you have a repro script by any chance? The following works for me as expected with 1.9.1:

await page.setContent(`
  <h2>
    <span>Title:</span>
    &nbsp;
    <span>text</span>
  </h2>`);
console.log(await page.$eval('"text"', e => e.outerHTML)); // prints "<span>text</span>"

@aha-oretama
Copy link

:text-is pseudo-class has the same issue...

<div>text1<span>child node</span>text2</div>
In v1.8.0 - text:is("child") did not select <span>child node</span>
But it does select it in v1.9.1.

@ychaudhari
Copy link

ychaudhari commented Mar 2, 2021

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 1000 });
  const page = await browser.newPage();

  await page.setContent(`
        <div>
           <h1>MyApp Login</h1>
           <form action="#">
              <div>
                 <div><button type="button">Login</button></div>
                 <div ><a href="/">My Login</a></div>
              </div>
           </form>
        </div>
      `);

  await page.click('"Login"');
  console.log(await page.$eval('"Login"', e => e.outerHTML));
  await browser.close();
})();

@dgozman , In above code if you turn debug logs on DEBUG=pw:api you will see following logs:

pw:api <= page.setContent succeeded +1s                                         
pw:api => page.click started +3ms                                               
pw:api waiting for selector ""Login"" +4ms                                      
pw:api   selector resolved to visible <h1>MyApp Login</h1> +15ms 

Note await page.click('"Login"') resolves to <h1>MyApp Login</h1> instead of <button type="button">Login</button>
'"Login"' should have been full-string, case-sensitive match.

@dgozman
Copy link
Contributor

dgozman commented Mar 2, 2021

@ychaudhari Thank you for the snippet! That's right, "Login" has slightly changed the behavior, and now resolves to h1 in this case. I'd suggest to use button:text("Login") instead. Overall, the more precise selector you use, the better the results. Let me think about what we can do. Sorry for inconvenience.

@pavelfeldman pavelfeldman changed the title [REGRESSION]: [REGRESSION]: Test selector changed behavior Mar 2, 2021
@ychaudhari
Copy link

ychaudhari commented Mar 3, 2021

Thanks @dgozman for the reply,
What is the way to match a full, case-sensitive string?

The documentation seems to be updated and it says that double quotes match is case-sensitive. But now, it does not specify if it is a full-string match. If it is updated to accept partial match then, what is the logic of matching this case-sensitive string?

Personally It is confusing to me that Login -> My Login (h1) match takes priority over Login -> Login (button)

PS: As per https://playwright.dev/docs/selectors/#prioritize-user-facing-attributes I would like to use only user facing text attribute - i.e. page.click('"Login"') instead of adding a application design element 'button' to the selector - page.click('button:text("Login"))

Here is my view on current state:

const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 1000 });
  const page = await browser.newPage();

  await page.setContent(`
        <div>
           <h1>MyApp Login</h1>
               <form action="#">
                  <div>
                     <div><button type="button">Login</button></div>
                     <div ><a href="/">My Login</a></div>
                  </div>
               </form>
        </div>
      `);

  // full-string, case-sensitive -- Expected: <button type="button">Login</button> ; Actual: <h1>MyApp Login</h1>
  console.log(await page.$eval('"Login"', (e) => e.outerHTML));

  // full-string, case-sensitive -- Expected: <button type="button">Login</button> ; Actual: <h1>MyApp Login</h1>
  console.log(await page.$eval('text="Login"', (e) => e.outerHTML));

  // partial-text, case-insensitive -- OK (prints <h1>MyApp Login</h1>)
  console.log(await page.$eval('text=lOgIn', (e) => e.outerHTML));

  // regex, full-string -- OK (prints <button type="button">Login</button>)
  console.log(await page.$eval('text=/^Login$/', (e) => e.outerHTML));

  // regex, partial-text, case-sensitive -- OK (prints <h1>MyApp Login</h1>)
  console.log(await page.$eval('text=/Login/', (e) => e.outerHTML));

  await browser.close();
})();

@dgozman
Copy link
Contributor

dgozman commented Mar 10, 2021

This is fixed in playwright v1.9.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants