Selenium if sentence and the click else find some other and click - java

I have a problem with Selenium Webdriver. Following code is where my headache is at:
boolean FindPrimary=driver.findElement(By.xpath("//*[#id='started_in_business_view']/p")) != null;
if(FindPrimary){
driver.findElement(By.xpath("//*[#id='started_in_business_view']/p")).click();
}
else
driver.findElement(By.xpath("//*[#id='started_in_business_view']/div")).click();
The excepted result that I want to achieve is that the driver searches for the element and clicks it. And if it doesn´t find it ,the driver clicks the optional element.

I assume you received a NoSuchElement in the first line.
boolean findPrimary=driver.findElements(By.xpath("//*[#id='started_in_business_view']/p")).size() > 0;
if(findPrimary){
driver.findElement(By.xpath("//*[#id='started_in_business_view']/p")).click();
}
else
driver.findElement(By.xpath("//*[#id='started_in_business_view']/div")).click();

I would do it with
try{
driver.findElement(By.xpath("//*[#id='started_in_business_view']/p")).click();
} catch (Exception exc) {
driver.findElement(By.xpath("//*[#id='started_in_business_view']/div")).click();
}
if you're xpaths are correct, should work...

Related

Selenium last conditional fail or pass

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.

StateElementReferenceException in Selenium

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")));

Selenium Try/Catch Error

I am using Selenium with Java an facing the following problem.
When I use the following code:
driver.findElement(By.xpath(firstNameXPath)).sendKeys(firstName);
I am able to successfully select the appropriate locator on the page and get no errors.
However, when I pass the locator to a method to check if the locator exists first and only then send keys I always get an error (locator not being present).
This is the method I am using:
public boolean IsXPathPresent(String XPath)
{
try
{
driver.findElement(By.xpath(XPath));
System.out.println("Selector: " + XPath + " found");
return true;
} catch (Exception e)
{
System.out.println(XPath + " Selector Not Present");
return false;
}
}
I am passing firstNameXPath to the method IsXPathPresent.
For some reason my program always outputs "Selector Not Present" which means it is always executing the catch part. But why ? The selector is present on page..
Is there something wrong with my try/catch block?
Thanks

NoSuchElementException after switching frames

UPDATE:
I think I saw the error, I configure again my Selenium IDE and recreate the test, and when i open in Eclipse i see this comments in code:
public void testEcsf3() throws Exception {
driver.get(baseUrl + "/something.com");
WebElement frame = driver.findElement(By.name("body"));
driver.switchTo().frame(frame);
//...
//code for navigate to the target page
//...
// ERROR: Caught exception [ERROR: Unsupported command [selectWindow | name=body | ]]
//Target page - another frame with name 'body'
driver.findElement(By.xpath("//tr[28]/td[2]/a/font")).click();// <-- target element in target page
//...
//code for navigate to the target page
//...
}
The problem is that the flow between pages have more of one frame with name 'body'(i can't change that), how i can make this work?
Thanks.
--
I'm trying to use a Selenium testcase(Ok in browser) using JUnit in Eclipse.
When I try to run the testcase I receive this error:
org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"name","selector":"user"}
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Driver info: org.openqa.selenium.firefox.FirefoxDriver
Note: the link mentioned in the error has no content!
This is the point of error:
driver.get(baseUrl + "/something.com");
driver.findElement(By.name("user")).sendKeys("aaa"); //<--
driver.findElement(By.name("password")).sendKeys("xxx");
driver.findElement(By.name("button0")).click();
I think your problem is the following:
This line: driver.get(baseUrl + "/something.com"); says him to go to this page, and the second line says him to search for the element immediately (so the browser dont have time at all to load the page)
So try this:
WebDriverWait wait;
wait = new WebDriverWait(webdriver, 10);
try{
wait.until(ExpectedConditions.visibilityOfElementLocated(By.name("user")));
}catch(TimeoutException e){
verifyElementPresent(locator);
}
or:
for (int second = 0;; second++) {
if (second >= 60)
fail("timeout");
try {
if (isElementPresent(By.name("user"))) {
break;
}
} catch (Exception e) {
}
Thread.sleep(1000);
}
Are you bound to the Driver? you could try this:
Selenium selenium = new WebDriverBackedSelenium(driver,"http://example.com");
selenium.open("http://something.com");
and optionally a
selenium.waitForPageToLoad();
The other things you tried to do are also simpler with the WebDriverBackedSelenium like
selenium.type(String field,String text);
you can look at that for the javadoc and deeper explanation
I stop for some days this project, and today i resolve the trouble.
This is the code:
for (String handle : driver.getWindowHandles()) {
driver.switchTo().window(handle);
}
WebElement body = driver.findElement(By.name("body"));
driver.switchTo().frame(body);
I hope this help someone.
Thanks.

Assert that a WebElement is not present using Selenium WebDriver with java

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());

Categories