I am a beginner for Selenium Webdriver, I have written a script in Java to test a functionality, and it is working fine. Sometimes I faces an issue.
Suppose I just click on create button to create something (let suppose customer) and after this I need to do some work with a screen which comes after create successfully customer. Sometimes due to slow response from server, my script get failed due to search a DOM element which comes after create customer.
If response come with in predefined time in my code, no issue, if not come then script failed (it search a element which has not rendered yet).
1) click on button
try{
// let suppose creatButtonElement is the web element of Create Button.
createButtonElement.click();
}catch(Exception e){
throw new Exception("Unable To Click on element [ " + element + " ] , plz see screenshot [ UnableToClick_" + element);
}
Expecting: after click on create button my script is expecting success message for assertion.
I had faced this issue once but I had handled this manually. This will work if after click button loader is appearing. It waits for one minute.
Please use the following code to wait manually to get response of server. It check the visibility of loader to know the response each second.
public static void loading_wait() throws Throwable {
int i = 0;
int maxloopDependOnBrowser = 60;
int totalSecond=0;
boolean loadinImageTakingMuchTime=false;
try{
while (true) {
i++;
if( !(loaderDisplayed(APP_LoadingImage_xpath)) ){
totalSecond+=i;
break;
}
if (i > maxloopDependOnBrowser) {
totalSecond=maxloopDependOnBrowser + 1;
loadinImageTakingMuchTime=true;
break;
} else {
totalSecond=i;
Thread.sleep(1000);
}
}
Thread.sleep(1000);
if(loadinImageTakingMuchTime){
throw new Throwable();
}
}catch (Throwable t) {
throw new Exception("FAILED:>>> Loading image is taking too much time :>>"+Throwables.getStackTraceAsString(t));
}
}
XpathKey :- to find the loader element
public static boolean loaderDisplayed(String XpathKey) {
int i = 0;
try {
driver.manage().timeouts().implicitlyWait(5, TimeUnit.MILLISECONDS);
List<WebElement> elementList = getORObject_list(XpathKey/*, 0, 500*/);
for (Iterator<WebElement> iterator = elementList.iterator(); iterator.hasNext();) {
WebElement webElement = (WebElement) iterator.next();
if (webElement.isDisplayed()) {
i = 1;
break;
}
}
} catch (Throwable t) {
}
finally {
driver.manage().timeouts().implicitlyWait(Long.parseLong(1), TimeUnit.SECONDS);
}
if (i == 0) {
return
} else {
return true;
}
}
You can join waiting
WebDriverWait wait = new NWebDriverWait(driver, 10); //10 second
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("btn1")));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("btn1")));
wait.until(ExpectedConditions.elementToBeClickable(By.id("btn1")));
Consider:
if(driver.findElement(By.xpath("//*[#id='myClass']/tr[1]")) != null){
// Passed
}
else{
// Failed
}
What should I write to make pass or fail for Selenium? I can do System.out.println("failed");, but it still shows Failure = 0 in the end.
Use findElements instead of findElement and check the size:
if(driver.findElements(By.xpath("//*[#id='myClass']/tr[1]")).size() != 0){
//passed
}else{
//failed
}
You could also catch the exception:
try {
WebElement element = driver.findElement(By.xpath("//*[#id='myClass']/tr[1]"));
//passed
} catch (NoSuchElementException ex) {
//failed
}
If you want your test to fail if some conditions weren't met, try using JUnit Assertions.
assertTrue(driver.findElements(By.className("myClass")).size() > 0);
In this case, the test will fail if no elements with class myClass weren't found.
I am getting a StateElementReferenceException when I try to perform a drag-and-drop action, see the code snippets below. Can anyone please help to solve this with appropriate suggestions and explanations?
#Test(priority=4)
public void addUserBySearch() {
driver.findElement(By.xpath(OR.getProperty("btnUserGroup"))).click();
driver.findElement(By.xpath(OR.getProperty("btnCreateUG"))).click();
driver.findElement(By.xpath(OR.getProperty("textUGName"))).sendKeys("UserGroup:" + Utils.randGen());
driver.findElement(By.xpath(OR.getProperty("userSearchField"))).sendKeys("testuser2", Keys.ENTER);
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));
destination = driver.findElement(By.xpath(OR.getProperty("userDestination")));
waitUntilElementVisible(30, source);
dragAndDrop(source, destination);
driver.findElement(By.xpath(OR.getProperty("btnScheduleNow"))).click();
}
public void waitUntilElementVisible(int seconds, WebElement element) {
WebDriverWait explicitWait = new WebDriverWait(driver, seconds);
explicitWait.until(ExpectedConditions.visibilityOf(element));
}
public void dragAndDrop(WebElement sourceElement, WebElement destinationElement){
try {
if (sourceElement.isDisplayed() && destinationElement.isDisplayed()) {
Actions action = new Actions(driver);
action.dragAndDrop(sourceElement, destinationElement).build().perform();
}
else {
System.out.println("Element not found to drag and drop");
}
}
catch (StaleElementReferenceException exc) {
exc.printStackTrace();
}
catch (NoSuchElementException exc) {
exc.printStackTrace();
}
}
btnUserGroup = //*[text()='User Groups']
btnCreateUG = //*[#id='stage']/div/div[2]/div/div/div[2]/div[3]/a
textUGName = //input[#id='user_group_name']
btnScheduleNow = //*[text()='Schedule Now']
userDestination = //*[#class='ConnectedList ConnectedListAdded']/div[2]/ul
userSearchField = //div[#class='ConnectedListConnectedListSelect']/div[2]/div[1]/ul/li[1]/input
searchedUserSource = //div[#class='ConnectedList ConnectedListSelect']/div[2]/ul/li/span[5]
Exception:
org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
Command duration or timeout: 10.28 seconds
A StaleReferenceException occurs for mainly one of two reasons:
The element has been deleted entirely.
The element is no longer attached to the DOM.
One possible solution to your problem is to surround dragAndDrop() in a while loop, and continually try and dragAndDrop() until you succeed. So something like the following:
boolean draggedAndDropped = false;
while(!draggedAndDropped ) {
try{
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));
destination = driver.findElement(By.xpath(OR.getProperty("userDestination")));
dragAndDrop(source, destination);
draggedAndDropped = true;
} catch(StaleElementReferenceException e) {
System.out.println("StaleElementReferenceException caught, trying again");
}
}
Of course its never a good idea idea to give allow a loop to loop infinitely, so you will want to incorporate a max attempts into the while loop.
As stated by the Selenium project's documentation, a StaleElementReferenceException can be thrown for two reasons:
The element has been deleted entirely.
The element is no longer attached to the DOM.
As such, I suspect that a race condition is occurring at this point:
driver.findElement(By.xpath(OR.getProperty("userSearchField"))).sendKeys("testuser2", Keys.ENTER);
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));
After you've entered "testuser2" in the "userSearchField" WebElement you've used Keys.ENTER to presumably submit the search query - the problem may be occurring because WebDriver is retrieving a reference to the "searchedUserSource" WebElement before the page has fully refreshed.
To get around this, you could try using the WebElement.submit() method to submit the search as it blocks the WebDriver's execution until the page has finished changing (i.e. finished displaying the search result).
Below is an example of how you could implement this:
driver.findElement(By.xpath(OR.getProperty("userSearchField"))).sendKeys("testuser2").submit();
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));
I have a large flows in my project. I am automating these flows using selenium if I get an any error in 99th step consisting of 100 steps then I need to start from first step.
So is there any thing to pause/continue selenium script even though if locator not found.
public void waitForElementToBeVisible(String cssSelector) throws Throwable {
try {
WebDriverWait wait = new WebDriverWait(driver, 30); //30 = TIMEOUT DURATION IN SECONDS
wait.until(ExpectedConditions.or(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector(cssSelector)) //CSS SELECTOR CAN BE DEFINED WHEN THIS METHOD IS CALLED e.g. waitForElementToBeVisible("Button");
));
} catch (Exception e) {
System.out.println("Timeout exceeded");
//ACTIONS YOU WANT TO CARRY OUT IF THE ELEMENT CAN'T BE FOUND, COULD JUST BE NOTHING.
}
}
alternatively, if you want to run this within your test, without setting up a method, simply do the following....
try {
WebDriverWait wait = new WebDriverWait(driver, 30); //30 = TIMEOUT DURATION IN SECONDS
wait.until(ExpectedConditions.or(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("Button")) //CSS SELECTOR CAN BE DEFINED WHEN THIS METHOD IS CALLED e.g. waitForElementToBeVisible("Button");
));
} catch (Exception e) {
System.out.println("Timeout exceeded");
//ACTIONS YOU WANT TO CARRY OUT IF THE ELEMENT CAN'T BE FOUND, COULD JUST BE NOTHING.
}
In tests that I write, if I want to assert a WebElement is present on the page, I can do a simple:
driver.findElement(By.linkText("Test Search"));
This will pass if it exists and it will bomb out if it does not exist. But now I want to assert that a link does not exist. I am unclear how to do this since the code above does not return a boolean.
EDIT This is how I came up with my own fix, I'm wondering if there's a better way out there still.
public static void assertLinkNotPresent (WebDriver driver, String text) throws Exception {
List<WebElement> bob = driver.findElements(By.linkText(text));
if (bob.isEmpty() == false) {
throw new Exception (text + " (Link is present)");
}
}
It's easier to do this:
driver.findElements(By.linkText("myLinkText")).size() < 1
I think that you can just catch org.openqa.selenium.NoSuchElementException that will be thrown by driver.findElement if there's no such element:
import org.openqa.selenium.NoSuchElementException;
....
public static void assertLinkNotPresent(WebDriver driver, String text) {
try {
driver.findElement(By.linkText(text));
fail("Link with text <" + text + "> is present");
} catch (NoSuchElementException ex) {
/* do nothing, link is not present, assert is passed */
}
}
Not Sure which version of selenium you are referring to, however some commands in selenium * can now do this:
http://release.seleniumhq.org/selenium-core/0.8.0/reference.html
assertNotSomethingSelected
assertTextNotPresent
Etc..
There is an Class called ExpectedConditions:
By loc = ...
Boolean notPresent = ExpectedConditions.not(ExpectedConditions.presenceOfElementLocated(loc)).apply(getDriver());
Assert.assertTrue(notPresent);
Try this -
private boolean verifyElementAbsent(String locator) throws Exception {
try {
driver.findElement(By.xpath(locator));
System.out.println("Element Present");
return false;
} catch (NoSuchElementException e) {
System.out.println("Element absent");
return true;
}
}
With Selenium Webdriver would be something like this:
assertTrue(!isElementPresent(By.linkText("Empresas en MisiĆ³n")));
boolean titleTextfield = driver.findElement(By.id("widget_polarisCommunityInput_113_title")).isDisplayed();
assertFalse(titleTextfield, "Title text field present which is not expected");
It looks like findElements() only returns quickly if it finds at least one element. Otherwise it waits for the implicit wait timeout, before returning zero elements - just like findElement().
To keep the speed of the test good, this example temporarily shortens the implicit wait, while waiting for the element to disappear:
static final int TIMEOUT = 10;
public void checkGone(String id) {
FluentWait<WebDriver> wait = new WebDriverWait(driver, TIMEOUT)
.ignoring(StaleElementReferenceException.class);
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
try {
wait.until(ExpectedConditions.numberOfElementsToBe(By.id(id), 0));
} finally {
resetTimeout();
}
}
void resetTimeout() {
driver.manage().timeouts().implicitlyWait(TIMEOUT, TimeUnit.SECONDS);
}
Still looking for a way to avoid the timeout completely though...
You can utlilize Arquillian Graphene framework for this. So example for your case could be
Graphene.element(By.linkText(text)).isPresent().apply(driver));
Is also provides you bunch of nice API's for working with Ajax, fluent waits, page objects, fragments and so on. It definitely eases a Selenium based test development a lot.
For node.js I've found the following to be effective way to wait for an element to no longer be present:
// variable to hold loop limit
var limit = 5;
// variable to hold the loop count
var tries = 0;
var retry = driver.findElements(By.xpath(selector));
while(retry.size > 0 && tries < limit){
driver.sleep(timeout / 10)
tries++;
retry = driver.findElements(By.xpath(selector))
}
Not an answer to the very question but perhaps an idea for the underlying task:
When your site logic should not show a certain element, you could insert an invisible "flag" element that you check for.
if condition
renderElement()
else
renderElementNotShownFlag() // used by Selenium test
Please find below example using Selenium "until.stalenessOf" and Jasmine assertion.
It returns true when element is no longer attached to the DOM.
const { Builder, By, Key, until } = require('selenium-webdriver');
it('should not find element', async () => {
const waitTime = 10000;
const el = await driver.wait( until.elementLocated(By.css('#my-id')), waitTime);
const isRemoved = await driver.wait(until.stalenessOf(el), waitTime);
expect(isRemoved).toBe(true);
});
For ref.: Selenium:Until Doc
The way that I have found best - and also to show in Allure report as fail - is to try-catch the findelement and in the catch block, set the assertTrue to false, like this:
try {
element = driver.findElement(By.linkText("Test Search"));
}catch(Exception e) {
assertTrue(false, "Test Search link was not displayed");
}
This is the best approach for me
public boolean isElementVisible(WebElement element) {
try { return element.isDisplayed(); } catch (Exception ignored) { return false; }
}
For a JavaScript (with TypeScript support) implementation I came up with something, not very pretty, that works:
async elementNotExistsByCss(cssSelector: string, timeout=100) {
try {
// Assume that at this time the element should be on page
await this.getFieldByCss(cssSelector, timeout);
// Throw custom error if element s found
throw new Error("Element found");
} catch (e) {
// If element is not found then we silently catch the error
if (!(e instanceof TimeoutError)) {
throw e;
}
// If other errors appear from Selenium it will be thrown
}
}
P.S: I am using "selenium-webdriver": "^4.1.1"
findElement will check the html source and will return true even if the element is not displayed. To check whether an element is displayed or not use -
private boolean verifyElementAbsent(String locator) throws Exception {
boolean visible = driver.findElement(By.xpath(locator)).isDisplayed();
boolean result = !visible;
System.out.println(result);
return result;
}
For appium 1.6.0 and above
WebElement button = (new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//XCUIElementTypeButton[#name='your button']"))));
button.click();
Assert.assertTrue(!button.isDisplayed());