├── bin ├── robotEyes_0.1.swc └── roboteyesDemoAppRunner.swf ├── assets └── skins │ ├── roboteyes │ ├── ProjectSprouts.png │ ├── roboteyesDemoApp.fla │ └── roboteyesDemoApp.swf │ └── roboteyesDemoAppSkin.as ├── lib └── asunit3 │ ├── asunit │ ├── util │ │ ├── Iterator.as │ │ ├── ArrayIterator.as │ │ └── Properties.as │ ├── errors │ │ ├── AbstractError.as │ │ ├── ClassNotFoundError.as │ │ ├── AssertionFailedError.as │ │ ├── InstanceNotFoundError.as │ │ └── UnimplementedFeatureError.as │ ├── runner │ │ ├── Version.as │ │ ├── TestSuiteLoader.as │ │ └── BaseTestRunner.as │ ├── framework │ │ ├── Test.as │ │ ├── TestListener.as │ │ ├── TestMethod.as │ │ ├── AsynchronousHTTPServiceTestCase.as │ │ ├── AsyncOperation.as │ │ ├── TestFailure.as │ │ ├── TestCaseExample.as │ │ ├── AsynchronousTestCaseExample.as │ │ ├── TestSuite.as │ │ ├── TestResult.as │ │ ├── AsynchronousTestCase.as │ │ ├── RemotingTestCase.as │ │ ├── Assert.as │ │ └── TestCase.as │ └── textui │ │ ├── FlexRunner.as │ │ ├── AirRunner.as │ │ ├── FlexTestRunner.as │ │ ├── TestTime.as │ │ ├── TestRunner.as │ │ ├── XMLResultPrinter.as │ │ └── ResultPrinter.as │ └── AsUnit.as ├── src ├── com │ └── newloop │ │ ├── roboteyes │ │ ├── getA.as │ │ ├── inViewOf.as │ │ ├── core │ │ │ ├── RobotEyes.as │ │ │ ├── RobotEyesMaster.as │ │ │ └── RobotEyesChief.as │ │ ├── errors │ │ │ └── RobotEyesError.as │ │ └── drivers │ │ │ ├── InteractiveObjectDriver.as │ │ │ ├── DisplayObjectDriverList.as │ │ │ ├── DisplayObjectDriver.as │ │ │ └── TextFieldDriver.as │ │ └── roboteyesdemoapp │ │ ├── RotatingShapesView.as │ │ ├── RotatingSquareView.as │ │ └── TestTextView.as ├── roboteyesDemoAppRunner.as └── robotEyesDemoApp.as ├── script └── generate ├── test ├── com │ └── newloop │ │ └── roboteyes │ │ ├── drivers │ │ ├── DisplayObjectDriverListTest.as │ │ ├── InteractiveObjectDriverTest.as │ │ ├── DisplayObjectDriverTest.as │ │ └── TextFieldDriverTest.as │ │ └── core │ │ └── RobotEyesTest.as └── AllTests.as ├── rakefile.rb └── README.md /bin/robotEyes_0.1.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stray/RobotEyes/HEAD/bin/robotEyes_0.1.swc -------------------------------------------------------------------------------- /bin/roboteyesDemoAppRunner.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stray/RobotEyes/HEAD/bin/roboteyesDemoAppRunner.swf -------------------------------------------------------------------------------- /assets/skins/roboteyes/ProjectSprouts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stray/RobotEyes/HEAD/assets/skins/roboteyes/ProjectSprouts.png -------------------------------------------------------------------------------- /assets/skins/roboteyes/roboteyesDemoApp.fla: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stray/RobotEyes/HEAD/assets/skins/roboteyes/roboteyesDemoApp.fla -------------------------------------------------------------------------------- /assets/skins/roboteyes/roboteyesDemoApp.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stray/RobotEyes/HEAD/assets/skins/roboteyes/roboteyesDemoApp.swf -------------------------------------------------------------------------------- /lib/asunit3/asunit/util/Iterator.as: -------------------------------------------------------------------------------- 1 | package asunit.util { 2 | 3 | [ExcludeClass] 4 | public interface Iterator { 5 | function next():Object; 6 | function hasNext():Boolean; 7 | function reset():void; 8 | } 9 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/errors/AbstractError.as: -------------------------------------------------------------------------------- 1 | package asunit.errors { 2 | 3 | public class AbstractError extends Error { 4 | 5 | public function AbstractError(message:String) { 6 | super(message); 7 | name = "AbstractError"; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/runner/Version.as: -------------------------------------------------------------------------------- 1 | package asunit.runner { 2 | 3 | public class Version { 4 | private static var version:String = "3.0"; 5 | 6 | public static function id():String { 7 | return version.toString(); 8 | } 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/runner/TestSuiteLoader.as: -------------------------------------------------------------------------------- 1 | package asunit.runner { 2 | 3 | public interface TestSuiteLoader { 4 | // throws ClassNotFoundException 5 | function load(suiteClassName:String):Class; 6 | // throws ClassNotFoundException 7 | function reload(aClass:Class):Class; 8 | } 9 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/errors/ClassNotFoundError.as: -------------------------------------------------------------------------------- 1 | package asunit.errors { 2 | 3 | public class ClassNotFoundError extends Error { 4 | 5 | public function ClassNotFoundError(message:String) { 6 | super(message); 7 | name = "ClassNotFoundError"; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/errors/AssertionFailedError.as: -------------------------------------------------------------------------------- 1 | package asunit.errors { 2 | 3 | public class AssertionFailedError extends Error { 4 | 5 | public function AssertionFailedError(message:String) { 6 | super(message); 7 | name = "AssertionFailedError"; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/errors/InstanceNotFoundError.as: -------------------------------------------------------------------------------- 1 | package asunit.errors { 2 | 3 | public class InstanceNotFoundError extends Error { 4 | 5 | public function InstanceNotFoundError(message:String) { 6 | super(message); 7 | name = "InstanceNotFoundError"; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/errors/UnimplementedFeatureError.as: -------------------------------------------------------------------------------- 1 | package asunit.errors { 2 | 3 | public class UnimplementedFeatureError extends Error { 4 | 5 | public function UnimplementedFeatureError(message:String) { 6 | super(message); 7 | name = "UnimplementedFeatureError"; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/runner/BaseTestRunner.as: -------------------------------------------------------------------------------- 1 | package asunit.runner { 2 | import flash.display.Sprite; 3 | 4 | /** 5 | * Base class for all test runners. 6 | * This class was born live on stage in Sardinia during XP2000. 7 | */ 8 | public class BaseTestRunner extends Sprite { 9 | 10 | // Filters stack frames from internal JUnit classes 11 | public static function getFilteredTrace(stack:String):String { 12 | return stack; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/getA.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes 2 | { 3 | 4 | import com.newloop.roboteyes.core.RobotEyesMaster; 5 | import com.newloop.roboteyes.drivers.DisplayObjectDriver; 6 | 7 | /** 8 | * Class description. 9 | * 10 | * @langversion ActionScript 3.0 11 | * @playerversion Flash 9.0 12 | * 13 | * @author Lindsey Fallow 14 | * @since 07.01.2010 15 | */ 16 | 17 | public function getA(viewClazz:Class):DisplayObjectDriver 18 | { 19 | return RobotEyesMaster.getA(viewClazz); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /assets/skins/roboteyesDemoAppSkin.as: -------------------------------------------------------------------------------- 1 | 2 | package skins { 3 | public class roboteyesDemoAppSkin { 4 | [Embed(source="roboteyes/roboteyesDemoApp.swf", symbol="com.newloop.roboteyesdemoapp.TestViewA")] 5 | public static var TextTestViewSkin:Class; 6 | 7 | [Embed(source="roboteyes/roboteyesDemoApp.swf", symbol="mc_squareView")] 8 | public static var SquareViewSkin:Class; 9 | 10 | [Embed(source="roboteyes/roboteyesDemoApp.swf", symbol="mc_pentagonView")] 11 | public static var PentagonViewSkin:Class; 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/roboteyesDemoAppRunner.as: -------------------------------------------------------------------------------- 1 | package { 2 | import asunit.textui.TestRunner; 3 | 4 | public class robotEyesDemoAppRunner extends TestRunner { 5 | 6 | public function robotEyesDemoAppRunner() { 7 | // start(clazz:Class, methodName:String, showTrace:Boolean) 8 | // NOTE: sending a particular class and method name will 9 | // execute setUp(), the method and NOT tearDown. 10 | // This allows you to get visual confirmation while developing 11 | // visual entities 12 | start(AllTests, null, TestRunner.SHOW_TRACE); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/inViewOf.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyes { 5 | 6 | import com.newloop.roboteyes.core.RobotEyesMaster; 7 | import com.newloop.roboteyes.drivers.DisplayObjectDriver; 8 | 9 | /** 10 | * Class description. 11 | * 12 | * @langversion ActionScript 3.0 13 | * @playerversion Flash 9.0 14 | * 15 | * @author Lindsey Fallow 16 | * @since 07.01.2010 17 | */ 18 | 19 | public function inViewOf(viewClazz:Class):DisplayObjectDriver{ 20 | return RobotEyesMaster.inViewOf(viewClazz); 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /script/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'rubygems' 3 | require 'sprout' 4 | sprout 'sprout-as3-bundle' 5 | 6 | # Add a class name if TestSuites were generated 7 | if(ARGV.size == 1 && ARGV[0] == 'suite') 8 | ARGV << 'AllTests' 9 | end 10 | 11 | # Insert class type by default 12 | if(ARGV.size == 1) 13 | ARGV.unshift('class') 14 | end 15 | 16 | # Execute generators like this: 17 | # script/generate class utils.MathUtil 18 | # script/generate suite 19 | # script/generate test utils.MathUtilTest 20 | 21 | Sprout::Sprout.generate('as3', ARGV.shift, ARGV, File.dirname(File.dirname(__FILE__))) 22 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/util/ArrayIterator.as: -------------------------------------------------------------------------------- 1 | package asunit.util { 2 | 3 | import asunit.util.Iterator; 4 | 5 | [ExcludeClass] 6 | public class ArrayIterator implements Iterator { 7 | private var list:Array; 8 | private var index:Number = 0; 9 | 10 | public function ArrayIterator(list:Array) { 11 | this.list = list; 12 | } 13 | 14 | public function hasNext():Boolean { 15 | return list[index] != null; 16 | } 17 | 18 | public function next():Object { 19 | return list[index++]; 20 | } 21 | 22 | public function reset():void { 23 | index = 0; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/Test.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import flash.display.DisplayObjectContainer; 3 | import flash.events.IEventDispatcher; 4 | 5 | public interface Test extends IEventDispatcher { 6 | function countTestCases():int; 7 | function getName():String; 8 | function getTestMethods():Array; 9 | function toString():String; 10 | function setResult(result:TestListener):void; 11 | function run():void; 12 | function runBare():void; 13 | function getCurrentMethod():String; 14 | function getIsComplete():Boolean; 15 | function setContext(context:DisplayObjectContainer):void; 16 | function getContext():DisplayObjectContainer; 17 | } 18 | } -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/core/RobotEyes.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes.core { 2 | 3 | import flash.display.DisplayObjectContainer; 4 | 5 | import flash.display.Sprite; 6 | 7 | import com.newloop.roboteyes.core.RobotEyesMaster; 8 | 9 | public class RobotEyes extends Sprite { 10 | 11 | private var _testApplication:DisplayObjectContainer; 12 | 13 | public function RobotEyes(applicationMainClazz:Class) { 14 | 15 | init(applicationMainClazz); 16 | 17 | } 18 | 19 | private function init(applicationMainClazz:Class):void{ 20 | _testApplication = new applicationMainClazz() as DisplayObjectContainer; 21 | addChild(_testApplication); 22 | RobotEyesMaster.viewRoot = _testApplication; 23 | } 24 | 25 | public function get testApplication():*{ 26 | return _testApplication; 27 | } 28 | 29 | } 30 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/textui/FlexRunner.as: -------------------------------------------------------------------------------- 1 | package asunit.textui { 2 | import asunit.framework.TestResult; 3 | 4 | import mx.core.Application; 5 | 6 | /** 7 | * The FlexTestRunner should be the base class for your 8 | * test harness if you're testing a project that uses Flex components. 9 | * 10 | * @includeExample FlexRunnerExample.mxml 11 | **/ 12 | public class FlexRunner extends Application { 13 | protected var runner:TestRunner; 14 | 15 | override protected function createChildren():void { 16 | super.createChildren(); 17 | runner = new FlexTestRunner(); 18 | rawChildren.addChild(runner); 19 | } 20 | 21 | public function start(testCase:Class, testMethod:String = null, showTrace:Boolean = false):TestResult { 22 | return runner.start(testCase, testMethod, showTrace); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/util/Properties.as: -------------------------------------------------------------------------------- 1 | package asunit.util { 2 | import asunit.errors.UnimplementedFeatureError; 3 | import flash.errors.IllegalOperationError; 4 | 5 | [ExcludeClass] 6 | public dynamic class Properties { 7 | 8 | public function store(sharedObjectId:String):void { 9 | throw new UnimplementedFeatureError("Properties.store"); 10 | } 11 | 12 | public function put(key:String, value:Object):void { 13 | this[key] = value; 14 | } 15 | 16 | public function setProperty(key:String, value:Object):void { 17 | put(key, value); 18 | } 19 | 20 | public function getProperty(key:String):Object { 21 | try { 22 | return this[key]; 23 | } 24 | catch(e:Error) { 25 | throw IllegalOperationError("Properties.getProperty"); 26 | } 27 | return null; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/textui/AirRunner.as: -------------------------------------------------------------------------------- 1 | package asunit.textui { 2 | import asunit.framework.TestResult; 3 | 4 | import mx.core.WindowedApplication; 5 | 6 | /** 7 | * The base class for Air application runners that use the Flex framework. 8 | * 9 | * @includeExample AirRunnerExample.mxml 10 | * 11 | * @author Ian 12 | * @playerversion AIR 1.1 13 | **/ 14 | public class AirRunner extends WindowedApplication { 15 | 16 | protected var runner:TestRunner; 17 | 18 | override protected function createChildren():void { 19 | super.createChildren(); 20 | runner = new FlexTestRunner(); 21 | rawChildren.addChild(runner); 22 | } 23 | 24 | public function start(testCase:Class, testMethod:String = null, showTrace:Boolean = false) : TestResult { 25 | return runner.start(testCase, testMethod, showTrace); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/com/newloop/roboteyes/drivers/DisplayObjectDriverListTest.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes.drivers { 2 | 3 | import asunit.framework.TestCase; 4 | 5 | import flash.display.Sprite; 6 | 7 | public class DisplayObjectDriverListTest extends TestCase { 8 | private var instance:DisplayObjectDriverList; 9 | 10 | private var testObjectArray:Array; 11 | 12 | public function DisplayObjectDriverListTest(methodName:String=null) { 13 | super(methodName) 14 | } 15 | 16 | override protected function setUp():void { 17 | super.setUp(); 18 | testObjectArray = [new Sprite(), new Sprite()]; 19 | instance = new DisplayObjectDriverList(testObjectArray); 20 | } 21 | 22 | override protected function tearDown():void { 23 | super.tearDown(); 24 | instance = null; 25 | } 26 | 27 | public function testInstantiated():void { 28 | assertTrue("instance is DisplayObjectDriverList", instance is DisplayObjectDriverList); 29 | } 30 | 31 | public function testFailure():void { 32 | assertTrue("Failing test", true); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /test/AllTests.as: -------------------------------------------------------------------------------- 1 | package { 2 | /** 3 | * This file has been automatically created using 4 | * #!/usr/bin/ruby script/generate suite 5 | * If you modify it and run this script, your 6 | * modifications will be lost! 7 | */ 8 | 9 | import asunit.framework.TestSuite; 10 | import com.newloop.roboteyes.core.RobotEyesTest; 11 | import com.newloop.roboteyes.drivers.DisplayObjectDriverListTest; 12 | import com.newloop.roboteyes.drivers.DisplayObjectDriverTest; 13 | import com.newloop.roboteyes.drivers.InteractiveObjectDriverTest; 14 | import com.newloop.roboteyes.drivers.TextFieldDriverTest; 15 | 16 | public class AllTests extends TestSuite { 17 | 18 | public function AllTests() { 19 | addTest(new com.newloop.roboteyes.core.RobotEyesTest()); 20 | addTest(new com.newloop.roboteyes.drivers.DisplayObjectDriverListTest()); 21 | addTest(new com.newloop.roboteyes.drivers.DisplayObjectDriverTest()); 22 | addTest(new com.newloop.roboteyes.drivers.InteractiveObjectDriverTest()); 23 | addTest(new com.newloop.roboteyes.drivers.TextFieldDriverTest()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/com/newloop/roboteyes/drivers/InteractiveObjectDriverTest.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes.drivers { 2 | 3 | import asunit.framework.TestCase; 4 | 5 | import flash.display.InteractiveObject; 6 | import flash.display.Sprite; 7 | 8 | public class InteractiveObjectDriverTest extends TestCase { 9 | private var instance:InteractiveObjectDriver; 10 | 11 | private var testObject:InteractiveObject; 12 | 13 | public function InteractiveObjectDriverTest(methodName:String=null) { 14 | super(methodName) 15 | } 16 | 17 | override protected function setUp():void { 18 | super.setUp(); 19 | testObject = new Sprite(); 20 | instance = new InteractiveObjectDriver(testObject); 21 | } 22 | 23 | override protected function tearDown():void { 24 | super.tearDown(); 25 | instance = null; 26 | } 27 | 28 | public function testInstantiated():void { 29 | assertTrue("instance is InteractiveObjectDriver", instance is InteractiveObjectDriver); 30 | } 31 | 32 | public function testFailure():void { 33 | assertTrue("Failing test", true); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/TestListener.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.errors.AssertionFailedError; 3 | 4 | public interface TestListener { 5 | 6 | /** 7 | * Run the provided Test. 8 | */ 9 | function run(test:Test):void; 10 | /** 11 | * A test started. 12 | */ 13 | function startTest(test:Test):void; 14 | /** 15 | * A failure occurred. 16 | */ 17 | function addFailure(test:Test, t:AssertionFailedError):void; 18 | /** 19 | * An error occurred. 20 | */ 21 | function addError(test:Test, t:Error):void; 22 | /** 23 | * A test method has begun execution. 24 | */ 25 | function startTestMethod(test:Test, methodName:String):void; 26 | /** 27 | * A test method has completed. 28 | */ 29 | function endTestMethod(test:Test, methodName:String):void; 30 | /** 31 | * A test ended. 32 | */ 33 | function endTest(test:Test):void; 34 | } 35 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/TestMethod.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | 3 | import flash.utils.getTimer; 4 | 5 | /** 6 | * A TestFailure collects a failed test together with 7 | * the caught exception. 8 | * @see TestResult 9 | */ 10 | public class TestMethod { 11 | protected var test:Test; 12 | protected var method:String; 13 | 14 | private var _duration:Number; 15 | private var start:Number; 16 | 17 | /** 18 | * Constructs a TestMethod with a given Test and method name. 19 | */ 20 | public function TestMethod(test:Test, method:String) { 21 | this.test = test; 22 | this.method = method; 23 | start = getTimer(); 24 | } 25 | 26 | public function getName():String { 27 | return method; 28 | } 29 | 30 | public function endTest(test:Test):void { 31 | _duration = (getTimer() - start) * .001; 32 | } 33 | 34 | public function duration():Number { 35 | return _duration; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/errors/RobotEyesError.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyes.errors { 5 | 6 | /** 7 | * Error subclass description. 8 | * 9 | * @langversion ActionScript 3.0 10 | * @playerversion Flash 9.0 11 | * 12 | * @author Lindsey Fallow 13 | * @since 12.01.2010 14 | */ 15 | public class RobotEyesError extends Error { 16 | 17 | //-------------------------------------- 18 | // CLASS CONSTANTS 19 | //-------------------------------------- 20 | 21 | //-------------------------------------- 22 | // CONSTRUCTOR 23 | //-------------------------------------- 24 | 25 | /** 26 | * @constructor 27 | * @param message The message that describes this error. 28 | */ 29 | public function RobotEyesError(message:String){ 30 | super(message); 31 | } 32 | 33 | //-------------------------------------- 34 | // PRIVATE VARIABLES 35 | //-------------------------------------- 36 | 37 | //-------------------------------------- 38 | // GETTER/SETTERS 39 | //-------------------------------------- 40 | 41 | //-------------------------------------- 42 | // PUBLIC METHODS 43 | //-------------------------------------- 44 | 45 | //-------------------------------------- 46 | // EVENT HANDLERS 47 | //-------------------------------------- 48 | 49 | //-------------------------------------- 50 | // PRIVATE & PROTECTED INSTANCE METHODS 51 | //-------------------------------------- 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /test/com/newloop/roboteyes/drivers/DisplayObjectDriverTest.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes.drivers { 2 | 3 | import asunit.framework.TestCase; 4 | 5 | import flash.display.DisplayObject; 6 | import flash.display.Sprite; 7 | 8 | import com.newloop.roboteyes.errors.RobotEyesError; 9 | 10 | public class DisplayObjectDriverTest extends TestCase { 11 | private var instance:DisplayObjectDriver; 12 | 13 | private var testObject:DisplayObject; 14 | 15 | public function DisplayObjectDriverTest(methodName:String=null) { 16 | super(methodName) 17 | } 18 | 19 | override protected function setUp():void { 20 | super.setUp(); 21 | testObject = new Sprite(); 22 | instance = new DisplayObjectDriver(testObject); 23 | } 24 | 25 | override protected function tearDown():void { 26 | super.tearDown(); 27 | instance = null; 28 | } 29 | 30 | public function testInstantiated():void { 31 | assertTrue("instance is DisplayObjectDriver", instance is DisplayObjectDriver); 32 | } 33 | 34 | public function testFailure():void { 35 | assertTrue("Failing test", true); 36 | } 37 | 38 | public function testCheckPropertyHasValueOfThrowsError():void { 39 | assertThrows(RobotEyesError, function():void{ 40 | instance.checkPropertyHasValueOf("text", "hi"); 41 | }) 42 | } 43 | 44 | public function testCheckPropertyHasValueOfPassesCorrectly():void{ 45 | assertTrue("checkPropertyHasValueOf passes correctly", (instance.checkPropertyHasValueOf("alpha", 1))); 46 | } 47 | 48 | public function testCheckPropertyHasValueOfFailsCorrectly():void{ 49 | assertFalse("checkPropertyHasValueOf fails correctly", (instance.checkPropertyHasValueOf("width", 10))); 50 | } 51 | 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/AsynchronousHTTPServiceTestCase.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.errors.AbstractError; 3 | 4 | import flash.errors.IllegalOperationError; 5 | import flash.events.*; 6 | import flash.net.URLLoader; 7 | import flash.utils.getTimer; 8 | 9 | import mx.rpc.AsyncToken; 10 | import mx.rpc.Responder; 11 | import mx.rpc.events.FaultEvent; 12 | 13 | /** 14 | * Extend this class if you have a TestCase that requires the 15 | * asynchronous load of external data. 16 | */ 17 | public class AsynchronousHTTPServiceTestCase extends TestCase implements Test { 18 | 19 | public function AsynchronousHTTPServiceTestCase(testMethod:String = null) { 20 | super(testMethod); 21 | } 22 | 23 | // use this method in overriding run() if you are using an HTTPService: 24 | protected function configureResponder(token:AsyncToken):void { 25 | token.addResponder(new Responder(resultFunc, faultFunc)); 26 | } 27 | 28 | protected function resultFunc(event:Object):void { 29 | completeHandler(event as Event); 30 | } 31 | 32 | protected function faultFunc(event:Object):void { 33 | var faultEvent:FaultEvent = event as FaultEvent; 34 | if (faultEvent == null) { 35 | return; 36 | } 37 | var cause:Object = faultEvent.fault.rootCause; 38 | var ioErrorEvent:IOErrorEvent = cause as IOErrorEvent; 39 | if (ioErrorEvent) { 40 | ioErrorHandler(ioErrorEvent); 41 | return; 42 | } 43 | var securityErrorEvent:SecurityErrorEvent = cause as SecurityErrorEvent; 44 | if (securityErrorEvent) { 45 | securityErrorHandler(securityErrorEvent); 46 | } 47 | } 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/AsyncOperation.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.errors.AssertionFailedError; 3 | import flash.errors.IllegalOperationError; 4 | import flash.events.Event; 5 | import flash.events.TimerEvent; 6 | import flash.utils.Timer; 7 | 8 | public class AsyncOperation{ 9 | 10 | private var timeout:Timer; 11 | private var testCase:TestCase; 12 | private var callback:Function; 13 | private var duration:Number; 14 | private var failureHandler:Function; 15 | 16 | public function AsyncOperation(testCase:TestCase, handler:Function, duration:Number, failureHandler:Function=null){ 17 | this.testCase = testCase; 18 | this.duration = duration; 19 | timeout = new Timer(duration, 1); 20 | timeout.addEventListener(TimerEvent.TIMER_COMPLETE, onTimeoutComplete); 21 | timeout.start(); 22 | if(handler == null) { 23 | handler = function(args:*):* {return;}; 24 | } 25 | this.failureHandler = failureHandler; 26 | var context:AsyncOperation = this; 27 | callback = function(args:*):* { 28 | timeout.stop(); 29 | try { 30 | handler.apply(testCase, arguments); 31 | } 32 | catch(e:AssertionFailedError) { 33 | testCase.getResult().addFailure(testCase, e); 34 | } 35 | catch(ioe:IllegalOperationError) { 36 | testCase.getResult().addError(testCase, ioe); 37 | } 38 | catch(unknownError:Error) { 39 | testCase.getResult().addError(testCase, unknownError); 40 | } 41 | finally { 42 | testCase.asyncOperationComplete(context); 43 | } 44 | return; 45 | }; 46 | } 47 | 48 | public function getCallback():Function{ 49 | return callback; 50 | } 51 | 52 | private function onTimeoutComplete(event:TimerEvent):void { 53 | if(null != failureHandler) { 54 | failureHandler(new Event('async timeout')); 55 | } 56 | testCase.asyncOperationTimeout(this, duration, null==failureHandler); 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/robotEyesDemoApp.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package { 5 | 6 | import flash.display.Sprite; 7 | 8 | import com.newloop.roboteyesdemoapp.TestTextView; 9 | import com.newloop.roboteyesdemoapp.RotatingShapesView; 10 | 11 | /** 12 | * Class description. 13 | * 14 | * @langversion ActionScript 3.0 15 | * @playerversion Flash 9.0 16 | * 17 | * @author Lindsey Fallow 18 | * @since 10.01.2010 19 | */ 20 | public class robotEyesDemoApp extends Sprite { 21 | 22 | //-------------------------------------- 23 | // CLASS CONSTANTS 24 | //-------------------------------------- 25 | 26 | //-------------------------------------- 27 | // CONSTRUCTOR 28 | //-------------------------------------- 29 | 30 | /** 31 | * @Constructor 32 | */ 33 | public function robotEyesDemoApp(){ 34 | trace("initialising: robotEyesDemoApp "); 35 | super(); 36 | init(); 37 | } 38 | 39 | //-------------------------------------- 40 | // PRIVATE VARIABLES 41 | //-------------------------------------- 42 | 43 | //-------------------------------------- 44 | // GETTER/SETTERS 45 | //-------------------------------------- 46 | 47 | //-------------------------------------- 48 | // PUBLIC METHODS 49 | //-------------------------------------- 50 | 51 | //-------------------------------------- 52 | // EVENT HANDLERS 53 | //-------------------------------------- 54 | 55 | //-------------------------------------- 56 | // PRIVATE & PROTECTED INSTANCE METHODS 57 | //-------------------------------------- 58 | 59 | private function init():void{ 60 | addChild(new TestTextView()); 61 | var shapesView:RotatingShapesView = new RotatingShapesView(); 62 | shapesView.x = 400; 63 | shapesView.y = 100; 64 | addChild(shapesView); 65 | } 66 | 67 | //-------------------------------------- 68 | // UNIT TESTS 69 | //-------------------------------------- 70 | 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/TestFailure.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.errors.AssertionFailedError; 3 | 4 | /** 5 | * A TestFailure collects a failed test together with 6 | * the caught exception. 7 | * @see TestResult 8 | */ 9 | public class TestFailure { 10 | protected var fFailedTest:Test; 11 | protected var fFailedTestMethod:String; 12 | protected var fThrownException:Error; 13 | 14 | /** 15 | * Constructs a TestFailure with the given test and exception. 16 | */ 17 | public function TestFailure(failedTest:Test, thrownException:Error) { 18 | fFailedTest = failedTest; 19 | fFailedTestMethod = failedTest.getCurrentMethod(); 20 | fThrownException = thrownException; 21 | } 22 | 23 | public function failedFeature():String { 24 | return failedTest().getName() + '.' + fFailedTestMethod; 25 | } 26 | 27 | public function failedMethod():String { 28 | return fFailedTestMethod; 29 | } 30 | 31 | /** 32 | * Gets the failed test case. 33 | */ 34 | public function failedTest():Test { 35 | return fFailedTest; 36 | } 37 | /** 38 | * Gets the thrown exception. 39 | */ 40 | public function thrownException():Error { 41 | return fThrownException; 42 | } 43 | /** 44 | * Returns a short description of the failure. 45 | */ 46 | public function toString():String { 47 | return ""; 48 | } 49 | 50 | public function exceptionMessage():String { 51 | return thrownException().message; 52 | } 53 | 54 | public function isFailure():Boolean { 55 | return thrownException() is AssertionFailedError; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/textui/FlexTestRunner.as: -------------------------------------------------------------------------------- 1 | package asunit.textui { 2 | import flash.display.DisplayObject; 3 | import flash.events.Event; 4 | import mx.core.IUIComponent; 5 | import asunit.textui.TestRunner; 6 | 7 | /** 8 | * @private 9 | **/ 10 | public class FlexTestRunner extends TestRunner { 11 | 12 | public function FlexTestRunner() { 13 | setPrinter(new ResultPrinter()); 14 | } 15 | 16 | protected override function addedHandler(event:Event):void { 17 | if(event.target === this) { 18 | parent.addEventListener(Event.RESIZE, resizeHandler); 19 | resizeHandler(new Event(Event.RESIZE)); 20 | } 21 | else { 22 | event.stopPropagation(); 23 | } 24 | } 25 | 26 | public override function set width(w:Number):void { 27 | fPrinter.width = w; 28 | } 29 | 30 | public override function set height(h:Number):void { 31 | fPrinter.height = h; 32 | } 33 | 34 | public function resizeHandler(event:Event):void { 35 | width = parent.width; 36 | height = parent.height; 37 | } 38 | 39 | public override function addChild(child:DisplayObject):DisplayObject { 40 | if(parent && child is IUIComponent) { 41 | // AND check for 'is' UIUComponent... 42 | return parent.addChild(child); 43 | } 44 | else { 45 | return super.addChild(child); 46 | } 47 | } 48 | 49 | public override function removeChild(child:DisplayObject):DisplayObject { 50 | if(child is IUIComponent) { 51 | return parent.removeChild(child); 52 | } 53 | else { 54 | return super.removeChild(child); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyesdemoapp/RotatingShapesView.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyesdemoapp { 5 | 6 | import flash.display.Sprite; 7 | import flash.events.Event; 8 | import flash.events.MouseEvent; 9 | 10 | import skins.roboteyesDemoAppSkin; 11 | 12 | /** 13 | * Sprite sub class description. 14 | * 15 | * @langversion ActionScript 3.0 16 | * @playerversion Flash 9.0 17 | * 18 | * @author Lindsey Fallow 19 | * @since 2010-01-12 20 | */ 21 | public class RotatingShapesView extends Sprite { 22 | 23 | //-------------------------------------- 24 | // CLASS CONSTANTS 25 | //-------------------------------------- 26 | 27 | //-------------------------------------- 28 | // CONSTRUCTOR 29 | //-------------------------------------- 30 | 31 | /** 32 | * @Constructor 33 | */ 34 | public function RotatingShapesView(){ 35 | super(); 36 | init(); 37 | } 38 | 39 | //-------------------------------------- 40 | // PRIVATE VARIABLES 41 | //-------------------------------------- 42 | 43 | private var squareView:RotatingSquareView; 44 | 45 | //-------------------------------------- 46 | // GETTER/SETTERS 47 | //-------------------------------------- 48 | 49 | //-------------------------------------- 50 | // PUBLIC METHODS 51 | //-------------------------------------- 52 | 53 | //-------------------------------------- 54 | // EVENT HANDLERS 55 | //-------------------------------------- 56 | 57 | private function clickHandler(e:MouseEvent):void{ 58 | if(this.alpha>0.1){ 59 | this.alpha-=0.1; 60 | } else { 61 | this.alpha = 1; 62 | } 63 | squareView.rotateShapes(); 64 | } 65 | 66 | //-------------------------------------- 67 | // PRIVATE & PROTECTED INSTANCE METHODS 68 | //-------------------------------------- 69 | 70 | /** 71 | * Initialises this object instance. 72 | */ 73 | private function init() : void 74 | { 75 | squareView = new RotatingSquareView(); 76 | addChild(squareView); 77 | this.addEventListener(MouseEvent.CLICK, clickHandler); 78 | } 79 | 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/textui/TestTime.as: -------------------------------------------------------------------------------- 1 | package asunit.textui 2 | { 3 | import asunit.framework.AsynchronousTestCase; 4 | import asunit.framework.Test; 5 | 6 | public class TestTime extends Object 7 | { 8 | public static function create(test:Test, duration:int):TestTime 9 | { 10 | var asyncTest:AsynchronousTestCase = test as AsynchronousTestCase; 11 | if (asyncTest && asyncTest.remoteDurationIsValid()) 12 | { 13 | return new AsyncTestTime(asyncTest, duration, PrivateConstructorEnforcer); 14 | } 15 | else 16 | { 17 | return new TestTime(test, duration, PrivateConstructorEnforcer); 18 | } 19 | } 20 | 21 | private var _name:String; 22 | private var _duration:int; 23 | public function get duration():int 24 | { 25 | return _duration; 26 | } 27 | 28 | public function TestTime(test:Test, duration:int, lock:Class) 29 | { 30 | super(); 31 | if (lock != PrivateConstructorEnforcer) 32 | { 33 | throw new Error("TestTime: private constructor"); 34 | } 35 | 36 | _name = test.getName(); 37 | _duration = duration; 38 | } 39 | 40 | public function toString():String 41 | { 42 | return "" + _duration + 'ms : ' + _name; 43 | } 44 | 45 | } 46 | } 47 | import asunit.framework.Test; 48 | import asunit.framework.AsynchronousTestCase; 49 | import asunit.textui.TestTime; 50 | 51 | 52 | class AsyncTestTime extends TestTime 53 | { 54 | private var _remoteDuration:int; 55 | 56 | public function AsyncTestTime(test:AsynchronousTestCase, duration:int, lock:Class) 57 | { 58 | super(test, duration, lock); 59 | _remoteDuration = test.remoteDuration; 60 | } 61 | 62 | override public function toString():String 63 | { 64 | return super.toString() + ' (remote: ' + _remoteDuration + 'ms)'; 65 | } 66 | } 67 | 68 | class PrivateConstructorEnforcer {} -------------------------------------------------------------------------------- /rakefile.rb: -------------------------------------------------------------------------------- 1 | require 'sprout' 2 | # Optionally load gems from a server other than rubyforge: 3 | # set_sources 'http://gems.projectsprouts.org' 4 | sprout 'as3' 5 | 6 | ############################################ 7 | # Configure your Project Model 8 | project_model :model do |m| 9 | m.project_name = 'robotEyesDemoApp' 10 | m.language = 'as3' 11 | m.background_color = '#FFFFFF' 12 | m.width = 800 13 | m.height = 600 14 | # m.use_fdb = true 15 | # m.use_fcsh = true 16 | # m.preprocessor = 'cpp -D__DEBUG=false -P - - | tail -c +3' 17 | # m.preprocessed_path = '.preprocessed' 18 | # m.src_dir = 'src' 19 | # m.lib_dir = 'lib' 20 | # m.swc_dir = 'lib' 21 | # m.bin_dir = 'bin' 22 | # m.test_dir = 'test' 23 | # m.doc_dir = 'doc' 24 | # m.asset_dir = 'assets' 25 | # m.compiler_gem_name = 'sprout-flex4sdk-tool' 26 | # m.compiler_gem_version = '>= 4.0.0' 27 | # m.source_path << "#{m.lib_dir}/somelib" 28 | # m.libraries << :corelib 29 | end 30 | 31 | desc 'Compile and debug the application' 32 | debug :debug 33 | 34 | desc 'Compile run the test harness' 35 | unit :test 36 | 37 | desc 'Compile the optimized deployment' 38 | deploy :deploy 39 | 40 | desc 'Create documentation' 41 | document :doc 42 | 43 | desc 'Compile a SWC file' 44 | swc :swc do |t| 45 | t.include_classes = "com.newloop.roboteyes.getA" 46 | t.include_classes << " com.newloop.roboteyes.inViewOf" 47 | t.include_classes << " com.newloop.roboteyes.core.RobotEyes" 48 | t.include_classes << " com.newloop.roboteyes.core.RobotEyesChief" 49 | t.include_classes << " com.newloop.roboteyes.core.RobotEyesMaster" 50 | t.include_classes << " com.newloop.roboteyes.drivers.DisplayObjectDriver" 51 | t.include_classes << " com.newloop.roboteyes.drivers.DisplayObjectDriverList" 52 | t.include_classes << " com.newloop.roboteyes.drivers.InteractiveObjectDriver" 53 | t.include_classes << " com.newloop.roboteyes.drivers.TextFieldDriver" 54 | t.include_classes << " com.newloop.roboteyes.errors.RobotEyesError" 55 | end 56 | 57 | desc 'Compile and run the test harness for CI' 58 | ci :cruise 59 | 60 | # set up the default rake task 61 | task :default => :debug 62 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyesdemoapp/RotatingSquareView.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyesdemoapp { 5 | 6 | import flash.display.Sprite; 7 | import flash.events.Event; 8 | import flash.events.MouseEvent; 9 | 10 | import skins.roboteyesDemoAppSkin; 11 | 12 | /** 13 | * Sprite sub class description. 14 | * 15 | * @langversion ActionScript 3.0 16 | * @playerversion Flash 9.0 17 | * 18 | * @author Lindsey Fallow 19 | * @since 2010-01-12 20 | */ 21 | public class RotatingSquareView extends Sprite { 22 | 23 | //-------------------------------------- 24 | // CLASS CONSTANTS 25 | //-------------------------------------- 26 | 27 | //-------------------------------------- 28 | // CONSTRUCTOR 29 | //-------------------------------------- 30 | 31 | /** 32 | * @Constructor 33 | */ 34 | public function RotatingSquareView(){ 35 | super(); 36 | init(); 37 | } 38 | 39 | //-------------------------------------- 40 | // PRIVATE VARIABLES 41 | //-------------------------------------- 42 | 43 | private var mcSquare:Sprite; 44 | 45 | private var mcPentagon:Sprite; 46 | 47 | //-------------------------------------- 48 | // GETTER/SETTERS 49 | //-------------------------------------- 50 | 51 | //-------------------------------------- 52 | // PUBLIC METHODS 53 | //-------------------------------------- 54 | 55 | public function rotateShapes():void{ 56 | rotateSquare(); 57 | rotatePentagon(); 58 | } 59 | 60 | //-------------------------------------- 61 | // EVENT HANDLERS 62 | //-------------------------------------- 63 | 64 | //-------------------------------------- 65 | // PRIVATE & PROTECTED INSTANCE METHODS 66 | //-------------------------------------- 67 | 68 | /** 69 | * Initialises this object instance. 70 | */ 71 | private function init() : void 72 | { 73 | mcSquare = new roboteyesDemoAppSkin.SquareViewSkin(); 74 | mcSquare.alpha = 0.8; 75 | addChild(mcSquare); 76 | 77 | mcPentagon = new roboteyesDemoAppSkin.PentagonViewSkin(); 78 | addChild(mcPentagon); 79 | } 80 | 81 | private function rotateSquare():void{ 82 | mcSquare.rotation += 20; 83 | } 84 | 85 | private function rotatePentagon():void{ 86 | mcPentagon.rotation -= 20; 87 | } 88 | 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/drivers/InteractiveObjectDriver.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyes.drivers { 5 | 6 | import flash.display.InteractiveObject; 7 | 8 | import flash.events.MouseEvent; 9 | 10 | /** 11 | * Class description. 12 | * 13 | * @langversion ActionScript 3.0 14 | * @playerversion Flash 9.0 15 | * 16 | * @author Lindsey Fallow 17 | * @since 07.01.2010 18 | */ 19 | public class InteractiveObjectDriver extends DisplayObjectDriver { 20 | 21 | private var _item:InteractiveObject; 22 | 23 | //-------------------------------------- 24 | // CLASS CONSTANTS 25 | //-------------------------------------- 26 | 27 | //-------------------------------------- 28 | // CONSTRUCTOR 29 | //-------------------------------------- 30 | 31 | /** 32 | * @Constructor 33 | */ 34 | public function InteractiveObjectDriver(uiItem:InteractiveObject){ 35 | super(uiItem); 36 | _item = uiItem; 37 | } 38 | 39 | //-------------------------------------- 40 | // PRIVATE VARIABLES 41 | //-------------------------------------- 42 | 43 | //-------------------------------------- 44 | // GETTER/SETTERS 45 | //-------------------------------------- 46 | 47 | public function get item():InteractiveObject{ 48 | return _item; 49 | } 50 | 51 | //-------------------------------------- 52 | // PUBLIC METHODS 53 | //-------------------------------------- 54 | 55 | public function click():void{ 56 | _item.dispatchEvent(new MouseEvent(MouseEvent.CLICK)); 57 | } 58 | 59 | public function mouseOver():void{ 60 | _item.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OVER)); 61 | } 62 | 63 | public function mouseOut():void{ 64 | _item.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OUT)); 65 | } 66 | 67 | public function mouseDown():void{ 68 | _item.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN)); 69 | } 70 | 71 | public function mouseUp():void{ 72 | _item.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP)); 73 | } 74 | 75 | public function rollOver():void{ 76 | _item.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER)); 77 | } 78 | 79 | public function rollOut():void{ 80 | _item.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT)); 81 | } 82 | 83 | //-------------------------------------- 84 | // EVENT HANDLERS 85 | //-------------------------------------- 86 | 87 | //-------------------------------------- 88 | // PRIVATE & PROTECTED INSTANCE METHODS 89 | //-------------------------------------- 90 | 91 | //-------------------------------------- 92 | // UNIT TESTS 93 | //-------------------------------------- 94 | 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /lib/asunit3/AsUnit.as: -------------------------------------------------------------------------------- 1 | package { 2 | import asunit.errors.AssertionFailedError; 3 | import asunit.errors.ClassNotFoundError; 4 | import asunit.errors.InstanceNotFoundError; 5 | import asunit.errors.UnimplementedFeatureError; 6 | import asunit.framework.Assert; 7 | import asunit.framework.AsynchronousTestCase; 8 | import asunit.framework.AsynchronousTestCaseExample; 9 | import asunit.framework.AsyncOperation; 10 | import asunit.framework.RemotingTestCase; 11 | import asunit.framework.Test; 12 | import asunit.framework.TestCase; 13 | import asunit.framework.TestCaseExample; 14 | import asunit.framework.TestFailure; 15 | import asunit.framework.TestListener; 16 | import asunit.framework.TestMethod; 17 | import asunit.framework.TestResult; 18 | import asunit.framework.TestSuite; 19 | import asunit.runner.BaseTestRunner; 20 | import asunit.runner.TestSuiteLoader; 21 | import asunit.runner.Version; 22 | import asunit.textui.AirRunner; 23 | import asunit.textui.FlexRunner; 24 | import asunit.textui.FlexTestRunner; 25 | import asunit.textui.ResultPrinter; 26 | import asunit.textui.TestRunner; 27 | import asunit.textui.XMLResultPrinter; 28 | import asunit.util.ArrayIterator; 29 | import asunit.util.Iterator; 30 | import asunit.util.Properties; 31 | 32 | public class AsUnit { 33 | private var assertionFailedError:AssertionFailedError; 34 | private var classNotFoundError:ClassNotFoundError; 35 | private var instanceNotFoundError:InstanceNotFoundError; 36 | private var unimplementedFeatureError:UnimplementedFeatureError; 37 | private var assert:Assert; 38 | private var asynchronousTestCase:AsynchronousTestCase; 39 | private var asynchronousTestCaseExample:AsynchronousTestCaseExample; 40 | private var asyncOperation:AsyncOperation; 41 | private var remotingTestCase:RemotingTestCase; 42 | private var test:Test; 43 | private var testCase:TestCase; 44 | private var testCaseExample:TestCaseExample; 45 | private var testFailure:TestFailure; 46 | private var testListener:TestListener; 47 | private var testMethod:TestMethod; 48 | private var testResult:TestResult; 49 | private var testSuite:TestSuite; 50 | private var baseTestRunner:BaseTestRunner; 51 | private var testSuiteLoader:TestSuiteLoader; 52 | private var version:Version; 53 | private var airRunner:AirRunner; 54 | private var flexRunner:FlexRunner; 55 | private var flexTestRunner:FlexTestRunner; 56 | private var resultPrinter:ResultPrinter; 57 | private var testRunner:TestRunner; 58 | private var xMLResultPrinter:XMLResultPrinter; 59 | private var arrayIterator:ArrayIterator; 60 | private var iterator:Iterator; 61 | private var properties:Properties; 62 | private var asUnit:AsUnit; 63 | } 64 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/TestCaseExample.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.framework.TestCase; 3 | import flash.display.Sprite; 4 | import flash.events.Event; 5 | import flash.events.IEventDispatcher; 6 | import flash.events.EventDispatcher; 7 | import flash.utils.setTimeout; 8 | 9 | // TestCase subclasses should always end with 'Test', the example 10 | // doesn't because we don't want TestSuites in this directory. 11 | public class TestCaseExample extends TestCase { 12 | private var date:Date; 13 | private var sprite:Sprite; 14 | 15 | // TestCase constructors must be implemented as follows 16 | // so that we can execute a single method on them from 17 | // the TestRunner 18 | public function TestCaseExample(testMethod:String = null) { 19 | super(testMethod); 20 | } 21 | 22 | // This method will be called before every test method 23 | override protected function setUp():void { 24 | date = new Date(); 25 | // sprite = new Sprite(); 26 | // addChild(sprite); 27 | } 28 | 29 | // This method will be called after every test method 30 | // but only if we're executing the entire TestCase, 31 | // the tearDown method won't be called if we're 32 | // calling start(MyTestCase, "someMethod"); 33 | override protected function tearDown():void { 34 | // removeChild(sprite); 35 | // sprite = null; 36 | date = null; 37 | } 38 | 39 | // This is auto-created by the XULUI and ensures that 40 | // our objects are actually created as we expect. 41 | public function testInstantiated():void { 42 | assertTrue("Date instantiated", date is Date); 43 | // assertTrue("Sprite instantiated", sprite is Sprite); 44 | } 45 | 46 | // This is an example of a typical test method 47 | public function testMonthGetterSetter():void { 48 | date.month = 1; 49 | assertEquals(1, date.month); 50 | } 51 | 52 | // This is an asynchronous test method 53 | public function testAsyncFeature():void { 54 | // create a new object that dispatches events... 55 | var dispatcher:IEventDispatcher = new EventDispatcher(); 56 | // get a TestCase async event handler reference 57 | // the 2nd arg is an optional timeout in ms. (default=1000ms ) 58 | var handler:Function = addAsync(changeHandler, 2000); 59 | // subscribe to your event dispatcher using the returned handler 60 | dispatcher.addEventListener(Event.CHANGE, handler); 61 | // cause the event to be dispatched. 62 | // either immediately: 63 | //dispatcher.dispatchEvent(new Event(Event.CHANGE)); 64 | // or in the future < your assigned timeout 65 | setTimeout( dispatcher.dispatchEvent, 200, new Event(Event.CHANGE)); 66 | } 67 | 68 | protected function changeHandler(event:Event):void { 69 | // perform assertions in your handler 70 | assertEquals(Event.CHANGE, event.type); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/core/RobotEyesMaster.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyes.core { 5 | 6 | import flash.display.DisplayObjectContainer; 7 | import flash.display.DisplayObject; 8 | import com.newloop.roboteyes.drivers.DisplayObjectDriver; 9 | import com.newloop.roboteyes.drivers.DisplayObjectDriverList; 10 | 11 | 12 | /** 13 | * Class description. 14 | * 15 | * @langversion ActionScript 3.0 16 | * @playerversion Flash 9.0 17 | * 18 | * @author Lindsey Fallow 19 | * @since 07.01.2010 20 | */ 21 | public class RobotEyesMaster extends Object { 22 | 23 | //-------------------------------------- 24 | // CLASS CONSTANTS 25 | //-------------------------------------- 26 | 27 | private static var _robotEyesChief:RobotEyesChief = new RobotEyesChief(); 28 | 29 | //-------------------------------------- 30 | // CONSTRUCTOR 31 | //-------------------------------------- 32 | 33 | /** 34 | * @Constructor 35 | */ 36 | public function RobotEyesMaster(){ 37 | super(); 38 | } 39 | 40 | //-------------------------------------- 41 | // PRIVATE VARIABLES 42 | //-------------------------------------- 43 | 44 | //-------------------------------------- 45 | // GETTER/SETTERS 46 | //-------------------------------------- 47 | 48 | public static function get robotEyesChief():RobotEyesChief 49 | { 50 | return _robotEyesChief; 51 | } 52 | 53 | public static function set viewRoot(_viewRoot:DisplayObjectContainer):void 54 | { 55 | _robotEyesChief.viewRoot = _viewRoot; 56 | } 57 | 58 | //-------------------------------------- 59 | // PUBLIC METHODS 60 | //-------------------------------------- 61 | 62 | public static function inViewOf(viewClazz:Class, viewRoot:DisplayObjectContainer = null):DisplayObjectDriver{ 63 | return _robotEyesChief.inViewOf(viewClazz, viewRoot); 64 | } 65 | 66 | public static function getA(uiClazz:Class, viewRoot:DisplayObjectContainer = null):DisplayObjectDriverList{ 67 | return _robotEyesChief.getA(uiClazz, viewRoot); 68 | } 69 | 70 | public static function getAny(uiClazz:Class, viewRoot:DisplayObjectContainer = null):DisplayObjectDriver{ 71 | return _robotEyesChief.getAny(uiClazz, viewRoot); 72 | } 73 | 74 | public static function getSome(uiClazz:Class, viewRoot:DisplayObjectContainer = null):DisplayObjectDriverList{ 75 | return _robotEyesChief.getSome(uiClazz, viewRoot); 76 | } 77 | 78 | public static function createDriverFor(uiItem:DisplayObject):DisplayObjectDriver{ 79 | return _robotEyesChief.createDriverFor(uiItem); 80 | } 81 | 82 | public static function countChildrenOfType(childClazz:Class, viewRoot:DisplayObjectContainer):uint{ 83 | return _robotEyesChief.countChildrenOfType(childClazz, viewRoot); 84 | } 85 | 86 | //-------------------------------------- 87 | // EVENT HANDLERS 88 | //-------------------------------------- 89 | 90 | //-------------------------------------- 91 | // PRIVATE & PROTECTED INSTANCE METHODS 92 | //-------------------------------------- 93 | 94 | //-------------------------------------- 95 | // UNIT TESTS 96 | //-------------------------------------- 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/drivers/DisplayObjectDriverList.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyes.drivers { 5 | 6 | import com.newloop.roboteyes.core.RobotEyesMaster; 7 | 8 | import flash.display.DisplayObject; 9 | 10 | /** 11 | * Class description. 12 | * 13 | * @langversion ActionScript 3.0 14 | * @playerversion Flash 9.0 15 | * 16 | * @author Lindsey Fallow 17 | * @since 07.01.2010 18 | */ 19 | public class DisplayObjectDriverList extends DisplayObjectDriver { 20 | 21 | private var _matchingInstancesArray:Array; 22 | 23 | //-------------------------------------- 24 | // CLASS CONSTANTS 25 | //-------------------------------------- 26 | 27 | //-------------------------------------- 28 | // CONSTRUCTOR 29 | //-------------------------------------- 30 | 31 | /** 32 | * @Constructor 33 | */ 34 | public function DisplayObjectDriverList(matchingInstancesArray:Array){ 35 | _matchingInstancesArray = matchingInstancesArray; 36 | super(_matchingInstancesArray[0]); 37 | } 38 | 39 | //-------------------------------------- 40 | // PRIVATE VARIABLES 41 | //-------------------------------------- 42 | 43 | //-------------------------------------- 44 | // GETTER/SETTERS 45 | //-------------------------------------- 46 | 47 | //-------------------------------------- 48 | // PUBLIC METHODS 49 | //-------------------------------------- 50 | 51 | public function named(withName:String):DisplayObjectDriver{ 52 | var iLength:uint = _matchingInstancesArray.length; 53 | for (var i:uint = 0; i 9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * This example was created to illustrate how one can build an synchronous 18 | * TestCase - one that relies on remote data of some sort. 19 | * This use case is now diminished by the creation of E4X and easily 20 | * readable/editable XML data directly in source form. 21 | * But asynchronous tests will probably need to be built at some point 22 | * by somebody... If you're them, maybe you can use this as a template. 23 | */ 24 | 25 | public class AsynchronousTestCaseExample extends AsynchronousTestCase { 26 | private var source:String = "asunit/framework/MockData.xml"; 27 | private var dataSource:XML; 28 | private var instance:Object; 29 | 30 | // Override the run method and begin the request for remote data 31 | public override function run():void { 32 | var request:URLRequest = new URLRequest(source); 33 | var loader:URLLoader = new URLLoader(); 34 | // configureListeners is a method on the AsynchronousTestCase 35 | // and it will handle error states by failing loudly... 36 | configureListeners(loader); 37 | loader.load(request); 38 | 39 | // call super.run() to start network duration: 40 | super.run(); 41 | } 42 | 43 | protected override function setDataSource(event:Event):void { 44 | // put a copy of the data into a member reference 45 | if (event == null) 46 | { 47 | dataSource = null; 48 | } 49 | else 50 | { 51 | dataSource = XML(event.target.data).copy(); 52 | } 53 | } 54 | 55 | protected override function setUp():void { 56 | // create a new instance of the class under test 57 | instance = new Object(); 58 | if (dataSource != null) // i.e. there was no IOError or SecurityError 59 | { 60 | // copy the data into a member or method of the _instance 61 | instance.data = dataSource.copy(); 62 | } 63 | } 64 | 65 | protected override function tearDown():void { 66 | // destroy the class under test instance 67 | instance = null; 68 | } 69 | 70 | public function testBookCount():void { 71 | var data:XML = XML(instance.data); 72 | var list:XMLList = data..book; 73 | assertTrue("list.length() == " + list.length() + " (6?)", list.length() == 6); 74 | } 75 | 76 | public function testOReillyBookCount():void { 77 | var data:XML = XML(instance.data); 78 | var list:XMLList = data..book.(@publisher == "O'Reilly Media"); 79 | assertTrue("list.length() == " + list.length() + " (2?)", list.length() == 2); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/drivers/DisplayObjectDriver.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyes.drivers { 5 | 6 | import flash.display.DisplayObject; 7 | import flash.display.DisplayObjectContainer; 8 | import com.newloop.roboteyes.core.RobotEyesMaster; 9 | import com.newloop.roboteyes.errors.RobotEyesError; 10 | 11 | /** 12 | * Class description. 13 | * 14 | * @langversion ActionScript 3.0 15 | * @playerversion Flash 9.0 16 | * 17 | * @author Lindsey Fallow 18 | * @since 07.01.2010 19 | */ 20 | public class DisplayObjectDriver extends Object { 21 | 22 | protected var _view:DisplayObject; 23 | 24 | //-------------------------------------- 25 | // CLASS CONSTANTS 26 | //-------------------------------------- 27 | 28 | //-------------------------------------- 29 | // CONSTRUCTOR 30 | //-------------------------------------- 31 | 32 | /** 33 | * @Constructor 34 | */ 35 | public function DisplayObjectDriver(view:DisplayObject){ 36 | _view = view; 37 | super(); 38 | } 39 | 40 | //-------------------------------------- 41 | // PRIVATE VARIABLES 42 | //-------------------------------------- 43 | 44 | //-------------------------------------- 45 | // GETTER/SETTERS 46 | //-------------------------------------- 47 | 48 | public function get view():DisplayObject { 49 | return _view; 50 | } 51 | 52 | //-------------------------------------- 53 | // PUBLIC METHODS 54 | //-------------------------------------- 55 | 56 | public function inViewOf(viewClazz:Class):DisplayObjectDriver{ 57 | 58 | if(_view is DisplayObjectContainer){ 59 | return RobotEyesMaster.inViewOf(viewClazz, _view as DisplayObjectContainer); 60 | 61 | } 62 | 63 | return null; 64 | } 65 | 66 | public function getA(uiClazz:Class):DisplayObjectDriverList{ 67 | 68 | if(_view is DisplayObjectContainer){ 69 | return RobotEyesMaster.getA(uiClazz, _view as DisplayObjectContainer); 70 | 71 | } 72 | 73 | return null; 74 | 75 | } 76 | 77 | public function getSome(uiClazz:Class):DisplayObjectDriverList{ 78 | 79 | if(_view is DisplayObjectContainer){ 80 | return RobotEyesMaster.getSome(uiClazz, _view as DisplayObjectContainer); 81 | 82 | } 83 | 84 | return null; 85 | 86 | } 87 | 88 | public function getAny(uiClazz:Class):DisplayObjectDriver{ 89 | 90 | if(_view is DisplayObjectContainer){ 91 | return RobotEyesMaster.getAny(uiClazz, _view as DisplayObjectContainer); 92 | 93 | } 94 | 95 | return null; 96 | 97 | } 98 | 99 | public function checkPropertyHasValueOf(propertyName:String, value:*):Boolean{ 100 | 101 | if(_view.hasOwnProperty(propertyName)){ 102 | if(_view[propertyName] == value) { 103 | return true; 104 | } 105 | return false; 106 | } 107 | // you're looking for something that doesn't exist... 108 | var err:RobotEyesError = new RobotEyesError("RobotEyes couldn't find the property " + propertyName + " on " + _view ); 109 | throw(err); 110 | 111 | return false; 112 | } 113 | 114 | public function countChildrenOfType(childClazz:Class):uint{ 115 | 116 | if(_view is DisplayObjectContainer){ 117 | return RobotEyesMaster.countChildrenOfType(childClazz, _view as DisplayObjectContainer); 118 | 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | //-------------------------------------- 125 | // EVENT HANDLERS 126 | //-------------------------------------- 127 | 128 | //-------------------------------------- 129 | // PRIVATE & PROTECTED INSTANCE METHODS 130 | //-------------------------------------- 131 | 132 | //-------------------------------------- 133 | // UNIT TESTS 134 | //-------------------------------------- 135 | 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/TestSuite.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.util.ArrayIterator; 3 | import asunit.util.Iterator; 4 | 5 | import flash.display.DisplayObjectContainer; 6 | import flash.events.Event; 7 | 8 | /** 9 | * A TestSuite is a Composite of Tests. 10 | * 11 | * @see Test 12 | * @see TestCase 13 | * 14 | * @includeExample TestSuiteExample.as 15 | */ 16 | public class TestSuite extends TestCase implements Test { 17 | private var fTests:Array = new Array(); 18 | private var testsCompleteCount:Number = 0; 19 | private var iterator:ArrayIterator; 20 | private var isRunning:Boolean; 21 | 22 | public function TestSuite() { 23 | super(); 24 | fTests = new Array(); 25 | } 26 | 27 | protected override function setTestMethods(methodNodes:XMLList):void { 28 | testMethods = new Array(); 29 | } 30 | 31 | /** 32 | * Adds a test instance to the suite. 33 | */ 34 | public function addTest(test:Test):void { 35 | if (!test.getIsComplete()) 36 | fTests.push(test); 37 | } 38 | 39 | /** 40 | * Counts the number of tests that will be run by this Suite. 41 | */ 42 | public override function countTestCases():int { 43 | var count:int; 44 | for each(var test:TestCase in fTests) { 45 | count = count + test.countTestCases(); 46 | } 47 | return count; 48 | } 49 | 50 | /** 51 | * Runs the tests and collects their result in a TestResult. 52 | */ 53 | public override function run():void { 54 | var result:TestListener = getResult(); 55 | var test:Test; 56 | var itr:Iterator = getIterator(); 57 | while(itr.hasNext()) { 58 | isRunning = true; 59 | test = Test(itr.next()); 60 | test.setResult(result); 61 | test.addEventListener(Event.COMPLETE, testCompleteHandler); 62 | test.run(); 63 | if(!test.getIsComplete()) { 64 | isRunning = false; 65 | break; 66 | } 67 | } 68 | } 69 | 70 | private function getIterator():ArrayIterator { 71 | if(iterator == null) { 72 | iterator = new ArrayIterator(fTests); 73 | } 74 | return iterator; 75 | } 76 | 77 | private function testCompleteHandler(event:Event):void { 78 | if(!isRunning) { 79 | run(); 80 | } 81 | if(++testsCompleteCount >= testCount()) { 82 | dispatchEvent(new Event(Event.COMPLETE)); 83 | } 84 | } 85 | 86 | /** 87 | * Returns the number of tests in this suite 88 | */ 89 | public function testCount():int { 90 | return fTests.length; 91 | } 92 | 93 | public override function toString():String { 94 | return getName(); 95 | } 96 | 97 | public override function getIsComplete():Boolean { 98 | for each(var test:TestCase in fTests) { 99 | if(!test.getIsComplete()) { 100 | return false; 101 | } 102 | } 103 | return true; 104 | } 105 | 106 | public override function setContext(context:DisplayObjectContainer):void { 107 | super.setContext(context); 108 | for each(var test:Test in fTests) { 109 | test.setContext(context); 110 | } 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /src/com/newloop/roboteyesdemoapp/TestTextView.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyesdemoapp { 5 | 6 | import flash.display.Sprite; 7 | import flash.events.Event; 8 | import flash.events.MouseEvent; 9 | import flash.text.TextField; 10 | 11 | import flash.geom.ColorTransform; 12 | 13 | import skins.roboteyesDemoAppSkin; 14 | 15 | /** 16 | * Sprite sub class description. 17 | * 18 | * @langversion ActionScript 3.0 19 | * @playerversion Flash 9.0 20 | * 21 | * @author Lindsey Fallow 22 | * @since 2010-01-10 23 | */ 24 | public class TestTextView extends Sprite { 25 | 26 | //-------------------------------------- 27 | // CLASS CONSTANTS 28 | //-------------------------------------- 29 | 30 | //-------------------------------------- 31 | // CONSTRUCTOR 32 | //-------------------------------------- 33 | 34 | /** 35 | * @Constructor 36 | */ 37 | public function TestTextView(){ 38 | super(); 39 | init(); 40 | } 41 | 42 | //-------------------------------------- 43 | // PRIVATE VARIABLES 44 | //-------------------------------------- 45 | 46 | private var entry_txt:TextField; 47 | 48 | private var store_txt:TextField; 49 | 50 | private var copy_btn:Sprite; 51 | 52 | private var clear_btn:Sprite; 53 | 54 | private var swapBGColour_btn:Sprite; 55 | 56 | private var backgroundSprite:Sprite; 57 | 58 | private var colour1:uint = 0x006699; 59 | private var colour2:uint = 0x993333; 60 | 61 | //-------------------------------------- 62 | // GETTER/SETTERS 63 | //-------------------------------------- 64 | 65 | //-------------------------------------- 66 | // PUBLIC METHODS 67 | //-------------------------------------- 68 | 69 | //-------------------------------------- 70 | // EVENT HANDLERS 71 | //-------------------------------------- 72 | 73 | private function copyClickHandler(evt:MouseEvent):void 74 | { 75 | // don't copy if it's blank 76 | if(entry_txt.text == ""){ 77 | return; 78 | } 79 | 80 | // 81 | store_txt.appendText(entry_txt.text + "\n"); 82 | entry_txt.text = ""; 83 | } 84 | 85 | private function clearClickHandler(evt:MouseEvent):void 86 | { 87 | store_txt.text = ""; 88 | } 89 | 90 | private function swapColourClickHandler(evt:MouseEvent):void 91 | { 92 | var newColour:uint = colour1; 93 | if(backgroundSprite.transform.colorTransform.color == colour1){ 94 | newColour = colour2; 95 | } 96 | 97 | var newTransform:ColorTransform = new ColorTransform(); 98 | newTransform.color = newColour; 99 | backgroundSprite.transform.colorTransform = newTransform; 100 | } 101 | 102 | //-------------------------------------- 103 | // PRIVATE & PROTECTED INSTANCE METHODS 104 | //-------------------------------------- 105 | 106 | /** 107 | * Initialises this object instance. 108 | */ 109 | private function init() : void 110 | { 111 | var viewSprite:Sprite = new roboteyesDemoAppSkin.TextTestViewSkin(); 112 | addChild(viewSprite); 113 | 114 | entry_txt = viewSprite['field1_txt']; 115 | store_txt = viewSprite['field2_txt']; 116 | copy_btn = viewSprite['copy_btn']; 117 | clear_btn = viewSprite['clear_btn']; 118 | swapBGColour_btn = viewSprite['swapColour_btn']; 119 | backgroundSprite = viewSprite['background_mc']; 120 | 121 | entry_txt.text =""; 122 | store_txt.text =""; 123 | 124 | setupButtons(); 125 | swapColourClickHandler(null); 126 | } 127 | 128 | private function setupButtons():void 129 | { 130 | copy_btn.buttonMode = true; 131 | clear_btn.buttonMode = true; 132 | swapBGColour_btn.buttonMode = true; 133 | 134 | copy_btn.addEventListener(MouseEvent.CLICK, copyClickHandler); 135 | clear_btn.addEventListener(MouseEvent.CLICK, clearClickHandler); 136 | swapBGColour_btn.addEventListener(MouseEvent.CLICK, swapColourClickHandler); 137 | } 138 | 139 | 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /test/com/newloop/roboteyes/drivers/TextFieldDriverTest.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes.drivers { 2 | 3 | import asunit.framework.TestCase; 4 | 5 | import flash.text.TextField; 6 | 7 | public class TextFieldDriverTest extends TestCase { 8 | private var instance:TextFieldDriver; 9 | 10 | private var testText:TextField; 11 | 12 | public function TextFieldDriverTest(methodName:String=null) { 13 | super(methodName) 14 | } 15 | 16 | override protected function setUp():void { 17 | super.setUp(); 18 | testText = new TextField(); 19 | testText.multiline = true; 20 | testText.wordWrap = true; 21 | instance = new TextFieldDriver(testText); 22 | } 23 | 24 | override protected function tearDown():void { 25 | super.tearDown(); 26 | instance = null; 27 | } 28 | 29 | public function testInstantiated():void { 30 | assertTrue("instance is TextFieldDriver", instance is TextFieldDriver); 31 | } 32 | 33 | public function testFailure():void { 34 | assertTrue("Failing test", true); 35 | } 36 | 37 | public function testEnterText():void{ 38 | instance.enterText("HelloWorld"); 39 | assertTrue("Text has been entered correctly", (testText.text == "HelloWorld")); 40 | } 41 | 42 | public function testAppendText():void{ 43 | instance.enterText("Hi "); 44 | instance.appendText("there"); 45 | assertTrue("Text has been appended correctly", (testText.text == "Hi there")); 46 | } 47 | 48 | public function testCheckTestPassesCorrectly():void{ 49 | testText.text = "HelloWorld"; 50 | assertTrue("checkText passes when text matches", (instance.checkText("HelloWorld"))); 51 | } 52 | 53 | public function testCheckTestFailsCorrectly():void{ 54 | testText.text = "Hi there"; 55 | assertFalse("checkText fails when text doesn't match", (instance.checkText("HelloWorld"))); 56 | } 57 | 58 | public function testWordCountIsPassesCorrectly():void{ 59 | testText.text = "Hello geek world"; 60 | assertTrue("wordCountIs passes when word count matches", (instance.wordCountIs(3))); 61 | } 62 | 63 | public function testWordCountIsFailsCorrectly():void{ 64 | testText.text = "Hello geek world"; 65 | assertFalse("wordCountIs passes when word count matches", (instance.wordCountIs(4))); 66 | } 67 | 68 | public function testIsNumericPassesCorrectly():void{ 69 | testText.text = "35"; 70 | assertTrue("isNumeric passes correctly", (instance.isNumeric())); 71 | } 72 | 73 | public function testIsNumericFailsCorrectly():void{ 74 | testText.text = "AB"; 75 | assertFalse("isNumeric fails correctly", (instance.isNumeric())); 76 | } 77 | 78 | public function testContainsPassesCorrectly():void{ 79 | testText.text = "The quick brown fox learned TDD"; 80 | assertTrue("contains passes correctly", (instance.contains("brown"))); 81 | } 82 | 83 | public function testContainsFailsCorrectly():void{ 84 | testText.text = "The quick brown fox learned TDD"; 85 | assertFalse("contains fails correctly", (instance.contains("green"))); 86 | } 87 | 88 | public function testIsEmptyPassesCorrectly():void{ 89 | testText.text = ""; 90 | assertTrue("isEmpty passes correctly", (instance.isEmpty())); 91 | } 92 | 93 | public function testIsEmptyFailsCorrectly():void{ 94 | testText.text = " "; 95 | assertFalse("isEmpty fails correctly", (instance.isEmpty())); 96 | } 97 | 98 | public function testIsNotEmptyPassesCorrectly():void{ 99 | testText.text = " "; 100 | assertTrue("isNotEmpty passes correctly", (instance.isNotEmpty())); 101 | } 102 | 103 | public function testIsNotEmptyFailsCorrectly():void{ 104 | testText.text = ""; 105 | assertFalse("isNotEmpty fails correctly", (instance.isNotEmpty())); 106 | } 107 | 108 | public function testIsBlankPassesCorrectly():void{ 109 | testText.text = " "; 110 | testText.appendText("\r"); 111 | testText.appendText(" "); 112 | assertTrue("isBlank passes correctly", (instance.isBlank())); 113 | } 114 | 115 | public function testIsBlankFailsCorrectly():void{ 116 | testText.text = "A"; 117 | assertFalse("isBlank fails correctly", (instance.isBlank())); 118 | } 119 | 120 | public function testIsNotBlankPassesCorrectly():void{ 121 | testText.text = "A"; 122 | assertTrue("isNotBlank passes correctly", (instance.isNotBlank())); 123 | } 124 | 125 | public function testIsNotBlankFailsCorrectly():void{ 126 | testText.text = " "; 127 | testText.appendText("\r"); 128 | testText.appendText(" "); 129 | assertFalse("isNotBlank fails correctly", (instance.isNotBlank())); 130 | } 131 | 132 | public function testTextIsPassesCorrectly():void{ 133 | testText.text = "Ruby"; 134 | assertTrue("textIs passes correctly", (instance.textIs("Ruby"))); 135 | } 136 | 137 | public function testTextIsFailsCorrectly():void{ 138 | testText.text = "Ruby"; 139 | assertFalse("textIs fails correctly", (instance.textIs("Badger"))); 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/drivers/TextFieldDriver.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes.drivers { 2 | 3 | import flash.text.TextField; 4 | import flash.events.TextEvent; 5 | import flash.events.Event; 6 | 7 | 8 | public class TextFieldDriver extends InteractiveObjectDriver { 9 | 10 | private var _textField:TextField; 11 | 12 | public function TextFieldDriver(tf:TextField) { 13 | _textField = tf; 14 | super(_textField); 15 | } 16 | 17 | public function get textField():TextField{ 18 | return _textField; 19 | } 20 | 21 | public function enterText(newText:String):void{ 22 | _textField.dispatchEvent(new TextEvent(TextEvent.TEXT_INPUT)); 23 | _textField.text = newText; 24 | _textField.dispatchEvent(new Event(Event.CHANGE)) 25 | } 26 | 27 | public function appendText(newText:String):void{ 28 | _textField.appendText(newText); 29 | } 30 | 31 | public function checkText(testText:String):Boolean{ 32 | return _textField.text == testText; 33 | } 34 | 35 | public function getText():String { 36 | return _textField.text; 37 | } 38 | 39 | public function textIs(testText:String):Boolean{ 40 | return checkText(testText); 41 | } 42 | 43 | public function isEmpty():Boolean { 44 | if (_textField.text == null) { return true; } 45 | return !_textField.text.length; 46 | } 47 | 48 | public function isNotEmpty():Boolean{ 49 | return !isEmpty(); 50 | } 51 | 52 | public function isBlank():Boolean{ 53 | return !hasText(_textField.text); 54 | } 55 | 56 | public function isNotBlank():Boolean{ 57 | return hasText(_textField.text); 58 | } 59 | 60 | public function contains(testText:String):Boolean{ 61 | return __contains(_textField.text, testText); 62 | } 63 | 64 | public function isNumeric():Boolean{ 65 | return __isNumeric(_textField.text); 66 | } 67 | 68 | public function wordCountIs(noWords:uint):Boolean{ 69 | return (wordCount(_textField.text) == noWords); 70 | } 71 | 72 | /** 73 | * Functions taken from String Utilities class by Ryan Matsikas, Feb 10 2006 74 | * 75 | * Visit www.gskinner.com for documentation, updates and more free code. 76 | * You may distribute this code freely, as long as this comment block remains intact. 77 | */ 78 | 79 | /** 80 | * Determines whether the specified string contains any instances of p_char. 81 | * 82 | * @param p_string The string. 83 | * 84 | * @param p_char The character or sub-string we are looking for. 85 | * 86 | * @returns Boolean 87 | * 88 | * @langversion ActionScript 3.0 89 | * @playerversion Flash 9.0 90 | * @tiptext 91 | */ 92 | private function __contains(p_string:String, p_char:String):Boolean { 93 | if (p_string == null) { return false; } 94 | return p_string.indexOf(p_char) != -1; 95 | } 96 | 97 | 98 | /** 99 | * Determines whether the specified string contains text. 100 | * 101 | * @param p_string The string to check. 102 | * 103 | * @returns Boolean 104 | * 105 | * @langversion ActionScript 3.0 106 | * @playerversion Flash 9.0 107 | * @tiptext 108 | */ 109 | private function hasText(p_string:String):Boolean { 110 | var str:String = removeExtraWhitespace(p_string); 111 | return !!str.length; 112 | } 113 | 114 | 115 | /** 116 | * Determines whether the specified string is numeric. 117 | * 118 | * @param p_string The string. 119 | * 120 | * @returns Boolean 121 | * 122 | * @langversion ActionScript 3.0 123 | * @playerversion Flash 9.0 124 | * @tiptext 125 | */ 126 | private function __isNumeric(p_string:String):Boolean { 127 | if (p_string == null) { return false; } 128 | var regx:RegExp = /^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$/; 129 | return regx.test(p_string); 130 | } 131 | 132 | /** 133 | * Determins the number of words in a string. 134 | * 135 | * @param p_string The string. 136 | * 137 | * @returns uint 138 | * 139 | * @langversion ActionScript 3.0 140 | * @playerversion Flash 9.0 141 | * @tiptext 142 | */ 143 | private function wordCount(p_string:String):uint { 144 | if (p_string == null) { return 0; } 145 | return p_string.match(/\b\w+\b/g).length; 146 | } 147 | 148 | /** 149 | * Removes whitespace from the front and the end of the specified 150 | * string. 151 | * 152 | * @param p_string The String whose beginning and ending whitespace will 153 | * will be removed. 154 | * 155 | * @returns String 156 | * 157 | * @langversion ActionScript 3.0 158 | * @playerversion Flash 9.0 159 | * @tiptext 160 | */ 161 | private function trim(p_string:String):String { 162 | if (p_string == null) { return ''; } 163 | return p_string.replace(/^\s+|\s+$/g, ''); 164 | } 165 | 166 | /** 167 | * Removes extraneous whitespace (extra spaces, tabs, line breaks, etc) from the 168 | * specified string. 169 | * 170 | * @param p_string The String whose extraneous whitespace will be removed. 171 | * 172 | * @returns String 173 | * 174 | * @langversion ActionScript 3.0 175 | * @playerversion Flash 9.0 176 | * @tiptext 177 | */ 178 | private function removeExtraWhitespace(p_string:String):String { 179 | if (p_string == null) { return ''; } 180 | var str:String = trim(p_string); 181 | return str.replace(/\s+/g, ' '); 182 | } 183 | 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/TestResult.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.errors.AssertionFailedError; 3 | import asunit.errors.InstanceNotFoundError; 4 | 5 | /** 6 | * A TestResult collects the results of executing 7 | * a test case. It is an instance of the Collecting Parameter pattern. 8 | * The test framework distinguishes between failures and errors. 9 | * A failure is anticipated and checked for with assertions. Errors are 10 | * unanticipated problems like an ArrayIndexOutOfBoundsException. 11 | * 12 | * @see Test 13 | */ 14 | public class TestResult implements TestListener { 15 | protected var fFailures:Array; 16 | protected var fErrors:Array; 17 | protected var fListeners:Array; 18 | protected var fRunTests:int; 19 | private var fStop:Boolean; 20 | 21 | public function TestResult() { 22 | fFailures = new Array(); 23 | fErrors = new Array(); 24 | fListeners = new Array(); 25 | fRunTests = 0; 26 | fStop = false; 27 | } 28 | /** 29 | * Adds an error to the list of errors. The passed in exception 30 | * caused the error. 31 | */ 32 | public function addError(test:Test, t:Error):void { 33 | fErrors.push(new TestFailure(test, t)); 34 | var len:uint = fListeners.length; 35 | var item:TestListener; 36 | for(var i:uint; i < len; i++) { 37 | item = TestListener(fListeners[i]); 38 | item.addError(test, t); 39 | } 40 | } 41 | /** 42 | * Adds a failure to the list of failures. The passed in exception 43 | * caused the failure. 44 | */ 45 | public function addFailure(test:Test, t:AssertionFailedError):void { 46 | fFailures.push(new TestFailure(test, t)); 47 | var len:uint = fListeners.length; 48 | var item:TestListener; 49 | for(var i:uint; i < len; i++) { 50 | item = TestListener(fListeners[i]); 51 | item.addFailure(test, t); 52 | } 53 | } 54 | /** 55 | * Registers a TestListener 56 | */ 57 | public function addListener(listener:TestListener):void { 58 | fListeners.push(listener); 59 | } 60 | /** 61 | * Unregisters a TestListener 62 | */ 63 | public function removeListener(listener:TestListener):void { 64 | var len:uint = fListeners.length; 65 | for(var i:uint; i < len; i++) { 66 | if(fListeners[i] == listener) { 67 | fListeners.splice(i, 1); 68 | return; 69 | } 70 | } 71 | throw new InstanceNotFoundError("removeListener called without listener in list"); 72 | } 73 | /** 74 | * Gets the number of detected errors. 75 | */ 76 | public function errorCount():int { 77 | return fErrors.length; 78 | } 79 | /** 80 | * Returns an Enumeration for the errors 81 | */ 82 | public function errors():Array { 83 | return fErrors; 84 | } 85 | /** 86 | * Gets the number of detected failures. 87 | */ 88 | public function failureCount():int { 89 | return fFailures.length; 90 | } 91 | /** 92 | * Returns an Enumeration for the failures 93 | */ 94 | public function failures():Array { 95 | return fFailures; 96 | } 97 | 98 | /** 99 | * Runs a TestCase. 100 | */ 101 | public function run(test:Test):void { 102 | startTest(test); 103 | test.runBare(); 104 | } 105 | /** 106 | * Gets the number of run tests. 107 | */ 108 | public function runCount():int { 109 | return fRunTests; 110 | } 111 | /** 112 | * Checks whether the test run should stop 113 | */ 114 | public function shouldStop():Boolean { 115 | return fStop; 116 | } 117 | /** 118 | * Informs the result that a test will be started. 119 | */ 120 | public function startTest(test:Test):void { 121 | var count:int = test.countTestCases(); 122 | fRunTests += count; 123 | 124 | var len:uint = fListeners.length; 125 | var item:TestListener; 126 | for(var i:uint; i < len; i++) { 127 | item = TestListener(fListeners[i]); 128 | item.startTest(test); 129 | } 130 | } 131 | 132 | public function startTestMethod(test:Test, method:String):void { 133 | var len:uint = fListeners.length; 134 | var item:TestListener; 135 | for(var i:uint; i < len; i++) { 136 | item = TestListener(fListeners[i]); 137 | item.startTestMethod(test, method); 138 | } 139 | } 140 | 141 | public function endTestMethod(test:Test, method:String):void { 142 | var len:uint = fListeners.length; 143 | var item:TestListener; 144 | for(var i:uint; i < len; i++) { 145 | item = TestListener(fListeners[i]); 146 | item.endTestMethod(test, method); 147 | } 148 | } 149 | 150 | /** 151 | * Informs the result that a test was completed. 152 | */ 153 | public function endTest(test:Test):void { 154 | var len:uint = fListeners.length; 155 | var item:TestListener; 156 | for(var i:uint; i < len; i++) { 157 | item = TestListener(fListeners[i]); 158 | item.endTest(test); 159 | } 160 | } 161 | /** 162 | * Marks that the test run should stop. 163 | */ 164 | public function stop():void { 165 | fStop = true; 166 | } 167 | /** 168 | * Returns whether the entire test was successful or not. 169 | */ 170 | public function wasSuccessful():Boolean { 171 | return failureCount() == 0 && errorCount() == 0; 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/AsynchronousTestCase.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | 3 | import asunit.errors.AbstractError; 4 | 5 | import flash.errors.IllegalOperationError; 6 | import flash.events.*; 7 | import flash.net.URLLoader; 8 | import flash.utils.getTimer; 9 | 10 | /** 11 | * Extend this class if you have a TestCase that requires the 12 | * asynchronous load of external data. 13 | */ 14 | public class AsynchronousTestCase extends TestCase implements Test { 15 | 16 | protected static const DEFAULT_REMOTE_TIMEOUT:int = 30000; 17 | private static const INVALID_TIME:int = -1; 18 | 19 | private var _ioErrorExpected:Boolean; 20 | private var _remoteDuration:int; 21 | private var _remoteStartTime:int; 22 | private var _remoteTimeout:int; 23 | private var _securityErrorExpected:Boolean; 24 | 25 | public function AsynchronousTestCase(testMethod:String = null) { 26 | super(testMethod); 27 | _remoteStartTime = INVALID_TIME; 28 | 29 | // set defaults for user-configurable properties: 30 | _remoteTimeout = DEFAULT_REMOTE_TIMEOUT; 31 | _ioErrorExpected = false; 32 | _securityErrorExpected = false; 33 | } 34 | 35 | public function get remoteDuration():int { 36 | return _remoteDuration; 37 | } 38 | 39 | public function remoteDurationIsValid():Boolean { 40 | return _remoteDuration != INVALID_TIME; 41 | } 42 | 43 | // see testRemoteDuration() below 44 | public function set remoteTimeout(ms:int):void { 45 | _remoteTimeout = ms; 46 | } 47 | 48 | public function set ioErrorExpected(yn:Boolean):void { 49 | _ioErrorExpected = yn; 50 | } 51 | 52 | public function set securityErrorExpected(yn:Boolean):void { 53 | _securityErrorExpected = yn; 54 | } 55 | 56 | // use this method in overriding run() if you are using a URLLoader: 57 | protected function configureListeners(loader:URLLoader):void { 58 | loader.addEventListener(Event.COMPLETE, completeHandler); 59 | loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler); 60 | loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); 61 | loader.addEventListener(Event.OPEN, openHandler); 62 | loader.addEventListener(ProgressEvent.PROGRESS, progressHandler); 63 | loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); 64 | } 65 | 66 | // in a subclass, you should override this method and call super.run() at the end 67 | public override function run():void { 68 | if ((this as Object).constructor == AsynchronousTestCase) 69 | { 70 | throw new AbstractError("run() method must be overridden in class derived from AsynchronousTestCase"); 71 | } 72 | 73 | startRemoteDuration(); 74 | } 75 | 76 | private final function startRemoteDuration():void { 77 | _remoteStartTime = getTimer(); 78 | } 79 | 80 | private final function setRemoteDuration():void { 81 | if (_remoteStartTime == INVALID_TIME) { 82 | // I guess you overrode run() in a subclass without calling super.run() 83 | _remoteDuration = INVALID_TIME; 84 | } 85 | else { 86 | _remoteDuration = getTimer() - _remoteStartTime; 87 | } 88 | } 89 | 90 | protected final function completeHandler(event:Event):void { 91 | setRemoteDuration(); 92 | setDataSource(event); 93 | // call super.run() to execute test methods: 94 | runTests(); 95 | } 96 | 97 | // override this method to put a copy of the data into a member reference 98 | protected function setDataSource(event:Event):void { 99 | throw new AbstractError("setDataSource must be overridden in class derived from AsynchronousTestCase"); 100 | } 101 | 102 | // this method gives derived classes access to TestCase.run() 103 | protected final function runTests():void { 104 | super.run(); 105 | } 106 | 107 | // TODO: add support for failing status events... 108 | protected function httpStatusHandler(event:HTTPStatusEvent):void { 109 | // I believe this is useless except in AIR. 110 | } 111 | 112 | protected final function ioErrorHandler(event:IOErrorEvent):void { 113 | result.startTest(this); 114 | if (_ioErrorExpected == false) 115 | { 116 | // access is authorized and we didn't get in: log the error 117 | result.addError(this, new IllegalOperationError(event.text)); 118 | } 119 | setRemoteDuration(); 120 | testRemoteDuration(); 121 | dispatchEvent(new Event(Event.COMPLETE)); 122 | } 123 | 124 | protected function openHandler(event:Event):void { 125 | } 126 | 127 | protected function progressHandler(event:ProgressEvent):void { 128 | } 129 | 130 | protected final function securityErrorHandler(event:SecurityErrorEvent):void { 131 | result.startTest(this); 132 | if (_securityErrorExpected == false) 133 | { 134 | // access is authorized and we didn't get in: log the error 135 | result.addError(this, new IllegalOperationError(event.text)); 136 | } 137 | setRemoteDuration(); 138 | testRemoteDuration(); 139 | dispatchEvent(new Event(Event.COMPLETE)); 140 | } 141 | 142 | public function testRemoteDuration():void { 143 | if (!remoteDurationIsValid()) 144 | { 145 | return; 146 | } 147 | if (_remoteDuration > _remoteTimeout) 148 | { 149 | result.addError(this, new IllegalOperationError("remote communication took too long: " + _remoteDuration/1000 + " seconds.\n" + this.toString())); 150 | } 151 | } 152 | 153 | public function testUnauthorizedAccess():void { 154 | if (_securityErrorExpected || _ioErrorExpected) 155 | { 156 | fail("unauthorized access permitted (expected no access)\n" + this.toString()); 157 | } 158 | } 159 | 160 | } 161 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/textui/TestRunner.as: -------------------------------------------------------------------------------- 1 | package asunit.textui { 2 | import asunit.framework.Test; 3 | import asunit.framework.TestResult; 4 | 5 | import flash.display.MovieClip; 6 | import flash.display.StageAlign; 7 | import flash.display.StageScaleMode; 8 | import flash.events.Event; 9 | import flash.system.fscommand; 10 | import flash.utils.clearInterval; 11 | import flash.utils.describeType; 12 | import flash.utils.getTimer; 13 | import flash.utils.setInterval; 14 | import flash.utils.Timer; 15 | import flash.events.TimerEvent; 16 | import flash.display.DisplayObject; 17 | 18 | /** 19 | * The base class for ActionScript 3.0 test harness. 20 | * 21 | * The TestRunner should be extended by your 22 | * concrete runner for your project. 23 | * 24 | * If you're building a Flex application, you will need to 25 | * extend the FlexRunner 26 | * 27 | * Your concrete runner will usually look like the following: 28 | * 29 | * package { 30 | * import asunit.textui.TestRunner; 31 | * 32 | * public class MyProjectRunner extends TestRunner { 33 | * 34 | * public function MyProjectRunner() { 35 | * // start(clazz:Class, methodName:String, showTrace:Boolean) 36 | * // NOTE: sending a particular class and method name will 37 | * // execute setUp(), the method and NOT tearDown. 38 | * // This allows you to get visual confirmation while developing 39 | * // visual entities 40 | * start(AllTests, null, TestRunner.SHOW_TRACE); 41 | * } 42 | * } 43 | * } 44 | * 45 | * 46 | * @includeExample TestRunnerExample.as 47 | * 48 | * @see asunit.textui.FlexRunner 49 | * @see asunit.textui.AirRunner 50 | * @see asunit.textui.XMLResultPrinter 51 | **/ 52 | public class TestRunner extends MovieClip { 53 | public static const SUCCESS_EXIT:int = 0; 54 | public static const FAILURE_EXIT:int = 1; 55 | public static const EXCEPTION_EXIT:int = 2; 56 | public static const SHOW_TRACE:Boolean = true; 57 | protected var fPrinter:ResultPrinter; 58 | protected var startTime:Number; 59 | protected var result:TestResult; 60 | 61 | public function TestRunner() { 62 | configureListeners(); 63 | } 64 | 65 | private function configureListeners():void { 66 | addEventListener(Event.ADDED_TO_STAGE, addedHandler); 67 | addEventListener(Event.ADDED, addedHandler); 68 | } 69 | 70 | protected function addedHandler(event:Event):void { 71 | if (!stage) 72 | { 73 | return; 74 | } 75 | if(event.target === fPrinter) { 76 | stage.align = StageAlign.TOP_LEFT; 77 | stage.scaleMode = StageScaleMode.NO_SCALE; 78 | stage.addEventListener(Event.RESIZE, resizeHandler); 79 | resizeHandler(new Event("resize")); 80 | } 81 | } 82 | 83 | private function resizeHandler(event:Event):void { 84 | fPrinter.width = stage.stageWidth; 85 | fPrinter.height = stage.stageHeight; 86 | } 87 | 88 | /** 89 | * Starts a test run based on the TestCase or TestSuite provided. 90 | * 91 | * If a concrete TestCase is provided to the start method, 92 | * you can also provide the string name of a single test method to execute. 93 | * 94 | * This will run the TestCase setUp method, then 95 | * the test method name that was provided, and will not run tearDown. 96 | * 97 | * This is a great way to build visual components in isolation and verify that they 98 | * behave as expected. 99 | * 100 | * @example The start method can accept a concrete test case and test method name: 101 | * 102 | * start(MyTestCase, 'myTestMethod'); 103 | * 104 | * 105 | * @example The start method usually accepts a test suite that includes all of your 106 | * test methods. 107 | * 108 | * start(AllTests, null, TestRunner.SHOW_TRACE); 109 | * 110 | * 111 | * @see TestSuite 112 | */ 113 | public function start(testCase:Class, testMethod:String = null, showTrace:Boolean = false):TestResult { 114 | // fscommand("showmenu", "false"); 115 | try { 116 | var instance:Test; 117 | if(testMethod != null) { 118 | instance = new testCase(testMethod); 119 | } 120 | else { 121 | instance = new testCase(); 122 | } 123 | return doRun(instance, showTrace); 124 | } 125 | catch(e:Error) { 126 | throw new Error("Could not create and run test suite: " + e.getStackTrace()); 127 | } 128 | return null; 129 | } 130 | 131 | public function doRun(test:Test, showTrace:Boolean = false):TestResult { 132 | 133 | result = new TestResult(); 134 | 135 | if (test.getIsComplete()) 136 | return result; 137 | 138 | if(fPrinter == null) { 139 | setPrinter(new ResultPrinter(showTrace)); 140 | } 141 | else { 142 | fPrinter.setShowTrace(showTrace); 143 | } 144 | result.addListener(getPrinter()); 145 | startTime = getTimer(); 146 | test.setResult(result); 147 | test.setContext(this); 148 | test.addEventListener(Event.COMPLETE, testCompleteHandler); 149 | test.run(); 150 | return result; 151 | } 152 | 153 | private function testCompleteHandler(event:Event):void { 154 | var endTime:Number = getTimer(); 155 | var runTime:Number = endTime - startTime; 156 | getPrinter().printResult(result, runTime); 157 | } 158 | 159 | public function setPrinter(printer:ResultPrinter):void { 160 | if(fPrinter is DisplayObject && getChildIndex(fPrinter)) { 161 | removeChild(fPrinter); 162 | } 163 | 164 | fPrinter = printer; 165 | if(fPrinter is DisplayObject) { 166 | addChild(fPrinter); 167 | } 168 | } 169 | 170 | public function getPrinter():ResultPrinter { 171 | return fPrinter; 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/RemotingTestCase.as: -------------------------------------------------------------------------------- 1 | package asunit.framework 2 | { 3 | import flash.errors.IllegalOperationError; 4 | import flash.events.IOErrorEvent; 5 | import flash.events.NetStatusEvent; 6 | import flash.events.SecurityErrorEvent; 7 | import flash.net.NetConnection; 8 | import flash.net.ObjectEncoding; 9 | import flash.net.Responder; 10 | 11 | import asunit.framework.TestCase; 12 | import asunit.util.ArrayIterator; 13 | 14 | /** 15 | * RemotingTestCase 16 | * @author Jens Krause [www.websector.de] 17 | * @date 11/29/07 18 | * 19 | */ 20 | public class RemotingTestCase extends TestCase 21 | { 22 | 23 | protected var connection: NetConnection; 24 | /** 25 | * Constructor 26 | * @param testMethod String Name of the test case 27 | * 28 | */ 29 | public function RemotingTestCase(testMethod: String = null) 30 | { 31 | super(testMethod); 32 | } 33 | 34 | /** 35 | * Inits a netConnection instance and add all necessary event listeners 36 | * 37 | */ 38 | protected function initConnection():void 39 | { 40 | if (connection == null) 41 | { 42 | connection = new NetConnection(); 43 | 44 | connection.addEventListener(NetStatusEvent.NET_STATUS, connectionStatusHandler); 45 | connection.addEventListener(IOErrorEvent.IO_ERROR, connectionIOErrorHandler); 46 | connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR , connectionSecurityErrorHandler); 47 | } 48 | } 49 | 50 | /** 51 | * Dispose the netConnection instance 52 | * 53 | */ 54 | protected function disposeConnection():void 55 | { 56 | if (connection != null) 57 | { 58 | connection.removeEventListener(NetStatusEvent.NET_STATUS, connectionStatusHandler); 59 | connection.removeEventListener(IOErrorEvent.IO_ERROR, connectionIOErrorHandler); 60 | connection.removeEventListener(SecurityErrorEvent.SECURITY_ERROR , connectionSecurityErrorHandler); 61 | 62 | connection = null; 63 | } 64 | } 65 | 66 | /** 67 | * Callback handler for receiving SecurityErrorEvent 68 | * @param event SecurityErrorEvent 69 | * 70 | */ 71 | protected function connectionSecurityErrorHandler(event: SecurityErrorEvent): void 72 | { 73 | result.addError(this, new IllegalOperationError(event.toString())); 74 | isComplete = true; 75 | } 76 | 77 | /** 78 | * Callback handler for receiving IOErrorEvent 79 | * @param event IOErrorEvent 80 | * 81 | */ 82 | protected function connectionIOErrorHandler(event: IOErrorEvent): void 83 | { 84 | result.addError(this, new IllegalOperationError(event.toString())); 85 | isComplete = true; 86 | } 87 | 88 | /** 89 | * Callback handler for receiving NetStatusEvent 90 | * @param event NetStatusEvent 91 | * 92 | */ 93 | protected function connectionStatusHandler(event: NetStatusEvent): void 94 | { 95 | 96 | } 97 | 98 | /** 99 | * Connects the gateway 100 | * 101 | * @param $gateway String Remote gateway 102 | * @param $encoding uint Object encoding using either AMF0 or AMF3 103 | * 104 | */ 105 | protected function connect ($gateway: String = null, $encoding: uint = 0): void 106 | { 107 | initConnection(); 108 | 109 | connection.objectEncoding = ($encoding > ObjectEncoding.AMF0) ? $encoding : ObjectEncoding.AMF0; 110 | 111 | try { 112 | connection.connect($gateway); 113 | } 114 | catch(error: Error) 115 | { 116 | result.addError(this, error); 117 | } 118 | }; 119 | 120 | /** 121 | * Calls a remote service method and test it 122 | * 123 | * @param $method String Remote service 124 | * @param $responder Responder Responder to handle remoting calls 125 | * @param $arguments Array Rest paramaters (optional) 126 | * 127 | */ 128 | protected function call ($method: String = null, $responder: Responder = null, ...$arguments): void 129 | { 130 | var hasReferenceError: Boolean = false; 131 | 132 | // parameters for calling connection.call(); 133 | // To avoid using the type unsafe ...rest operator I decided to use type safe parameters within RemotingTestCase.call() 134 | // and apply these later to connection.call(); 135 | var params: Array = []; 136 | 137 | // check remote method 138 | if ($method != null) 139 | { 140 | params.push($method); 141 | } 142 | else 143 | { 144 | result.addError(this, new ReferenceError("RemotingTestCase.call() has to defined a remote method.")); 145 | hasReferenceError = true; 146 | } 147 | 148 | // check responder 149 | if ($responder != null) 150 | { 151 | params.push($responder); 152 | } 153 | else 154 | { 155 | result.addError(this, new ReferenceError("RemotingTestCase.call() has to defined a responder to handling its results.")); 156 | hasReferenceError = true; 157 | } 158 | 159 | // In case of a reference error invoke test running instantly 160 | // to show the errors created above and return 161 | if (hasReferenceError) 162 | { 163 | super.run(); 164 | return; 165 | } 166 | 167 | 168 | var arrIterator: ArrayIterator = new ArrayIterator($arguments); 169 | while (arrIterator.hasNext()) 170 | { 171 | params.push(arrIterator.next()); 172 | } 173 | 174 | // call remote service 175 | try { 176 | connection.call.apply(null, params); 177 | } 178 | catch(error: Error) 179 | { 180 | result.addError(this, error); 181 | } 182 | 183 | 184 | }; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /test/com/newloop/roboteyes/core/RobotEyesTest.as: -------------------------------------------------------------------------------- 1 | package com.newloop.roboteyes.core { 2 | 3 | import asunit.framework.TestCase; 4 | 5 | import robotEyesDemoApp; 6 | import skins.roboteyesDemoAppSkin; 7 | 8 | import com.newloop.roboteyesdemoapp.TestTextView; 9 | import com.newloop.roboteyesdemoapp.RotatingShapesView; 10 | import com.newloop.roboteyesdemoapp.RotatingSquareView; 11 | 12 | import flash.display.DisplayObject; 13 | import flash.display.InteractiveObject; 14 | import flash.display.Shape; 15 | import flash.display.SimpleButton; 16 | import flash.display.Sprite; 17 | import flash.events.Event; 18 | import flash.events.TimerEvent; 19 | import flash.text.TextField; 20 | import flash.utils.Timer; 21 | 22 | import com.newloop.roboteyes.errors.RobotEyesError; 23 | import com.newloop.roboteyes.inViewOf; 24 | import com.newloop.roboteyes.drivers.DisplayObjectDriver; 25 | import com.newloop.roboteyes.drivers.TextFieldDriver; 26 | import com.newloop.roboteyes.drivers.InteractiveObjectDriver; 27 | 28 | 29 | 30 | public class RobotEyesTest extends TestCase { 31 | private var robotEyes:RobotEyes; 32 | 33 | public function RobotEyesTest(methodName:String=null) { 34 | super(methodName) 35 | } 36 | 37 | override public function run():void{ 38 | trace("RobotEyesTest: run"); 39 | 40 | if(robotEyes==null){ 41 | robotEyes = new RobotEyes(robotEyesDemoApp); 42 | addChild(robotEyes); 43 | robotEyes.visible = false; 44 | } 45 | // need to wait a while 46 | var timer:Timer = new Timer(1000,1); 47 | timer.addEventListener(TimerEvent.TIMER, timerHandler); 48 | timer.start(); 49 | } 50 | 51 | private function timerHandler(e:TimerEvent):void{ 52 | trace("RobotEyesTest timerHandler"); 53 | robotEyes.visible = true; 54 | super.run(); 55 | } 56 | 57 | override protected function setUp():void { 58 | super.setUp(); 59 | 60 | } 61 | 62 | override protected function tearDown():void { 63 | super.tearDown(); 64 | } 65 | 66 | override protected function cleanUp():void{ 67 | removeChild(robotEyes); 68 | robotEyes = null; 69 | } 70 | 71 | public function testInstantiated():void { 72 | assertTrue("robotEyes is RobotEyes", robotEyes is RobotEyes); 73 | } 74 | 75 | public function testFailure():void { 76 | assertTrue("Failing test", true); 77 | } 78 | 79 | public function testChucksAnErrorWhenViewNotFound():void{ 80 | assertThrows(RobotEyesError, function():void{ 81 | var viewDriver:DisplayObjectDriver = inViewOf(TestTextView).getA(SimpleButton); 82 | }); 83 | } 84 | 85 | public function testCanFindCorrectTopLevelView():void{ 86 | var viewDriver:DisplayObjectDriver = inViewOf(TestTextView); 87 | assertTrue("View driver is not null", (viewDriver!=null)); 88 | var view:DisplayObject = viewDriver.view; 89 | assertTrue("View is not null", (view!=null)); 90 | assertTrue("View is of correct type", (view is TestTextView)); 91 | } 92 | 93 | public function testCanFindAnyNestedViewUsingGetA():void{ 94 | var viewDriver:DisplayObjectDriver = inViewOf(TestTextView).getA(Sprite); 95 | assertTrue("View driver is not null", (viewDriver!=null)); 96 | var view:DisplayObject = viewDriver.view; 97 | assertTrue("View is not null", (view!=null)); 98 | assertTrue("View is of correct type", (view is Sprite)); 99 | } 100 | 101 | public function testCanFindNestedViewUsingGetANamed():void{ 102 | var viewDriver:DisplayObjectDriver = inViewOf(TestTextView).inViewOf(roboteyesDemoAppSkin.TextTestViewSkin).getA(Sprite).named("background_mc"); 103 | assertTrue("View driver is not null", (viewDriver!=null)); 104 | var view:DisplayObject = viewDriver.view; 105 | assertTrue("View is not null", (view!=null)); 106 | assertTrue("View is of correct type", (view is Sprite)); 107 | } 108 | 109 | public function testCanFindCorrectNestedViewUsingInViewOf():void{ 110 | var viewDriver:DisplayObjectDriver = inViewOf(RotatingShapesView).inViewOf(RotatingSquareView); 111 | assertTrue("View driver is not null", (viewDriver!=null)); 112 | var view:DisplayObject = viewDriver.view; 113 | assertTrue("View is not null", (view!=null)); 114 | assertTrue("View is of correct type", (view is RotatingSquareView)); 115 | } 116 | 117 | public function testCanFindCorrectDoubleNestedViewUsingGetAWithProperty():void{ 118 | var viewDriver:DisplayObjectDriver = inViewOf(RotatingShapesView).inViewOf(RotatingSquareView).getA(Sprite).withProperty('alpha', 1); 119 | assertTrue("View driver is not null", (viewDriver!=null)); 120 | var view:DisplayObject = viewDriver.view; 121 | assertTrue("View is not null", (view!=null)); 122 | assertTrue("View is of correct type", (view is Sprite)); 123 | } 124 | 125 | public function testCanFindCorrectViewUsingInViewOfWithoutNesting():void{ 126 | var viewDriver:DisplayObjectDriver = inViewOf(RotatingSquareView); 127 | assertTrue("View driver is not null", (viewDriver!=null)); 128 | var view:DisplayObject = viewDriver.view; 129 | assertTrue("View is not null", (view!=null)); 130 | assertTrue("View is of correct type", (view is RotatingSquareView)); 131 | } 132 | 133 | public function testCanFindCorrectTextFieldDriver():void{ 134 | var textFieldDriver:TextFieldDriver = inViewOf(TestTextView).inViewOf(roboteyesDemoAppSkin.TextTestViewSkin).getA(TextField).named("field1_txt") as TextFieldDriver; 135 | var textField:TextField = textFieldDriver.textField; 136 | assertTrue("TextFieldDriver doesn't think textfield contains 'blah'", (textFieldDriver.checkText('blah')==false)); 137 | textFieldDriver.enterText("Hello world"); 138 | assertTrue("TextField contains Hello world", (textField.text == "Hello world")); 139 | assertTrue("TextFieldDriver verifies text contains 'Hello world'", (textFieldDriver.checkText('Hello world'))); 140 | } 141 | 142 | public function testCanFindCorrectInteractiveObjectDriver():void{ 143 | var buttonDriver:InteractiveObjectDriver = inViewOf(TestTextView).inViewOf(roboteyesDemoAppSkin.TextTestViewSkin).getA(Sprite).withProperty("name", "copy_btn") as InteractiveObjectDriver; 144 | 145 | assertTrue("button driver is not null", (buttonDriver!=null)); 146 | var button:InteractiveObject = buttonDriver.item; 147 | assertTrue("Button is not null", (button!=null)); 148 | 149 | } 150 | 151 | public function testCanUseInteractiveObjectDriverToClick():void{ 152 | var textFieldDriver:TextFieldDriver = inViewOf(TestTextView).inViewOf(roboteyesDemoAppSkin.TextTestViewSkin).getA(TextField).named("field1_txt") as TextFieldDriver; 153 | textFieldDriver.enterText("Copy test"); 154 | var buttonDriver:InteractiveObjectDriver = inViewOf(TestTextView).inViewOf(roboteyesDemoAppSkin.TextTestViewSkin).getA(Sprite).withProperty("name", "copy_btn") as InteractiveObjectDriver; 155 | var asyncTest:Function = addAsync(null, 2000,textShouldBeCopied); 156 | buttonDriver.click(); 157 | } 158 | 159 | public function textShouldBeCopied(e:Event):void{ 160 | var textFieldDriver:TextFieldDriver = inViewOf(TestTextView).inViewOf(roboteyesDemoAppSkin.TextTestViewSkin).getA(TextField).named("field2_txt") as TextFieldDriver; 161 | assertTrue('Text has been copied', textFieldDriver.contains("Copy test")); 162 | } 163 | 164 | } 165 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## RobotEyes can help you end-to-end test your AS3 app 2 | 3 | Inspired by a hybrid of WindowLicker (for Java) and Drew Bourne's Mockolate (for AS3). 4 | 5 | RobotEyes should really be called RobotEyes and RobotFingers. It's called RobotEyes because it was developed for RobotLegs... but then I removed all the RobotLegs dependencies. Ho hum. 6 | 7 | The aim is to deliver end-to-end testing to AS3 applications. 8 | 9 | Currently I'm only adding functionality as I actually need to make use of it, so feel free to fork and expand. 10 | 11 | Functionality included in this version has been tested by incorporation in an end-to-end test of an application. It may well do unexpected things. 12 | 13 | ## What's an end-to-end test? 14 | 15 | In TDD speak (Test Driven Development), an end-to-end test is one that proves that your application carries out one of your user stories successfully. 16 | 17 | A good example would be that, given a certain viable user/password combination, when the login button is clicked the login procedure completes and whatever application state change is required occurs. Or - that given a blank username, clicking doesn't submit the details to the login service. Or - that given a crappy user/password combination, the login fails and the application handles this gracefully, with user feedback... you get the idea. 18 | 19 | End-to-end testing is different from Unit Testing and is additional to it - not a replacement for it. It aims to provide certainty that your actual application works, not just your individual classes, and, in doing so, it'll usually include coverage of any backend services as well. 20 | 21 | ## How do I use RobotEyes? 22 | 23 | RobotEyes is designed to integrate with your Unit Testing framework - it was developed for ASUnit 3 but doesn't have any dependencies. 24 | 25 | The idea is that you set your tests up to use RobotEyes as the user: both to visually verify that certain things appear how they should, and to enter text, press buttons, operate scrollers and so on. RobotEyes provides for this by supplying you with a driver wrapping your UIElements / Views. 26 | 27 | If your test requires a TextField nested within a certain view you can grab a driver for that view using: 28 | 29 | var textDriver:TextFieldDriver = inViewOf(LoginPanel).getA(TextField).named("username_txt"); 30 | 31 | The TextFieldDriver provides some useful functions: 32 | 33 | textDriver.enterText('User A'); 34 | 35 | ... this sets the text, but also fires the TextEvent.TEXT_INPUT event before, and the Event.CHANGE event after, just as if a real people type person had edited it. 36 | 37 | Then you can also use the TextFieldDriver.checkText('Blah') function in a test: 38 | 39 | assertTrue('TextField starts blank', (textDriver.(checkText('')))); 40 | 41 | If you want to be specific about the view containing the view you're hooking into - for example, if you have a view that recurs in your app you can nest 'inViewOf' - start at the outside and work inward: 42 | 43 | var textDriver:TextFieldDriver = inViewOf(StatsReportScreen).inViewOf(DateTimeWidget).getA(TextField).named("weekdayAbbreviation_txt"); 44 | 45 | ## You can also: 46 | 47 | ### Get an interactive object (in this case by specifying a property) and click it: 48 | 49 | var buttonDriver:InteractiveObjectDriver = inViewOf(InterestingView).getA(Sprite).withProperty('name', 'btn_login'); 50 | buttonDriver.click(); 51 | 52 | This will dispatch a MouseEvent.CLICK from the button / sprite / whatever you specified. 53 | 54 | List of helpers for the InteractiveObjectDriver: 55 | click(); 56 | mouseOver(); 57 | mouseOut(); 58 | mouseDown(); 59 | mouseUp(); 60 | rollOver(); 61 | rollOut(); 62 | 63 | ### Get a general view and check something about it: 64 | 65 | var loginScreenDriver:DisplayObjectDriver = inViewOf(ShellContextView).getA(LoginPanel); 66 | var loginScreen:DisplayObject = loginScreenDriver.view; 67 | assertTrue('LoginPanel is off screen', (loginScreen.y < (-loginScreen.height))); 68 | 69 | ### Count instances of a specific type - for example to check that the correct number of instances have been added to a list 70 | 71 | var listHolderDriver:DisplayObjectDriver = inViewOf(SomeApp).getA(ListHolder); 72 | assertEquals('Correct number of items added to the list', 8, listHolderDriver.countInstancesOf(ListItem)); 73 | 74 | ### TestCase Examples: 75 | 76 | To use RobotEyes you need to grab an instance of it and tell it which class to use to start up your application. 77 | You probably don't want to start your tests instantly - give the app a little room to breathe if it has async startup stuff. 78 | 79 | In AsUnit 3 this is done with: 80 | 81 | // these are the really important RobotEyes classes 82 | import com.newloop.roboteyes.core.RobotEyes; 83 | import com.newloop.roboteyes.inViewOf; 84 | 85 | // grab any drivers that you need to use - currently there are only 3 but more to come... 86 | import com.newloop.roboteyes.drivers.DisplayObjectDriver; 87 | import com.newloop.roboteyes.drivers.InteractiveObjectDriver; 88 | import com.newloop.roboteyes.drivers.TextFieldDriver; 89 | 90 | // the main class for the app you want to test 91 | import com.client.app.AcademyShell; 92 | 93 | public class RobotEyesTest extends TestCase { 94 | private var robotEyes:RobotEyes; 95 | 96 | public function RobotEyesTest(methodName:String=null) { 97 | super(methodName) 98 | } 99 | 100 | override public function run():void{ 101 | if(robotEyes==null){ 102 | // AcademyShell is the main class for this application (ie the one the compiler gets fed) 103 | robotEyes = new RobotEyes(AcademyShell); 104 | addChild(robotEyes); 105 | } 106 | // need to wait a while 107 | var timer:Timer = new Timer(1000,1); 108 | timer.addEventListener(TimerEvent.TIMER, timerHandler); 109 | timer.start(); 110 | } 111 | 112 | // we run the tests after a second has passed just to give the application a chance to step through any set up 113 | private function timerHandler(e:TimerEvent):void{ 114 | super.run(); 115 | } 116 | 117 | .... 118 | 119 | In an end-to-end test you'll probably need to test some stuff asynchronously, and in ASUnit you'd do this by: 120 | 121 | public function testEndToEndProcessPass():void{ 122 | var textFieldDriver:TextFieldDriver = inViewOf(ShellContextView).inViewOf(LoginPanel).getA(TextField).named("username_txt") as TextFieldDriver; 123 | textFieldDriver.enterText('Pass'); 124 | 125 | var buttonDriver:InteractiveObjectDriver = inViewOf(ShellContextView).inViewOf(LoginPanel).getA(Sprite).withProperty("name", "btn_login") as InteractiveObjectDriver; 126 | 127 | // we're going to wait 4 seconds for the dummy service to return, and the login screen to tween away before we test this 128 | var asyncTest:Function = addAsync(null, 4000,loginShouldBeOffScreen); 129 | 130 | // simulate clicking the button 131 | buttonDriver.click(); 132 | } 133 | 134 | public function loginShouldBeOffScreen(e:Event):void{ 135 | var loginScreenDriver:DisplayObjectDriver = inViewOf(ShellContextView).getA(LoginPanel); 136 | var loginScreen:DisplayObject = loginScreenDriver.view; 137 | assertTrue('LoginPanel is off screen', (loginScreen.y < (-loginScreen.height))); 138 | } 139 | 140 | ## What if I ask for something that doesn't exist? 141 | 142 | RobotEyes generally currently returns null whenever it can't find something. This will almost certainly then cause your test to throw a null pointer error, so first it will throw an Error with message: 'RobotEyes can't find an instance of [Class:WidgetView] inside [Object:SpiffingSectionView]'. 143 | 144 | ## Get in touch 145 | 146 | Fork, message me on git or email dailystraying@gmail.com. I'm @stray_and_ruby on twitter. -------------------------------------------------------------------------------- /lib/asunit3/asunit/textui/XMLResultPrinter.as: -------------------------------------------------------------------------------- 1 | package asunit.textui { 2 | 3 | import asunit.errors.AssertionFailedError; 4 | import asunit.framework.Test; 5 | import asunit.framework.TestListener; 6 | import asunit.framework.TestResult; 7 | import flash.utils.setTimeout; 8 | import flash.utils.Dictionary; 9 | 10 | /** 11 | * The XMLResultPrinter is used to transform AsUnit test results 12 | * to JUnit-compatible XML content. 13 | * 14 | * This printer will send JUnit-compatible XML content to trace output. The XML content 15 | * will be enclosed by '<XMLResultPrinter/>' tags. 16 | * 17 | * @includeExample XMLResultPrinterExample.as 18 | * @includeExample XMLResultPrinterExample.xml 19 | **/ 20 | public class XMLResultPrinter extends ResultPrinter { 21 | 22 | protected var results:Dictionary; 23 | 24 | public function XMLResultPrinter() { 25 | results = new Dictionary(); 26 | } 27 | 28 | override public function startTest(test:Test):void { 29 | super.startTest(test); 30 | var result:TestListener = new XMLTestResult(test); 31 | results[test.getName()] = result; 32 | result.startTest(test); 33 | } 34 | 35 | override public function endTest(test:Test):void { 36 | super.endTest(test); 37 | results[test.getName()].endTest(test); 38 | } 39 | 40 | override public function startTestMethod(test:Test, methodName:String):void { 41 | super.startTestMethod(test, methodName); 42 | results[test.getName()].startTestMethod(test, methodName); 43 | } 44 | 45 | override public function endTestMethod(test:Test, methodName:String):void { 46 | super.endTestMethod(test, methodName); 47 | results[test.getName()].endTestMethod(test, methodName); 48 | } 49 | 50 | override public function addFailure(test:Test, t:AssertionFailedError):void { 51 | super.addFailure(test, t); 52 | results[test.getName()].addFailure(test, t); 53 | } 54 | 55 | override public function addError(test:Test, t:Error):void { 56 | super.addError(test, t); 57 | results[test.getName()].addError(test, t); 58 | } 59 | 60 | override public function printResult(result:TestResult, runTime:Number):void { 61 | super.printResult(result, runTime); 62 | trace(""); 63 | trace(""); 64 | trace(""); 65 | trace(""); 66 | var xmlTestResult:XMLTestResult; 67 | for each(xmlTestResult in results) { 68 | trace(xmlTestResult.toString()); 69 | } 70 | trace(""); 71 | trace(""); 72 | trace(""); 73 | } 74 | } 75 | } 76 | 77 | import asunit.framework.Test; 78 | import asunit.framework.TestFailure; 79 | import flash.utils.getQualifiedClassName; 80 | import flash.utils.getTimer; 81 | import asunit.framework.TestListener; 82 | import asunit.errors.AssertionFailedError; 83 | import asunit.framework.TestMethod; 84 | import flash.utils.Dictionary; 85 | 86 | class XMLTestResult implements TestListener { 87 | 88 | private var _duration:Number; 89 | private var start:Number; 90 | private var test:Test; 91 | private var testName:String; 92 | private var failureHash:Dictionary; 93 | private var failures:Array; 94 | private var errorHash:Dictionary; 95 | private var errors:Array; 96 | private var methodHash:Dictionary; 97 | private var methods:Array; 98 | 99 | public function XMLTestResult(test:Test) { 100 | this.test = test; 101 | testName = test.getName().split("::").join("."); 102 | failures = new Array(); 103 | errors = new Array(); 104 | methods = new Array(); 105 | 106 | failureHash = new Dictionary(); 107 | errorHash = new Dictionary(); 108 | methodHash = new Dictionary(); 109 | } 110 | 111 | public function startTest(test:Test):void { 112 | start = getTimer(); 113 | } 114 | 115 | public function run(test:Test):void { 116 | } 117 | 118 | public function addError(test:Test, t:Error):void { 119 | var failure:TestFailure = new TestFailure(test, t); 120 | errors.push(failure); 121 | errorHash[failure.failedMethod()] = failure; 122 | } 123 | 124 | public function addFailure(test:Test, t:AssertionFailedError):void { 125 | var failure:TestFailure = new TestFailure(test, t); 126 | failures.push(failure); 127 | failureHash[failure.failedMethod()] = failure; 128 | } 129 | 130 | public function startTestMethod(test:Test, methodName:String):void { 131 | var method:TestMethod = new TestMethod(test, methodName); 132 | methods.push(method); 133 | methodHash[method.getName()] = method; 134 | } 135 | 136 | public function endTestMethod(test:Test, methodName:String):void { 137 | methodHash[methodName].endTest(test); 138 | } 139 | 140 | public function endTest(test:Test):void { 141 | _duration = (getTimer() - start) * .001; 142 | } 143 | 144 | private function errorCount():int { 145 | return errors.length; 146 | } 147 | 148 | private function failureCount():int { 149 | return failures.length; 150 | } 151 | 152 | private function duration():Number { 153 | return _duration; 154 | } 155 | 156 | private function renderSuiteOpener():String { 157 | return "\n"; 158 | } 159 | 160 | private function renderTestOpener(methodName:String):String { 161 | return "\n"; 162 | } 163 | 164 | private function renderTestBody(method:String):String { 165 | if(errorHash[method]) { 166 | return renderError(errorHash[method]); 167 | } 168 | else if(failureHash[method]) { 169 | return renderFailure(failureHash[method]); 170 | } 171 | else { 172 | return ""; 173 | } 174 | } 175 | 176 | private function renderError(failure:TestFailure):String { 177 | return "\n"; 178 | } 179 | 180 | private function renderFailure(failure:TestFailure):String { 181 | return "\n"; 182 | } 183 | 184 | private function renderTestCloser():String { 185 | return '\n'; 186 | } 187 | 188 | private function renderSuiteCloser():String { 189 | return '\n'; 190 | } 191 | 192 | public function toString():String { 193 | var str:String = ''; 194 | str += renderSuiteOpener(); 195 | for(var name:String in methodHash) { 196 | str += renderTestOpener(name); 197 | str += renderTestBody(name); 198 | str += renderTestCloser(); 199 | } 200 | str += renderSuiteCloser(); 201 | return str; 202 | } 203 | } 204 | 205 | -------------------------------------------------------------------------------- /src/com/newloop/roboteyes/core/RobotEyesChief.as: -------------------------------------------------------------------------------- 1 | /* AS3 2 | Copyright 2010 Newloop. 3 | */ 4 | package com.newloop.roboteyes.core { 5 | 6 | import flash.display.DisplayObjectContainer; 7 | import flash.display.DisplayObject; 8 | import flash.display.InteractiveObject; 9 | import com.newloop.roboteyes.drivers.DisplayObjectDriver; 10 | import com.newloop.roboteyes.drivers.DisplayObjectDriverList; 11 | import com.newloop.roboteyes.drivers.TextFieldDriver; 12 | import com.newloop.roboteyes.drivers.InteractiveObjectDriver; 13 | import com.newloop.roboteyes.errors.RobotEyesError; 14 | 15 | import flash.text.TextField; 16 | 17 | /** 18 | * Class description. 19 | * 20 | * @langversion ActionScript 3.0 21 | * @playerversion Flash 9.0 22 | * 23 | * @author Lindsey Fallow 24 | * @since 07.01.2010 25 | */ 26 | public class RobotEyesChief extends Object { 27 | 28 | private var _viewRoot:DisplayObjectContainer; 29 | 30 | //-------------------------------------- 31 | // CLASS CONSTANTS 32 | //-------------------------------------- 33 | 34 | //-------------------------------------- 35 | // CONSTRUCTOR 36 | //-------------------------------------- 37 | 38 | /** 39 | * @Constructor 40 | */ 41 | public function RobotEyesChief(){ 42 | super(); 43 | } 44 | 45 | //-------------------------------------- 46 | // PRIVATE VARIABLES 47 | //-------------------------------------- 48 | 49 | //-------------------------------------- 50 | // GETTER/SETTERS 51 | //-------------------------------------- 52 | 53 | public function set viewRoot(view:DisplayObjectContainer):void{ 54 | _viewRoot = view; 55 | } 56 | 57 | //-------------------------------------- 58 | // PUBLIC METHODS 59 | //-------------------------------------- 60 | 61 | public function inViewOf(viewClazz:Class, useViewRoot:DisplayObjectContainer = null):DisplayObjectDriver{ 62 | return findContextView(viewClazz, useViewRoot); 63 | } 64 | 65 | public function getA(uiClazz:Class, useViewRoot:DisplayObjectContainer = null):DisplayObjectDriverList{ 66 | return findInstancesOf(uiClazz, useViewRoot); 67 | } 68 | 69 | public function getAny(uiClazz:Class, useViewRoot:DisplayObjectContainer = null):DisplayObjectDriver{ 70 | return findAnyInstanceOf(uiClazz, useViewRoot); 71 | } 72 | 73 | public function getSome(uiClazz:Class, useViewRoot:DisplayObjectContainer = null):DisplayObjectDriverList{ 74 | return findInstancesOf(uiClazz, useViewRoot); 75 | } 76 | 77 | public function createDriverFor(uiItem:DisplayObject):DisplayObjectDriver{ 78 | if(uiItem is TextField){ 79 | return new TextFieldDriver(uiItem as TextField); 80 | } 81 | 82 | if(uiItem is InteractiveObject){ 83 | return new InteractiveObjectDriver(uiItem as InteractiveObject); 84 | } 85 | return new DisplayObjectDriver(uiItem); 86 | } 87 | 88 | public function countChildrenOfType(childClazz:Class, useViewRoot:DisplayObjectContainer):uint { 89 | return countChildInstancesOf(childClazz, useViewRoot); 90 | } 91 | 92 | //-------------------------------------- 93 | // EVENT HANDLERS 94 | //-------------------------------------- 95 | 96 | //-------------------------------------- 97 | // PRIVATE & PROTECTED INSTANCE METHODS 98 | //-------------------------------------- 99 | 100 | private function findInstancesOf(uiClazz:Class, useViewRoot:DisplayObjectContainer = null):DisplayObjectDriverList{ 101 | if(useViewRoot == null){ 102 | useViewRoot = _viewRoot; 103 | } 104 | 105 | var matchingInstancesArray:Array = []; 106 | 107 | var iLength:uint = useViewRoot.numChildren; 108 | for (var i:uint = 0; i0){ 117 | return new DisplayObjectDriverList(matchingInstancesArray); 118 | } 119 | 120 | for(i=0; iXMLResultPrinter provides a good example of how this class can 26 | * be subclassed and used to emit different/additional output. 27 | * 28 | * @see XMLResultPrinter 29 | **/ 30 | public class ResultPrinter extends Sprite implements TestListener { 31 | private var fColumn:int = 0; 32 | private var textArea:TextField; 33 | private var gutter:uint = 0; 34 | private var backgroundColor:uint = 0x333333; 35 | private var bar:SuccessBar; 36 | private var barHeight:Number = 3; 37 | private var showTrace:Boolean; 38 | protected var startTime:Number; 39 | protected var testTimes:Array; 40 | 41 | public function ResultPrinter(showTrace:Boolean = false) { 42 | this.showTrace = showTrace; 43 | testTimes = new Array(); 44 | configureAssets(); 45 | println(); 46 | 47 | // Create a loop so that the FDBTask 48 | // can halt execution properly: 49 | setInterval(function():void { 50 | }, 500); 51 | } 52 | 53 | private function configureAssets():void { 54 | textArea = new TextField(); 55 | textArea.background = true; 56 | textArea.backgroundColor = backgroundColor; 57 | textArea.border = true; 58 | textArea.wordWrap = true; 59 | var format:TextFormat = new TextFormat(); 60 | format.font = "Verdana"; 61 | format.size = 10; 62 | format.color = 0xFFFFFF; 63 | textArea.defaultTextFormat = format; 64 | addChild(textArea); 65 | println("AsUnit " + Version.id() + " by Luke Bayes and Ali Mills"); 66 | println(""); 67 | println("Flash Player version: " + Capabilities.version); 68 | 69 | bar = new SuccessBar(); 70 | addChild(bar); 71 | } 72 | 73 | public function setShowTrace(showTrace:Boolean):void { 74 | this.showTrace = showTrace; 75 | } 76 | 77 | public override function set width(w:Number):void { 78 | textArea.x = gutter; 79 | textArea.width = w - gutter*2; 80 | bar.x = gutter; 81 | bar.width = textArea.width; 82 | } 83 | 84 | public override function set height(h:Number):void { 85 | textArea.height = h - ((gutter*2) + barHeight); 86 | textArea.y = gutter; 87 | bar.y = h - (gutter + barHeight); 88 | bar.height = barHeight; 89 | } 90 | 91 | public function println(...args:Array):void { 92 | textArea.appendText(args.toString() + "\n"); 93 | } 94 | 95 | public function print(...args:Array):void { 96 | textArea.appendText(args.toString()); 97 | } 98 | 99 | /** 100 | * API for use by textui.TestRunner 101 | */ 102 | 103 | public function run(test:Test):void { 104 | } 105 | 106 | public function printResult(result:TestResult, runTime:Number):void { 107 | printHeader(runTime); 108 | printErrors(result); 109 | printFailures(result); 110 | printFooter(result); 111 | 112 | bar.setSuccess(result.wasSuccessful()); 113 | if(showTrace) { 114 | trace(textArea.text.split("\r").join("\n")); 115 | } 116 | } 117 | 118 | /* Internal methods 119 | */ 120 | protected function printHeader(runTime:Number):void { 121 | println(); 122 | println(); 123 | println("Time: " + elapsedTimeAsString(runTime)); 124 | } 125 | 126 | protected function printErrors(result:TestResult):void { 127 | printDefects(result.errors(), result.errorCount(), "error"); 128 | } 129 | 130 | protected function printFailures(result:TestResult):void { 131 | printDefects(result.failures(), result.failureCount(), "failure"); 132 | } 133 | 134 | protected function printDefects(booBoos:Object, count:int, type:String):void { 135 | if (count == 0) { 136 | return; 137 | } 138 | if (count == 1) { 139 | println("There was " + count + " " + type + ":"); 140 | } 141 | else { 142 | println("There were " + count + " " + type + "s:"); 143 | } 144 | var i:uint; 145 | for each (var item:TestFailure in booBoos) { 146 | printDefect(TestFailure(item), i); 147 | i++; 148 | } 149 | } 150 | 151 | public function printDefect(booBoo:TestFailure, count:int ):void { // only public for testing purposes 152 | printDefectHeader(booBoo, count); 153 | printDefectTrace(booBoo); 154 | } 155 | 156 | protected function printDefectHeader(booBoo:TestFailure, count:int):void { 157 | // I feel like making this a println, then adding a line giving the throwable a chance to print something 158 | // before we get to the stack trace. 159 | var startIndex:uint = textArea.text.length; 160 | println(count + ") " + booBoo.failedFeature()); 161 | var endIndex:uint = textArea.text.length; 162 | 163 | var format:TextFormat = textArea.getTextFormat(); 164 | format.bold = true; 165 | 166 | // GROSS HACK because of bug in flash player - TextField isn't accepting formats... 167 | setTimeout(onFormatTimeout, 1, format, startIndex, endIndex); 168 | } 169 | 170 | public function onFormatTimeout(format:TextFormat, startIndex:uint, endIndex:uint):void { 171 | textArea.setTextFormat(format, startIndex, endIndex); 172 | } 173 | 174 | protected function printDefectTrace(booBoo:TestFailure):void { 175 | println(BaseTestRunner.getFilteredTrace(booBoo.thrownException().getStackTrace())); 176 | } 177 | 178 | protected function printFooter(result:TestResult):void { 179 | println(); 180 | if (result.wasSuccessful()) { 181 | print("OK"); 182 | println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")"); 183 | } else { 184 | println("FAILURES!!!"); 185 | println("Tests run: " + result.runCount()+ 186 | ", Failures: "+result.failureCount()+ 187 | ", Errors: "+result.errorCount()); 188 | } 189 | 190 | printTimeSummary(); 191 | println(); 192 | } 193 | 194 | protected function printTimeSummary():void { 195 | testTimes.sortOn('duration', Array.NUMERIC | Array.DESCENDING); 196 | println(); 197 | println(); 198 | println('Time Summary:'); 199 | println(); 200 | var len:Number = testTimes.length; 201 | for(var i:Number = 0; i < len; i++) { 202 | println(testTimes[i].toString()); 203 | } 204 | } 205 | 206 | /** 207 | * Returns the formatted string of the elapsed time. 208 | * Duplicated from BaseTestRunner. Fix it. 209 | */ 210 | protected function elapsedTimeAsString(runTime:Number):String { 211 | return Number(runTime/1000).toString(); 212 | } 213 | 214 | /** 215 | * @see asunit.framework.TestListener#addError(Test, Throwable) 216 | */ 217 | public function addError(test:Test, t:Error):void { 218 | print("E"); 219 | } 220 | 221 | /** 222 | * @see asunit.framework.TestListener#addFailure(Test, AssertionFailedError) 223 | */ 224 | public function addFailure(test:Test, t:AssertionFailedError):void { 225 | print("F"); 226 | } 227 | 228 | /** 229 | * @see asunit.framework.TestListener#endTestMethod(test, testMethod); 230 | */ 231 | public function startTestMethod(test:Test, methodName:String):void { 232 | } 233 | 234 | /** 235 | * @see asunit.framework.TestListener#endTestMethod(test, testMethod); 236 | */ 237 | public function endTestMethod(test:Test, methodName:String):void { 238 | } 239 | 240 | /** 241 | * @see asunit.framework.TestListener#startTest(Test) 242 | */ 243 | public function startTest(test:Test):void { 244 | startTime = getTimer(); 245 | var count:uint = test.countTestCases(); 246 | for(var i:uint; i < count; i++) { 247 | print("."); 248 | if (fColumn++ >= 80) { 249 | println(); 250 | fColumn = 0; 251 | } 252 | } 253 | } 254 | 255 | /** 256 | * @see asunit.framework.TestListener#endTest(Test) 257 | */ 258 | public function endTest(test:Test):void { 259 | var duration:Number = getTimer() - startTime; 260 | testTimes.push(TestTime.create(test, duration)); 261 | } 262 | } 263 | } 264 | 265 | import flash.display.Sprite; 266 | 267 | class SuccessBar extends Sprite { 268 | private var myWidth:uint; 269 | private var myHeight:uint; 270 | private var bgColor:uint; 271 | private var passingColor:uint = 0x00FF00; 272 | private var failingColor:uint = 0xFD0000; 273 | 274 | public function SuccessBar() { 275 | } 276 | 277 | public function setSuccess(success:Boolean):void { 278 | bgColor = (success) ? passingColor : failingColor; 279 | draw(); 280 | } 281 | 282 | public override function set width(num:Number):void { 283 | myWidth = num; 284 | draw(); 285 | } 286 | 287 | public override function set height(num:Number):void { 288 | myHeight = num; 289 | draw(); 290 | } 291 | 292 | private function draw():void { 293 | graphics.clear(); 294 | graphics.beginFill(bgColor); 295 | graphics.drawRect(0, 0, myWidth, myHeight); 296 | graphics.endFill(); 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/Assert.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import asunit.errors.AssertionFailedError; 3 | 4 | import flash.utils.getQualifiedClassName; 5 | 6 | import flash.errors.IllegalOperationError; 7 | import flash.events.EventDispatcher; 8 | 9 | /** 10 | * A set of assert methods. Messages are only displayed when an assert fails. 11 | */ 12 | 13 | public class Assert extends EventDispatcher { 14 | /** 15 | * Protect constructor since it is a static only class 16 | */ 17 | public function Assert() { 18 | } 19 | 20 | /** 21 | * Asserts that a condition is true. If it isn't it throws 22 | * an AssertionFailedError with the given message. 23 | */ 24 | static public function assertTrue(...args:Array):void { 25 | var message:String; 26 | var condition:Boolean; 27 | 28 | if(args.length == 1) { 29 | message = ""; 30 | condition = Boolean(args[0]); 31 | } 32 | else if(args.length == 2) { 33 | message = args[0]; 34 | condition = Boolean(args[1]); 35 | } 36 | else { 37 | throw new IllegalOperationError("Invalid argument count"); 38 | } 39 | 40 | if(!condition) { 41 | fail(message); 42 | } 43 | } 44 | /** 45 | * Asserts that a condition is false. If it isn't it throws 46 | * an AssertionFailedError with the given message. 47 | */ 48 | static public function assertFalse(...args:Array):void { 49 | var message:String; 50 | var condition:Boolean; 51 | 52 | if(args.length == 1) { 53 | message = ""; 54 | condition = Boolean(args[0]); 55 | } 56 | else if(args.length == 2) { 57 | message = args[0]; 58 | condition = Boolean(args[1]); 59 | } 60 | else { 61 | throw new IllegalOperationError("Invalid argument count"); 62 | } 63 | 64 | assertTrue(message, !condition); 65 | } 66 | /** 67 | * Fails a test with the given message. 68 | * 69 | * @example This method can be called anytime you want to break out and fail 70 | * the current test. 71 | * 72 | * 73 | * public function testSomething():void { 74 | * var instance:MyClass = new MyClass(); 75 | * if(instance.foo()) { 76 | * fail('The foo should not have been there'); 77 | * } 78 | * } 79 | * 80 | */ 81 | static public function fail(message:String):void { 82 | throw new AssertionFailedError(message); 83 | } 84 | 85 | /** 86 | * Asserts that the provided block throws an exception that matches 87 | * the type provided. 88 | * 89 | * 90 | * public function testFailingCode():void { 91 | * assertThrows(CustomError, function():void { 92 | * var instance:Sprite = new Sprite(); 93 | * instance.callMethodThatThrows(); 94 | * }); 95 | * } 96 | * 97 | **/ 98 | static public function assertThrows(errorType:Class, block:Function):void { 99 | try { 100 | block.call(); 101 | fail("assertThrows block did not throw an expected exception"); 102 | } 103 | catch(e:Error) { 104 | if(!(e is errorType)) { 105 | fail("assertThrows did not throw the expected error type, instead threw: " + getQualifiedClassName(e)); 106 | } 107 | } 108 | } 109 | 110 | /** 111 | * Asserts that two objects are equal. If they are not 112 | * an AssertionFailedError is thrown with the given message. 113 | * 114 | * This assertion should be (by far) the one you use the most. 115 | * It automatically provides useful information about what 116 | * the failing values were. 117 | * 118 | * 119 | * public function testNames():void { 120 | * var name1:String = "Federico Aubele"; 121 | * var name2:String = "Frederico Aubele"; 122 | * 123 | * assertEquals(name1, name2); 124 | * } 125 | * 126 | */ 127 | static public function assertEquals(...args:Array):void { 128 | var message:String; 129 | var expected:Object; 130 | var actual:Object; 131 | 132 | if(args.length == 2) { 133 | message = ""; 134 | expected = args[0]; 135 | actual = args[1]; 136 | } 137 | else if(args.length == 3) { 138 | message = args[0]; 139 | expected = args[1]; 140 | actual = args[2]; 141 | } 142 | else { 143 | throw new IllegalOperationError("Invalid argument count"); 144 | } 145 | 146 | if(expected == null && actual == null) { 147 | return; 148 | } 149 | 150 | try { 151 | if(expected != null && expected.equals(actual)) { 152 | return; 153 | } 154 | } 155 | catch(e:Error) { 156 | if(expected != null && expected == actual) { 157 | return; 158 | } 159 | } 160 | 161 | failNotEquals(message, expected, actual); 162 | } 163 | /** 164 | * Asserts that an object isn't null. If it is 165 | * an AssertionFailedError is thrown with the given message. 166 | */ 167 | static public function assertNotNull(...args:Array):void { 168 | var message:String; 169 | var object:Object; 170 | 171 | if(args.length == 1) { 172 | message = ""; 173 | object = args[0]; 174 | } 175 | else if(args.length == 2) { 176 | message = args[0]; 177 | object = args[1]; 178 | } 179 | else { 180 | throw new IllegalOperationError("Invalid argument count"); 181 | } 182 | 183 | assertTrue(message, object != null); 184 | } 185 | /** 186 | * Asserts that an object is null. If it is not 187 | * an AssertionFailedError is thrown with the given message. 188 | */ 189 | static public function assertNull(...args:Array):void { 190 | var message:String; 191 | var object:Object; 192 | 193 | if(args.length == 1) { 194 | message = ""; 195 | object = args[0]; 196 | } 197 | else if(args.length == 2) { 198 | message = args[0]; 199 | object = args[1]; 200 | } 201 | else { 202 | throw new IllegalOperationError("Invalid argument count"); 203 | } 204 | 205 | assertTrue(message, object == null); 206 | } 207 | /** 208 | * Asserts that two objects refer to the same object. If they are not 209 | * an AssertionFailedError is thrown with the given message. 210 | */ 211 | static public function assertSame(...args:Array):void { 212 | var message:String; 213 | var expected:Object; 214 | var actual:Object; 215 | 216 | if(args.length == 2) { 217 | message = ""; 218 | expected = args[0]; 219 | actual = args[1]; 220 | } 221 | else if(args.length == 3) { 222 | message = args[0]; 223 | expected = args[1]; 224 | actual = args[2]; 225 | } 226 | else { 227 | throw new IllegalOperationError("Invalid argument count"); 228 | } 229 | 230 | if(expected === actual) { 231 | return; 232 | } 233 | failNotSame(message, expected, actual); 234 | } 235 | /** 236 | * Asserts that two objects do not refer to the same object. If they do, 237 | * an AssertionFailedError is thrown with the given message. 238 | */ 239 | static public function assertNotSame(...args:Array):void { 240 | var message:String; 241 | var expected:Object; 242 | var actual:Object; 243 | 244 | if(args.length == 2) { 245 | message = ""; 246 | expected = args[0]; 247 | actual = args[1]; 248 | } 249 | else if(args.length == 3) { 250 | message = args[0]; 251 | expected = args[1]; 252 | actual = args[2]; 253 | } 254 | else { 255 | throw new IllegalOperationError("Invalid argument count"); 256 | } 257 | 258 | if(expected === actual) 259 | failSame(message); 260 | } 261 | 262 | /** 263 | * Asserts that two numerical values are equal within a tolerance range. 264 | * If they are not an AssertionFailedError is thrown with the given message. 265 | */ 266 | static public function assertEqualsFloat(...args:Array):void { 267 | var message:String; 268 | var expected:Number; 269 | var actual:Number; 270 | var tolerance:Number = 0; 271 | 272 | if(args.length == 3) { 273 | message = ""; 274 | expected = args[0]; 275 | actual = args[1]; 276 | tolerance = args[2]; 277 | } 278 | else if(args.length == 4) { 279 | message = args[0]; 280 | expected = args[1]; 281 | actual = args[2]; 282 | tolerance = args[3]; 283 | } 284 | else { 285 | throw new IllegalOperationError("Invalid argument count"); 286 | } 287 | if (isNaN(tolerance)) tolerance = 0; 288 | if(Math.abs(expected - actual) <= tolerance) { 289 | return; 290 | } 291 | failNotEquals(message, expected, actual); 292 | } 293 | 294 | /** 295 | * Asserts that two arrays have the same length and contain the same 296 | * objects in the same order. If the arrays are not equal by this 297 | * definition an AssertionFailedError is thrown with the given message. 298 | */ 299 | static public function assertEqualsArrays(...args:Array):void { 300 | var message:String; 301 | var expected:Array; 302 | var actual:Array; 303 | 304 | if(args.length == 2) { 305 | message = ""; 306 | expected = args[0]; 307 | actual = args[1]; 308 | } 309 | else if(args.length == 3) { 310 | message = args[0]; 311 | expected = args[1]; 312 | actual = args[2]; 313 | } 314 | else { 315 | throw new IllegalOperationError("Invalid argument count"); 316 | } 317 | 318 | if (expected == null && actual == null) { 319 | return; 320 | } 321 | if ((expected == null && actual != null) || (expected != null && actual == null)) { 322 | failNotEquals(message, expected, actual); 323 | } 324 | // from here on: expected != null && actual != null 325 | if (expected.length != actual.length) { 326 | failNotEquals(message, expected, actual); 327 | } 328 | for (var i : int = 0; i < expected.length; i++) { 329 | assertEquals(expected[i], actual[i]); 330 | } 331 | } 332 | 333 | /** 334 | * Asserts that two arrays have the same length and contain the same 335 | * objects. The order of the objects in the arrays is ignored. If they 336 | * are not equal by this definition an AssertionFailedError is thrown 337 | * with the given message. 338 | */ 339 | static public function assertEqualsArraysIgnoringOrder(...args:Array):void { 340 | var message:String; 341 | var expected:Array; 342 | var actual:Array; 343 | 344 | if(args.length == 2) { 345 | message = ""; 346 | expected = args[0]; 347 | actual = args[1]; 348 | } 349 | else if(args.length == 3) { 350 | message = args[0]; 351 | expected = args[1]; 352 | actual = args[2]; 353 | } 354 | else { 355 | throw new IllegalOperationError("Invalid argument count"); 356 | } 357 | 358 | if (expected == null && actual == null) { 359 | return; 360 | } 361 | if ((expected == null && actual != null) || (expected != null && actual == null)) { 362 | failNotEquals(message, expected, actual); 363 | } 364 | // from here on: expected != null && actual != null 365 | if (expected.length != actual.length) { 366 | failNotEquals(message, expected, actual); 367 | } 368 | for (var i : int = 0; i < expected.length; i++) { 369 | var foundMatch : Boolean = false; 370 | var expectedMember : Object = expected[i]; 371 | for (var j : int = 0; j < actual.length; j++) { 372 | var actualMember : Object = actual[j]; 373 | try { 374 | assertEquals(expectedMember, actualMember); 375 | foundMatch = true; 376 | break; 377 | } 378 | catch (e : AssertionFailedError) { 379 | // no match, try next 380 | } 381 | } 382 | if (!foundMatch) { 383 | failNotEquals("Found no match for " + expectedMember + ";", expected, actual); 384 | } 385 | } 386 | } 387 | 388 | 389 | static private function failSame(message:String):void { 390 | var formatted:String = ""; 391 | if(message != null) { 392 | formatted = message + " "; 393 | } 394 | fail(formatted + "expected not same"); 395 | } 396 | 397 | static private function failNotSame(message:String, expected:Object, actual:Object):void { 398 | var formatted:String = ""; 399 | if(message != null) { 400 | formatted = message + " "; 401 | } 402 | fail(formatted + "expected same:<" + expected + "> was not:<" + actual + ">"); 403 | } 404 | 405 | static private function failNotEquals(message:String, expected:Object, actual:Object):void { 406 | fail(format(message, expected, actual)); 407 | } 408 | 409 | static private function format(message:String, expected:Object, actual:Object):String { 410 | var formatted:String = ""; 411 | if(message != null) { 412 | formatted = message + " "; 413 | } 414 | return formatted + "expected:<" + expected + "> but was:<" + actual + ">"; 415 | } 416 | } 417 | } 418 | -------------------------------------------------------------------------------- /lib/asunit3/asunit/framework/TestCase.as: -------------------------------------------------------------------------------- 1 | package asunit.framework { 2 | import flash.display.DisplayObject; 3 | import flash.display.DisplayObjectContainer; 4 | import flash.errors.IllegalOperationError; 5 | import flash.events.Event; 6 | import flash.utils.describeType; 7 | import flash.utils.getDefinitionByName; 8 | import flash.utils.setTimeout; 9 | 10 | import asunit.errors.AssertionFailedError; 11 | import asunit.util.ArrayIterator; 12 | import asunit.util.Iterator; 13 | 14 | /** 15 | * A test case defines the fixture to run multiple tests. To define a test case
16 | * 1) implement a subclass of TestCase
17 | * 2) define instance variables that store the state of the fixture
18 | * 3) initialize the fixture state by overriding setUp
19 | * 4) clean-up after a test by overriding tearDown.
20 | * Each test runs in its own fixture so there 21 | * can be no side effects among test runs. 22 | * Here is an example: 23 | * 24 | * public class MathTest extends TestCase { 25 | * private var value1:Number; 26 | * private var value2:Number; 27 | * 28 | * public function MathTest(methodName:String=null) { 29 | * super(methodName); 30 | * } 31 | * 32 | * override protected function setUp():void { 33 | * super.setUp(); 34 | * value1 = 2; 35 | * value2 = 3; 36 | * } 37 | * } 38 | * 39 | * 40 | * For each test implement a method which interacts 41 | * with the fixture. Verify the expected results with assertions specified 42 | * by calling assertTrue with a boolean, or assertEquals 43 | * with two primitive values that should match. 44 | * 45 | * public function testAdd():void { 46 | * var result:Number = value1 + value2; 47 | * assertEquals(5, result); 48 | * } 49 | * 50 | * 51 | * There are three common types of test cases: 52 | * 53 | *
    54 | *
  1. Simple unit test
  2. 55 | *
  3. Visual integration test
  4. 56 | *
  5. Asynchronous test
  6. 57 | *
58 | * 59 | * @includeExample MathUtilTest.as 60 | * @includeExample ComponentTestIntroduction.as 61 | * @includeExample ComponentUnderTest.as 62 | * @includeExample ComponentTestExample.as 63 | * @includeExample AsynchronousTestMethodExample.as 64 | */ 65 | public class TestCase extends Assert implements Test { 66 | protected static const PRE_SET_UP:int = 0; 67 | protected static const SET_UP:int = 1; 68 | protected static const RUN_METHOD:int = 2; 69 | protected static const TEAR_DOWN:int = 3; 70 | protected static const DEFAULT_TIMEOUT:int = 1000; 71 | 72 | protected var context:DisplayObjectContainer; 73 | protected var fName:String; 74 | protected var isComplete:Boolean; 75 | protected var result:TestListener; 76 | protected var testMethods:Array; 77 | 78 | private var asyncQueue:Array; 79 | private var currentMethod:String; 80 | private var currentState:int; 81 | private var layoutManager:Object; 82 | private var methodIterator:Iterator; 83 | private var runSingle:Boolean; 84 | 85 | /** 86 | * Constructs a test case with the given name. 87 | * 88 | * Be sure to implement the constructor in your own TestCase base classes. 89 | * 90 | * Using the optional testMethod constructor parameter is how we 91 | * create and run a single test case and test method. 92 | */ 93 | public function TestCase(testMethod:String = null) { 94 | var description:XML = describeType(this); 95 | var className:Object = description.@name; 96 | var methods:XMLList = description..method.(@name.match("^test")); 97 | if(testMethod != null) { 98 | testMethods = testMethod.split(", ").join(",").split(","); 99 | if(testMethods.length == 1) { 100 | runSingle = true; 101 | } 102 | } else { 103 | setTestMethods(methods); 104 | } 105 | setName(className.toString()); 106 | resolveLayoutManager(); 107 | asyncQueue = []; 108 | } 109 | 110 | private function resolveLayoutManager():void { 111 | // Avoid creating import dependencies on flex framework 112 | // If you have the framework.swc in your classpath, 113 | // the layout manager will be found, if not, a mcok 114 | // will be used. 115 | try { 116 | var manager:Class = getDefinitionByName("mx.managers.LayoutManager") as Class; 117 | layoutManager = manager["getInstance"](); 118 | if(!layoutManager.hasOwnProperty("resetAll")) { 119 | throw new Error("TestCase :: mx.managers.LayoutManager missing resetAll method"); 120 | } 121 | } 122 | catch(e:Error) { 123 | layoutManager = new Object(); 124 | layoutManager.resetAll = function():void { 125 | }; 126 | } 127 | } 128 | 129 | /** 130 | * Sets the name of a TestCase 131 | * @param name The name to set 132 | */ 133 | public function setName(name:String):void { 134 | fName = name; 135 | } 136 | 137 | protected function setTestMethods(methodNodes:XMLList):void { 138 | testMethods = new Array(); 139 | var methodNames:Object = methodNodes.@name; 140 | var name:String; 141 | for each(var item:Object in methodNames) { 142 | name = item.toString(); 143 | testMethods.push(name); 144 | } 145 | } 146 | 147 | public function getTestMethods():Array { 148 | return testMethods; 149 | } 150 | 151 | /** 152 | * Counts the number of test cases executed by run(TestResult result). 153 | */ 154 | public function countTestCases():int { 155 | return testMethods.length; 156 | } 157 | 158 | /** 159 | * Creates a default TestResult object 160 | * 161 | * @see TestResult 162 | */ 163 | protected function createResult():TestResult { 164 | return new TestResult(); 165 | } 166 | 167 | /** 168 | * A convenience method to run this test, collecting the results with 169 | * either the TestResult provided or a default, new TestResult object. 170 | * Expects either: 171 | * run():void // will return the newly created TestResult 172 | * run(result:TestResult):TestResult // will use the TestResult 173 | * that was passed in. 174 | * 175 | * @see TestResult 176 | */ 177 | public function run():void { 178 | getResult().run(this); 179 | } 180 | 181 | public function setResult(result:TestListener):void { 182 | this.result = result; 183 | } 184 | 185 | internal function getResult():TestListener { 186 | return (result == null) ? createResult() : result; 187 | } 188 | 189 | /** 190 | * Runs the bare test sequence. 191 | * @throws Error if any exception is thrown 192 | */ 193 | public function runBare():void { 194 | if(isComplete) { 195 | return; 196 | } 197 | var name:String; 198 | var itr:Iterator = getMethodIterator(); 199 | if(itr.hasNext()) { 200 | name = String(itr.next()); 201 | currentState = PRE_SET_UP; 202 | runMethod(name); 203 | } 204 | else { 205 | cleanUp(); 206 | getResult().endTest(this); 207 | isComplete = true; 208 | dispatchEvent(new Event(Event.COMPLETE)); 209 | } 210 | } 211 | 212 | private function getMethodIterator():Iterator { 213 | if(methodIterator == null) { 214 | methodIterator = new ArrayIterator(testMethods); 215 | } 216 | return methodIterator; 217 | } 218 | 219 | /** 220 | * Override this method in Asynchronous test cases 221 | * or any other time you want to perform additional 222 | * member cleanup after all test methods have run 223 | **/ 224 | protected function cleanUp():void { 225 | } 226 | 227 | private function runMethod(methodName:String):void { 228 | try { 229 | if(currentState == PRE_SET_UP) { 230 | currentState = SET_UP; 231 | getResult().startTestMethod(this, methodName); 232 | setUp(); // setUp may be async and change the state of methodIsAsynchronous 233 | } 234 | currentMethod = methodName; 235 | if(!waitForAsync()) { 236 | currentState = RUN_METHOD; 237 | this[methodName](); 238 | } 239 | } 240 | catch(assertionFailedError:AssertionFailedError) { 241 | getResult().addFailure(this, assertionFailedError); 242 | } 243 | catch(unknownError:Error) { 244 | getResult().addError(this, unknownError); 245 | } 246 | finally { 247 | if(!waitForAsync()) { 248 | runTearDown(); 249 | } 250 | } 251 | } 252 | 253 | /** 254 | * Sets up the fixture, for example, instantiate a mock object. 255 | * This method is called before each test is executed. 256 | * throws Exception on error. 257 | * 258 | * @example This method is usually overridden in your concrete test cases: 259 | * 260 | * private var instance:MyInstance; 261 | * 262 | * override protected function setUp():void { 263 | * super.setUp(); 264 | * instance = new MyInstance(); 265 | * addChild(instance); 266 | * } 267 | * 268 | */ 269 | protected function setUp():void { 270 | } 271 | /** 272 | * Tears down the fixture, for example, delete mock object. 273 | * 274 | * This method is called after a test is executed - even if the test method 275 | * throws an exception or fails. 276 | * 277 | * Even though the base class TestCase doesn't do anything on tearDown, 278 | * It's a good idea to call super.tearDown() in your subclasses. Many projects 279 | * wind up using some common fixtures which can often be extracted out a common project 280 | * TestCase. 281 | * 282 | * tearDown is not called when we tell a test case to execute 283 | * a single test method. 284 | * 285 | * @throws Error on error. 286 | * 287 | * @example This method is usually overridden in your concrete test cases: 288 | * 289 | * private var instance:MyInstance; 290 | * 291 | * override protected function setUp():void { 292 | * super.setUp(); 293 | * instance = new MyInstance(); 294 | * addChild(instance); 295 | * } 296 | * 297 | * override protected function tearDown():void { 298 | * super.tearDown(); 299 | * removeChild(instance); 300 | * } 301 | * 302 | * 303 | */ 304 | protected function tearDown():void { 305 | } 306 | 307 | /** 308 | * Returns a string representation of the test case 309 | */ 310 | override public function toString():String { 311 | if(getCurrentMethod()) { 312 | return getName() + "." + getCurrentMethod() + "()"; 313 | } 314 | else { 315 | return getName(); 316 | } 317 | } 318 | /** 319 | * Gets the name of a TestCase 320 | * @return returns a String 321 | */ 322 | public function getName():String { 323 | return fName; 324 | } 325 | 326 | public function getCurrentMethod():String { 327 | return currentMethod; 328 | } 329 | 330 | public function getIsComplete():Boolean { 331 | return isComplete; 332 | } 333 | 334 | public function setContext(context:DisplayObjectContainer):void { 335 | this.context = context; 336 | } 337 | 338 | /** 339 | * Returns the visual DisplayObjectContainer that will be used by 340 | * addChild and removeChild helper methods. 341 | **/ 342 | public function getContext():DisplayObjectContainer { 343 | return context; 344 | } 345 | 346 | /** 347 | * Called from within setUp or the body of any test method. 348 | * 349 | * Any call to addAsync, will prevent test execution from continuing 350 | * until the duration (in milliseconds) is exceeded, or the function returned by addAsync 351 | * is called. addAsync can be called any number of times within a particular 352 | * test method, and will block execution until each handler has returned. 353 | * 354 | * Following is an example of how to use the addAsync feature: 355 | * 356 | * public function testDispatcher():void { 357 | * var dispatcher:IEventDispatcher = new EventDispatcher(); 358 | * // Subscribe to an event by sending the return value of addAsync: 359 | * dispatcher.addEventListener(Event.COMPLETE, addAsync(function(event:Event):void { 360 | * // Make assertions *inside* your async handler: 361 | * assertEquals(34, dispatcher.value); 362 | * })); 363 | * } 364 | * 365 | * 366 | * If you just want to verify that a particular event is triggered, you don't 367 | * need to provide a handler of your own, you can do the following: 368 | * 369 | * public function testDispatcher():void { 370 | * var dispatcher:IEventDispatcher = new EventDispatcher(); 371 | * dispatcher.addEventListener(Event.COMPLETE, addAsync()); 372 | * } 373 | * 374 | * 375 | * If you have a series of events that need to happen, you can generally add 376 | * the async handler to the last one. 377 | * 378 | * The main thing to remember is that any assertions that happen outside of the 379 | * initial thread of execution, must be inside of an addAsync block. 380 | **/ 381 | protected function addAsync(handler:Function = null, duration:Number=DEFAULT_TIMEOUT, failureHandler:Function=null):Function { 382 | if(handler == null) { 383 | handler = function(args:*):* {return;}; 384 | } 385 | var async:AsyncOperation = new AsyncOperation(this, handler, duration, failureHandler); 386 | asyncQueue.push(async); 387 | return async.getCallback(); 388 | } 389 | 390 | internal function asyncOperationTimeout(async:AsyncOperation, duration:Number, isError:Boolean=true):void { 391 | if(isError) getResult().addError(this, new IllegalOperationError("TestCase.timeout (" + duration + "ms) exceeded on an asynchronous operation.")); 392 | asyncOperationComplete(async); 393 | } 394 | 395 | internal function asyncOperationComplete(async:AsyncOperation):void{ 396 | // remove operation from queue 397 | var i:int = asyncQueue.indexOf(async); 398 | asyncQueue.splice(i,1); 399 | // if we still need to wait, return 400 | if(waitForAsync()) return; 401 | if(currentState == SET_UP) { 402 | runMethod(currentMethod); 403 | } 404 | else if(currentState == RUN_METHOD) { 405 | runTearDown(); 406 | } 407 | } 408 | 409 | private function waitForAsync():Boolean{ 410 | return asyncQueue.length > 0; 411 | } 412 | 413 | protected function runTearDown():void { 414 | if(currentState == TEAR_DOWN) { 415 | return; 416 | } 417 | currentState = TEAR_DOWN; 418 | if(isComplete) { 419 | return; 420 | } 421 | if(!runSingle) { 422 | getResult().endTestMethod(this, currentMethod); 423 | tearDown(); 424 | layoutManager.resetAll(); 425 | } 426 | setTimeout(runBare, 5); 427 | } 428 | 429 | /** 430 | * Helper method for testing DisplayObjects. 431 | * 432 | * This method allows you to more easily add and manage DisplayObject 433 | * instances in your TestCase. 434 | * 435 | * If you are using the regular TestRunner, you cannot add Flex classes. 436 | * 437 | * If you are using a FlexRunner base class, you can add either 438 | * regular DisplayObjects or IUIComponents. 439 | * 440 | * Usually, this method is called within setUp, and removeChild 441 | * is called from within tearDown. Using these methods, ensures that added 442 | * children will be subsequently removed, even when tests fail. 443 | * 444 | * Here is an example of the addChild method: 445 | * 446 | * private var instance:MyComponent; 447 | * 448 | * override protected function setUp():void { 449 | * super.setUp(); 450 | * instance = new MyComponent(); 451 | * instance.addEventListener(Event.COMPLETE, addAsync()); 452 | * addChild(instance); 453 | * } 454 | * 455 | * override protected function tearDown():void { 456 | * super.tearDown(); 457 | * removeChild(instance); 458 | * } 459 | * 460 | * public function testParam():void { 461 | * assertEquals(34, instance.value); 462 | * } 463 | * 464 | **/ 465 | protected function addChild(child:DisplayObject):DisplayObject { 466 | return getContext().addChild(child); 467 | } 468 | 469 | /** 470 | * Helper method for removing added DisplayObjects. 471 | * 472 | * Update: This method should no longer fail if the provided DisplayObject 473 | * has already been removed. 474 | **/ 475 | protected function removeChild(child:DisplayObject):DisplayObject { 476 | if(child == null) { 477 | return null; 478 | } 479 | try { 480 | return getContext().removeChild(child); 481 | } 482 | catch(e:Error) { 483 | } 484 | return null; 485 | } 486 | } 487 | } 488 | --------------------------------------------------------------------------------