Tutorial: Custom Library

Top  Previous  Next

In this section, you will learn how to create a Custom Library and add support for a third-party GUI control to SmarteStudio.  We will be using a demo application called CustomControlApp. Our Custom Library  will be simple.  It will allow to  Record and Learn objects of CustomListboxControl type and also Playback actions for this type of objects. This tutorial is complemented by a ready test CustomControlTest which you'll be able to examine and run.

 

Tutorial Data

CustomControlApp folder: C:\Program Files\SmarteSoft\SmarteStudio\Samples\Extensibility\CustomLibrary\CustomControlApp. You may build this application yourself in Microsoft Visual Studio (C++) or use ready executable: <CustomControlApp folder>\Release\CustomControlApp.exe
CustomControlTest folder: C:\Program Files\SmarteSoft\SmarteStudio\Samples\Extensibility\CustomLibrary\CustomControlTest
CustomLibrary file: C:\Program Files\SmarteSoft\SmarteStudio\Samples\Extensibility\CustomLibrary\CustomLibrary.js

 

If you prefer active experimentation learning style you may first skip to subsection 9 and after playing with the ready test and library start reading from the beginning.

 

1.Application Under Test

CustomControlApp contains an object of type CustomListboxControl. The control is similar to a single-select listbox, but each line item has a corresponding progress bar indicator indicating a current value. Using the left/right cursor keys you can change the value of the currently focused item.

customcontrolapp

 

If you will try to record a test for CustomControlApp using just Generic library you'll see that CustomListboxControl is treated as Simulated Object and all interactions with it are recorded as mouse clicks and key presses. For some tests such functionality is sufficient, but if you want to be able to recognize CustomListboxControl as a list, get its items, select an item by name, set value for a particular item you need to create a Custom Library.

customcontrolapp, simulated object

 

2.LibUser

A good place to start implementing a Custom Library is empty LibUser library included into SmarteStudio. All SmarteStudio libraries live in C:\Program Files\SmarteSoft\SmarteStudio\Engine\Lib folder and LibUser is not an exception. LibUser library consists of two files:

1.C:\Program Files\SmarteSoft\SmarteStudio\Engine\Lib\LibUser.jslib which is a library declaration file.
2.C:\Program Files\SmarteSoft\SmarteStudio\Engine\Lib\LibUser\LibUser.js which is a library definition file.

 

3.Open Engine.sstest

Open Engine.sstest project in SmarteStudio. Then find LibUser.js in the project tree and open it. You are about to start implementing a Custom Library to support CustomListboxControl.

libuser, engine

 

4.Analyze CustomListboxControl in Spy

Launch CustomControlApp and open Spy. Spy on CustomListboxControl. It is easy to see that CustomListboxControl has the following accessibility tree: ROLE_SYSTEM_WINDOW top node contains ROLE_SYSTEM_LIST child that in its turn may contain zero to many ROLE_SYSTEM_SLIDER nodes.

spy, customlistboxcontrol

 

5.Create Matcher Rule for CustomListboxControl

With knowledge of CustomListboxControl accessibility tree we can create a matcher rule that will make CustomListboxControl recognizable by SmarteStudio. Write the following code into LibUser.js:

new SeSMatcherRule(

{

    object_type: "CustomListboxControl",

    object_flavor: "List",

    behavior: [Win32ItemSelectable, Win32CustomListboxControl],

    role: "ROLE_SYSTEM_WINDOW",

    or_rules: [

        {

            role: "regex:ROLE_SYSTEM_LIST",

            save_to: "list",

            or_rules: [

                {

                    role: "ROLE_SYSTEM_SLIDER",

                    zero_to_many: true,

                    save_to: "items"

                }

            ]

        }

    ]

});

 

Each matcher rule (instance of SeSMatcherRule) is a tree like structure that describes a particular GUI control type. Each node in this tree is a rule object that is defined by the following simplified grammar:

or_rules: (rule)+

and_rules: (rule)+

 

rule: 

    role

    [save_to]

    [zero_to_many]

    [or_rules]

    [and_rules]

 

object_type: the string that uniquely identifies this matcher rule and designates type of the control
object_flavor: visual type of the control, it is used to show an appropriate icon in the Object Tree and to filter actions and properties in composite behavior patterns (like in Adobe Flex, see FlexActions.js)
behavior: array of behavior patterns that define object actions, properties and events.
role: accessibility role of the corresponding node in the accessibility tree of the control. The role equals to a Role of the accessible element as displayed in the Spy.
or_rules: array of rules (defining child nodes) joined with logical OR. Any OR rule can be satisfied to consider child nodes matched.
and_rules: array of rules (defining child nodes) joined with logical AND. All AND rules must be satisfied to consider child nodes matched.
save_to: SeSObject created for accessibility tree node corresponding to this rule is assigned to the field with "save_to" name of the top level SeSObject. I.e. if rule has save_to: "items" element then you can access learned element using SeS('ObjID').items. In many cases such named fields are used in behavior patterns.
zero_to_many: if this property is present in the rule and set to 'true' then it means that parent rule may contain from zero to many of child nodes that match this rule.

 

6.CustomListboxControl Behavior

After defining the matcher rule we can proceed to behavior patterns. Behavior patterns operate with SeSObject contents, so they should not be aware about accessibility tree of the underlying GUI control and thus the same behavior pattern can be assigned to different matcher rules. There are a plenty of behavior patterns defined in SeSBahavior.js. After looking at those patterns it is possible to notice that Win32ItemSelectable pattern is the one that perfectly suites for capturing selection accessibility events and for selecting list items. This pattern contains OnSelect event that is called during recording when an item is selected in list and DoSelectItem action used to select desired item during playback.

 

But using just Win32ItemSelectable behavior pattern is not sufficient. It does not support recording of progress bar value change events and it does not support setting progress bar value during playback. That is why we need to define new behavior pattern: Win32CustomListboxControl. Look at its code:

 

var Win32CustomListboxControl = 

{

    actions: [

        {

            actionName: "SetItemValue",

            DoAction: function(/**String*/ itemName, /**Number*/ value)

            {

                var item = this.findItemByName(itemName);

                if(null!=item)

                {

                    item.getTopObject().instance.HWND.SetForegroundWindow();

                    item.instance.Value = value;

                    return true;

                }

                return false;

            }

        },

        {

            actionName: "GetItemValue",

            DoAction: function(/**String*/ itemName)

            {

                var item = this.findItemByName(itemName);

                if(null!=item)

                {

                    return item.instance.Value

                }

                return null;

            }

        }

    ],

    events:

    {

        OnValueChange: function(/**SeSObject*/ param)

        {

            var itemName = param.name;

            if(l2)Log2("OnValueChange:"+itemName);

            var item = this.findItemByName(itemName);

            if(null!=item)

            {

                var value = item.instance.Value;

                RegisterAction(this, param.name, "SetItemValue", parseInt(value), "Set item:'"+param.name+"' to "+value+" in '"+this.name+"'");

            }            

            return;

        }

    }

};

 

 

 

During recording process OnValueChange function captures progress bar change events and calls RegisterAction function that adds SetItemValue action to the test.

 

7.CustomListboxControl Specific Accessibility Events

 

What accessibility events are fired when user changes progress bar value? Use Spy to find out. Launch CustomControlApp and open Spy window. Spy on CustomListboxControl. Choose Monitor Events...

spy, customlistboxcontrol, monitor events

 

You will see Accessible Events dialog:

customcontrolapp, accessible events

 

Select an item in CustomControlApp and advance its progress bar using right key. Accessible Events dialog will show you captured events:

customcontrolapp, accessible events filled

 

You can see that changing progress bar leads to generation of EVENT_OBJECT_VALUECHANGE events.

 

Not all accessibility events a processed and propagated by SmarteStudio engine. EVENT_OBJECT_VALUECHANGE is one of such events. To consume this event and make an appropriate call to  OnValueChange of Win32CustomListboxControl you need to add and register custom accessibility event handler:

function CustomRegisterAccessibleEvent(evt, etxt)

{

    if(etxt.indexOf("EVENT_OBJECT_VALUECHANGE")>=0)

    {

        var ao;

        try

        {

            ao = evt.AccessibleObject;

            if(!_SeSisValidObject(ao)) return false;

        }

        catch(e)

        {

            Log("Error getting event object:"+e.Description+"/"+etxt);

            return false;

        }

        

        var ro = SeSCacheAccessibleObject(ao);

        if (l3 && ro) Log3("CustomListboxControl: " + ro.toString());

        

        if (ro != null && ("OnValueChange" in ro))

        {

            ro.OnValueChange();

        }

        

        return true;

    }

    return false;

}

 

g_customEventHandlers.push(CustomRegisterAccessibleEvent);

 

8. Record and Playback

Now you are ready to record and playback a test. Just remember that in Select an Application to Record dialog you need to uncheck Auto library and select User and Generic libraries.

generic, libuser

 

 

9.CustomControlTest

This tutorial is complemented by a ready test CustomControlTest which you can examine and run. Open CustomControlTest in SmarteStudio and place contents of CustomLibrary file into LibUser.js file (C:\Program Files\SmarteSoft\SmarteStudio\Engine\Lib\LibUser\LibUser.js). LibUser.js is added to CustomControlTest, so you can populate it with CustomLibrary code right in SmarteStudio.

 

custom library test

 

Tip: It is possible to launch CustomControlApp right from SmarteStudio, just double click on CustomControlApp.exe in the project tree.

 

10. Wrap-up: Implementation Sequence

Full support for a custom object requires support for Record, Learn and Playback. Let's go over created library and specify the purpose of each component in it.

 

Matcher Rule:- it is used to recognize the object inside an application, required for Record, Learn and Playback.
Events in Behavior Patterns: handling events is required for Record.
Actions in Behavior Patterns: actions are used to examine or change state of the control, required for Playback.
Custom Accessibility Event Handler: required for Record if some important events are not processed by SmarteStudio engine as needed.