I have written a piece of code to login into an application which is working fine. Now I have to click an add button, and I have tried it by Id, XPath, ClassName but it just gives me the exception of element not found. I thought I should apply an explicit wait, but it also did not work. Please check my code below:
public static void Login()
{
Browser.Url = "http://example.com";
_username = Browser.FindElement(By.Id("UserName"));
var password = Browser.FindElement(By.Id("Password"));
var loginbtn = Browser.FindElement(By.ClassName("btn-primary"));
_username.SendKeys("admin");
password.SendKeys("123");
loginbtn.Click();
var supplierTab = Browser.FindElement(By.Id("mainSupplier"));
supplierTab.Click();
WebDriverWait wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(20));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
try
{
return d.FindElement(By.Id("btnAddSupplier_SupplierForm"));
}
catch
{
return null;
}
});
var addbtn = Browser.FindElement(By.Id("btnAddSupplier_SupplierForm"));
addbtn.Click();
}
This always gives an exception on the second last line of code that element not found.
Here is the HTML:
Try the following
public static void Login()
{
Browser.Url = "http://example.com";
_username = Browser.FindElement(By.Id("UserName"));
var password = Browser.FindElement(By.Id("Password"));
var loginbtn = Browser.FindElement(By.ClassName("btn-primary"));
_username.SendKeys("admin");
password.SendKeys("123");
loginbtn.Click();
//I think you have mentioned the iframe exist and assuming the element is inside the iframe do the following. If not skip the SwitchTo() part
//you can use name, css to identify the iframe
Browser.SwitchTo().Frame(Browser.FindElement(By.XPath("xpath for the iframe")));
var supplierTab = Browser.FindElement(By.Id("mainSupplier"));
supplierTab.Click();
WebDriverWait wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(20));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("btnAddSupplier_SupplierForm"));
});
//if you think the id is not unique try using xpath or css
//even though you added an explicit wait you never used it
myDynamicElement.Click();
}
Sometimes the element will be existing in the source code but will not be visible for selenium to perform a click operation. Try the below code which will wait until the element is visible:
WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(20));
IWebElement element = wait.Until(
ExpectedConditions.ElementIsVisible(By.Id("btnAddSupplier_SupplierForm")));
element.Click();
Not sure if this would help, but try calling this function before you click on Add button:
void waitForPageLoad(WebDriver driver)
{
ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
wait.until(pageLoadCondition);
}
A NoSuchElementException is thrown when the locating mechanism used is not available in the dom.
A TimeoutException is thrown when your expected condition fails to be true within the time limit. An expected condition can be anything, (exists,visibility,attribute value etc...).
First you want to figure out if the element's locating mechanism you are using is indeed not found in the dom. Here is a good way to manually find out.
Open chrome and navigate to the page.
Open chrome dev tools and click on the console tab.
In the text box type $x("//*[#id='btnAddSupplier_SupplierForm']") and hit enter. This will run an xpath query, basically you are looking for any element that has an id attribute with value "btnAddSupplier_SupplierForm".
If an element appears in the console and is the correct element then it's likely that you are trying to find an element in the dom before the dom is finished loading. If no element appears in the console then you have a bad locator.
Please report your findings.
Related
Tried sendomg keys , right relative xpath or ID used but still not working properly
Tried using absolute xpath , relative xpath also ID. Tried using selassist and chropath still not working. Could there be something preventing it?
public void LoginWebSystem() {
driver = new ChromeDriver();
driver.get("http://localhost:82");
WebElement email = driver.findElement(By.id("login_username"));
email.sendKeys("superadmin");
System.out.println("Username Set");
WebElement password = driver.findElement(By.id("login_password"));
password.sendKeys("nelsoft121586");
System.out.println("Password Set");
WebElement login = driver.findElement(By.id("login_submit"));
login.click();
System.out.println("Login Button Clicked");
String newUrl = driver.getCurrentUrl();
if(newUrl.equalsIgnoreCase("http://localhost:82/controlpanel.php")){
System.out.println("Login Success");
}
else {
System.out.println("Login Failed");
}
driver.findElement(By.partialLinkText("Product")).click();
System.out.println("Successful in proceeding to Product Page");
driver.findElement(By.id("createlink")).click();
System.out.println("Successful in proceeding to Create Product by Detailed");
driver.switchTo().alert().accept();
System.out.println("Successful in clicking alert button");
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
}
#Test (priority=1)
public void ProductDetails() {
WebElement product = driver.findElement(By.xpath(" //*[#id="text-product"]"));
product.sendKeys("superadmin");
}
}
Expected output should input superadmin to product textbox
You have a typo in your XPath expression:
WebElement product = driver.findElement(By.xpath(" //*[#id="text-product"]"));
^ remove this space break
It's better to use By.Id locator strategy where possible as this is the fastest and the most robust way of identifying elements in DOM
Consider using Explicit Wait to ensure that the element is present and can be interacted with as it might be the case the element becomes available after document.readyState becomes complete. Check out How to use Selenium to test web applications using AJAX technology article for more detailed explanation.
new WebDriverWait(driver, 10)
.until(ExpectedConditions.elementToBeClickable(By.id("text-product")))
.click();
Make sure that your selector matches an <input> because if the id belongs to other element type like <div> it doesn't make a lot of sense to send keys there.
I am clicking one element and I am using wait function to identify the next element. This is the wait function.
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("some xpath")));
After identifying the element, I carry out other actions but when I click for the 1st element it will lead to next page so by the time page loads the wait function is applying for the current page and giving exception. Is there any solution for this? I tried
Browser.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
before wait but it's not working. It will only work if I use thread.sleep(1000) before wait but I dont want use thread.sleep().
I'm guessing the problem is with the fact that you are using
ExpectedConditions.presenceOfElementLocated(...)
Presence just means that the element is present in the DOM, not that it's visible, enabled, clickable, etc. I would suggest that you change to wait to match what you want to do with the element you are looking for. If you want to click it, wait for it to be clickable. If you want to get text from it, wait for it to be visible, etc.
Another issue may be that you are intending to wait for an element on page 2 but an element matches that locator on page 1. One solution is to find a unique element on page 2, wait for it to be visible, and then wait for your desired element. That way you ensure that you are on the correct page before waiting for the desired element on page 2.
I think there are 2 waits in this situation:
Wait for next page loaded
Wait for specified element loaded in the new page
Below is an option to wait for page loaded:
public void waitForLoad() {
ExpectedCondition<Boolean> condition = webDriver -> webDriver.getCurrentUrl().contains(getPageUrl());
WebDriverWait wait = new WebDriverWait(driver, pageLoadTimeout);
wait.until(condition);
}
Then wait for next element visible:
protected void waitFor(By by) {
ExpectedCondition<Boolean> condition = webDriver -> !webDriver.findElements(by).isEmpty();
WebDriverWait wait = new WebDriverWait(driver, pageLoadTimeout);
wait.until(condition);
}
or using other solutions:
public WebElement elementToBeClickable(By locator, int timeout) {
try {
return getWebDriverFluentWait(timeout)
.until(ExpectedConditions.elementToBeClickable(locator));
} catch (Exception e) {
return null;
}
}
with:
private Wait<WebDriver> getWebDriverFluentWait(int timeout) {
return new FluentWait<WebDriver>(driver)
.withTimeout(timeout, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
}
I think you want to click on element, so use elementToBeClickable
WebDriverWait wait=new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(locator))
I also Have the same Problem
But using this I solved
WebElement element = (new WebDriverWait(driver, 30)).until(ExpectedConditions.elementToBeClickable(By.xpath(".//*[#class='IM_overlay']"))); //it will wait 30 second for get this element
element .click();
//You can Do any operator here
If the element that is to be clicked is in the next(new) page, you'll have to use the windows iterator.
You could use this code:
Set <Strings> ids = driver.getWindowHandles();
Iterator <String> it = ids.iterator();
String currentPage = it.next();
String newPage = it.next();
driver.switchTo().window(newPage);//this will switch to the new window. Use your 'wait' condition now and do all the operations
//now to switch back to the previous(current) window, you could use the below code
driver.switchTo().window(currentPage);
The Code is:
public void setRing(int index, String ringPattern) throws InterruptedException {
List<WebElement> webElementList = driver.findElements(By.xpath(an.getProperty("an_ringPattern")));
webElementList.get(index).click();
List<WebElement> options = webElementList.get(index).findElements(By.tagName("option"));
for (WebElement element : options) {
if (element.getText().equals(ringPattern)) {
element.click();
Thread.sleep(2000);
}
}
}
When I execute this code in debug mode, it is working fine. It selects whatever value I pass to the method.
But when I run this code it is not able to change the value in the drop down. It selects the value in the drop down, but it's not able to set the value.
Please let me know if I am missing something.
If the Exception .Error message display below at org.openqa.selenium.support.ui.WebDriverWait.timeoutException(WebDriverWait.java:80) is being thrown, means that somehow that element is not ready on the frame, the driver is not on that frame or the xpath is wrong.
You can try to switch to the frame where the element is located, like this: driver.switchToFrame("here goes the id of the frame"); You can inspect the ID of the frame or sometimes just passing the integer 0 works. Also, I would rather use wait1.until(ExpectedConditions.visibilityOfElementLocated(element)); instead of wait1.until(ExpectedConditions.presenceOfElementLocated(element));.
When you use presenceOfElementLocated, you cant assure that the element is visible for the driver.
You can use explicit wait in selenium - WebDriverWait
Use below modified code
public void setRing(int index, String ringPattern) throws InterruptedException {
List<WebElement> webElementList = driver.findElements(By.xpath(an.getProperty("an_ringPattern")));
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.presenceOfElementLocated(webElementList.get(index)));
webElementList.get(index).click();
List<WebElement> options = webElementList.get(index).findElements(By.tagName("option"));
for (WebElement element : options) {
WebDriverWait wait1 = new WebDriverWait(driver, 60);
wait1.until(ExpectedConditions.presenceOfElementLocated(element));
if (element.getText().equals(ringPattern)) {
element.click();
Thread.sleep(2000);
}
}
}
we are doing automation for web application and most of the scenario getting loading icon will appear at center of the page .. we need to wait for dis appear to loading icon
<div id="loading" style="display: none; visibility: hidden;">
<div></div>
<div></div>
Example : we are having search functionality their in most of scenario we are getting this loading icon.
selenium webdriver we are using: id we are getting for loading to complete is id= "loading"..please any give the solutions for the above issues am facing.
we have different functionality like click & sendkeys
Explicit Wait should help:
public static String waitForElementNotVisible(int timeOutInSeconds, WebDriver driver, String elementXPath) {
if ((driver == null) || (elementXPath == null) || elementXPath.isEmpty()) {
return "Wrong usage of WaitforElementNotVisible()";
}
try {
(new WebDriverWait(driver, timeOutInSeconds)).until(ExpectedConditions.invisibilityOfElementLocated(By
.xpath(elementXPath)));
return null;
} catch (TimeoutException e) {
return "Build your own errormessage...";
}
}
I have recently faced this issue. My solution might sound hacky but it worked pretty well in my case:
public static void loadingWait(WebDriver driver, WebElement loader) {
WebDriverWait wait = new WebDriverWait(driver, 5000L);
wait.until(ExpectedConditions.visibilityOf(loader)); // wait for loader to appear
wait.until(ExpectedConditions.invisibilityOf(loader)); // wait for loader to disappear
}
you can call this method after clicking on submit button. You have to pass driver, and loader web element to this method.
You can also wait till the ajax calls have been completed. Loading wheel disappears when all the ajax calls have completed (in most of the scenarios):
WebDriverWait wait = new WebDriverWait(d, timeOutSeconds);
wait.until(waitForAjaxCalls());
public static ExpectedCondition<Boolean> waitForAjaxCalls() {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
return Boolean.valueOf(((JavascriptExecutor) driver).executeScript("return (window.angular !== undefined) && (angular.element(document).injector() !== undefined) && (angular.element(document).injector().get('$http').pendingRequests.length === 0)").toString());
}
};
}
I faced this issue and the solution is really simple :
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until( ExpectedConditions.invisibilityOfElementLocated(By.xpath("path_of_loader")));
Generally, you must have something like on your website :Image
so use path_of_loader = //div[#id='circular3dG'] .. You can also try searching using keywords like loader, spinner or use a page to inspect loader/spinner where it takes long to load the page.
There is a html page with button, and my selenium test is testing, that there is an action executed, when the button is clicked.
The problem is, that it looks like the click happens before the javascript is executed - before the handler is bound to the page. The consequence is, that the selenium test will click on the button, but no action happens.
I can solve this problem by repeatedly trying to click and then observe, if the desired action happened (some element is present on page, typically). I'd like to hear that there are some more elegant solutions...
There is no clear way to say "wait until element X has such-and-such handler"; this is a limitation of JavaScript and the DOM (see for example Get event listeners attached to node using addEventListener and jQuery find events handlers registered with an object), and for that matter a selenium Expected Condition can't be created, at least not trivially.
I've resorted to time.sleep(0.5).
You can write some logic to handle this.
I have write a method that will return the WebElement and this method will be called three times or you can increase the time and add a null check for WebElement
Here is an example
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("https://www.crowdanalytix.com/#home");
WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
int i = 1;
while (webElement == null && i < 4) {
webElement = getWebElement(driver, "homessssssssssss");
System.out.println("calling");
i++;
}
System.out.println(webElement.getTagName());
System.out.println("End");
driver.close();
}
public static WebElement getWebElement(WebDriver driver, String id) {
WebElement myDynamicElement = null;
try {
myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By
.id(id)));
return myDynamicElement;
} catch (TimeoutException ex) {
return null;
}
}