How to get InfoObjet from element

Class library usage, coding and language questions.
stefanb
Posts: 18
Joined: Fri Feb 01, 2013 2:30 pm

How to get InfoObjet from element

Post by stefanb » Thu Mar 14, 2013 9:50 am

Hi

I have mapped some elements in Ranorox spy and exported to C#. In Visual Studio I noticed that for each element there is a corresponding RepoItemInfo object for which you can do for example .exists().
My qusetion is, is there any way of accessing the info object from the element object, i.e.

I have the :repo.Base.LeftPanelMenu.MenuX.FieldX object

from where I would like to fetch the:

repo.Base.LeftPanelMenu.MenuX.FieldXInfo object

BR Stefan

hs.fk
Posts: 12
Joined: Thu Jul 12, 2012 11:47 am
Location: Hamburg

Re: How to get InfoObjet from element

Post by hs.fk » Thu Mar 14, 2013 6:15 pm

Can you please explain why you want the RepoItemInfo?
I don't see the point in getting the RepoItemInfo if you already have the corresponding Element.

Nonetheless, I don't see a useful common indicator between the RepoItemInfo and the Element.
The only thing that could be used is the path, but the Element doesn't save the path (that's what I think, maybe I'm wrong), which was used to create that Element.
So 'repoItemInfoInstance.AbsolutePath' is not guaranteed to be equal to 'elementInstance.GetPath(/*whatever*/)'. But if someone has code to compare two paths, than the following code could be used (maybe there's even a way in Ranorex-Libs, which i don't know).


Warning: guaranteed NOT bug free
#region RepoItemInfo Madness

public static RepoItemInfo GetRepoItemInfo( RepoGenBaseFolder repoFolder, Element element )
  {
  string searchedPath = element.GetPath( PathBuildMode.Reduce ).ToString();
  var repoItemInfos = GetRepoItemInfosRecrusiv( repoFolder ).ToArray();
  foreach ( var repoItemInfo in repoItemInfos )
    {
    string curPath = "/" + repoItemInfo.AbsolutePath.ToString();
    if ( curPath == searchedPath )
      {
      return repoItemInfo;
      }
    }
  return null;
  }

private static IEnumerable<RepoItemInfo> GetRepoItemInfosRecrusiv( RepoGenBaseFolder repoFolder )
  {
  var repoItemInfoType = typeof( RepoItemInfo );
  var repoGenBaseFolderType = typeof( RepoGenBaseFolder );
  var curRepoFolderType = repoFolder.GetType();
  foreach ( var propInfo in curRepoFolderType.GetProperties( BindingFlags.Public | BindingFlags.Instance ) )
    {
    if ( propInfo.PropertyType == repoItemInfoType )
      {
      yield return (RepoItemInfo)propInfo.GetValue( repoFolder, null );
      }
    else if ( propInfo.PropertyType.IsSubclassOf( repoGenBaseFolderType ) )
      {
      var subRepoFolder = (RepoGenBaseFolder)propInfo.GetValue( repoFolder, null );
      foreach ( var subRepoItemInfo in GetRepoItemInfosRecrusiv( subRepoFolder ) )
        {
        yield return subRepoItemInfo;
        }
      }
    }
  }

#endregion

stefanb
Posts: 18
Joined: Fri Feb 01, 2013 2:30 pm

Re: How to get InfoObjet from element

Post by stefanb » Fri Mar 15, 2013 11:32 am

Hi!

Thanks for your input.

The reason that I wanted the Infoobject in addition to the element is that I would like to do a method like below where I check for existence before I validate "Visible" and "Enabled"
public static void PressButton(Ranorex.Button element)
         {
            RepoItemInfo InfoObj = element.getInfo;
            Validate.IsTrue(infoObj.Exists() && element.Visible && element.Enabled);
            b.Click();
        }
However, maybe it is not necessary to do this check?

BR Stefan

User avatar
Support Team
Site Admin
Site Admin
Posts: 11709
Joined: Fri Jul 07, 2006 4:30 pm
Location: Graz, Austria

Re: How to get InfoObjet from element

Post by Support Team » Fri Mar 15, 2013 1:30 pm

Hello,

I am not sure if I understand you correctly, but why don't you use the Validate.Exists() method in order to check if the element exists?
Validate.Exists(element.AbsoluteBasePath);
Regards,
Bernhard
.
Image

hs.fk
Posts: 12
Joined: Thu Jul 12, 2012 11:47 am
Location: Hamburg

Re: How to get InfoObjet from element

Post by hs.fk » Fri Mar 15, 2013 1:31 pm

I think 'Adapter.Valid' is what you want, but I'm not quite sure.
API-Documention wrote:Returns true if the element is believed to be valid.
'RepoInfoItem.Exists()' internally tries to create a Element with the path from the RepoInfoItem.
This can also be done with only the Element.
int pid = Host.Local.RunApplication( "calc" );
Ranorex.Form formCalc = "/form[@processid='" + pid + "']";

Host.Local.CloseApplication( formCalc );         // comment this out
//formCalc.State = FormWindowState.Minimized;    // comment this in      
                                                 // to see that 'formCalc.Valid' is still true and 'formCalc.Visible' not

bool isOK = formCalc.Valid && formCalc.Visible;

Ranorex.Form newFormCalc;
bool isOK2 = formCalc.TryRecreate( out newFormCalc ) && newFormCalc.Visible;
TryRecreate source:
public static class ElementExtensions
  {
  public static bool TryRecreate<T>( this T adapter, out T newAdapter )
    where T : Adapter
    {
    newAdapter = null;
    try
      {
      var element = adapter.Element.Recreate();
      newAdapter = element.As<T>();
      }
    catch ( ElementNotFoundException )
      {
      return false;
      }
    return true;
    }

  public static T Recreate<T>( this T adapter )
    where T : Adapter
    {
    var newElement = adapter.Element.Recreate();
    return newElement.As<T>();
    }

  public static Element Recreate( this Element element )
    {
    var path = element.GetPath(PathBuildMode.Reduce);
    return Host.Local.FindSingle( path );
    }
  }
/e
Regarding Bernhards suggestion:
yeah, that's propably a simpler way of doing it

stefanb
Posts: 18
Joined: Fri Feb 01, 2013 2:30 pm

Re: How to get InfoObjet from element

Post by stefanb » Fri Mar 15, 2013 3:39 pm

Hi!

Thanks both of you for your support!

I can´t find the "AbsoluteBasePath" method for element but I guess I can do like this?
public static void PressButton(Ranorex.Button element)
         {
            Validate.Exists(element);
            Validate.IsTrue(element.Visible && element.Enabled);
            b.Click();
        }
It seems to be a good solution.

BR Stefan

User avatar
Support Team
Site Admin
Site Admin
Posts: 11709
Joined: Fri Jul 07, 2006 4:30 pm
Location: Graz, Austria

Re: How to get InfoObjet from element

Post by Support Team » Mon Mar 18, 2013 4:08 pm

Hello,

Yes, that should also work. Sorry about my previous post. The part with the "AbsoluteBasePath" was too much.
I meant Validate.Exists(element);

Regards,
Bernhard
.
Image

stefanb
Posts: 18
Joined: Fri Feb 01, 2013 2:30 pm

Re: How to get InfoObjet from element

Post by stefanb » Mon Mar 18, 2013 4:51 pm

Hi Bernhard!

Unfortunately my report doesn´t show any failure when I run my code and the element doesn´t exist. I have set up my reporting like this:
Report.Setup(ReportLevel.Debug, Properties.Settings.Default.ReportPath, true);
and than I do
public static void PressButton(Ranorex.Button element)  
         {  
            Validate.Exists(element);  
            Validate.IsTrue(element.Visible && element.Enabled);  
            b.Click();  
        }
An exception is thrown in VS studio but the validation is not reported in Ranorex report. Do you know why?

Thanks Stefan

User avatar
Support Team
Site Admin
Site Admin
Posts: 11709
Joined: Fri Jul 07, 2006 4:30 pm
Location: Graz, Austria

Re: How to get InfoObjet from element

Post by Support Team » Tue Mar 19, 2013 5:06 pm

Hello Stefan,

How is your element defined when you call the function PressButton() is called?
Could you send us a sample solution in order to analyze your code?
A reason for your problem could be you try to set the value of the parameter using the path to your button. Please try to make the Validate.Exists() method before you define the value for the element as shown below.
Validate.Exists(@"/form[@title='Calculator']//button[@controlid='135']");
Ranorex.Core.Element button = @"/form[@title='Calculator']//button[@controlid='135']";
PressButton(button);
Regards,
Bernhard
.
Image

stefanb
Posts: 18
Joined: Fri Feb 01, 2013 2:30 pm

Re: How to get InfoObjet from element

Post by stefanb » Wed Mar 20, 2013 9:56 am

Hi!

I´m not able to send you the solution but when i debug my code I realize where the problem is. I use the C# file that can be generated from Ranorex Spy to fetch the elements. However if the element doesn´t exist an exception is thrown already in the Repository.Repository.cs file.
public virtual Ranorex.Button Button_Ny
            {
                get
                {
                    return _button_nyInfo.CreateAdapter<Ranorex.Button>(true);
                }
            }
How can I verify the existence of an element when I use repository file generated by Ranorex Spy?

BR Stefan

hs.fk
Posts: 12
Joined: Thu Jul 12, 2012 11:47 am
Location: Hamburg

Re: How to get InfoObjet from element

Post by hs.fk » Wed Mar 20, 2013 1:24 pm

Hi,

you can use the corresponding RepoItemInfo-Property. It is generated along with the Button-Adapter-Property.

Maybe this is what you want:
// call
PressButton( repo.Button_NyInfo );
// instead of 
// PressButton( repo.Button_Ny );

public static void PressButton( RepoItemInfo btnInfo )
  {
  Validate.Exists( btnInfo );
  Button btn = btnInfo.CreateAdapter<Button>( true );
  Validate.IsTrue( btn.Visible, "btn.Visible" );
  Validate.IsTrue( btn.Enabled, "btn.Enabled" );
  btn.Click();
  }

stefanb
Posts: 18
Joined: Fri Feb 01, 2013 2:30 pm

Re: How to get InfoObjet from element

Post by stefanb » Thu Mar 21, 2013 10:02 am

Hi!

So now we´re back to the first question :) As I don´t want to pass around both the element and the InfoObjact I was interested in whether it would be possible to get the InfoObject from the element. This would simplify my setup and make it more intuitive.

BR Stefan

hs.fk
Posts: 12
Joined: Thu Jul 12, 2012 11:47 am
Location: Hamburg

Re: How to get InfoObjet from element

Post by hs.fk » Thu Mar 21, 2013 2:35 pm

OK, my intention was, that you only pass around the RepoItemInfo, because you can create the Element on demand from it. The downside is that you lose the information which Adapter-Type should be used for that Element (E.g. Button, Text etc.; Necessary for the RepoItemInfoInstance.CreateAdapter-Call).

I have a hard time understanding your need for passing the Element around, because you can only have a Element-Instance, if the Element does exist.
If you have a Element that was created successfully and some time later the corresponding GUI-Element does not exist anymore, than you can use the Element.Valid-Property (I think) to validate the existence. See my other post

If you want to write something like this
PushButton( repo.ButtonAsdf );
the ButtonAsdf-Property already verifies the existence of the control with a ElementNotFoundException.
If you want to write a specified report message, than you can enclose your whole test code in something like this
try
  {
  /*... code ...*/

  PressButton( repo.ButtonAsdf );
        
  /*... code ...*/
  }
catch ( ElementNotFoundException ex )
  {
  Report.Failure( "Element not found! >Additional infos... what you want to report.<\r\n" + ex.ToString() );
  throw;
  }

stefanb
Posts: 18
Joined: Fri Feb 01, 2013 2:30 pm

Re: How to get InfoObjet from element

Post by stefanb » Fri Mar 22, 2013 9:47 am

Thanks Hf.fk

I will use the "try, catch" solution instead of validate.Exists :)

BR Stefan