Finding and Clicking element in list - Selenium - java

I have been messing around with automating this options page, and since it provides a variety of options each with its own sub-options, I do not want to take the time to identify and declare all of the elements by their xpath(or CSS.. either or). So I have this reliable code that does a good job at finding the text identifier in the HTML tags.
public void selectAnOption(String option) {
List<WebElement> choice = driver.findElements(By.xpath("//div[#class='atcui-scrollPanel-wrapper']/ul/li"));
for(WebElement e : choice){
System.out.println(e.getText());
if(e.getText().equals(option)){
e.click();
break;
}
}
}
By running this I get a printout like
Mileage
Transmission
Gas Type
And so on.So boom! I know that they are identified, but my e.click() is not actually clicking. I get no errors when I start the test it just says it passed but the button was never actually clicked. Below is the HTML segment I am working with and you can see how nested it is.

For Java 8 and above you can use:
public void selectAnOption(String option) {
List<WebElement> choice = driver.findElements(By.xpath("your_xpath"));
choice
.stream()
.filter(e->e.getText().equals(option))
.findFirst().get().click();
}

Fixed it.. for anyone with a similar issue, I believe it lies in the fact that when this html code was developed, there were excess spaces (used for design purposes or fitting elements during development..maybe?) so I used .contains instead of .equals. duh!!
public void selectAnOption(String option) {
List<WebElement> choice = driver.findElements(By.xpath("//div[#class='atcui-scrollPanel-wrapper']/ul/li"));
for(WebElement e : choice){
System.out.println(e.getText());
if(e.getText().contains(option)){
e.click();
break;
}
}
}

Related

How to extract the display attribute of an element using Selenium Webdriver and Java

unable to locate the hidden element in div
<div id="divDuplicateBarcodeCheck" class="spreadsheetEditGui" style="z-
index: 1200; width: 640px; height: 420px; top: 496.5px; left: 640px;
display:block"> ==$0
I want to locate the display element, but the element is hidden, i have written the code for it too.
String abc=d.findElement(By.xpath("//div[#id='divDuplicateBarcodeCheck']/"))
.getAttribute("display");
System.out.println(abc);
Thread.sleep(3000);
if(abc.equalsIgnoreCase("block"))
{
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
}
else
{ System.out.println("Barcode selected");}
There is no such attribute as display. It's part of style attribute.
You can either find the element and get its attribute style:
String style = d.findElement(By.xpath("//div[#id='divDuplicateBarcodeCheck']")).getAttribute("style");
if(style.contains("block")) {
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
} else {
System.out.println("Barcode selected");}
}
OR you can find this element directly with cssSelector (it's also possible with xpath):
WebElement abc = d.findElement(By.cssSelector("div[id='divDuplicateBarcodeCheck'][style*='display: block']"))
Note, that above will throw NoSuchElementException if the element was not found. You can use try-catch block to perform similar operations just like you did in if-else statement like this:
try {
d.findElement(By.cssSelector("div[id='divDuplicateBarcodeCheck'][style*='display: block']"));
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
} catch (NoSuchElementException e) {
System.out.println("Barcode selected");
}
If I'm getting you correct you are trying to archive checking if an element is displayed or not. You could do something like this using plain selenium and java:
// the #FindBy annotation provides a lazy implementation of `findElement()`
#FindBy(css = "#divDuplicateBarcodeCheck")
private WebElement barcode;
#Test
public void example() {
driver.get("http://some.url");
waitForElement(barcode);
// isDisplay() is natively provided by type WebElement
if (barcode.isDisplayed()) {
// do something
} else {
// do something else
}
}
private void waitForElement(final WebElement element) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOf(element));
}
Your Test (an end-to-end UI test!) should not stick to an implementation detail like display:none or display:block. Imagine the implementation will be changed to remove the element via javascript or something. A good selenium test should always try represent a real users perspective as good as possible. Means if the UI will still behave the same your test should still be successful. Therefore you should do a more general check - is an element displayed or not.
This is one of the basic functionalities of Seleniums WebElement interface, or to be even more precise its isDisplayed() method.
Quote from the Selenium Java Docs:
boolean isDisplayed()
Is this element displayed or not?
This method avoids the problem of having to
parse an element's "style" attribute.
Returns:
Whether or not the element is displayed
Furthermore I would recommend to write some small helper methods for things like that, in my experience it's a common use case you'll face more often.
helper method could for instance look something like this:
boolean isElementVisible(final By by) {
return driver.findElement(by).isDisplayed();
}
boolean isElementVisible(final WebElement element) {
return element.isDisplayed();
}
If you are using some Selenium abstractions like FluentLenium or Selenide things will become even more convenient because they provide things like assertion extensions and custom matchers for well known assertion libraries like assertJ, hamcrest, junit.
For instance with FluentLenium and AssertJ (a stack that i can personally recommend) the answer for your problem is looking as easy as this:
// check if element is displayed
assertThat(el("#divDuplicateBarcodeCheck")).isDisplayed();
// check if element is not displayed
assertThat(el("#divDuplicateBarcodeCheck")).isNotDisplayed();
Some more thoughts:
You should also use CSS selectors if possible instead of xPath selectors. CSS selectors are less fragile, it will speed up your tests and are better readable.
You should have a look at implicit waits instead of using Thread sleeps (bad practice). you can again implement helper methods like this by yourself, e.g:
void waitForElement(final WebElement element) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOf(element));
}
void waitForElement(final By by) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(by));
}
void waitForElementIsInvisible(final By by) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.invisibilityOfElementLocated(by));
}
or (what i would recommend) use a library for that, for instance Awaitility
If your are looking for a more extended example you can have a look here:
java example with plain selenium
example using fluentlenium and a lot of other helpful stuff
Seems there is an extra / at the end of the xpath which you need to remove. Additionally, you need to induce WebDriverWait for visibilityOfElementLocated(). So effectively your line of code will be:
String abc = new WebDriverWait(d, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//label[contains(.,'Leave Balance')]//following::div[#id='applyleave_leaveBalance']"))).getAttribute("style");
System.out.println(abc);
if(abc.contains("block"))
{
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
}
else
{
System.out.println("Barcode selected");
}
Virtually, if() block is still an overhead and you can achieve the same with:
try {
new WebDriverWait(d, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//label[contains(.,'Leave Balance')]//following::div[#id='applyleave_leaveBalance']"))).click();
System.out.println("duplicate barcode Close");
} catch (NoSuchElementException e) {
System.out.println("Barcode selected");
}
Q1. I want to locate the display element, but the element is hidden, i have written the code for it too.
A1. As per your below code:
<div id="divDuplicateBarcodeCheck" class="spreadsheetEditGui" style="z-
index: 1200; width: 640px; height: 420px; top: 496.5px; left: 640px;
display:block"> ==$0
It doesn't look hidden, the problem is that your using incorrect xpath and element getter.
Use:
String abc = d.findElement(By.xpath("//div[#id='divDuplicateBarcodeCheck']"))
.getCssValue("display");
Instead of:
=> .getAttribute("display");
Alternative method using JavascriptExecutor:
JavascriptExecutor jse = (JavascriptExecutor) d;
String displayProperty = (String) jse.executeScript("return
document.getElementById('divDuplicateBarcodeCheck').style.display");
System.out.println("Display property is: "+displayProperty);

Selenium, ensure that all the checkbox are checked

I'm using Selenium to test action on a html page. The one i'm working on contains multiple list of check box. My selenium script do the following actions :
-Click on the dropdown list to display the check box list
-Click on all the check box
-Click on the dropdown list to close the check box list
-Repeat for the next list
The problem is that somtimes the script goes too fast for the browser and some box are not checked, it happens really often since i make multiple test
To resolve my problem i tried to make a method that check if the
checkbox is checked, if not then i click again but it's not working and it increases the time of my test. Here my code so far :
public void clickClearanceListBox(int numberInList) throws InterruptedException {
int iteration = countTheNumberOfElement("//div[5]/div["+numberInList+"]/div[2]");
for(int i = 1; i <= iteration; i++) {
String xpathBox ="//div["+numberInList+"]/div[2]/div["+i+"]/div/div/label/span/span[2]";//xpath de la checkbox
String xpathInput = "//div["+numberInList+"]/div[2]/div["+i+"]/div/div/label/input";
clickTheDOMbyJs(xpathBox);
while(!checkBoxChecked(xpathInput)) {
Thread.sleep(200);
clickTheDOMbyJs(xpathBox);
}
}
}
Or :
public void clickClearanceListBox(int numberInList) throws InterruptedException {
int iteration = countTheNumberOfElement("//div[5]/div["+numberInList+"]/div[2]");
for(int i = 1; i <= iteration; i++) {
String xpathBox ="//div["+numberInList+"]/div[2]/div["+i+"]/div/div/label/span/span[2]";//xpath de la checkbox
String xpathInput = "//div["+numberInList+"]/div[2]/div["+i+"]/div/div/label/input";
clickTheDOMbyJs(xpathBox);
while(!checkBoxChecked(xpathInput)) {
Thread.sleep(200);
}
}
}
It looks like you need to use WebDriverWait in here. First, wait for the dropdown list to load completely, then wait for the checkbox to be visible.
A word of warning to you though. These xpaths are likely to be very brittle, and your tests will break quite easily. You should consider finding these various elements using ids, classes, or other attributes.
I manage to do it by checking if the attribute "value" of my checkbox has the value "true". While the attribute value is false, it means that the checkbox is still not checked for the browser so i wait... This extremly slow but at least it's working everytime. After the script clicked on the checkbox i do this :
while(!getAnElementAttribute(xpathInput, "value").equals("true")) {
}

Verify Select element

Good afternoon in my timezone
I am using Selenium to test my web application.There is a dropdown list on a page that when we choose one value from it, it will fullfill 3 input text fields and select values in three more dropdown lists.
There is a lot of possible combinations to fullfill those fields so i want to use regular expressions to verify the fulfillment.The Dropdown list when selected makes an Ajax call to fullfill all those fields.
So i was thinking to use the following statements to make the "assertions":
wait.until(ExpectedConditions.textToBePresentInElement(By.xpath("//input[#name='name']"), text));
This statement will be used to check the input fields, but i realize that the method "textToBePresentInElement" does not accept regular expression in the place of the text(second argument). Which options do i have ?
Because the fullfillment is made through Ajax , i have to wait , one possible solution is to use Thread.sleep while verifying the text through something like this driver.findElement().getText().matches("REgEx");
There is no better solution ?
To check the other 3 dropdown lists what method should i use ?
The Thread.sleep following this statement :
(new Select(driver.findElement(By.xpath("//select[#name='tipoTransacao']")))).getFirstSelectedOption().getText().matches
Thanks in advance
Best regards
Here is Java solution
public void waitUntilTextIsPresent(WebElement element, String regex, long timeout, long polling) {
final WebElement webElement = element;
final String regex = regex;
new FluentWait<WebDriver>(driver)
.withTimeout(timeout, TimeUnit.SECONDS)
.pollingEvery(polling, TimeUnit.MILLISECONDS)
.until(new Predicate<WebDriver>() {
public boolean apply(WebDriver d) {
return (webElement.getText().matches(regex);
}
});
}
A horrible mismash of Java & C# here, due to copy/pasting your examples and my working solution, but hopefully you can adapt it to just Java...
This should wait until the regex matches, you don't always have to use the ExpectedConditions class
public void WaitForTextPresent(By by, string regex, int maxSecondsToWait = 30)
{
new WebDriverWait(_webDriver, new TimeSpan(0, 0, maxSecondsToWait))
.Until(d => d.FindElement(by).getText().matches(regex));
}

Which is the correct way to check if an element is present or displayed on a page with Selenium WebDriver using Java?

I'm testing a web application using Selenium WebDriver and I was wondering which is the proper method to check if the elements are present or displayed. I usually assert that all elements are present on the page but it also checks the hidden elements which in this case would also be necessary to check if the elements are displayed only when some action is done. For example I click a link and other fields and labels are displayed, while they were hidden before. In this case I should both check if the elements are present and also if they are or not displayed before and after some other element is clicked.
I was wondering which is the proper way to do this. Is it too much to check all the elements on the page ( assuming that I have some buttons, text-fields, labels, links etc. in the page)?
For the purpose of discussion I want to include some code snippets. To check that elements are present on the page I use the following snippet:
public boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
To check if an element is displayed I use the following snippet:
public boolean isElementDisplay(By by) {
if (driver.findElement(by).isDisplayed()) {
return true;
} else
return false;
}
One purpose of testing this application is to check if the elements exists and are displayed correctly. Am I doing the right thing here? Please give me your point of view. I've recently started working with Selenium WebDriver and being the only one in my company who does this...I don't have anyone to turn to. Any answer is appreciated.
There are no problems with it, except if you call your "checkIfDisplayed" method on an element that doesn't exist in the first place, it will throw an exception. I would modify it to this:
public boolean checkIfDisplayed(By by) {
if (isElementPresent(by) {
if (driver.findElement(by).isDisplayed()) {
return true;
} else
return false;
} else
return false;
}
(This may not be code that compiles, I am a C# man, but you should see what I mean)
It may have a slight performance hit, but overall what you are doing is perfectly fine anyway.
To check for element's existence I'd rather use
public boolean isElementPresent(By by)
{
return driver.findElements(by).size() > 0
}
I don't really get the idea behind your checkIfDisplayed function. It returns the result returned by WebElemet's isDisplayed() method without adding any new functionality...
EDIT
So far Arran provided the best answer. Just to modify it a little bit:
public boolean checkIfDisplayed(By by)
{
List<WebElemet> elements = driver.findElements(by);
return ((elements.size() > 0) && (elements[0].isDisplayed()));
}
I believe however that it would be better to call isElementPresent and isDisplayed separately. In this way you will know why the test failed (if it was caused by element's existence or visibility)
I use the same approach (I mean the same methods). But it is important to understand two things.
Some element can be present but not visible.
So for the purpose to verify whether element is present we can call the method
public boolean isElementPresent(By locatorKey) {
try {
driver.findElement(locatorKey);
return true;
} catch (NoSuchElementException e) {
return false;
}
But the drawback of isElementPresent method it can point out elements in DOM model that are not visible on the page and consequently are not accesssible with webDriver. So in that case additional check helps us:
driver.findElement(By.xpath(....)).isDisplayed()
Hope things come clear now)
I'd say your first method looks just fine.
The 2nd thus will give you trouble if the findElement-call will give you no result.
You should add a check if there is an element found and then check if it's displayed:
try {
final WebElement elem = driver.findElement(by);
elem.isDisplayed();
return true;
} catch (NoSuchElementException nse) {
return false;
}
Also note: You are ignore the possibility that more than one element matches the criteria given by the by instance. See the findElemts() method.
You can also combine both the methods as per your requirement as follows,
if(driver.findElements(By.LOCATOR).size()>0)
{
if(driver.findElement(By.LOCATOR).isDisplayed())
{ print "Element is present and displayed"; }
else
{ print "Element is present but not displayed"; }
}
else
{ print "Element is not present"; }

Selenium webdriver can't click on a link outside the page

I am having an issue with Selenium WebDriver. I try to click on a link that is outside the window page (you'd need to scroll up to see it). My current code is fairly standard:
menuItem = driver.findElement(By.id("MTP"));
menuItem.click();
// I also tried menuItem.sendKeys(Keys.RETURN);
I know I could scroll up, and it would work in this case. But in a case where you have a long list of items, you don't necessarily know how far you have to scroll down.
Is there any way to click on a link that is not on the visible part of the page (but that would be visible if you scroll)?
As a side note, I'm using Firefox, but I am planning to use IE7/8/9 and Chrome as well.
Any help would be greatly appreciated.
Edit: I'm afraid I can't give the source code, as the company I work for doesn't allow it, but I can give the code of the link I want to click on:
<div class="submenu">
<div id="MTP">Link title</div>
</div>
The exact same code works when the link is visible, only when it is not does it not work.
Edit2: Actually, oddly enough, it doesn't raise any exception and just goes to the next instruction. So basically, what happens is:
menuItem = driver.findElement(By.id("MTP")); // no exception
menuItem.click(); // no exception
//... some code ensuring we got to the next page: timeout reached
driver.findElement(By.id("smLH")).click(); // NoSuchElementException, as we're on the wrong page.
It is actually possible to scroll automatically to element. Although this is not a good solution in this case (there must be a way to get it working without scrolling) I will post it as a workaround. I hope someone will come up with better idea...
public void scrollAndClick(By by)
{
WebElement element = driver.findElement(by);
int elementPosition = element.getLocation().getY();
String js = String.format("window.scroll(0, %s)", elementPosition);
((JavascriptExecutor)driver).executeScript(js);
element.click();
}
I posted this same answer in another question so this is just a copy and paste.
I once had a combo box that wasn't in view that I needed to expand. What I did was use the Actions builder because the moveToElement() function will automatically scroll the object into view. Then it can be clicked on.
WebElement element = panel.findElement(By.className("tabComboBoxButton"));
Actions builder = new Actions(this.driver);
builder.moveToElement(element);
builder.click();
builder.build().perform();
(panel is simply a wrapped element in my POM)
Instead of move the scrollbar to the button position, which sometimes it didn't work for me, I send the enter key to the button
var element = driver.FindElement(By.Id("button"));
element.SendKeys(Keys.Enter);
I ran into a similar problem recently when there was a list of selectable objects in a JS dialog. Sometimes selenium would not select the correct object in the list. So i found this javascript suggestion:
WebElement target = driver.findElement(By.id("myId"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", target);
Thread.sleep(500); //not sure why the sleep was needed, but it was needed or it wouldnt work :(
target.click();
That solved my issue
Hey you can use this for ruby
variable.element.location_once_scrolled_into_view
Store the element to find in variable
It might be occurring because your header element or the footer element might be blocking the view of the element you want to perform action on. Selenium tries to scroll to the element position when it has to perform some action on the element (I am using Selenium WebDriver v3.4.0).
Here is a workaround -
private WebElement scrollToElementByOffset(WebElement element, int offset) {
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("window.scrollTo(" + element.getLocation().getX() + "," + (element.getLocation().getY()
+ offset) + ");");
return element;
}
The above function scrolls the view to the element and then scrolls further by the offset you provide. And you can call this method by doing something like -
WebElement webElement = driver.findElement(By.id("element1"));
scrollToElementByOffset(webElement, -200).click();
Now, this is just a workaround. I gladly welcome better solutions to this issue.
This solution worked like a charm for me:
public void click(By by) throws Exception{
WebElement element = driver.findElement(by);
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500);
element.click();
}
This works for me (in c#)-
item = driver.findelement(by.....);
item.SendKeys(Keys.LeftControl);
item.Click();
Just an addition:
In my case the button was overlapped by another floating button.
Just resizing the browser window solved the problem!
I used the method below to solve a similar issue for Selenium Java:
public static void scrollToElementByElement(WebElement element) {
Coordinates coordinates = ((Locatable)element).getCoordinates();
coordinates.inViewPort();
coordinates.click(); //if needed
}
Then called on the method on my main test class
I have used below method to solve the problem of element not present in the visible area. The code scrolls down the webpage, till selenium operations can be performed on the element. Change the co ordinate of Y-axis and value of i as per requirement.
public void scrooling(By ele) throws InterruptedException {
for (int i = 0; i < 10; i++) {
try {
driver.findElement(ele);
break;
} catch (ElementNotVisibleException e) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,400)");
System.out.println("inside ElementNotVisibleException block");
Thread.sleep(3000);
} catch (NoSuchElementException e) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,400)");
System.out.println("inside NoSuchElementException block");
Thread.sleep(3000);
}
}
}

Categories