Accessibility

Table of Contents

Writing and running functional tests for Flash with Selenium RC

The FlashSelenium component

Selenium RC uses JavaScript to communicate with the browser. Flash ExternalInterface provides a mechanism for which you can use JavaScript to call an ActionScript function in a SWF file embedded in an HTML page. Therefore, we created FlashSelenium, a Selenium RC client extension that uses JavaScript as the conduit between Selenium RC and the Flash application (see Figure 2).

FlashSelenium with JavaScript connecting
to Flash ExternalInterface

Figure 2. FlashSelenium with JavaScript connecting to Flash ExternalInterface

FlashSelenium is the component that adds Flash communication capabilities to the Selenium framework. Basically, it is a Selenium RC client driver extension for helping execute the tests against the Flash component. The FlashSelenium constructor takes a Selenium instance and a Flash object ID as parameters.

An instance of FlashSelenium is used to invoke the functions on the Flash component. You can invoke functions that were externalized by the ExternalInterface, as well as the default functions of any Flash SWF (for example, isPlaying, PercentLoaded and TotalFrames). FlashSelenium is currently available for Java, .NET, Ruby, and Python. Analogous components are being created for PHP.

Next we will show you a complete example of a Flash-based web application and its corresponding Selenium RC tests.

Sample web application

The sample web application is very simple. It consists of a web page with an embedded Flash SWF object. The title of the page is "Clicking Colors." The Flash SWF object presents a clickable rectangle that repaints itself (rotating colors green, blue and red) for every click. Try it out on our demonstration page.

Below is the source code for colors.html, the web application containing a Flash SWF object:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1" />
<title>Clicking Colors</title>
<body>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"
width="100" height="100" id="clickcolors" align="middle">
 <param name="allowScriptAccess" value="sameDomain" />
 <param name="movie" value="ColoredSquare.swf" />
 <param name="quality" value="high" />
 <param name="bgcolor" value="#ffffff" />
 <embed src="ColoredSquare.swf" quality="high" bgcolor="#ffffff" width="500" height="500" name="clickcolors" align="middle" allowscriptaccess="*" type="application/x-shockwave-flash" pluginspage="/go/getflashplayer" />
</object>
</body>
</html>

Note that the Flash SWF object ID, clickcolors, will be used by the Selenium RC test.

Below is ColoredSquare.as, the source code for the Flash SWF component embedded in the web application:

package {
  import flash.display.Sprite;
  import flash.events.MouseEvent;
  import flash.external.ExternalInterface;
  import flash.text.TextField;
  import flash.text.TextFieldAutoSize;
  import flash.text.TextFormat;
 
  public class ColoredSquare extends Sprite {
    private const COLOR_HEX_VALUES:Array = [0×00ff00, 0×0000ff, 0xff0000];
    private const COLORS:Array = ["GREEN", "BLUE", "RED"];
    private const SQUARE_SIDE:uint = 500;
    private var currentColor:uint;
    private var currentColorIndex:uint = 0;
    private var buttonSprite:Sprite = new Sprite();
    private var squareLabel:String = "(Click here)";
    private var label:TextField = new TextField();
 
    public function ColoredSquare() {
      currentColor = COLOR_HEX_VALUES[currentColorIndex % 3];
      updateButtonLabel();
      drawButton();
      addEventListener(MouseEvent.CLICK, buttonClicked);
    
      // functions available for JavaSript calls
      ExternalInterface.addCallback("getColor", getColor);
      ExternalInterface.addCallback("click", changeColor);
      ExternalInterface.addCallback("getSquareLabel", getSquareLabel);
      ExternalInterface.addCallback("setSquareLabel", setSquareLabel);
    }
 
    private function buttonClicked(event:MouseEvent):void {
      changeColor();  
    }
 
    private function changeColor():void {
      currentColorIndex++;
      currentColor = COLOR_HEX_VALUES[currentColorIndex % 3];
      this.squareLabel = COLORS[currentColorIndex % 3];
      updateButtonLabel();
      drawButton();
    }
 
    private function updateButtonLabel():void {
      var format:TextFormat = new TextFormat();
      format.size = SQUARE_SIDE / 10;
      var label:TextField = new TextField();
      label.autoSize = TextFieldAutoSize.LEFT;
      label.selectable = false;
      label.defaultTextFormat = format;
      label.text = squareLabel;
      label.x = SQUARE_SIDE / 5;
      label.y = SQUARE_SIDE / 2.5;
      if (buttonSprite.contains(this.label)) {
        buttonSprite.removeChild(this.label);
      }
      this.label = label; 
      buttonSprite.addChild(this.label);  
    }
 
    private function drawButton():void {
      buttonSprite.graphics.beginFill(currentColor);
      buttonSprite.graphics.drawRect(0, 0, SQUARE_SIDE, SQUARE_SIDE);
      buttonSprite.graphics.endFill();
      addChild(buttonSprite);
    }
 
    public function setSquareLabel(squareLabel:String):void {
      this.squareLabel = squareLabel;
      updateButtonLabel();
      drawButton();
    }
 
    public function getColor():String {
      return COLORS[currentColorIndex % 3];
    }
 
    public function getSquareLabel():String {
      return this.squareLabel;
    }
  }
}

The following ChangeColor functions are made available for JavaScript invocation by means of the ExternalInterface: getColor, changeColor, getSquareLabel, and setSquareLabel:

// functions available for JavaSript call
ExternalInterface.addCallback("getColor", getColor);
ExternalInterface.addCallback("click", changeColor);
ExternalInterface.addCallback("getSquareLabel",
getSquareLabel);
ExternalInterface.addCallback("setSquareLabel",
setSquareLabel);