How to find the total number of rows in a nested table using xpath?

Yes. It clicks on a search icon and then an iframe opens up containing a table.

WebUI.click(findTestObject('Object Repository/Create Event/SearchReportedBy'))

WebUI.delay(3)

if (WebUI.switchToFrame(findTestObject('Object Repository/Reported By/iFrame_ReportedBy'), 5, FailureHandling.OPTIONAL)) {
	println (" switchToFrame is true ")
	}
	else {
	println (" switchToFrame is false")
}

//Click on alphabet B 
WebUI.click(findTestObject('Object Repository/Reported By/Filter'))

WebDriver driver = DriverFactory.getWebDriver()
WebUI.verifyElementPresent(byXPath("//table[@id='mlist']"), 10)
List<WebElement> tableRows = WebUI.findWebElements(byXPath("//table[@id='mlist']/tbody/tr"), 10)
assert tableRows != null
WebUI.comment("number of rows of <table id='mlist'> : " + tableRows.size())

TestObject byXPath(String xpath) {
	TestObject tObj = new TestObject(xpath)
	tObj.addProperty("xpath", ConditionType.EQUALS, xpath)
	return tObj
}

for (def rowIndex=1; rowIndex<=15; rowIndex++) {

def myCell = driver.findElement(By.xpath('//*[@id="mlist"]/tbody/tr[${rowIndex}]/td[3]/div/span'))
	def theName = myCell.getText()
	println theName

	if (theName.equals("I")) {
		String AppText=WebUI.getText(findTestObject('Object Repository/Reported By/ApplicationAccount2'))
		println (AppText)
		break
	}
else {
	println ("Name is not in the first page")
	}
}

Please note that it cannot click on alphabet B for the time being. Another issue. Now, I am just running the script at the start of the for loop.

Just a bit of an explanation. The “byXPath” in your code above is a method that allows you to create a Test Object by supplying an xpath, so we don’t need the “driver” reference. How about the below:

for (def rowIndex=1; rowIndex<=15; rowIndex++) {

   def myCell = byXPath("//*[@id='mlist']/tbody/tr[${rowIndex}]/td[3]/div/span")
   def theName = WebUI.getText(myCell)
   println theName

Oh I understand. You mean the function byXPath creates at object virtually at runtime?

The outcomes:

Which properties is it referring to?

In dev mode
//*[@id=‘mlist’]/tbody/tr[${rowIndex}]/td[3]/div/span works fine.

The “properties” is the pathway (the xpath) provided to the byXPath method.

Does the pathway "//*[@id='mlist']/tbody/tr[1]/td[3]/div/span" exist? The upper error message states that the pathway has a problem. Are you trying on two different environments? Are the builds the same?

Oh no! The xpath does not point to any object on the true env.

This one //*[@id=“mlist”]/tbody/tr[1]/td[3] works. I replace and see what it will give.

The xpath is good.

But again KO.



Which properties?

Is there another <iframe> to be concerned about?

I see there are 2 actually.
@grylion54 @kazurayam I can NOW upload a duplicate of the true environment!

testFindNameAndID.zip (1.6 MB)

How to retrieve an APPLICATION ACCOUNT (for eg. Fadela Haddadi {Main}) and capture his EMPLOYEE ID?

You already know how to loop to find one item (like the name), such as “Fadela Haddadi {Main}” and you were able to do that with a “parameterized” rowIndex. So the rowIndex of the “Employee Id” would be the exact same, but the column, or “td” element, would be different–and you know which column it is (you can hardcode this column). There you go. Put the two concepts together.

Maybe like:

   def myCell = byXPath("//*[@id='mlist']/tbody/tr[${rowIndex}]/td[3]")
   def theName = WebUI.getText(myCell)

   if (theName.contains("Fadela Haddadi")) {  // or (theName == "Fadela Haddadi {Main}")
          def myEmpId = byXPath("//*[@id='mlist']/tbody/tr[${rowIndex}]/td[???]")
          def theEmpid = WebUI.getText(myEmpId )

    }

Ok. Thanks.
The xpath “//*[@id=‘mlist’]/tbody/tr[${rowIndex}]/td[3]/div/span” does not work.

//*[@id=‘mlist’]/tbody/tr[${rowIndex}]/td[3] → Works.

EMP ID is the 2nd col.
xpath → “//*[@id=‘mlist’]/tbody/tr[${rowIndex}]/td[2]”

The test fails at the step:

def myCell = byXPath("//*[@id='mlist']/tbody/tr[${rowIndex}]/td[3]")

@grylion54 Do you have any idea of the properties it is mentioning?

@grylion54 I replied in the previous post. The pathway “//*[@id=‘mlist’]/tbody/tr[1]/td[3]/div/span” does not work.

//*[@id=‘mlist’]/tbody/tr[${rowIndex}]/td[3] >>>Works.

I was using two different environments. But now I am using the TRUE build which I uploaded yesterday - please see post #47.

All logic is good. There are no errors in the script. I ran it many times today. Yet, the error is persistant.

What can we do to tackle this issue? Can you please download the true build and see if you are getting the names and it gets the expected name, let’s say Fadela Haddadi {Main} ?

You wrote you are using two environments. I guess, one is a development environment, which has small amount of data, which responds quickly. Another environment is a production environment, which has full of data, which responds slowly (you need to wait for a few seconds). Your script happened to run OK against the dev env, but it fails against the prod env. Why?

This is a Frequently Asked Question in this forum.

Any web app needs certain duration of milli-seconds to respond. Web app responds slower than your test script runs. Especially, the document inside <iframe> would require several seconds to load because it is loaded from another URL.

Therefore your script must cope with the slowness of your Application Under Test. Your test script must wait for the HTML pages are completely loaded into browser before it makes any action against the page.

You need to lear how to use “WebUI.verifyXXXX(TestObject, timeout)” and “WebUI.waitForXXXX(TestObject, timeout)” keywords. For example

https://docs.katalon.com/katalon-studio/docs/webui-verify-element-present.html

Search this forum for previous topics that tell you how to use these keywords. You will easily find many.

@kazurayam Yes I did researches. I used the function WebUI.verifyElementPresent.

Test Code

WebUI.delay(5)
for (def rowIndex=1; rowIndex<=15; rowIndex++) {
WebUI.verifyElementPresent(byXPath("//[@id='mlist']/tbody/tr[${rowIndex}]/td[3]"), 20)	
def myCell = byXPath("//*[@id='mlist']/tbody/tr[${rowIndex}]/td[3]")
def theName = WebUI.getText(myCell)
println theName
	
if (theName.contains("Scott Backhouse {Main}")) {  
def myEmpId = byXPath("//*[@id='mlist']/tbody/tr[${rowIndex}]/td[2]")
def theEmpid = WebUI.getText(myEmpId)
}
else {
println ("Name is not in the first page")
	}
}

This is what it is giving:
I am using the Chrome browser. Why is it showing Netscape?



The name is well present in the page but it is unable to find it!

@grylion54 @kazurayam Any other way of getting the name?

The idea of “contains” is to get a smaller bit of the whole. If you are going to compare to the whole, then perhaps use:

if (theName == "Scott Backhouse {Main}") {

Saying that, there are a lot of ways that you can use “contains”, like:

if (theName.contains("Scott Backhouse")) {

Also, since you are having concerns about finding the name, you should make a print out of the names so you can see if there is something else in the “cell” that you have not realized, such as a non-printable character, including getting the correct column

println("Name is ${theName}")
if (theName.contains("Scott Backhouse")) {

Ah Ok. But it is still KO.

It is failing here:

How about slowing your script down with a waitFor statement?

I also notice that you are printing out the name but nothing is displayed. You should find out why. Is your path incorrect or is there another reason.

image

@1Medy_Albion

Why do you place verifyElementPresent() after if () ... else ... ?

In your case, you would want to place verifyElementPresent() before if () ... else ....


I suppose that you misunderstood what WebUI.verifyEementPresent does + how to use it yet.