In webdriver, how to ask to webdriver to wait until text is present in text field.
actually i have one kendo text field whose values comes from database which takes some time to load. Once it load i can proceed further.
please help on this
You can use WebDriverWait. From docs example:
(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.findElement(...).getText().length() != 0;
}
});
You can use WebDriverWait. From docs example:
above ans using .getTex() this is not returning text from input field
use .getAttribute("value") instead of getText()
(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.findElement(...).getAttribute("value").length() != 0;
}
});
tested
100% working
hope this will help
A one liner that works and uses lambda function.
wait.until((ExpectedCondition<Boolean>) driver -> driver.findElement(By.id("elementId")).getAttribute("value").length() != 0);
Using WebDriverWait (org.openqa.selenium.support.ui.WebDriverWait) and ExpectedCondition (org.openqa.selenium.support.ui.ExpectedConditions) objects
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.textToBePresentInElementLocated(By.id("element_id"), "The Text"));
You can use a simple method in which you need to pass driver object webelement in which text is going to come and the text which is goint to come.
public static void waitForTextToAppear(WebDriver newDriver, String textToAppear, WebElement element) {
WebDriverWait wait = new WebDriverWait(newDriver,30);
wait.until(ExpectedConditions.textToBePresentInElement(element, textToAppear));
}
This is my solution for sending text to input:
public void sendKeysToElement(WebDriver driver, WebElement webElement, String text) {
WebDriverWait wait = new WebDriverWait(driver, Configuration.standardWaitTime);
try {
wait.until(ExpectedConditions.and(
ExpectedConditions.not(ExpectedConditions.attributeToBeNotEmpty(webElement, "value")),
ExpectedConditions.elementToBeClickable(webElement)));
webElement.sendKeys(text);
wait.until(ExpectedConditions.textToBePresentInElementValue(webElement, text));
activeElementFocusChange(driver);
} catch (Exception e) {
Configuration.printStackTraceException(e);
}
}
WebElement nameInput = driver.findElement(By.id("name"));
sendKeysToElement(driver, nameInput, "some text");
Related
Hi i am working on a selenium project and the top difficulty that i am having was waiting for XHR request to be completed. What i am currently doing is i wait for a request to be made using following expected condition,
public ExpectedCondition<Boolean> jQueryExpect (int expectedActive) {
ExpectedCondition<Boolean> jQLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver dr) {
try {
logger.log(Level.INFO,"Checking number of jQueries Active");
Long active = (Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active");
logger.log(Level.INFO,"jQuery''s active: {0}",active);
return (active >= expectedActive);
}
catch (Exception e) {
logger.log(Level.WARNING,"Error executing script in jQueryLoad method");
// no jQuery present
return true;
}
}
};
return jQLoad;
}
And then i wait for the jQuery to load using this expected condition
public ExpectedCondition<Boolean> jQueryLoad (int expectedActive) {
ExpectedCondition<Boolean> jQLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver dr) {
try {
logger.log(Level.INFO,"Checking number of jQueries Active");
Long active = (Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active");
logger.log(Level.INFO,"jQuery''s active: {0}",active);
return (active <= expectedActive);
}
catch (Exception e) {
logger.log(Level.WARNING,"Error executing script in jQueryLoad method");
// no jQuery present
return true;
}
}
};
return jQLoad;
}
This method is working pretty solid for now since i know how many requests to expect. But as you have already noticed it can easily break in future as number of requests made are changed for some reason.
I been looking at cypress documentation and found this. According to cypress documentation this waits for the specified requests to be made.
cy.wait(['#getUsers', '#getActivities', '#getComments']).then((xhrs) => {
// xhrs will now be an array of matching XHR's
// xhrs[0] <-- getUsers
// xhrs[1] <-- getActivities
// xhrs[2] <-- getComments
})
Is there any such method available in Selenium? or Is there any way this can be implemented? So far from what i have googled i got nothing. So any help will be appreciated.
You can locate Element and wait for element
There are Implicit and Explicit waits in selenium.
You can use either
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));
or
wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>));
More information: on this answer
After login get successful in gmail, I am not able to click on compose mail button. It gives NoSuchElementException error.
Executemail.java
public void clickin(String objectname) throws Exception{
WebDriverWait wait=new WebDriverWait(driver,20);
WebElement element=wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(prop.getProperty(objectname))));
element.click();
}
keyword.java
if(a.get(i).equals("clickin")) {
String Keyword = (String)a.get(i);
String data = (String)a.get(i+1);
String objectname = (String)a.get(i+2);
String runmode = (String)a.get(i+3);
System.out.println(Keyword);
System.out.println(data);
System.out.println(objectname);
System.out.println(runmode);
if(runmode.equals("Yes")) {
key.clickin(objectname);
}
}
enter image description here
Double check your locator, for me the following XPath expression works fine:
//div[#role='button' and normalize-space()='Compose']
It filters the div element by the role attribute and uses normalize-space() function to ignore spaces and line breaks
My suggest would be waiting for the JS on the page to load before calling your click. I would do this with the following method - I have typed this out on my phone so sorry in advanced if any mistakes.
public static void waitForPageToLoad(){
WebDriverWait wait = new WebDriverWait(driver, 120);
wait.until(new ExpectedCondition<Boolean>(){
#Override
public Boolean apply(WebDriver driver){
return ((JavascriptExecutor)driver).executeScript(“return document.readyState”).equals(“complete”);}});
`
I have a problem triying to recognize a xpath from the following web page
http://smartchanneltech.com/top100canalti/
This is the element I want to recognize: https://imgur.com/a/ENOP1
This is the xpath that I´m using:/html/body/div/div/div[1]/h1/a
This is the code I´m using:
public WebElement Empresa (WebDriver driver, int Iterator) {
//WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div/div/div[1]/h1/a")));
return driver.findElement(By.xpath("/html/body/div/div/div[1]/h1/a"));
}
And, finally, this is the error log: https://imgur.com/a/quFjg
I tried just to driver.findElement(By.xpath("/html/body/div/div/div[1]/h1/a")); but is not working also.
Can you help me with this please?
It is inside a iframe. First switch to the frame and try identifying it.
public WebElement Empresa (WebDriver driver, int Iterator) {
driver.switchTo().frame(0);
String xpath="/html/body/div/div/div[1]/h1/a";
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
return driver.findElement(By.xpath(xpath));
}
If you look into the HTML DOM the WebElement is within an <iframe>. So we need to switch to the <iframe> first with proper WebDriverWait and then locate the WebElement as follows :
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[#src='https://www.rise.global/display/top100-canalti/latest/embeddable/cut/stripes']")));
return driver.findElement(By.xpath("div[#class='lb-leaderboard-header']/h1/a[#class='lb-leaderboard-name']"));
I have update the method as below.
Please use this.
public WebElement Empresa (WebDriver driver, int Iterator) {
//WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[#src='https://www.rise.global/display/top100-canalti/latest/embeddable/cut/stripes']")));
driver.switchTo().frame(driver.findElement(By.tagName("iframe")));
WebElement elem = driver.findElement(By.className("lb-leaderboard-widget-wrapper"));
WebElement elemH1 = elem.findElement(By.tagName("h1"));
WebElement elemIWant = elem.findElement(By.tagName("a"));
System.out.println(elemIWant.getAttribute("innerHTML").toString());
return elemIWant;
}
let me know your feedback.
I'm currently using PhantomJS + Selenium to populate some form fields but having weird results. 50% of the time, the test runs fine. The other 50% it errors out and gives me the following
{"errorMessage":"Element is not currently interactable and may not be
manipulated"
I'm doing the following to make sure the page is loaded.
private static boolean waitForJQueryProcessing(WebDriver driver,
int timeOutInSeconds) {
boolean jQcondition = false;
try {
new WebDriverWait(driver, timeOutInSeconds) {
}.until(new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driverObject) {
return (Boolean) ((JavascriptExecutor) driverObject)
.executeScript("return jQuery.active == 0");
}
});
jQcondition = (Boolean) ((JavascriptExecutor) driver)
.executeScript("return window.jQuery != undefined && jQuery.active === 0");
return jQcondition;
} catch (Exception e) {
logger.debug(e.getMessage());
}
return jQcondition;
}
And then to interact with the element(s):
pageWait.until(ExpectedConditions.presenceOfElementLocated(By
.cssSelector("#myForm-searchDate")));
driver.findElement(
By.cssSelector("#myForm-searchDate"))
.sendKeys(Keys.CONTROL + "a");
driver.findElement(
By.cssSelector("#myForm-searchDate"))
.sendKeys(Keys.DELETE);
driver.findElement(
By.cssSelector("#myForm-searchDate"))
.sendKeys(MY_TEST_DATE);
I could see if it failed all the time, but it doesn't fail all the time so it's hard to repeat the results when debugging.
Edit 1. I've tried swapping following the comment below; however, it doesn't work. I've since come to realize this seems to only happen when I fire up several (5+) instances of PhantomJS at once.
I posed with a difficult task. I am fairly new to selenium and still working through the functionalities of waiting for elements and alike.
I have to manipulate some data on a website and then proceed to another. Problem: the manipulation invokes a script that makes a little "Saving..." label appear while the manipulated data is being processed in the background. I have to wait until I can proceed to the next website.
So here it is:
How do i wait for and element to DISAPPEAR? Thing is: It is always present in the DOM but only made visible by some script (I suppose, see image below).
This is what I tried but it just doesn't work - there is no waiting, selenium just proceeds to the next step (and gets stuck with an alert asking me if I want to leave or stay on the page because of the "saving...").
private By savingLableLocator = By.id("lblOrderHeaderSaving");
public boolean waitForSavingDone(By webelementLocator, Integer seconds){
WebDriverWait wait = new WebDriverWait(driver, seconds);
Boolean element = wait.until(ExpectedConditions.invisibilityOfElementLocated(webelementLocator));
return element;
}
UPDATE / SOLUTION:
I came up ith the following solution: I built my own method. Basically it checks in a loop for the CssValue to change.
the loops checks for a certain amount of time for the CSSVALUE "display" to go from "block" to another state.
public void waitForSavingOrderHeaderDone(Integer _seconds){
WebElement savingLbl = driver.findElement(By.id("lblOrderHeaderSaving"));
for (int second = 0;; second++) {
if (second >= _seconds)
System.out.println("Waiting for changes to be saved...");
try {
if (!("block".equals(savingLbl.getCssValue("display"))))
break;
} catch (Exception e) {
}
}
You can wait for a WebElement to throw a StaleElementReferenceException like this:
public void waitForInvisibility(WebElement webElement, int maxSeconds) {
Long startTime = System.currentTimeMillis();
try {
while (System.currentTimeMillis() - startTime < maxSeconds * 1000 && webElement.isDisplayed()) {}
} catch (StaleElementReferenceException e) {
return;
}
}
So you would pass in the WebElement you want to wait for, and the max amount of seconds you want to wait.
Webdriver has built in waiting functionality you just need to build in the condition to wait for.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return (driver.findElements(By.id("lblOrderHeaderSaving")).size() == 0);
}
});
I'm not sure, but you can try something like this :)
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //time in second
WebElement we = driver.findElement(By.id("lblOrderHeaderSaving"));
assertEquals("none", we.getCssValue("display"));
This works with selenium 2.4.0. you have to use the invisibility mehtod to find it.
final public static boolean waitForElToBeRemove(WebDriver driver, final By by) {
try {
driver.manage().timeouts()
.implicitlyWait(0, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(UITestBase.driver,
DEFAULT_TIMEOUT);
boolean present = wait
.ignoring(StaleElementReferenceException.class)
.ignoring(NoSuchElementException.class)
.until(ExpectedConditions.invisibilityOfElementLocated(by));
return present;
} catch (Exception e) {
return false;
} finally {
driver.manage().timeouts()
.implicitlyWait(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
}
}
I used following C# code to handle this, you may convert it to Java
public bool WaitForElementDisapper(By element)
{
try
{
while (true)
{
try
{
if (driver.FindElement(element).Displayed)
Thread.Sleep(2000);
}
catch (NoSuchElementException)
{
break;
}
}
return true;
}
catch (Exception e)
{
logger.Error(e.Message);
return false;
}
}
You can also try waiting for the ajax calls to complete. I've used this to check when the page load is complete and all the elements are visible.
Here's the code - https://stackoverflow.com/a/46640938/4418897
You could use XPath and WebDriverWait to check whether display: none is present in the style attribute of an element. Here is an example:
// Specify the time in seconds the driver should wait while searching for an element which is not present yet.
int WAITING_TIME = 10;
// Use the driver for the browser you want to use.
ChromeDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, WAITING_TIME);
// Replace ELEMENT_ID with the ID of the element which should disappear.
// Waits unit style="display: none;" is present in the element, which means the element is not visible anymore.
driver.wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[#id='ELEMENT_ID'][contains(#style, 'display: block')]")));
Try using invisibilityOfElementLocated method.
You can reference example here How to wait until an element no longer exists in Selenium?
enter image description hereI created my own method for element disappearing from dom....
In Conditions class (In .m2\repository\org\seleniumhq\selenium\selenium-support\3.141.59\selenium-support-3.141.59.jar!\org\openqa\selenium\support\ui\ExpectedConditions.class)
we can see that 'isInvisible' method with 'isDisplayed' method,,, i wrote the same with 'isEnabled'
public static ExpectedCondition<Boolean> invisibilityOf(final WebElement element) {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver webDriver) {
return isRemovedFromDom(element);
}
#Override
public String toString() {
return "invisibility of " + element;
}
};
}
private static boolean isRemovedFromDom(final WebElement element) {
try {
return !element.isEnabled();
} catch (StaleElementReferenceException ignored) {
return true;
}
}