How to get that total count of xpath results on a page?

I want to get the total of the xpath result just like the the image above.
I want to store it on a list webelement
Can anybody help me?

This is the general case where the elements you want to count are present in the main document.

String js = "return document.querySelectorAll('.gh_rgt')"
int total_count = (int) WebUI.executeJavaScript(js, null)
println("The count is: " + total_count.toString())

This is the specific case you’re asking about where the elements you want to count are inside an HTML <iframe>

String js = "return document.querySelector('#myframe').contentDocument.querySelectorAll('.gh_rgt')"
int total_count = (int) WebUI.executeJavaScript(js, null)
println("The count is: " + total_count.toString())

I don’t know what that is.

1 Like

Similar to your other question about this, how about the below?

import org.openqa.selenium.By as By
import org.openqa.selenium.Keys as Keys
import org.openqa.selenium.WebDriver as WebDriver
import org.openqa.selenium.WebElement as WebElement

import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.testobject.ConditionType as ConditionType
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

// take care of <iframe>
xpath = 'id("myFrame")'
TestObject tObj = new TestObject(xpath )
tObj.addProperty("xpath", ConditionType.EQUALS, xpath )

WebUI.switchToFrame(tObj, 10)

//List<WebElement> list2 = DriverFactory.getWebDriver().findElements(By.xpath('//div[@class="gh_rgt"]'))
xpath =  '//div[@class="gh_rgt"]'
tobj = new TestObject(xpath)
tobj.addProperty("xpath", ConditionType.EQUALS, xpath)

List<WebElement> list2 = WebUI.findWebElements(tobj, 10)

WebUI.comment("Count of items is ${list2.size().toString()}")

You’re using the same TestObject for the iframe container (to switch to it), and then for the actual WebElements? This is a code smell.

Also, how’s come we don’t use the commented-out code? Does it not work in case of <iframe>? I genuinely do not know.

I am not sure what are you ‘smelling’.
If you are referring to the occurrences of:
tobj = new TestObject(xpath)

It is not the same object.
It is the same variable, first time it assigns the value of (points to) a new testobject with a given xpath, 2nd time it gets the value of (points to) another new test object with a different xpath.

Once the frame is switched, I suppose the first testobject is no longer needed. Since nothing points to this object now, will make it available for the garbage collector to release it from memory.
So it make sense to reuse the variable. At least for me …

…and THAT is the problem! That is code smell. They are mixing concerns over the same variable, making their code harder to read (and maintain) when they don’t need to.

They could simply do:

// take care of <iframe>
WebUI.switchToFrame(new TestObject("Your Page/List View Container/iframe element")
	.addProperty("xpath", 
		ConditionType.EQUALS, 
		"id('myFrame')"), 
	10)

final TestObject elements = new TestObject("Your Page/List View Container/Detail elements")
	.addProperty("xpath", 
		ConditionType.EQUALS, 
		"//div[@class='gh_rgt']")

List<WebElement> list2 = WebUI.findWebElements(elements, 10)

WebUI.comment("Count of items is ${list2.size().toString()}")

NOTE: TestObject.addProperty() adds properties to the TestObject and returns the TestObject!

This is already WAAAY better to maintain! Even better if they used the Object Repository feature, or created a Page Object keyword for the page itself, and hit the methods on it at test case runtime.

Also, the garbage collector thing is a copout. Variables are NOT some limited resource we have to maintain. Yes, good code involves few of them, but it shouldn’t come at expense of readability/maintainability.

Well, yeah, with this I agree, for this case the variable is not needed at all :slight_smile:
It will just create an unnecessary pointer, which stays in memory until the thread ends his scope, pointing to the last object assigned, even if that is no longer needed.

1 Like

Hi may I know what is this for?
(“Your Page/List View Container/iframe element”)
(“Your Page/List View Container/Detail elements”)

Where can I find those?

Oh, those are suggested names, for the test objects in your Object Repository, for :

  • your <iframe> and
  • your detail elements that you wish to count

respectively. Replace those with whatever you name them in your project!

When you create TestObjects programmatically, using that TestObject constructor, you can name them programmatically (their names will show up in the test logs, and more importantly, in case of Error on them). The name is what you pass into the TestObject constructor!