Page 1 of 1

Need help to set values of combo boxes in a table via code

Posted: Fri Jul 28, 2017 11:39 pm
by fester13579
Hello, I am using Ranorex 7.1 and this is a vb based project and could use some help with understanding how to work with tables and combo boxes via code and I really don’t understand the mechanics of what is involved (me=vb.net n00b so please keep that in mind).


At the start of the code module I will be at this page looking at a table of hard drives of which the row count is unknown at run time.

Each row contains an ACTION combo box and an APPLY button that the test will need to interact with.
0286-main table.jpg


The code needs to iterate each row, find the ACTION combo box for the current row then set it to the 3rd option “CryptoErase”
0288-action combo box.jpg

Once the action option is set it needs to click the APPLY button for that row then continue setting the combo boxes and applying for the remaining rows.





I have only once before created any code that involves iterating table objects (from a different test), it was built with a lot of trial and error from some forum examples. It works for my other test but I don’t fully understand why it work and it is probably not the right/best template to use for this so if there is a better way to start from I am open to suggestion.

Code: Select all

Sub Enable_CryptoErase_for_CurrentDrivePage()
			Ranorex.Controls.ProgressForm.Hide()
			Dim tblPD_Config_SSDs As Ranorex.TBodyTag = repo.Idrac2.tblPD_Config_SSDs
			Dim cboAction_xPath As RxPath
			
			repo.Idrac2.Refresh.Click() ' refresh the page
			System.Threading.Thread.Sleep(2000)
			
			
			
			Dim myRow_IDX As Integer=0
			For Each row As TrTag In tblPD_Config_SSDs.Find("./tr") 
				
								
				Dim rowNameCell As TdTag = row.FindSingle("./td[2]")  ' extra question what does [2] reference here???  
				
			 			
				
				Dim myCell_IDX As Integer =0 ' reset cell idx counter
				For Each cell As TdTag In row.Find("./td")  
					Report.debug("Info","Checking drive row #" & CStr(myRow_IDX+1) )
					
									
					If myCell_IDX = 7 Then 
						cboAction_xPath = cell.FromElement(cell).Children(0).GetPath()
						'raw getpath  example   /dom[@domain='100.65.132.1']//div[#'module-div']/div/?/?/div[2]//form[@name='configuration.storage.pdisks']//table/tbody/tr[1]/td[7]/div
						
						'spy examples for each row
						' row 1 example  /dom[@domain='100.65.132.1']//select[#'304|C|Disk.Bay.20:Enclosure.Internal.0-1:PCIeExtender.Slot.1.operation']
						' row 2 exmaple  /dom[@domain='100.65.132.1']//select[#'304|C|Disk.Bay.21:Enclosure.Internal.0-1:PCIeExtender.Slot.1.operation']
						' row 3 example  /dom[@domain='100.65.132.1']//select[#'304|C|Disk.Bay.22:Enclosure.Internal.0-1:PCIeExtender.Slot.1.operation']
						
						Dim myCBO   = Host.Local.FindSingle(cboAction_xPath)
						myCBO.Click()
							
					
					
					End If
					
					
					myCell_IDX +=1
				Next
				
			Next
			
		End Sub
Because I don’t know a better way to address the cell directly I am looping through the rows and then keeping my own counter (myCell_IDX) of each cell of the current row. I believe that the ACTION combobox is in cell 7 so I was assuming I could at the very least get its xpath then click on it to verify I have the right object. Of course I don’t need to click it in the final version of the code but rather change its value to the 3rd option (Erase) but baby steps...

The cell xpath at runtime differs from what see in spy. The comment line "'raw getpath example" is what cboAction_xPath = at run time and the lines below it are examples from spy on each of the action combo boxes on the page.

I've also tried:

Code: Select all

 cboAction_xPath = cell.FromElement(cell).Children(0).FindDescendant(Of SelectTag).GetPath()
which gets me:

Code: Select all

/dom[@domain='100.65.132.1']//div[#'module-div']/div/?/?/div[2]//form[@name='configuration.storage.pdisks']/div/div/div/table/tbody/tr[1]/td[7]/?/?/select[@id='304|C|Disk.Bay.20:Enclosure.Internal.0-1:PCIeExtender.Slot.1.operation']
but the click event gives this error:

Code: Select all

Public member 'Click' on type 'Element' not found. 
In spy the Select object has 3 options:
Option 'number:255'
Option 'number:0'
Option 'number:1'


I assume that 1 = the erase option.


So I could use some help to know if this is a good starting approach and then if so what are my next steps for the current row?

How can I set the combo box value and how do I click APPLY for the current row?

Thanks.

Re: Need help to set values of combo boxes in a table via code

Posted: Tue Aug 01, 2017 1:52 pm
by Support Team
Hello fester,

There are several ways to do this, but here is how I would tackle it. The below code module will do the following.
  • 1. Create a list of all rows from a single RxPath
    2. Loop through each row
    3. Look for select box, and set the value
    4. Look for a button, and click it
RxPath returning all rows

Code: Select all

/dom[@domain='100.65.132.1']//div[#'module-div']/div[2]/div/div[2]//form[@name='configuration.storage.pdisks']/div/div/div/table/tbody/tr
VB

Code: Select all

'Define Repo (Drag and drop element from repo to code module)
Dim repo = SampleSolutionRepository.Instance

'Repo Item Pointing to all rows - add 'Info' to end to use .CreateAdapters method
Dim allRowsInfo = repo.Table.allRowsInfo

'Create IList of all returned rows
Dim allRows As IList(Of TrTag) = allRowsInfo.CreateAdapters(Of TrTag)()

'Loop through each row
For Each row As TrTag In allRows
	'Find Select box in row
	Dim selectBox As SelectTag = row.Element.FindSingle(row.GetPath() + "//select")
	'Perform action on select box
	selectBox.Element.SetAttributeValue("tagvalue", "number:1")

	'Find Apply button in row
	Dim applyButton As ButtonTag = row.FindSingle(row.GetPath() + "//button")
	'Perform action on button
	applyButton.Click()
Next
C#

Code: Select all

//Define Repo (Drag and drop element from repo to code module)
var repo = SampleSolutionRepository.Instance;

//Repo Item Pointing to all rows - add 'Info' to end to use .CreateAdapters method
var allRowsInfo = repo.Table.allRowsInfo;

//Create IList of all returned rows
IList<TrTag> allRows = allRowsInfo.CreateAdapters<TrTag>();

//Loop through each row
foreach (TrTag row in allRows)
{
	//Find Select box in row
	SelectTag selectBox = row.Element.FindSingle(row.GetPath() + "//select");
	//Perform action on select box
	selectBox.Element.SetAttributeValue("tagvalue", "number:1");
	
	//Find Apply button in row
	ButtonTag applyButton = row.FindSingle(row.GetPath() + "//button");
	//Perform action on button
	applyButton.Click();
}
Note, this code is not refined and is meant for demonstration purposes. It should be enough to get you pointed in the right direction and provide another angle to tackle your issue. If used, I recommend at least adding some try/catch blocks, and basic Ranorex reporting.

I hope this helps!

Cheers,
Ned

Re: Need help to set values of combo boxes in a table via code

Posted: Tue Aug 01, 2017 10:10 pm
by fester13579
Almost there...

Code: Select all

 Dim applyButton As ButtonTag = row.FindSingle(row.GetPath() + "//button")
This line finds the 1st button on the row but the apply button is the 2nd button how do I address the 2nd button or Nth buttons?

Thanks

Re: Need help to set values of combo boxes in a table via code

Posted: Wed Aug 02, 2017 1:55 pm
by krstcs
If you know FOR SURE that you will always want the second one, you can add an index to your xpath.

Code: Select all

row.FindSingle(row.GetPath() + "//button[2]")
Notice the "[2]". That tells Ranorex to get the 2nd button it finds that matches the given path. Note that XPath indexes are 1-based (instead of 0-based like the rest of the software world).

Re: Need help to set values of combo boxes in a table via code

Posted: Wed Aug 02, 2017 4:24 pm
by fester13579
Yea, I tried that but when I set it to [2]

Code: Select all

'Find Apply button in row
Dim applyButton As ButtonTag = row.FindSingle(Convert.ToString(row.GetPath()) & "//button[2]")


I get an error
No element found for path '/dom[@domain='100.65.132.1']//div[#'module-div']/div[2]/div/div[2]//form[@name='configuration.storage.pdisks']/div/div/div/table/tbody/tr[1]//button[2]'.

So as an experiment if set to [1] it still clicks the 1st button 'DISCARD' and no error is generated when [1]

Thanks.

Re: Need help to set values of combo boxes in a table via code

Posted: Wed Aug 02, 2017 5:32 pm
by krstcs
OK, that means your path is not correct for the second button or Ranorex couldn't find it within the timeout.

For the first issue, make sure your path is correct and that the second button is under the same parent as what you are trying to find. From looking at the snapshot, the buttons are in different TD tags. This may be an issue. Your row object might not have the path that will work for the second button, it may contain elements after the trtag that it shouldn't. Check it.

For the second issue, try to make your path more specific in order to make it faster.

If it were me, I would use the innertext instead, it will make it much cleaner and you will just have to use the appropriate one when needed.


Tips (my not-so-humble-opinions...):
1. Make your modules as small as possible. They should do one thing only (Click a button; or Enter a username;). This allows you to drag and drop them into the test suite as needed. It also makes them easier to maintain. Name them according to what they do ("Click_OKButton", "Enter_Username", "Validate_HomeScreen") so everyone can tell at a glance what is going on.

2. Make your xpath as specific as possible. There are times when you want generic, but usually that is when you are variablizing the path. Even then, you still want them as specific as possible. This makes it faster to find and work with the elements. Use rooted folders in the repo to help with management.

3. Use the tools Ranorex already has. Don't go into code if you don't need to. Ranorex already gives you a repository for managing element identification and modules and suites for managing the test flow. Use them. I know others will disagree, but to me, you're reinventing the wheel here when you don't need to. Ranorex can be made to do a great many things out of the box, especially if you follow #1 above.

4. If you're new to .NET, you should go ahead and learn C# instead of VB as it is used much more around here (and everywhere else for that matter). The syntax more closely matches the other most highly used languages (Java, C/C++, JavaScript, etc.), where VB doesn't match anything but VB. And, there are a few features that C# has that VB doesn't (although they are really for hard-core users usually). It will give you a leg-up later on that you know C#.


Hope it helps, and take everything for what it cost you!! :D

Kelly

Re: Need help to set values of combo boxes in a table via code

Posted: Thu Aug 03, 2017 3:43 pm
by fester13579
I got it working now using your innertext idea :D

Code: Select all

Dim applyButton As ButtonTag = row.FindSingle(Convert.ToString(row.GetPath())  & "//button[@innertext='Apply']")
So now I am good again - Thank you all for the help...