Select items from 3 dropdowns with dependency of first one - java

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

Related

SELENIUM & JAVA - Ecommerce Application - Unable to remove product from the cart page

With the below code, I am able to remove only the first product from the cart page but not all the products
public class RemoveProductFromCart {
public static void main(String[] args) throws Exception {
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://askomdch.com/account/");
driver.findElement(By.id("username")).sendKeys("testuser1");
driver.findElement(By.id("password")).sendKeys("Password#123");
driver.findElement(By.xpath("//button[#type='submit' and #name='login']")).click();
Thread.sleep(2000);
Clicking on the cart icon==>
driver.findElement(By.xpath("//div[#id='ast-desktop-header']//div[#class='ast-cart-menu-wrap']")).click();
Thread.sleep(2000);
Grouped all the items to remove into a list and then click them one by one to remove all the products==>
List<WebElement> removeList = driver
.findElements(By.xpath("//table[contains(#class,'shop_table')]//a[#class='remove']"));
for (int i = 0; i < removeList.size(); i++) {
removeList.get(i).click();
Thread.sleep(2000);
if (removeList.size() == 0) {
break;
}
}
}
}
By removing the first product from the cart the remaining products are rearranged there so the remaining WebElements in the removeList list becoming stale elements.
In order to remove all the products from the cart you have to get the removeList again after each time the product is removed and validate there are still products in the cart, as following:
WebDriverWait wait = new WebDriverWait(driver, 30);
List<WebElement> removeList = driver.findElements(By.xpath("//table[contains(#class,'shop_table')]//a[#class='remove']"));
while(!removeList.isEmpty()){
removeList.get(0).click();
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("div.blockUI.blockOverlay")));
Thread.sleep(200);
removeList = driver.findElements(By.xpath("//table[contains(#class,'shop_table')]//a[#class='remove']"));
}

Getting Stale Element Reference Exception while accessing the element from a list

Below is the code which I am trying to get to work.
//Method to fetch all links from the sitemap container
public void GetAllLinks() {
WebElement pointer = LinksContainer;
String url = "";
List <WebElement> allURLs = pointer.findElements(By.tagName("a"));
System.out.println("Total links on the page: "+ allURLs.size());
for (int i=0; i<allURLs.size(); i++) {
WebElement link = allURLs.get(i);
url = link.getAttribute("href");
OpenAllLinks(url);
}
}
//Method to hit all the fetched URLs
public void OpenAllLinks(String linkURL) {
driver.get(linkURL);
}
I am fetching all the anchor elements from a sitemap page and then putting all those elements into a list. Then, I am getting the URLs from all those elements using the getAttribute(href). The code is working fine till here.
However, after that I am taking these URLs as arguments and passing into the method OpenAllLinks() to open all these URLs one by one using driver.get(). The code works till the first link but as soon as the first page is loaded, it gives me the stale element exception.
At the moment you are leaving the page where all these links are appearing all the web elements in allURLs list becoming stale elements.
What you can do is first to extract and save in a list all the links, not the web elements, and after that iterate with loop opening all these links.
Like this:
public void GetAllLinks() {
WebElement pointer = LinksContainer;
String url = "";
List <WebElement> allURLs = pointer.findElements(By.tagName("a"));
System.out.println("Total links on the page: "+ allURLs.size());
List<String>links = new ArrayList<>();
for (int i=0; i<allURLs.size(); i++) {
WebElement link = allURLs.get(i);
url = link.getAttribute("href");
links.add(url);
}
for (int i=0; i<links.size(); i++) {
OpenLink(links.get(i));
}
}
//Method to open the fetched URLs
public void OpenLink(String linkURL) {
driver.get(linkURL);
}

How to loop inside containers to select value in selenium?

I have a product page which has the sizes inside containers, i tried to list elements and get size by text but the list always returns zero, i tried the xpath of the parent and child and i get the same error, How can i list the sizes and select specific size ?
public void chooseSize(String size) {
String selectedSize;
List<WebElement> sizesList = actions.driver.findElements(By.xpath("SelectSizeLoactor"));
try {
for (int i = 0; i <= sizesList.size(); i++) {
if (sizesList.get(i).getText().toLowerCase().contains(size.toLowerCase()));
{
selectedSize = sizesList.get(i).getText();
sizesList.get(i).click();
assertTrue(selectedSize.equals(size));
}
}
} catch (Exception e) {
Assert.fail("Couldn't select size cause of " + e.getMessage());
}
It looks to me like the proper selector would be:
actions.driver.findElements(By.cssSelector(".SizeSelection-option"))
Try below options
List<WebElement> sizesList = actions.driver.findElements(By.xpath("//[#class='SelectSizeLoactor']"));
List<WebElement> sizesList = actions.driver.findElements(By.cssSelector(".SelectSizeLoactor"));
I found a quick solution i used part of the xpath with text() and passed the value of that text later then added the last of the xpath and it worked!
String SelectSizeLoactor = "//button[text()='"
public void chooseSize(String size) {
String selectedSize;
WebElement sizeLocator = actions.driver.findElement(By.xpath(SelectSizeLoactor+size.toUpperCase()+"']"));
try {
if (sizeLocator.getText().toUpperCase().contains(size.toUpperCase()));
{
selectedSize = sizeLocator.getText();
sizeLocator.click();
assertTrue(selectedSize.equals(size));
}
} catch (Exception e) {
Assert.fail("Couldn't select size cause of " + e.getMessage());
}
}

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

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
}

How to select all list options from drop downlist loop through them selcet each option and click submit button using selenium webdriver

Here is the link to print name and meaning columns of all pages using drop down
Try to build the script for following:
1. Go to http://babynames.merschat.com/index.cgi?function=Search&origin=Sanskrit&gender=f
2. print the name and meaning columns to syso.
I was able to print page 1 as it is a default page.
Here is the code:
public class BabyNamesAndMeanings {
WebDriver driver = new FirefoxDriver();
#BeforeClass
public void setUp() {
driver.get("http://babynames.merschat.com/index.cgi?function=Search&origin=Sanskrit&gender=f");
driver.manage().window().maximize();
}
#Test
public void printBabyNamesAndMeaningsOfFirstPage() {
WebElement baby_names = driver
.findElement(By
.xpath("//tbody/tr[7]/td[3]/table[2]/tbody/tr[2]/td[2]/font/table[1]/tbody"));
List<WebElement> names = baby_names.findElements(By
.xpath("//tr/td[1]/font/a"));
List<WebElement> meanings = baby_names.findElements(By
.xpath("//tr/td[4]/font/a"));
for (int i = 0; i < names.size(); i++) {
System.out.println("Name: " + names.get(i).getText()
+ " Meaning: " + meanings.get(i).getText());
}
}
I don't know how to loop through rest of the options in the drop down list at the bottom of the page and hit submit button to print name and meaning of all the pages.
There are 100+ pages.
Thanks in advance.
The code below will do your job.
driver.get("http://babynames.merschat.com/index.cgi?function=Search&origin=Sanskrit&gender=f");
List<WebElement> pageOptions = new Select(driver.findElement(By.xpath("//select[#name='page']"))).getOptions();//Get all options in dropdown
ArrayList<String> pageDd = new ArrayList<String>();
for(WebElement eachPage:pageOptions){
pageDd.add(eachPage.getText());//Save text of each option
}
int i=1;
for(String eachVal:pageDd){
new Select(driver.findElement(By.xpath("//select[#name='page']"))).selectByVisibleText(eachVal);//Select page
driver.findElement(By.xpath("//input[#value='Go']")).click();//Click on go
List<WebElement> names = driver.findElements(By.xpath("//a[contains(#title,' meanings and popularity')]"));//Get all names on page
for(WebElement eachName:names){
String name = eachName.getText(); //Get each name's text
WebElement mean = eachName.findElement(By.xpath("./../../..//a[contains(#title,'Names for baby with meanings like ')]"));//Get meaning for that name
String meaning = mean.getText();//Get text of meaning
System.out.println(i+") Name: " +name+ " Meaning: " + meaning);//Print the data
i++;
}
}
Try and understand the way requirement is achieved. If you have any doubt ask.
Another method to iterate and select all the Dropdown values
Select dropdown= new Select(WebUIDriver.webDr.findElement(By.xpath("enter xpath")));
int noOfDropDownValues= dropdown.getOptions().size()-1;
for(int i=0;i<noOfDropDownValues;i++){
new Select(WebUIDriver.webDr.findElement(By.xpath("Enter Xpath']"))).selectByValue(String.valueOf(i));
}

Categories

Resources