Implementing Automation Support for a Custom Control

Before you can test a custom control, implement automation support (the automation delegate) in ActionScript for the custom control and compile that into the test application.

The following procedure uses a custom Flex spinner control to demonstrate how to implement automation support for a custom control. The spinner custom control includes two buttons and a textfield, as shown in the following graphic.

Flex custom control

The user can click Down to decrement the value that is displayed in the textfield and click Up to increment the value in the textfield.

The custom control offers a public "Value" property that can be set and retrieved.

  1. Implement automation support (the automation delegate) in ActionScript for the custom control. For further information about implementing an automation delegate, see the Adobe Live Documentation at http://livedocs.adobe.com/flex/3/html/help.html?content=functest_components2_14.html. In this example, the automation delegate adds support for the methods "increment", "decrement". The example code for the automation delegate looks like this:
    package customcontrols
    {
    	import flash.display.DisplayObject;
    	import mx.automation.Automation;
    	import customcontrols.SpinnerEvent;
    	import mx.automation.delegates.containers.BoxAutomationImpl;
    	import flash.events.Event;
    	import mx.automation.IAutomationObjectHelper;
    	import mx.events.FlexEvent;
    	import flash.events.IEventDispatcher;
    	import mx.preloaders.DownloadProgressBar;
    	import flash.events.MouseEvent;
    	import mx.core.EventPriority;
    	
    	[Mixin]
    	public class SpinnerAutomationDelegate extends BoxAutomationImpl
    	{
    		
    		public static function init(root:DisplayObject) : void {
    			// register delegate for the automation
    			Automation.registerDelegateClass(Spinner, SpinnerAutomationDelegate);
    		}   
    		
    		public function SpinnerAutomationDelegate(obj:Spinner) {
    			super(obj);
    			// listen to the events of interest (for recording)
    			obj.addEventListener(SpinnerEvent.DECREMENT, decrementHandler);
    			obj.addEventListener(SpinnerEvent.INCREMENT, incrementHandler);
    		}
    		
    		protected function decrementHandler(event : SpinnerEvent) : void {
    			recordAutomatableEvent(event);	
    		}
    		
    		protected function incrementHandler(event : SpinnerEvent) : void {
    			recordAutomatableEvent(event);
    		}
    		
    		protected function get spinner() : Spinner {
    			return uiComponent as Spinner;
    		}
    		
    		//----------------------------------
    		//  override functions
    		//----------------------------------
    		
    		override public function get automationValue():Array {
    			return [ spinner.Value.toString() ];
    		}
    		
    		private function replayClicks(button : IEventDispatcher, steps : int) : Boolean {
    			var helper : IAutomationObjectHelper = Automation.automationObjectHelper;
    			var result : Boolean;
    			for(var i:int; i < steps; i++) {
    				helper.replayClick(button);
    			}
    			return result;
    		}
    		
    		override public function replayAutomatableEvent(event:Event):Boolean {
    			
    			if(event is SpinnerEvent) {
    				var spinnerEvent : SpinnerEvent = event as SpinnerEvent;
    				if(event.type == SpinnerEvent.INCREMENT) {
    					return replayClicks(spinner.upButton, spinnerEvent.steps);
    				}
    				else if(event.type == SpinnerEvent.DECREMENT) {
    					return replayClicks(spinner.downButton, spinnerEvent.steps);
    				}
    				else {
    					return false;
    				}
    				
    			}
    			else {
    				return super.replayAutomatableEvent(event);
    			}
    		}
    		
    		// do not expose the child controls (i.e the buttons and the textfield) as individual controls 
    		override public function get numAutomationChildren():int {
    			return 0;
    		}	
    		
    	}
    }
  2. To introduce the automation delegate to the Open Agent, create an XML file that describes the custom control. The class definition file contains information about all instrumented Flex components. This file (or files) provides information about the components that can send events during recording and accept events for replay. The class definition file also includes the definitions for the supported properties. The XML file for the spinner custom control looks like this:
    <?xml version="1.0" encoding="UTF-8"?>
    <TypeInformation>
    	<ClassInfo Name="FlexSpinner" Extends="FlexBox">
    		<Implementation
    			Class="customcontrols.Spinner" />
    		<Events>
    			<Event Name="Decrement">
    				<Implementation
    					Class="customcontrols.SpinnerEvent"
    					Type="decrement" />
    				<Property Name="steps">
    					<PropertyType Type="integer" />
    				</Property>
    			</Event>
    			<Event Name="Increment">
    				<Implementation
    					Class="customcontrols.SpinnerEvent"
    					Type="increment" />
    				<Property Name="steps">
    					<PropertyType Type="integer" />
    				</Property>
    			</Event>
    		</Events>
    		<Properties>
    			<Property Name="lowerBound" accessType="read">
    				<PropertyType Type="integer" />
    			</Property>
    			<Property Name="upperBound" accessType="read">
    				<PropertyType Type="integer" />
    			</Property>
    			<!-- expose read and write access for the Value property -->
    			<Property Name="Value" accessType="both">
    				<PropertyType Type="integer" />
    			</Property>
    			<Property Name="stepSize" accessType="read">
    				<PropertyType Type="integer" />
    			</Property>
    		</Properties>
    	</ClassInfo>
    </TypeInformation>
  3. Include the XML file for the custom control in the folder that includes all the XML files that describe all classes and their methods and properties for the supported Flex controls. Silk Test contains several XML files that describe all classes and their methods and properties for the supported Flex controls. Those XML files are located in the <<Silk Test_install_directory>\ng\agent\plugins\com.borland.fastxd.techdomain.flex.agent_<version>\config\automationEnvironment folder. If you provide your own XML file, you must copy your XML file into this folder. When the Open Agent starts and initializes support for Apache Flex, it reads the contents of this directory. To test the Flex Spinner sample control, you must copy the CustomControls.xml file into this folder. If the Open Agent is currently running, restart it after you copy the file into the folder.
You can now record and playback visual tests or scripts that include the custom control.