Page 1 of 2

Convert String to Repo Element

Posted: Mon Dec 05, 2016 2:06 pm
by xibinki
Hi guys,


I'm trying to create a method which allows me to convert strings to repository elements.
I already have the elements on my repository and I wish to do something like this:

Code: Select all

public void method1 (string WhatIWant)
{
BValid = repo.BO.SincronizacaoDeEntidadesInfo.Exists();
	if (BValid == true) 
	{
	  string A = "repo.BO.SIGABOClient."+WhatIWant+"Info.WaitForExists(180000)";
          //Conversion of string A to repository element: 
          //repo.BO.SIGABOClient.Products1Info.WaitForExists(180000)
          ??? How to ???
	}				
	else 
	{
	string B = "repo.BO.SIGABOClient."+WhatIWant+"Info.WaitForExists(180000)";
          //Conversion of string B to repository element: 
          //repo.BO.SIGABOClient.Products2Info.WaitForExists(180000)
          ??? How to ???
	}
}
Just a note, we have 3 different elements identified in the repository:

Code: Select all

repo.BO.SIGABOClient.SincronizacaoDeEntidades
repo.BO.SIGABOClient.Products1
repo.BO.SIGABOClient.Products2

Re: Convert String to Repo Element

Posted: Mon Dec 05, 2016 3:00 pm
by odklizec
Hi,

As far as I know, there is currently no way to convert a plain string to repoitem. The only solution seems to be a workaround suggested here:
http://www.ranorex.com/forum/pass-repos ... tml#p23444
But since it's already possible to pass a repoiteminfo/adapter to method (as a parameter), it's better to go this way. I would personally create a method, with repoiteminfo parameter pointing to an element/folder, which is common to all three requested repo items (sigaboclient). Then search for the element in question using Find method and xpath with variable (starting from the common repo item/folder). But do whatever suits you best ;)

Re: Convert String to Repo Element

Posted: Mon Dec 05, 2016 4:12 pm
by xibinki
Could you exemplify your method:
pass a repoiteminfo/adapter to method (as a parameter), it's better to go this way. I would personally create a method, with repoiteminfo parameter pointing to an element/folder, which is common to all three requested repo items (sigaboclient).

Re: Convert String to Repo Element

Posted: Mon Dec 05, 2016 4:35 pm
by Vaughan.Douglas
If I understand what you're trying to do, I'd go about it like this (in VB)... I'm not as comfortable with LINQ in C#
Dim myQuery As IEnumerable(Of RepoItemInfo) = From things In repo.SelfInfo.Children
                                                          Where things.Name Is Me.myName
                                                          Select things

Dim myObject As RepoItemInfo = myQuery.FirstOrDefault()

myObject.WaitForExists(500)
I'd further stick this method on one of those new user code groups in Ranorex 6.2
public Function SearchRepoItemByName(ByVal repoItemName As string) As RepoItemInfo
     Dim myQuery As IEnumerable(Of RepoItemInfo) = From things In repo.SelfInfo.Children
                                           Where things.Name Is repoItemName
                                           Select things
           
     SearchRepoItemByName = myQuery.FirstOrDefault()
End Function
or this
Public Sub SearchByNameAndWaitForExist(ByVal repoItemName As String, ByVal timeOut As Duration)
     Dim myQuery As IEnumerable(Of RepoItemInfo) = From things In repo.SelfInfo.Children
                                           Where things.Name Is repoItemName
                                           Select things
     myQuery.First().WaitForExists(timeOut)
End Sub

Re: Convert String to Repo Element

Posted: Tue Dec 06, 2016 2:09 pm
by xibinki
Hummm, interesting...

I've tried creating the same structure on C# but I'm missing something :X

Re: Convert String to Repo Element

Posted: Tue Dec 06, 2016 2:25 pm
by odklizec
If you are not sure about correct conversion of VB .NET code to C#, you can use built-in conversion tool, which can be found in menu Tools >> Convert code to...
Just create a new VB .NET based project, copy the provided VB .Net code into it and then convert it to C# ;)

Re: Convert String to Repo Element

Posted: Tue Dec 06, 2016 4:14 pm
by xibinki
So for example, I have these two elements identified on my repository:

Code: Select all

repo.BO.SincronizacaoDeEntidades.Self
repo.BO.SincronizacaoDeProdutos.Self
I also have this validation method:

Code: Select all

public SearchAndValidate (//element I want to pass//) {
bool BValid = true;
while (BValid) {
	if (//element I want to pass//Info.Exists()) {
		BValid = true;
	}
	else {
		BValid = false;
	}
}
}
By using your method:

Code: Select all

Dim myQuery As IEnumerable(Of RepoItemInfo) = From things In repo.SelfInfo.Children  
                                                          Where things.Name Is Me.myName  
                                                          Select things  
  
Dim myObject As RepoItemInfo = myQuery.FirstOrDefault()  
  
myObject.WaitForExists(500)
I would only need to call like this:

Code: Select all

repo.BO.SincronizacaoDeEntidades.Self)
and

Code: Select all

myQuery(repo.BO.SincronizacaoDeProdutos.Self)
And it would search for the item in my repository and tell me if it exists after 500ms while the test is running:

Code: Select all

myObject.WaitForExists(500)
Is that it?

Re: Convert String to Repo Element

Posted: Tue Dec 06, 2016 9:54 pm
by Vaughan.Douglas
odklizec wrote:If you are not sure about correct conversion of VB .NET code to C#, you can use built-in conversion tool, which can be found in menu Tools >> Convert code to...
Just create a new VB .NET based project, copy the provided VB .Net code into it and then convert it to C# ;)
I haven't met a conversion tool (including Ranorex) that can convert LINQ flawlessly. I tested out the VB code. I would have written the C# equivalent but didn't have time to test it out.

Re: Convert String to Repo Element

Posted: Tue Dec 06, 2016 10:20 pm
by Vaughan.Douglas
xibinki wrote:So for example, I have these two elements identified on my repository:

Code: Select all

repo.BO.SincronizacaoDeEntidades.Self
repo.BO.SincronizacaoDeProdutos.Self
I also have this validation method:

Code: Select all

public SearchAndValidate (//element I want to pass//) {
bool BValid = true;
while (BValid) {
	if (//element I want to pass//Info.Exists()) {
		BValid = true;
	}
	else {
		BValid = false;
	}
}
}
By using your method:

Code: Select all

Dim myQuery As IEnumerable(Of RepoItemInfo) = From things In repo.SelfInfo.Children  
                                                          Where things.Name Is Me.myName  
                                                          Select things  
  
Dim myObject As RepoItemInfo = myQuery.FirstOrDefault()  
  
myObject.WaitForExists(500)
I would only need to call like this: Not So much

Code: Select all

repo.BO.SincronizacaoDeEntidades.Self)
and
Yes, this is more along the lines of what you'd need to do

Code: Select all

myQuery(repo.BO.SincronizacaoDeProdutos.Self)
And it would search for the item in my repository and tell me if it exists after 500ms while the test is running:

Code: Select all

myObject.WaitForExists(500)
Is that it?
I think you've more or less got the idea.

The query is basically iterating through the collection of repo items and looking for a match on the "name" property. you could do exactly the same thing using a for each loop, although I think it would be more costly from a resource/time prospective.

If I'm perfectly honest, this is the point where I crack open my Ranorex solution in Visual Studio because it has much better real time code analysis and IntelliSense. If you want to throw what you've got up in here, I'll take a look and see if I can get it sorted out.

Give either of these a shot
public RepoItemInfo SearchRepoItemByName(string repoItemName)
		{
			var myQuery = from things in repo.SelfInfo.Children where ReferenceEquals(things.Name, repoItemName) select things;
			return myQuery.FirstOrDefault();
		}
to use the above, you'll need to set a variable equal to the function as it's going to return a RepoItemInfo object back to you and then you'd use the waitforExist on it.
RepoItemInfo myObject = SearchRepoItemByName("you string goes here");
myObject.WaitForExists(5000);
__________________________________________________________________________________________
public void SearchByNameAndWaitForExist(string repoItemName, Duration timeOut)
		{
			var myQuery = from things in repo.SelfInfo.Children where object.ReferenceEquals(things.Name, repoItemName) select things;
			myQuery.First().WaitForExists(timeOut);
		}
For this one you're not going to get anything back, so you just call the method and provide the arguments.
SearchByNameAndWaitForExist("Your string goes here", 5000);
I didn't actually run either of these conversions, so I can't promise they'll work as expected. Let me know if you run into issues and I can help you through them.

Re: Convert String to Repo Element

Posted: Wed Dec 07, 2016 9:28 am
by odklizec
Vaughan.Douglas wrote:
odklizec wrote:If you are not sure about correct conversion of VB .NET code to C#, you can use built-in conversion tool, which can be found in menu Tools >> Convert code to...
Just create a new VB .NET based project, copy the provided VB .Net code into it and then convert it to C# ;)
I haven't met a conversion tool (including Ranorex) that can convert LINQ flawlessly. I tested out the VB code. I would have written the C# equivalent but didn't have time to test it out.
My bad, I missed the LINQ part in the VB code ;)

Re: Convert String to Repo Element

Posted: Wed Dec 07, 2016 3:00 pm
by Vaughan.Douglas
odklizec wrote:
Vaughan.Douglas wrote:
odklizec wrote:If you are not sure about correct conversion of VB .NET code to C#, you can use built-in conversion tool, which can be found in menu Tools >> Convert code to...
Just create a new VB .NET based project, copy the provided VB .Net code into it and then convert it to C# ;)
I haven't met a conversion tool (including Ranorex) that can convert LINQ flawlessly. I tested out the VB code. I would have written the C# equivalent but didn't have time to test it out.
My bad, I missed the LINQ part in the VB code ;)
It's all good. I like to use LINQ and there are a lot of resources that discuss LINQ in C# and many fewer for VB. I have to say things have gotten MUCH better. It used to be that these converters just threw up all over LINQ, but now VB to C# works pretty well and C# to VB gets you in the right neighborhood just depending on how fancy things got in the original code. I think that is because C# had more robust support out of the gate.

Re: Convert String to Repo Element

Posted: Fri Dec 09, 2016 5:07 pm
by xibinki
Vaughan.Douglas wrote:
xibinki wrote:So for example, I have these two elements identified on my repository:

Code: Select all

repo.BO.SincronizacaoDeEntidades.Self
repo.BO.SincronizacaoDeProdutos.Self
I also have this validation method:

Code: Select all

public SearchAndValidate (//element I want to pass//) {
bool BValid = true;
while (BValid) {
	if (//element I want to pass//Info.Exists()) {
		BValid = true;
	}
	else {
		BValid = false;
	}
}
}
By using your method:

Code: Select all

Dim myQuery As IEnumerable(Of RepoItemInfo) = From things In repo.SelfInfo.Children  
                                                          Where things.Name Is Me.myName  
                                                          Select things  
  
Dim myObject As RepoItemInfo = myQuery.FirstOrDefault()  
  
myObject.WaitForExists(500)
I would only need to call like this: Not So much

Code: Select all

repo.BO.SincronizacaoDeEntidades.Self)
and
Yes, this is more along the lines of what you'd need to do

Code: Select all

myQuery(repo.BO.SincronizacaoDeProdutos.Self)
And it would search for the item in my repository and tell me if it exists after 500ms while the test is running:

Code: Select all

myObject.WaitForExists(500)
Is that it?
I think you've more or less got the idea.

The query is basically iterating through the collection of repo items and looking for a match on the "name" property. you could do exactly the same thing using a for each loop, although I think it would be more costly from a resource/time prospective.

If I'm perfectly honest, this is the point where I crack open my Ranorex solution in Visual Studio because it has much better real time code analysis and IntelliSense. If you want to throw what you've got up in here, I'll take a look and see if I can get it sorted out.

Give either of these a shot
public RepoItemInfo SearchRepoItemByName(string repoItemName)
		{
			var myQuery = from things in repo.SelfInfo.Children where ReferenceEquals(things.Name, repoItemName) select things;
			return myQuery.FirstOrDefault();
		}
to use the above, you'll need to set a variable equal to the function as it's going to return a RepoItemInfo object back to you and then you'd use the waitforExist on it.
RepoItemInfo myObject = SearchRepoItemByName("you string goes here");
myObject.WaitForExists(5000);
__________________________________________________________________________________________
public void SearchByNameAndWaitForExist(string repoItemName, Duration timeOut)
		{
			var myQuery = from things in repo.SelfInfo.Children where object.ReferenceEquals(things.Name, repoItemName) select things;
			myQuery.First().WaitForExists(timeOut);
		}
For this one you're not going to get anything back, so you just call the method and provide the arguments.
SearchByNameAndWaitForExist("Your string goes here", 5000);
I didn't actually run either of these conversions, so I can't promise they'll work as expected. Let me know if you run into issues and I can help you through them.
When I use the first method:

Code: Select all

public RepoItemInfo SearchRepoItemByName(string repoItemName)  
        {  
            var myQuery = from things in repo.SelfInfo.Children where ReferenceEquals(things.Name, repoItemName) select things;  
            return myQuery.FirstOrDefault();  
        }  
And then:

Code: Select all

RepoItemInfo myObject = SearchRepoItemByName("you string goes here");  
myObject.WaitForExists(5000);  
I get the following error at the code line with "myObject.WaitForExists(5000);":

Code: Select all

Object reference not set to an instance of an object. 
When I use the second method:

Code: Select all

		public void validacao(string repoItemName, Duration timeOut)  
        {  
            var myQuery = from things in repo.SelfInfo.Children where object.ReferenceEquals(things.Name, repoItemName) select things;  
            myQuery.First().WaitForExists(timeOut);  
        }  
I get this error at the code line with "myQuery.First().WaitForExists(timeOut);":

Code: Select all

Sequence contains no elements 
------------------------------------------------------------------------------------------------

It seems like the 1st method isn't returning anything, but I'm passing the string of my xpath element, example:

Code: Select all

string repoItemName = "repo.BO.SincronizacaoDeEntidades.Self"
For the 2nd method, it's the exact same thing, it looks like it isn't getting anything into "myQuery" variable and I'm passing the same xpath element string.

A little help here, please :( I'm not quite sure why it isn't getting the repo item into the "vars".

Re: Convert String to Repo Element

Posted: Mon Dec 12, 2016 3:36 pm
by Vaughan.Douglas
There is clearly a problem with the code. Like I said my C# isn't all that great. I'll see if I can't get a working version of the C# up here sometime today.

--EDIT--

As with most things, it's a simple problem and totally my fault.
public RepoItemInfo SearchRepoItemByName(string repoItemName)  
        {  
            var myQuery = from things in repo.SelfInfo.Children
                 where ReferenceEquals(things.Name, repoItemName)
                 select things;  
            return myQuery.FirstOrDefault();  
        }
I omitted the base object from the query. repo.selfinfo.children is wrong it should be repo.myBaseObject.selfinfo.children
baseObject.png
public RepoItemInfo SearchRepoItemByName(string repoItemName)  
        {  
            var myQuery = from things in repo.myBaseObject.SelfInfo.Children
                 where _ReferenceEquals(things.Name, repoItemName) 
                 select things;  
            return myQuery.FirstOrDefault();  
        }
The same issue is present in the rest of my examples. I apologize for any additional frustration this might have caused. :oops:

To make up for it, here's the full working c# code
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using WinForms = System.Windows.Forms;
using Microsoft.VisualBasic;

using Ranorex;
using Ranorex.Core;
using Ranorex.Core.Repository;
using Ranorex.Core.Testing;

namespace moreJunk
{
    public partial class Recording1
    {

        /// <summary>
        /// This method gets called right after the recording has been started.
        /// It can be used to execute recording specific initialization code.
        /// </summary>
        private void Init()
        {
            //Dim myName As string = repo.InsidePrincipalHomePage.AnotherItemInfo.name                  
            string myName = "AnotherItem";
            IEnumerable<RepoItemInfo> myQuery = from things in repo.myBaseObject.SelfInfo.Children
                                                where ReferenceEquals(things.Name, myName)
                                                select things;

            RepoItemInfo myObject = myQuery.FirstOrDefault();

            Report.Log(ReportLevel.Success, "CSharp", myObject.Name);
            Report.Log(ReportLevel.Success, myObject.FullName);
            Report.Log(ReportLevel.Success, "From CSharp version of SearchRepoItemByName", SearchRepoItemByName(myName).Name);
        }

        public RepoItemInfo SearchRepoItemByName(string repoItemName)
        {
            IEnumerable<RepoItemInfo> myQuery = from things in repo.myBaseObject.SelfInfo.Children
                                                where ReferenceEquals(things.Name, repoItemName)
                                                select things;
            return myQuery.FirstOrDefault();
        }
        /// <summary>
        /// This won't work because the object doesn't exist.  
        /// </summary>
        /// <param name="repoItemName"></param>
        /// <param name="timeOut"></param>
        public void SearchByNameAndWaitForExist(string repoItemName, Duration timeOut)
        {
            IEnumerable<RepoItemInfo> myQuery = from things in repo.myBaseObject.SelfInfo.Children
                                                where ReferenceEquals(things.Name, repoItemName)
                                                select things;
            myQuery.First().WaitForExists(timeOut);
        }




    }
}

Re: Convert String to Repo Element

Posted: Tue Dec 13, 2016 1:40 pm
by xibinki
Vaughan.Douglas wrote:There is clearly a problem with the code. Like I said my C# isn't all that great. I'll see if I can't get a working version of the C# up here sometime today.

--EDIT--

As with most things, it's a simple problem and totally my fault.
public RepoItemInfo SearchRepoItemByName(string repoItemName)  
        {  
            var myQuery = from things in repo.SelfInfo.Children
                 where ReferenceEquals(things.Name, repoItemName)
                 select things;  
            return myQuery.FirstOrDefault();  
        }
I omitted the base object from the query. repo.selfinfo.children is wrong it should be repo.myBaseObject.selfinfo.children
baseObject.png
public RepoItemInfo SearchRepoItemByName(string repoItemName)  
        {  
            var myQuery = from things in repo.myBaseObject.SelfInfo.Children
                 where _ReferenceEquals(things.Name, repoItemName) 
                 select things;  
            return myQuery.FirstOrDefault();  
        }
The same issue is present in the rest of my examples. I apologize for any additional frustration this might have caused. :oops:

To make up for it, here's the full working c# code
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using WinForms = System.Windows.Forms;
using Microsoft.VisualBasic;

using Ranorex;
using Ranorex.Core;
using Ranorex.Core.Repository;
using Ranorex.Core.Testing;

namespace moreJunk
{
    public partial class Recording1
    {

        /// <summary>
        /// This method gets called right after the recording has been started.
        /// It can be used to execute recording specific initialization code.
        /// </summary>
        private void Init()
        {
            //Dim myName As string = repo.InsidePrincipalHomePage.AnotherItemInfo.name                  
            string myName = "AnotherItem";
            IEnumerable<RepoItemInfo> myQuery = from things in repo.myBaseObject.SelfInfo.Children
                                                where ReferenceEquals(things.Name, myName)
                                                select things;

            RepoItemInfo myObject = myQuery.FirstOrDefault();

            Report.Log(ReportLevel.Success, "CSharp", myObject.Name);
            Report.Log(ReportLevel.Success, myObject.FullName);
            Report.Log(ReportLevel.Success, "From CSharp version of SearchRepoItemByName", SearchRepoItemByName(myName).Name);
        }

        public RepoItemInfo SearchRepoItemByName(string repoItemName)
        {
            IEnumerable<RepoItemInfo> myQuery = from things in repo.myBaseObject.SelfInfo.Children
                                                where ReferenceEquals(things.Name, repoItemName)
                                                select things;
            return myQuery.FirstOrDefault();
        }
        /// <summary>
        /// This won't work because the object doesn't exist.  
        /// </summary>
        /// <param name="repoItemName"></param>
        /// <param name="timeOut"></param>
        public void SearchByNameAndWaitForExist(string repoItemName, Duration timeOut)
        {
            IEnumerable<RepoItemInfo> myQuery = from things in repo.myBaseObject.SelfInfo.Children
                                                where ReferenceEquals(things.Name, repoItemName)
                                                select things;
            myQuery.First().WaitForExists(timeOut);
        }




    }
}
So when I try to use the following code:

Code: Select all

public void v(string repoItemName, Duration timeOut)  
{
    IEnumerable<RepoItemInfo> myQuery = from things in repo.BO.SIGABOClient.SelfInfo.Children  
    
    where ReferenceEquals(things.Name, repoItemName)  
    select things;  
    myQuery.First().WaitForExists(timeOut); 
}
I still get the "Sequence contains no element" on the "myQuery.First().WaitForExists(timeOut);", it seems that doesn't find anything on the xpath I just gave to myBaseObject (repo.BO.SIGABOClient) which is where the element I want to search is (repo.BO.SIGABOClient.Importacao.SincronizacaoDeProdutosInfo).

What now? :?

---Edit 1---

Ok, so I managed to put it to work with the following code:

Code: Select all

public void v(string repoItemName, Duration timeOut)  
{ 
IEnumerable<RepoItemInfo> myQuery = from things in repo.BO.SIGABOClient.Importacao.SelfInfo.Children

where ReferenceEquals(things.Name, repoItemName)  
select things;  

myQuery.First().Exists(timeOut);
}
But now I have another question, I noticed that in order to successfully search for an element, I had to give the full xPath where the element actually is. My question is, isn't possible to make the method have a wider range, what I'm trying to say is, is it possible to give the root of the repository (ex: repo.BO.SelfInfo.Children) and make the method search deeper through the tree of paths/folders? Because I tried to give the root of the repository and the method presented didn't work (Sequence contains no element). I'm suspecting it's because he's only searching on the "SelfInfo.Children", isn't there an instruction in Ranorex that allows to search on the entire tree of elements?

Re: Convert String to Repo Element

Posted: Tue Dec 13, 2016 4:34 pm
by Vaughan.Douglas
But now I have another question, I noticed that in order to successfully search for an element, I had to give the full xPath where the element actually is. My question is, isn't possible to make the method have a wider range, what I'm trying to say is, is it possible to give the root of the repository (ex: repo.BO.SelfInfo.Children) and make the method search deeper through the tree of paths/folders? Because I tried to give the root of the repository and the method presented didn't work (Sequence contains no element). I'm suspecting it's because he's only searching on the "SelfInfo.Children", isn't there an instruction in Ranorex that allows to search on the entire tree of elements?
The code sample I provided only works for that first order of children. As written it won't find element in both repo.BO.SelfInfo.Children and repo.BO.SomeRootedFolder.SelfInfo.Children

To answer your question, I would think it should be possible but I don't know of a canned Ranorex method to recursively search through the object repository. Also, since it is possible to have multiple elements with the same name in different branches it'll need to search with the FullName property. My code didn't allow for that when I just gave it a go here this morning.

I'll let this spin for a while, but we may need someone with more advanced skills to help us out at this point. Here are some examples I pulled for stackocerflow:

http://stackoverflow.com/questions/2126 ... ubchildren
http://stackoverflow.com/questions/1025 ... -recursion