4

Currently, I have the following page object fields:

this.filterTeamDropdown = $("filter-item-edit .dropdown button");
this.teams = this.filterTeamDropdown.all(by.xpath("following-sibling::ul//li[contains(@class, 'dropdown-list-item')]"));

Is there a way to replace the XPath locator for the teams field and have a CSS selector instead?


The motivation for it is coming from the Style Guide and the recommendation not to use XPaths.

From what I understand, it is impossible to have a CSS selector to go to the next sibling starting from current element in the context. But, are there any alternatives?

7
  • may be useful: saucelabs.com/selenium/css-selectors Commented Jul 6, 2016 at 17:02
  • 2
    @Bhansa yeah, I know the + is what I'm looking for, but the problem is, I cannot simply start the selector with + and expect it to work in the context of the current element. And, there is no way to reference the current node inside the selector string. Thanks. Commented Jul 6, 2016 at 17:03
  • 2
    XPath may be the "most brittle" strategy as the style guide says, but I suspect that's only because it can do things that CSS can't. An XPath expression that does the same thing as a CSS expression is no more brittle than the equivalent CSS. And in this case, CSS apparently can't do what you need. Commented Jul 6, 2016 at 18:07
  • 2
    @LarsH great point. I actually think the guide is too cruel and has too strong of a statement about the XPaths since, clearly, there are actual practical use cases for it where there is no direct alternative in CSS selectors. Sometimes though people overuse the xpaths as a silver bullet applying to every locator in the codebase which results into overcompilcating the problems and making the maintaining the test code harder. Thanks, feel free to post it as an answer - "no, still use xpath in this case and don't worry" is a valid opinion. Commented Jul 6, 2016 at 18:13
  • 1
    Alecxe, I agree, the style guide's "never" recommendation is too strong. XPath has certainly been abused by those who try to use it without understanding, but the guide is overreacting. As with any language, if you work on a team and others have to maintain your code, you need to consider that when you choose what language to use. XPath is also less well suited to predicates about classes. (I hesitate to submit an answer because I don't know CSS well enough to say that it can't do 'following-sibling from current element'.) Commented Jul 6, 2016 at 18:19

2 Answers 2

5

Saying NEVER to anything is silly. I strongly favor CSS selectors because locating element by id, CSS selector, just about anything... is faster than XPath. But... at the same time we're talking a few ms of difference.

There are some things that XPath can do that no other locator method can. One example that comes to mind is finding an element (other than A) by contained element text. Other than that I generally stick to CSS selectors when ID doesn't work.

I strongly dislike a lot of people's locator strategies on SO because XPath seems to be the goto way to find elements to the point where it's silly. I've seen people looking for nothing but an id and using XPath. I think part of it is the ease of which you can obtain an XPath, right click on element in inspector and copy XPath and paste in code. The problem with that, as I'm sure you know, is that sometimes (many times?) that results in a very brittle XPath but some/many people don't know any better.

All that said, I'll point you to the W3C CSS Selector reference and maybe you can find what you are looking for. There are some sibling combinators in there but I don't have your HTML so I don't know which, if any, of them would work.

https://www.w3.org/TR/selectors/#selectors

https://www.w3.org/TR/selectors/#adjacent-sibling-combinators


I just read some of the comments below your question and see that you already knew about the + combinator. Is there some reason you can't reuse your initial locator CSS with the XPath converted string? I don't know if this is even valid/usable but I've combined the two locators you provided in your code after converting the XPath to a CSS selector.

filter-item-edit .dropdown button + ul li.dropdown-list-item
Sign up to request clarification or add additional context in comments.

1 Comment

Found a way to solve it with Protractor, check out my answer. Thanks.
1

There is an another, Protractor-specific way to solve it - use the locator() of the parent element and concatenate to make a child element selector:

this.filterTeamDropdown = $("filter-item-edit .dropdown button");
this.teams = this.filterTeamDropdown.$$(this.filterTeamDropdown.locator().value + " + ul li.dropdown-list-item")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.