Forum Discussion

pkudrys's avatar
pkudrys
Frequent Contributor
20 days ago

FindAll returns only one (first) element

Hi guys, 

I'm experiencing a weird problem. I have a mapped element, from which I need to get an array of elements. If tested in chrome/edge dev mode, the xpath of mapped element happily returns number of elements. But FindAll returns only one (first) element. Here is the code I'm using:

function CompareElementsWithRefJSON(createNewRefFiles, setElementFlag, headerInputs, tabInputs, autocompleteMenu, selectPopUpMenu, tabsData, filePath)
{
    let headerItems = headerInputs.FindAll('type','*',5000);
    headerItems = headerItems.toArray();
...
} 

I have a workaround, using FindElements, which works OK, but I don't like it, because it's unnecessary complicated:

function CompareElementsWithRefJSON(createNewRefFiles, setElementFlag, headerInputs, tabInputs, autocompleteMenu, selectPopUpMenu, tabsData, filePath)
{
    let formInputsXpath = GetXpathFromAlias(headerInputs); // This returns xpath of mapped alias object
    let headerParent = headerInputs.Parent; // Get parent element
    let headerItems = headerParent.FindElements(formInputsXpath); // Returns array of elements. Works OK. 
...
}

So, any idea why FindAll returns just one element? BTW, it does not matter what PropName I use as the first parameter. The result is the same. Always just one element.  

19 Replies

  • rraghvani's avatar
    rraghvani
    Icon for Champion Level 3 rankChampion Level 3

    Another reason for not liking XPath, it would never located the correct object in the Object Browser!

    If you were to Highlight, is TestComplete able to locate your mapped object i.e. Aliases.browser.Main_PAGE.DescartesRoutePlanner_SECTION.Asset_Header_FRM.Asset_Form_Header_IPTs on the UI?

    If yes, are you able to try the following snippets of code in a separate function,

    // Also try with a different object/property
    
    // Test 1
    var obj = Aliases.browser.Main_PAGE.DescartesRoutePlanner_SECTION.Asset_Header_FRM.Asset_Form_Header_IPTs.FindAll("type", "*", 100);
    Sys.HighlightObject(obj);
    Log.Message(`Number of objects ${obj.length}`);
    
    // Test 2
    var obj = Aliases.browser.Main_PAGE.DescartesRoutePlanner_SECTION.Asset_Header_FRM.FindAll("type", "*", 100);
    Sys.HighlightObject(obj);
    Log.Message(`Number of objects ${obj.length}`);
    
    // Test 3
    var obj = Aliases.browser.Main_PAGE.DescartesRoutePlanner_SECTION.FindAll("type", "*", 100);
    Sys.HighlightObject(obj);
    Log.Message(`Number of objects ${obj.length}`);

    Does it highlight the correct object in question, and does it return more than one object matching the criteria?

     

    I'm just trying to mimic what you have done. I have a mapped object using XPath, and I'm referring to that object using aliases. FindAll and FindElements return the same number of objects based on the criteria search

     

    • pkudrys's avatar
      pkudrys
      Frequent Contributor

      Hi,

      Thank you for your investigation and help! I really appreciate it. 

      The Test 2 is closest to what I want. The thing is it returns all inputs from given form, not just those specified with my xpath. So it's not usable for my needs. I would have to specify an array of FindAll properties, which is not something I want to do. Anyway, I have a workaround using the Parent function. Not nice, but functional. 

      BTW, sys.highlight fails with "type error", because obj is in fact array, even if it returns only one element. It only works if I specify the obj with array index.     

      • rraghvani's avatar
        rraghvani
        Icon for Champion Level 3 rankChampion Level 3

        You can also include multiple objects and property values e.g. FindAll(["ObjectType", "Enabled", "contentText"], ["Button", "True", "Default*"], 100) to search for objects matching that criteria in Aliases.browser.Main_PAGE.DescartesRoutePlanner_SECTION.Asset_Header_FRM

        My copy and paste of "Sys.HighlightObject(obj);" didn't go to plan!

  • rraghvani's avatar
    rraghvani
    Icon for Champion Level 3 rankChampion Level 3

    The reason I said to do this,

    let headerItems = headerInputs.FindAll('type','*',5000);
    Log.Message("Number of items: " & UBound(headerItems))

    Is so that I can see the number of items being returned by the FindAll method, without performing toArray.

    Is there any object called 'type'?

    The example that I provided, searches for this (ObjectType = Button) -

    For reference, use any object name as shown in green, followed by a matching property value as shown in orange

     

    • pkudrys's avatar
      pkudrys
      Frequent Contributor

      Just tried FindAll with Enabled=True. The same result.

       

      • rraghvani's avatar
        rraghvani
        Icon for Champion Level 3 rankChampion Level 3

        Could you create a new project and select JavaScript as the language (or convert the code and use VBScript). Using Chrome, navigate to https://www.w3schools.com/css/css3_buttons.asp and run the following code,

        function GetAllButtons()
        {
            var browser = Sys.Browser("chrome");
            var page = browser.Page("https://www.w3schools.com/css/css3_buttons.asp").Panel(2).Panel(0).Panel("belowtopnav").Panel(0).Panel("main");
            var buttons = page.FindAll("ObjectType", "Button", 1);
            Log.Message(`Number of buttons on page ${buttons.length}`);
        }

        Does it work, and does it return 56 buttons? I just want to eliminate and ensure that FindAll method is working as expected, before proceeding to the next step.

    • pkudrys's avatar
      pkudrys
      Frequent Contributor

      Yes, there definitely is "Type" property in the found element. In fact, each of the elements, if inspected with Spy, have Type property. And I also tried other properties, unfortunately, with he same result. 

        

  • rraghvani's avatar
    rraghvani
    Icon for Champion Level 3 rankChampion Level 3

    Here's a simple example, of using FindAll to search for all objects that have the specified value of 'ObjectType' and of the specified property 'Button'.

    The search is performed in the object hierarchy displayed in the Object Browser panel starting from 'Panel("main")' object and continuing down the hierarchy to the specified depth of 1.

    If you were to do

    let headerItems = headerInputs.FindAll('type','*',5000);
    Log.Message("Number of items: " & UBound(headerItems))

    What does "Number of items:" show? And what does the Object Browser hierarchy show?

    • pkudrys's avatar
      pkudrys
      Frequent Contributor

      Hi,

      This is my 4th attempt to answer you. From some reasons, my answers disappear few minutes after posting :) My guess is that it happens because of attached images? I will try to attach the pictures in separate answers.   

      The code returns "1" and the found element is just the first element from the expected array of elements.

      As for the Object Browser, no matter what I try, it always shows an ancestor element, instead of the one I'm trying to show.