Forum Discussion

Rammherz's avatar
Rammherz
Occasional Contributor
7 years ago

Flex object is not presented in object tree

Hi all,

 

In Test Complete project, which was written in 2013 (not by me), I see that one of the flex objects can be successfully found:

 

function ActionToolbar()
{
    var oParent = MVVO_PageContainers.DocumentViewer();
    var aProps = ["ObjectType", "ObjectLabel"];
    var aVals = ["ActionToolbar", "actionToolbar"];
    return CFInternetBrowser.FindObjectByProperties(aProps, aVals, oParent, "ActionToolbar", 2);
}

But I don`t see object 'ActionToolbar' in object tree: 

 

On pic above I marked objects which exactly have 'ActionToolbar' as parent object (according to autotests code).

 

Could you explain why 'ActionToolbar' object is not presented in object tree?

 

If it is make sense I use Debug Version of Flash Player approach.

 

P.S. Sorry for my questions, I`m new in automation testing :)

  • Rammherz's avatar
    Rammherz
    7 years ago

    I found the solution. 

    I just use page URL instead of ActionToolbar as parent object in the function 

     

    function Approve()
    {
        var oParent = ActionToolbar();
        var aProps = ["Caption", "ObjectType"];
        var aVals = ['Approve', 'ToolButton'];
        
        return CFInternetBrowser.FindObjectByProperties(aProps, aVals, oParent, "Approve");
    }

    and it finds both types of buttons.

     

    So I wonder why developers of this autotests used ActionToolbar as parent objects... I suggest they had reasons for it.

    But I have no problem to resolve now :)

    tristaanogre, thanks a lot!

  • tristaanogre's avatar
    tristaanogre
    Esteemed Contributor

    There's a lot of custom code in the function you presented.  MVVO_PageContainers.DocumentViewer for one, the CFInternetBrowser.FindObjectByProperties is another.  These are methods that your predecessor(s) must have written so, with regards to your question, there's too much unknown for us to be able to help you fully.

     

    My GUESS is this... you are mistaken in that there should be an "ActionToolbar" showing up explicitly in the ObjectBrowser.  What it appears to be is that there is some sort of custom code written around the native FindChild method common to all objects in TestComplete.  This means that "ActionToolbar" might not be the immediate parent nor even named that way in the object tree.

     

    If the code works... then it works... and I wouldn't be overly concerned with it except for needing further understanding.  But for us to comment further, we would need to see more about your custom code as noted above to be able to give you a better determination of what's going on.

    • Rammherz's avatar
      Rammherz
      Occasional Contributor

      Thanks!

      Actually another part of code doesn`t work, and I`m trying to understand the structure of objects to fix it.

       

      Yes, here is a lot custom code.

      MVVO_PageContainers.DocumentViewer returns Document Viewer object container:

      function DocumentViewer()
      {
        var oParent = Page();
        var aProps = ["ObjectType", "ObjectLabel"];
        var aVals = ["DocumentView", "documentView"];
        return CFInternetBrowser.FindObjectByProperties(aProps, aVals, oParent, "DocumentViewer", 100);
      }

      CFInternetBrowser.FindObjectByProperties is more complicated function, it searches the specified parent object for an object who's that matches the specified property values.

      function FindObjectByProperties(aPropertyNames, aPropertyValues, oParentObject, strDescription, nDepth, bTryWaitForBrowser)
      {
        var strModuleID = c_strModule + GetFunctionName(arguments.callee); 
        var strStatus = "(Object NOT found)";
        var oReturn = null;
        var oObject = null;
        var oPage;
          
        try
        {
          CFLog.DebugMessageBegin(strModuleID + " Values: " + aPropertyValues.toString());
                  
          // Assign default parameter values.
          nDepth = CFGeneralUtilities.GetValueOrDefault(nDepth, 50);
          bTryWaitForBrowser = CFGeneralUtilities.GetValueOrDefault(bTryWaitForBrowser, true);
        
          if (CFObject.ObjectExists(oParentObject))
          {
            // Refresh the parent object
            oParentObject.Refresh();
          }
          else
          {
            // The ParentObject does not exist, so there is not point in continuing to attempt to find the child element
            throw new kfxException(strModuleID, "The provided oParentObject does not exist. #1", null, strDescription);
          }
          
          // Try to find the object the first time
          oObject = CFObject.FindObjectByProperties(aPropertyNames, aPropertyValues, oParentObject, strDescription, nDepth);
          
          // If the object was not found, try one last time.
          if ((CFException.IsException(oObject)) && (bTryWaitForBrowser))
          {
            // Find the page object in the hierarchy
            oPage = GetPageFromDescendent(oParentObject);
            CheckResult(oPage);
      
            // Make sure the page is loaded and rendered before trying again.
            CheckResult(WaitForBrowser(oPage));
            
            if (CFObject.ObjectExists(oParentObject))
            {
              // Refresh the parent again
              oParentObject.Refresh();
            }
            else
            {
              // The ParentObject does not exist, so there is not point in continuing to attempt to find the child element
              throw new kfxException(strModuleID, "The provided oParentObject does not exist. #2", null, strDescription);
            }
      
            // Try one more time to see if we can find the object.
            oObject = CFObject.FindObjectByProperties(aPropertyNames, aPropertyValues, oParentObject, strDescription, nDepth); 
          }
      
          // Finally if the object was not found, throw an exception.
          CheckResult(oObject, "Could not find object: " + strDescription);
      
          // Set the return value
          oReturn = oObject;
        }
        catch(oException)
        {
          oReturn = CFException.ProcessException(strModuleID, oException);
          CFLog.DebugException(oReturn);
        }
        CFLog.DebugMessageEnd(strModuleID);
      
        // Object was found
        if (! CFException.IsException(oObject))
          strStatus = "(Object found)";
      
        WriteToLog(strModuleID, strStatus + ": Names='" + aPropertyNames.toString() + "', Values='" + aPropertyValues.toString() + "', Depth=" + nDepth);
        return oReturn;
      }

      CFObject.FindObjectByProperties:

      function FindObjectByProperties(aPropertyNames, aPropertyValues, oParentObject, strDescription, nDepth)
      {
        var strModuleID = c_strModule + CFGeneralUtilities.GetFunctionName(arguments.callee); 
        var oObject = null;
      
        try
        {
          CFLog.DebugMessageBegin(strModuleID + " Values: " + aPropertyValues.toString());
      
          // Assign default parameter values.
          nDepth = CFGeneralUtilities.GetValueOrDefault(nDepth, 100);
      
          // See if provided parent object is an exception object
          if (CFException.IsException(oParentObject))
            throw new kfxException(strModuleID, "The provided oParentObject was already an exception object.", oParentObject, strDescription);    
      
          // Make sure we were given a valid parent object.
          if (oParentObject == null)
            throw new kfxException(strModuleID, "You must supply a valid parent object. The parent object specified is null.");
      
          // We need to convert the arrays for use with the TestComplete API.
          var aConvertedPropertyNames = CFGeneralUtilities.ConvertArrayToDictionary(aPropertyNames);
          var aConvertedPropertyValues = CFGeneralUtilities.ConvertArrayToDictionary(aPropertyValues); 
      
          // Attempt to locate an object that matches the set of properties we were given.
          oObject = oParentObject.Find(aConvertedPropertyNames, aConvertedPropertyValues, nDepth);
      
          // Finally if the object was not found, throw an exception.
          if (! ObjectExists(oObject))
            throw new kfxException(strModuleID, "Could not find object: " + strDescription, null, "", arguments);
        }
        catch(oException)
        {
          oObject = CFException.ProcessException(strModuleID, oException);
          CFLog.DebugException(oObject);
        }
        CFLog.DebugMessageEnd(strModuleID);
        return oObject;
      }

      And this object uses parent ActionToolbar (successfully):

      function Approve()
      {
          var oParent = ActionToolbar();
          var aProps = ["Caption", "ObjectType"];
          var aVals = ['Approve', 'ToolButton'];
          
          return CFInternetBrowser.FindObjectByProperties(aProps, aVals, oParent, "Approve");

      All objects in my application which were used in code I could see object tree, except of ActionToolbar.

      In debug mode I also see ActionToolbar object:

       So as I see this is real object.. So why I can`t see it in project tree?)) I don`t understand.

       

       

      • tristaanogre's avatar
        tristaanogre
        Esteemed Contributor

        OK, best that I can see...

         

        DocumentViewer is searching for a child object of the page that could be anywhere within 100 layers of the page that is of ObjectType DocumentViewer with ObjectLabel documentViewer.  So... that's where you need to start.  Yes, you're seeing buttons in your viewer... but I don't see in your initial screenshot where that Document Viewer object is... it could be ANYWHERE in your tree within 100 layers deep.  

         

        Keep in mind that ObjectType and ObjectLabel don't always display in the object tree.  You need to inspect the details of the objects in your tree to find the specific object.

         

        So... once it finds the DocumentViewer, it then finds another object with ObjectType ActionToolbar with label actionToolBar.  Again... it might not show up exactly like that in the tree, you need to inspect the object details.

         

        Again... it all comes down to, as I suspected, a LOT of code being wrapped around the native "Find" method.  To understand the custom code, you need to understand that method.

         

        Start with reading this

         

        https://support.smartbear.com/testcomplete/docs/reference/test-objects/members/common-for-all/find-method.html

         

        Now.... you say something is not working... what EXACTLY is not working?  Any error message? If so, what?