Trying to click each element in the list - java

#Test
public void homework() throws InterruptedException {
driver.get("http://www.localhost/litecart/admin/");
driver.findElement(By.cssSelector("td [name = username]")).sendKeys("admin");
driver.findElement(By.cssSelector("td [name = password]")).sendKeys("admin");
driver.findElement(By.cssSelector("div.footer [name = login]")).click();
List<WebElement> elements = driver.findElements(By.cssSelector("ul#box-apps-menu > li"));
for (WebElement we : elements) {
we.click();
}
}
This is my code. elements i want to click
I only click the first item and then i get this "stale element reference: element is not attached to the page document".
Once you click on a list item, it expands and few more child list-items appear, so idk if that's what's causing the issue.
EDIT:
Here's how i did it, i included even child elements. Thanks to the comments below i managed to finally complete this task.
public class HomeWork1 extends TestBase {
#Test
public void homework() throws InterruptedException {
driver.get("http://www.localhost/litecart/admin/");
driver.findElement(By.cssSelector("td [name = username]")).sendKeys("admin");
driver.findElement(By.cssSelector("td [name = password]")).sendKeys("admin");
driver.findElement(By.cssSelector("div.footer [name = login]")).click();
List<WebElement> elements = driver.findElements(By.xpath(("//ul//li")));
for (int i = 1; i <= elements.size(); i++) {
driver.findElement(By.xpath("//ul[#id='box-apps-menu']/li["+i+"]")).click();
List<WebElement> element = driver.findElements(By.xpath("//ul[#class='docs']/li"));
for (int j = 1; j < element.size() + 1; j++){
driver.findElement(By.xpath("//ul[#class='docs']//li["+j+"]")).click();
}
if (i == 17) break;
}
}
}

or Try this
#Test
public void homework() throws InterruptedException {
driver.get("http://www.localhost/litecart/admin/");
driver.findElement(By.cssSelector("td [name = username]")).sendKeys("admin");
driver.findElement(By.cssSelector("td [name = password]")).sendKeys("admin");
driver.findElement(By.cssSelector("div.footer [name = login]")).click();
List<WebElement> elements = driver.findElements(By.xpath("//ul//li"));
// elements.size() will give you the total number of elements.
for (i=1;i<=elements.size(),i++) {// This will iterate through all the elements
driver.findElement(By.xpath("//ul/li["+i+"]")).click(); // clicking on each li element one by one
//include wait here
}
}
Yes, you can apply the same logic if you want to work with child items. For example you can use following for first parent item:
List<WebElement> elements = driver.findElements(By.xpath("//ul/li[1]/**")); // ** can be replaced by child identifiers

Related

merge two WebElements list

cannot print values from the merged lists as it is throwing me null!
List<WebElement> DateTime2 = driver.findElements(By.xpath(""));
driver.findElement(By.xpath("")).click();
List<WebElement> DateTime3 = driver.findElements(By.xpath(""));
List<WebElement> DateTime = new ArrayList<>(DateTime2);
DateTime.addAll(DateTime3);
Thread.sleep(2000);
System.out.println("This is for testing the list " +
DateTime.get(2).getText());
System.out.println("This is for testing the list " +
DateTime.get(30).getText());
i expect output to be printed date and time
Here's an example of some code I use (though I changed it a bit for this example. This is usually a part of a class that extends another.)
int sanitycount= 0;
int ec_Timeout = 10; //seconds to wait for list...
public void RunAction(WebDriver driver, String in_xpath)
{
try
{
wait = new WebDriverWait(driver, ec_Timeout);
List<WebElement> found_elements = new ArrayList<>();
found_elements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(in_xpath)));
if (!found_elements.isEmpty())
{
// store this array, return an array from function
// or loop through array and add items to more global array..
}
}
catch (Exception e)
{
if (e.getClass().getCanonicalName().equals("org.openqa.selenium.StaleElementReferenceException"))
{
//need to do it again, not finished loading
System.out.println("*****************Stale caught-redoing");
sanitycount++;
if (sanitycount<ec_Timeout * 2)
{
RunAction(driver, in_xpath);
}
System.out.println (e.toString());
}
else
{
System.out.println (e.toString());
}
}
}
RunAction(your_driver, your_xpath);
//set sanitycount back to zero if you run again...

Putting Jsoup abs:href results into an array and looping through the array

I am having some trouble understanding how to properly add to an array. What I am trying to accomplish is adding the results from the a method into an array and then run through the array.
Here is an example of what I need, or assume I need:
array{"websiteaddress","websiteaddress","websiteaddress","websiteaddress","websiteaddress"}
but instead I'm getting:
websiteaddress
websiteaddress
websiteaddress
websiteaddress
websiteaddress
websiteaddress
Here is the code I am working with:
private static final String webSiteURL = "https://websitename.com/";
//The path of the folder that you want to save the images to
private static final String folderPath = "C://path/";
private static final ArrayList<String> webPages = new ArrayList<>();
public static String[] thisIsAStringArray = {"https://websitename.com/"};
public static String[] tempArray = new String[ thisIsAStringArray.length + 1 ];
/**
*
* Method description:
* Date: Mar 17, 2018
* #param args
* #return void
*/
public static void main(String[] args) {
String path = folderPath + getPageTitle(webSiteURL).replaceAll(" ", "-");
pageLinks(webSiteURL);
System.out.println(thisIsAStringArray);
for(String web : thisIsAStringArray)
{
for(int n = 0; n < thisIsAStringArray.length - 1; n++)
{
System.out.println(thisIsAStringArray[n]);
getPageTitle(web);
pageLinks(web);
creatDirectory(folderPath, getPageTitle(web));
getsImagesAndSaves(path, web);
n++;
}
}
}
/**
*
* Method description: Get all the links on the page and put them into an array
* Date: Mar 16, 2018
* #param src
* #return void
*/
public static void pageLinks(String src)
{
try
{
URL url = new URL(src);
Document doc = Jsoup.parse(url, 3*1000);
Elements links = doc.select("a[href]"); // a with href
for (Element link : links)
{
System.out.println(link.attr("abs:href"));
String noHref = link.attr("abs:href");
for(int i = 0; i < thisIsAStringArray.length; i++)
{
tempArray[i] = thisIsAStringArray[i];
}
//thisIsAStringArray[i] = noHref;
tempArray[thisIsAStringArray.length] = noHref;
}
thisIsAStringArray = tempArray;
}
catch(Exception error)
{
System.out.println(error + " Something went wrong getting the links!");
}
}
}
Any help would be greatly appreciated and thank you in advance!
You have 2 arrays: thisIsAStringArray with size 1 and tempArray with size 2. Their size is fixed and cannot be changed! Now you have a loop:
for (Element link : links)
{
...
for(int i = 0; i < thisIsAStringArray.length; i++)
{
tempArray[i] = thisIsAStringArray[i];
}
}
which reads - for each link you've found, i loops from zero to one (which means that inside the inner loop i will have only the value 0) and than adds the link to the first place (with index 0).
You cannot change the size of an array in runtime. If you cannot tell ahead how many items you will have, you must use a List. Try something like this:
ArrayList<String> myList = new ArrayList<>();
for (Element link : links)
myList.add(link);

Java Selenium why click function doesn't works?

Why click() doesn't works?
website:
String startPage = "http://www.domiporta.pl/mieszkanie/sprzedam?Localization=dolno%C5%9Bl%C4%85skie&PageNumber=24&SortingOrder=InsertionDate";
Code:
List<WebElement> RowsMain = driver.findElements(By.className("detail-card__heading"));
for(int i=0;i<RowsMain.size();i++){
driver.get(startPage);
List<WebElement> rows = driver.findElements(By.className("detail-card__heading"));
List<WebElement> cols=new ArrayList<WebElement>();
cols=rows.get(i).findElements(By.tagName("div"));
for(WebElement col:cols) {
col.click();
}
}
Why click doesn't workS?
It is error because you navigate out of the current page, so DOM has been destroyed. The solution is simple, find the elements every time when you navigate out of the page. See code below.
int rowCount = driver.findElements(By.className("detail-card__heading")).size();
for(int i=0; i<rowCount; i++){
List<WebElement> rows = driver.findElements(By.className("detail-card__heading"));
int colsCount = rows.get(i).findElements(By.tagName("div")).size();
for(int j=0;j<colsCount; j++) {
rows = driver.findElements(By.className("detail-card__heading"));
List<WebElement>cols = rows.get(i).findElements(By.tagName("div"));
cols.get(j).click();
driver.get(startPage);
}
}

How to find the Empty city dropdown in the below image?

Functionality: We have three fields Country, State, City -
After select the Country it reveal the States list and after select the state it reveal the city list.
Question: In this some states don't have cities, so how find country, states list those not have cities list using selenium?
i tried the code below like this but loop is not working & not shows the empty list
#Test
public void findstate() throws InterruptedException {
WebDriver driver = new FirefoxDriver();
driver.get("URL");
Select country = new Select(driver.findElement(By.xpath("//*[#id='UserProfileCountryId']")));
List<WebElement> countrylist = country.getOptions();
System.out.println(countrylist.size());
for (int i = 1; i <= countrylist.size(); i++) {
countrylist.get(i).click();
Select state = new Select(driver.findElement(By.xpath("//*[#id='UserProfileStateId']")));
List<WebElement> statelist = state.getOptions();
for (int j = 1; j <= statelist.size(); j++) {
statelist.get(j).click();
Select city = new Select(driver.findElement(By.xpath("//*[#id='UserProfileCityId']")));
List<WebElement> citylist = city.getOptions();
System.out.println("Country, state list of Empty Cities");
if (citylist.size() > 1) {
System.out.println(countrylist.get(i).getText() + "-----" + statelist.get(j).getText() + "-----");
}
}
}
}
Source Code for Country, State, City:
<span class="select-wrapper"><select name="data[UserProfile][country_id]" class="custom-select valid" id="UserProfileCountryId" aria-invalid="false" aria-required="true">
<option value="">Country</option>
<option value="1">Afghanistan</option>
<option value="2">Albania</option>
</select><span class="holder">Afghanistan</span></span>
<select name="data[UserProfile][state_id]" class="custom-select valid" id="UserProfileStateId" aria-invalid="false" aria-required="true">
<option value="">State</option>
<option value="42">Badakhshan</option>
<option value="43">Badgis</option>
<option value="44">Baglan</option>
</select>
<select name="data[UserProfile][city_id]" class="custom-select valid" id="UserProfileCityId" aria-invalid="false" aria-required="true">
<option value="">City</option>
<option value="5916">Andarab</option>
<option value="5917">Baghlan</option>
</select>
You have some typos due to copy&paste I think.
You need to use the correct Select variables in your loops, but you always use country.
Try this:
#Test
public void findstate() throws InterruptedException {
WebDriver driver = new FirefoxDriver();
driver.get("URL");
Select country = new Select(driver.findElement(By.xpath("//*[#id='UserProfileCountryId']")));
List<WebElement> countrylist = country.getOptions();
System.out.println(countrylist.size());
for (int i = 1; i <= countrylist.size(); i++) {
countrylist.get(i).click();
Select state = new Select(driver.findElement(By.xpath("//*[#id='UserProfileStateId']")));
List<WebElement> statelist = state.getOptions();
for (int j = 1; j <= statelist.size(); j++) {
statelist.get(j).click();
Select city = new Select(driver.findElement(By.xpath("//*[#id='UserProfileCityId']")));
List<WebElement> citylist = city.getOptions();
System.out.println("Country, state list of Empty Cities");
if (citylist.size() > 1) {
System.out.println(countrylist.get(i).getText() + "-----" + statelist.get(j).getText() + "-----");
}
}
}
}
To avoid this error it might be better to use foreach loops like this:
for (WebElement element : country.getOptions()) { }
I don't know your HTML code, but it might also be necessary to wait for the other dropdowns to fill with elements before asking getOptions(). Selenium is very very fast and it might ask for the options of the dropdown before they are loaded by your site. In this case you will not get any results even using the updated code.
Try to wait for the dropdowns to fill like this every time:
Select country = new Select(driver.findElement(By.xpath("//*[#id='UserProfileCountryId']")));
List<WebElement> countrylist = country.getOptions();
System.out.println(countrylist.size());
for (WebElement element : countrylist) {
element.click();
Select state = new Select(driver.findElement(By.xpath("//*[#id='UserProfileStateId']")));
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver webdriver) {
return state.getOptions() > 1;
}
});
List<WebElement> statelist = state.getOptions();
....
You do the same for city-options -> if you run into a timeout you found the state that has no cities...
Hi please try like below
#Test
public void findstate() throws InterruptedException {
WebDriver driver = new FirefoxDriver();
driver.get("URL");
WebDriverWait wait = new WebDriverWait(driver,20);
Select country = new Select(driver.findElement(By.xpath("//*[#id='UserProfileCountryId']")));
List<WebElement> countrylist = country.getOptions();
System.out.println(countrylist.size());
for (int i = 0; i <= countrylist.size(); i++) {
countrylist.get(i).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='UserProfileStateId']")));
Select state = new Select(driver.findElement(By.xpath("//*[#id='UserProfileStateId']")));
// here use state not country
List<WebElement> statelist = state.getOptions();
for (int j = 0; j <= statelist.size(); j++) {
statelist.get(j).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='UserProfileCityId']")));
Select city = new Select(driver.findElement(By.xpath("//*[#id='UserProfileCityId']")));
// here use city not country
List<WebElement> citylist = city.getOptions();
for (int k = 0; k <= citylist.size(); k++) {
citylist.get(k).click();
System.out.println("Country, state list of Empty Cities");
if (citylist.get(k).getText() == null) {
System.out.println(countrylist.get(i).getText() + "-----" + statelist.get(j).getText() + "-----"+ citylist.get(k).getText());
}
}
}
}
}
In the outermost loop select country and then in an inner loop select each state for that country and check if city is found. If not then get the city & country & go on this way.
I think, it helps you.
its worked fine, add the 'tab' key after select the country
driver.findElement(By.xpath("//*#id='UserProfileCountryId']")).sendKeys(Keys.TAB);
But I got another problem while executing, After some time run the script i got error
org.openqa.selenium.StaleElementReferenceException: Element is no longer attached to the DOM
Command duration or timeout: 31 milliseconds
Thanks for answers

java and xml, use of Element

i'm a beginner in java and XML , but I have a task to perform and I don't know how to use a recursive function which uses Element.
I made this program.
public class JDOM2
{
private static final String xmlroutes = "C://Users//Thomas//Desktop//routes.xml";
static Element root;
public static void main(String[] args) throws JDOMException, IOException
{
// the SAXBuilder is the easiest way to create the JDOM2 objects.
SAXBuilder jdomBuilder = new SAXBuilder();
// jdomDocument is the JDOM2 Object
Document jdomDocument = jdomBuilder.build(xmlroutes);
root = jdomDocument.getRootElement();
List <Element> location_properties = root.getChildren("LOCATION_PROPERTIES");
Iterator<Element> it = location_properties.iterator();
Element loc = it.next();
rootiteration();
}
public static void rootiteration()
{
int time;
List <Element> location_properties = root.getChildren("LOCATION_PROPERTIES");
Iterator<Element> it = location_properties.iterator();
Element loc = it.next();
if(loc.getAttributeValue("NAME").startsWith("STN")== true)
{
List <Element> segment_properties = loc.getChildren("SEGMENT_PROPERTIES");
Iterator<Element> it2 = segment_properties.iterator();
Element seg = it2.next();
List <Element> next_location = seg.getChildren("NEXT_LOCATION");
for (Element next: next_location)
{
if(next.getAttributeValue("NAME").startsWith("STN")== true)
{
System.out.print("Arrival : " +next.getAttributeValue("NAME"));
int L = Integer.parseInt(next.getAttributeValue("LENGTH"));
int S = Integer.parseInt(next.getAttributeValue("SPEED"));
time = L/S;
System.out.println(" --- Time to go : "+time+" seconds");
}
if(next.getAttributeValue("NAME").startsWith("STN")== false)
{
recursive(); // I think the problem is here but I may have done some other mistakes.
}
}
}
}
public static int recursive(Element parent, int t0, Element child) throws IOException
{
List <Element> location_properties = root.getChildren("LOCATION_PROPERTIES");
Iterator <Element> i = location_properties.iterator();
int t1 = 0;
while (i.hasNext())
{
child = (Element) i.next();
int L = Integer.parseInt(child.getChild("SEGMENT_PROPERTIES").getChild("NEXT_LOCATION").getAttributeValue("LENGTH"));
int S = Integer.parseInt(child.getChild("SEGMENT_PROPERTIES").getChild("NEXT_LOCATION").getAttributeValue("SPEED"));
t1 = L/S;
//t1 = time_between();
if (child.getAttributeValue("NAME").startsWith("STN")== true)
{
System.out.println("From : "+parent+" to "+child+" --- Time to go : "+t1+" seconds");
System.out.println(child.getAttributeValue("NAME"));
System.out.println(parent);
}
if (child.getAttributeValue("NAME").startsWith("X")== true) // child is not STN, recurse
{
recursive(parent, t0 + t1,child);
System.out.println("From : "+parent+" to "+child+" --- Time to go : "+t1+" seconds");
// t0 = t0 + t1;
}
}
return t0;
}
This is supposed to calculate the time between 2 Elements. King of this way :
I need two functions, one which iterates over all root elements, and starts the tree traversal at a starting STN, and a recursive function that traverse the tree until it finds an ending STN.
To have something like that :
Departure Station : STN10
Arrival : X535 --- Time to go : 16 seconds
Arrival : X536 --- Time to go : 2 seconds
Arrival : X537 --- ...
Arrival : STN26 --- Total time to Station : ...
Departure Station : STN11
Arrival : X535 ---
...And so on.
I think you can change the second method as follows and it would work:
public static int recursive(Element root, int t0, Element current) throws IOException
{
List <Element> location_properties = current.getChildren("LOCATION_PROPERTIES");
Iterator <Element> i = location_properties.iterator();
int t1 = 0;
while (i.hasNext())
{
child = (Element) i.next();
int L = Integer.parseInt(child.getChild("SEGMENT_PROPERTIES").getChild("NEXT_LOCATION").getAttributeValue("LENGTH"));
int S = Integer.parseInt(child.getChild("SEGMENT_PROPERTIES").getChild("NEXT_LOCATION").getAttributeValue("SPEED"));
t1 = L/S;
//t1 = time_between();
if (child.getAttributeValue("NAME").startsWith("STN")== true)
{
System.out.println("From : "+root+" to "+child+" --- Time to go : "+t1+" seconds");
System.out.println(child.getAttributeValue("NAME"));
}
if (child.getAttributeValue("NAME").startsWith("X")== true) // child is not STN, recurse
{
recursive(root, t0 + t1, child);
}
}
return t0;
}
Everytime a non-STN element is encountered the child element will be passed to the recursive method as the current element.
You will have to call this method using the root element as the root parameter and the same element as the current parameter. i.e., recursive(root, 0, root).
Please note that I could not test this as the xml file is not accessible to me. Hope this helps.
For those who can be interested, I used this function to re-use the string "next.getAttributeValue("NAME")" as an element.
public static Element getElembyName(final String name){
List <Element> location_properties = root.getChildren("LOCATION_PROPERTIES");
for (Element loc : location_properties)
{
if(loc.getAttributeValue("NAME").equals(name))
return loc;
}
return null;
}

Categories

Resources