How to put add condition in for loop using java / selenium - java

I wanted to click on Add button to add items , after clicking on add button if it displayed error then it should remove that added item and again it should click on add button to add items
Here is my code:
driver.findElement(By.id("addItem")).click(); // it will add item
WebElement errrmsg = driver.findElement(By.id("sameAMC-invalid"));
/* if error is displayed then it should remove added item and should
*again add another item again clicking on add item button and should again check
*whether it is showing error message or not if not then else condition should get
*execute*/
if(errrmsg.isDisplayed())
{
driver.findElement(By.id("remove-Itemadd")).click();
Thread.sleep(2000);
}
else
{
driver.findElement(By.id("button-payment")).click();
Thread.sleep(6000);
}
I want to put loop condition when error occured , which is it should again click on add item button and also it should check whether it is showing any error if not then it should execute in else condition ..... i don't know how to do this ...need help

You can use while as given below. but it goes to infinite loop and if you know the maximum count. we can include the condition to check as well.
driver.findElement(By.id("addItem")).click(); // it will add item
WebElement errrmsg = driver.findElement(By.id("sameAMC-invalid"));
while(errrmsg.isDisplayed())
{
driver.findElement(By.id("remove-Itemadd")).click();
Thread.sleep(2000);
driver.findElement(By.id("addItem")).click(); // it will add item
errrmsg = driver.findElement(By.id("sameAMC-invalid"));
}
driver.findElement(By.id("button-payment")).click();
Thread.sleep(6000);

try this code : Use findElements instead of findElement
driver.findElement(By.id("addItem")).click();
while(true) {
List<WebElement> errMsg = UI.getdriver().findElements(By.id("sameAMC-invalid"));
if(errMsg.size()==1) {
driver.findElement(By.id("remove-Itemadd")).click();
Thread.sleep(2000);
driver.findElement(By.id("addItem")).click();
}
else if(errMsg.size() == 0 ) {
driver.findElement(By.id("button-payment")).click();
Thread.sleep(6000);
break;
}
}
Note : Code provided by #Murthi would fail , if there is no error msg.

You can try next:
private By removeButtons = By.xpath("remove-Itemadd");
private By addButtons = By.xpath("addItem");
private By errorMsg = By.xpath("sameAMC-invalid");
private By payButton = By.id("button-payment");
private boolean isErrorOccur() {
try {
return driver.findElement(errorMsg).isDisplayed();
} catch (org.openqa.selenium.NoSuchElementException ex) {
return false;
}
}
public void someMethod() {
List<WebElement> addItemsButtons = driver.findElements(addButtons);
List<WebElement> deleteItemsButtons = driver.findElements(removeButtons);
//it will be works if this add/remove buttons are enabled for all items - list size is the same
for (int i = 0; i < addItemsButtons.size(); i++) {
addItemsButtons.get(i).click();
if (isErrorOccur()){
deleteItemsButtons.get(i).click();
//here need some wait, possibly
}
}
driver.findElement(payButton).click();
//here need some wait, possibly
}

Related

Selenium Java compare not true?

i'm trying to compare some texts with this code bellow:
driver.get("https://www.hotel.de/");
boolean status = false;
String searchText = "Hannover, Niedersachsen";
WebElement inputBox = driver.findElement(By.xpath("//div[#class='LocationAutoSuggest__container--2Hli_']//input"));
Now i send String "Hannover" to Searchbox:
Actions actions = new Actions(driver);
actions.moveToElement(inputBox).click().sendKeys("Hannover").build().perform();
Thread.sleep(3000);
List<WebElement> listsearch = driver.findElements(By.id("react-autowhatever-1"));
And compare the found text with searchText :
for(WebElement listElem : listsearch) {
System.out.println(listElem.getText());
System.out.println(searchText.equals(listElem.getText()));
if(searchText.equals(listElem.getText())) {
System.out.println("hooho");
status = true;
break;
} else {
status = false;
}
}
System.out.println(status);
==> Could you tell me: why i become FALSE instead of TRUE? (How can i see the logs, to know what was actually compared?). Many thanks.
Check the size of your List if it zero than directly false will be printed.
If size is not greater than zero check your locator.

Appium is able to see beyond what is displayed on screen

Appium is able to see and find elements that is not displayed on screen
I am trying to build a test automation project, I would like my driver to scroll down
and then perform some operation. but for some reason appium is able to find element even without scrolling down . I am not sure how appium is able to identify element that is not on screen and is only visible to naked eye when you scroll down. Anyone with similar issue found a workaround ?
I am using ExpectedCondition.visibilityOF(element) to determine if element is vsible on screen
public boolean verifyCoverage(String coverage, String value, String type) throws IOException, InterruptedException {
int counter = 0;
for (int i = 0; i < 15; i++) {
AndroidElement element = (AndroidElement) driver.findElementByAndroidUIAutomator("UiSelector().textContains(\"" + coverage + "\")");
//WebElement coverageOption= driver.findElementByXPath("//android.widget.Button[contains(text(),'"+coverage+"')]");
if (AndroidUtilities.waitForVisibility(driver, element)) {
return true;
}
else {
System.out.println ("Cannot see");
return false;
}
}
public static boolean waitForVisibility(AndroidDriver<WebElement> driver, AndroidElement AndroidElement){
try{
// driver.findElementByAndroidUIAutomator("UiSelector().resourceId(\""+targetResourceId+"\")");
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(AndroidElement));
boolean isElementPresent = AndroidElement.isDisplayed();
return isElementPresent;
}catch(Exception e){
boolean isElementPresent = false;
System.out.println(e.getMessage());
return isElementPresent;
}
}
As an answer i would recommend you to use visibilityOfElementLocated instean of visibilityOf.
Plus, if you want to check an element for the existence without getting exceptions, try to take that approach:
if (!((AndroidDriver)driver).findElementsByAndroidUIAutomator("UiSelector().textContains(\"" + coverage + "\")").isEmpty()) {
//some logic when element is located
} else {
//scroll to the particular element
}
You can try these two solution within the page it will able to scroll to the element and do your actions .
MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().textContains(\""+element+"\").instance(0))"));
MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().textMatches(\"" + NumbersCount + "\").instance(0))"));

Select items from 3 dropdowns with dependency of first one

What I want to do is:
1- Going to this site: http://www.emlakyonetim.com.tr/tr-TR/sitelerimiz ,
2- Click on first dropdown - click a city, click second dropdown - click a county, click third dropdown.
At short, second dropdown items are dependant on first one and third dropdown items are dependant on second one.
Code (not complete):
#Test
public void SiteCek() throws InterruptedException
{
driver.get("http://www.emlakyonetim.com.tr/tr-TR/sitelerimiz");
Thread.sleep(2000);
driver.findElement(By.id("select2-city-list-container")).click();
List<WebElement> elm = driver.findElements(By.xpath("//*[#class='select2-results__option']"));
for(int i = 1; i < elm.size(); i++)
{
By ID = By.id(driver.findElements(By.xpath("//*[#class='select2-results__option']")).get(i).getText());
System.out.println(ID);
driver.findElements(By.xpath("//*[#class='select2-results__option']")).get(i).click();
Thread.sleep(500);
}
}
I get java.lang.IndexOutOfBoundsException: Index: 2, Size: 0 error after city "ADANA".
If I manage to handle first error, I will write second and third for loops, so code is this for now.
When the issue is solved I want to get all cities first. Then countys of each city. Then sites of each county. This must be done dynamically as the size of city list, county list and site list. To do that I need three nested for loops. After all of that, each value must be written in excel.
here is the code that worked for me
public void testMethod() {
driver.manage().window().maximize();
WebElement firstDropDown = driver.findElement(By.id("select2-city-list-container"));
firstDropDown.click();
sleep();
List<WebElement> citiesEls = getCitiesEls();
Map<String, Map<String, List<String>>> cityData = new HashMap<>();
for (int i = 0; i < citiesEls.size(); i++) {
//we need to take this element every iteration, because it gets reloaded every time we open the dropdown
WebElement cityEl = driver.findElement(By.id("select2-city-list-results")).findElements(By.xpath("//*[contains(#id,'select2-city-list-result')]")).get(i);
String cityText = cityEl.getText();
cityEl.click();
sleep();
cityData.put(cityText, getRegions());
firstDropDown.click();
sleep();
}
System.out.println(cityData);
}
private Map<String, List<String>> getRegions() {
WebElement secondDropDown = driver.findElement(By.id("select2-region-list-container"));
secondDropDown.click();
sleep();
List<WebElement> regionsEls = getRegionEls();
Map<String, List<String>> regionData = new HashMap<>();
for (int i = 0; i < regionsEls.size(); i++) {
WebElement regionEl = driver.findElement(By.id("select2-region-list-results")).findElements(By.xpath("//*[contains(#id,'select2-region-list-result')]")).get(i);
String regionText = regionEl.getText();
regionEl.click();
WebElement thirdDropDown = driver.findElement(By.id("select2-site-list-container"));
thirdDropDown.click();
List<WebElement> sitesEl = getSiteEls();
List<String> sitesTexts = getSites(sitesEl);
//populate region data
regionData.put(regionText, sitesTexts);
secondDropDown.click();
sleep();
}
return regionData;
}
private List<String> getSites(List<WebElement> sitesEl) {
List<String> sitesTexts = new ArrayList<>();
for (WebElement siteEl : sitesEl) {
sitesTexts.add(siteEl.getText());
}
return sitesTexts;
}
private List<WebElement> getSiteEls() {
WebElement ulSites = driver.findElement(By.id("select2-site-list-results"));
return ulSites.findElements(By.xpath("//*[contains(#id,'select2-site-list-result')]"));
}
private List<WebElement> getRegionEls() {
return driver.findElement(By.id("select2-region-list-results")).findElements(By.xpath("//*[contains(#id,'select2-region-list-result')]"));
}
private List<WebElement> getCitiesEls() {
return driver.findElement(By.id("select2-city-list-results")).findElements(By.xpath("//*[contains(#id,'select2-city-list-result')]"));
}
As data is dynamically changed after each click, you might need some delays after each click. The code below worked well on Mac+Chrome. Nevertheless, if it fails from you end do add a sleep method call after each click.
private void sleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
Important note: Sleeps are not recommended to use, and should be used only as the quick temporary workaround. More robust solution is to use smart waits

Handling alerts using if/else in Java

How to handle the alerts using if/else commands? If alerts comes up do accept/dismiss, if not proceed further. I was trying with below code but an error at (r==true) says incompatible type.
bool r = driver.findElement(By.xpath("//div[contains(text(),'javax.baja.sys.ActionInvokeException')]"));
if (r = true) {
driver.switchTo().alert().accept();
} else {
Actions click2 = new Actions(driver);
WebElement dclick2 = driver.findElement(By.xpath(".//span[text()='Bluemix_As_Device']"));
click2.moveToElement(dclick2).doubleClick().build().perform();
}
The incompatible type is for the reason that
driver.findElement
would return a WebElement type and not a boolean(that's java). You might want to change the code to:
try {
WebElement r = driver.findElement(By.xpath("//div[contains(text(),'javax.baja.sys.ActionInvokeException')]"));
driver.switchTo().alert().accept(); // this would be executed only if above element is found
} catch (NoSuchElementException ex) {
// since the element was not found, I 'm still doing some stuff
Actions click2 = new Actions(driver);
WebElement dclick2 = driver.findElement(By.xpath(".//span[text()='Bluemix_As_Device']"));
click2.moveToElement(dclick2).doubleClick().build().perform();
}
As r is of boolean type so there is no need to write if(r == true) or if(r == false) you can directly write if(r) and java will understand the code.
driver.findElements will check the existence of the object and will return 1 if exist else zero.
So in your case though the alert exist or not, it will handle and based on size it will execute next step. Hope this helps in your case.
int r= driver.findElements(By.xpath("//div[contains(text(),'javax.baja.sys.ActionInvokeException')]")).size();
if(r!=0){
driver.switchTo().alert().accept();
} else {
Actions click2 = new Actions(driver);
WebElement dclick2 = driver.findElement(By.xpath(".//span[text()='Bluemix_As_Device']"));
click2.moveToElement(dclick2).doubleClick().build().perform();
}

how to click a result from google search that is not on first page with selenium java

I am trying to navigate through search results from google with selenium webdriver. I have a interface for user to inset word to search and site title to choose. If the result is not on the first page the driver should go to next page to look for the site, and if not there than to next page and so on..
Somehow I don't manage to get beyond the second page end if I did get to the second page and the right site is there, the driver doesn't click on it.
Here is some of the code in Java:
private void setLoopNum(int l){
String getText = urlText.getText();
String getSiteName = linkToChoose.getText();
System.setProperty("webdriver.chrome.driver", "C:\\selenium-2.44.0\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize(); //Maximize window
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
for(int i=0;i<l;i++){
//WebDriver driver = new FirefoxDriver();
driver.get("http://google.com");
//driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
WebElement element1 = driver.findElement(By.name("q"));
element1.sendKeys(getText);
element1.submit();
//driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS); //wait for page to load
//try{
boolean flag = false;
String page_number = "1";
while(! flag){
//get all the search results
List<WebElement> linkElements = driver.findElements(By.xpath("//h3[#class='r']/a"));
for(WebElement eachResult: linkElements){
if(eachResult.getAttribute(getSiteName).equals(getSiteName)){
eachResult.findElement(By.xpath("//a[#href='" + getSiteName + "']")).click();;
flag =true;
}else{
driver.findElement(By.xpath("//a[#id='pnnext']/span")).click();
linkElements.clear(); //celean list
break;
} //end else
}
}//end while loop
//}catch(Exception e){
// System.out.println("Error!");
// }
}
driver.quit(); //clear memory
}
Three things that you are missing in your code:
Firstly, in your code you are looking for only first element in your list.
Secondly, in getAttribute you are passing link instead of href:
if(eachResult.getAttribute(getSiteName).equals(getSiteName)){
it should be:
if(eachResult.getAttribute("href").equals(getSiteName)){
Thirdly, on clicking next the page is loaded via Google Ajax Api. Thus webdriver click will never block the execution of your code and will load linkElements with previous page links only. To avoid this let the driver get refreshed or put some wait for certain condition in your code.
Can u try out with this code:
WebDriverWait wait = new WebDriverWait(driver, 10)
while (!flag) {
// get all the search results
linkElements = wait
.until(ExpectedConditions
.presenceOfAllElementsLocatedBy(By
.xpath("//h3[#class='r']/a")));
for (WebElement eachResult : linkElements) {
if (eachResult.getAttribute("href").contains(getSiteName)) {
eachResult.click();
flag = true;
break;
}
}
if (!flag) {
driver.findElement(By.xpath("//a[#id='pnnext']/span[1]"))
.click();
pageNumber++;
linkElements.clear(); // celean list
wait.until(ExpectedConditions
.textToBePresentInElementLocated(
By.xpath("//td[#class='cur']"), pageNumber
+ "")); // Checking whether page number is changed as expected.
}
}// end while loop
EDIT:
List<WebElement> linkElements = new ArrayList<WebElement>();
ListIterator<WebElement> itr = null;
System.setProperty("webdriver.chrome.driver",
"webdrivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize(); // Maximize window
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.get("http://google.com");
WebElement element1 = driver.findElement(By.name("q"));
WebElement toClick = null;
element1.sendKeys(getText);
element1.submit();
// try{
int pageNumber = 1;
WebDriverWait wait = new WebDriverWait(driver, 10);
boolean flag = false;
while (!flag) {
linkElements = wait.until(ExpectedConditions
.presenceOfAllElementsLocatedBy(By
.xpath("//h3[#class='r']/a")));
itr = linkElements.listIterator(); // re-initializing iterator
while (itr.hasNext()) {
toClick = itr.next();
if (toClick.getAttribute("href").contains(getSiteName)) {
toClick.click();
flag = true;
break;
}
}
if (!flag) {
driver.findElement(By.xpath("//a[#id='pnnext']/span[1]"))
.click();
pageNumber++;
linkElements.clear(); // clean list
wait.until(ExpectedConditions.textToBePresentInElementLocated(
By.xpath("//td[#class='cur']"), pageNumber + ""));
}
}
driver.quit(); // clear memory
}
It looks like you're moving to the next page every time ANY of the WebElements in linkElements isn't what you're looking for. This will cause problems, as you need to relocate any elements that are re-rendered.
Give this a shot:
boolean found = false;
int page_number = 1; //If you need this as a string, you can make it one later
while(! found){
//get all the search results
List<WebElement> linkElements = driver.findElements(By.xpath("//h3[#class='r']/a"));
for(WebElement result: linkElements){
if(result.getAttribute("href").equals(getSiteName))
{
result.click();
found=true;
break;
}
}//End of foreach-loop
if(!found){
driver.findElement(By.xpath("//a[#id='pnnext']/span")).click();
page_number++;
}
}//End of while-loop
Also, you'll want to have some element-finding protection. Say that you search for something that has 0 results, or only one page of them (rare though that is). In the first case, you're lucky, because driver.findElements() should just return an empty list rather than throwing some exception, and the foreach loop just won't run, but in both cases, there won't be the anchor #pnnext, which will cause driver.findElement to throw an exception when you search for it. There are several ways to protect against this, such as writing a small wrapper function (IIRC, they have a simple implementation for findelementwithtimeoutwait() written on the Selenium website somewhere). I suggest you pick/write one and start using it, instead of the raw Selenium functions.

Categories

Resources