Selenium Webdriver element identification - java

Hi I am new to Selenium Webdriver.
I have taken this website and I am trying to click on the Register Link. I have written the following code.
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get("http://www.stepintohealth.qa");
driver.findElement(By.linkText("Register")).click();
while executing the code it is throwing element not found exception. i have tried same in seleniunm IDE it works without any issue. I have verified for the iframes also, but Register link is not in iframes.

Welcome to the world of Selenium. It is often the element wait/find issue that you are facing. I added explicit wait to make sure the element is there before you perform the click.
driver = new FirefoxDriver();
driver.get("http://www.stepintohealth.qa");
By byCss = By.cssSelector(".right1.navmenu a.register");
WebElement myDynamicElement = (new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(byCss ));
myDynamicElement.click();
Couple of things to keep in mind:
You don't want to mix the implicit and explicit waits together since that can be a performance issue. It is not recommended.
Selector is very important in finding the element uniquely. I tend to avoid LinkText as much as I can. id should be your first choice always. Try using name,clasName,cssSelector,xpath if you can. In this case className did not work pretty good. Tested with cssSelector and did what it supposed to do. See this for more info.

Related

How To avoid stale element reference: element is not attached to the page document when I use a command to change the paage

I have a problem using Ecplise. When I use a command to do something that drives me into another page. For example if I do commands that do not require to change the page it works fine. But when I do one that changes the page, it works, but after that it stops and I get that error. So, there is a portion of the code. After the third command which implies going to another page, the next 2 commands don't work.
driver.get("https://mathaus.ro");
driver.manage().window().maximize();
driver.findElement(By.id("Constructii10NavNode")).click();
driver.findElement(By.id("changeLocationReference")).click();
driver.findElement(By.className("close-modal")).click();
I think you need Explicit waits :
Code :
driver.manage().window().maximize();
driver.get("https://mathaus.ro");
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.id("Constructii10NavNode"))).click();
Thread.sleep(3000);
wait.until(ExpectedConditions.elementToBeClickable(By.id("changeLocationReference"))).click();
Thread.sleep(3000);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("div.close-modal"))).click();
Thread.sleep(3000);
PS : Thread.sleep(3000); is just for visualization purpose. You can remove that. It's not really required

element not interactable exception in selenium web automation

In the below code i cannot send password keys in the password field, i tried clicking the field, clearing the field and sending the keys. But now working in any of the method. But its working if i debug and test
public class TestMail {
protected static WebDriver driver;
protected static String result;
#BeforeClass
public static void setup() {
System.setProperty("webdriver.gecko.driver","D:\\geckodriver.exe");
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
}
#Test
void Testcase1() {
driver.get("http://mail.google.com");
WebElement loginfield = driver.findElement(By.name("Email"));
if(loginfield.isDisplayed()){
loginfield.sendKeys("ragesh#gmail.in");
}
else{
WebElement newloginfield = driver.findElemnt(By.cssSelector("#identifierId"));
newloginfield.sendKeys("ragesh#gmail.in");
// System.out.println("This is new login");
}
driver.findElement(By.name("signIn")).click();
// driver.findElement(By.cssSelector(".RveJvd")).click();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// WebElement pwd = driver.findElement(By.name("Passwd"));
WebElement pwd = driver.findElement(By.cssSelector("#Passwd"));
pwd.click();
pwd.clear();
// pwd.sendKeys("123");
if(pwd.isEnabled()){
pwd.sendKeys("123");
}
else{
System.out.println("Not Enabled");
}
Try setting an implicit wait of maybe 10 seconds.
gmail.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Or set an explicit wait. An explicit waits is code you define to wait for a certain condition to occur before proceeding further in the code. In your case, it is the visibility of the password input field. (Thanks to ainlolcat's comment)
WebDriver gmail= new ChromeDriver();
gmail.get("https://www.gmail.co.in");
gmail.findElement(By.id("Email")).sendKeys("abcd");
gmail.findElement(By.id("next")).click();
WebDriverWait wait = new WebDriverWait(gmail, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));
gmail.findElement(By.id("Passwd")).sendKeys("xyz");
Explanation: The reason selenium can't find the element is because the id of the password input field is initially Passwd-hidden. After you click on the "Next" button, Google first verifies the email address entered and then shows the password input field (by changing the id from Passwd-hidden to Passwd). So, when the password field is still hidden (i.e. Google is still verifying the email id), your webdriver starts searching for the password input field with id Passwd which is still hidden. And hence, an exception is thrown.
"element not interactable" error can mean two things :
a. Element has not properly rendered:
Solution for this is just to use implicit /explicit wait
Implicit wait :
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
Explicit wait :
WebDriverWait wait=new WebDriverWait(driver, 20);
element1 = wait.until(ExpectedConditions.elementToBeClickable(By.className("fa-stack-1x")));
b. Element has rendered but it is not in the visible part of the screen:
Solution is just to scroll till the element. Based on the version of Selenium it can be handled in different ways but I will provide a solution that works in all versions :
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].scrollIntoView(true);", element1);
Suppose all this fails then another way is to again make use of Javascript executor as following :
executor.executeScript("arguments[0].click();", element1);
If you still can't click , then it could again mean two things :
1. Iframe
Check the DOM to see if the element you are inspecting lives in any frame. If that is true then you would need to switch to this frame before attempting any operation.
driver.switchTo().frame("a077aa5e"); //switching the frame by ID
System.out.println("********We are switching to the iframe*******");
driver.findElement(By.xpath("html/body/a/img")).click();
2. New tab
If a new tab has opened up and the element exists on it then you again need to code something like below to switch to it before attempting operation.
String parent = driver.getWindowHandle();
driver.findElement(By.partialLinkText("Continue")).click();
Set<String> s = driver.getWindowHandles();
// Now iterate using Iterator
Iterator<String> I1 = s.iterator();
while (I1.hasNext()) {
String child_window = I1.next();
if (!parent.equals(child_window)) {
driver.switchTo().window(child_window);
element1.click()
}
Please try selecting the password field like this.
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement passwordElement = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#Passwd")));
passwordElement.click();
passwordElement.clear();
passwordElement.sendKeys("123");
you may also try full xpath, I had a similar issue where I had to click on an element which has a property javascript onclick function. the full xpath method worked and no interactable exception was thrown.
In my case the element that generated the Exception was a button belonging to a form. I replaced
WebElement btnLogin = driver.findElement(By.cssSelector("button"));
btnLogin.click();
with
btnLogin.submit();
My environment was chromedriver windows 10
In my case, I'm using python-selenium.
I have two instructions. The second instruction wasn't able to execute.
I put a time.sleep(1) between two instructions and I'm done.
If you want you can change the sleep amount according to your need.
I had the same problem and then figured out the cause. I was trying to type in a span tag instead of an input tag. My XPath was written with a span tag, which was a wrong thing to do. I reviewed the Html for the element and found the problem. All I then did was to find the input tag which happens to be a child element. You can only type in an input field if your XPath is created with an input tagname
I'm going to hedge this answer with this: I know it's crap.. and there's got to be a better way. (See above answers) But I tried all the suggestions here and still got nill. Ended up chasing errors, ripping the code to bits. Then I tried this:
import keyboard
keyboard.press_and_release('tab')
keyboard.press_and_release('tab')
keyboard.press_and_release('tab') #repeat as needed
keyboard.press_and_release('space')
It's pretty insufferable and you've got to make sure that you don't lose focus otherwise you'll just be tabbing and spacing on the wrong thing.
My assumption on why the other methods didn't work for me is that I'm trying to click on something the developers didn't want a bot clicking on. So I'm not clicking on it!
I got this error because I was using a wrong CSS selector with the Selenium WebDriver Node.js function By.css().
You can check if your selector is correct by using it in the web console of your web browser (Ctrl+Shift+K shortcut), with the JavaScript function document.querySelectorAll().
If it's working in the debug, then wait must be the proper solution.
I will suggest to use the explicit wait, as given below:
WebDriverWait wait = new WebDriverWait(new ChromeDriver(), 5);
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#Passwd")));
I came across this error too. I thought it might have been because the field was not visible. I tried the scroll solution above and although the field became visible in the controlled browser session I still got the exception. The solution I am committing looks similar to below. It looks like the event can bubble to the contained input field and the end result is the Selected property becomes true.
The field appears in my page something like this.
<label>
<input name="generic" type="checkbox" ... >
<label>
The generic working code looks more or less like this:
var checkbox = driver.FindElement(By.Name("generic"), mustBeVisible: false);
checkbox.Selected.Should().BeFalse();
var label = checkbox.FindElement(By.XPath(".."));
label.Click();
checkbox.Selected.Should().BeTrue();
You'll need to translate this to your specific language. I'm using C# and FluentAssertions. This solution worked for me with Chrome 94 and Selenium 3.141.0.
I had to hover over the element first for the sub-elements to appear. I didn't take that into account at first.
WebElement boardMenu = this.driver.findElement(By.linkText(boardTitle));
Actions action = new Actions(this.driver);
action.moveToElement(boardMenu).perform();
Another tip is to check that you are having one element of that DOM. Try using Ctrl+F when inspecting the web page and check your xpath there; it should return one element if you are going with the findElement method.

Selenium WebElement times out on most commands

I've run into a problem that has baffled me while attempting to use Selenium 3.4 on jre 1.8 in JUnit. After successfully grabbing a WebElement, attempting to perform the click(), isDisplayed(), sendKeys(), and clear() functions all cause the driver connection to timeout before they can complete. I've wound up creating the following code:
#Test
public void canLogIn(){
WebDriver driver = new HtmlUnitDriver();
driver.get("http://"+ip+"/login/loginpage.html");
WebElement username = driver.findElement(By.id("username_div"));
System.out.println("Username to string: "+username.toString());
/*Thread.sleep(6000);*/
if(!username.isEnabled()) fail();
if(!username.isDisplayed()) fail();
username.click();
username.clear();
username.sendKeys("manager");
...
So far, the code has timed out on username.isDisplayed(), username.click(), username.clear(), and username.sendKeys() when all the other elements were commented out. However, username.toString() works, and shows the correct element, and the code has yet to hang on username.isEnabled(). Thread.sleep() was used to test whether allowing the page to load would eliminate the issue, but to no avail. I have tried executing these commands using Selenium's JavascriptExecutor, also to no avail. I am well and truly stumped at this point, and any assistance you could give me would be greatly appreciated.
Is the username element visible? Perhaps you can try adding this after opening the page:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until( ExpectedConditions.visibilityOfElementLocated("username_div"));
What exception are you getting if any?

Action class works in debug mode in selenium webdriver

I have written the code and that works well when I run this is debugging mode but when I run it in normal mode then I am getting the following exception
org.openqa.selenium.NoSuchElementException: no such element:
Unable to locate element: {"method":"xpath","selector":".//*[#id='address-0']/span"}
The code I have written is:
WebElement searchBox = driver.findElement(By.id("search-input"));
searchBox.sendKeys("somepostcode");
Actions actions = new Actions(driver);
actions.moveToElement(searchBox);
WebElement address = driver.findElement(By.xpath(".//*[#id='address-0']/span"));
actions.moveToElement(address);
actions.click();
actions.perform();
I am not able to understand where should I put wait.
I am using eclipse IDE. The functionality works like when I put some postcode in the search box it search for some addresses at runtime and the user has to select any address related to the postcode. Ajax has been used to fetch the postcode
Here search box is a textbox.
Please let me know if more information is required.
Try adding some wait time before WebElement address = driver.findElement(By.xpath(".//*[#id='address-0']/span"));
Error tells you that, you are trying to create an instance of WebElement "address" before its visible on the page.
Try adding wait before
WebElement address = driver.findElement(By.xpath(".//*[#id='address-0']/span"));
In cases like this, when the script works in debug mode but fails during normal it is almost always the issue with timing. So your page is just not fully loaded at the time you are trying to locate that element.
Place an explicit wait just before your problematic element. It's usually not the best practice to use explicit wait but you can do it as a quick try to see if that solves your problem. If that does you can refactor it into a sturdier solution later.
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
Hope this will help you..
WebElement searchBox = driver.findElement(By.id("search-input"));
searchBox.sendKeys("somepostcode");
Actions actions = new Actions(driver);
actions.moveToElement(searchBox);
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(".//*[#id='address-0']/span")));
WebElement address = driver.findElement(By.xpath(".//*[#id='address-0']/span"));
actions.moveToElement(address);
actions.click();
actions.perform();
I have solved this problem by breaking the postcode in two parts
searchBox.sendKeys("postcodePart1");
searchBox.sendKeys("postcodePart2");
There must be kind of on change event was calling.

Why my test is throwing Exception-Unable to locate element in webdriver?

package testproject;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.*;
public class mytestclass {
public static void main(String[] args) {
WebDriver Driver = new FirefoxDriver();
Driver.get("https://www.gmail.com/");
WebElement wb= Driver.findElement(By.name("Email"));
wb.sendKeys("sweta");
WebElement wb1= Driver.findElement(By.name("Passwd"));
wb1.sendKeys("123456");
WebElement wb2= Driver.findElement(By.id("signIn"));
wb2.click();
WebElement wb3= Driver.findElement(By.xpath(".//*[#id='gb']/div[1]/div[1]/div[2]/div[5]/div[1]/a"));
wb3.click();
WebElement wb4= Driver.findElement(By.id("gb_71"));
wb4.click();
}
}
When i am executing this code everything is going fine till the point where i want the sign in button to be clicked. I am getting exception which says that
Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":".//*[#id='gb']/div[1]/div[1]/div[2]/div[5]/div[1]/a"} but when i am trying to locate it using fierbug its working fine.
In the above mentioned code i changed the email id and password to keep the email safe.
I was facing problem with one more program which i already posted on stakwave so if u can then please have a look at this link-webdriver is not able to click on a hyperlink in firefox
Are you certain your page is completely loaded after you sign in?
Did you set a timeout for your webdriver? (how long it has to wait for elements). Probably it reads your html before it's completey loaded.
Webdriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
To find out quickly if this is the problem do Thread.sleep(8000) after you do wb2.click();
Remove the dot at the beginning of your xpath expression. That way you have an xpath expression thaty could match everything. With the dot at the beginning you might retrict yourself depending on if the current node is the root node or not. Ther eis no way to know it. Just the fact the dot can only give you trouble. Unfortunately you cannot always trust what tools like firebug give you (it is still true in 99% of the case).
Of course, ensure that the elemetns you are targeting are already on the screen as suggested by the previous answer.
I faced similar problem,
issue resolved after setting timeout.
Webdriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
Not sure whats the role of timeout here though.
remove the dot(.) and star(*) from the xpath and give proper tag name in place of star.
for example if #id=gb is the id of div element, place div in place of star.
Hope it will work.
//launch browser
FirefoxDriver driver = new FirefoxDriver(options);
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
//gmail login :
driver.get("http://www.gmail.com");
driver.findElement(By.id("identifierId")).sendKeys("****",Keys.ENTER);
Thread.sleep(5000);
driver.findElement(By.id("password")).sendKeys("***",Keys.ENTER);
//logout:
driver.findElement(By.xpath("//div[#id='gb']/div[1]/div[1]/div[2]/div[4]/div[1]/a/span")).click();
Thread.sleep(5000);
driver.findElement(By.linkText("Sign out")).click();

Categories

Resources