1. #1
    Sencha Premium Member
    Join Date
    Oct 2012
    Posts
    6
    Vote Rating
    0
    mihaichiritescu is on a distinguished road

      0  

    Default ExtJS functional testing - get internal elements of extjs controls

    ExtJS functional testing - get internal elements of extjs controls


    Hello everyone,

    We have decided to use Sencha ExtJS for the client side of our new products and we plan to do automated functional testing on the client side. We looked into several tools like Ranorex, Selenium, Telerik Test Studio etc and so far we like Test Studio more than the others. Anyway, the question I am asking is relevant no matter which of these tools one might use.

    I am interested to find out what is the recommended way to get internal elements of extjs controls. In order to be clear enough I will give an example.

    I have a numberfield control and I would like to test that if I clicked on the 'up' button the value in the field will increase by one unit. Note that I did set an unique ID to the number field (id="testDurationHourNumberField"). The number field has the following (simplified) DOM structure:

    Code:
    <table id="testDurationHourNumberField">
        <tbody>
            <tr id="testDurationHourNumberField-inputRow">
                <td id="testDurationHourNumberField-labelCell">
                    <label id="testDurationHourNumberField-labelEl">Label:</label>
                </td>
                <td id="testDurationHourNumberField-bodyEl">
                    <table id="testDurationHourNumberField-triggerWrap">
                        <tbody>
                            <tr>
                                <td id="testDurationHourNumberField-inputCell">
                                    <input id="testDurationHourNumberField-inputEl">
                                </td>
                                <td>
                                    <div role="button" id="ext-gen1211"></div>
                                    <div role="button" id="ext-gen1212"></div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
        </tbody>
    </table>
    In order to do this I must access the input element (id="testDurationHourNumberField-inputEl") and the button (id="ext-gen1211"). How is the recommended way of accessing these 2 elements?

    So far I have the following options:
    • Use ExtJS internal IDs - does NOT seem good because:
      • These are internal IDs, they are out of my control and they may change if I will later add another control on the page
      • It seems that for the same page I get different IDs in different browsers. For example in IE 10 I get different IDs for the buttons from the IDs I get in Google Chrome.
    • Get controls by unique ID and get internal elements by knowing their internal DOM structure or attributes - does NOT seem good because:
      • I would rather not use this way because I do not know that when upgrading to the next version of ExtJS the internal DOM structure won't change or some attribute names will change and I will have to update the tests that I created
      • eg pseudocode: getById('testDurationHourNumberField').getElementByAttributeAndIndex('role=button', 0)
    Can you please let me know which is the recommended way to do this?

    Thanks,
    Paul

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    36,812
    Vote Rating
    835
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Each component has an el property on itself when it has been rendered. That Element class can use the down/query methods to resolve other elements...

    comp.el.down('input') to get the <input>
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  3. #3
    Sencha Premium Member
    Join Date
    Aug 2011
    Posts
    59
    Vote Rating
    4
    ids is on a distinguished road

      0  

    Default


    I had the same problem some time ago, so I decided to add CSS-Classes for all Components (cls-Property).
    For me every...
    - View has a reference, so I add "prefix-ref-reference"
    - Field has a name, so I add "prefix-name-name"
    Now for the CSS-Selector I simply put those together ".prefix-ref-reference .prefix-name-name .x-form-field", that's it!

  4. #4
    Sencha Premium Member
    Join Date
    Oct 2012
    Posts
    6
    Vote Rating
    0
    mihaichiritescu is on a distinguished road

      0  

    Default


    Quote Originally Posted by ids View Post
    I had the same problem some time ago, so I decided to add CSS-Classes for all Components (cls-Property).
    For me every...
    - View has a reference, so I add "prefix-ref-reference"
    - Field has a name, so I add "prefix-name-name"
    Now for the CSS-Selector I simply put those together ".prefix-ref-reference .prefix-name-name .x-form-field", that's it!
    Thanks for the solution!
    Still this seems to be based on some internal class of Extjs, in this case "x-form-field". If, on a later upgrade of ExtJS, this class will be removed than the test suites will fail, so there is a risk of backwards compatibility. But hopefully that class won't be removed or renamed too soon so this might work.

    Do you have a similar solution for the elements that are not fields? The solution proposed seems to work only for fields...like for buttons, I did not see a similar class, other than "x-btn-center", that is set on the "button" html element.

    Regards,
    Paul

  5. #5
    Sencha Premium Member
    Join Date
    Oct 2012
    Posts
    6
    Vote Rating
    0
    mihaichiritescu is on a distinguished road

      0  

    Default


    Quote Originally Posted by mitchellsimoens View Post
    Each component has an el property on itself when it has been rendered. That Element class can use the down/query methods to resolve other elements...

    comp.el.down('input') to get the <input>
    In my post I said that I am aware of a similar solution, which is to get internal elements by knowing the internal structure of extjs controls. Also in my post I explained why I do not like this solution very much. Is there any other way of doing this without relying on something internal to ExtJS that I have no idea when it will change?

    Regards,
    Paul

  6. #6
    Sencha - Community Support Team mankz's Avatar
    Join Date
    Nov 2007
    Location
    Stockholm, Sweden
    Posts
    2,739
    Vote Rating
    104
    mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all

      0  

    Default


    Paul, did you try Siesta? It tries to solve this exact issue. Using Siesta, you can target components, component queries, CSS selectors etc which makes it so much easier to do functional testing.

  7. #7
    Sencha Premium Member
    Join Date
    Oct 2012
    Posts
    6
    Vote Rating
    0
    mihaichiritescu is on a distinguished road

      0  

    Default


    Hi,

    I am aware of Siesta but using it would mean that we have to manually code the test suites.
    We are more interested in using some tools that incorporate an action recorder (eg. Telerik Test Studio, Selenium, RiaTest), which means that the user records the tests and just plays them afterwards. This way these test suites can be done by our QA engineers without much manual code being involved.

    The issue is that these tools operate on the DOM but ExtJS actually generates the DOM so I have no guarantee that the tests I recorded will still work after I change some parts of the GUI or I upgrade ExtJS.

    I am asking on this thread for the recommended generic way of getting internal elements of ExtJS controls so I might be able to create a plugin for these automation tools or alter the way the action recorders generate code - to make life easier for QA engineers.

    Thanks,
    Paul

  8. #8
    Sencha Premium Member
    Join Date
    Oct 2012
    Posts
    6
    Vote Rating
    0
    mihaichiritescu is on a distinguished road

      0  

    Default


    I am thinking right now of another solution...
    The solution would imply that we can override the way ExtJS generates IDs. Is there any support for this?

    As an example, let's say I have a number field, and programatically I will set the ID = "testDurationHourNumberField". Currently ExtJS generates the following DOM structure:

    HTML Code:
    <table id="testDurationHourNumberField">
        <tbody>    
            <tr id="testDurationHourNumberField-inputRow">        
                <td id="testDurationHourNumberField-labelCell">            
                    <label id="testDurationHourNumberField-labelEl">Label:</label>        
                </td>
                <td id="testDurationHourNumberField-bodyEl">            
                    <table id="testDurationHourNumberField-triggerWrap">                
                        <tbody>                      
                            <tr>                        
                                <td id="testDurationHourNumberField-inputCell">                            
                                    <input id="testDurationHourNumberField-inputEl">                        
                                </td>                        
                                <td>                            
                                    <div role="button" id="ext-gen1211"></div>                            
                                    <div role="button" id="ext-gen1212"></div>                        
                                </td>                    
                            </tr>                
                         </tbody>            
                    </table>
                </td>    
            </tr>
        </tbody>
    </table>
    I would like, if possible, to have the ID that I set programatically as a base ID for all internal elements within the number field control.
    This would mean, that I would somehow be able to specify that the up and down buttons will have the IDs "testDurationHourNumberField-upButton" and "testDurationHourNumberField-downButton".
    In other words, I want to get rid of all these ugly ExtJS generated ID like "ext-gen-1500", which don't mean anything. The desired DOM structure with the nice IDs would be the following:

    HTML Code:
    <table id="testDurationHourNumberField">
        <tbody>    
            <tr id="testDurationHourNumberField-inputRow">        
                <td id="testDurationHourNumberField-labelCell">            
                    <label id="testDurationHourNumberField-labelEl">Label:</label>        
                </td>
                <td id="testDurationHourNumberField-bodyEl">            
                    <table id="testDurationHourNumberField-triggerWrap">                
                        <tbody>                      
                            <tr>                        
                                <td id="testDurationHourNumberField-inputCell">                            
                                    <input id="testDurationHourNumberField-inputEl">                        
                                </td>                        
                                <td>                            
                                    <div role="button" id="testDurationHourNumberField-upButton"></div>                            
                                    <div role="button" id="testDurationHourNumberField-downButton"></div>                        
                                </td>                    
                            </tr>                
                         </tbody>            
                    </table>
                </td>    
            </tr>
        </tbody>
    </table>
    This is a way to avoid randomly generated IDs and at the same time keeps IDs the same no matter what browser I am using.
    I would actually suggest that ExtJS switches to this approach as I do not see any flaws right now and evidently would have the customers happier (as there are many complaining about this!)

    Can the ExtJS dev team tell me if overriding the way ExtJS names the IDs is possible?

    Thanks,
    Paul