A lot of websites use Flash to improve the user interface. The ability to pimp up a web page with flash is great, it looks excellent and often better than simple HTML pages. But the ability to test Flash pages is poor. In this tutorial I try to explain a way to test flash objects with javascript and selenium.
Preconditions:
The steps described in this tutorial were done with selenium-core 0.8.2-SNAPSHOT and selenium-rc 0.9.1-SNAPSHOT and executed on an IE6.
To test Flash Objects it is necessary to know the "internals" of the flash object and you must have the ability to add some code to the flash object. You cannot test any flash you find in the net, it must be yours!
Flash and Javascript:
Flash objects on a webpage are accessable by some javascript functions. We will use only three of them:
- GetVariable(varName)
- SetVariable(varName, varValue)
- TCallLabel(target, label)
A full list is found on the adobe site
First I explain how Flash variables are accessed by javascript:
Assume you have embedded a flash object on the webpage with
<object name="flashTest" codebase="..."></object>
To get the value of a variable inside the flash object, you have to call a javascript function like this
function getFlashVariable(varName) {
flashObj = window.document.getElementById( 'flashTest' );
return flashObj.GetVariable(varName);
}
To set a value:
function setFlashVariable(varName,varValue) {
flashObj = window.document.getElementById( 'flashTest' );
return flashObj.SetVariable(varName,varValue);
}
To call a flash function, e.g. to simulate the click on a button, a flash function like button.onRelease must be called. Our Flash developer added a label to all Flash objects, which calls a function via reflection ( see below ) . To call this label - and execute the designated function - use this javascript function:
function execFlashMethod( methodName, paramList) {
flashObj = window.document.getElementById( 'flashTest' );
flashObj.SetVariable("buttonClickFunction", methodName);
flashObj.SetVariable("buttonClickTarget",paramList);
flashObj.TCallLabel("/", "clickIt");
};
Add the following code to your flash. The code must reside on the label clickIt.
buttonClickTarget = buttonClickTarget.split(",");
for (var x = 0; x<buttonClickTarget.length; x++) {
if (buttonClickTarget[x] == "true") {
buttonClickTarget[x] = true;
} else if (buttonClickTarget[x] == "false") {
buttonClickTarget[x] = false;
} else if (Number(buttonClickTarget[x])) {
buttonClickTarget[x] = Number(buttonClickTarget[x]);
}
}
eval(buttonClickFunction).apply(null, buttonClickTarget);
Now we are able to set and get values of variables and to execute functions inside a flash object via javascript.
Adding the stuff to selenium:
The next step explains how to inject the 3 javascript functions to selenium.( selenium-core 0.8.1 and selenium-rc 0.9.1)
Add the javascript to selenium core
As these functions are not builtin functions of selenium core, we have to add them manually. In the selenium-core project the folder javascript/core/scripts contains the js file selenium-api.js. Find a apropiate location for the new functions ( add them after the last Selenium.prototype function) and put them there.
Note: Before we start, I have to mention that selenium-rc has problems calling javascrip functions with more than two parameters. As we need three parameters for the setVariable and executeMethod function, I assume the name of the flash object is flashTest. Then we can reduce the number of parameters to 2.
Selenium.prototype.getFlashVariable = function(locator,varName ) {
/**
* Returns the value of a variable inside the flash object.
*
* @param locator the locator of the flash object
* @param varName the name of the variable
* @return string the value of the variable
*/
var flashObj = this.page().findElement(locator);
return flashObj.GetVariable(varName);
}
Selenium.prototype.doSetFlashTestVariable= function(flashVarName,varValue) {
/**
* Sets a variable inside the flash object.
*
* @param flashVarName the name of the variable
* @param varValue the value of the variable
*/
var flashObj = this.page().findElement("flashTest")
flashObj.SetVariable(varName, varValue );
}
Selenium.prototype.doExecuteFlashMethod = function(methodName,paramList ) {
/**
* Executes a method in the flash object identified by the locator. This
* is NOT a standard flash function. The flash must be contain function clickIt
* which reads the parameter buttonClickFunction and buttonClickTarget and calls the
* named function via reflection.
*
* @param methodName the name of the method to call
* @param paramList a comma separated list of parameters
*/
var flashObj = this.page().findElement("flashTest");
flashObj.SetVariable("buttonClickFunction", methodName);
flashObj.SetVariable("buttonClickTarget",paramList);
flashObj.TCallLabel("/", "clickIt");
}
That's all for selenium.core, so build it now.
After that a full build of the selenium-rc server and client (in this example the java client) generates additional functions.
The Java Client should contain three extra methods:
void setFlashVariable(String flashVarName,String varValue);
String getFlashVariable(String locator,String varName);
void executeFlashTestMethod(String methodName,String paramList);
Now you are able to write a test with the java client which accesses variables in the flash object and executes some methods. E.g. to click on a button named buttonTest call the function buttonTest.onRelease with
executeFlashTestMethod("buttonTest.onRelease","");
The click on the button will be simulated by the javascript stuff.
One tip to read arrays: if you have an array in your flash object like
You can read the 5.th element of the result array with:
getFlashVariable("flashTest","result:5");
Start the new flash enabled selenium server and try it out!
Hi,
I'm using selenium rc and i need to test flash. In step Adding the stuff to Selenium (adding the 3 javascript functions to selenium) do i need install selenium core? if not, where in selenium rc do i add these three methods?
Just need some help getting started?