Search code examples
regexrft

RFT Html.Select has dynamic id and is not recognized


The recorded line is list_prmT_SV_N18947080x18A5068().click(atText("Claimed Students"));

What I have tried to make it work is this:

ClickDropdown("Claimed Students");


public static void ClickDropdown(String name)
{
    GuiTestObject textObj = findTextObject(name);
    if (textObj != null) {
        textObj.click();
    } else {
        throw new ObjectNotFoundException();
    }
}


 private static GuiTestObject findTextObject(String name)
 {
     TestObject[] tobs = find(atDescendant(".class", "Html.SELECT", ".value", name ), true);
     if(tobs.length == 0)
         return null;
     return (GuiTestObject)tobs[0];
 }

The properties available are .id(dynamic), .text, .class


Solution

  • The problem that you described in your question is a common problem and it is mainly related to HTML applications built using JQuery.

    Using the find method is the right way, because you can abstract on the recognition properties used by RFT. Looking at your findTextObject I suggest you to modify the find invocation as follow:

    find(atDescendant(".class", "Html.SELECT"), false);
    

    Using the false argument, you allow RFT to search among all page elements, and not only among the ones that you've previously recorded.

    If you have only one Html.SELECT in page, you can use directly the method select(String value) of the type SelectGuiSubitemTestObject. Otherwise, first you have to cycle over the objects previously found and search for the one that contains the text you want to select. Then, your code will become:

    public static void clickDropdown(String name) {
       // Prepare finding properties
       Property[] props = new Property[2];
       props[0] = new Property(".class", "Html.SELECT");
       props[1] = new Property(".text", new RegularExpression(".*" + name + ".*", false));
       // Find al select items inside the current page
       TestObject slcs = find(atDescendant(props), false);
       // Interact with the element
       if (slcs.length > 0)
          ((SelectGuiSubitemTestObject) slcs[0]).select(name);
    }
    

    In this case you cannot use directly the .text in the find method, because the value of the .text property of a select equals to a concatenation of all its values. So, you have to use a RegularExpression.

    Warning: the find method works if and only if the object your are searching is fully loaded in the page at the time of the search action.

    Using the dynamic find technique could be slower than using elements directly recorded by RFT. Unfortunately, if your UI has dynamic elements' ids, this is the only way to interact with them.

    In this blog there are given some hints to increase the performances of the dynamic find approach.

    1) Object Selection : Here you need to find the right set of objects to search on. Let's call the selected objects as landmarks, which is what we use when we have to move from one place to another in real world.

    2) Search Type: Second important decision to make is how do you want to search on the selected object.

    3) Property selection : We have found the object on which we want to make a search, we have also figured out the scope of search within the object children hierarchy, now is the time to decide what parameters we like to pass to our search type.

    4) Memory cleanup : Last but equally important thing to remember while using objects returned by find is to free the objects as soon as the work is done or whenever you feel that the object might have changed in the AUT as part of some intermediate transaction.

    I'm developing a small framework over RFT, that let's you to compose your script without any recording action. Let me know if you're interested.

    Hope this will help you :)