37

In one of my tests, I'm locating an element using a CSS selector:

element(by.css("ul.nav button"))

There is more than one element matching the query, but, since I need only the first one, I'm okay with the selector.

The problem is, protractor throws a warning:

WARNING - more than one element found for locator By.cssSelector("ul.nav button") - the first result will be used

Is it possible to suppress the warning? In other words, how can I let protractor know that I'm aware of the problem and don't want the warning to be shown anymore?


Using protractor development version (installed directly from the master branch).

alecxe
  • 414,977
  • 106
  • 935
  • 1,083

4 Answers4

69

Try this instead:

element.all(by.css("ul.nav button")).first()

Basically, this tells Protractor that you already know there's more than one element, and you just want the first one (like you said in your question).

Isaac Lyman
  • 2,124
  • 1
  • 19
  • 39
  • That works! As a bonus and out of curiosity, though, would be useful to know if it is possible to silence the warning, any ideas? Thanks. – alecxe Feb 11 '15 at 21:27
  • 3
    If there was one, it would be [here](https://github.com/angular/protractor/blob/master/docs/referenceConf.js). I don't see anything like that, though, and I think the reason is because non-specific locators make for very fragile tests. – Isaac Lyman Feb 11 '15 at 21:33
  • Yeah, I'm afraid I can turn it off only by setting an appropriate `logLevel` which would by extension turn off other warnings which is not good. But I totally agree about your last point, makes sense to me. Thanks for the help again. – alecxe Feb 11 '15 at 21:37
  • You've answered a couple of my questions, so I'm glad I could return the favor. – Isaac Lyman Feb 11 '15 at 21:38
7

The warning is there for a reason. You've tied your tests too closely to your data. The selector is too general & you should be more specific. Either by saying element(by.css("ul.nav button:nth-child(1)")) or scoping your search differently. Protractor tests aren't supposed to be testing style or dom, they're supposed to be testing business logic.

bwegs
  • 3,711
  • 2
  • 27
  • 31
Jon
  • 99
  • 1
  • 3
  • 1
    After long consideration, I'm downvoting this answer because: 1) it makes an accusation against the OP that, given the simplicity of the question, is completely unwarranted; 2) the given solution, although it may work, depends on a presumed DOM structure which is not stated in the question; 3) the answer claims that the given solution has specific advantages over the OP's code, but in reality it does not have these advantages; and 4) outside of the code sample, the answer amounts to little more than non-sequiturs and sermonizing. – Isaac Lyman May 23 '17 at 21:54
3

Less code:

$$("ul.nav button").first()
Yago
  • 144
  • 6
2

Do not underestimate xpath. You can solve thousands of problems with it, including this one

let elem = element(by.xpath('(//div//a)[3]'))

You can specify the number of element to use. Keep in mind the numbers start from 1, not 0 as usually in js

Sergey Pleshakov
  • 5,833
  • 2
  • 10
  • 30