findElement not working as expected in for-each loop - java

I'm completely stuck and have no idea why I'm getting the output that I am. Here's the relevant snippet.
WebElement section = driver.findElement(By.xpath("//div[contains(#class,'_main')]"));
List<WebElement> searchResults = new ArrayList<WebElement>();
searchResults.addAll(section.findElements(By.xpath("//div[contains(#class,'_listing')]")));
for (WebElement element : searchResults) {
System.out.println(element.getAttribute("innerHTML"));
System.out.println(element.findElement(By.xpath("//p[contains(#class,'_2tux')]")).getText());
currentlistings.add(newListing('f',element.findElement(By.xpath("//a[contains(#class,'_1oem')]")).getAttribute("href"),
element.findElement(By.xpath("//p[contains(#class,'_2tux')]")).getText(),
element.findElement(By.xpath("//div[contains(#class,'_f3l _4x3g')]")).getText()));
}
The code seemingly functions fine when storing elements to the list, the size is correct and when I iterate through the list elements innerHTML outputs as expected.
However when I then try and use findElement on each of the iterated elements, it seemingly reads the HTML from the element at index 0, even though the command immediately prior outputs the html from the correct index. Any pointers would be much appreciated.

You need to use .//.
element.findElement(By.xpath(".//p[contains(#class,'_2tux')]")).getText(),
element.findElement(By.xpath(".//div[contains(#class,'_f3l _4x3g')]")).getText()));

Related

How to count HTML Tags if I have dynamic changes in these tags?

I want to count some tags in this page Link
I am trying to count the tags of opening positions so, I tried this code
using java to count but I always find my count is = 0;
public By cardsNumOfPositions = By.xpath("//div[#class='card']");
List<WebElement> element = driver.findElements(cardsNumOfPositions);
int countelements = element.size();
And I write this function to count:-
public void printCountElements() {
System.out.println(countelements);
}
Everytime the count is 0, I searched for an Iframe but I didn't find any.
so how can I get the size of this element?
Also, you can make countelements as a static variable.
like this:
static int countelements;
now since it's static, its value will persist. You can call it like this:
public void printCountElements() {
countelements = element.size();
System.out.println(countelements);
}
Looking at the code, it doesn't look like there's anything wrong with it if what you're trying to achieve is to count the number of elements on the page matching that xpath.
The xpath also looks good, and I've tested it and it works. I can see that iframes exist on the page, but it doesn't look like these elements are within those iframes, so it doesn't look like stepping into an iframe would be required.
Are there sufficient waits in place, to make sure these elements are fully loaded before we're trying to find them? I'm worried that we're trying to put these elements into a list before they've loaded.
Failing that, what I'd check next is run the same test, but this time using the parents (or parents parents) of this element, and follow it up the chain to see if we can get any hits whilst running the code.

Iterate through each element in java to see if it's displayed

I am new to Java and would like assistance on the best way to perform the following:
I wanted to grab all of the elements that belongs to a class but I want to perform a count on how many of these elements are displayed. I have set up the code to create an int counter, the findelements and the assertion but basically my question is how in java do you create a for loop to simply check if an element within the elements list is displayed, then +1 on the count?
int testNumber = 0;
List<WebElement> testItems = _driver.findElements(By.className("test"));
//Loop each element from the list and if it's displayed then +1 for test Number
Assert.assertEquals(testNumber, 4,
"Mismatch between the number of test items displayed");
Use the method WebElement#isDisplayed (documentation) to get the status of an element.
All you need to do is to setup a counter like int counter = 0. Then create a loop over all elements like for (WebElement e : testItems) { ... }. Then, inside the loop, create some sort of if (e.isDisplayed()) { ... }. And inside this you increase the counter like counter++. All in all:
int counter = 0;
for (WebElement e : testItems) {
if (e.isDisplayed()) {
counter++;
}
}
This variant uses the enhanced for-loop. You can of course use other loop variants too.
Using streams this could be made a compact one-liner like
int count = testItems.stream()
.filter(WebElement::isDisplayed)
.count();
Note that WebElements can, depending on the website, quickly stale if they aren't processed quickly after their generation. This is indicated by them throwing a StaleElementReferenceException. It happens whenever the website rebuilds itself (completely or partially), your element was then retrieved from an old state of the website and is thus invalid.
If you experience this, you may directly collect the display status of an element before finding the other elements. This decreases the time between generation and access of a single WebElement.

arraylist size less than real

I was using webdriver to grab web elements with class name topredo into ArrayList.
Seeing that the web elements is increasing when screen scrolls, i use while loop to do scroll and grab.
Java code like this:
outer: while (isContinue) {
List<WebElement> all = driver.findElements(By.className("torpedo"));
/* do screen scrolling*/
}
It runs well until the last loop.
In last secode loop, i get the all.size() result 208, but in the last loop, the all.size() result is 172 while the real total size of web elements on browser is 243,and i use eclipse debug to see the list stack content.
Screenshots like this:
all.size()
content end on index 171
So my question is why all.size() less than the real size, and why the contents on index greater than 171 are unvisiable?
Thanks a lot!
As mentioned in the comment, you keeps on resetting your list for every iteration of the loop. We can initiate the List outside the loop and keep om adding elements to the list inside the loop. The code should look something like this.
List<WebElement> all = null;
outer: while (isContinue)
{
all.addAll(driver.findElements(By.className("torpedo")));
/* do screen scrolling*/
}
You can also use a set instead of list if you get duplicate elements in the list.
Set<WebElement> all = null;
outer: while (isContinue)
{
all.addAll(driver.findElements(By.className("torpedo")));
/* do screen scrolling*/
}

select odd/even elements of array using recursion

Am working on some programming homework and am a bit lost. The project is to select the even/odd elements of a listarray and store in another array. It is not the even numbers in each element, but the elements themselves so if an array had values "1,2,5,7,9" and returned the even elements it would give "1, 5, 9". Also have to use recursion. Would anyone be able to give me a starting point or some advice. Though about starting with 2 elements and taking 2nd element and then building up from that, but don't know how it would add on the 2nd pass
public static ArrayList<Integer> even(ArrayList<Integer> list)
ArrayList<Integer> evenlist = ListMethods.deepClone(tList);//make copy of list
if (evenlist.size()<=1) // The list is empty or has one element
{
// return null;// Return the list as is
}
if
(evenlist.size()==2)
{
//return right element
//call method again
//add to list
}
Psuedocode
int[] evens,odds;
function categorize(List<Integer> in,int idx)
if(idx>=in.length)
return
int cur = in[idx]
if(even), add to evens
else add to odds
categorize(in,idx+1)
This sounds similar to the homework I just completed, so if it is (And you're in my class!), I'll not tell you to use any terminology we haven't covered as I know it can be daunting trying to discover something new for practicals (beyond what we have to do).
First, set your exit condition. As you've already said, you have to create a new ArrayList out of the existing one. You are going to remove items from the existing ArrayList, storing the integers that are at even (or odd) indices, until the list is empty.
So your exit condition is:
if (evenList is Empty)
return evenList;
Then, work your way through the steps. I would advise determining if the Array you start with has an even of odd number of steps, something like this:
if (evenList has Even Elements)
int holderForIntsAtEvenElements = last evenList EVEN element
Note we start at the last element, so when you are coming OUT of the recursive method, this will be the last one added to your new ArrayList, and thus it'll be in numerical order. You might find this post interesting to do this: What does this boolean return mean?
We then want to remove the last element from the list and recursively call the method again.
Finally, when we hit our exit condition and start to come out, we want to add the ints we've been storing to them, e.g.:
evenList.add(holderForIntsAtEvenElements);
return evenList;
That doesn't solve one problem, which is what to do with the very first element if the list does NOT have an even number of elements - however, I'll let you try and solve that!
That's a good mix of code and pseudo code and will hopefully help to get you on the right track.
You could use a simple for loop like this:
for (int i = 0; i < list.size(); i += 2) {
System.out.println(list.get(i));
}
If you have to use recursion, here's an outline of the steps you might take. (I won't tell you exactly what to do because you haven't tried anything and it is like homework.)
Take first element and store it
Remove (new) first element from list
Call self

How does java's iterator.remove() translate to python?

I have a python set that I need to iterate over, and for each element, check if it satisfies a constraint, and if so, remove it and add it to a different, possibly already nonempty set. I could just add it to a buffer and then, after the loop is complete, iterate through the buffer and remove its contents from the set, but there must be a better way to do this.
Here is what I'm trying to do:
for elem in S:
if (P(elem)):
S.remove(elem)
T.add(elem)
This doesn't work.
Here's the fix that would work but is unclean:
B = set()
for elem in S:
if (P(elem)):
B.add(elem)
T.add(elem)
for elem in B:
S.remove(elem)
EDIT:
The best solution seems to be:
for elem in S.copy():
if (P(elem)):
S.remove(elem)
T.add(elem)
For a list, create a copy before iterating:
for elem in S[:]:
where the [:] slice notation creates a copy of the full list. You cannot otherwise remove elements from a list while iterating over it.
One option is to use a list comprehension to create T and then remove all elements in T from S.
T = set([elem for elem in S if P(elem)])
S = S - T
If iterating over the list twice and calling P() twice for each item is not an issue this would be the most readable solution::
T = [x for x in S if P(elem)]
S = [x for x in S if not P(elem)]

Categories