0

I am encountering a very unusual thing, the one I haven't seen before. There is one element I needed to find for testing purposes, it is visible on the page and I can find its unique relative XPath with rclick-->inspect option, but in run time it is not recognized. Here is more info:

  1. I know for sure that the element is not in any of the frames because I checked and all frames have different XPath.

  2. I tried to get all elements of the page and print their text (the element I need does have text) with //* option and the text I needed wasn't printed

  3. I tried full XPath and very strangely beside the element I need, there is another element with the same full XPath. For sure relative XPath can be duplicate, but I thought it is not possible with full XPath. How can it happen?

  4. Also, when I used that full XPath to put all elements in a list, the size of the list was 1. In other words, it found the other element, not the one I needed. How can all that happen?

The XPaths are:

  • relative - //*[@id='NoChainFound']
  • absolute - /html/body/div[5]/div[2]

The HTML I am looking at is:

<div id="NoChainFound" ng-show="!inGantt &amp;&amp; isChainEmpty() &amp;&amp; serviceId">This service appointment has no scheduling dependencies. 
    <a class="learn-more" href="help.salesforce.com/articleView?id=pfs_complex_work.htm" target="_blank">Learn More</a>
</div> 

My code is:

WebElement message = driver.findElement (By.xpath("//*[@id='NoChainFound']"));

And the error is:

no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id='NoChainFound']"}(Session info: chrome=79.0.3945.88)(Driver info: chromedriver=2.40.565498
  • Please put the Dom and the xpath – PDHide Jan 4 at 10:18
  • Have u used explicit wait ? – PDHide Jan 4 at 10:19
  • Absolute xpath doesn't mean u will get Oly 1 element , u will get all siblings also /a/b , gives all the b tag directly under a – PDHide Jan 4 at 10:22
  • here is xpath - relative //*[@id='NoChainFound'] – Richardson Jan 5 at 1:20
  • 3
    Unless you provide the Dom , your code , proper screenshots , output logs , it's hard to give a answer – PDHide Jan 5 at 9:41
5
+100

This could be a timing issue(as most of the scenario you already discussed) when you're going to find it would not be present at that time on DOM, so you should try using WebDriverWait to wait until this element could be present as below:-

WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement el = wait.until(ExpectedConditions.presenceOfElementLocated(By.className("messageStackError")));
el.getText()

One more thing you can try use findElements instead of findElement, findElements will return an empty list if no matching element is found instead of an exception. this will help you to find the root cause of the issue atleast.

Boolean isPresent = driver.findElements(By.yourLocator).size() > 0

Just make sure one more time before finding the element that it is not inside any frame or iframe. If it is inside then you need to switch that frame or iframe before finding element as driver.switchTo().frame("frame id or name");

  • I wrote above that it is not inside a frame, since frames , as I have checked, have different xpathes – Richardson Jan 6 at 13:34
  • In my code I used Thread.sleep() instead of Wait. Does it make a big difference? – Richardson Jan 6 at 13:53
  • yes... the major difference is that wait() releases the lock or monitor while sleep() doesn't release the lock or monitor while waiting. wait() is used for inter-thread communication while sleep() is used to introduce pause on execution. – Nitin Rastogi Jan 6 at 14:26
  • and how was it possible that under right click ---> inspect I got two elements with the same full xpath. At run time only one, (not the one I needed) was found by using findElements () and size() methods. I thought tht full xpath is always unique, relatives can be duplicate,right? – Richardson Jan 6 at 14:49
  • Did you try explicit wait? – Nitin Rastogi Jan 7 at 4:33
3

It mostly seems like your DOM is changing dynamically, so please use explicit wait using proper locator that uniquely identifies the element you want:

The below thread shows the full discussion on 'Element not found': How to analyse 'Element not Found' exceptions when working with Selenium

The summary is to :

1. Trust your code and doubt SUT (Software under test):

If everything was working fine and the test starts to fail suddenly. Instead of debugging your code for issues, start with checking the actual product. Do some visual inspection and see whether the development team has modified the element or the element is no longer being displayed.

2. Trust your code and doubt the environment:

If everything was working fine locally and failed as soon as you integrated to CI/CD. Then investigate the the product behavior in test server. Mostly due to OS and configuration difference product won't work as it would in local ( Raise a Bug)

3. Now doubt your scripts (Using absolute XPATH):

You might be using absolute XPATH, this causes flaky tests when DOM structure changes. Use relative XPATH (CSS would be more recommended). Never use xpath/ if you have unique ID/name to identify an element.

4. Now doubt your scripts (Not using explicit wait):

Sometimes scripts lacks explicit wait and try to interact with dynamic elements, this causes test to fail because it try to interact with the element before it is even available in DOM.

5. Now doubt your scripts (Handling spinners):

Sometimes spinner takes time to get displayed. SO, if you are just checking for the invisibility condition then it will be return true and try to interact with next element before the actual spinner event completes

So, first check visibility of spinner and then check for invisibility before interacting with other dynamic elements.

6. Now doubt your scripts (Not handling iFrames):

Sometimes element will be inside iframes and scripts won't switch between frames before interacting with these elements.

Check whether , any parent element contains the tag frame or iframe to determine whether element is inside an iframe

7. Now doubt your scripts (Not disabling wait for angular):

Sometimes products uses spinners to wait for asynchronous operations to complete behind the scene. For example you click login and spinner comes up and will not disappear till the background tasks are not completed.

In this case make sure you are not waiting for the asynchronous operations to complete (eg waitforangular flag set to true in protractor) before interacting with the elements in the temporary overlay.

This is because , if you set waitforangular to true, then scripts wait till all the tasks are completed and by then the temporary overlay (say spinner) will be removed from DOM

2

Reading your comments I see that app is based on Angular and this:

This service appointment has no scheduling dependencies.

Does that mean that:

  1. First you need to select service appointment (whatver that is)
  2. And then check for scheduling dependencies?

If yes, then it looks like you need to:

  1. Click for something
  2. Wait until the element is shown (you can use Expected condition)
  3. After wait from step 2 interact with element //*[@id='NoChainFound']

Be sure that you are selecting proper item, because if this Chain will be found, the element won't be visible in your browser ;)

0

Put a breakpoint on this line:

WebElement message = driver.findElement (By.xpath("//*[@id='NoChainFound']"));

In the browser window, that selenium opened press F12, then type in the console:

document.querySelector("#NoChainFound")

  • If the result is null:

    1. Switch the iframe and try the query again, like this: enter image description here
    2. The website might require some other user interaction for this element to appear, whatever it is, it's missing from your script.
  • If the result is not null or the result appeared after some time:

    1. You are trying to interact with the element too early before the actual thing has finished loading - add a FluentWait with polling.

Sometimes it is also wise, to check if you are not capturing more then one element, to do that type document.querySelectorAll(some_locator) in the console window. This will return an array of objects if its size is bigger then 1, it means your some_locator is pointing to more then 1 element.

0

I don’t know you are still looking for solution or you have solved it. You can give it a try with click using Javascript. Click with java script doesn’t depends on that element is loaded properly in DOM or not. So no chance of timeout but you can use Thread.sleep(5000); for give sometime to load DOM. Explicit wait can throw timeoutException.

If there will be click happens or No click without any error that means we can locate element.

Please try this code:

//Creating the JavascriptExecutor interface object by Type casting      
        JavascriptExecutor js = (JavascriptExecutor)driver;

// I am using a to click as DIV is just container
WebElement button =driver.findElement(By.xpath("//a[.=‘Learn More’]"));

 //Perform Click on LOGIN button using JavascriptExecutor       
        js.executeScript("arguments[0].click();", button);

js.executeScript("alert('Element is located.');");   

Try it and let me know.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.