domingo, 13 de janeiro de 2008

Como testar funções que fazem chamadas javascript no actionscript?

No ActionScript é possível chamar funções javascript utilizando a função ExternalInterface.call. O problema é que essa função é estática, dificultando muito a criação de testes unitários para as funções que necessitam acessar esses recursos externos.

Para fazer isso é preciso isolar a chamada ao javascript em uma função, e no teste unitário substituir essa função por uma outra que apenas a substitua por uma comportamento esperado de acordo com o teste. Vamos ver como fazer isso:

Primeiro isolamos a chamada a ExternalInterface.call em um função que serviria apenas como proxy. Em linguagens menos dinâmicas precisaríamos isolar essa função em uma outra classe pois não seria possível substitui-la posteriormente:
public function executarJavaScript(funcao:String,parametros:Object = null) {
try {
return ExternalInterface.call(funcao,parametros);
} catch(erro:Error) {
return null;
}
}
A classe então que possui essa função precisa ser dinâmica, ou seja deve ter um modificador dynamic, e possuir um atributo da classe Function que recebe no construtor essa função que foi criada:
dynamic public class MinhaClasse {
public var js:Function;
function MinhaClasse() {
js = executarJavaScript;
}
public function executarJavaScript(funcao:String,parametros:Object = null) {
//Conteudo da função já exibido acima :P
}
//Outras funções
}
As demais funções da classe deverão usar então o atributo js como uma função para executar o recurso externo desejado. Veja um exemplo que recupera do javascript a URL onde o swf está sendo exibido:
public function obterUrlAtual():String {
try {
var objJs = js("document.location.href.toString");
if( !objJs ) objJs = js("document.location.toString");
if( !objJs ) return null;
return new String(objJs);
} catch(e:Error) {
return null;
}
}
Para criar um teste unitário com o ASUnit para esta função de exemplo basta configurar de diversas formas o atributo js da classe MinhaClasse de acordo com o comportamento que você deseja testar. Um exemplo é exibido abaixo:
public function testSegundFuncaoJavaScriptEhChamada():void {
var m:MinhaClasse = new MinhaClasse();
m.js = function(funcao:String,parametros:Object = null) {
if(funcao=="document.location.toString") {
return "http://programandosemcafeina.blogspot.com";
} else {
return null;
}
}
var s:String = m.obterUrlAtual();
assertEquals("Quando a primeira função retorna null a segunda função deve ser chamada","http://programandosemcafeina.blogspot.com",s);
}

Um comentário: