Forum Discussion

Stub's avatar
Stub
Occasional Contributor
9 years ago

Mapping FindChild object to Alias?

I have a popup window in a Desktop app that script recording creates an alias for automagically. However, playing the script back doesn't work because it fails to find the popup object on subsequent attempts and I'm not sure how to fix this yet.

 

Being new to TC I then started fiddling with FindChild which finds exactly what I'm after. However, the aliased names e.g. pageLines.ListBox.ClickItemXY(...); no longer works as it can't find "ListBox" on my dialog.

 

Is there a cunning way to map a FindChild object to an existing Alias so I can continue using the name mapping entries that TC10 has already created?

12 Replies

  • Sounds like something is changing at runtime.

     

    What identification properties is it using for the popup? And do they match what you see if you inspect the element manually using the object spy?

  • dsstrainer's avatar
    dsstrainer
    Occasional Contributor

    You are asking for the holy grail of namemapping. I asked for something along these lines as well and unfortunately neither at possible at this time making namemapping unusable for me.

     

    The problem you are encountering is that Aliases can point to objects that are not yet loaded

    but FindChild is an active lookup on an object at the time you call it.

     

     

    • Colin_McCrae's avatar
      Colin_McCrae
      Community Hero

      Are you sure the popup is present when you make the call? If you try and use it before it's available, it'll fail.

       

      You maybe need to wait until it (or some component part of it) exisits before you try and work on it?

       

      (Use helper/finder function if you can rather than a simple hardcoded wait .... they're never a good long term solution)

      • dsstrainer's avatar
        dsstrainer
        Occasional Contributor

        That is what he's getting at. He's trying to set a compile-time Alias equal to a run-time object and was looking for a way to do it. Unfortunately it cannot be done.

         

        Here's one method I use instead....

         

        Instead of setting something at the beginning like

         

         

        Set CustomerGrid = Aliases.MyApp.MainWindow.root.ContentControl.Grid.FloatingContainer.Grid.FloatingContainerBody.border.customerPanel.dataListGrid

         

         

        Instead I create my own nickname for it and use my own accessor function that I call when I need to interact with "CustomerGrid" and completely get rid of Namemapping/Aliasing.

         

         

        Function TCGetObject (objName)
        
             MyApp = Sys.Process("MyApp").WPFObject("HwndSource: Shell", "*").FindChild("Name", "WPFObject(""HwndSource: standAloneWindow"")")
        
            Select Case objName
                Case "CustomerGrid"
                    Set TCGetObject = MyApp.FindChild("Name", "customerGrid", 99999)
                Case "AddressGrid"
                    Set TCGetObject = MyApp.FindChild("Name", "addressGrid", 99999)
                Case "SubmitButton"
                    Set TCGetObject = MyApp.FindChild("Name", "buttonSubmit", 99999)
                Case "ClearForm"
                    Set TCGetObject = MyApp.FindChild("Name", "buttonClear", 99999)
                Case Else
                    msgbox "No object found with that name"
                    Runner.Halt
            End Select
        
        End Function

         

         

        Then in my individual test calls, I simply pass the function as the object

        Sub Test1
            Set CG = TCGetObject("CustomerGrid")
         
            CG.Click
        End Sub

         

        It doesn't solve the issue with being able to pre-define objects, but makes it a lot more manageable and readable to use a more model-based object define that you'd call from within each test script. It also makes it completely dynamic in case the stuff in between changes, and it does all the time for my application. We use devexpress for our grids and UIs and it seems like each update changes the decorators and other layers.

         

        You could even add something like a WaitChild call within the case statement to wait for that object to exist.

         

        The only other alternative would be to do an init function that does a fly-by run through of all the menus first, and sets the objects as globals for use later. For example, if you are trying to test a popup in test 3 but that popup doesn't exist until you do test 1 and test 2, then you'd need to "fake" some data to get the popup active, then pop it up, set the globalized object, then delete all your fake data and start the real test. But this would be very inefficient.