Forum Discussion

theraud-g's avatar
theraud-g
Occasional Contributor
9 years ago

Custom Web Objects Recognition (TC10 + Angular)

Hi.

 

I have been using TCs for couple of years from TC6 to TC9. I am now trying to understand if TC10 might help us to perform web testing over angular MVVM applications...

 

I have been looking over support but could not find that much information. Only two thread have been created here... 

 

I have difficulties to identify angular web elements within TestComplete. I would rather avoid using script to enable TestComplete full support of custom property.

 

For instance, angular provides a directive ng-repeat that will generate following HTML code : 

 

 

<div ng-controller="simplePiecesController" class="pieces-list ng-scope">
    
    <!-- ngRepeat: piece in pieces -->
    <div class="ng-scope" ng-repeat="piece in pieces">
      <div class="piece-form" max-documents-authorized="maxDocumentsAuthorized" validate="savePersistence()">First piece</div>
    </div>
    
    <!-- ngRepeat: piece in pieces -->
    <div class="ng-scope" ng-repeat="piece in pieces">
      <div class="piece-form" max-documents-authorized="maxDocumentsAuthorized" validate="savePersistence()">Second piece</div>
    </div>
    
    <!-- ngRepeat: piece in pieces -->
    <div class="ng-scope" ng-repeat="piece in pieces">
      <div class="piece-form" max-documents-authorized="maxDocumentsAuthorized" validate="savePersistence()">Third piece</div>
    </div>
    
</div>

 

 

I am trying to achieve custom object identifying. If I manage to changed HTML to something like this (see following code), is there any chance I could have TestComplete to identify each of my divs ?

 

 

<div ng-controller="simplePiecesController" class="pieces-list ng-scope"><br>
    
    <!-- ngRepeat: piece in pieces -->
    <div class="ng-scope" ng-repeat="piece in pieces" ng-reference="first-piece">
      <div class="piece-form" max-documents-authorized="maxDocumentsAuthorized" validate="savePersistence()">First piece</div>
    </div>
    
    <!-- ngRepeat: piece in pieces -->
    <div class="ng-scope" ng-repeat="piece in pieces" ng-reference="second-piece">
      <div class="piece-form" max-documents-authorized="maxDocumentsAuthorized" validate="savePersistence()">Second piece</div>
    </div>
    
    <!-- ngRepeat: piece in pieces -->
    <div class="ng-scope" ng-repeat="piece in pieces" ng-reference="third-piece">
      <div class="piece-form" max-documents-authorized="maxDocumentsAuthorized" validate="savePersistence()">Third piece</div>
    </div>
    
</div>

 

 

I would like to use NameMapping, but unfortunately, TestComplete Object Spy wont let me access this ng-reference custom property... And I can't find any documentation about extending Object property without dealing with SDK !

 

I don't want to use NameMapping hierarchy since it might change often and is kind of dynamic... I would rather use extend find property... Furthermore, I don't want to force developers to add ID or Class property (since it is not angular philosophy) !

 

Any help would be greatly appreciated !

 

Best regards,

 

Guillaume.

10 Replies

  • Lage's avatar
    Lage
    Contributor

    Hi,

     

    Would be possible for you locate the panel using the contentText? I know that is not the best way but may work....

     

    Temember that we can use ***, then you only have to look for a title or a piece of text. 

    In this case you will have to use the Extended find

     

    2015_05_19_ngRepeat_First.png

     

    Regards

    Lage

    • dganov's avatar
      dganov
      Staff

      There is one tricky way to use custom attributes in Name Mapping.

      1. Map the object of interest using auto name mapping.

      All the following steps are to be made on the Name Mapping panel.

      2. Find and select this mapped node in Mapped Objects tree.

      3. Change its ObjectType property value to something like "MyPanel", so that the node could not be found using the specified properties anymore.

      4. Double-click this node - you should see the "Unable to find the object..." dialog. Select "Edit the identification properties..." item. "Update Name Mapping" dialog should appear.

      5. Delete all properties from the Selected list using "fast forward" button.

      6. Click "Add Property" button, in the Name field specify "ng-reference", in the Type select "Sting", in the Value specify "first-piece" (or another value that corresponds to the node being edited), and click OK. Click Finish in the dialog. If you will see the message that object cannot be found the just click Yes to save settings.

      7. Try to highlight this node on screen - TestComplete should find it using new settings.

      8. If everything is fine, then you can check "Extended find" for this node, as well as move it to some higher level in the Name Mapping tree (using drag-and-drop), and delete all unnecessary automatically created nodes.

  • AlexKaras's avatar
    AlexKaras
    Champion Level 3

    Hi Guillaume,

     

    Another possible approach is to use the .EvaluateByXPath()/.FindChildByXPath() method (if you succeed to append the ng-reference="first-piece to the final html markup). Might appear to be quite convenient if you can identify some parent element not far from the sought for object.

    • theraud-g's avatar
      theraud-g
      Occasional Contributor

      Hi again.

       

      Thanks for your answers. 

       

      @lage: I would rather avoid using textContent. I assume I can not base my object recognition using innerHTML. There are two many elements (ancestors) that will contains the specify HTML code. Beside, I think it might take longer to parse DOM using regexp.

       

      @dganov: Thanks. Indeed, that might help ! I actually never tried to add a non-existing property to identify a object in NameMapping. It is a bit tricky but it would do the job. 

       

      @alex: I would also avoid using EvaluateByXPath. I use Keyword Test and I avoid as much as possible script as it become difficult to understand and maintain test case. I assumed xpath/css selector would work, but I am trying to use namemapping.

       

      Since @dganov answers actually works, I am still wondering how could I have TestComplete Object Browser to add specific property added to Extended Properties...

       

      For instance, the following code actually works. I guess TestComplete NameMapping implementation actually uses a similar mechanism to retrieve element.

       

        var PropArray = new Array("ng-repeat", "Visible");
        var ValuesArray = new Array("*", true);
        var ngRepeats = Aliases.theBrowser.page.FindAllChildren(PropArray, ValuesArray, 50, true);
        ngRepeats = (new VBArray(ngRepeats)).toArray();
        for(var idx = 0; idx < ngRepeats.length; idx++ ){
          Log.Message(ngRepeats[idx].getAttribute("ng-repeat"))
        }

      Are there any other solution (less tricky and time consumming) that would let me configure TestComplete in order to directly provide some property within Object Browser and NameMapping ?! If ng-repeat (or ng-reference, or anything else I would like to configure) attribute exists, then add it to Extended Property !

       

      I tried Open Applications / Web Testing / Object Identification but that is not what I am looking for.

       

      Thanks !

       

      Guillaume

       

      • dganov's avatar
        dganov
        Staff

        I know about another trick, but I did not find any documentation on it, so use it at your own risk :smileywink:

        There is "tcWebTestingRules.xml" configuration file in the "TestComplete 10\Bin\Extensions" folder.

        To add "ng-reference" to the list of properties that can be used when mapping Panel (div) objects, you should find the following comment

        <!-- FORM SPECIFIC -->

        and right before it insert the following code:

        	<!-- PANEL SPECIFIC -->
        		<MapOnAnyLevelRule>
        			<Recognition>
        				<True Name="canBeMappedOnAnyLevel" />
        				<Eq Name="ObjectType" Value="Panel" />
        			</Recognition>
        
        			<Optional>ng-reference</Optional>
        		</MapOnAnyLevelRule>

        Then restart TestComplete, and after that auto mapping of Panels should use the "ng-reference" attribute as well.

        Don't forget to backup the original file :smileyhappy: