Repository navigation
Description
I would really love, if Playwright could combine selectors of different kinds or selectors of same kind. Because I would like to simplify writing selectors.
For example, all navigation links on our website has class called "nav-link", and I also want to make sure they aren't hidden for example. So I would really love to create a class called NavigationLink, which has selector:
"xpath=//a[contains(Class, 'nav-link') and not(contains(Class, 'dg-hidden'))]"
Now I would just write something like:
var someNavigationLink = new NavigationLink(id='hello')
And it would combine that kinda long selector I defined in my class NavigationLink that would be used for all navigation links, and it would then be super easy to just define what else I know about some concrete navigation link like id=´'hello' or name='hello' or any other selector, but there would be no need to define that long selector over and over again, because it would be combined together. Now this was just an example to illustrate what I would really love to achieve, but you could imagine even more complicated selectors that I know about some element types.
But I don't think it's possible to do with Playwright right now.
There is fantastic operator >> that can combine multiple selectors like selector_1 >> selector_2, but in a way, that selector_2 looks in a subtree of selector_1. I would like to have some operator like selector_1 && selector_2, which would do intersection of elements found with selector_1 and elements found with selector_2.
This && operator would allow me to define that long selector in the class, and ask for another supplementary selector in constructor, and inside this class I would be able to combine them.
But there is also another use case: If anybody wants to just simply combine different selector types (selector engines) in selector, like: "css='input:enabled' && name='hello' && text='world'". It's just a normal simple selector, but thanks to this && operator, I would be able to beautifully combine different selector engines.
Thank you very much for any replies and if you consider implementing it, I would greatly greatly appreciate it :)
Because I really do believe, that this feature could be super cool and also could be very useful.
Activity
andydelso commentedon Mar 8, 2022
Could you get them all and then just filter out
dg-hiddenones? Just trying to get more details as to reason and use of the feature.You could also have the component class take in a boolean for hidden and apply that in the constructor (depending on the language being used)
PeterHevesi commentedon Mar 9, 2022
I am not sure what you suggest. Surely I am thinking about implementing it myself, but I don't think it's that easy, even one of Playwright guys Max Schmitt told me, that it's not that easy.
And I tried so hard to explain use case of this feature as clearly as I could :D
But to make it simple and clear, this feature would allow a huge simplification of complicated selectors that are used for many elements of a same kind.
If it's only one element, I totally don't care, but when I have many elements of same kind with complicated selectors, it's kinda huge pain to maintain them. So I want to extract some common part of these complicated selectors into a base class, and then all these elements I need to use would be able to have much simpler selectors. But it's not possible to combine selectors, so I am not able to achieve this extraction into base class.
Another use case is just simple combinations of different selector engines in normal simple selectors (also not possible right now):
var selector = "css='input:enabled' && name='hello' && text='world'"
[-][Feature] Combine different selectors to locate element[/-][+][Feature] Combine different selectors to locate elements[/+]azad-derakhshani-GS commentedon Jun 27, 2022
You could just write your own helper function that achieves what you want:
So from there it would be pretty straightforward and easy to use.
To use your example from above:
let someNavigationLink = await this.getNavigationLinkByAttribute('id','hello');PeterHevesi commentedon Jun 29, 2022
Thanks for your reply :)
Surely I can do that, but it's not universal, you did it only using attribute and it's value in xpath.
But there are some disadvantages of xpath in some cases, when compared to css selectors.
For example when I want to test an element if it contains some class, i can just write:
//someElement[contains(Class, 'someClass')]
But this example can leads to problems when someClass also appears in plural form like someClasses.
(** we can have like for example: dg-item and dg-items)
Then this selector would match singular and plural form of that class, so if I don't want that, I just need to write:
//someElement[contains(Class, 'someClass') and not(contains(Class, 'someClasses'))]
But in CSS, I could write:
someElement.someClass and it would immediately solve this problem, because that's how CSS selectors match up classes..
==> Soooo I want to achieve this universally across all Playwright selector engines, wheter it is xpath, css, or any other Playwright selector engine like text=... or hasText=.... and so on, because these are also useful.
PS:
I don't actually need it anymore to solve any of my problem, and of course I could do helper methods like you showed to achieve these kind of things (I actually created a lot of infrastructure to deal with problems that happens in testing :D)
Buut while I was thinking about that, when you have >> operator, which looks inside the subtree of a current locator, it could also even have << this operator, which would look in ancestors of that locator and also && operator, which would do union of elements found and also II operator that would do that intersection.
Across all selector engines.... >> and << and && and II would be super combo of helping operators, that would made Playwright selectors even much much better...
And by the way, I always do mix up xpath and css but with that >> operator...
Let's say I define locator for whole component and then locator for subElement or subComponent and so I really do have selectors, which looks like this:
xpath=... >> css=... >> css=... >> text=.... >> xpath=....
That's how selectors are created when you call Locator.Locator() , it just puts that >> there...
So just imagine, if you could do this kind selector, but also using << and && and II operators...
PeterHevesi commentedon Jun 29, 2022
And in Playwright, they probably got inspired by my idea and created that Filter function in version 1.22, so thank you very much 🥇:)
azad-derakhshani-GS commentedon Jul 4, 2022
Hehe yeah I also had to create a lot of infrastructure to deal with certain issues. :D
Yeah I get what you mean, although xpath also supports
starts-withandends-with, so you could doends-with(@class, 'someClass')for example.That's a good idea actually, adding the other operators to PW!
I've been using other CSS combinators too, not just >>, but also > (child) and + (adjacent sibling) for example. But they are quite limited, unlike Xpath they don't offer ancestors, parents etc.
That's actually why I always preferred Xpath, because it has a lot more features like and/or operators and all the node selectors to reach anything in the DOM you want. Currently only using CSS for selectors with unique and descriptive IDs, which aren't that many at the moment. 😂
PeterHevesi commentedon Jul 12, 2022
I am glad you like my idea 😊
And I didn't know about > (child) and + (adjacent sibling) operators, so thank you for this tip 🙂
And I also prefer XPath, which is much more powerful than CSS.
But even better then just XPath selectors are Playwright selectors 😂
It is sooo awesome you can combine whatever selector engines together and even create your own, it's just fantastic 🙂
I really want to learn how to create custom selector engines in Playwright.NET, I am not sure, if there is a bug in Playwright.NET for that feature, but I just couldn't make it work even with that example that is shown in documentation for Playwright.NET:
And that example is obviously a little bit outdated...
https://playwright.dev/dotnet/docs/api/class-selectors#selectors-register
azad-derakhshani-GS commentedon Jul 12, 2022
Yeah I only found them here a few months ago, hadn't used CSS that much before either:
https://www.w3schools.com/css/css_combinators.asp
Also found this helpful since it provides things like "starts with" etc:
https://www.w3schools.com/css/css_attribute_selectors.asp
dgozman commentedon Mar 23, 2023
This issue seems to be covered by
Locator.filter, CSS>and>>combinators and XPath syntax. Please file a new issue if you are missing some specific usecase.