3
votes

I get this error when I try to run the code below:

Failed: element not visible

Following is the html code for the elements I want to locate:

<a class="dropdown-toggle ng-binding ng-scope" aria-expanded="false"    
role="button" href="/" data-toggle="dropdown" ng-if="tab.subtabs">
Content
<span class="caret"></span></a>
<ul class="dropdown-menu ng-scope" role="menu" ng-if="tab.subtabs">
<li class="ng-scope" ng-repeat="test in tab.subtabs">
<a class="ng-binding" target="_self" href="/custom/ui">Custom</a>
</li>
<li class="ng-scope" ng-repeat="test in tab.subtabs">
<a class="ng-binding" target="_self" href="/patch/ui">Patch</a></li>
<li class="ng-scope" ng-repeat="test in tab.subtabs">
<a class="ng-binding" target="_self" href="/swd/ui">Software</a>

I want to click on element within the tags:

<a class="ng-binding" target="_self" href="/custom/ui">Custom</a>
<a class="ng-binding" target="_self" href="/patch/ui">Patch</a>
<a class="ng-binding" target="_self" href="/swd/ui">Software</a>

I have tried following code in protractor, but it is not working:

it("should click on Content and then custom", function(){
    element(by.xpath('/html/body/bf-header/div/nav/div/div/div[2]/ul[1]  
   /li[2]/a')).element(by.xpath('/html/body/bf-header/div/nav/div/div   
   /div[2]/ul[1]/li[3]/ul/li[1]')).click();
1

1 Answers

2
votes

element(by.xpath('/html/body/bf-header/div/nav/div/div/div[2]/ul[1]
/li[2]/a')).element(by.xpath('/html/body/bf-header/div/nav/div/div
/div[2]/ul[1]/li[3]/ul/li[1]')).click();

Well, now you can probably see why the Protractor Style Guide recommends not to ever use XPath location technique:

NEVER use xpath

Why?

  • It's the slowest and most brittle locator strategy of all
  • Markup is very easily subject to change and therefore xpath locators require a lot of maintenance
  • xpath expressions are unreadable and very hard to debug

It is not always true and, if you choose XPath, the expressions you make must at least really be simple and readable. The first thing to fix, if you are gonna stay with XPaths, is not to make absolute XPath expressions - you don't have to start with html element and check every single element going down the tree to the desired element.


In this case, simple "by link text" or "by partial link text" locators should work perfectly:

element(by.linkText("Custom")).click();

Note that the Failed: element not visible error might be thrown, because you don't click the menu to open it up, before trying to click the submenu (assuming these are the submenu links you need to click).

You might also need to wait for the element to be clickable:

var EC = protractor.ExpectedConditions;
var custom = element(by.linkText("Custom"));

browser.wait(Ec.elementToBeClickable(custom), 5000);
custom.click();

Hope that helps.