Selection method used always selects last element in a list


I have a menu that contains a link per user account whereby selecting a specific link will login that specific user. The issue i am encountering is that for some reason when i run the script, the last user in the list is always the one selected. Please see screenshots below of the user list as well as the Objects details.


I realized this is because the selector locator used is as follows:

This means it will always take the element in the 3rd row (tr[3]. Is there a way to use a wild card for this?

There are several ways. My way would be to pick a random one of the table:

import org.openqa.selenium.By as By 
import org.openqa.selenium.WebDriver as WebDriver 
import org.openqa.selenium.WebElement as WebElement 
import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory 
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

WebDriver driver = DriverFactory.getWebDriver()

Random rnd = new Random();

'To locate table'
WebElement pTable = driver.findElement(By.xpath("id('kGridUserSites')/div[2]/div/table/tbody"));

'To locate rows of table it will capture all the rows available in the table'
List<WebElement> rows_table = pTable.findElements(By.tagName('tr'));

'To calculate no of rows in table'
int rows_count = rows_table.size();
'get random row within table'
List<WebElement> columns_row  = rows_table.get(rnd.nextInt(rows_count.size)).findElements(By.tagName('td'));

'click on the 5th element of the row'

Would there be an easier way, maybe just to play with the object’s properties to select a specific element in the table?

How you address the situation depends on your experience and background. Another idea is you could create “different” Test Objects and use a CASE block with a RANDOM value to select which id or element to click. Or store a list of id in a List<String> and randomly pick one of the the items.

Other users may come and offer their ideas too. Keep searching also.

FYI, depending on the test case i run, it would not be a random but a specific element i want to click on.
I would think playing with the objects properties for a specific object and using that object in the script would be an idea, but ihave tried playing with the objects properties, the test results are random.It will pass when the element is at the end of the list, because of the Selector locator which makes reference to the table row. I wou,ld think instead of referencing a table row, can we just reference the name of the account you want to switch to? Can that be done somewhere within the object’s properties without having to worry about where in the table the element is located??

Check out if there are any properties you can use within the table and cell you want and try to create a TestObject in the code? There are several examples using addProperty within this forum.

Hi, I have followed the code in your example and from the documentation and adapted the code to my needs. Basically what I want to achieve is find the row that corresponds to the account name im looking for, and click on the TestObject defined which happens to be the 4th column/cell for that row.
When I run the script, I get the error shown below. Please find below the script and snapshot of the error along with the xpath. Note that I have changed the xpath value in Katalon as such. I am not sure if this is required. Instead of row, it was 4, since this is the location of the element but it;'s not always in that location.

NOTE: If i replace redirectLink.setSelectorValue(SelectorMethod.XPATH,"//div[@id=‘kGridUserSites’]/div[2]/div/table/tbody/tr["+row+"]/td[4]/a/span")

with the actual row number it works (see below).But the intention is to get the row number and use the row variable to click on the actual object in question. When I try that I get a MissingPropertyException.


def getRowColumnTable(){

	String switchAccountsArrow = "Object Repository/Page_Stratocast portal - Cloud administrators/switchAccountsArrow"
	String switchAccountsMenuOption = "Object Repository/Page_Stratocast portal - Cloud administrators/Switch accounts"

	TestObject redirectLink = new TestObject('Object Repository/Page_Stratocast portal - Massimo2.3_Train09/span_Cloud administrator_k-i-arrow-e k-icon')
	WebDriver driver = DriverFactory.getWebDriver()
	String ExpectedValue = "Client administrator";

	'To locate table'
	WebElement Table = driver.findElement(By.xpath("//table/tbody"))
	'To locate rows of table it will Capture all the rows available in the table'
	List<WebElement> rows_table = Table.findElements(By.tagName('tr'))
	'To calculate no of rows In table'
	int rows_count = rows_table.size()

	'Loop will execute for all the rows of the table'
	for (int row = 0; row < rows_count; row++) {
		'To locate columns(cells) of that specific row'
		List<WebElement> Columns_row = rows_table.get(row).findElements(By.tagName('td'))

		'To calculate no of columns(cells) In that specific row'
		int columns_count = Columns_row.size()

		println((('Number of cells In Row ' + row) + ' are ') + columns_count)

		'Loop will execute till the last cell of that specific row'
		for (int column = 0; column < columns_count; column++) {
			'It will retrieve text from each cell'
			String celltext = Columns_row.get(column).getText()

			println((((('Cell Value Of row number ' + row) + ' and column number ') + column) + ' Is ') + celltext)

			'Checking if Cell text is matching with the expected value'
			 if (celltext == ExpectedValue) {
			    'Click on the redirect/switch account link button'
			// println('Text present in row number 3 is: ' + Columns_row.get(2).getText())

			//  'After getting the Expected value from Table we will Terminate the loop'
		     break Loop;

Okay, I see it now…

Your row variable is defined inside the for loop. You cannot use it OUTSIDE the for loop.

Define it first BEFORE the for loop. Something like this…

int row;

for(row = 0; row < rows_count ...) {

I made some code changes and solved my problem. I put the last 3 statements in the if statement and also used row+1 since it’s 0 based.

Yes that’s what i have done, i put it inside the for loop and now it works. I just need to glue things together to achieve what I want, thanks!!