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

[Feature] Docs update for text= vs :has-text vs :text #5748

Closed
thernstig opened this issue Mar 7, 2021 · 6 comments
Closed

[Feature] Docs update for text= vs :has-text vs :text #5748

thernstig opened this issue Mar 7, 2021 · 6 comments

Comments

@thernstig
Copy link
Contributor

I just read https://playwright.dev/docs/selectors/#text-selector

There are a few ways to look for text on a page, but I cannot from the docs deduct which one I should use. For example these three:

await page.click('#nav-bar >> text=Playwright');
await page.click('#nav-bar:has-text("Playwright")');
await page.click('#nav-bar :text("Playwright")');

To me, these seem functionally equivalent from the docs. Is that assumption incorrect?
Also, which one is the Best practice to use out of these? I've always used >> text before the other psuedo classes became available, but I am not sure that if I refactor my code which of these I should use. >> text has looks cleaner to me, easier to read, and is faster to type.

@thernstig thernstig changed the title [Feature] Docs update for text= vs has-text [Feature] Docs update for text= vs :has-text vs :text Mar 7, 2021
@thernstig thernstig changed the title [Feature] Docs update for text= vs :has-text vs :text [Feature] Docs update for text= vs :has-text vs :text Mar 7, 2021
@yury-s
Copy link
Member

yury-s commented Mar 9, 2021

If >> text looks cleaner to you and achieves desired result go ahead and use it! Each element could be selected in a number of different ways with different types of selectors, just use the one that works for you. Look at other types of selectors if you cannot express your current condition.

These three are very similar indeed and the difference is subtle. All of them will perform case-insensitive match of the text regardless of its dom structure, i.e. the text could be spread across several nodes. >> text=Playwright can be combined with other types of selectors (e.g. it could follow an xpath) while :has-text() and :text() should be a part of a CSS selector. The latter two will select different elements:

  await page.setContent(`<div id=nav-bar>Hello<i>,</i> <span id=nav-name>Playwright</span><b>!</b></div>`);

  expect(await page.$eval(`#nav-bar >> text=Playwright`, e => e.id)).toBe('nav-name');
  expect(await page.$eval(`#nav-bar:has-text("Playwright")`, e => e.id)).toBe('nav-bar');
  expect(await page.$eval(`#nav-bar :text("Playwright")`, e => e.id)).toBe('nav-name');

You are right that we should add more examples to highlight differences between different selector types.

@thernstig
Copy link
Contributor Author

Thanks for the clarification! A doc update to let the reader know this would be good. It seems that the first and last example are functionally equivalent, but that >> text is more powerful as it can be combined with other selector engines.

Aside: To me the second example with #nav-bar:has-text("Playwright") is the most confusing that it selects nav-bar. What if it was nested within multiple divs like <div id=nav-foo>Hello, <div id=nav-bar>Hello<i>,</i> <span id=nav-name>Playwright</span><b>!</b></div>!</div>?

@yury-s
Copy link
Member

yury-s commented Mar 9, 2021

Aside: To me the second example with #nav-bar:has-text("Playwright") is the most confusing that it selects nav-bar.
We'll add more examples for the selectors to clarify the differences.

What if it was nested within multiple divs like <div id=nav-foo>Hello, <div id=nav-bar>Hello<i>,</i> <span id=nav-name>Playwright</span><b>!</b></div>!</div>?

It would still match it and the documentation mentions that:
image

but in any case more examples (probably more complex) would be helpful.

@thernstig
Copy link
Contributor Author

thernstig commented Mar 10, 2021

It would still match it

"it" in this case instead being nav-foo?

But to me that would mean it matches the outer-most element of the hold web page, at least, that is how I read it. I.e. it should always match <body> (or <html>) in a real website? 😕

@yury-s
Copy link
Member

yury-s commented Mar 10, 2021

"it" in this case instead being nav-foo?

No, by "it" I meant #nav-bar, the selector would have to be #nav-foo:has-text("Playwright") to match nav-foo. This is no different from other css selectors, you specify two conditions on the selected element: it has to have id=nav-bar and also contain text "Playwright".

@thernstig
Copy link
Contributor Author

Got it, thanks!

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

3 participants