FlexUnit4 Async Testing Events

When doing Unit testing in FlexUnit 4, you can test Async event firing. This is a tricky test if there are multiple events being fired. The reason it gets tricky is because of the single threaded nature of Flex.

When you simply dispatch one event ofter the other, they are added to the display stack and thus handled in REVERSE order when removed from the stack. However, if you are using remote calls, the stack is given a change to execute, while the remote call is sent off and thus Async events happen in NORMAL order. What makes this really tricky is if you have a combination of local events (reverse order) and remote events (normal order)

Here are some high level examples:

Example 1

dispatchEvent(Event1)

dispatchEvent(Event2)

dispatchEvent(Event3)

Correct Async testing is now done in reverse order, since each event is added to the display stack

Async.proceedOnEvent(this, someEventDispatcher, Event3, checkVars3, 500, null, noEventFired);

Async.proceedOnEvent(this, someEventDispatcher, Event2, checkVars2, 500, null, noEventFired);

Async.proceedOnEvent(this, someEventDispatcher, Event1, checkVars1, 500, null, noEventFired);

Notice the order of the Async.proceedOnEvent is reversed

Example 2

remote call(Event1)

dispatchEvent(Event2)

dispatchEvent(Event3)

Async.proceedOnEvent(this, someEventDispatcher, Event1, checkVars1, 500, null, noEventFired);

Async.proceedOnEvent(this, someEventDispatcher, Event3, checkVars3, 500, null, noEventFired);

Async.proceedOnEvent(this, someEventDispatcher, Event2, checkVars2, 500, null, noEventFired);

Notice the remote call clears properly, but the local calls are reverse order.

So the only way to do this is to understand that if a remote call is executed, you check for it and that if there are any local events, they are placed on a stack until no more events or a remote event takes place and then checked in reverse order.

Tricky….

Flex DateTimeValidator

I wrote the first version of a Date & Time validator for Flex. This version extends DateValidator and adds optional time. At the moment the time format is fixed to HH:MM:SS using “:” separator. I may update this later.

Enjoy



package com.helper
{
import mx.validators.DateValidator;
import mx.validators.ValidationResult;
import mx.validators.Validator;
public class DateTimeValidator extends DateValidator
{
// Define Array for the return value of doValidation().
private var results:Array;
private var timeArray:Array = new Array();
public static const RANGE_ERROR:String = “RangeError”;
public static const FORMAT_ERROR:String = “FormatError”;
public static const MAX_EXCEEDED_ERROR:String = “MaxValueExceeded”;
public static const MIN_EXCEEDED_ERROR:String = “MinValuesExceeded”;
public static const INVALID_HOUR_ERROR:String = “INVALID_HOUR_ERROR”;
public static const INVALID_MIN_ERROR:String = “INVALID_MIN_ERROR”;
public static const INVALID_SEC_ERROR:String = “INVALID_SEC_ERROR”;
public static const INVALID_TIME_ERROR:String = “INVALID_TIME_ERROR”;
public static const INVALID_SEPARATOR_ERROR:String = “INVALID_SEPARATOR_ERROR”;
private var _wrongHour:String;
private var _wrongMinute:String;
private var _wrongSecond:String;
public function DateTimeValidator()
{
super();
}
// Define the doValidation() method.
override protected function doValidation(value:Object):Array
{
var dateTimeArray:Array = new Array();
// Clear results Array.
results = [];
var dateString:String = String(value);
// Assume Date is now DATE[ TIME]
dateTimeArray = String(dateString).split(” “);
if(dateTimeArray.length > 0 && String(dateTimeArray[0]).length != 0)
{
// Call the parent Date Validator to validate the date part
results = super.doValidation(dateTimeArray[0]);
}
// Return if there are errors.
if (results.length > 0)
{
return results;
}
// Now validate the time part if there is one
if(dateTimeArray.length > 1)
{
// Expecting HH:MM:SS String. Split the String
timeArray = String(dateTimeArray[1]).split(“:”);
if(timeArray.length == 3)
{
var hour:int = Number(timeArray[0]);
var minute:int = Number(timeArray[1]);
var second:int = Number(timeArray[2]);
/////
// Now check the hour values
if(hour >= 0 && hour <= 23)
{
} else {
results.push(new ValidationResult(true,”hour”,RANGE_ERROR,”Hours need to be between 00 and 23″));
}
// Now check the minute values
if(minute >= 0 && minute <= 59)
{
} else {
results.push(new ValidationResult(true,”minute”,RANGE_ERROR,”Minutes need to be between 00 and 59″));
}
// Now check the minute values
if(second >= 0 && second <= 59)
{
} else {
results.push(new ValidationResult(true,”second”,RANGE_ERROR,”Seconds need to be between 00 and 59″));
}
} else {
results.push(new ValidationResult(true,”format”, FORMAT_ERROR, “Please enter the time as HH:MM:SS”));
}
}
// Return if there are errors.
if (results.length > 0)
{
return results;
}
return results;
}
}
}
And just for kicks, here is the FlexUnit testing of the code:
package com.helper
{
import com.helper.DateTimeValidator;
import flexunit.framework.Assert;
import mx.events.ValidationResultEvent;
public class DateTimeValidatorTests
{
private var fixture:DateTimeValidator
[Before]
public function runBeforeEveryTest():void
{
fixture = new DateTimeValidator();
fixture.inputFormat =  “YYYY/MM/DD”;
fixture.allowedFormatChars = “/-.”;
}
[After]
public function runAfterEveryTest():void
{
fixture = null;
}
[Test]
public function formatDateTimeTests():void
{
fixture.inputFormat = “YYYY/MM/DD”;
Assert.assertEquals(“2010/12/31 00:00:00″, ValidationResultEvent.VALID, fixture.validate(“2010/12/31 00:00:00″).type);
Assert.assertEquals(“31/12/2010 00:00:00″, ValidationResultEvent.INVALID, fixture.validate(“31/12/2010 00:00:00″).type);
Assert.assertEquals(“12/31/2010 00:00:00″, ValidationResultEvent.INVALID, fixture.validate(“12/31/2010 00:00:00″).type);
fixture.inputFormat = “DD/MM/YYYY”;
Assert.assertEquals(“2010/12/31 00:00:00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:00:00″).type);
Assert.assertEquals(“31/12/2010 00:00:00″, ValidationResultEvent.VALID, fixture.validate(“31/12/2010 00:00:00″).type);
Assert.assertEquals(“12/31/2010 00:00:00″, ValidationResultEvent.INVALID, fixture.validate(“12/31/2010 00:00:00″).type);
fixture.inputFormat = “MM/DD/YYYY”;
Assert.assertEquals(“2010/12/31 00:00:00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:00:00″).type);
Assert.assertEquals(“31/12/2010 00:00:00″, ValidationResultEvent.INVALID, fixture.validate(“31/12/2010 00:00:00″).type);
Assert.assertEquals(“12/31/2010 00:00:00″, ValidationResultEvent.VALID, fixture.validate(“12/31/2010 00:00:00″).type);
}
[Test]
public function validDateTimeTests():void
{
Assert.assertEquals(“2010/12/31″, ValidationResultEvent.VALID, fixture.validate(“2010/12/31″).type);
Assert.assertEquals(“2010-12-31″, ValidationResultEvent.VALID, fixture.validate(“2010-12-31″).type);
Assert.assertEquals(“2010.12.31″, ValidationResultEvent.VALID, fixture.validate(“2010.12.31″).type);
Assert.assertEquals(“2010/12/31 00:00:00″, ValidationResultEvent.VALID, fixture.validate(“2010/12/31 00:00:00″).type);
Assert.assertEquals(“2010/12/31 23:59:59″, ValidationResultEvent.VALID, fixture.validate(“2010/12/31 23:59:59″).type);
Assert.assertEquals(“2010/12/31 01:09:09″, ValidationResultEvent.VALID, fixture.validate(“2010/12/31 01:09:09″).type);
Assert.assertEquals(“2010/12/31 2:3:4″, ValidationResultEvent.VALID, fixture.validate(“2010/12/31 2:3:4″).type);
}
[Test]
public function invalidDateTimeTests():void
{
Assert.assertEquals(“99/12/31″, ValidationResultEvent.INVALID, fixture.validate(“99/12/31″).type);
Assert.assertEquals(“12/31″, ValidationResultEvent.INVALID, fixture.validate(“12/31″).type);
Assert.assertEquals(“31″, ValidationResultEvent.INVALID, fixture.validate(“31″).type);
Assert.assertEquals(“2010/22/31″, ValidationResultEvent.INVALID, fixture.validate(“2010/22/31″).type);
Assert.assertEquals(“2010/12/55″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/55″).type);
Assert.assertEquals(“-2010/12/31″, ValidationResultEvent.INVALID, fixture.validate(“-2010/12/31″).type);
Assert.assertEquals(“2010/-12/31″, ValidationResultEvent.INVALID, fixture.validate(“2010/-12/31″).type);
Assert.assertEquals(“2010/12/-31″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/-31″).type);
Assert.assertEquals(“2010/12/31 -1:00:00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 -1:00:00″).type);
Assert.assertEquals(“2010/12/31 00:-1:00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:-1:00″).type);
Assert.assertEquals(“2010/12/31 00:00:-1″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:-1:00″).type);
Assert.assertEquals(“2010/12/31 00:00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:00″).type);
Assert.assertEquals(“2010/12/31 00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00″).type);
Assert.assertEquals(“2010/12/31 25:00:00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 25:00:00″).type);
Assert.assertEquals(“2010/12/31 00:60:00″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:60:00″).type);
Assert.assertEquals(“2010/12/31 00:00:60″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:00:60″).type);
Assert.assertEquals(“2010/12/31 25:60:60″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 25:60:60″).type);
Assert.assertEquals(“2010/12/31 00:00 AM”, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:00 AM”).type);
Assert.assertEquals(“2010/12/31 00:00 PM”, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 00:00 PM”).type);
Assert.assertEquals(“2010/12/31 3654567″, ValidationResultEvent.INVALID, fixture.validate(“2010/12/31 3654567″).type);
Assert.assertEquals(3654567, ValidationResultEvent.INVALID, fixture.validate(3654567).type);
}
}
}

Deploying Swiz based Flex app

When you decide to deploy a Swiz based Flex app, you need to tell the compiler to keep the meta data tags. Under compiler settings, add the following:

-keep-as3-metadata+=Inject,Autowire,Mediate,Dispatcher,PostConstruct,PreDestroy

Then from the menu. Project -> Export Release Build.

Select the Tomcat WebApps directory and export. This will deploy the export to Tomcat as binary and with Swiz strapped in



		
	

Chrome Flash debugger cannot connect

From this website:

What to do if you upgraded and the Flash Debugger doesn’t work.

In Flex the progress bar read “Waiting for Adobe Flash Player to connect to debugger…”, and after a minute or so it timed out with the error: Failed to connect; session timed out.

The fix is actually pretty simple. In Chrome, just type the following URL into your address bar, chrome://plugins/ and click Disable under the Shockwave Flash plugin with the location that ends with “Flash Player Plugin for Chrome.plugin”. You will want to keep the other Flash plugin enabled because that is your debugger version.

Installing log4FX

This may seem odd, but there are no good install howto’s for log4fx. Log4FX is a Flex equivalent of lof4J, but allows you to do remote logging.

Install:

1) Download the latest from here

2) Download the license file from the same location as above (Look at the bottom, there are license files

3) Start Eclipse

4) Go to Software updates

5) Add an Archive and select the ZIP file

6) Select all the files and install

7) Restart Eclipse when prompted to do so

======

Set up Log4FX on a project

1) Right click on your project -> Log4FX -> Add Dependencies

2) You get a warning about the license. Select Yes to manage the license

3) Install the license and restart

Logging in Flex like log4J

Here is a quick way to put logs in your Flex code. Inside each class or MXML, create a variable to hold the logging.

private static const logger:ILogger = Log.getLogger(“MyLoggingName”);

Then inside the class, put the following line to trigger an output:

logger.info(“Inside creationCompleteHandler”);

or

logger.debug(“Inside creationCompleteHandler”);

HTH

Swiz Log output

Found this in my searching to see what Swiz is doing. Put this in your main application

<fx:Declarations>
<!– Configure Swiz Framework–>
<swiz:SwizConfig
strict=”true”
eventPackages=”com.wl.sfx.events”
viewPackages=”com.wl.sfx.views”
mediateBubbledEvents=”true”
beanLoaders=”{[ Beans ]}”
logEventLevel=”{LogEventLevel.DEBUG}”/>

<mx:TraceTarget id=”logTarget”
includeDate=”true”
includeTime=”true”
includeCategory=”true”
includeLevel=”true”
/>

</fx:Declarations>

When you run debugging on Flex now, you will see what Flex is up to

Follow

Get every new post delivered to your Inbox.